Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(688)

Unified Diff: base/third_party/dmg_fp/dtoa.cc

Issue 99315: Merge latest changes from http://www.netlib.org/fp/dtoa.c into dtoa.cc (Closed)
Patch Set: define NO_HEX_FP Created 11 years, 8 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « base/third_party/dmg_fp/README.chromium ('k') | base/third_party/dmg_fp/gcc_warnings.patch » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: base/third_party/dmg_fp/dtoa.cc
diff --git a/base/third_party/dmg_fp/dtoa.cc b/base/third_party/dmg_fp/dtoa.cc
index ba49857514bdec0d20afe22fb41c9ba3585db374..6ab2aefb0bc86e9009d637483f31973ea62ee00b 100644
--- a/base/third_party/dmg_fp/dtoa.cc
+++ b/base/third_party/dmg_fp/dtoa.cc
@@ -103,7 +103,12 @@
* #define MALLOC your_malloc, where your_malloc(n) acts like malloc(n)
* if memory is available and otherwise does something you deem
* appropriate. If MALLOC is undefined, malloc will be invoked
- * directly -- and assumed always to succeed.
+ * directly -- and assumed always to succeed. Similarly, if you
+ * want something other than the system's free() to be called to
+ * recycle memory acquired from MALLOC, #define FREE to be the
+ * name of the alternate routine. (FREE or free is only called in
+ * pathological cases, e.g., in a dtoa call after a dtoa return in
+ * mode 3 with thousands of digits requested.)
* #define Omit_Private_Memory to omit logic (added Jan. 1998) for making
* memory allocations from a private pool of memory when possible.
* When used, the private pool is PRIVATE_MEM bytes long: 2304 bytes,
@@ -147,11 +152,6 @@
* floating-point numbers and flushes underflows to zero rather
* than implementing gradual underflow, then you must also #define
* Sudden_Underflow.
- * #define YES_ALIAS to permit aliasing certain double values with
- * arrays of ULongs. This leads to slightly better code with
- * some compilers and was always used prior to 19990916, but it
- * is not strictly legal and can cause trouble with aggressively
- * optimizing compilers (e.g., gcc 2.95.1 under -O2).
* #define USE_LOCALE to use the current locale's decimal_point value.
* #define SET_INEXACT if IEEE arithmetic is being used and extra
* computation should be done to set the inexact flag when the
@@ -169,13 +169,18 @@
* inexact or when it is a numeric value rounded to +-infinity).
* #define NO_ERRNO if strtod should not assign errno = ERANGE when
* the result overflows to +-Infinity or underflows to 0.
+ * #define NO_HEX_FP to omit recognition of hexadecimal floating-point
+ * values by strtod.
+ * #define NO_STRTOD_BIGCOMP (on IEEE-arithmetic systems only for now)
+ * to disable logic for "fast" testing of very long input strings
+ * to strtod. This testing proceeds by initially truncating the
+ * input string, then if necessary comparing the whole string with
+ * a decimal expansion to decide close cases. This logic is only
+ * used for input more than STRTOD_DIGLIM digits long (default 40).
*/
#define IEEE_8087
-#if defined(__GNUC__)
-// Make gcc 4.3+ warnings about parentheses non-fatal warnings.
-#pragma GCC diagnostic warning "-Wparentheses"
-#endif
+#define NO_HEX_FP
#ifndef Long
#define Long long
@@ -196,6 +201,12 @@ typedef unsigned Long ULong;
#include "locale.h"
#endif
+#ifdef Honor_FLT_ROUNDS
+#ifndef Trust_FLT_ROUNDS
+#include <fenv.h>
+#endif
+#endif
+
#ifdef MALLOC
#ifdef KR_headers
extern char *MALLOC();
@@ -230,6 +241,7 @@ static double private_mem[PRIVATE_mem], *pmem_next = private_mem;
#endif
#else
#undef INFNAN_CHECK
+#define NO_STRTOD_BIGCOMP
#endif
#include "errno.h"
@@ -287,24 +299,23 @@ Exactly one of IEEE_8087, IEEE_MC68k, VAX, or IBM should be defined.
typedef union { double d; ULong L[2]; } U;
-#ifdef YES_ALIAS
-#define dval(x) x
#ifdef IEEE_8087
-#define word0(x) ((ULong *)&x)[1]
-#define word1(x) ((ULong *)&x)[0]
+#define word0(x) (x)->L[1]
+#define word1(x) (x)->L[0]
#else
-#define word0(x) ((ULong *)&x)[0]
-#define word1(x) ((ULong *)&x)[1]
+#define word0(x) (x)->L[0]
+#define word1(x) (x)->L[1]
#endif
-#else
-#ifdef IEEE_8087
-#define word0(x) ((U*)&x)->L[1]
-#define word1(x) ((U*)&x)->L[0]
-#else
-#define word0(x) ((U*)&x)->L[0]
-#define word1(x) ((U*)&x)->L[1]
+#define dval(x) (x)->d
+
+#ifndef STRTOD_DIGLIM
+#define STRTOD_DIGLIM 40
#endif
-#define dval(x) ((U*)&x)->d
+
+#ifdef DIGLIM_DEBUG
+extern int strtod_diglim;
+#else
+#define strtod_diglim STRTOD_DIGLIM
#endif
/* The following definition of Storeinc is appropriate for MIPS processors.
@@ -332,7 +343,9 @@ typedef union { double d; ULong L[2]; } U;
#define Exp_msk11 0x100000
#define Exp_mask 0x7ff00000
#define P 53
+#define Nbits 53
#define Bias 1023
+#define Emax 1023
#define Emin (-1022)
#define Exp_1 0x3ff00000
#define Exp_11 0x3ff00000
@@ -387,7 +400,10 @@ typedef union { double d; ULong L[2]; } U;
#define Exp_msk11 0x1000000
#define Exp_mask 0x7f000000
#define P 14
+#define Nbits 56
#define Bias 65
+#define Emax 248
+#define Emin (-260)
#define Exp_1 0x41000000
#define Exp_11 0x41000000
#define Ebits 8 /* exponent has 7 bits, but 8 is the right value in b2d */
@@ -413,7 +429,10 @@ typedef union { double d; ULong L[2]; } U;
#define Exp_msk11 0x800000
#define Exp_mask 0x7f80
#define P 56
+#define Nbits 56
#define Bias 129
+#define Emax 126
+#define Emin (-129)
#define Exp_1 0x40800000
#define Exp_11 0x4080
#define Ebits 8
@@ -457,6 +476,10 @@ extern double rnd_prod(double, double), rnd_quot(double, double);
#define Pack_32
#endif
+typedef struct BCinfo BCinfo;
+ struct
+BCinfo { int dp0, dp1, dplen, dsign, e0, inexact, nd, nd0, rounding, scale, uflchk; };
+
#ifdef KR_headers
#define FFFFFFFF ((((unsigned long)0xffff)<<16)|(unsigned long)0xffff)
#else
@@ -487,7 +510,7 @@ extern double rnd_prod(double, double), rnd_quot(double, double);
#define FREE_DTOA_LOCK(n) /*nothing*/
#endif
-#define Kmax 15
+#define Kmax 7
double strtod(const char *s00, char **se);
char *dtoa(double d, int mode, int ndigits,
@@ -519,9 +542,10 @@ Balloc
#endif
ACQUIRE_DTOA_LOCK(0);
- if ((rv = freelist[k])) {
+ /* The k > Kmax case does not need ACQUIRE_DTOA_LOCK(0), */
+ /* but this case seems very unlikely. */
+ if (k <= Kmax && (rv = freelist[k]))
freelist[k] = rv->next;
- }
else {
x = 1 << k;
#ifdef Omit_Private_Memory
@@ -529,7 +553,7 @@ Balloc
#else
len = (sizeof(Bigint) + (x-1)*sizeof(ULong) + sizeof(double) - 1)
/sizeof(double);
- if (pmem_next - private_mem + len <= PRIVATE_mem) {
+ if (k <= Kmax && pmem_next - private_mem + len <= PRIVATE_mem) {
rv = (Bigint*)pmem_next;
pmem_next += len;
}
@@ -553,10 +577,18 @@ Bfree
#endif
{
if (v) {
- ACQUIRE_DTOA_LOCK(0);
- v->next = freelist[v->k];
- freelist[v->k] = v;
- FREE_DTOA_LOCK(0);
+ if (v->k > Kmax)
+#ifdef FREE
+ FREE((void*)v);
+#else
+ free((void*)v);
+#endif
+ else {
+ ACQUIRE_DTOA_LOCK(0);
+ v->next = freelist[v->k];
+ freelist[v->k] = v;
+ FREE_DTOA_LOCK(0);
+ }
}
}
@@ -623,9 +655,9 @@ multadd
static Bigint *
s2b
#ifdef KR_headers
- (s, nd0, nd, y9) CONST char *s; int nd0, nd; ULong y9;
+ (s, nd0, nd, y9, dplen) CONST char *s; int nd0, nd, dplen; ULong y9;
#else
- (CONST char *s, int nd0, int nd, ULong y9)
+ (CONST char *s, int nd0, int nd, ULong y9, int dplen)
#endif
{
Bigint *b;
@@ -649,10 +681,10 @@ s2b
s += 9;
do b = multadd(b, 10, *s++ - '0');
while(++i < nd0);
- s++;
+ s += dplen;
}
else
- s += 10;
+ s += dplen + 9;
for(; i < nd; i++)
b = multadd(b, 10, *s++ - '0');
return b;
@@ -661,12 +693,12 @@ s2b
static int
hi0bits
#ifdef KR_headers
- (x) register ULong x;
+ (x) ULong x;
#else
- (register ULong x)
+ (ULong x)
#endif
{
- register int k = 0;
+ int k = 0;
if (!(x & 0xffff0000)) {
k = 16;
@@ -700,8 +732,8 @@ lo0bits
(ULong *y)
#endif
{
- register int k;
- register ULong x = *y;
+ int k;
+ ULong x = *y;
if (x & 7) {
if (x & 1)
@@ -1116,13 +1148,13 @@ diff
static double
ulp
#ifdef KR_headers
- (x) double x;
+ (x) U *x;
#else
- (double x)
+ (U *x)
#endif
{
- register Long L;
- double a;
+ Long L;
+ U u;
L = (word0(x) & Exp_mask) - (P-1)*Exp_msk1;
#ifndef Avoid_Underflow
@@ -1133,26 +1165,26 @@ ulp
#ifdef IBM
L |= Exp_msk1 >> 4;
#endif
- word0(a) = L;
- word1(a) = 0;
+ word0(&u) = L;
+ word1(&u) = 0;
#ifndef Avoid_Underflow
#ifndef Sudden_Underflow
}
else {
L = -L >> Exp_shift;
if (L < Exp_shift) {
- word0(a) = 0x80000 >> L;
- word1(a) = 0;
+ word0(&u) = 0x80000 >> L;
+ word1(&u) = 0;
}
else {
- word0(a) = 0;
+ word0(&u) = 0;
L -= Exp_shift;
- word1(a) = L >= 31 ? 1 : 1 << 31 - L;
+ word1(&u) = L >= 31 ? 1 : 1 << 31 - L;
}
}
#endif
#endif
- return dval(a);
+ return dval(&u);
}
static double
@@ -1165,12 +1197,12 @@ b2d
{
ULong *xa, *xa0, w, y, z;
int k;
- double d;
+ U d;
#ifdef VAX
ULong d0, d1;
#else
-#define d0 word0(d)
-#define d1 word1(d)
+#define d0 word0(&d)
+#define d1 word1(&d)
#endif
xa0 = a->x;
@@ -1183,16 +1215,16 @@ b2d
*e = 32 - k;
#ifdef Pack_32
if (k < Ebits) {
- d0 = Exp_1 | y >> Ebits - k;
+ d0 = Exp_1 | y >> (Ebits - k);
w = xa > xa0 ? *--xa : 0;
- d1 = y << (32-Ebits) + k | w >> Ebits - k;
+ d1 = y << ((32-Ebits) + k) | w >> (Ebits - k);
goto ret_d;
}
z = xa > xa0 ? *--xa : 0;
if (k -= Ebits) {
- d0 = Exp_1 | y << k | z >> 32 - k;
+ d0 = Exp_1 | y << k | z >> (32 - k);
y = xa > xa0 ? *--xa : 0;
- d1 = z << k | y >> 32 - k;
+ d1 = z << k | y >> (32 - k);
}
else {
d0 = Exp_1 | y;
@@ -1216,21 +1248,21 @@ b2d
#endif
ret_d:
#ifdef VAX
- word0(d) = d0 >> 16 | d0 << 16;
- word1(d) = d1 >> 16 | d1 << 16;
+ word0(&d) = d0 >> 16 | d0 << 16;
+ word1(&d) = d1 >> 16 | d1 << 16;
#else
#undef d0
#undef d1
#endif
- return dval(d);
+ return dval(&d);
}
static Bigint *
d2b
#ifdef KR_headers
- (d, e, bits) double d; int *e, *bits;
+ (d, e, bits) U *d; int *e, *bits;
#else
- (double d, int *e, int *bits)
+ (U *d, int *e, int *bits)
#endif
{
Bigint *b;
@@ -1269,7 +1301,7 @@ d2b
#ifdef Pack_32
if ((y = d1)) {
if ((k = lo0bits(&y))) {
- x[0] = y | z << 32 - k;
+ x[0] = y | z << (32 - k);
z >>= k;
}
else
@@ -1280,10 +1312,6 @@ d2b
b->wds = (x[1] = z) ? 2 : 1;
}
else {
-#ifdef DEBUG
- if (!z)
- Bug("Zero passed to d2b");
-#endif
k = lo0bits(&z);
x[0] = z;
#ifndef Sudden_Underflow
@@ -1371,11 +1399,11 @@ ratio
(Bigint *a, Bigint *b)
#endif
{
- double da, db;
+ U da, db;
int k, ka, kb;
- dval(da) = b2d(a, &ka);
- dval(db) = b2d(b, &kb);
+ dval(&da) = b2d(a, &ka);
+ dval(&db) = b2d(b, &kb);
#ifdef Pack_32
k = ka - kb + 32*(a->wds - b->wds);
#else
@@ -1383,25 +1411,25 @@ ratio
#endif
#ifdef IBM
if (k > 0) {
- word0(da) += (k >> 2)*Exp_msk1;
+ word0(&da) += (k >> 2)*Exp_msk1;
if (k &= 3)
- dval(da) *= 1 << k;
+ dval(&da) *= 1 << k;
}
else {
k = -k;
- word0(db) += (k >> 2)*Exp_msk1;
+ word0(&db) += (k >> 2)*Exp_msk1;
if (k &= 3)
- dval(db) *= 1 << k;
+ dval(&db) *= 1 << k;
}
#else
if (k > 0)
- word0(da) += k*Exp_msk1;
+ word0(&da) += k*Exp_msk1;
else {
k = -k;
- word0(db) += k*Exp_msk1;
+ word0(&db) += k*Exp_msk1;
}
#endif
- return dval(da) / dval(db);
+ return dval(&da) / dval(&db);
}
static CONST double
@@ -1441,6 +1469,48 @@ static CONST double tinytens[] = { 1e-16, 1e-32 };
#endif
#endif
+#undef Need_Hexdig
+#ifdef INFNAN_CHECK
+#ifndef No_Hex_NaN
+#define Need_Hexdig
+#endif
+#endif
+
+#ifndef Need_Hexdig
+#ifndef NO_HEX_FP
+#define Need_Hexdig
+#endif
+#endif
+
+#ifdef Need_Hexdig /*{*/
+static unsigned char hexdig[256];
+
+ static void
+#ifdef KR_headers
+htinit(h, s, inc) unsigned char *h; unsigned char *s; int inc;
+#else
+htinit(unsigned char *h, unsigned char *s, int inc)
+#endif
+{
+ int i, j;
+ for(i = 0; (j = s[i]) !=0; i++)
+ h[j] = i + inc;
+ }
+
+ static void
+#ifdef KR_headers
+hexdig_init()
+#else
+hexdig_init(void)
+#endif
+{
+#define USC (unsigned char *)
+ htinit(hexdig, USC "0123456789", 0x10);
+ htinit(hexdig, USC "abcdef", 0x10 + 10);
+ htinit(hexdig, USC "ABCDEF", 0x10 + 10);
+ }
+#endif /* } Need_Hexdig */
+
#ifdef INFNAN_CHECK
#ifndef NAN_WORD0
@@ -1476,15 +1546,17 @@ match
static void
hexnan
#ifdef KR_headers
- (rvp, sp) double *rvp; CONST char **sp;
+ (rvp, sp) U *rvp; CONST char **sp;
#else
- (double *rvp, CONST char **sp)
+ (U *rvp, CONST char **sp)
#endif
{
ULong c, x[2];
CONST char *s;
- int havedig, udx0, xshift;
+ int c1, havedig, udx0, xshift;
+ if (!hexdig['0'])
+ hexdig_init();
x[0] = x[1] = 0;
havedig = xshift = 0;
udx0 = 1;
@@ -1495,12 +1567,8 @@ hexnan
if (s[1] == '0' && (s[2] == 'x' || s[2] == 'X'))
s += 2;
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';
+ if ((c1 = hexdig[c]))
+ c = c1 & 0xf;
else if (c <= ' ') {
if (udx0 && havedig) {
udx0 = 0;
@@ -1537,13 +1605,818 @@ hexnan
x[1] = (x[1] << 4) | c;
}
if ((x[0] &= 0xfffff) || x[1]) {
- word0(*rvp) = Exp_mask | x[0];
- word1(*rvp) = x[1];
+ word0(rvp) = Exp_mask | x[0];
+ word1(rvp) = x[1];
}
}
#endif /*No_Hex_NaN*/
#endif /* INFNAN_CHECK */
+#ifdef Pack_32
+#define ULbits 32
+#define kshift 5
+#define kmask 31
+#else
+#define ULbits 16
+#define kshift 4
+#define kmask 15
+#endif
+#ifndef NO_HEX_FP /*{*/
+
+ static void
+#ifdef KR_headers
+rshift(b, k) Bigint *b; int k;
+#else
+rshift(Bigint *b, int k)
+#endif
+{
+ ULong *x, *x1, *xe, y;
+ int n;
+
+ x = x1 = b->x;
+ n = k >> kshift;
+ if (n < b->wds) {
+ xe = x + b->wds;
+ x += n;
+ if (k &= kmask) {
+ n = 32 - k;
+ y = *x++ >> k;
+ while(x < xe) {
+ *x1++ = (y | (*x << n)) & 0xffffffff;
+ y = *x++ >> k;
+ }
+ if ((*x1 = y) !=0)
+ x1++;
+ }
+ else
+ while(x < xe)
+ *x1++ = *x++;
+ }
+ if ((b->wds = x1 - b->x) == 0)
+ b->x[0] = 0;
+ }
+
+ static ULong
+#ifdef KR_headers
+any_on(b, k) Bigint *b; int k;
+#else
+any_on(Bigint *b, int k)
+#endif
+{
+ int n, nwds;
+ ULong *x, *x0, x1, x2;
+
+ x = b->x;
+ nwds = b->wds;
+ n = k >> kshift;
+ if (n > nwds)
+ n = nwds;
+ else if (n < nwds && (k &= kmask)) {
+ x1 = x2 = x[n];
+ x1 >>= k;
+ x1 <<= k;
+ if (x1 != x2)
+ return 1;
+ }
+ x0 = x;
+ x += n;
+ while(x > x0)
+ if (*--x)
+ return 1;
+ return 0;
+ }
+
+enum { /* rounding values: same as FLT_ROUNDS */
+ Round_zero = 0,
+ Round_near = 1,
+ Round_up = 2,
+ Round_down = 3
+ };
+
+ static Bigint *
+#ifdef KR_headers
+increment(b) Bigint *b;
+#else
+increment(Bigint *b)
+#endif
+{
+ ULong *x, *xe;
+ Bigint *b1;
+
+ x = b->x;
+ xe = x + b->wds;
+ do {
+ if (*x < (ULong)0xffffffffL) {
+ ++*x;
+ return b;
+ }
+ *x++ = 0;
+ } while(x < xe);
+ {
+ if (b->wds >= b->maxwds) {
+ b1 = Balloc(b->k+1);
+ Bcopy(b1,b);
+ Bfree(b);
+ b = b1;
+ }
+ b->x[b->wds++] = 1;
+ }
+ return b;
+ }
+
+ void
+#ifdef KR_headers
+gethex(sp, rvp, rounding, sign)
+ CONST char **sp; U *rvp; int rounding, sign;
+#else
+gethex( CONST char **sp, U *rvp, int rounding, int sign)
+#endif
+{
+ Bigint *b;
+ CONST unsigned char *decpt, *s0, *s, *s1;
+ Long e, e1;
+ ULong L, lostbits, *x;
+ int big, denorm, esign, havedig, k, n, nbits, up, zret;
+#ifdef IBM
+ int j;
+#endif
+ enum {
+#ifdef IEEE_Arith /*{{*/
+ emax = 0x7fe - Bias - P + 1,
+ emin = Emin - P + 1
+#else /*}{*/
+ emin = Emin - P,
+#ifdef VAX
+ emax = 0x7ff - Bias - P + 1
+#endif
+#ifdef IBM
+ emax = 0x7f - Bias - P
+#endif
+#endif /*}}*/
+ };
+#ifdef USE_LOCALE
+ int i;
+#ifdef NO_LOCALE_CACHE
+ const unsigned char *decimalpoint = (unsigned char*)
+ localeconv()->decimal_point;
+#else
+ const unsigned char *decimalpoint;
+ static unsigned char *decimalpoint_cache;
+ if (!(s0 = decimalpoint_cache)) {
+ s0 = (unsigned char*)localeconv()->decimal_point;
+ if ((decimalpoint_cache = (unsigned char*)
+ MALLOC(strlen((CONST char*)s0) + 1))) {
+ strcpy((char*)decimalpoint_cache, (CONST char*)s0);
+ s0 = decimalpoint_cache;
+ }
+ }
+ decimalpoint = s0;
+#endif
+#endif
+
+ if (!hexdig['0'])
+ hexdig_init();
+ havedig = 0;
+ s0 = *(CONST unsigned char **)sp + 2;
+ while(s0[havedig] == '0')
+ havedig++;
+ s0 += havedig;
+ s = s0;
+ decpt = 0;
+ zret = 0;
+ e = 0;
+ if (hexdig[*s])
+ havedig++;
+ else {
+ zret = 1;
+#ifdef USE_LOCALE
+ for(i = 0; decimalpoint[i]; ++i) {
+ if (s[i] != decimalpoint[i])
+ goto pcheck;
+ }
+ decpt = s += i;
+#else
+ if (*s != '.')
+ goto pcheck;
+ decpt = ++s;
+#endif
+ if (!hexdig[*s])
+ goto pcheck;
+ while(*s == '0')
+ s++;
+ if (hexdig[*s])
+ zret = 0;
+ havedig = 1;
+ s0 = s;
+ }
+ while(hexdig[*s])
+ s++;
+#ifdef USE_LOCALE
+ if (*s == *decimalpoint && !decpt) {
+ for(i = 1; decimalpoint[i]; ++i) {
+ if (s[i] != decimalpoint[i])
+ goto pcheck;
+ }
+ decpt = s += i;
+#else
+ if (*s == '.' && !decpt) {
+ decpt = ++s;
+#endif
+ while(hexdig[*s])
+ s++;
+ }/*}*/
+ if (decpt)
+ e = -(((Long)(s-decpt)) << 2);
+ pcheck:
+ s1 = s;
+ big = esign = 0;
+ switch(*s) {
+ case 'p':
+ case 'P':
+ switch(*++s) {
+ case '-':
+ esign = 1;
+ /* no break */
+ case '+':
+ s++;
+ }
+ if ((n = hexdig[*s]) == 0 || n > 0x19) {
+ s = s1;
+ break;
+ }
+ e1 = n - 0x10;
+ while((n = hexdig[*++s]) !=0 && n <= 0x19) {
+ if (e1 & 0xf8000000)
+ big = 1;
+ e1 = 10*e1 + n - 0x10;
+ }
+ if (esign)
+ e1 = -e1;
+ e += e1;
+ }
+ *sp = (char*)s;
+ if (!havedig)
+ *sp = (char*)s0 - 1;
+ if (zret)
+ goto retz1;
+ if (big) {
+ if (esign) {
+#ifdef IEEE_Arith
+ switch(rounding) {
+ case Round_up:
+ if (sign)
+ break;
+ goto ret_tiny;
+ case Round_down:
+ if (!sign)
+ break;
+ goto ret_tiny;
+ }
+#endif
+ goto retz;
+#ifdef IEEE_Arith
+ ret_tiny:
+#ifndef NO_ERRNO
+ errno = ERANGE;
+#endif
+ word0(rvp) = 0;
+ word1(rvp) = 1;
+ return;
+#endif /* IEEE_Arith */
+ }
+ switch(rounding) {
+ case Round_near:
+ goto ovfl1;
+ case Round_up:
+ if (!sign)
+ goto ovfl1;
+ goto ret_big;
+ case Round_down:
+ if (sign)
+ goto ovfl1;
+ goto ret_big;
+ }
+ ret_big:
+ word0(rvp) = Big0;
+ word1(rvp) = Big1;
+ return;
+ }
+ n = s1 - s0 - 1;
+ for(k = 0; n > (1 << (kshift-2)) - 1; n >>= 1)
+ k++;
+ b = Balloc(k);
+ x = b->x;
+ n = 0;
+ L = 0;
+#ifdef USE_LOCALE
+ for(i = 0; decimalpoint[i+1]; ++i);
+#endif
+ while(s1 > s0) {
+#ifdef USE_LOCALE
+ if (*--s1 == decimalpoint[i]) {
+ s1 -= i;
+ continue;
+ }
+#else
+ if (*--s1 == '.')
+ continue;
+#endif
+ if (n == ULbits) {
+ *x++ = L;
+ L = 0;
+ n = 0;
+ }
+ L |= (hexdig[*s1] & 0x0f) << n;
+ n += 4;
+ }
+ *x++ = L;
+ b->wds = n = x - b->x;
+ n = ULbits*n - hi0bits(L);
+ nbits = Nbits;
+ lostbits = 0;
+ x = b->x;
+ if (n > nbits) {
+ n -= nbits;
+ if (any_on(b,n)) {
+ lostbits = 1;
+ k = n - 1;
+ if (x[k>>kshift] & 1 << (k & kmask)) {
+ lostbits = 2;
+ if (k > 0 && any_on(b,k))
+ lostbits = 3;
+ }
+ }
+ rshift(b, n);
+ e += n;
+ }
+ else if (n < nbits) {
+ n = nbits - n;
+ b = lshift(b, n);
+ e -= n;
+ x = b->x;
+ }
+ if (e > Emax) {
+ ovfl:
+ Bfree(b);
+ ovfl1:
+#ifndef NO_ERRNO
+ errno = ERANGE;
+#endif
+ word0(rvp) = Exp_mask;
+ word1(rvp) = 0;
+ return;
+ }
+ denorm = 0;
+ if (e < emin) {
+ denorm = 1;
+ n = emin - e;
+ if (n >= nbits) {
+#ifdef IEEE_Arith /*{*/
+ switch (rounding) {
+ case Round_near:
+ if (n == nbits && (n < 2 || any_on(b,n-1)))
+ goto ret_tiny;
+ break;
+ case Round_up:
+ if (!sign)
+ goto ret_tiny;
+ break;
+ case Round_down:
+ if (sign)
+ goto ret_tiny;
+ }
+#endif /* } IEEE_Arith */
+ Bfree(b);
+ retz:
+#ifndef NO_ERRNO
+ errno = ERANGE;
+#endif
+ retz1:
+ rvp->d = 0.;
+ return;
+ }
+ k = n - 1;
+ if (lostbits)
+ lostbits = 1;
+ else if (k > 0)
+ lostbits = any_on(b,k);
+ if (x[k>>kshift] & 1 << (k & kmask))
+ lostbits |= 2;
+ nbits -= n;
+ rshift(b,n);
+ e = emin;
+ }
+ if (lostbits) {
+ up = 0;
+ switch(rounding) {
+ case Round_zero:
+ break;
+ case Round_near:
+ if (lostbits & 2
+ && (lostbits & 1) | (x[0] & 1))
+ up = 1;
+ break;
+ case Round_up:
+ up = 1 - sign;
+ break;
+ case Round_down:
+ up = sign;
+ }
+ if (up) {
+ k = b->wds;
+ b = increment(b);
+ x = b->x;
+ if (denorm) {
+#if 0
+ if (nbits == Nbits - 1
+ && x[nbits >> kshift] & 1 << (nbits & kmask))
+ denorm = 0; /* not currently used */
+#endif
+ }
+ else if (b->wds > k
+ || ((n = nbits & kmask) !=0
+ && hi0bits(x[k-1]) < 32-n)) {
+ rshift(b,1);
+ if (++e > Emax)
+ goto ovfl;
+ }
+ }
+ }
+#ifdef IEEE_Arith
+ if (denorm)
+ word0(rvp) = b->wds > 1 ? b->x[1] & ~0x100000 : 0;
+ else
+ word0(rvp) = (b->x[1] & ~0x100000) | ((e + 0x3ff + 52) << 20);
+ word1(rvp) = b->x[0];
+#endif
+#ifdef IBM
+ if ((j = e & 3)) {
+ k = b->x[0] & ((1 << j) - 1);
+ rshift(b,j);
+ if (k) {
+ switch(rounding) {
+ case Round_up:
+ if (!sign)
+ increment(b);
+ break;
+ case Round_down:
+ if (sign)
+ increment(b);
+ break;
+ case Round_near:
+ j = 1 << (j-1);
+ if (k & j && ((k & (j-1)) | lostbits))
+ increment(b);
+ }
+ }
+ }
+ e >>= 2;
+ word0(rvp) = b->x[1] | ((e + 65 + 13) << 24);
+ word1(rvp) = b->x[0];
+#endif
+#ifdef VAX
+ /* The next two lines ignore swap of low- and high-order 2 bytes. */
+ /* word0(rvp) = (b->x[1] & ~0x800000) | ((e + 129 + 55) << 23); */
+ /* word1(rvp) = b->x[0]; */
+ word0(rvp) = ((b->x[1] & ~0x800000) >> 16) | ((e + 129 + 55) << 7) | (b->x[1] << 16);
+ word1(rvp) = (b->x[0] >> 16) | (b->x[0] << 16);
+#endif
+ Bfree(b);
+ }
+#endif /*}!NO_HEX_FP*/
+
+ static int
+#ifdef KR_headers
+dshift(b, p2) Bigint *b; int p2;
+#else
+dshift(Bigint *b, int p2)
+#endif
+{
+ int rv = hi0bits(b->x[b->wds-1]) - 4;
+ if (p2 > 0)
+ rv -= p2;
+ return rv & kmask;
+ }
+
+ static int
+quorem
+#ifdef KR_headers
+ (b, S) Bigint *b, *S;
+#else
+ (Bigint *b, Bigint *S)
+#endif
+{
+ int n;
+ ULong *bx, *bxe, q, *sx, *sxe;
+#ifdef ULLong
+ ULLong borrow, carry, y, ys;
+#else
+ ULong borrow, carry, y, ys;
+#ifdef Pack_32
+ ULong si, z, zs;
+#endif
+#endif
+
+ n = S->wds;
+#ifdef DEBUG
+ /*debug*/ if (b->wds > n)
+ /*debug*/ Bug("oversize b in quorem");
+#endif
+ if (b->wds < n)
+ return 0;
+ sx = S->x;
+ sxe = sx + --n;
+ bx = b->x;
+ bxe = bx + n;
+ q = *bxe / (*sxe + 1); /* ensure q <= true quotient */
+#ifdef DEBUG
+ /*debug*/ if (q > 9)
+ /*debug*/ Bug("oversized quotient in quorem");
+#endif
+ if (q) {
+ borrow = 0;
+ carry = 0;
+ do {
+#ifdef ULLong
+ ys = *sx++ * (ULLong)q + carry;
+ carry = ys >> 32;
+ y = *bx - (ys & FFFFFFFF) - borrow;
+ borrow = y >> 32 & (ULong)1;
+ *bx++ = y & FFFFFFFF;
+#else
+#ifdef Pack_32
+ si = *sx++;
+ ys = (si & 0xffff) * q + carry;
+ zs = (si >> 16) * q + (ys >> 16);
+ carry = zs >> 16;
+ y = (*bx & 0xffff) - (ys & 0xffff) - borrow;
+ borrow = (y & 0x10000) >> 16;
+ z = (*bx >> 16) - (zs & 0xffff) - borrow;
+ borrow = (z & 0x10000) >> 16;
+ Storeinc(bx, z, y);
+#else
+ ys = *sx++ * q + carry;
+ carry = ys >> 16;
+ y = *bx - (ys & 0xffff) - borrow;
+ borrow = (y & 0x10000) >> 16;
+ *bx++ = y & 0xffff;
+#endif
+#endif
+ }
+ while(sx <= sxe);
+ if (!*bxe) {
+ bx = b->x;
+ while(--bxe > bx && !*bxe)
+ --n;
+ b->wds = n;
+ }
+ }
+ if (cmp(b, S) >= 0) {
+ q++;
+ borrow = 0;
+ carry = 0;
+ bx = b->x;
+ sx = S->x;
+ do {
+#ifdef ULLong
+ ys = *sx++ + carry;
+ carry = ys >> 32;
+ y = *bx - (ys & FFFFFFFF) - borrow;
+ borrow = y >> 32 & (ULong)1;
+ *bx++ = y & FFFFFFFF;
+#else
+#ifdef Pack_32
+ si = *sx++;
+ ys = (si & 0xffff) + carry;
+ zs = (si >> 16) + (ys >> 16);
+ carry = zs >> 16;
+ y = (*bx & 0xffff) - (ys & 0xffff) - borrow;
+ borrow = (y & 0x10000) >> 16;
+ z = (*bx >> 16) - (zs & 0xffff) - borrow;
+ borrow = (z & 0x10000) >> 16;
+ Storeinc(bx, z, y);
+#else
+ ys = *sx++ + carry;
+ carry = ys >> 16;
+ y = *bx - (ys & 0xffff) - borrow;
+ borrow = (y & 0x10000) >> 16;
+ *bx++ = y & 0xffff;
+#endif
+#endif
+ }
+ while(sx <= sxe);
+ bx = b->x;
+ bxe = bx + n;
+ if (!*bxe) {
+ while(--bxe > bx && !*bxe)
+ --n;
+ b->wds = n;
+ }
+ }
+ return q;
+ }
+
+#ifndef NO_STRTOD_BIGCOMP
+
+ static void
+bigcomp
+#ifdef KR_headers
+ (rv, s0, bc)
+ U *rv; CONST char *s0; BCinfo *bc;
+#else
+ (U *rv, CONST char *s0, BCinfo *bc)
+#endif
+{
+ Bigint *b, *d;
+ int b2, bbits, d2, dd, dig, dsign, i, j, nd, nd0, p2, p5, speccase;
+
+ dsign = bc->dsign;
+ nd = bc->nd;
+ nd0 = bc->nd0;
+ p5 = nd + bc->e0 - 1;
+ speccase = 0;
+#ifndef Sudden_Underflow
+ if (rv->d == 0.) { /* special case: value near underflow-to-zero */
+ /* threshold was rounded to zero */
+ b = i2b(1);
+ p2 = Emin - P + 1;
+ bbits = 1;
+#ifdef Avoid_Underflow
+ word0(rv) = (P+2) << Exp_shift;
+#else
+ word1(rv) = 1;
+#endif
+ i = 0;
+#ifdef Honor_FLT_ROUNDS
+ if (bc->rounding == 1)
+#endif
+ {
+ speccase = 1;
+ --p2;
+ dsign = 0;
+ goto have_i;
+ }
+ }
+ else
+#endif
+ b = d2b(rv, &p2, &bbits);
+#ifdef Avoid_Underflow
+ p2 -= bc->scale;
+#endif
+ /* floor(log2(rv)) == bbits - 1 + p2 */
+ /* Check for denormal case. */
+ i = P - bbits;
+ if (i > (j = P - Emin - 1 + p2)) {
+#ifdef Sudden_Underflow
+ Bfree(b);
+ b = i2b(1);
+ p2 = Emin;
+ i = P - 1;
+#ifdef Avoid_Underflow
+ word0(rv) = (1 + bc->scale) << Exp_shift;
+#else
+ word0(rv) = Exp_msk1;
+#endif
+ word1(rv) = 0;
+#else
+ i = j;
+#endif
+ }
+#ifdef Honor_FLT_ROUNDS
+ if (bc->rounding != 1) {
+ if (i > 0)
+ b = lshift(b, i);
+ if (dsign)
+ b = increment(b);
+ }
+ else
+#endif
+ {
+ b = lshift(b, ++i);
+ b->x[0] |= 1;
+ }
+#ifndef Sudden_Underflow
+ have_i:
+#endif
+ p2 -= p5 + i;
+ d = i2b(1);
+ /* Arrange for convenient computation of quotients:
+ * shift left if necessary so divisor has 4 leading 0 bits.
+ */
+ if (p5 > 0)
+ d = pow5mult(d, p5);
+ else if (p5 < 0)
+ b = pow5mult(b, -p5);
+ if (p2 > 0) {
+ b2 = p2;
+ d2 = 0;
+ }
+ else {
+ b2 = 0;
+ d2 = -p2;
+ }
+ i = dshift(d, d2);
+ if ((b2 += i) > 0)
+ b = lshift(b, b2);
+ if ((d2 += i) > 0)
+ d = lshift(d, d2);
+
+ /* Now b/d = exactly half-way between the two floating-point values */
+ /* on either side of the input string. Compute first digit of b/d. */
+
+ if (!(dig = quorem(b,d))) {
+ b = multadd(b, 10, 0); /* very unlikely */
+ dig = quorem(b,d);
+ }
+
+ /* Compare b/d with s0 */
+
+ for(i = 0; i < nd0; ) {
+ if ((dd = s0[i++] - '0' - dig))
+ goto ret;
+ if (!b->x[0] && b->wds == 1) {
+ if (i < nd)
+ dd = 1;
+ goto ret;
+ }
+ b = multadd(b, 10, 0);
+ dig = quorem(b,d);
+ }
+ for(j = bc->dp1; i++ < nd;) {
+ if ((dd = s0[j++] - '0' - dig))
+ goto ret;
+ if (!b->x[0] && b->wds == 1) {
+ if (i < nd)
+ dd = 1;
+ goto ret;
+ }
+ b = multadd(b, 10, 0);
+ dig = quorem(b,d);
+ }
+ if (b->x[0] || b->wds > 1)
+ dd = -1;
+ ret:
+ Bfree(b);
+ Bfree(d);
+#ifdef Honor_FLT_ROUNDS
+ if (bc->rounding != 1) {
+ if (dd < 0) {
+ if (bc->rounding == 0) {
+ if (!dsign)
+ goto retlow1;
+ }
+ else if (dsign)
+ goto rethi1;
+ }
+ else if (dd > 0) {
+ if (bc->rounding == 0) {
+ if (dsign)
+ goto rethi1;
+ goto ret1;
+ }
+ if (!dsign)
+ goto rethi1;
+ dval(rv) += 2.*ulp(rv);
+ }
+ else {
+ bc->inexact = 0;
+ if (dsign)
+ goto rethi1;
+ }
+ }
+ else
+#endif
+ if (speccase) {
+ if (dd <= 0)
+ rv->d = 0.;
+ }
+ else if (dd < 0) {
+ if (!dsign) /* does not happen for round-near */
+retlow1:
+ dval(rv) -= ulp(rv);
+ }
+ else if (dd > 0) {
+ if (dsign) {
+ rethi1:
+ dval(rv) += ulp(rv);
+ }
+ }
+ else {
+ /* Exact half-way case: apply round-even rule. */
+ if (word1(rv) & 1) {
+ if (dsign)
+ goto rethi1;
+ goto retlow1;
+ }
+ }
+
+#ifdef Honor_FLT_ROUNDS
+ ret1:
+#endif
+ return;
+ }
+#endif /* NO_STRTOD_BIGCOMP */
+
double
strtod
#ifdef KR_headers
@@ -1552,29 +2425,27 @@ strtod
(CONST char *s00, char **se)
#endif
{
-#ifdef Avoid_Underflow
- int scale;
-#endif
- int bb2, bb5, bbe, bd2, bd5, bbbits, bs2, c, dsign,
- e, e1, esign, i, j, k, nd, nd0, nf, nz, nz0, sign;
+ int bb2, bb5, bbe, bd2, bd5, bbbits, bs2, c, e, e1;
+ int esign, i, j, k, nd, nd0, nf, nz, nz0, sign;
CONST char *s, *s0, *s1;
- double aadj, aadj1, adj, rv, rv0;
+ double aadj, aadj1;
Long L;
+ U aadj2, adj, rv, rv0;
ULong y, z;
+ BCinfo bc;
Bigint *bb, *bb1, *bd, *bd0, *bs, *delta;
#ifdef SET_INEXACT
- int inexact, oldinexact;
+ int oldinexact;
#endif
#ifdef Honor_FLT_ROUNDS /*{*/
- int Rounding;
#ifdef Trust_FLT_ROUNDS /*{{ only define this if FLT_ROUNDS really works! */
- Rounding = Flt_Rounds;
+ bc.rounding = Flt_Rounds;
#else /*}{*/
- Rounding = 1;
+ bc.rounding = 1;
switch(fegetround()) {
- case FE_TOWARDZERO: Rounding = 0; break;
- case FE_UPWARD: Rounding = 2; break;
- case FE_DOWNWARD: Rounding = 3;
+ case FE_TOWARDZERO: bc.rounding = 0; break;
+ case FE_UPWARD: bc.rounding = 2; break;
+ case FE_DOWNWARD: bc.rounding = 3;
}
#endif /*}}*/
#endif /*}*/
@@ -1582,8 +2453,8 @@ strtod
CONST char *s2;
#endif
- sign = nz0 = nz = 0;
- dval(rv) = 0.;
+ sign = nz0 = nz = bc.dplen = bc.uflchk = 0;
+ dval(&rv) = 0.;
for(s = s00;;s++) switch(*s) {
case '-':
sign = 1;
@@ -1606,6 +2477,18 @@ strtod
}
break2:
if (*s == '0') {
+#ifndef NO_HEX_FP /*{*/
+ switch(s[1]) {
+ case 'x':
+ case 'X':
+#ifdef Honor_FLT_ROUNDS
+ gethex(&s, &rv, bc.rounding, sign);
+#else
+ gethex(&s, &rv, 1, sign);
+#endif
+ goto ret;
+ }
+#endif /*}*/
nz0 = 1;
while(*++s == '0') ;
if (!*s)
@@ -1619,6 +2502,7 @@ strtod
else if (nd < 16)
z = 10*z + c - '0';
nd0 = nd;
+ bc.dp0 = bc.dp1 = s - s0;
#ifdef USE_LOCALE
s1 = localeconv()->decimal_point;
if (c == *s1) {
@@ -1640,6 +2524,8 @@ strtod
#endif
if (c == '.') {
c = *++s;
+ bc.dp1 = s - s0;
+ bc.dplen = bc.dp1 - bc.dp0;
if (!nd) {
for(; c == '0'; c = *++s)
nz++;
@@ -1711,23 +2597,24 @@ strtod
if (!nz && !nz0) {
#ifdef INFNAN_CHECK
/* Check for Nan and Infinity */
- switch(c) {
+ if (!bc.dplen)
+ switch(c) {
case 'i':
case 'I':
if (match(&s,"nf")) {
--s;
if (!match(&s,"inity"))
++s;
- word0(rv) = 0x7ff00000;
- word1(rv) = 0;
+ word0(&rv) = 0x7ff00000;
+ word1(&rv) = 0;
goto ret;
}
break;
case 'n':
case 'N':
if (match(&s, "an")) {
- word0(rv) = NAN_WORD0;
- word1(rv) = NAN_WORD1;
+ word0(&rv) = NAN_WORD0;
+ word1(&rv) = NAN_WORD1;
#ifndef No_Hex_NaN
if (*s == '(') /*)*/
hexnan(&rv, &s);
@@ -1742,7 +2629,7 @@ strtod
}
goto ret;
}
- e1 = e -= nf;
+ bc.e0 = e1 = e -= nf;
/* Now we have nd0 digits, starting at s0, followed by a
* decimal point, followed by nd-nd0 digits. The number we're
@@ -1752,13 +2639,13 @@ strtod
if (!nd0)
nd0 = nd;
k = nd < DBL_DIG + 1 ? nd : DBL_DIG + 1;
- dval(rv) = y;
+ dval(&rv) = y;
if (k > 9) {
#ifdef SET_INEXACT
if (k > DBL_DIG)
oldinexact = get_inexact();
#endif
- dval(rv) = tens[k - 9] * dval(rv) + z;
+ dval(&rv) = tens[k - 9] * dval(&rv) + z;
}
bd0 = 0;
if (nd <= DBL_DIG
@@ -1778,11 +2665,11 @@ strtod
#ifdef Honor_FLT_ROUNDS
/* round correctly FLT_ROUNDS = 2 or 3 */
if (sign) {
- rv = -rv;
+ rv.d = -rv.d;
sign = 0;
}
#endif
- /* rv = */ rounded_product(dval(rv), tens[e]);
+ /* rv = */ rounded_product(dval(&rv), tens[e]);
goto ret;
#endif
}
@@ -1794,25 +2681,25 @@ strtod
#ifdef Honor_FLT_ROUNDS
/* round correctly FLT_ROUNDS = 2 or 3 */
if (sign) {
- rv = -rv;
+ rv.d = -rv.d;
sign = 0;
}
#endif
e -= 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:
- word0(rv) -= P*Exp_msk1;
- /* rv = */ rounded_product(dval(rv), tens[e]);
- if ((word0(rv) & Exp_mask)
+ word0(&rv) -= P*Exp_msk1;
+ /* rv = */ rounded_product(dval(&rv), tens[e]);
+ if ((word0(&rv) & Exp_mask)
> Exp_msk1*(DBL_MAX_EXP+Bias-1-P))
goto ovfl;
- word0(rv) += P*Exp_msk1;
+ word0(&rv) += P*Exp_msk1;
#else
- /* rv = */ rounded_product(dval(rv), tens[e]);
+ /* rv = */ rounded_product(dval(&rv), tens[e]);
#endif
goto ret;
}
@@ -1822,11 +2709,11 @@ strtod
#ifdef Honor_FLT_ROUNDS
/* round correctly FLT_ROUNDS = 2 or 3 */
if (sign) {
- rv = -rv;
+ rv.d = -rv.d;
sign = 0;
}
#endif
- /* rv = */ rounded_quotient(dval(rv), tens[-e]);
+ /* rv = */ rounded_quotient(dval(&rv), tens[-e]);
goto ret;
}
#endif
@@ -1835,20 +2722,20 @@ strtod
#ifdef IEEE_Arith
#ifdef SET_INEXACT
- inexact = 1;
+ bc.inexact = 1;
if (k <= DBL_DIG)
oldinexact = get_inexact();
#endif
#ifdef Avoid_Underflow
- scale = 0;
+ bc.scale = 0;
#endif
#ifdef Honor_FLT_ROUNDS
- if (Rounding >= 2) {
+ if (bc.rounding >= 2) {
if (sign)
- Rounding = Rounding == 2 ? 0 : 2;
+ bc.rounding = bc.rounding == 2 ? 0 : 2;
else
- if (Rounding != 2)
- Rounding = 0;
+ if (bc.rounding != 2)
+ bc.rounding = 0;
}
#endif
#endif /*IEEE_Arith*/
@@ -1857,7 +2744,7 @@ strtod
if (e1 > 0) {
if ((i = e1 & 15))
- dval(rv) *= tens[i];
+ dval(&rv) *= tens[i];
if (e1 &= ~15) {
if (e1 > DBL_MAX_10_EXP) {
ovfl:
@@ -1867,103 +2754,99 @@ strtod
/* Can't trust HUGE_VAL */
#ifdef IEEE_Arith
#ifdef Honor_FLT_ROUNDS
- switch(Rounding) {
+ switch(bc.rounding) {
case 0: /* toward 0 */
case 3: /* toward -infinity */
- word0(rv) = Big0;
- word1(rv) = Big1;
+ word0(&rv) = Big0;
+ word1(&rv) = Big1;
break;
default:
- word0(rv) = Exp_mask;
- word1(rv) = 0;
+ word0(&rv) = Exp_mask;
+ word1(&rv) = 0;
}
#else /*Honor_FLT_ROUNDS*/
- word0(rv) = Exp_mask;
- word1(rv) = 0;
+ word0(&rv) = Exp_mask;
+ word1(&rv) = 0;
#endif /*Honor_FLT_ROUNDS*/
#ifdef SET_INEXACT
/* set overflow bit */
- dval(rv0) = 1e300;
- dval(rv0) *= dval(rv0);
+ dval(&rv0) = 1e300;
+ dval(&rv0) *= dval(&rv0);
#endif
#else /*IEEE_Arith*/
- word0(rv) = Big0;
- word1(rv) = Big1;
+ word0(&rv) = Big0;
+ word1(&rv) = Big1;
#endif /*IEEE_Arith*/
- if (bd0)
- goto retfree;
goto ret;
}
e1 >>= 4;
for(j = 0; e1 > 1; j++, e1 >>= 1)
if (e1 & 1)
- dval(rv) *= bigtens[j];
+ dval(&rv) *= bigtens[j];
/* The last multiplication could overflow. */
- word0(rv) -= P*Exp_msk1;
- dval(rv) *= bigtens[j];
- if ((z = word0(rv) & Exp_mask)
+ word0(&rv) -= P*Exp_msk1;
+ dval(&rv) *= bigtens[j];
+ if ((z = word0(&rv) & Exp_mask)
> Exp_msk1*(DBL_MAX_EXP+Bias-P))
goto ovfl;
if (z > Exp_msk1*(DBL_MAX_EXP+Bias-1-P)) {
/* set to largest number */
/* (Can't trust DBL_MAX) */
- word0(rv) = Big0;
- word1(rv) = Big1;
+ word0(&rv) = Big0;
+ word1(&rv) = Big1;
}
else
- word0(rv) += P*Exp_msk1;
+ word0(&rv) += P*Exp_msk1;
}
}
else if (e1 < 0) {
e1 = -e1;
if ((i = e1 & 15))
- dval(rv) /= tens[i];
+ dval(&rv) /= tens[i];
if (e1 >>= 4) {
if (e1 >= 1 << n_bigtens)
goto undfl;
#ifdef Avoid_Underflow
if (e1 & Scale_Bit)
- scale = 2*P;
+ bc.scale = 2*P;
for(j = 0; e1 > 0; j++, e1 >>= 1)
if (e1 & 1)
- dval(rv) *= tinytens[j];
- if (scale && (j = 2*P + 1 - ((word0(rv) & Exp_mask)
+ dval(&rv) *= tinytens[j];
+ if (bc.scale && (j = 2*P + 1 - ((word0(&rv) & Exp_mask)
>> Exp_shift)) > 0) {
/* scaled rv is denormal; clear j low bits */
if (j >= 32) {
- word1(rv) = 0;
+ word1(&rv) = 0;
if (j >= 53)
- word0(rv) = (P+2)*Exp_msk1;
+ word0(&rv) = (P+2)*Exp_msk1;
else
- word0(rv) &= 0xffffffff << j-32;
+ word0(&rv) &= 0xffffffff << (j-32);
}
else
- word1(rv) &= 0xffffffff << j;
+ word1(&rv) &= 0xffffffff << j;
}
#else
for(j = 0; e1 > 1; j++, e1 >>= 1)
if (e1 & 1)
- dval(rv) *= tinytens[j];
+ dval(&rv) *= tinytens[j];
/* The last multiplication could underflow. */
- dval(rv0) = dval(rv);
- dval(rv) *= tinytens[j];
- if (!dval(rv)) {
- dval(rv) = 2.*dval(rv0);
- dval(rv) *= tinytens[j];
+ dval(&rv0) = dval(&rv);
+ dval(&rv) *= tinytens[j];
+ if (!dval(&rv)) {
+ dval(&rv) = 2.*dval(&rv0);
+ dval(&rv) *= tinytens[j];
#endif
- if (!dval(rv)) {
+ if (!dval(&rv)) {
undfl:
- dval(rv) = 0.;
+ dval(&rv) = 0.;
#ifndef NO_ERRNO
errno = ERANGE;
#endif
- if (bd0)
- goto retfree;
goto ret;
}
#ifndef Avoid_Underflow
- word0(rv) = Tiny0;
- word1(rv) = Tiny1;
+ word0(&rv) = Tiny0;
+ word1(&rv) = Tiny1;
/* The refinement below will clean
* this approximation up.
*/
@@ -1976,12 +2859,44 @@ strtod
/* Put digits into bd: true value = bd * 10^e */
- bd0 = s2b(s0, nd0, nd, y);
+ bc.nd = nd;
+#ifndef NO_STRTOD_BIGCOMP
+ bc.nd0 = nd0; /* Only needed if nd > strtod_diglim, but done here */
+ /* to silence an erroneous warning about bc.nd0 */
+ /* possibly not being initialized. */
+ if (nd > strtod_diglim) {
+ /* ASSERT(strtod_diglim >= 18); 18 == one more than the */
+ /* minimum number of decimal digits to distinguish double values */
+ /* in IEEE arithmetic. */
+ i = j = 18;
+ if (i > nd0)
+ j += bc.dplen;
+ for(;;) {
+ if (--j <= bc.dp1 && j >= bc.dp0)
+ j = bc.dp0 - 1;
+ if (s0[j] != '0')
+ break;
+ --i;
+ }
+ e += nd - i;
+ nd = i;
+ if (nd0 > nd)
+ nd0 = nd;
+ if (nd < 9) { /* must recompute y */
+ y = 0;
+ for(i = 0; i < nd0; ++i)
+ y = 10*y + s0[i] - '0';
+ for(j = bc.dp1; i < nd; ++i)
+ y = 10*y + s0[j++] - '0';
+ }
+ }
+#endif
+ bd0 = s2b(s0, nd0, nd, y, bc.dplen);
for(;;) {
bd = Balloc(bd0->k);
Bcopy(bd, bd0);
- bb = d2b(dval(rv), &bbe, &bbbits); /* rv = bb * 2^bbe */
+ bb = d2b(&rv, &bbe, &bbbits); /* rv = bb * 2^bbe */
bs = i2b(1);
if (e >= 0) {
@@ -1998,11 +2913,11 @@ strtod
bd2 -= bbe;
bs2 = bb2;
#ifdef Honor_FLT_ROUNDS
- if (Rounding != 1)
+ if (bc.rounding != 1)
bs2++;
#endif
#ifdef Avoid_Underflow
- j = bbe - scale;
+ j = bbe - bc.scale;
i = j + bbbits - 1; /* logb(rv) */
if (i < Emin) /* denormal */
j += P - Emin;
@@ -2027,7 +2942,7 @@ strtod
bb2 += j;
bd2 += j;
#ifdef Avoid_Underflow
- bd2 += scale;
+ bd2 += bc.scale;
#endif
i = bb2 < bd2 ? bb2 : bd2;
if (i > bs2)
@@ -2052,99 +2967,116 @@ strtod
if (bs2 > 0)
bs = lshift(bs, bs2);
delta = diff(bb, bd);
- dsign = delta->sign;
+ bc.dsign = delta->sign;
delta->sign = 0;
i = cmp(delta, bs);
+#ifndef NO_STRTOD_BIGCOMP
+ if (bc.nd > nd && i <= 0) {
+ if (bc.dsign)
+ break; /* Must use bigcomp(). */
#ifdef Honor_FLT_ROUNDS
- if (Rounding != 1) {
+ if (bc.rounding != 1) {
+ if (i < 0)
+ break;
+ }
+ else
+#endif
+ {
+ bc.nd = nd;
+ i = -1; /* Discarded digits make delta smaller. */
+ }
+ }
+#endif
+#ifdef Honor_FLT_ROUNDS
+ if (bc.rounding != 1) {
if (i < 0) {
/* Error is less than an ulp */
if (!delta->x[0] && delta->wds <= 1) {
/* exact */
#ifdef SET_INEXACT
- inexact = 0;
+ bc.inexact = 0;
#endif
break;
}
- if (Rounding) {
- if (dsign) {
- adj = 1.;
+ if (bc.rounding) {
+ if (bc.dsign) {
+ adj.d = 1.;
goto apply_adj;
}
}
- else if (!dsign) {
- adj = -1.;
- if (!word1(rv)
- && !(word0(rv) & Frac_mask)) {
- y = word0(rv) & Exp_mask;
+ else if (!bc.dsign) {
+ adj.d = -1.;
+ if (!word1(&rv)
+ && !(word0(&rv) & Frac_mask)) {
+ y = word0(&rv) & Exp_mask;
#ifdef Avoid_Underflow
- if (!scale || y > 2*P*Exp_msk1)
+ if (!bc.scale || y > 2*P*Exp_msk1)
#else
if (y)
#endif
{
delta = lshift(delta,Log2P);
if (cmp(delta, bs) <= 0)
- adj = -0.5;
+ adj.d = -0.5;
}
}
apply_adj:
#ifdef Avoid_Underflow
- if (scale && (y = word0(rv) & Exp_mask)
+ if (bc.scale && (y = word0(&rv) & Exp_mask)
<= 2*P*Exp_msk1)
- word0(adj) += (2*P+1)*Exp_msk1 - y;
+ word0(&adj) += (2*P+1)*Exp_msk1 - y;
#else
#ifdef Sudden_Underflow
- if ((word0(rv) & Exp_mask) <=
+ if ((word0(&rv) & Exp_mask) <=
P*Exp_msk1) {
- word0(rv) += P*Exp_msk1;
- dval(rv) += adj*ulp(dval(rv));
- word0(rv) -= P*Exp_msk1;
+ word0(&rv) += P*Exp_msk1;
+ dval(&rv) += adj.d*ulp(dval(&rv));
+ word0(&rv) -= P*Exp_msk1;
}
else
#endif /*Sudden_Underflow*/
#endif /*Avoid_Underflow*/
- dval(rv) += adj*ulp(dval(rv));
+ dval(&rv) += adj.d*ulp(&rv);
}
break;
}
- adj = ratio(delta, bs);
- if (adj < 1.)
- adj = 1.;
- if (adj <= 0x7ffffffe) {
+ adj.d = ratio(delta, bs);
+ if (adj.d < 1.)
+ adj.d = 1.;
+ if (adj.d <= 0x7ffffffe) {
/* adj = rounding ? ceil(adj) : floor(adj); */
- y = adj;
- if (y != adj) {
- if (!((Rounding>>1) ^ dsign))
+ y = adj.d;
+ if (y != adj.d) {
+ if (!((bc.rounding>>1) ^ bc.dsign))
y++;
- adj = y;
+ adj.d = y;
}
}
#ifdef Avoid_Underflow
- if (scale && (y = word0(rv) & Exp_mask) <= 2*P*Exp_msk1)
- word0(adj) += (2*P+1)*Exp_msk1 - y;
+ if (bc.scale && (y = word0(&rv) & Exp_mask) <= 2*P*Exp_msk1)
+ word0(&adj) += (2*P+1)*Exp_msk1 - y;
#else
#ifdef Sudden_Underflow
- if ((word0(rv) & Exp_mask) <= P*Exp_msk1) {
- word0(rv) += P*Exp_msk1;
- adj *= ulp(dval(rv));
- if (dsign)
- dval(rv) += adj;
+ if ((word0(&rv) & Exp_mask) <= P*Exp_msk1) {
+ word0(&rv) += P*Exp_msk1;
+ adj.d *= ulp(dval(&rv));
+ if (bc.dsign)
+ dval(&rv) += adj.d;
else
- dval(rv) -= adj;
- word0(rv) -= P*Exp_msk1;
+ dval(&rv) -= adj.d;
+ word0(&rv) -= P*Exp_msk1;
goto cont;
}
#endif /*Sudden_Underflow*/
#endif /*Avoid_Underflow*/
- adj *= ulp(dval(rv));
- if (dsign) {
- if (word0(rv) == Big0 && word1(rv) == Big1)
+ adj.d *= ulp(&rv);
+ if (bc.dsign) {
+ if (word0(&rv) == Big0 && word1(&rv) == Big1)
goto ovfl;
- dval(rv) += adj;
+ dval(&rv) += adj.d;
}
else
- dval(rv) -= adj;
+ dval(&rv) -= adj.d;
goto cont;
}
#endif /*Honor_FLT_ROUNDS*/
@@ -2153,25 +3085,25 @@ strtod
/* Error is less than half an ulp -- check for
* special case of mantissa a power of two.
*/
- if (dsign || word1(rv) || word0(rv) & Bndry_mask
+ if (bc.dsign || word1(&rv) || word0(&rv) & Bndry_mask
#ifdef IEEE_Arith
#ifdef Avoid_Underflow
- || (word0(rv) & Exp_mask) <= (2*P+1)*Exp_msk1
+ || (word0(&rv) & Exp_mask) <= (2*P+1)*Exp_msk1
#else
- || (word0(rv) & Exp_mask) <= Exp_msk1
+ || (word0(&rv) & Exp_mask) <= Exp_msk1
#endif
#endif
) {
#ifdef SET_INEXACT
if (!delta->x[0] && delta->wds <= 1)
- inexact = 0;
+ bc.inexact = 0;
#endif
break;
}
if (!delta->x[0] && delta->wds <= 1) {
/* exact result */
#ifdef SET_INEXACT
- inexact = 0;
+ bc.inexact = 0;
#endif
break;
}
@@ -2182,62 +3114,72 @@ strtod
}
if (i == 0) {
/* exactly half-way between */
- if (dsign) {
- if ((word0(rv) & Bndry_mask1) == Bndry_mask1
- && word1(rv) == (
+ if (bc.dsign) {
+ if ((word0(&rv) & Bndry_mask1) == Bndry_mask1
+ && word1(&rv) == (
#ifdef Avoid_Underflow
- (scale && (y = word0(rv) & Exp_mask) <= 2*P*Exp_msk1)
+ (bc.scale && (y = word0(&rv) & Exp_mask) <= 2*P*Exp_msk1)
? (0xffffffff & (0xffffffff << (2*P+1-(y>>Exp_shift)))) :
#endif
0xffffffff)) {
/*boundary case -- increment exponent*/
- word0(rv) = (word0(rv) & Exp_mask)
+ word0(&rv) = (word0(&rv) & Exp_mask)
+ Exp_msk1
#ifdef IBM
| Exp_msk1 >> 4
#endif
;
- word1(rv) = 0;
+ word1(&rv) = 0;
#ifdef Avoid_Underflow
- dsign = 0;
+ bc.dsign = 0;
#endif
break;
}
}
- else if (!(word0(rv) & Bndry_mask) && !word1(rv)) {
+ else if (!(word0(&rv) & Bndry_mask) && !word1(&rv)) {
drop_down:
/* boundary case -- decrement exponent */
#ifdef Sudden_Underflow /*{{*/
- L = word0(rv) & Exp_mask;
+ L = word0(&rv) & Exp_mask;
#ifdef IBM
if (L < Exp_msk1)
#else
#ifdef Avoid_Underflow
- if (L <= (scale ? (2*P+1)*Exp_msk1 : Exp_msk1))
+ if (L <= (bc.scale ? (2*P+1)*Exp_msk1 : Exp_msk1))
#else
if (L <= Exp_msk1)
#endif /*Avoid_Underflow*/
#endif /*IBM*/
+ {
+ if (bc.nd >nd) {
+ bc.uflchk = 1;
+ break;
+ }
goto undfl;
+ }
L -= Exp_msk1;
#else /*Sudden_Underflow}{*/
#ifdef Avoid_Underflow
- if (scale) {
- L = word0(rv) & Exp_mask;
+ if (bc.scale) {
+ L = word0(&rv) & Exp_mask;
if (L <= (2*P+1)*Exp_msk1) {
if (L > (P+2)*Exp_msk1)
/* round even ==> */
/* accept rv */
break;
/* rv = smallest denormal */
+ if (bc.nd >nd) {
+ bc.uflchk = 1;
+ break;
+ }
goto undfl;
}
}
#endif /*Avoid_Underflow*/
- L = (word0(rv) & Exp_mask) - Exp_msk1;
+ L = (word0(&rv) & Exp_mask) - Exp_msk1;
#endif /*Sudden_Underflow}}*/
- word0(rv) = L | Bndry_mask1;
- word1(rv) = 0xffffffff;
+ word0(&rv) = L | Bndry_mask1;
+ word1(&rv) = 0xffffffff;
#ifdef IBM
goto cont;
#else
@@ -2245,32 +3187,42 @@ strtod
#endif
}
#ifndef ROUND_BIASED
- if (!(word1(rv) & LSB))
+ if (!(word1(&rv) & LSB))
break;
#endif
- if (dsign)
- dval(rv) += ulp(dval(rv));
+ if (bc.dsign)
+ dval(&rv) += ulp(&rv);
#ifndef ROUND_BIASED
else {
- dval(rv) -= ulp(dval(rv));
+ dval(&rv) -= ulp(&rv);
#ifndef Sudden_Underflow
- if (!dval(rv))
+ if (!dval(&rv)) {
+ if (bc.nd >nd) {
+ bc.uflchk = 1;
+ break;
+ }
goto undfl;
+ }
#endif
}
#ifdef Avoid_Underflow
- dsign = 1 - dsign;
+ bc.dsign = 1 - bc.dsign;
#endif
#endif
break;
}
if ((aadj = ratio(delta, bs)) <= 2.) {
- if (dsign)
+ if (bc.dsign)
aadj = aadj1 = 1.;
- else if (word1(rv) || word0(rv) & Bndry_mask) {
+ else if (word1(&rv) || word0(&rv) & Bndry_mask) {
#ifndef Sudden_Underflow
- if (word1(rv) == Tiny1 && !word0(rv))
+ if (word1(&rv) == Tiny1 && !word0(&rv)) {
+ if (bc.nd >nd) {
+ bc.uflchk = 1;
+ break;
+ }
goto undfl;
+ }
#endif
aadj = 1.;
aadj1 = -1.;
@@ -2288,9 +3240,9 @@ strtod
}
else {
aadj *= 0.5;
- aadj1 = dsign ? aadj : -aadj;
+ aadj1 = bc.dsign ? aadj : -aadj;
#ifdef Check_FLT_ROUNDS
- switch(Rounding) {
+ switch(bc.rounding) {
case 2: /* towards +infinity */
aadj1 -= 0.5;
break;
@@ -2303,65 +3255,72 @@ strtod
aadj1 += 0.5;
#endif /*Check_FLT_ROUNDS*/
}
- y = word0(rv) & Exp_mask;
+ y = word0(&rv) & Exp_mask;
/* Check for overflow */
if (y == Exp_msk1*(DBL_MAX_EXP+Bias-1)) {
- dval(rv0) = dval(rv);
- word0(rv) -= P*Exp_msk1;
- adj = aadj1 * ulp(dval(rv));
- dval(rv) += adj;
- if ((word0(rv) & Exp_mask) >=
+ dval(&rv0) = dval(&rv);
+ word0(&rv) -= P*Exp_msk1;
+ adj.d = aadj1 * ulp(&rv);
+ dval(&rv) += adj.d;
+ if ((word0(&rv) & Exp_mask) >=
Exp_msk1*(DBL_MAX_EXP+Bias-P)) {
- if (word0(rv0) == Big0 && word1(rv0) == Big1)
+ if (word0(&rv0) == Big0 && word1(&rv0) == Big1)
goto ovfl;
- word0(rv) = Big0;
- word1(rv) = Big1;
+ word0(&rv) = Big0;
+ word1(&rv) = Big1;
goto cont;
}
else
- word0(rv) += P*Exp_msk1;
+ word0(&rv) += P*Exp_msk1;
}
else {
#ifdef Avoid_Underflow
- if (scale && y <= 2*P*Exp_msk1) {
+ if (bc.scale && y <= 2*P*Exp_msk1) {
if (aadj <= 0x7fffffff) {
if ((z = aadj) <= 0)
z = 1;
aadj = z;
- aadj1 = dsign ? aadj : -aadj;
+ aadj1 = bc.dsign ? aadj : -aadj;
}
- word0(aadj1) += (2*P+1)*Exp_msk1 - y;
+ dval(&aadj2) = aadj1;
+ word0(&aadj2) += (2*P+1)*Exp_msk1 - y;
+ aadj1 = dval(&aadj2);
}
- adj = aadj1 * ulp(dval(rv));
- dval(rv) += adj;
+ adj.d = aadj1 * ulp(&rv);
+ dval(&rv) += adj.d;
#else
#ifdef Sudden_Underflow
- if ((word0(rv) & Exp_mask) <= P*Exp_msk1) {
- dval(rv0) = dval(rv);
- word0(rv) += P*Exp_msk1;
- adj = aadj1 * ulp(dval(rv));
- dval(rv) += adj;
+ if ((word0(&rv) & Exp_mask) <= P*Exp_msk1) {
+ dval(&rv0) = dval(&rv);
+ word0(&rv) += P*Exp_msk1;
+ adj.d = aadj1 * ulp(&rv);
+ dval(&rv) += adj.d;
#ifdef IBM
- if ((word0(rv) & Exp_mask) < P*Exp_msk1)
+ if ((word0(&rv) & Exp_mask) < P*Exp_msk1)
#else
- if ((word0(rv) & Exp_mask) <= P*Exp_msk1)
+ if ((word0(&rv) & Exp_mask) <= P*Exp_msk1)
#endif
{
- if (word0(rv0) == Tiny0
- && word1(rv0) == Tiny1)
+ if (word0(&rv0) == Tiny0
+ && word1(&rv0) == Tiny1) {
+ if (bc.nd >nd) {
+ bc.uflchk = 1;
+ break;
+ }
goto undfl;
- word0(rv) = Tiny0;
- word1(rv) = Tiny1;
+ }
+ word0(&rv) = Tiny0;
+ word1(&rv) = Tiny1;
goto cont;
}
else
- word0(rv) -= P*Exp_msk1;
+ word0(&rv) -= P*Exp_msk1;
}
else {
- adj = aadj1 * ulp(dval(rv));
- dval(rv) += adj;
+ adj.d = aadj1 * ulp(&rv);
+ dval(&rv) += adj.d;
}
#else /*Sudden_Underflow*/
/* Compute adj so that the IEEE rounding rules will
@@ -2373,31 +3332,33 @@ strtod
*/
if (y <= (P-1)*Exp_msk1 && aadj > 1.) {
aadj1 = (double)(int)(aadj + 0.5);
- if (!dsign)
+ if (!bc.dsign)
aadj1 = -aadj1;
}
- adj = aadj1 * ulp(dval(rv));
- dval(rv) += adj;
+ adj.d = aadj1 * ulp(&rv);
+ dval(&rv) += adj.d;
#endif /*Sudden_Underflow*/
#endif /*Avoid_Underflow*/
}
- z = word0(rv) & Exp_mask;
+ z = word0(&rv) & Exp_mask;
#ifndef SET_INEXACT
+ if (bc.nd == nd) {
#ifdef Avoid_Underflow
- if (!scale)
+ if (!bc.scale)
#endif
if (y == z) {
/* Can we stop now? */
L = (Long)aadj;
aadj -= L;
/* The tolerances below are conservative. */
- if (dsign || word1(rv) || word0(rv) & Bndry_mask) {
+ if (bc.dsign || word1(&rv) || word0(&rv) & Bndry_mask) {
if (aadj < .4999999 || aadj > .5000001)
break;
}
else if (aadj < .4999999/FLT_RADIX)
break;
}
+ }
#endif
cont:
Bfree(bb);
@@ -2405,168 +3366,53 @@ strtod
Bfree(bs);
Bfree(delta);
}
+ Bfree(bb);
+ Bfree(bd);
+ Bfree(bs);
+ Bfree(bd0);
+ Bfree(delta);
+#ifndef NO_STRTOD_BIGCOMP
+ if (bc.nd > nd)
+ bigcomp(&rv, s0, &bc);
+#endif
#ifdef SET_INEXACT
- if (inexact) {
+ if (bc.inexact) {
if (!oldinexact) {
- word0(rv0) = Exp_1 + (70 << Exp_shift);
- word1(rv0) = 0;
- dval(rv0) += 1.;
+ word0(&rv0) = Exp_1 + (70 << Exp_shift);
+ word1(&rv0) = 0;
+ dval(&rv0) += 1.;
}
}
else if (!oldinexact)
clear_inexact();
#endif
#ifdef Avoid_Underflow
- if (scale) {
- word0(rv0) = Exp_1 - 2*P*Exp_msk1;
- word1(rv0) = 0;
- dval(rv) *= dval(rv0);
+ if (bc.scale) {
+ word0(&rv0) = Exp_1 - 2*P*Exp_msk1;
+ word1(&rv0) = 0;
+ dval(&rv) *= dval(&rv0);
#ifndef NO_ERRNO
/* try to avoid the bug of testing an 8087 register value */
#ifdef IEEE_Arith
- if (!(word0(rv) & Exp_mask))
+ if (!(word0(&rv) & Exp_mask))
#else
- if (word0(rv) == 0 && word1(rv) == 0)
+ if (word0(&rv) == 0 && word1(&rv) == 0)
#endif
errno = ERANGE;
#endif
}
#endif /* Avoid_Underflow */
#ifdef SET_INEXACT
- if (inexact && !(word0(rv) & Exp_mask)) {
+ if (bc.inexact && !(word0(&rv) & Exp_mask)) {
/* set underflow bit */
- dval(rv0) = 1e-300;
- dval(rv0) *= dval(rv0);
+ dval(&rv0) = 1e-300;
+ dval(&rv0) *= dval(&rv0);
}
#endif
- retfree:
- Bfree(bb);
- Bfree(bd);
- Bfree(bs);
- Bfree(bd0);
- Bfree(delta);
ret:
if (se)
*se = (char *)s;
- return sign ? -dval(rv) : dval(rv);
- }
-
- static int
-quorem
-#ifdef KR_headers
- (b, S) Bigint *b, *S;
-#else
- (Bigint *b, Bigint *S)
-#endif
-{
- int n;
- ULong *bx, *bxe, q, *sx, *sxe;
-#ifdef ULLong
- ULLong borrow, carry, y, ys;
-#else
- ULong borrow, carry, y, ys;
-#ifdef Pack_32
- ULong si, z, zs;
-#endif
-#endif
-
- n = S->wds;
-#ifdef DEBUG
- /*debug*/ if (b->wds > n)
- /*debug*/ Bug("oversize b in quorem");
-#endif
- if (b->wds < n)
- return 0;
- sx = S->x;
- sxe = sx + --n;
- bx = b->x;
- bxe = bx + n;
- q = *bxe / (*sxe + 1); /* ensure q <= true quotient */
-#ifdef DEBUG
- /*debug*/ if (q > 9)
- /*debug*/ Bug("oversized quotient in quorem");
-#endif
- if (q) {
- borrow = 0;
- carry = 0;
- do {
-#ifdef ULLong
- ys = *sx++ * (ULLong)q + carry;
- carry = ys >> 32;
- y = *bx - (ys & FFFFFFFF) - borrow;
- borrow = y >> 32 & (ULong)1;
- *bx++ = y & FFFFFFFF;
-#else
-#ifdef Pack_32
- si = *sx++;
- ys = (si & 0xffff) * q + carry;
- zs = (si >> 16) * q + (ys >> 16);
- carry = zs >> 16;
- y = (*bx & 0xffff) - (ys & 0xffff) - borrow;
- borrow = (y & 0x10000) >> 16;
- z = (*bx >> 16) - (zs & 0xffff) - borrow;
- borrow = (z & 0x10000) >> 16;
- Storeinc(bx, z, y);
-#else
- ys = *sx++ * q + carry;
- carry = ys >> 16;
- y = *bx - (ys & 0xffff) - borrow;
- borrow = (y & 0x10000) >> 16;
- *bx++ = y & 0xffff;
-#endif
-#endif
- }
- while(sx <= sxe);
- if (!*bxe) {
- bx = b->x;
- while(--bxe > bx && !*bxe)
- --n;
- b->wds = n;
- }
- }
- if (cmp(b, S) >= 0) {
- q++;
- borrow = 0;
- carry = 0;
- bx = b->x;
- sx = S->x;
- do {
-#ifdef ULLong
- ys = *sx++ + carry;
- carry = ys >> 32;
- y = *bx - (ys & FFFFFFFF) - borrow;
- borrow = y >> 32 & (ULong)1;
- *bx++ = y & FFFFFFFF;
-#else
-#ifdef Pack_32
- si = *sx++;
- ys = (si & 0xffff) + carry;
- zs = (si >> 16) + (ys >> 16);
- carry = zs >> 16;
- y = (*bx & 0xffff) - (ys & 0xffff) - borrow;
- borrow = (y & 0x10000) >> 16;
- z = (*bx >> 16) - (zs & 0xffff) - borrow;
- borrow = (z & 0x10000) >> 16;
- Storeinc(bx, z, y);
-#else
- ys = *sx++ + carry;
- carry = ys >> 16;
- y = *bx - (ys & 0xffff) - borrow;
- borrow = (y & 0x10000) >> 16;
- *bx++ = y & 0xffff;
-#endif
-#endif
- }
- while(sx <= sxe);
- bx = b->x;
- bxe = bx + n;
- if (!*bxe) {
- while(--bxe > bx && !*bxe)
- --n;
- b->wds = n;
- }
- }
- return q;
+ return sign ? -dval(&rv) : dval(&rv);
}
#ifndef MULTIPLE_THREADS
@@ -2671,10 +3517,10 @@ freedtoa(char *s)
char *
dtoa
#ifdef KR_headers
- (d, mode, ndigits, decpt, sign, rve)
- double d; int mode, ndigits, *decpt, *sign; char **rve;
+ (dd, mode, ndigits, decpt, sign, rve)
+ double dd; int mode, ndigits, *decpt, *sign; char **rve;
#else
- (double d, int mode, int ndigits, int *decpt, int *sign, char **rve)
+ (double dd, int mode, int ndigits, int *decpt, int *sign, char **rve)
#endif
{
/* Arguments ndigits, decpt, sign are similar to those
@@ -2711,7 +3557,7 @@ dtoa
to hold the suppressed trailing zeros.
*/
- int bbits, b2, b5, be, dig, i, ieps, ilim = 0, ilim0, ilim1 = 0,
+ int bbits, b2, b5, be, dig, i, ieps, ilim, ilim0, ilim1,
j, j1, k, k0, k_check, leftright, m2, m5, s2, s5,
spec_case, try_quick;
Long L;
@@ -2720,7 +3566,8 @@ dtoa
ULong x;
#endif
Bigint *b, *b1, *delta, *mlo, *mhi, *S;
- double d2, ds, eps;
+ U d2, eps, u;
+ double ds;
char *s, *s0;
#ifdef SET_INEXACT
int inexact, oldinexact;
@@ -2746,34 +3593,35 @@ dtoa
}
#endif
- if (word0(d) & Sign_bit) {
+ u.d = dd;
+ if (word0(&u) & Sign_bit) {
/* set sign for everything, including 0's and NaNs */
*sign = 1;
- word0(d) &= ~Sign_bit; /* clear sign bit */
+ word0(&u) &= ~Sign_bit; /* clear sign bit */
}
else
*sign = 0;
#if defined(IEEE_Arith) + defined(VAX)
#ifdef IEEE_Arith
- if ((word0(d) & Exp_mask) == Exp_mask)
+ if ((word0(&u) & Exp_mask) == Exp_mask)
#else
- if (word0(d) == 0x8000)
+ if (word0(&u) == 0x8000)
#endif
{
/* Infinity or NaN */
*decpt = 9999;
#ifdef IEEE_Arith
- if (!word1(d) && !(word0(d) & 0xfffff))
+ if (!word1(&u) && !(word0(&u) & 0xfffff))
return nrv_alloc("Infinity", rve, 8);
#endif
return nrv_alloc("NaN", rve, 3);
}
#endif
#ifdef IBM
- dval(d) += 0; /* normalize */
+ dval(&u) += 0; /* normalize */
#endif
- if (!dval(d)) {
+ if (!dval(&u)) {
*decpt = 1;
return nrv_alloc("0", rve, 1);
}
@@ -2792,18 +3640,18 @@ dtoa
}
#endif
- b = d2b(dval(d), &be, &bbits);
+ b = d2b(&u, &be, &bbits);
#ifdef Sudden_Underflow
- i = (int)(word0(d) >> Exp_shift1 & (Exp_mask>>Exp_shift1));
+ i = (int)(word0(&u) >> Exp_shift1 & (Exp_mask>>Exp_shift1));
#else
- if ((i = (int)(word0(d) >> Exp_shift1 & (Exp_mask>>Exp_shift1)))) {
+ if ((i = (int)(word0(&u) >> Exp_shift1 & (Exp_mask>>Exp_shift1)))) {
#endif
- dval(d2) = dval(d);
- word0(d2) &= Frac_mask1;
- word0(d2) |= Exp_11;
+ dval(&d2) = dval(&u);
+ word0(&d2) &= Frac_mask1;
+ word0(&d2) |= Exp_11;
#ifdef IBM
- if (j = 11 - hi0bits(word0(d2) & Frac_mask))
- dval(d2) /= 1 << j;
+ if (j = 11 - hi0bits(word0(&d2) & Frac_mask))
+ dval(&d2) /= 1 << j;
#endif
/* log(x) ~=~ log(1.5) + (x-1.5)/1.5
@@ -2840,21 +3688,21 @@ dtoa
/* d is denormalized */
i = bbits + be + (Bias + (P-1) - 1);
- x = i > 32 ? word0(d) << 64 - i | word1(d) >> i - 32
- : word1(d) << 32 - i;
- dval(d2) = x;
- word0(d2) -= 31*Exp_msk1; /* adjust exponent */
+ x = i > 32 ? word0(&u) << (64 - i) | word1(&u) >> (i - 32)
+ : word1(&u) << (32 - i);
+ dval(&d2) = x;
+ word0(&d2) -= 31*Exp_msk1; /* adjust exponent */
i -= (Bias + (P-1) - 1) + 1;
denorm = 1;
}
#endif
- ds = (dval(d2)-1.5)*0.289529654602168 + 0.1760912590558 + i*0.301029995663981;
+ ds = (dval(&d2)-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 (dval(d) < tens[k])
+ if (dval(&u) < tens[k])
k--;
k_check = 0;
}
@@ -2893,10 +3741,11 @@ dtoa
try_quick = 0;
}
leftright = 1;
+ ilim = ilim1 = -1; /* Values for cases 0 and 1; done here to */
+ /* silence erroneous "gcc -Wall" warning. */
switch(mode) {
case 0:
case 1:
- ilim = ilim1 = -1;
i = 18;
ndigits = 0;
break;
@@ -2930,7 +3779,7 @@ dtoa
/* Try to get by with floating-point arithmetic. */
i = 0;
- dval(d2) = dval(d);
+ dval(&d2) = dval(&u);
k0 = k;
ilim0 = ilim;
ieps = 2; /* conservative */
@@ -2940,7 +3789,7 @@ dtoa
if (j & Bletch) {
/* prevent overflows */
j &= Bletch - 1;
- dval(d) /= bigtens[n_bigtens-1];
+ dval(&u) /= bigtens[n_bigtens-1];
ieps++;
}
for(; j; j >>= 1, i++)
@@ -2948,32 +3797,32 @@ dtoa
ieps++;
ds *= bigtens[i];
}
- dval(d) /= ds;
+ dval(&u) /= ds;
}
else if ((j1 = -k)) {
- dval(d) *= tens[j1 & 0xf];
+ dval(&u) *= tens[j1 & 0xf];
for(j = j1 >> 4; j; j >>= 1, i++)
if (j & 1) {
ieps++;
- dval(d) *= bigtens[i];
+ dval(&u) *= bigtens[i];
}
}
- if (k_check && dval(d) < 1. && ilim > 0) {
+ if (k_check && dval(&u) < 1. && ilim > 0) {
if (ilim1 <= 0)
goto fast_failed;
ilim = ilim1;
k--;
- dval(d) *= 10.;
+ dval(&u) *= 10.;
ieps++;
}
- dval(eps) = ieps*dval(d) + 7.;
- word0(eps) -= (P-1)*Exp_msk1;
+ dval(&eps) = ieps*dval(&u) + 7.;
+ word0(&eps) -= (P-1)*Exp_msk1;
if (ilim == 0) {
S = mhi = 0;
- dval(d) -= 5.;
- if (dval(d) > dval(eps))
+ dval(&u) -= 5.;
+ if (dval(&u) > dval(&eps))
goto one_digit;
- if (dval(d) < -dval(eps))
+ if (dval(&u) < -dval(&eps))
goto no_digits;
goto fast_failed;
}
@@ -2982,34 +3831,34 @@ dtoa
/* Use Steele & White method of only
* generating digits needed.
*/
- dval(eps) = 0.5/tens[ilim-1] - dval(eps);
+ dval(&eps) = 0.5/tens[ilim-1] - dval(&eps);
for(i = 0;;) {
- L = dval(d);
- dval(d) -= L;
+ L = dval(&u);
+ dval(&u) -= L;
*s++ = '0' + (int)L;
- if (dval(d) < dval(eps))
+ if (dval(&u) < dval(&eps))
goto ret1;
- if (1. - dval(d) < dval(eps))
+ if (1. - dval(&u) < dval(&eps))
goto bump_up;
if (++i >= ilim)
break;
- dval(eps) *= 10.;
- dval(d) *= 10.;
+ dval(&eps) *= 10.;
+ dval(&u) *= 10.;
}
}
else {
#endif
/* Generate ilim digits, then fix them up. */
- dval(eps) *= tens[ilim-1];
- for(i = 1;; i++, dval(d) *= 10.) {
- L = (Long)(dval(d));
- if (!(dval(d) -= L))
+ dval(&eps) *= tens[ilim-1];
+ for(i = 1;; i++, dval(&u) *= 10.) {
+ L = (Long)(dval(&u));
+ if (!(dval(&u) -= L))
ilim = i;
*s++ = '0' + (int)L;
if (i == ilim) {
- if (dval(d) > 0.5 + dval(eps))
+ if (dval(&u) > 0.5 + dval(&eps))
goto bump_up;
- else if (dval(d) < 0.5 - dval(eps)) {
+ else if (dval(&u) < 0.5 - dval(&eps)) {
while(*--s == '0');
s++;
goto ret1;
@@ -3022,7 +3871,7 @@ dtoa
#endif
fast_failed:
s = s0;
- dval(d) = dval(d2);
+ dval(&u) = dval(&d2);
k = k0;
ilim = ilim0;
}
@@ -3034,22 +3883,22 @@ dtoa
ds = tens[k];
if (ndigits < 0 && ilim <= 0) {
S = mhi = 0;
- if (ilim < 0 || dval(d) <= 5*ds)
+ if (ilim < 0 || dval(&u) <= 5*ds)
goto no_digits;
goto one_digit;
}
- for(i = 1;; i++, dval(d) *= 10.) {
- L = (Long)(dval(d) / ds);
- dval(d) -= L*ds;
+ for(i = 1;; i++, dval(&u) *= 10.) {
+ L = (Long)(dval(&u) / ds);
+ dval(&u) -= L*ds;
#ifdef Check_FLT_ROUNDS
/* If FLT_ROUNDS == 2, L will usually be high by 1 */
- if (dval(d) < 0) {
+ if (dval(&u) < 0) {
L--;
- dval(d) += ds;
+ dval(&u) += ds;
}
#endif
*s++ = '0' + (int)L;
- if (!dval(d)) {
+ if (!dval(&u)) {
#ifdef SET_INEXACT
inexact = 0;
#endif
@@ -3063,8 +3912,8 @@ dtoa
case 2: goto bump_up;
}
#endif
- dval(d) += dval(d);
- if (dval(d) > ds || dval(d) == ds && L & 1) {
+ dval(&u) += dval(&u);
+ if (dval(&u) > ds || (dval(&u) == ds && L & 1)) {
bump_up:
while(*--s == '9')
if (s == s0) {
@@ -3129,9 +3978,9 @@ dtoa
&& Rounding == 1
#endif
) {
- if (!word1(d) && !(word0(d) & Bndry_mask)
+ if (!word1(&u) && !(word0(&u) & Bndry_mask)
#ifndef Sudden_Underflow
- && word0(d) & (Exp_mask & ~Exp_msk1)
+ && word0(&u) & (Exp_mask & ~Exp_msk1)
#endif
) {
/* The special case */
@@ -3151,22 +4000,16 @@ dtoa
#ifdef Pack_32
if ((i = ((s5 ? 32 - hi0bits(S->x[S->wds-1]) : 1) + s2) & 0x1f))
i = 32 - i;
+#define iInc 28
#else
if (i = ((s5 ? 32 - hi0bits(S->x[S->wds-1]) : 1) + s2) & 0xf)
i = 16 - i;
+#define iInc 12
#endif
- if (i > 4) {
- i -= 4;
- b2 += i;
- m2 += i;
- s2 += i;
- }
- else if (i < 4) {
- i += 28;
- b2 += i;
- m2 += i;
- s2 += i;
- }
+ i = dshift(S, s2);
+ b2 += i;
+ m2 += i;
+ s2 += i;
if (b2 > 0)
b = lshift(b, b2);
if (s2 > 0)
@@ -3217,7 +4060,7 @@ dtoa
j1 = delta->sign ? 1 : cmp(b, delta);
Bfree(delta);
#ifndef ROUND_BIASED
- if (j1 == 0 && mode != 1 && !(word1(d) & 1)
+ if (j1 == 0 && mode != 1 && !(word1(&u) & 1)
#ifdef Honor_FLT_ROUNDS
&& Rounding >= 1
#endif
@@ -3234,11 +4077,11 @@ dtoa
goto ret;
}
#endif
- if (j < 0 || j == 0 && mode != 1
+ if (j < 0 || (j == 0 && mode != 1
#ifndef ROUND_BIASED
- && !(word1(d) & 1)
+ && !(word1(&u) & 1)
#endif
- ) {
+ )) {
if (!b->x[0] && b->wds <= 1) {
#ifdef SET_INEXACT
inexact = 0;
@@ -3255,7 +4098,7 @@ dtoa
if (j1 > 0) {
b = lshift(b, 1);
j1 = cmp(b, S);
- if ((j1 > 0 || j1 == 0 && dig & 1)
+ if ((j1 > 0 || (j1 == 0 && dig & 1))
&& dig++ == '9')
goto round_9_up;
}
@@ -3315,7 +4158,7 @@ dtoa
#endif
b = lshift(b, 1);
j = cmp(b, S);
- if (j > 0 || j == 0 && dig & 1) {
+ if (j > 0 || (j == 0 && dig & 1)) {
roundoff:
while(*--s == '9')
if (s == s0) {
@@ -3343,9 +4186,9 @@ dtoa
#ifdef SET_INEXACT
if (inexact) {
if (!oldinexact) {
- word0(d) = Exp_1 + (70 << Exp_shift);
- word1(d) = 0;
- dval(d) += 1.;
+ word0(&u) = Exp_1 + (70 << Exp_shift);
+ word1(&u) = 0;
+ dval(&u) += 1.;
}
}
else if (!oldinexact)
« no previous file with comments | « base/third_party/dmg_fp/README.chromium ('k') | base/third_party/dmg_fp/gcc_warnings.patch » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698