]> git.saurik.com Git - apple/libc.git/blobdiff - gdtoa/FreeBSD/gdtoa-strtodg.c
Libc-1439.100.3.tar.gz
[apple/libc.git] / gdtoa / FreeBSD / gdtoa-strtodg.c
index 41ead32decb9ca6706d685ec7d2b06f59aa33126..c436ea9a8a96eac36e5cf899ab6bb6cc7dde3f98 100644 (file)
@@ -29,13 +29,29 @@ THIS SOFTWARE.
 /* Please send bug reports to David M. Gay (dmg at acm dot org,
  * with " at " changed at "@" and " dot " changed to ".").     */
 
+#include "xlocale_private.h"
+
 #include "gdtoaimp.h"
 
 #ifdef USE_LOCALE
 #include "locale.h"
 #endif
 
- static CONST int
+#define fivesbits __fivesbits_D2A
+#define all_on __all_on_D2A
+#define set_ones __set_ones_D2A
+#define rvOK __rvOK_D2A
+#define mantbits __mantbits_D2A
+
+#ifdef BUILDING_VARIANT
+extern CONST int fivesbits[];
+int all_on(Bigint *b, int n);
+Bigint *set_ones(Bigint *b, int n);
+int rvOK(U *d, CONST FPI *fpi, Long *exp, ULong *bits, int exact, int rd, int *irv);
+int mantbits(U *d);
+#else /* !BUILDING_VARIANT */
+
+ __private_extern__ CONST int
 fivesbits[] = {         0,  3,  5,  7, 10, 12, 14, 17, 19, 21,
                24, 26, 28, 31, 33, 35, 38, 40, 42, 45,
                47, 49, 52
@@ -121,7 +137,7 @@ decrement(Bigint *b)
 #endif
        }
 
static int
__private_extern__ int
 #ifdef KR_headers
 all_on(b, n) Bigint *b; int n;
 #else
@@ -168,13 +184,13 @@ set_ones(Bigint *b, int n)
        return b;
        }
 
static int
__private_extern__ int
 rvOK
 #ifdef KR_headers
  (d, fpi, exp, bits, exact, rd, irv)
double d; FPI *fpi; Long *exp; ULong *bits; int exact, rd, *irv;
U *d; CONST FPI *fpi; Long *exp; ULong *bits; int exact, rd, *irv;
 #else
