+
+int mpilogb(struct t *t)
+{
+ MPFR_DECL_INIT(mx, 53);
+
+ mpfr_set_d(mx, t->x, MPFR_RNDN);
+ t->i = mpfr_get_exp(mx) - 1;
+ t->e = 0;
+ if (isinf(t->x) || isnan(t->x) || t->x == 0)
+ t->e = INVALID;
+ return 0;
+}
+int mpilogbf(struct t *t)
+{
+ MPFR_DECL_INIT(mx, 24);
+
+ mpfr_set_flt(mx, t->x, MPFR_RNDN);
+ t->i = mpfr_get_exp(mx) - 1;
+ t->e = 0;
+ if (isinf(t->x) || isnan(t->x) || t->x == 0)
+ t->e = INVALID;
+ return 0;
+}
+int mpilogbl(struct t *t)
+{
+ MPFR_DECL_INIT(mx, 64);
+
+ mpfr_set_ld(mx, t->x, MPFR_RNDN);
+ t->i = mpfr_get_exp(mx) - 1;
+ t->e = 0;
+ if (isinf(t->x) || isnan(t->x) || t->x == 0)
+ t->e = INVALID;
+ return 0;
+}
+
+// TODO: ll* is hard to do with mpfr
+#define mp_f_i(n) \
+int mp##n(struct t *t) \
+{ \
+ setupfenv(t->r); \
+ t->i = n(t->x); \
+ t->e = getexcept(); \
+ if (t->e & INVALID) \
+ t->i = 0; \
+ return 0; \
+}
+
+mp_f_i(llrint)
+mp_f_i(llrintf)
+mp_f_i(llrintl)
+mp_f_i(lrint)
+mp_f_i(lrintf)
+mp_f_i(lrintl)
+mp_f_i(llround)
+mp_f_i(llroundf)
+mp_f_i(llroundl)
+mp_f_i(lround)
+mp_f_i(lroundf)
+mp_f_i(lroundl)
+
+int mpmodf(struct t *t)
+{
+ int e, r;
+
+ r = mpd1(t, wrap_trunc);
+ if (r)
+ return r;
+ t->y2 = t->y;
+ t->dy2 = t->dy;
+ e = t->e & ~INEXACT;
+ r = mpd1(t, mpfr_frac);
+ t->e |= e;
+ return r;
+}
+
+int mpmodff(struct t *t)
+{
+ int e, r;
+
+ r = mpf1(t, wrap_trunc);
+ if (r)
+ return r;
+ t->y2 = t->y;
+ t->dy2 = t->dy;
+ e = t->e & ~INEXACT;
+ r = mpf1(t, mpfr_frac);
+ t->e |= e;
+ return r;
+}
+
+int mpmodfl(struct t *t)
+{
+ int e, r;
+
+ r = mpl1(t, wrap_trunc);
+ if (r)
+ return r;
+ t->y2 = t->y;
+ t->dy2 = t->dy;
+ e = t->e & ~INEXACT;
+ r = mpl1(t, mpfr_frac);
+ t->e |= e;
+ return r;
+}
+
+int mpsincos(struct t *t)
+{
+ int e, r;
+
+ r = mpd1(t, mpfr_cos);
+ if (r)
+ return r;
+ t->y2 = t->y;
+ t->dy2 = t->dy;
+ e = t->e;
+ r = mpd1(t, mpfr_sin);
+ t->e |= e;
+ return r;
+}
+
+int mpsincosf(struct t *t)
+{
+ int e, r;
+
+ r = mpf1(t, mpfr_cos);
+ if (r)
+ return r;
+ t->y2 = t->y;
+ t->dy2 = t->dy;
+ e = t->e;
+ r = mpf1(t, mpfr_sin);
+ t->e |= e;
+ return r;
+}
+
+int mpsincosl(struct t *t)
+{
+ int e, r;
+
+ r = mpl1(t, mpfr_cos);
+ if (r)
+ return r;
+ t->y2 = t->y;
+ t->dy2 = t->dy;
+ e = t->e;
+ r = mpl1(t, mpfr_sin);
+ t->e |= e;
+ return r;
+}
+
+int mpremquo(struct t *t) { return mpd2(t, wrap_remquo) || (t->i = mpremquo_q, 0); }
+int mpremquof(struct t *t) { return mpf2(t, wrap_remquo) || (t->i = mpremquo_q, 0); }
+int mpremquol(struct t *t) { return mpl2(t, wrap_remquo) || (t->i = mpremquo_q, 0); }
+
+int mpfma(struct t *t)
+{
+ int tn;
+ int r = rmap(t->r);
+ MPFR_DECL_INIT(mx, 53);
+ MPFR_DECL_INIT(mx2, 53);
+ MPFR_DECL_INIT(mx3, 53);
+ MPFR_DECL_INIT(my, 128);
+
+ mpfr_clear_flags();
+ mpfr_set_d(mx, t->x, MPFR_RNDN);
+ mpfr_set_d(mx2, t->x2, MPFR_RNDN);
+ mpfr_set_d(mx3, t->x3, MPFR_RNDN);
+ tn = mpfr_fma(my, mx, mx2, mx3, r);
+ gend(t, my, tn, r);
+ return 0;
+}
+
+int mpfmaf(struct t *t)
+{
+ int tn;
+ int r = rmap(t->r);
+ MPFR_DECL_INIT(mx, 24);
+ MPFR_DECL_INIT(mx2, 24);
+ MPFR_DECL_INIT(mx3, 24);
+ MPFR_DECL_INIT(my, 128);
+
+ mpfr_clear_flags();
+ mpfr_set_flt(mx, t->x, MPFR_RNDN);
+ mpfr_set_flt(mx2, t->x2, MPFR_RNDN);
+ mpfr_set_flt(mx3, t->x3, MPFR_RNDN);
+ tn = mpfr_fma(my, mx, mx2, mx3, r);
+ genf(t, my, tn, r);
+ return 0;
+}
+
+int mpfmal(struct t *t)
+{
+#if LDBL_MANT_DIG == 53
+ return mpfma(t);
+#elif LDBL_MANT_DIG == 64
+ int tn;
+ int r = rmap(t->r);
+ MPFR_DECL_INIT(mx, 64);
+ MPFR_DECL_INIT(mx2, 64);
+ MPFR_DECL_INIT(mx3, 64);
+ MPFR_DECL_INIT(my, 128);
+
+ mpfr_clear_flags();
+ mpfr_set_ld(mx, t->x, MPFR_RNDN);
+ mpfr_set_ld(mx2, t->x2, MPFR_RNDN);
+ mpfr_set_ld(mx3, t->x3, MPFR_RNDN);
+ tn = mpfr_fma(my, mx, mx2, mx3, r);
+ genl(t, my, tn, r);
+ return 0;
+#else
+ return -1;
+#endif
+}
+
+int mpjn(struct t *t) { mpbessel_n = t->i; return mpd1(t, wrap_jn); }
+int mpjnf(struct t *t) { mpbessel_n = t->i; return mpf1(t, wrap_jn); }
+int mpjnl(struct t *t) { mpbessel_n = t->i; return mpl1(t, wrap_jn); }
+int mpyn(struct t *t) { mpbessel_n = t->i; return mpd1(t, wrap_yn); }
+int mpynf(struct t *t) { mpbessel_n = t->i; return mpf1(t, wrap_yn); }
+int mpynl(struct t *t) { mpbessel_n = t->i; return mpl1(t, wrap_yn); }
+