]> git.lizzy.rs Git - plan9front.git/blobdiff - sys/src/libstdio/dtoa.c
kernel: avoid selecting the boot process in killbig()
[plan9front.git] / sys / src / libstdio / dtoa.c
old mode 100755 (executable)
new mode 100644 (file)
index 26441de..80fd3c7
@@ -21,8 +21,9 @@ static double private_mem[PRIVATE_mem], *pmem_next = private_mem;
 #define DBL_MAX_EXP    1024
 #define FLT_RADIX      2
 #define Storeinc(a,b,c) (*a++ = b << 16 | c & 0xffff)
-#define fpword0(x) ((FPdbleword*)&x)->hi
-#define fpword1(x) ((FPdbleword*)&x)->lo
+#define fpword0(x) ((x).hi)
+#define fpword1(x) ((x).lo)
+
 /* Ten_pmax = floor(P*log(2)/log(5)) */
 /* Bletch = (highest power of 2 < DBL_MAX_10_EXP) / 16 */
 /* Quick_max = floor((P-1)*log(FLT_RADIX)/log(10) - 1) */
@@ -45,14 +46,12 @@ static double private_mem[PRIVATE_mem], *pmem_next = private_mem;
 #define Bletch 0x10
 #define Bndry_mask  0xfffff
 #define Bndry_mask1 0xfffff
-#define LSB 1
 #define Sign_bit 0x80000000
 #define Log2P 1
 #define Tiny0 0
 #define Tiny1 1
 #define Quick_max 14
 #define Int_max 14
-#define Avoid_Underflow
 
 #define rounded_product(a,b) a *= b
 #define rounded_quotient(a,b) a /= b
@@ -84,6 +83,8 @@ Balloc(int k)
        Bigint * rv;
        unsigned int    len;
 
+       assert(k < nelem(freelist));
+
        ACQUIRE_DTOA_LOCK(0);
        if (rv = freelist[k]) {
                freelist[k] = rv->next;
@@ -150,34 +151,6 @@ multadd(Bigint *b, int m, int a)   /* multiply by m and add a */
        return b;
 }
 
-static Bigint *
-s2b(const char *s, int nd0, int nd, unsigned int y9)
-{
-       Bigint * b;
-       int     i, k;
-       int x, y;
-
-       x = (nd + 8) / 9;
-       for (k = 0, y = 1; x > y; y <<= 1, k++) 
-               ;
-       b = Balloc(k);
-       b->x[0] = y9;
-       b->wds = 1;
-
-       i = 9;
-       if (9 < nd0) {
-               s += 9;
-               do 
-                       b = multadd(b, 10, *s++ - '0');
-               while (++i < nd0);
-               s++;
-       } else
-               s += 10;
-       for (; i < nd; i++)
-               b = multadd(b, 10, *s++ - '0');
-       return b;
-}
-
 static int     
 hi0bits(register unsigned int x)
 {
@@ -482,26 +455,14 @@ diff(Bigint *a, Bigint *b)
        return c;
 }
 
-static double  
-ulp(double x)
-{
-       register int L;
-       double  a;
-
-       L = (fpword0(x) & Exp_mask) - (P - 1) * Exp_msk1;
-       fpword0(a) = L;
-       fpword1(a) = 0;
-       return a;
-}
-
-static double  
+static FPdbleword      
 b2d(Bigint *a, int *e)
 {
        unsigned int * xa, *xa0, w, y, z;
        int     k;
-       double  d;
 #define d0 fpword0(d)
 #define d1 fpword1(d)
+       FPdbleword d;
 
        xa0 = a->x;
        xa = xa0 + a->wds;
@@ -530,13 +491,13 @@ ret_d:
 }
 
 static Bigint *
-d2b(double d, int *e, int *bits)
+d2b(FPdbleword d, int *e, int *bits)
 {
        Bigint * b;
-       int     de, i, k;
+       int     de, k;
        unsigned int * x, y, z;
-#define d0 fpword0(d)
-#define d1 fpword1(d)
+#define d0 d.hi
+#define d1 d.lo
 
        b = Balloc(1);
        x = b->x;
@@ -551,11 +512,11 @@ d2b(double d, int *e, int *bits)
                        z >>= k;
                } else
                        x[0] = y;
-               i = b->wds = (x[1] = z) ? 2 : 1;
+               b->wds = (x[1] = z) ? 2 : 1;
        } else {
                k = lo0bits(&z);
                x[0] = z;
-               i = b->wds = 1;
+               b->wds = 1;
                k += 32;
        }
        *e = de - Bias - (P - 1) + k;
@@ -566,24 +527,6 @@ d2b(double d, int *e, int *bits)
 #undef d0
 #undef d1
 
