math/gen: fix ilogb, logb and modf in mp, change integer print fmt
authorSzabolcs Nagy <nsz@port70.net>
Sun, 11 Nov 2012 21:53:47 +0000 (22:53 +0100)
committerSzabolcs Nagy <nsz@port70.net>
Sun, 11 Nov 2012 21:53:47 +0000 (22:53 +0100)
src/math/gen/gen.c
src/math/gen/mp.c

index 123cfb8..6bc3c96 100644 (file)
@@ -290,7 +290,7 @@ static int print(const char *fmt, struct t *t, char *buf, int n)
                        continue;
                }
                if (*fmt == 'i') {
-                       k = snprintf(buf, n, ", %lld", t->i);
+                       k = snprintf(buf, n, ", %11lld", t->i);
                        if (k < 0 || k >= n)
                                return -1;
                        n -= k;
index bebc019..48492c1 100644 (file)
@@ -482,30 +482,69 @@ int mplogb(struct t *t)
 {
        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); }
@@ -580,6 +619,7 @@ int mptanl(struct t *t) { return mpl1(t, mpfr_tan); }
 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); }
@@ -748,6 +788,8 @@ int mpilogb(struct t *t)
        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)
@@ -757,6 +799,8 @@ 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)
@@ -766,6 +810,8 @@ 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;
 }
 
@@ -801,7 +847,7 @@ int mpmodf(struct t *t)
                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;
@@ -816,7 +862,7 @@ int mpmodff(struct t *t)
                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;
@@ -831,7 +877,7 @@ int mpmodfl(struct t *t)
                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;