t = adjust(mr, my, t, r);
p->y = mpfr_get_flt(mr, r);
- p->e = eflags(isnan(p->x) || isnan(p->x2));
+ p->e = eflags(isnan(p->x) || isnan(p->x2) || isnan(p->x3));
i = eulpf(p->y);
if (!isfinite(p->y)) {
p->dy = 0;
t = adjust(mr, my, t, r);
p->y = mpfr_get_d(mr, r);
- p->e = eflags(isnan(p->x) || isnan(p->x2));
+ p->e = eflags(isnan(p->x) || isnan(p->x2) || isnan(p->x3));
i = eulp(p->y);
if (!isfinite(p->y)) {
p->dy = 0;
t = adjust(mr, my, t, r);
p->y = mpfr_get_ld(mr, r);
- p->e = eflags(isnan(p->x) || isnan(p->x2));
+ p->e = eflags(isnan(p->x) || isnan(p->x2) || isnan(p->x3));
i = eulpl(p->y);
if (!isfinite(p->y)) {
p->dy = 0;
{
return mpfr_lgamma(my, &mplgamma_sign, mx, r);
}
+static long mpremquo_q;
+static int wrap_remquo(mpfr_t my, const mpfr_t mx, const mpfr_t mx2, mpfr_rnd_t r)
+{
+ return mpfr_remquo(my, &mpremquo_q, mx, mx2, r);
+}
+static int mpbessel_n;
+static int wrap_jn(mpfr_t my, const mpfr_t mx, mpfr_rnd_t r)
+{
+ return mpfr_jn(my, mpbessel_n, mx, r);
+}
+static int wrap_yn(mpfr_t my, const mpfr_t mx, mpfr_rnd_t r)
+{
+ return mpfr_yn(my, mpbessel_n, mx, r);
+}
static int wrap_ceil(mpfr_t my, const mpfr_t mx, mpfr_rnd_t r)
{
return mpfr_ceil(my, mx);
return mpfr_ui_pow(my, 10, mx, r);
}
+int mpadd(struct t *t) { return mpd2(t, mpfr_add); }
+
int mpacos(struct t *t) { return mpd1(t, mpfr_acos); }
int mpacosf(struct t *t) { return mpf1(t, mpfr_acos); }
int mpacosl(struct t *t) { return mpl1(t, mpfr_acos); }
{
MPFR_DECL_INIT(mx, 53);
- mpfr_set_d(mx, t->x, MPFR_RNDN);
- t->y = mpfr_get_exp(mx) - 1;
t->dy = 0;
t->e = 0;
+ if (t->x == 0) {
+ t->y = -INFINITY;
+ t->e |= DIVBYZERO;
+ return 0;
+ }
+ if (isinf(t->x)) {
+ t->y = INFINITY;
+ return 0;
+ }
+ if (isnan(t->x)) {
+ t->y = t->x;
+ return 0;
+ }
+ mpfr_set_d(mx, t->x, MPFR_RNDN);
+ t->y = mpfr_get_exp(mx) - 1;
return 0;
}
int mplogbf(struct t *t)
{
MPFR_DECL_INIT(mx, 24);
- mpfr_set_flt(mx, t->x, MPFR_RNDN);
- t->y = mpfr_get_exp(mx) - 1;
t->dy = 0;
t->e = 0;
+ if (t->x == 0) {
+ t->y = -INFINITY;
+ t->e |= DIVBYZERO;
+ return 0;
+ }
+ if (isinf(t->x)) {
+ t->y = INFINITY;
+ return 0;
+ }
+ if (isnan(t->x)) {
+ t->y = t->x;
+ return 0;
+ }
+ mpfr_set_flt(mx, t->x, MPFR_RNDN);
+ t->y = mpfr_get_exp(mx) - 1;
return 0;
}
int mplogbl(struct t *t)
{
MPFR_DECL_INIT(mx, 64);
- mpfr_set_ld(mx, t->x, MPFR_RNDN);
- t->y = mpfr_get_exp(mx) - 1;
t->dy = 0;
t->e = 0;
+ if (t->x == 0) {
+ t->y = -INFINITY;
+ t->e |= DIVBYZERO;
+ return 0;
+ }
+ if (isinf(t->x)) {
+ t->y = INFINITY;
+ return 0;
+ }
+ if (isnan(t->x)) {
+ t->y = t->x;
+ return 0;
+ }
+ mpfr_set_ld(mx, t->x, MPFR_RNDN);
+ t->y = mpfr_get_exp(mx) - 1;
return 0;
}
int mpnearbyint(struct t *t) { return mpd1(t, wrap_nearbyint) || (t->e&=~INEXACT, 0); }
int mptanh(struct t *t) { return mpd1(t, mpfr_tanh); }
int mptanhf(struct t *t) { return mpf1(t, mpfr_tanh); }
int mptanhl(struct t *t) { return mpl1(t, mpfr_tanh); }
+// TODO: tgamma(2) raises wrong flags
int mptgamma(struct t *t) { return mpd1(t, mpfr_gamma); }
int mptgammaf(struct t *t) { return mpf1(t, mpfr_gamma); }
int mptgammal(struct t *t) { return mpl1(t, mpfr_gamma); }
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_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_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;
}
return r;
t->y2 = t->y;
t->dy2 = t->dy;
- e = t->e;
+ e = t->e & ~INEXACT;
r = mpd1(t, mpfr_frac);
t->e |= e;
return r;
return r;
t->y2 = t->y;
t->dy2 = t->dy;
- e = t->e;
+ e = t->e & ~INEXACT;
r = mpf1(t, mpfr_frac);
t->e |= e;
return r;
return r;
t->y2 = t->y;
t->dy2 = t->dy;
- e = t->e;
+ e = t->e & ~INEXACT;
r = mpl1(t, mpfr_frac);
t->e |= e;
return r;
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);
+
+ mpsetup();
+ 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);
+ if ((t->e & INEXACT) && nextafter(t->y, 0) == 0) {
+ mpfr_set_emin(-(1<<20));
+ tn = mpfr_fma(my, mx, mx2, mx3, r);
+ mpfr_mul_2si(my, my, 1074, MPFR_RNDN);
+ t->dy = scalbnl(t->y, 1074) - mpfr_get_ld(my, r);
+ mpfr_set_emin(-1073);
+ }
+ 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);
+
+ mpsetupf();
+ 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);
+ if ((t->e & INEXACT) && nextafterf(t->y, 0) == 0) {
+ mpfr_set_emin(-(1<<20));
+ tn = mpfr_fma(my, mx, mx2, mx3, r);
+ mpfr_mul_2si(my, my, 149, MPFR_RNDN);
+ t->dy = scalbnl(t->y, 149) - mpfr_get_ld(my, r);
+ mpfr_set_emin(-148);
+ }
+ 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);
+
+ mpsetupl();
+ 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);
+ if ((t->e & INEXACT) && nextafterl(t->y, 0) == 0) {
+ mpfr_set_emin(-(1<<20));
+ tn = mpfr_fma(my, mx, mx2, mx3, r);
+ mpfr_mul_2si(my, my, 16445, MPFR_RNDN);
+ t->dy = scalbnl(t->y, 16445) - mpfr_get_ld(my, r);
+ mpfr_set_emin(-16444);
+ }
+ 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); }
+