#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) */
#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
Bigint * rv;
unsigned int len;
+ assert(k < nelem(freelist));
+
ACQUIRE_DTOA_LOCK(0);
if (rv = freelist[k]) {
freelist[k] = rv->next;
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)
{
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;
}
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;
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;
#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,
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
#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)
{
*/
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
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;
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);
}
*/
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;
}
b5 = -k;
s5 = 0;
}
+ assert(k < 100);
if (mode < 0 || mode > 9)
mode = 0;
try_quick = 1;
switch (mode) {
case 0:
case 1:
+ default:
ilim = ilim1 = -1;
i = 18;
ndigits = 0;
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++)
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++;
}
fast_failed:
s = s0;
- d = d2;
+ d.x = d2.x;
k = k0;
ilim = ilim0;
}
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) {
}
break;
}
- if (!(d *= 10.))
+ if (!(d.x *= 10.))
break;
}
goto ret1;