- (double d, FPI *fpi, Long *exp, ULong *bits, int exact, int rd, int *irv)
+ (U *d, CONST FPI *fpi, Long *exp, ULong *bits, int exact, int rd, int *irv)
 #endif
 {
        Bigint *b;
@@ -182,7 +198,7 @@ rvOK
        int bdif, e, j, k, k1, nb, rv;
 
        carry = rv = 0;
-       b = d2b(d, &e, &bdif);
+       b = d2b(dval(d), &e, &bdif);
        bdif -= nb = fpi->nbits;
        e += bdif;
        if (bdif <= 0) {
@@ -289,11 +305,11 @@ rvOK
        return rv;
        }
 
static int
__private_extern__ int
 #ifdef KR_headers
-mantbits(d) double d;
+mantbits(d) U *d;
 #else
-mantbits(double d)
+mantbits(U *d)
 #endif
 {
        ULong L;
@@ -312,13 +328,15 @@ mantbits(double d)
        return P - 32 - lo0bits(&L);
        }
 
+#endif /* BUILDING_VARIANT */
+
  int
 strtodg
 #ifdef KR_headers
-       (s00, se, fpi, exp, bits)
-       CONST char *s00; char **se; FPI *fpi; Long *exp; ULong *bits;
+       (s00, se, fpi, exp, bits, loc)
+       CONST char *s00; char **se; CONST FPI *fpi; Long *exp; ULong *bits; locale_t loc;
 #else
-       (CONST char *s00, char **se, FPI *fpi, Long *exp, ULong *bits)
+       (CONST char *s00, char **se, CONST FPI *fpi, Long *exp, ULong *bits, locale_t loc)
 #endif
 {
        int abe, abits, asub;
@@ -327,30 +345,38 @@ strtodg
        int j, k, nbits, nd, nd0, nf, nz, nz0, rd, rvbits, rve, rve1, sign;
        int sudden_underflow;
        CONST char *s, *s0, *s1;
-       double adj, adj0, rv, tol;
+       char *strunc = NULL;
+       double adj0, tol;
        Long L;
+       U adj, rv;
        ULong *b, *be, y, z;
        Bigint *ab, *bb, *bb1, *bd, *bd0, *bs, *delta, *rvb, *rvb0;
-#ifdef USE_LOCALE
+#ifdef USE_LOCALE /*{{*/
+       NORMALIZE_LOCALE(loc);
 #ifdef NO_LOCALE_CACHE
-       char *decimalpoint = localeconv()->decimal_point;
+       char *decimalpoint = localeconv_l(loc)->decimal_point;
+       int dplen = strlen(decimalpoint);
 #else
        char *decimalpoint;
        static char *decimalpoint_cache;
+       static int dplen;
        if (!(s0 = decimalpoint_cache)) {
-               s0 = localeconv()->decimal_point;
-               if ((decimalpoint_cache = (char*)malloc(strlen(s0) + 1))) {
+               s0 = localeconv_l(loc)->decimal_point;
+               if ((decimalpoint_cache = (char*)MALLOC(strlen(s0) + 1))) {
                        strcpy(decimalpoint_cache, s0);
                        s0 = decimalpoint_cache;
                        }
+               dplen = strlen(s0);
                }
        decimalpoint = (char*)s0;
-#endif
-#endif
+#endif /*NO_LOCALE_CACHE*/
+#else  /*USE_LOCALE}{*/
+#define dplen 1
+#endif /*USE_LOCALE}}*/
 
        irv = STRTOG_Zero;
        denorm = sign = nz0 = nz = 0;
-       dval(rv) = 0.;
+       dval(&rv) = 0.;
        rvb = 0;
        nbits = fpi->nbits;
        for(s = s00;;s++) switch(*s) {
@@ -382,7 +408,7 @@ strtodg
                switch(s[1]) {
                  case 'x':
                  case 'X':
-                       irv = gethex(&s, fpi, exp, &rvb, sign);
+                       irv = gethex(&s, fpi, exp, &rvb, sign, loc);
                        if (irv == STRTOG_NoNumber) {
                                s = s00;
                                sign = 0;
@@ -519,6 +545,7 @@ strtodg
                        }
                goto ret;
                }
+       TRUNCATE_DIGITS(s0, strunc, nd, nd0, nf, fpi->nbits, fpi->emin, dplen);
 
        irv = STRTOG_Normal;
        e1 = e -= nf;
@@ -542,13 +569,13 @@ strtodg
        if (!nd0)
                nd0 = nd;
        k = nd < DBL_DIG + 1 ? nd : DBL_DIG + 1;
-       dval(rv) = y;
+       dval(&rv) = y;
        if (k > 9)
-               dval(rv) = tens[k - 9] * dval(rv) + z;
+               dval(&rv) = tens[k - 9] * dval(&rv) + z;
        bd0 = 0;
        if (nbits <= P && nd <= DBL_DIG) {
                if (!e) {
-                       if (rvOK(dval(rv), fpi, exp, bits, 1, rd, &irv))
+                       if (rvOK(&rv, fpi, exp, bits, 1, rd, &irv))
                                goto ret;
                        }
                else if (e > 0) {
@@ -556,9 +583,9 @@ strtodg
 #ifdef VAX
                                goto vax_ovfl_check;
 #else
-                               i = fivesbits[e] + mantbits(dval(rv)) <= P;
-                               /* rv = */ rounded_product(dval(rv), tens[e]);
-                               if (rvOK(dval(rv), fpi, exp, bits, i, rd, &irv))
+                               i = fivesbits[e] + mantbits(&rv) <= P;
+                               /* rv = */ rounded_product(dval(&rv), tens[e]);
+                               if (rvOK(&rv, fpi, exp, bits, i, rd, &irv))
                                        goto ret;
                                e1 -= e;
                                goto rv_notOK;
@@ -571,32 +598,32 @@ strtodg
                                 */
                                e2 = e - i;
                                e1 -= i;
-                               dval(rv) *= tens[i];
+                               dval(&rv) *= tens[i];
 #ifdef VAX
                                /* VAX exponent range is so narrow we must
                                 * worry about overflow here...
                                 */
  vax_ovfl_check:
-                               dval(adj) = dval(rv);
-                               word0(adj) -= P*Exp_msk1;
-                               /* adj = */ rounded_product(dval(adj), tens[e2]);
-                               if ((word0(adj) & Exp_mask)
+                               dval(&adj) = dval(&rv);
+                               word0(&adj) -= P*Exp_msk1;
+                               /* adj = */ rounded_product(dval(&adj), tens[e2]);
+                               if ((word0(&adj) & Exp_mask)
                                 > Exp_msk1*(DBL_MAX_EXP+Bias-1-P))
                                        goto rv_notOK;
-                               word0(adj) += P*Exp_msk1;
-                               dval(rv) = dval(adj);
+                               word0(&adj) += P*Exp_msk1;
+                               dval(&rv) = dval(&adj);
 #else
-                               /* rv = */ rounded_product(dval(rv), tens[e2]);
+                               /* rv = */ rounded_product(dval(&rv), tens[e2]);
 #endif
-                               if (rvOK(dval(rv), fpi, exp, bits, 0, rd, &irv))
+                               if (rvOK(&rv, fpi, exp, bits, 0, rd, &irv))
                                        goto ret;
                                e1 -= e2;
                                }
                        }
 #ifndef Inaccurate_Divide
                else if (e >= -Ten_pmax) {
-                       /* rv = */ rounded_quotient(dval(rv), tens[-e]);
-                       if (rvOK(dval(rv), fpi, exp, bits, 0, rd, &irv))
+                       /* rv = */ rounded_quotient(dval(&rv), tens[-e]);
+                       if (rvOK(&rv, fpi, exp, bits, 0, rd, &irv))
                                goto ret;
                        e1 -= e;
                        }
@@ -610,45 +637,45 @@ strtodg
        e2 = 0;
        if (e1 > 0) {
                if ( (i = e1 & 15) !=0)
-                       dval(rv) *= tens[i];
+                       dval(&rv) *= tens[i];
                if (e1 &= ~15) {
                        e1 >>= 4;
-                       while(e1 >= (1 << n_bigtens-1)) {
-                               e2 += ((word0(rv) & Exp_mask)
+                       while(e1 >= (1 << (n_bigtens-1))) {
+                               e2 += ((word0(&rv) & Exp_mask)
                                        >> Exp_shift1) - Bias;
-                               word0(rv) &= ~Exp_mask;
-                               word0(rv) |= Bias << Exp_shift1;
-                               dval(rv) *= bigtens[n_bigtens-1];
-                               e1 -= 1 << n_bigtens-1;
+                               word0(&rv) &= ~Exp_mask;
+                               word0(&rv) |= Bias << Exp_shift1;
+                               dval(&rv) *= bigtens[n_bigtens-1];
+                               e1 -= 1 << (n_bigtens-1);
                                }
-                       e2 += ((word0(rv) & Exp_mask) >> Exp_shift1) - Bias;
-                       word0(rv) &= ~Exp_mask;
-                       word0(rv) |= Bias << Exp_shift1;
+                       e2 += ((word0(&rv) & Exp_mask) >> Exp_shift1) - Bias;
+                       word0(&rv) &= ~Exp_mask;
+                       word0(&rv) |= Bias << Exp_shift1;
                        for(j = 0; e1 > 0; j++, e1 >>= 1)
                                if (e1 & 1)
-                                       dval(rv) *= bigtens[j];
+                                       dval(&rv) *= bigtens[j];
                        }
                }
        else if (e1 < 0) {
                e1 = -e1;
                if ( (i = e1 & 15) !=0)
-                       dval(rv) /= tens[i];
+                       dval(&rv) /= tens[i];
                if (e1 &= ~15) {
                        e1 >>= 4;
-                       while(e1 >= (1 << n_bigtens-1)) {
-                               e2 += ((word0(rv) & Exp_mask)
+                       while(e1 >= (1 << (n_bigtens-1))) {
+                               e2 += ((word0(&rv) & Exp_mask)
                                        >> Exp_shift1) - Bias;
-                               word0(rv) &= ~Exp_mask;
-                               word0(rv) |= Bias << Exp_shift1;
-                               dval(rv) *= tinytens[n_bigtens-1];
-                               e1 -= 1 << n_bigtens-1;
+                               word0(&rv) &= ~Exp_mask;
+                               word0(&rv) |= Bias << Exp_shift1;
+                               dval(&rv) *= tinytens[n_bigtens-1];
+                               e1 -= 1 << (n_bigtens-1);
                                }
-                       e2 += ((word0(rv) & Exp_mask) >> Exp_shift1) - Bias;
-                       word0(rv) &= ~Exp_mask;
-                       word0(rv) |= Bias << Exp_shift1;
+                       e2 += ((word0(&rv) & Exp_mask) >> Exp_shift1) - Bias;
+                       word0(&rv) &= ~Exp_mask;
+                       word0(&rv) |= Bias << Exp_shift1;
                        for(j = 0; e1 > 0; j++, e1 >>= 1)
                                if (e1 & 1)
-                                       dval(rv) *= tinytens[j];
+                                       dval(&rv) *= tinytens[j];
                        }
                }
 #ifdef IBM
@@ -659,7 +686,7 @@ strtodg
         */
        e2 <<= 2;
 #endif
-       rvb = d2b(dval(rv), &rve, &rvbits);     /* rv = rvb * 2^rve */
+       rvb = d2b(dval(&rv), &rve, &rvbits);    /* rv = rvb * 2^rve */
        rve += e2;
        if ((j = rvbits - nbits) > 0) {
                rshift(rvb, j);
@@ -687,6 +714,10 @@ strtodg
                                        rvb->x[0] = 0;
                                        *exp = emin;
                                        irv = STRTOG_Underflow | STRTOG_Inexlo;
+/* When __DARWIN_UNIX03 is set, we don't need this (errno is set later) */
+#if !defined(NO_ERRNO) && !__DARWIN_UNIX03
+                                       errno = ERANGE;
+#endif
                                        goto ret;
                                        }
                                rvb->x[0] = rvb->wds = rvbits = 1;
@@ -703,7 +734,7 @@ strtodg
 
        /* Put digits into bd: true value = bd * 10^e */
 
-       bd0 = s2b(s0, nd0, nd, y);
+       bd0 = s2b(s0, nd0, nd, y, dplen);
 
        for(;;) {
                bd = Balloc(bd0->k);
@@ -837,7 +868,7 @@ strtodg
                                }
                        else
                                irv = STRTOG_Normal | STRTOG_Inexhi;
-                       if (bbbits < nbits && !denorm || !(rvb->x[0] & 1))
+                       if ((bbbits < nbits && !denorm) || !(rvb->x[0] & 1))
                                break;
                        if (dsign) {
                                rvb = increment(rvb);
@@ -854,7 +885,7 @@ strtodg
                                }
                        break;
                        }
-               if ((dval(adj) = ratio(delta, bs)) <= 2.) {
+               if ((dval(&adj) = ratio(delta, bs)) <= 2.) {
  adj1:
                        inex = STRTOG_Inexlo;
                        if (dsign) {
@@ -868,15 +899,15 @@ strtodg
                                irv = STRTOG_Underflow | STRTOG_Inexlo;
                                break;
                                }
-                       adj0 = dval(adj) = 1.;
+                       adj0 = dval(&adj) = 1.;
                        }
                else {
-                       adj0 = dval(adj) *= 0.5;
+                       adj0 = dval(&adj) *= 0.5;
                        if (dsign) {
                                asub = 0;
                                inex = STRTOG_Inexlo;
                                }
-                       if (dval(adj) < 2147483647.) {
+                       if (dval(&adj) < 2147483647.) {
                                L = adj0;
                                adj0 -= L;
                                switch(rd) {
@@ -895,12 +926,12 @@ strtodg
                                                inex = STRTOG_Inexact - inex;
                                                }
                                  }
-                               dval(adj) = L;
+                               dval(&adj) = L;
                                }
                        }
                y = rve + rvbits;
 
-               /* adj *= ulp(dval(rv)); */
+               /* adj *= ulp(dval(&rv)); */
                /* if (asub) rv -= adj; else rv += adj; */
 
                if (!denorm && rvbits < nbits) {
@@ -908,7 +939,7 @@ strtodg
                        rve -= j;
                        rvbits = nbits;
                        }
-               ab = d2b(dval(adj), &abe, &abits);
+               ab = d2b(dval(&adj), &abe, &abits);
                if (abe < 0)
                        rshift(ab, -abe);
                else if (abe > 0)
@@ -962,15 +993,15 @@ strtodg
                z = rve + rvbits;
                if (y == z && L) {
                        /* Can we stop now? */
-                       tol = dval(adj) * 5e-16; /* > max rel error */
-                       dval(adj) = adj0 - .5;
-                       if (dval(adj) < -tol) {
+                       tol = dval(&adj) * 5e-16; /* > max rel error */
+                       dval(&adj) = adj0 - .5;
+                       if (dval(&adj) < -tol) {
                                if (adj0 > tol) {
                                        irv |= inex;
                                        break;
                                        }
                                }
-                       else if (dval(adj) > tol && adj0 < 1. - tol) {
+                       else if (dval(&adj) > tol && adj0 < 1. - tol) {
                                irv |= inex;
                                break;
                                }
@@ -1032,7 +1063,7 @@ strtodg
                if (sudden_underflow) {
                        rvb->wds = 0;
                        irv = STRTOG_Underflow | STRTOG_Inexlo;
-#ifndef NO_ERRNO
+#if !defined(NO_ERRNO) && __DARWIN_UNIX03
                        errno = ERANGE;
 #endif
                        }
@@ -1041,7 +1072,7 @@ strtodg
                                (rvb->wds > 0 ? STRTOG_Denormal : STRTOG_Zero);
                        if (irv & STRTOG_Inexact) {
                                irv |= STRTOG_Underflow;
-#ifndef NO_ERRNO
+#if !defined(NO_ERRNO) && __DARWIN_UNIX03
                                errno = ERANGE;
 #endif
                                }
@@ -1055,5 +1086,11 @@ strtodg
                copybits(bits, nbits, rvb);
                Bfree(rvb);
                }
+       if (strunc)
+#ifdef FREE
+               FREE(strunc);
+#else
+               free(strunc);
+#endif
        return irv;
        }