-static double  
-ratio(Bigint *a, Bigint *b)
-{
-       double  da, db;
-       int     k, ka, kb;
-
-       da = b2d(a, &ka);
-       db = b2d(b, &kb);
-       k = ka - kb + 32 * (a->wds - b->wds);
-       if (k > 0)
-               fpword0(da) += k * Exp_msk1;
-       else {
-               k = -k;
-               fpword0(db) += k * Exp_msk1;
-       }
-       return da / db;
-}
-
 static const double
 tens[] = {
        1e0, 1e1, 1e2, 1e3, 1e4, 1e5, 1e6, 1e7, 1e8, 1e9,
@@ -595,11 +538,6 @@ static const double
 bigtens[] = { 
        1e16, 1e32, 1e64, 1e128, 1e256 };
 
-static const double tinytens[] = { 
-       1e-16, 1e-32, 1e-64, 1e-128,
-       9007199254740992.e-256
-};
-
 /* The factor of 2^53 in tinytens[4] helps us avoid setting the underflow */
 /* flag unnecessarily.  It leads to a song and dance at the end of strtod. */
 #define Scale_Bit 0x10
@@ -609,67 +547,6 @@ static const double tinytens[] = {
 
 #define NAN_WORD1 0
 
-static int     
-match(const char **sp, char *t)
-{
-       int     c, d;
-       const char * s = *sp;
-
-       while (d = *t++) {
-               if ((c = *++s) >= 'A' && c <= 'Z')
-                       c += 'a' - 'A';
-               if (c != d)
-                       return 0;
-       }
-       *sp = s + 1;
-       return 1;
-}
-
-static void    
-gethex(double *rvp, const char **sp)
-{
-       unsigned int c, x[2];
-       const char * s;
-       int     havedig, udx0, xshift;
-
-       x[0] = x[1] = 0;
-       havedig = xshift = 0;
-       udx0 = 1;
-       s = *sp;
-       while (c = *(const unsigned char * )++s) {
-               if (c >= '0' && c <= '9')
-                       c -= '0';
-               else if (c >= 'a' && c <= 'f')
-                       c += 10 - 'a';
-               else if (c >= 'A' && c <= 'F')
-                       c += 10 - 'A';
-               else if (c <= ' ') {
-                       if (udx0 && havedig) {
-                               udx0 = 0;
-                               xshift = 1;
-                       }
-                       continue;
-               } else if (/*(*/ c == ')') {
-                       *sp = s + 1;
-                       break;
-               } else
-                       return; /* invalid form: don't change *sp */
-               havedig = 1;
-               if (xshift) {
-                       xshift = 0;
-                       x[0] = x[1];
-                       x[1] = 0;
-               }
-               if (udx0)
-                       x[0] = (x[0] << 4) | (x[1] >> 28);
-               x[1] = (x[1] << 4) | c;
-       }
-       if ((x[0] &= 0xfffff) || x[1]) {
-               fpword0(*rvp) = Exp_mask | x[0];
-               fpword1(*rvp) = x[1];
-       }
-}
-
 static int     
 quorem(Bigint *b, Bigint *S)
 {
@@ -813,7 +690,7 @@ freedtoa(char *s)
  */
 
 char   *
-dtoa(double d, int mode, int ndigits, int *decpt, int *sign, char **rve)
+dtoa(double _d, int mode, int ndigits, int *decpt, int *sign, char **rve)
 {
        /*      Arguments ndigits, decpt, sign are similar to those
        of ecvt and fcvt; trailing zeros are suppressed from
@@ -854,9 +731,11 @@ dtoa(double d, int mode, int ndigits, int *decpt, int *sign, char **rve)
        spec_case, try_quick;
        int L;
        Bigint * b, *b1, *delta, *mlo=nil, *mhi, *S;
-       double  d2, ds, eps;
+       double  ds;
+       FPdbleword d, d2, eps;
        char    *s, *s0;
 
+       d.x = _d;
        if (fpword0(d) & Sign_bit) {
                /* set sign for everything, including 0's and NaNs */
                *sign = 1;
@@ -871,7 +750,7 @@ dtoa(double d, int mode, int ndigits, int *decpt, int *sign, char **rve)
                        return nrv_alloc("Infinity", rve, 8);
                return nrv_alloc("NaN", rve, 3);
        }
-       if (!d) {
+       if (!d.x) {
                *decpt = 1;
                return nrv_alloc("0", rve, 1);
        }
@@ -905,13 +784,13 @@ dtoa(double d, int mode, int ndigits, int *decpt, int *sign, char **rve)
                 */
 
        i -= Bias;
-       ds = (d2 - 1.5) * 0.289529654602168 + 0.1760912590558 + i * 0.301029995663981;
+       ds = (d2.x - 1.5) * 0.289529654602168 + 0.1760912590558 + i * 0.301029995663981;
        k = (int)ds;
        if (ds < 0. && ds != k)
                k--;    /* want k = floor(ds) */
        k_check = 1;
        if (k >= 0 && k <= Ten_pmax) {
-               if (d < tens[k])
+               if (d.x < tens[k])
                        k--;
                k_check = 0;
        }
@@ -932,6 +811,7 @@ dtoa(double d, int mode, int ndigits, int *decpt, int *sign, char **rve)
                b5 = -k;
                s5 = 0;
        }
+       assert(k < 100);
        if (mode < 0 || mode > 9)
                mode = 0;
        try_quick = 1;
@@ -943,6 +823,7 @@ dtoa(double d, int mode, int ndigits, int *decpt, int *sign, char **rve)
        switch (mode) {
        case 0:
        case 1:
+       default:
                ilim = ilim1 = -1;
                i = 18;
                ndigits = 0;
@@ -982,7 +863,7 @@ dtoa(double d, int mode, int ndigits, int *decpt, int *sign, char **rve)
                        if (j & Bletch) {
                                /* prevent overflows */
                                j &= Bletch - 1;
-                               d /= bigtens[n_bigtens-1];
+                               d.x /= bigtens[n_bigtens-1];
                                ieps++;
                        }
                        for (; j; j >>= 1, i++)
@@ -990,44 +871,44 @@ dtoa(double d, int mode, int ndigits, int *decpt, int *sign, char **rve)
                                        ieps++;
                                        ds *= bigtens[i];
                                }
-                       d /= ds;
+                       d.x /= ds;
                } else if (j1 = -k) {
-                       d *= tens[j1 & 0xf];
+                       d.x *= tens[j1 & 0xf];
                        for (j = j1 >> 4; j; j >>= 1, i++)
                                if (j & 1) {
                                        ieps++;
-                                       d *= bigtens[i];
+                                       d.x *= bigtens[i];
                                }
                }
-               if (k_check && d < 1. && ilim > 0) {
+               if (k_check && d.x < 1. && ilim > 0) {
                        if (ilim1 <= 0)
                                goto fast_failed;
                        ilim = ilim1;
                        k--;
-                       d *= 10.;
+                       d.x *= 10.;
                        ieps++;
                }
-               eps = ieps * d + 7.;
+               eps.x = ieps * d.x + 7.;
                fpword0(eps) -= (P - 1) * Exp_msk1;
                if (ilim == 0) {
                        S = mhi = 0;
-                       d -= 5.;
-                       if (d > eps)
+                       d.x -= 5.;
+                       if (d.x > eps.x)
                                goto one_digit;
-                       if (d < -eps)
+                       if (d.x < -eps.x)
                                goto no_digits;
                        goto fast_failed;
                }
                /* Generate ilim digits, then fix them up. */
-               eps *= tens[ilim-1];
-               for (i = 1; ; i++, d *= 10.) {
-                       L = d;
-                       d -= L;
+               eps.x *= tens[ilim-1];
+               for (i = 1; ; i++, d.x *= 10.) {
+                       L = d.x;
+                       d.x -= L;
                        *s++ = '0' + (int)L;
                        if (i == ilim) {
-                               if (d > 0.5 + eps)
+                               if (d.x > 0.5 + eps.x)
                                        goto bump_up;
-                               else if (d < 0.5 - eps) {
+                               else if (d.x < 0.5 - eps.x) {
                                        while (*--s == '0')
                                                ;
                                        s++;
@@ -1038,7 +919,7 @@ dtoa(double d, int mode, int ndigits, int *decpt, int *sign, char **rve)
                }
 fast_failed:
                s = s0;
-               d = d2;
+               d.x = d2.x;
                k = k0;
                ilim = ilim0;
        }
@@ -1050,17 +931,17 @@ fast_failed:
                ds = tens[k];
                if (ndigits < 0 && ilim <= 0) {
                        S = mhi = 0;
-                       if (ilim < 0 || d <= 5 * ds)
+                       if (ilim < 0 || d.x <= 5 * ds)
                                goto no_digits;
                        goto one_digit;
                }
                for (i = 1; ; i++) {
-                       L = d / ds;
-                       d -= L * ds;
+                       L = d.x / ds;
+                       d.x -= L * ds;
                        *s++ = '0' + (int)L;
                        if (i == ilim) {
-                               d += d;
-                               if (d > ds || d == ds && L & 1) {
+                               d.x += d.x;
+                               if (d.x > ds || d.x == ds && L & 1) {
 bump_up:
                                        while (*--s == '9')
                                                if (s == s0) {
@@ -1072,7 +953,7 @@ bump_up:
                                }
                                break;
                        }
-                       if (!(d *= 10.))
+                       if (!(d.x *= 10.))
                                break;
                }
                goto ret1;