2009-06-28 Ozkan Sezer <sezero@users.sourceforge.net>

* mingwex/gdtoa/README.mingw mingwex/gdtoa/gdtoa_fltrnds.h: New files.
        * mingwex/gdtoa/README mingwex/gdtoa/dmisc.c mingwex/gdtoa/dtoa.c
        mingwex/gdtoa/g__fmt.c mingwex/gdtoa/g_dfmt.c mingwex/gdtoa/g_ffmt.c
        mingwex/gdtoa/g_xfmt.c mingwex/gdtoa/gd_arith.h mingwex/gdtoa/gd_qnan.h
        mingwex/gdtoa/gdtoa.c mingwex/gdtoa/gdtoa.h mingwex/gdtoa/gdtoaimp.h
        mingwex/gdtoa/gethex.c mingwex/gdtoa/gmisc.c mingwex/gdtoa/hd_init.c
        mingwex/gdtoa/hexnan.c mingwex/gdtoa/misc.c mingwex/gdtoa/qnan.c
        mingwex/gdtoa/smisc.c mingwex/gdtoa/strtodg.c mingwex/gdtoa/strtodnrp.c
        mingwex/gdtoa/strtof.c mingwex/gdtoa/strtopx.c mingwex/gdtoa/sum.c
        mingwex/gdtoa/ulp.c:  Update the gdtoa library to match the netlib.org
        sources as of Apr. 20, 2009.  Update further to match the sources in
        the mingw-w64 tree as of June 28, 2009, by removing IBM, CRAY and VAX
        code, removing KR_headers, ANSI, Void and Char ifdefs, renaming the
        double/ulong union from U to dbl_union for better grepping and white-
        space tidy-ups.
This commit is contained in:
Chris Sutcliffe 2009-07-12 22:44:37 +00:00
parent 62fb43a722
commit 15e114f5c5
28 changed files with 1345 additions and 1437 deletions

View File

@ -1,3 +1,21 @@
2009-06-28 Ozkan Sezer <sezero@users.sourceforge.net>
* mingwex/gdtoa/README.mingw mingwex/gdtoa/gdtoa_fltrnds.h: New files.
* mingwex/gdtoa/README mingwex/gdtoa/dmisc.c mingwex/gdtoa/dtoa.c
mingwex/gdtoa/g__fmt.c mingwex/gdtoa/g_dfmt.c mingwex/gdtoa/g_ffmt.c
mingwex/gdtoa/g_xfmt.c mingwex/gdtoa/gd_arith.h mingwex/gdtoa/gd_qnan.h
mingwex/gdtoa/gdtoa.c mingwex/gdtoa/gdtoa.h mingwex/gdtoa/gdtoaimp.h
mingwex/gdtoa/gethex.c mingwex/gdtoa/gmisc.c mingwex/gdtoa/hd_init.c
mingwex/gdtoa/hexnan.c mingwex/gdtoa/misc.c mingwex/gdtoa/qnan.c
mingwex/gdtoa/smisc.c mingwex/gdtoa/strtodg.c mingwex/gdtoa/strtodnrp.c
mingwex/gdtoa/strtof.c mingwex/gdtoa/strtopx.c mingwex/gdtoa/sum.c
mingwex/gdtoa/ulp.c: Update the gdtoa library to match the netlib.org
sources as of Apr. 20, 2009. Update further to match the sources in
the mingw-w64 tree as of June 28, 2009, by removing IBM, CRAY and VAX
code, removing KR_headers, ANSI, Void and Char ifdefs, renaming the
double/ulong union from U to dbl_union for better grepping and white-
space tidy-ups.
2009-06-16 Chris Sutcliffe <ir0nh34d@users.sourceforge.net> 2009-06-16 Chris Sutcliffe <ir0nh34d@users.sourceforge.net>
* include/stdlib.h (_wtof): Define. * include/stdlib.h (_wtof): Define.

View File

@ -56,7 +56,9 @@ two letters:
whose sum is the desired value whose sum is the desired value
For decimal -> binary conversions, there are three families of For decimal -> binary conversions, there are three families of
helper routines: one for round-nearest: helper routines: one for round-nearest (or the current rounding
mode on IEEE-arithmetic systems that provide the C99 fegetround()
function, if compiled with -DHonor_FLT_ROUNDS):
strtof strtof
strtod strtod
@ -191,6 +193,9 @@ in the buffer, if the buffer was long enough, or 0. Other forms of
conversion are easily done with the help of gdtoa(), such as %e or %f conversion are easily done with the help of gdtoa(), such as %e or %f
style and conversions with direction of rounding specified (so that, if style and conversions with direction of rounding specified (so that, if
desired, the decimal value is either >= or <= the binary value). desired, the decimal value is either >= or <= the binary value).
On IEEE-arithmetic systems that provide the C99 fegetround() function,
if compiled with -DHonor_FLT_ROUNDS, these routines honor the current
rounding mode.
For an example of more general conversions based on dtoa(), see For an example of more general conversions based on dtoa(), see
netlib's "printf.c from ampl/solvers". netlib's "printf.c from ampl/solvers".
@ -332,5 +337,21 @@ Compiling g__fmt.c, strtod.c, and strtodg.c with -DUSE_LOCALE causes
the decimal-point character to be taken from the current locale; otherwise the decimal-point character to be taken from the current locale; otherwise
it is '.'. it is '.'.
Source files dtoa.c and strtod.c in this directory are derived from
netlib's "dtoa.c from fp" and are meant to function equivalently.
When compiled with Honor_FLT_ROUNDS #defined (on systems that provide
FLT_ROUNDS and fegetround() as specified in the C99 standard), they
honor the current rounding mode. Because FLT_ROUNDS is buggy on some
(Linux) systems -- not reflecting calls on fesetround(), as the C99
standard says it should -- when Honor_FLT_ROUNDS is #defined, the
current rounding mode is obtained from fegetround() rather than from
FLT_ROUNDS, unless Trust_FLT_ROUNDS is also #defined.
Compile with -DUSE_LOCALE to use the current locale; otherwise
decimal points are assumed to be '.'. With -DUSE_LOCALE, unless
you also compile with -DNO_LOCALE_CACHE, the details about the
current "decimal point" character string are cached and assumed not
to change during the program's execution.
Please send comments to David M. Gay (dmg at acm dot org, with " at " Please send comments to David M. Gay (dmg at acm dot org, with " at "
changed at "@" and " dot " changed to "."). changed at "@" and " dot " changed to ".").

View File

@ -0,0 +1,19 @@
The gdtoa code here is based on David M. Gay's original
gdtoa source at http://www.netlib.org/fp/ from April 20,
2009. The major changes between the original source and
the mingw port here include:
* IBM, CRAY and VAX code removed.
* KR_headers, ANSI, Void and Char ifdefs are removed.
* gdtoa symbols are prepended with "__".
* g_xfmt() uses __fpclassifyl() instead of interpreting
the flags bit-wise.
* lo0bits() and hi0bits() of misc.c replaced by wrappers
to gcc's __builtin_clz()
* The double/ulong union renamed from U to dbl_union
(grep'ped better..)
* A few compiler warning fixes here and there.
* A few other insignificant changes (if any..)
MinGW specific compile-time definitions are at the top of
gdtoaimp.h and gdtoa.h headers.

View File

@ -31,12 +31,11 @@ THIS SOFTWARE.
#include "gdtoaimp.h" #include "gdtoaimp.h"
char * #ifndef MULTIPLE_THREADS
#ifdef KR_headers char *dtoa_result;
rv_alloc(i) int i;
#else
rv_alloc(int i)
#endif #endif
char *rv_alloc (int i)
{ {
int j, k, *r; int j, k, *r;
@ -52,14 +51,9 @@ rv_alloc(int i)
dtoa_result = dtoa_result =
#endif #endif
(char *)(r+1); (char *)(r+1);
} }
char * char *nrv_alloc (char *s, char **rve, int n)
#ifdef KR_headers
nrv_alloc(s, rve, n) char *s, **rve; int n;
#else
nrv_alloc(char *s, char **rve, int n)
#endif
{ {
char *rv, *t; char *rv, *t;
@ -69,7 +63,7 @@ nrv_alloc(char *s, char **rve, int n)
if (rve) if (rve)
*rve = t; *rve = t;
return rv; return rv;
} }
/* freedtoa(s) must be used to free values s returned by dtoa /* freedtoa(s) must be used to free values s returned by dtoa
* when MULTIPLE_THREADS is #defined. It should be used in all cases, * when MULTIPLE_THREADS is #defined. It should be used in all cases,
@ -77,12 +71,7 @@ nrv_alloc(char *s, char **rve, int n)
* when MULTIPLE_THREADS is not defined. * when MULTIPLE_THREADS is not defined.
*/ */
void void __freedtoa (char *s)
#ifdef KR_headers
__freedtoa(s) char *s;
#else
__freedtoa(char *s)
#endif
{ {
Bigint *b = (Bigint *)((int *)s - 1); Bigint *b = (Bigint *)((int *)s - 1);
b->maxwds = 1 << (b->k = *(int*)b); b->maxwds = 1 << (b->k = *(int*)b);
@ -91,15 +80,9 @@ __freedtoa(char *s)
if (s == dtoa_result) if (s == dtoa_result)
dtoa_result = 0; dtoa_result = 0;
#endif #endif
} }
int int quorem (Bigint *b, Bigint *S)
quorem
#ifdef KR_headers
(b, S) Bigint *b, *S;
#else
(Bigint *b, Bigint *S)
#endif
{ {
int n; int n;
ULong *bx, *bxe, q, *sx, *sxe; ULong *bx, *bxe, q, *sx, *sxe;
@ -157,15 +140,16 @@ quorem
*bx++ = y & 0xffff; *bx++ = y & 0xffff;
#endif #endif
#endif #endif
} } while(sx <= sxe);
while(sx <= sxe);
if (!*bxe) { if (!*bxe) {
bx = b->x; bx = b->x;
while(--bxe > bx && !*bxe) while(--bxe > bx && !*bxe)
--n; --n;
b->wds = n; b->wds = n;
}
} }
}
if (cmp(b, S) >= 0) { if (cmp(b, S) >= 0) {
q++; q++;
borrow = 0; borrow = 0;
@ -198,15 +182,15 @@ quorem
*bx++ = y & 0xffff; *bx++ = y & 0xffff;
#endif #endif
#endif #endif
} } while(sx <= sxe);
while(sx <= sxe);
bx = b->x; bx = b->x;
bxe = bx + n; bxe = bx + n;
if (!*bxe) { if (!*bxe) {
while(--bxe > bx && !*bxe) while(--bxe > bx && !*bxe)
--n; --n;
b->wds = n; b->wds = n;
}
} }
return q;
} }
return q;
}

View File

@ -66,21 +66,13 @@ THIS SOFTWARE.
*/ */
#ifdef Honor_FLT_ROUNDS #ifdef Honor_FLT_ROUNDS
#define Rounding rounding
#undef Check_FLT_ROUNDS #undef Check_FLT_ROUNDS
#define Check_FLT_ROUNDS #define Check_FLT_ROUNDS
#else #else
#define Rounding Flt_Rounds #define Rounding Flt_Rounds
#endif #endif
char * char *__dtoa (double d0, int mode, int ndigits, int *decpt, int *sign, char **rve)
__dtoa
#ifdef KR_headers
(d, mode, ndigits, decpt, sign, rve)
double d; int mode, ndigits, *decpt, *sign; char **rve;
#else
(double d, int mode, int ndigits, int *decpt, int *sign, char **rve)
#endif
{ {
/* Arguments ndigits, decpt, sign are similar to those /* Arguments ndigits, decpt, sign are similar to those
of ecvt and fcvt; trailing zeros are suppressed from of ecvt and fcvt; trailing zeros are suppressed from
@ -116,7 +108,7 @@ __dtoa
to hold the suppressed trailing zeros. 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, j, j1, k, k0, k_check, leftright, m2, m5, s2, s5,
spec_case, try_quick; spec_case, try_quick;
Long L; Long L;
@ -125,88 +117,84 @@ __dtoa
ULong x; ULong x;
#endif #endif
Bigint *b, *b1, *delta, *mlo, *mhi, *S; Bigint *b, *b1, *delta, *mlo, *mhi, *S;
double d2, ds, eps; union _dbl_union d, d2, eps;
double ds;
char *s, *s0; char *s, *s0;
#ifdef Honor_FLT_ROUNDS
int rounding;
#endif
#ifdef SET_INEXACT #ifdef SET_INEXACT
int inexact, oldinexact; int inexact, oldinexact;
#endif #endif
#ifdef Honor_FLT_ROUNDS /*{*/
int Rounding;
#ifdef Trust_FLT_ROUNDS /*{{ only define this if FLT_ROUNDS really works! */
Rounding = Flt_Rounds;
#else /*}{*/
Rounding = 1;
switch(fegetround()) {
case FE_TOWARDZERO: Rounding = 0; break;
case FE_UPWARD: Rounding = 2; break;
case FE_DOWNWARD: Rounding = 3;
}
#endif /*}}*/
#endif /*}*/
#ifndef MULTIPLE_THREADS #ifndef MULTIPLE_THREADS
if (dtoa_result) { if (dtoa_result) {
__freedtoa(dtoa_result); __freedtoa(dtoa_result);
dtoa_result = 0; dtoa_result = 0;
} }
#endif #endif
d.d = d0;
if (word0(d) & Sign_bit) { if (word0(&d) & Sign_bit) {
/* set sign for everything, including 0's and NaNs */ /* set sign for everything, including 0's and NaNs */
*sign = 1; *sign = 1;
word0(d) &= ~Sign_bit; /* clear sign bit */ word0(&d) &= ~Sign_bit; /* clear sign bit */
} }
else else
*sign = 0; *sign = 0;
#if defined(IEEE_Arith) + defined(VAX) if ((word0(&d) & Exp_mask) == Exp_mask)
#ifdef IEEE_Arith {
if ((word0(d) & Exp_mask) == Exp_mask)
#else
if (word0(d) == 0x8000)
#endif
{
/* Infinity or NaN */ /* Infinity or NaN */
*decpt = 9999; *decpt = 9999;
#ifdef IEEE_Arith if (!word1(&d) && !(word0(&d) & 0xfffff))
if (!word1(d) && !(word0(d) & 0xfffff))
return nrv_alloc("Infinity", rve, 8); return nrv_alloc("Infinity", rve, 8);
#endif
return nrv_alloc("NaN", rve, 3); return nrv_alloc("NaN", rve, 3);
} }
#endif if (!dval(&d)) {
#ifdef IBM
dval(d) += 0; /* normalize */
#endif
if (!dval(d)) {
*decpt = 1; *decpt = 1;
return nrv_alloc("0", rve, 1); return nrv_alloc("0", rve, 1);
} }
#ifdef SET_INEXACT #ifdef SET_INEXACT
try_quick = oldinexact = get_inexact(); try_quick = oldinexact = get_inexact();
inexact = 1; inexact = 1;
#endif #endif
#ifdef Honor_FLT_ROUNDS #ifdef Honor_FLT_ROUNDS
if ((rounding = Flt_Rounds) >= 2) { if (Rounding >= 2) {
if (*sign) if (*sign)
rounding = rounding == 2 ? 0 : 2; Rounding = Rounding == 2 ? 0 : 2;
else else
if (rounding != 2) if (Rounding != 2)
rounding = 0; Rounding = 0;
} }
#endif #endif
b = d2b(dval(d), &be, &bbits); b = d2b(dval(&d), &be, &bbits);
#ifdef Sudden_Underflow #ifdef Sudden_Underflow
i = (int)(word0(d) >> Exp_shift1 & (Exp_mask>>Exp_shift1)); i = (int)(word0(&d) >> Exp_shift1 & (Exp_mask>>Exp_shift1));
#else #else
if (( i = (int)(word0(d) >> Exp_shift1 & (Exp_mask>>Exp_shift1)) )!=0) { if (( i = (int)(word0(&d) >> Exp_shift1 & (Exp_mask>>Exp_shift1)) )!=0) {
#endif
dval(d2) = dval(d);
word0(d2) &= Frac_mask1;
word0(d2) |= Exp_11;
#ifdef IBM
if (( j = 11 - hi0bits(word0(d2) & Frac_mask) )!=0)
dval(d2) /= 1 << j;
#endif #endif
dval(&d2) = dval(&d);
word0(&d2) &= Frac_mask1;
word0(&d2) |= Exp_11;
/* log(x) ~=~ log(1.5) + (x-1.5)/1.5 /* log(x) ~=~ log(1.5) + (x-1.5)/1.5
* log10(x) = log(x) / log(10) * log10(x) = log(x) / log(10)
* ~=~ log(1.5)/log(10) + (x-1.5)/(1.5*log(10)) * ~=~ log(1.5)/log(10) + (x-1.5)/(1.5*log(10))
* log10(d) = (i-Bias)*log(2)/log(10) + log10(d2) * log10(&d) = (i-Bias)*log(2)/log(10) + log10(&d2)
* *
* This suggests computing an approximation k to log10(d) by * This suggests computing an approximation k to log10(&d) by
* *
* k = (i - Bias)*0.301029995663981 * k = (i - Bias)*0.301029995663981
* + ( (d2-1.5)*0.289529654602168 + 0.176091259055681 ); * + ( (d2-1.5)*0.289529654602168 + 0.176091259055681 );
@ -224,54 +212,50 @@ __dtoa
*/ */
i -= Bias; i -= Bias;
#ifdef IBM
i <<= 2;
i += j;
#endif
#ifndef Sudden_Underflow #ifndef Sudden_Underflow
denorm = 0; denorm = 0;
} }
else { else {
/* d is denormalized */ /* d is denormalized */
i = bbits + be + (Bias + (P-1) - 1); i = bbits + be + (Bias + (P-1) - 1);
x = i > 32 ? word0(d) << (64 - i) | word1(d) >> (i - 32) x = i > 32 ? word0(&d) << (64 - i) | word1(&d) >> (i - 32)
: word1(d) << (32 - i); : word1(&d) << (32 - i);
dval(d2) = x; dval(&d2) = x;
word0(d2) -= 31*Exp_msk1; /* adjust exponent */ word0(&d2) -= 31*Exp_msk1; /* adjust exponent */
i -= (Bias + (P-1) - 1) + 1; i -= (Bias + (P-1) - 1) + 1;
denorm = 1; denorm = 1;
} }
#endif #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; k = (int)ds;
if (ds < 0. && ds != k) if (ds < 0. && ds != k)
k--; /* want k = floor(ds) */ k--; /* want k = floor(ds) */
k_check = 1; k_check = 1;
if (k >= 0 && k <= Ten_pmax) { if (k >= 0 && k <= Ten_pmax) {
if (dval(d) < tens[k]) if (dval(&d) < tens[k])
k--; k--;
k_check = 0; k_check = 0;
} }
j = bbits - i - 1; j = bbits - i - 1;
if (j >= 0) { if (j >= 0) {
b2 = 0; b2 = 0;
s2 = j; s2 = j;
} }
else { else {
b2 = -j; b2 = -j;
s2 = 0; s2 = 0;
} }
if (k >= 0) { if (k >= 0) {
b5 = 0; b5 = 0;
s5 = k; s5 = k;
s2 += k; s2 += k;
} }
else { else {
b2 -= k; b2 -= k;
b5 = -k; b5 = -k;
s5 = 0; s5 = 0;
} }
if (mode < 0 || mode > 9) if (mode < 0 || mode > 9)
mode = 0; mode = 0;
@ -286,12 +270,13 @@ __dtoa
if (mode > 5) { if (mode > 5) {
mode -= 4; mode -= 4;
try_quick = 0; try_quick = 0;
} }
leftright = 1; leftright = 1;
ilim = ilim1 = -1; /* Values for cases 0 and 1; done here to */
/* silence erroneous "gcc -Wall" warning. */
switch(mode) { switch(mode) {
case 0: case 0:
case 1: case 1:
ilim = ilim1 = -1;
i = 18; i = 18;
ndigits = 0; ndigits = 0;
break; break;
@ -312,11 +297,11 @@ __dtoa
ilim1 = i - 1; ilim1 = i - 1;
if (i <= 0) if (i <= 0)
i = 1; i = 1;
} }
s = s0 = rv_alloc(i); s = s0 = rv_alloc(i);
#ifdef Honor_FLT_ROUNDS #ifdef Honor_FLT_ROUNDS
if (mode > 1 && rounding != 1) if (mode > 1 && Rounding != 1)
leftright = 0; leftright = 0;
#endif #endif
@ -325,7 +310,7 @@ __dtoa
/* Try to get by with floating-point arithmetic. */ /* Try to get by with floating-point arithmetic. */
i = 0; i = 0;
dval(d2) = dval(d); dval(&d2) = dval(&d);
k0 = k; k0 = k;
ilim0 = ilim; ilim0 = ilim;
ieps = 2; /* conservative */ ieps = 2; /* conservative */
@ -335,92 +320,92 @@ __dtoa
if (j & Bletch) { if (j & Bletch) {
/* prevent overflows */ /* prevent overflows */
j &= Bletch - 1; j &= Bletch - 1;
dval(d) /= bigtens[n_bigtens-1]; dval(&d) /= bigtens[n_bigtens-1];
ieps++; ieps++;
} }
for(; j; j >>= 1, i++) for(; j; j >>= 1, i++)
if (j & 1) { if (j & 1) {
ieps++; ieps++;
ds *= bigtens[i]; ds *= bigtens[i];
} }
dval(d) /= ds; dval(&d) /= ds;
} }
else if (( j1 = -k )!=0) { else if (( j1 = -k )!=0) {
dval(d) *= tens[j1 & 0xf]; dval(&d) *= tens[j1 & 0xf];
for(j = j1 >> 4; j; j >>= 1, i++) for(j = j1 >> 4; j; j >>= 1, i++)
if (j & 1) { if (j & 1) {
ieps++; ieps++;
dval(d) *= bigtens[i]; dval(&d) *= bigtens[i];
} }
} }
if (k_check && dval(d) < 1. && ilim > 0) { if (k_check && dval(&d) < 1. && ilim > 0) {
if (ilim1 <= 0) if (ilim1 <= 0)
goto fast_failed; goto fast_failed;
ilim = ilim1; ilim = ilim1;
k--; k--;
dval(d) *= 10.; dval(&d) *= 10.;
ieps++; ieps++;
} }
dval(eps) = ieps*dval(d) + 7.; dval(&eps) = ieps*dval(&d) + 7.;
word0(eps) -= (P-1)*Exp_msk1; word0(&eps) -= (P-1)*Exp_msk1;
if (ilim == 0) { if (ilim == 0) {
S = mhi = 0; S = mhi = 0;
dval(d) -= 5.; dval(&d) -= 5.;
if (dval(d) > dval(eps)) if (dval(&d) > dval(&eps))
goto one_digit; goto one_digit;
if (dval(d) < -dval(eps)) if (dval(&d) < -dval(&eps))
goto no_digits; goto no_digits;
goto fast_failed; goto fast_failed;
} }
#ifndef No_leftright #ifndef No_leftright
if (leftright) { if (leftright) {
/* Use Steele & White method of only /* Use Steele & White method of only
* generating digits needed. * generating digits needed.
*/ */
dval(eps) = 0.5/tens[ilim-1] - dval(eps); dval(&eps) = 0.5/tens[ilim-1] - dval(&eps);
for(i = 0;;) { for(i = 0;;) {
L = dval(d); L = dval(&d);
dval(d) -= L; dval(&d) -= L;
*s++ = '0' + (int)L; *s++ = '0' + (int)L;
if (dval(d) < dval(eps)) if (dval(&d) < dval(&eps))
goto ret1; goto ret1;
if (1. - dval(d) < dval(eps)) if (1. - dval(&d) < dval(&eps))
goto bump_up; goto bump_up;
if (++i >= ilim) if (++i >= ilim)
break; break;
dval(eps) *= 10.; dval(&eps) *= 10.;
dval(d) *= 10.; dval(&d) *= 10.;
}
} }
}
else { else {
#endif #endif
/* Generate ilim digits, then fix them up. */ /* Generate ilim digits, then fix them up. */
dval(eps) *= tens[ilim-1]; dval(&eps) *= tens[ilim-1];
for(i = 1;; i++, dval(d) *= 10.) { for(i = 1;; i++, dval(&d) *= 10.) {
L = (Long)(dval(d)); L = (Long)(dval(&d));
if (!(dval(d) -= L)) if (!(dval(&d) -= L))
ilim = i; ilim = i;
*s++ = '0' + (int)L; *s++ = '0' + (int)L;
if (i == ilim) { if (i == ilim) {
if (dval(d) > 0.5 + dval(eps)) if (dval(&d) > 0.5 + dval(&eps))
goto bump_up; goto bump_up;
else if (dval(d) < 0.5 - dval(eps)) { else if (dval(&d) < 0.5 - dval(&eps)) {
while(*--s == '0'); while(*--s == '0');
s++; s++;
goto ret1; goto ret1;
}
break;
} }
break;
} }
#ifndef No_leftright
} }
#ifndef No_leftright
}
#endif #endif
fast_failed: fast_failed:
s = s0; s = s0;
dval(d) = dval(d2); dval(&d) = dval(&d2);
k = k0; k = k0;
ilim = ilim0; ilim = ilim0;
} }
/* Do we have a "small" integer? */ /* Do we have a "small" integer? */
@ -429,51 +414,51 @@ __dtoa
ds = tens[k]; ds = tens[k];
if (ndigits < 0 && ilim <= 0) { if (ndigits < 0 && ilim <= 0) {
S = mhi = 0; S = mhi = 0;
if (ilim < 0 || dval(d) <= 5*ds) if (ilim < 0 || dval(&d) <= 5*ds)
goto no_digits; goto no_digits;
goto one_digit; goto one_digit;
} }
for(i = 1;; i++, dval(d) *= 10.) { for(i = 1;; i++, dval(&d) *= 10.) {
L = (Long)(dval(d) / ds); L = (Long)(dval(&d) / ds);
dval(d) -= L*ds; dval(&d) -= L*ds;
#ifdef Check_FLT_ROUNDS #ifdef Check_FLT_ROUNDS
/* If FLT_ROUNDS == 2, L will usually be high by 1 */ /* If FLT_ROUNDS == 2, L will usually be high by 1 */
if (dval(d) < 0) { if (dval(&d) < 0) {
L--; L--;
dval(d) += ds; dval(&d) += ds;
} }
#endif #endif
*s++ = '0' + (int)L; *s++ = '0' + (int)L;
if (!dval(d)) { if (!dval(&d)) {
#ifdef SET_INEXACT #ifdef SET_INEXACT
inexact = 0; inexact = 0;
#endif #endif
break; break;
} }
if (i == ilim) { if (i == ilim) {
#ifdef Honor_FLT_ROUNDS #ifdef Honor_FLT_ROUNDS
if (mode > 1) if (mode > 1)
switch(rounding) { switch(Rounding) {
case 0: goto ret1; case 0: goto ret1;
case 2: goto bump_up; case 2: goto bump_up;
} }
#endif #endif
dval(d) += dval(d); dval(&d) += dval(&d);
if (dval(d) > ds || (dval(d) == ds && L & 1)) { if (dval(&d) > ds || (dval(&d) == ds && L & 1)) {
bump_up: bump_up:
while(*--s == '9') while(*--s == '9')
if (s == s0) { if (s == s0) {
k++; k++;
*s = '0'; *s = '0';
break; break;
} }
++*s++; ++*s++;
}
break;
} }
break;
} }
goto ret1;
} }
goto ret1;
}
m2 = b2; m2 = b2;
m5 = b5; m5 = b5;
@ -483,21 +468,17 @@ __dtoa
#ifndef Sudden_Underflow #ifndef Sudden_Underflow
denorm ? be + (Bias + (P-1) - 1 + 1) : denorm ? be + (Bias + (P-1) - 1 + 1) :
#endif #endif
#ifdef IBM
1 + 4*P - 3 - bbits + ((bbits + be - 1) & 3);
#else
1 + P - bbits; 1 + P - bbits;
#endif
b2 += i; b2 += i;
s2 += i; s2 += i;
mhi = i2b(1); mhi = i2b(1);
} }
if (m2 > 0 && s2 > 0) { if (m2 > 0 && s2 > 0) {
i = m2 < s2 ? m2 : s2; i = m2 < s2 ? m2 : s2;
b2 -= i; b2 -= i;
m2 -= i; m2 -= i;
s2 -= i; s2 -= i;
} }
if (b5 > 0) { if (b5 > 0) {
if (leftright) { if (leftright) {
if (m5 > 0) { if (m5 > 0) {
@ -505,13 +486,13 @@ __dtoa
b1 = mult(mhi, b); b1 = mult(mhi, b);
Bfree(b); Bfree(b);
b = b1; b = b1;
} }
if (( j = b5 - m5 )!=0) if (( j = b5 - m5 )!=0)
b = pow5mult(b, j); b = pow5mult(b, j);
} }
else else
b = pow5mult(b, b5); b = pow5mult(b, b5);
} }
S = i2b(1); S = i2b(1);
if (s5 > 0) if (s5 > 0)
S = pow5mult(S, s5); S = pow5mult(S, s5);
@ -521,20 +502,20 @@ __dtoa
spec_case = 0; spec_case = 0;
if ((mode < 2 || leftright) if ((mode < 2 || leftright)
#ifdef Honor_FLT_ROUNDS #ifdef Honor_FLT_ROUNDS
&& rounding == 1 && Rounding == 1
#endif #endif
) { ) {
if (!word1(d) && !(word0(d) & Bndry_mask) if (!word1(&d) && !(word0(&d) & Bndry_mask)
#ifndef Sudden_Underflow #ifndef Sudden_Underflow
&& word0(d) & (Exp_mask & ~Exp_msk1) && word0(&d) & (Exp_mask & ~Exp_msk1)
#endif #endif
) { ) {
/* The special case */ /* The special case */
b2 += Log2P; b2 += Log2P;
s2 += Log2P; s2 += Log2P;
spec_case = 1; spec_case = 1;
}
} }
}
/* Arrange for convenient computation of quotients: /* Arrange for convenient computation of quotients:
* shift left if necessary so divisor has 4 leading 0 bits. * shift left if necessary so divisor has 4 leading 0 bits.
@ -555,13 +536,13 @@ __dtoa
b2 += i; b2 += i;
m2 += i; m2 += i;
s2 += i; s2 += i;
} }
else if (i < 4) { else if (i < 4) {
i += 28; i += 28;
b2 += i; b2 += i;
m2 += i; m2 += i;
s2 += i; s2 += i;
} }
if (b2 > 0) if (b2 > 0)
b = lshift(b, b2); b = lshift(b, b2);
if (s2 > 0) if (s2 > 0)
@ -573,20 +554,20 @@ __dtoa
if (leftright) if (leftright)
mhi = multadd(mhi, 10, 0); mhi = multadd(mhi, 10, 0);
ilim = ilim1; ilim = ilim1;
}
} }
}
if (ilim <= 0 && (mode == 3 || mode == 5)) { if (ilim <= 0 && (mode == 3 || mode == 5)) {
if (ilim < 0 || cmp(b,S = multadd(S,5,0)) <= 0) { if (ilim < 0 || cmp(b,S = multadd(S,5,0)) <= 0) {
/* no digits, fcvt style */ /* no digits, fcvt style */
no_digits: no_digits:
k = -1 - ndigits; k = -1 - ndigits;
goto ret; goto ret;
} }
one_digit: one_digit:
*s++ = '1'; *s++ = '1';
k++; k++;
goto ret; goto ret;
} }
if (leftright) { if (leftright) {
if (m2 > 0) if (m2 > 0)
mhi = lshift(mhi, m2); mhi = lshift(mhi, m2);
@ -600,7 +581,7 @@ __dtoa
mhi = Balloc(mhi->k); mhi = Balloc(mhi->k);
Bcopy(mhi, mlo); Bcopy(mhi, mlo);
mhi = lshift(mhi, Log2P); mhi = lshift(mhi, Log2P);
} }
for(i = 1;;i++) { for(i = 1;;i++) {
dig = quorem(b,S) + '0'; dig = quorem(b,S) + '0';
@ -612,9 +593,9 @@ __dtoa
j1 = delta->sign ? 1 : cmp(b, delta); j1 = delta->sign ? 1 : cmp(b, delta);
Bfree(delta); Bfree(delta);
#ifndef ROUND_BIASED #ifndef ROUND_BIASED
if (j1 == 0 && mode != 1 && !(word1(d) & 1) if (j1 == 0 && mode != 1 && !(word1(&d) & 1)
#ifdef Honor_FLT_ROUNDS #ifdef Honor_FLT_ROUNDS
&& rounding >= 1 && Rounding >= 1
#endif #endif
) { ) {
if (dig == '9') if (dig == '9')
@ -627,11 +608,11 @@ __dtoa
#endif #endif
*s++ = dig; *s++ = dig;
goto ret; goto ret;
} }
#endif #endif
if (j < 0 || (j == 0 && mode != 1 if (j < 0 || (j == 0 && mode != 1
#ifndef ROUND_BIASED #ifndef ROUND_BIASED
&& !(word1(d) & 1) && !(word1(&d) & 1)
#endif #endif
)) { )) {
if (!b->x[0] && b->wds <= 1) { if (!b->x[0] && b->wds <= 1) {
@ -639,13 +620,13 @@ __dtoa
inexact = 0; inexact = 0;
#endif #endif
goto accept_dig; goto accept_dig;
} }
#ifdef Honor_FLT_ROUNDS #ifdef Honor_FLT_ROUNDS
if (mode > 1) if (mode > 1)
switch(rounding) { switch(Rounding) {
case 0: goto accept_dig; case 0: goto accept_dig;
case 2: goto keep_dig; case 2: goto keep_dig;
} }
#endif /*Honor_FLT_ROUNDS*/ #endif /*Honor_FLT_ROUNDS*/
if (j1 > 0) { if (j1 > 0) {
b = lshift(b, 1); b = lshift(b, 1);
@ -653,24 +634,24 @@ __dtoa
if ((j1 > 0 || (j1 == 0 && dig & 1)) if ((j1 > 0 || (j1 == 0 && dig & 1))
&& dig++ == '9') && dig++ == '9')
goto round_9_up; goto round_9_up;
} }
accept_dig: accept_dig:
*s++ = dig; *s++ = dig;
goto ret; goto ret;
} }
if (j1 > 0) { if (j1 > 0) {
#ifdef Honor_FLT_ROUNDS #ifdef Honor_FLT_ROUNDS
if (!rounding) if (!Rounding)
goto accept_dig; goto accept_dig;
#endif #endif
if (dig == '9') { /* possible if i == 1 */ if (dig == '9') { /* possible if i == 1 */
round_9_up: round_9_up:
*s++ = '9'; *s++ = '9';
goto roundoff; goto roundoff;
} }
*s++ = dig + 1; *s++ = dig + 1;
goto ret; goto ret;
} }
#ifdef Honor_FLT_ROUNDS #ifdef Honor_FLT_ROUNDS
keep_dig: keep_dig:
#endif #endif
@ -683,9 +664,9 @@ __dtoa
else { else {
mlo = multadd(mlo, 10, 0); mlo = multadd(mlo, 10, 0);
mhi = multadd(mhi, 10, 0); mhi = multadd(mhi, 10, 0);
}
} }
} }
}
else else
for(i = 1;; i++) { for(i = 1;; i++) {
*s++ = dig = quorem(b,S) + '0'; *s++ = dig = quorem(b,S) + '0';
@ -694,19 +675,19 @@ __dtoa
inexact = 0; inexact = 0;
#endif #endif
goto ret; goto ret;
} }
if (i >= ilim) if (i >= ilim)
break; break;
b = multadd(b, 10, 0); b = multadd(b, 10, 0);
} }
/* Round off last digit */ /* Round off last digit */
#ifdef Honor_FLT_ROUNDS #ifdef Honor_FLT_ROUNDS
switch(rounding) { switch(Rounding) {
case 0: goto trimzeros; case 0: goto trimzeros;
case 2: goto roundoff; case 2: goto roundoff;
} }
#endif #endif
b = lshift(b, 1); b = lshift(b, 1);
j = cmp(b, S); j = cmp(b, S);
@ -717,30 +698,32 @@ __dtoa
k++; k++;
*s++ = '1'; *s++ = '1';
goto ret; goto ret;
} }
++*s++; ++*s++;
} }
else { else {
// trimzeros: #ifdef Honor_FLT_ROUNDS
trimzeros:
#endif
while(*--s == '0'); while(*--s == '0');
s++; s++;
} }
ret: ret:
Bfree(S); Bfree(S);
if (mhi) { if (mhi) {
if (mlo && mlo != mhi) if (mlo && mlo != mhi)
Bfree(mlo); Bfree(mlo);
Bfree(mhi); Bfree(mhi);
} }
ret1: ret1:
#ifdef SET_INEXACT #ifdef SET_INEXACT
if (inexact) { if (inexact) {
if (!oldinexact) { if (!oldinexact) {
word0(d) = Exp_1 + (70 << Exp_shift); word0(&d) = Exp_1 + (70 << Exp_shift);
word1(d) = 0; word1(&d) = 0;
dval(d) += 1.; dval(&d) += 1.;
}
} }
}
else if (!oldinexact) else if (!oldinexact)
clear_inexact(); clear_inexact();
#endif #endif
@ -750,4 +733,4 @@ __dtoa
if (rve) if (rve)
*rve = s; *rve = s;
return s0; return s0;
} }

View File

@ -35,65 +35,108 @@ THIS SOFTWARE.
#include "locale.h" #include "locale.h"
#endif #endif
char * char *__g__fmt (char *b, char *s, char *se, int decpt, ULong sign, size_t blen)
#ifdef KR_headers
__g__fmt(b, s, se, decpt, sign) char *b; char *s; char *se; int decpt; ULong sign;
#else
__g__fmt(char *b, char *s, char *se, int decpt, ULong sign)
#endif
{ {
int i, j, k; int i, j, k;
char *s0 = s; char *be, *s0;
size_t len;
#ifdef USE_LOCALE #ifdef USE_LOCALE
char decimalpoint = *localeconv()->decimal_point; #ifdef NO_LOCALE_CACHE
char *decimalpoint = localeconv()->decimal_point;
size_t dlen = strlen(decimalpoint);
#else #else
#define decimalpoint '.' char *decimalpoint;
static char *decimalpoint_cache;
static size_t dlen;
if (!(s0 = decimalpoint_cache)) {
s0 = localeconv()->decimal_point;
dlen = strlen(s0);
if ((decimalpoint_cache = (char*)MALLOC(strlen(s0) + 1))) {
strcpy(decimalpoint_cache, s0);
s0 = decimalpoint_cache;
}
}
decimalpoint = s0;
#endif #endif
#else
#define dlen 0
#endif
s0 = s;
len = (se-s) + dlen + 6; /* 6 = sign + e+dd + trailing null */
if (blen < len)
goto ret0;
be = b + blen - 1;
if (sign) if (sign)
*b++ = '-'; *b++ = '-';
if (decpt <= -4 || decpt > se - s + 5) { if (decpt <= -4 || decpt > se - s + 5) {
*b++ = *s++; *b++ = *s++;
if (*s) { if (*s) {
*b++ = decimalpoint; #ifdef USE_LOCALE
while((*b = *decimalpoint++))
++b;
#else
*b++ = '.';
#endif
while((*b = *s++) !=0) while((*b = *s++) !=0)
b++; b++;
} }
*b++ = 'e'; *b++ = 'e';
/* sprintf(b, "%+.2d", decpt - 1); */ /* sprintf(b, "%+.2d", decpt - 1); */
if (--decpt < 0) { if (--decpt < 0) {
*b++ = '-'; *b++ = '-';
decpt = -decpt; decpt = -decpt;
} }
else else
*b++ = '+'; *b++ = '+';
for(j = 2, k = 10; 10*k <= decpt; j++, k *= 10){} for(j = 2, k = 10; 10*k <= decpt; j++, k *= 10){}
for(;;) { for(;;) {
i = decpt / k; i = decpt / k;
if (b >= be)
goto ret0;
*b++ = i + '0'; *b++ = i + '0';
if (--j <= 0) if (--j <= 0)
break; break;
decpt -= i*k; decpt -= i*k;
decpt *= 10; decpt *= 10;
}
*b = 0;
} }
*b = 0;
}
else if (decpt <= 0) { else if (decpt <= 0) {
*b++ = decimalpoint; #ifdef USE_LOCALE
while((*b = *decimalpoint++))
++b;
#else
*b++ = '.';
#endif
if (be < b - decpt + (se - s))
goto ret0;
for(; decpt < 0; decpt++) for(; decpt < 0; decpt++)
*b++ = '0'; *b++ = '0';
while((*b = *s++) !=0) while((*b = *s++) != 0)
b++; b++;
} }
else { else {
while((*b = *s++) !=0) { while((*b = *s++) != 0) {
b++; b++;
if (--decpt == 0 && *s) if (--decpt == 0 && *s) {
*b++ = decimalpoint; #ifdef USE_LOCALE
while((*b = *decimalpoint++))
++b;
#else
*b++ = '.';
#endif
} }
}
if (b + decpt > be) {
ret0:
b = 0;
goto ret;
}
for(; decpt > 0; decpt--) for(; decpt > 0; decpt--)
*b++ = '0'; *b++ = '0';
*b = 0; *b = 0;
} }
ret:
__freedtoa(s0); __freedtoa(s0);
return b; return b;
} }

View File

@ -31,17 +31,17 @@ THIS SOFTWARE.
#include "gdtoaimp.h" #include "gdtoaimp.h"
char* char *__g_dfmt (char *buf, double *d, int ndig, size_t bufsize)
#ifdef KR_headers
__g_dfmt(buf, d, ndig, bufsize) char *buf; double *d; int ndig; unsigned bufsize;
#else
__g_dfmt(char *buf, double *d, int ndig, unsigned bufsize)
#endif
{ {
static FPI fpi = { 53, 1-1023-53+1, 2046-1023-53+1, 1, 0 }; static FPI fpi0 = { 53, 1-1023-53+1, 2046-1023-53+1, 1, 0 };
char *b, *s, *se; char *b, *s, *se;
ULong bits[2], *L, sign; ULong bits[2], *L, sign;
int decpt, ex, i, mode; int decpt, ex, i, mode;
#ifdef Honor_FLT_ROUNDS
#include "gdtoa_fltrnds.h"
#else
#define fpi &fpi0
#endif
if (ndig < 0) if (ndig < 0)
ndig = 0; ndig = 0;
@ -52,14 +52,16 @@ __g_dfmt(char *buf, double *d, int ndig, unsigned bufsize)
sign = L[_0] & 0x80000000L; sign = L[_0] & 0x80000000L;
if ((L[_0] & 0x7ff00000) == 0x7ff00000) { if ((L[_0] & 0x7ff00000) == 0x7ff00000) {
/* Infinity or NaN */ /* Infinity or NaN */
if (bufsize < 10)
return 0;
if (L[_0] & 0xfffff || L[_1]) { if (L[_0] & 0xfffff || L[_1]) {
return strcp(buf, "NaN"); return strcp(buf, "NaN");
} }
b = buf; b = buf;
if (sign) if (sign)
*b++ = '-'; *b++ = '-';
return strcp(b, "Infinity"); return strcp(b, "Infinity");
} }
if (L[_1] == 0 && (L[_0] ^ sign) == 0 /*d == 0.*/) { if (L[_1] == 0 && (L[_0] ^ sign) == 0 /*d == 0.*/) {
b = buf; b = buf;
#ifndef IGNORE_ZERO_SIGN #ifndef IGNORE_ZERO_SIGN
@ -69,7 +71,7 @@ __g_dfmt(char *buf, double *d, int ndig, unsigned bufsize)
*b++ = '0'; *b++ = '0';
*b = 0; *b = 0;
return b; return b;
} }
bits[0] = L[_1]; bits[0] = L[_1];
bits[1] = L[_0] & 0xfffff; bits[1] = L[_0] & 0xfffff;
if ( (ex = (L[_0] >> 20) & 0x7ff) !=0) if ( (ex = (L[_0] >> 20) & 0x7ff) !=0)
@ -78,12 +80,9 @@ __g_dfmt(char *buf, double *d, int ndig, unsigned bufsize)
ex = 1; ex = 1;
ex -= 0x3ff + 52; ex -= 0x3ff + 52;
mode = 2; mode = 2;
if (ndig <= 0) { if (ndig <= 0)
if (bufsize < 25)
return 0;
mode = 0; mode = 0;
}
i = STRTOG_Normal; i = STRTOG_Normal;
s = __gdtoa(&fpi, ex, bits, &i, mode, ndig, &decpt, &se); s = __gdtoa(fpi, ex, bits, &i, mode, ndig, &decpt, &se);
return __g__fmt(buf, s, se, decpt, sign); return __g__fmt(buf, s, se, decpt, sign, bufsize);
} }

View File

@ -31,17 +31,17 @@ THIS SOFTWARE.
#include "gdtoaimp.h" #include "gdtoaimp.h"
char* char *__g_ffmt (char *buf, float *f, int ndig, size_t bufsize)
#ifdef KR_headers
__g_ffmt(buf, f, ndig, bufsize) char *buf; float *f; int ndig; unsigned bufsize;
#else
__g_ffmt(char *buf, float *f, int ndig, unsigned bufsize)
#endif
{ {
static FPI fpi = { 24, 1-127-24+1, 254-127-24+1, 1, 0 }; static FPI fpi0 = { 24, 1-127-24+1, 254-127-24+1, 1, 0 };
char *b, *s, *se; char *b, *s, *se;
ULong bits[1], *L, sign; ULong bits[1], *L, sign;
int decpt, ex, i, mode; int decpt, ex, i, mode;
#ifdef Honor_FLT_ROUNDS
#include "gdtoa_fltrnds.h"
#else
#define fpi &fpi0
#endif
if (ndig < 0) if (ndig < 0)
ndig = 0; ndig = 0;
@ -54,12 +54,12 @@ __g_ffmt(char *buf, float *f, int ndig, unsigned bufsize)
/* Infinity or NaN */ /* Infinity or NaN */
if (L[0] & 0x7fffff) { if (L[0] & 0x7fffff) {
return strcp(buf, "NaN"); return strcp(buf, "NaN");
} }
b = buf; b = buf;
if (sign) if (sign)
*b++ = '-'; *b++ = '-';
return strcp(b, "Infinity"); return strcp(b, "Infinity");
} }
if (*f == 0.) { if (*f == 0.) {
b = buf; b = buf;
#ifndef IGNORE_ZERO_SIGN #ifndef IGNORE_ZERO_SIGN
@ -69,7 +69,7 @@ __g_ffmt(char *buf, float *f, int ndig, unsigned bufsize)
*b++ = '0'; *b++ = '0';
*b = 0; *b = 0;
return b; return b;
} }
bits[0] = L[0] & 0x7fffff; bits[0] = L[0] & 0x7fffff;
if ( (ex = (L[0] >> 23) & 0xff) !=0) if ( (ex = (L[0] >> 23) & 0xff) !=0)
bits[0] |= 0x800000; bits[0] |= 0x800000;
@ -81,8 +81,8 @@ __g_ffmt(char *buf, float *f, int ndig, unsigned bufsize)
if (bufsize < 16) if (bufsize < 16)
return 0; return 0;
mode = 0; mode = 0;
}
i = STRTOG_Normal;
s = __gdtoa(&fpi, ex, bits, &i, mode, ndig, &decpt, &se);
return __g__fmt(buf, s, se, decpt, sign);
} }
i = STRTOG_Normal;
s = __gdtoa(fpi, ex, bits, &i, mode, ndig, &decpt, &se);
return __g__fmt(buf, s, se, decpt, sign, bufsize);
}

View File

@ -51,21 +51,22 @@ THIS SOFTWARE.
#define _4 0 #define _4 0
#endif #endif
char* char *__g_xfmt (char *buf, void *V, int ndig, size_t bufsize)
#ifdef KR_headers
__g_xfmt(buf, V, ndig, bufsize) char *buf; char *V; int ndig; unsigned bufsize;
#else
__g_xfmt(char *buf, void *V, int ndig, unsigned bufsize)
#endif
{ {
static FPI fpi = { 64, 1-16383-64+1, 32766 - 16383 - 64 + 1, 1, 0 }; static FPI fpi0 = { 64, 1-16383-64+1, 32766 - 16383 - 64 + 1, 1, 0 };
char *b, *s, *se; char *b, *s, *se;
ULong bits[2], sign; ULong bits[2], sign;
UShort *L; UShort *L;
int decpt, ex, i, mode; int decpt, ex, i, mode;
#if defined(__MINGW32__) || defined(__MINGW64__)
int fptype = __fpclassifyl (*(long double*) V); int fptype = __fpclassifyl (*(long double*) V);
#endif /* MinGW */
#ifdef Honor_FLT_ROUNDS
#include "gdtoa_fltrnds.h"
#else
#define fpi &fpi0
#endif
if (ndig < 0) if (ndig < 0)
ndig = 0; ndig = 0;
if (bufsize < ndig + 10) if (bufsize < ndig + 10)
@ -73,36 +74,54 @@ __g_xfmt(char *buf, void *V, int ndig, unsigned bufsize)
L = (UShort *)V; L = (UShort *)V;
sign = L[_0] & 0x8000; sign = L[_0] & 0x8000;
ex = L[_0] & 0x7fff; ex = L[_0] & 0x7fff;
bits[1] = (L[_1] << 16) | L[_2]; bits[1] = (L[_1] << 16) | L[_2];
bits[0] = (L[_3] << 16) | L[_4]; bits[0] = (L[_3] << 16) | L[_4];
if (fptype & FP_NAN) /* NaN or Inf */ #if defined(__MINGW32__) || defined(__MINGW64__)
{ if (fptype & FP_NAN) {
if (fptype & FP_NORMAL) /* NaN or Inf */
{ if (fptype & FP_NORMAL) {
b = buf; b = buf;
*b++ = sign ? '-': '+'; *b++ = sign ? '-': '+';
strncpy (b, "Infinity", ndig ? ndig : 8); strncpy (b, "Infinity", ndig ? ndig : 8);
return (buf + strlen (buf));
}
strncpy (buf, "NaN", ndig ? ndig : 3);
return (buf + strlen (buf)); return (buf + strlen (buf));
} }
strncpy (buf, "NaN", ndig ? ndig : 3); else if (fptype & FP_NORMAL) {
return (buf + strlen (buf)); /* Normal or subnormal */
} if (fptype & FP_ZERO) {
i = STRTOG_Denormal;
else if (fptype & FP_NORMAL) /* Normal or subnormal */ ex = 1;
{ }
if (fptype & FP_ZERO) else
{ i = STRTOG_Normal;
}
#else
if (ex != 0) {
if (ex == 0x7fff) {
/* Infinity or NaN */
if (bits[0] | bits[1])
b = strcp(buf, "NaN");
else {
b = buf;
if (sign)
*b++ = '-';
b = strcp(b, "Infinity");
}
return b;
}
i = STRTOG_Normal;
}
else if (bits[0] | bits[1]) {
i = STRTOG_Denormal; i = STRTOG_Denormal;
ex = 1; ex = 1;
} }
else #endif
i = STRTOG_Normal;
}
else { else {
i = STRTOG_Zero; /* i = STRTOG_Zero; */
b = buf; b = buf;
#ifndef IGNORE_ZERO_SIGN #ifndef IGNORE_ZERO_SIGN
if (sign) if (sign)
@ -111,15 +130,14 @@ __g_xfmt(char *buf, void *V, int ndig, unsigned bufsize)
*b++ = '0'; *b++ = '0';
*b = 0; *b = 0;
return b; return b;
} }
ex -= 0x3fff + 63; ex -= 0x3fff + 63;
mode = 2; mode = 2;
if (ndig <= 0) { if (ndig <= 0) {
if (bufsize < 32) if (bufsize < 32)
return 0; return 0;
mode = 0; mode = 0;
}
s = __gdtoa(&fpi, ex, bits, &i, mode, ndig, &decpt, &se);
return __g__fmt(buf, s, se, decpt, sign);
} }
s = __gdtoa(fpi, ex, bits, &i, mode, ndig, &decpt, &se);
return __g__fmt(buf, s, se, decpt, sign, bufsize);
}

View File

@ -1,3 +1,6 @@
#define IEEE_8087 #define IEEE_8087
#define Arith_Kind_ASL 1 #define Arith_Kind_ASL 1
#define Double_Align #define Double_Align
#ifdef _WIN64
#define X64_bit_pointers
#endif /* w64 */

View File

@ -1,12 +1,12 @@
#define f_QNAN 0xffc00000 #define f_QNAN 0xffc00000
#define d_QNAN0 0x0 #define d_QNAN0 0x0
#define d_QNAN1 0xfff80000 #define d_QNAN1 0xfff80000
#define ld_QNAN0 0x0 #define ld_QNAN0 0x0
#define ld_QNAN1 0xc0000000 #define ld_QNAN1 0xc0000000
#define ld_QNAN2 0xffff #define ld_QNAN2 0xffff
#define ld_QNAN3 0x0 #define ld_QNAN3 0x0
#define ldus_QNAN0 0x0 #define ldus_QNAN0 0x0
#define ldus_QNAN1 0x0 #define ldus_QNAN1 0x0
#define ldus_QNAN2 0x0 #define ldus_QNAN2 0x0
#define ldus_QNAN3 0xc000 #define ldus_QNAN3 0xc000
#define ldus_QNAN4 0xffff #define ldus_QNAN4 0xffff

View File

@ -31,12 +31,7 @@ THIS SOFTWARE.
#include "gdtoaimp.h" #include "gdtoaimp.h"
static Bigint * static Bigint *bitstob (ULong *bits, int nbits, int *bbits)
#ifdef KR_headers
bitstob(bits, nbits, bbits) ULong *bits; int nbits; int *bbits;
#else
bitstob(ULong *bits, int nbits, int *bbits)
#endif
{ {
int i, k; int i, k;
Bigint *b; Bigint *b;
@ -47,7 +42,7 @@ bitstob(ULong *bits, int nbits, int *bbits)
while(i < nbits) { while(i < nbits) {
i <<= 1; i <<= 1;
k++; k++;
} }
#ifndef Pack_32 #ifndef Pack_32
if (!k) if (!k)
k = 1; k = 1;
@ -60,19 +55,19 @@ bitstob(ULong *bits, int nbits, int *bbits)
#ifdef Pack_16 #ifdef Pack_16
*x++ = (*bits >> 16) & ALL_ON; *x++ = (*bits >> 16) & ALL_ON;
#endif #endif
} while(++bits <= be); } while(++bits <= be);
i = x - x0; i = x - x0;
while(!x0[--i]) while(!x0[--i])
if (!i) { if (!i) {
b->wds = 0; b->wds = 0;
*bbits = 0; *bbits = 0;
goto ret; goto ret;
} }
b->wds = i + 1; b->wds = i + 1;
*bbits = i*ULbits + 32 - hi0bits(b->x[i]); *bbits = i*ULbits + 32 - hi0bits(b->x[i]);
ret: ret:
return b; return b;
} }
/* dtoa for IEEE arithmetic (dmg): convert double to ASCII string. /* dtoa for IEEE arithmetic (dmg): convert double to ASCII string.
* *
@ -108,15 +103,8 @@ bitstob(ULong *bits, int nbits, int *bbits)
* calculation. * calculation.
*/ */
char * char *__gdtoa (FPI *fpi, int be, ULong *bits, int *kindp, int mode, int ndigits,
__gdtoa int *decpt, char **rve)
#ifdef KR_headers
(fpi, be, bits, kindp, mode, ndigits, decpt, rve)
FPI *fpi; int be; ULong *bits;
int *kindp, mode, ndigits, *decpt; char **rve;
#else
(FPI *fpi, int be, ULong *bits, int *kindp, int mode, int ndigits, int *decpt, char **rve)
#endif
{ {
/* Arguments ndigits and decpt are similar to the second and third /* Arguments ndigits and decpt are similar to the second and third
arguments of ecvt and fcvt; trailing zeros are suppressed from arguments of ecvt and fcvt; trailing zeros are suppressed from
@ -152,19 +140,20 @@ __gdtoa
to hold the suppressed trailing zeros. to hold the suppressed trailing zeros.
*/ */
int bbits, b2, b5, be0, dig, i, ieps, ilim = 0, ilim0, ilim1 = 0, inex; int bbits, b2, b5, be0, dig, i, ieps, ilim, ilim0, ilim1, inex;
int j, j1, k, k0, k_check, kind, leftright, m2, m5, nbits; int j, j1, k, k0, k_check, kind, leftright, m2, m5, nbits;
int rdir, s2, s5, spec_case, try_quick; int rdir, s2, s5, spec_case, try_quick;
Long L; Long L;
Bigint *b, *b1, *delta, *mlo, *mhi, *mhi1, *S; Bigint *b, *b1, *delta, *mlo, *mhi, *mhi1, *S;
double d, d2, ds, eps; double d2, ds;
char *s, *s0; char *s, *s0;
union _dbl_union d, eps;
#ifndef MULTIPLE_THREADS #ifndef MULTIPLE_THREADS
if (dtoa_result) { if (dtoa_result) {
__freedtoa(dtoa_result); __freedtoa(dtoa_result);
dtoa_result = 0; dtoa_result = 0;
} }
#endif #endif
inex = 0; inex = 0;
kind = *kindp &= ~STRTOG_Inexact; kind = *kindp &= ~STRTOG_Inexact;
@ -182,36 +171,32 @@ __gdtoa
return nrv_alloc("NaN", rve, 3); return nrv_alloc("NaN", rve, 3);
default: default:
return 0; return 0;
} }
b = bitstob(bits, nbits = fpi->nbits, &bbits); b = bitstob(bits, nbits = fpi->nbits, &bbits);
be0 = be; be0 = be;
if ( (i = trailz(b)) !=0) { if ( (i = trailz(b)) !=0) {
rshift(b, i); rshift(b, i);
be += i; be += i;
bbits -= i; bbits -= i;
} }
if (!b->wds) { if (!b->wds) {
Bfree(b); Bfree(b);
ret_zero: ret_zero:
*decpt = 1; *decpt = 1;
return nrv_alloc("0", rve, 1); return nrv_alloc("0", rve, 1);
} }
dval(d) = b2d(b, &i); dval(&d) = b2d(b, &i);
i = be + bbits - 1; i = be + bbits - 1;
word0(d) &= Frac_mask1; word0(&d) &= Frac_mask1;
word0(d) |= Exp_11; word0(&d) |= Exp_11;
#ifdef IBM
if ( (j = 11 - hi0bits(word0(d) & Frac_mask)) !=0)
dval(d) /= 1 << j;
#endif
/* log(x) ~=~ log(1.5) + (x-1.5)/1.5 /* log(x) ~=~ log(1.5) + (x-1.5)/1.5
* log10(x) = log(x) / log(10) * log10(x) = log(x) / log(10)
* ~=~ log(1.5)/log(10) + (x-1.5)/(1.5*log(10)) * ~=~ log(1.5)/log(10) + (x-1.5)/(1.5*log(10))
* log10(d) = (i-Bias)*log(2)/log(10) + log10(d2) * log10(&d) = (i-Bias)*log(2)/log(10) + log10(d2)
* *
* This suggests computing an approximation k to log10(d) by * This suggests computing an approximation k to log10(&d) by
* *
* k = (i - Bias)*0.301029995663981 * k = (i - Bias)*0.301029995663981
* + ( (d2-1.5)*0.289529654602168 + 0.176091259055681 ); * + ( (d2-1.5)*0.289529654602168 + 0.176091259055681 );
@ -227,11 +212,7 @@ __gdtoa
* (We could get a more accurate k by invoking log10, * (We could get a more accurate k by invoking log10,
* but this is probably not worthwhile.) * but this is probably not worthwhile.)
*/ */
#ifdef IBM ds = (dval(&d)-1.5)*0.289529654602168 + 0.1760912590558 + i*0.301029995663981;
i <<= 2;
i += j;
#endif
ds = (dval(d)-1.5)*0.289529654602168 + 0.1760912590558 + i*0.301029995663981;
/* correct assumption about exponent range */ /* correct assumption about exponent range */
if ((j = i) < 0) if ((j = i) < 0)
@ -243,50 +224,44 @@ __gdtoa
if (ds < 0. && ds != k) if (ds < 0. && ds != k)
k--; /* want k = floor(ds) */ k--; /* want k = floor(ds) */
k_check = 1; k_check = 1;
#ifdef IBM word0(&d) += (be + bbits - 1) << Exp_shift;
j = be + bbits - 1;
if ( (j1 = j & 3) !=0)
dval(d) *= 1 << j1;
word0(d) += j << Exp_shift - 2 & Exp_mask;
#else
word0(d) += (be + bbits - 1) << Exp_shift;
#endif
if (k >= 0 && k <= Ten_pmax) { if (k >= 0 && k <= Ten_pmax) {
if (dval(d) < tens[k]) if (dval(&d) < tens[k])
k--; k--;
k_check = 0; k_check = 0;
} }
j = bbits - i - 1; j = bbits - i - 1;
if (j >= 0) { if (j >= 0) {
b2 = 0; b2 = 0;
s2 = j; s2 = j;
} }
else { else {
b2 = -j; b2 = -j;
s2 = 0; s2 = 0;
} }
if (k >= 0) { if (k >= 0) {
b5 = 0; b5 = 0;
s5 = k; s5 = k;
s2 += k; s2 += k;
} }
else { else {
b2 -= k; b2 -= k;
b5 = -k; b5 = -k;
s5 = 0; s5 = 0;
} }
if (mode < 0 || mode > 9) if (mode < 0 || mode > 9)
mode = 0; mode = 0;
try_quick = 1; try_quick = 1;
if (mode > 5) { if (mode > 5) {
mode -= 4; mode -= 4;
try_quick = 0; try_quick = 0;
} }
leftright = 1; leftright = 1;
ilim = ilim1 = -1; /* Values for cases 0 and 1; done here to */
/* silence erroneous "gcc -Wall" warning. */
switch(mode) { switch(mode) {
case 0: case 0:
case 1: case 1:
ilim = ilim1 = -1;
i = (int)(nbits * .30103) + 3; i = (int)(nbits * .30103) + 3;
ndigits = 0; ndigits = 0;
break; break;
@ -307,7 +282,7 @@ __gdtoa
ilim1 = i - 1; ilim1 = i - 1;
if (i <= 0) if (i <= 0)
i = 1; i = 1;
} }
s = s0 = rv_alloc(i); s = s0 = rv_alloc(i);
if ( (rdir = fpi->rounding - 1) !=0) { if ( (rdir = fpi->rounding - 1) !=0) {
@ -315,7 +290,7 @@ __gdtoa
rdir = 2; rdir = 2;
if (kind & STRTOG_Neg) if (kind & STRTOG_Neg)
rdir = 3 - rdir; rdir = 3 - rdir;
} }
/* Now rdir = 0 ==> round near, 1 ==> round up, 2 ==> round down. */ /* Now rdir = 0 ==> round near, 1 ==> round up, 2 ==> round down. */
@ -328,11 +303,7 @@ __gdtoa
/* Try to get by with floating-point arithmetic. */ /* Try to get by with floating-point arithmetic. */
i = 0; i = 0;
d2 = dval(d); d2 = dval(&d);
#ifdef IBM
if ( (j = 11 - hi0bits(word0(d) & Frac_mask)) !=0)
dval(d) /= 1 << j;
#endif
k0 = k; k0 = k;
ilim0 = ilim; ilim0 = ilim;
ieps = 2; /* conservative */ ieps = 2; /* conservative */
@ -342,99 +313,97 @@ __gdtoa
if (j & Bletch) { if (j & Bletch) {
/* prevent overflows */ /* prevent overflows */
j &= Bletch - 1; j &= Bletch - 1;
dval(d) /= bigtens[n_bigtens-1]; dval(&d) /= bigtens[n_bigtens-1];
ieps++; ieps++;
} }
for(; j; j >>= 1, i++) for(; j; j >>= 1, i++)
if (j & 1) { if (j & 1) {
ieps++; ieps++;
ds *= bigtens[i]; ds *= bigtens[i];
} }
} }
else { else {
ds = 1.; ds = 1.;
if ( (j1 = -k) !=0) { if ( (j1 = -k) !=0) {
dval(d) *= tens[j1 & 0xf]; dval(&d) *= tens[j1 & 0xf];
for(j = j1 >> 4; j; j >>= 1, i++) for(j = j1 >> 4; j; j >>= 1, i++)
if (j & 1) { if (j & 1) {
ieps++; ieps++;
dval(d) *= bigtens[i]; dval(&d) *= bigtens[i];
} }
}
} }
if (k_check && dval(d) < 1. && ilim > 0) { }
if (k_check && dval(&d) < 1. && ilim > 0) {
if (ilim1 <= 0) if (ilim1 <= 0)
goto fast_failed; goto fast_failed;
ilim = ilim1; ilim = ilim1;
k--; k--;
dval(d) *= 10.; dval(&d) *= 10.;
ieps++; ieps++;
} }
dval(eps) = ieps*dval(d) + 7.; dval(&eps) = ieps*dval(&d) + 7.;
word0(eps) -= (P-1)*Exp_msk1; word0(&eps) -= (P-1)*Exp_msk1;
if (ilim == 0) { if (ilim == 0) {
S = mhi = 0; S = mhi = 0;
dval(d) -= 5.; dval(&d) -= 5.;
if (dval(d) > dval(eps)) if (dval(&d) > dval(&eps))
goto one_digit; goto one_digit;
if (dval(d) < -dval(eps)) if (dval(&d) < -dval(&eps))
goto no_digits; goto no_digits;
goto fast_failed; goto fast_failed;
} }
#ifndef No_leftright #ifndef No_leftright
if (leftright) { if (leftright) {
/* Use Steele & White method of only /* Use Steele & White method of only
* generating digits needed. * generating digits needed.
*/ */
dval(eps) = ds*0.5/tens[ilim-1] - dval(eps); dval(&eps) = ds*0.5/tens[ilim-1] - dval(&eps);
for(i = 0;;) { for(i = 0;;) {
L = (Long)(dval(d)/ds); L = (Long)(dval(&d)/ds);
dval(d) -= L*ds; dval(&d) -= L*ds;
*s++ = '0' + (int)L; *s++ = '0' + (int)L;
if (dval(d) < dval(eps)) { if (dval(&d) < dval(&eps)) {
if (dval(d)) if (dval(&d))
inex = STRTOG_Inexlo; inex = STRTOG_Inexlo;
goto ret1; goto ret1;
} }
if (ds - dval(d) < dval(eps)) if (ds - dval(&d) < dval(&eps))
goto bump_up; goto bump_up;
if (++i >= ilim) if (++i >= ilim)
break; break;
dval(eps) *= 10.; dval(&eps) *= 10.;
dval(d) *= 10.; dval(&d) *= 10.;
}
} }
}
else { else {
#endif #endif
/* Generate ilim digits, then fix them up. */ /* Generate ilim digits, then fix them up. */
dval(eps) *= tens[ilim-1]; dval(&eps) *= tens[ilim-1];
for(i = 1;; i++, dval(d) *= 10.) { for(i = 1;; i++, dval(&d) *= 10.) {
if ( (L = (Long)(dval(d)/ds)) !=0) if ( (L = (Long)(dval(&d)/ds)) !=0)
dval(d) -= L*ds; dval(&d) -= L*ds;
*s++ = '0' + (int)L; *s++ = '0' + (int)L;
if (i == ilim) { if (i == ilim) {
ds *= 0.5; ds *= 0.5;
if (dval(d) > ds + dval(eps)) if (dval(&d) > ds + dval(&eps))
goto bump_up; goto bump_up;
else if (dval(d) < ds - dval(eps)) { else if (dval(&d) < ds - dval(&eps)) {
while(*--s == '0'){} if (dval(&d))
s++;
if (dval(d))
inex = STRTOG_Inexlo; inex = STRTOG_Inexlo;
goto ret1; goto clear_trailing0;
}
break;
} }
break;
} }
#ifndef No_leftright
} }
#ifndef No_leftright
}
#endif #endif
fast_failed: fast_failed:
s = s0; s = s0;
dval(d) = d2; dval(&d) = d2;
k = k0; k = k0;
ilim = ilim0; ilim = ilim0;
} }
/* Do we have a "small" integer? */ /* Do we have a "small" integer? */
@ -443,22 +412,22 @@ __gdtoa
ds = tens[k]; ds = tens[k];
if (ndigits < 0 && ilim <= 0) { if (ndigits < 0 && ilim <= 0) {
S = mhi = 0; S = mhi = 0;
if (ilim < 0 || dval(d) <= 5*ds) if (ilim < 0 || dval(&d) <= 5*ds)
goto no_digits; goto no_digits;
goto one_digit; goto one_digit;
} }
for(i = 1;; i++, dval(d) *= 10.) { for(i = 1;; i++, dval(&d) *= 10.) {
L = dval(d) / ds; L = dval(&d) / ds;
dval(d) -= L*ds; dval(&d) -= L*ds;
#ifdef Check_FLT_ROUNDS #ifdef Check_FLT_ROUNDS
/* If FLT_ROUNDS == 2, L will usually be high by 1 */ /* If FLT_ROUNDS == 2, L will usually be high by 1 */
if (dval(d) < 0) { if (dval(&d) < 0) {
L--; L--;
dval(d) += ds; dval(&d) += ds;
} }
#endif #endif
*s++ = '0' + (int)L; *s++ = '0' + (int)L;
if (dval(d) == 0.) if (dval(&d) == 0.)
break; break;
if (i == ilim) { if (i == ilim) {
if (rdir) { if (rdir) {
@ -466,9 +435,9 @@ __gdtoa
goto bump_up; goto bump_up;
inex = STRTOG_Inexlo; inex = STRTOG_Inexlo;
goto ret1; goto ret1;
} }
dval(d) += dval(d); dval(&d) += dval(&d);
if (dval(d) > ds || (dval(d) == ds && L & 1)) { if (dval(&d) > ds || (dval(&d) == ds && L & 1)) {
bump_up: bump_up:
inex = STRTOG_Inexhi; inex = STRTOG_Inexhi;
while(*--s == '9') while(*--s == '9')
@ -476,16 +445,20 @@ __gdtoa
k++; k++;
*s = '0'; *s = '0';
break; break;
} }
++*s++; ++*s++;
}
else
inex = STRTOG_Inexlo;
break;
} }
else {
inex = STRTOG_Inexlo;
clear_trailing0:
while(*--s == '0'){}
++s;
}
break;
} }
goto ret1;
} }
goto ret1;
}
m2 = b2; m2 = b2;
m5 = b5; m5 = b5;
@ -496,7 +469,7 @@ __gdtoa
if (be - i++ < fpi->emin) if (be - i++ < fpi->emin)
/* denormal */ /* denormal */
i = be - fpi->emin + 1; i = be - fpi->emin + 1;
} }
else { else {
j = ilim - 1; j = ilim - 1;
if (m5 >= j) if (m5 >= j)
@ -505,22 +478,22 @@ __gdtoa
s5 += j -= m5; s5 += j -= m5;
b5 += j; b5 += j;
m5 = 0; m5 = 0;
} }
if ((i = ilim) < 0) { if ((i = ilim) < 0) {
m2 -= i; m2 -= i;
i = 0; i = 0;
}
} }
}
b2 += i; b2 += i;
s2 += i; s2 += i;
mhi = i2b(1); mhi = i2b(1);
} }
if (m2 > 0 && s2 > 0) { if (m2 > 0 && s2 > 0) {
i = m2 < s2 ? m2 : s2; i = m2 < s2 ? m2 : s2;
b2 -= i; b2 -= i;
m2 -= i; m2 -= i;
s2 -= i; s2 -= i;
} }
if (b5 > 0) { if (b5 > 0) {
if (leftright) { if (leftright) {
if (m5 > 0) { if (m5 > 0) {
@ -528,13 +501,13 @@ __gdtoa
b1 = mult(mhi, b); b1 = mult(mhi, b);
Bfree(b); Bfree(b);
b = b1; b = b1;
} }
if ( (j = b5 - m5) !=0) if ( (j = b5 - m5) !=0)
b = pow5mult(b, j); b = pow5mult(b, j);
} }
else else
b = pow5mult(b, b5); b = pow5mult(b, b5);
} }
S = i2b(1); S = i2b(1);
if (s5 > 0) if (s5 > 0)
S = pow5mult(S, s5); S = pow5mult(S, s5);
@ -548,8 +521,8 @@ __gdtoa
b2++; b2++;
s2++; s2++;
spec_case = 1; spec_case = 1;
}
} }
}
/* Arrange for convenient computation of quotients: /* Arrange for convenient computation of quotients:
* shift left if necessary so divisor has 4 leading 0 bits. * shift left if necessary so divisor has 4 leading 0 bits.
@ -558,28 +531,11 @@ __gdtoa
* and for all and pass them and a shift to quorem, so it * and for all and pass them and a shift to quorem, so it
* can do shifts and ors to compute the numerator for q. * can do shifts and ors to compute the numerator for q.
*/ */
#ifdef Pack_32 i = ((s5 ? hi0bits(S->x[S->wds-1]) : ULbits - 1) - s2 - 4) & kmask;
if ( (i = ((s5 ? 32 - hi0bits(S->x[S->wds-1]) : 1) + s2) & 0x1f) !=0) m2 += i;
i = 32 - i; if ((b2 += i) > 0)
#else
if ( (i = ((s5 ? 32 - hi0bits(S->x[S->wds-1]) : 1) + s2) & 0xf) !=0)
i = 16 - i;
#endif
if (i > 4) {
i -= 4;
b2 += i;
m2 += i;
s2 += i;
}
else if (i < 4) {
i += 28;
b2 += i;
m2 += i;
s2 += i;
}
if (b2 > 0)
b = lshift(b, b2); b = lshift(b, b2);
if (s2 > 0) if ((s2 += i) > 0)
S = lshift(S, s2); S = lshift(S, s2);
if (k_check) { if (k_check) {
if (cmp(b,S) < 0) { if (cmp(b,S) < 0) {
@ -588,8 +544,8 @@ __gdtoa
if (leftright) if (leftright)
mhi = multadd(mhi, 10, 0); mhi = multadd(mhi, 10, 0);
ilim = ilim1; ilim = ilim1;
}
} }
}
if (ilim <= 0 && mode > 2) { if (ilim <= 0 && mode > 2) {
if (ilim < 0 || cmp(b,S = multadd(S,5,0)) <= 0) { if (ilim < 0 || cmp(b,S = multadd(S,5,0)) <= 0) {
/* no digits, fcvt style */ /* no digits, fcvt style */
@ -597,13 +553,13 @@ __gdtoa
k = -1 - ndigits; k = -1 - ndigits;
inex = STRTOG_Inexlo; inex = STRTOG_Inexlo;
goto ret; goto ret;
} }
one_digit: one_digit:
inex = STRTOG_Inexhi; inex = STRTOG_Inexhi;
*s++ = '1'; *s++ = '1';
k++; k++;
goto ret; goto ret;
} }
if (leftright) { if (leftright) {
if (m2 > 0) if (m2 > 0)
mhi = lshift(mhi, m2); mhi = lshift(mhi, m2);
@ -617,7 +573,7 @@ __gdtoa
mhi = Balloc(mhi->k); mhi = Balloc(mhi->k);
Bcopy(mhi, mlo); Bcopy(mhi, mlo);
mhi = lshift(mhi, 1); mhi = lshift(mhi, 1);
} }
for(i = 1;;i++) { for(i = 1;;i++) {
dig = quorem(b,S) + '0'; dig = quorem(b,S) + '0';
@ -635,14 +591,14 @@ __gdtoa
if (j <= 0) { if (j <= 0) {
if (b->wds > 1 || b->x[0]) if (b->wds > 1 || b->x[0])
inex = STRTOG_Inexlo; inex = STRTOG_Inexlo;
} }
else { else {
dig++; dig++;
inex = STRTOG_Inexhi; inex = STRTOG_Inexhi;
} }
*s++ = dig; *s++ = dig;
goto ret; goto ret;
} }
#endif #endif
if (j < 0 || (j == 0 && !mode if (j < 0 || (j == 0 && !mode
#ifndef ROUND_BIASED #ifndef ROUND_BIASED
@ -653,7 +609,7 @@ __gdtoa
if (rdir == 2) { if (rdir == 2) {
inex = STRTOG_Inexlo; inex = STRTOG_Inexlo;
goto accept; goto accept;
} }
while (cmp(S,mhi) > 0) { while (cmp(S,mhi) > 0) {
*s++ = dig; *s++ = dig;
mhi1 = multadd(mhi, 10, 0); mhi1 = multadd(mhi, 10, 0);
@ -662,12 +618,12 @@ __gdtoa
mhi = mhi1; mhi = mhi1;
b = multadd(b, 10, 0); b = multadd(b, 10, 0);
dig = quorem(b,S) + '0'; dig = quorem(b,S) + '0';
} }
if (dig++ == '9') if (dig++ == '9')
goto round_9_up; goto round_9_up;
inex = STRTOG_Inexhi; inex = STRTOG_Inexhi;
goto accept; goto accept;
} }
if (j1 > 0) { if (j1 > 0) {
b = lshift(b, 1); b = lshift(b, 1);
j1 = cmp(b, S); j1 = cmp(b, S);
@ -675,24 +631,24 @@ __gdtoa
&& dig++ == '9') && dig++ == '9')
goto round_9_up; goto round_9_up;
inex = STRTOG_Inexhi; inex = STRTOG_Inexhi;
} }
if (b->wds > 1 || b->x[0]) if (b->wds > 1 || b->x[0])
inex = STRTOG_Inexlo; inex = STRTOG_Inexlo;
accept: accept:
*s++ = dig; *s++ = dig;
goto ret; goto ret;
} }
if (j1 > 0 && rdir != 2) { if (j1 > 0 && rdir != 2) {
if (dig == '9') { /* possible if i == 1 */ if (dig == '9') { /* possible if i == 1 */
round_9_up: round_9_up:
*s++ = '9'; *s++ = '9';
inex = STRTOG_Inexhi; inex = STRTOG_Inexhi;
goto roundoff; goto roundoff;
} }
inex = STRTOG_Inexhi; inex = STRTOG_Inexhi;
*s++ = dig + 1; *s++ = dig + 1;
goto ret; goto ret;
} }
*s++ = dig; *s++ = dig;
if (i == ilim) if (i == ilim)
break; break;
@ -702,16 +658,16 @@ __gdtoa
else { else {
mlo = multadd(mlo, 10, 0); mlo = multadd(mlo, 10, 0);
mhi = multadd(mhi, 10, 0); mhi = multadd(mhi, 10, 0);
}
} }
} }
}
else else
for(i = 1;; i++) { for(i = 1;; i++) {
*s++ = dig = quorem(b,S) + '0'; *s++ = dig = quorem(b,S) + '0';
if (i >= ilim) if (i >= ilim)
break; break;
b = multadd(b, 10, 0); b = multadd(b, 10, 0);
} }
/* Round off last digit */ /* Round off last digit */
@ -719,7 +675,7 @@ __gdtoa
if (rdir == 2 || (b->wds <= 1 && !b->x[0])) if (rdir == 2 || (b->wds <= 1 && !b->x[0]))
goto chopzeros; goto chopzeros;
goto roundoff; goto roundoff;
} }
b = lshift(b, 1); b = lshift(b, 1);
j = cmp(b, S); j = cmp(b, S);
if (j > 0 || (j == 0 && dig & 1)) { if (j > 0 || (j == 0 && dig & 1)) {
@ -730,23 +686,23 @@ __gdtoa
k++; k++;
*s++ = '1'; *s++ = '1';
goto ret; goto ret;
} }
++*s++; ++*s++;
} }
else { else {
chopzeros: chopzeros:
if (b->wds > 1 || b->x[0]) if (b->wds > 1 || b->x[0])
inex = STRTOG_Inexlo; inex = STRTOG_Inexlo;
while(*--s == '0'){} while(*--s == '0'){}
s++; ++s;
} }
ret: ret:
Bfree(S); Bfree(S);
if (mhi) { if (mhi) {
if (mlo && mlo != mhi) if (mlo && mlo != mhi)
Bfree(mlo); Bfree(mlo);
Bfree(mhi); Bfree(mhi);
} }
ret1: ret1:
Bfree(b); Bfree(b);
*s = 0; *s = 0;
@ -755,4 +711,4 @@ __gdtoa
*rve = s; *rve = s;
*kindp |= inex; *kindp |= inex;
return s0; return s0;
} }

View File

@ -36,6 +36,15 @@ THIS SOFTWARE.
#define GDTOA_H_INCLUDED #define GDTOA_H_INCLUDED
#include "gd_arith.h" #include "gd_arith.h"
#include <stddef.h> /* for size_t */
#if defined(__MINGW32__) || defined(__MINGW64__)
/* keep the 'Long' definition as 'long' for compatibility
* with older/other software. long in w64 is 32 bits anyway..
*/
#define Long long /* int */
#undef NO_LONG_LONG /* we have long long type */
#endif /* MinGW */
#ifndef Long #ifndef Long
#define Long long #define Long long
@ -47,25 +56,7 @@ typedef unsigned Long ULong;
typedef unsigned short UShort; typedef unsigned short UShort;
#endif #endif
#ifndef ANSI enum { /* return values from strtodg */
#ifdef KR_headers
#define ANSI(x) ()
#define Void /*nothing*/
#else
#define ANSI(x) x
#define Void void
#endif
#endif /* ANSI */
#ifndef CONST
#ifdef KR_headers
#define CONST /* blank */
#else
#define CONST const
#endif
#endif /* CONST */
enum { /* return values from strtodg */
STRTOG_Zero = 0, STRTOG_Zero = 0,
STRTOG_Normal = 1, STRTOG_Normal = 1,
STRTOG_Denormal = 2, STRTOG_Denormal = 2,
@ -77,49 +68,49 @@ typedef unsigned short UShort;
/* The following may be or-ed into one of the above values. */ /* The following may be or-ed into one of the above values. */
STRTOG_Neg = 0x08, STRTOG_Neg = 0x08, /* does not affect STRTOG_Inexlo or STRTOG_Inexhi */
STRTOG_Inexlo = 0x10, STRTOG_Inexlo = 0x10, /* returned result rounded toward zero */
STRTOG_Inexhi = 0x20, STRTOG_Inexhi = 0x20, /* returned result rounded away from zero */
STRTOG_Inexact = 0x30, STRTOG_Inexact = 0x30,
STRTOG_Underflow= 0x40, STRTOG_Underflow= 0x40,
STRTOG_Overflow = 0x80 STRTOG_Overflow = 0x80
}; };
typedef struct typedef struct
FPI { FPI {
int nbits; int nbits;
int emin; int emin;
int emax; int emax;
int rounding; int rounding;
int sudden_underflow; int sudden_underflow;
} FPI; } FPI;
enum { /* FPI.rounding values: same as FLT_ROUNDS */ enum { /* FPI.rounding values: same as FLT_ROUNDS */
FPI_Round_zero = 0, FPI_Round_zero = 0,
FPI_Round_near = 1, FPI_Round_near = 1,
FPI_Round_up = 2, FPI_Round_up = 2,
FPI_Round_down = 3 FPI_Round_down = 3
}; };
#ifdef __cplusplus #ifdef __cplusplus
extern "C" { extern "C" {
#endif #endif
extern char* __dtoa ANSI((double d, int mode, int ndigits, int *decpt, extern char* __dtoa (double d, int mode, int ndigits, int *decpt,
int *sign, char **rve)); int *sign, char **rve);
extern char* __gdtoa ANSI((FPI *fpi, int be, ULong *bits, int *kindp, extern char* __gdtoa (FPI *fpi, int be, ULong *bits, int *kindp,
int mode, int ndigits, int *decpt, char **rve)); int mode, int ndigits, int *decpt, char **rve);
extern void __freedtoa ANSI((char*)); extern void __freedtoa (char *);
extern int __strtodg ANSI((CONST char*, char**, FPI*, Long*, ULong*)); extern float __strtof (const char *, char **);
extern float __strtof ANSI((CONST char *, char **)); extern double __strtod (const char *, char **);
extern double __strtod ANSI((CONST char *, char **)); extern long double __strtold (const char *, char **);
extern long double strtold ANSI((CONST char *, char **)); extern int __strtodg (const char *, char **, FPI *, Long *, ULong *);
extern char* __g__fmt ANSI((char *, char *, char *e, int, ULong)); extern char* __g__fmt (char*, char*, char*, int, ULong, size_t);
extern char* __g_dfmt ANSI((char*, double*, int, unsigned)); extern char* __g_dfmt (char*, double*, int, size_t);
extern char* __g_ffmt ANSI((char*, float*, int, unsigned)); extern char* __g_ffmt (char*, float*, int, size_t);
extern char* __g_xfmt ANSI((char*, void*, int, unsigned)); extern char* __g_xfmt (char*, void*, int, size_t);
#ifdef __cplusplus #ifdef __cplusplus
} }

View File

@ -0,0 +1,18 @@
FPI *fpi, fpi1;
int Rounding;
#ifdef Trust_FLT_ROUNDS /*{{ only define this if FLT_ROUNDS really works! */
Rounding = Flt_Rounds;
#else /*}{*/
Rounding = 1;
switch(fegetround()) {
case FE_TOWARDZERO: Rounding = 0; break;
case FE_UPWARD: Rounding = 2; break;
case FE_DOWNWARD: Rounding = 3;
}
#endif /*}}*/
fpi = &fpi0;
if (Rounding != 1) {
fpi1 = fpi0;
fpi = &fpi1;
fpi1.rounding = Rounding;
}

View File

@ -2,7 +2,7 @@
The author of this software is David M. Gay. The author of this software is David M. Gay.
Copyright (C) 1998-2008 by Lucent Technologies Copyright (C) 1998-2000 by Lucent Technologies
All Rights Reserved All Rights Reserved
Permission to use, copy, modify, and distribute this software and Permission to use, copy, modify, and distribute this software and
@ -126,17 +126,22 @@ THIS SOFTWARE.
* conversions of IEEE doubles in single-threaded executions with * conversions of IEEE doubles in single-threaded executions with
* 8-byte pointers, PRIVATE_MEM >= 7400 appears to suffice; with * 8-byte pointers, PRIVATE_MEM >= 7400 appears to suffice; with
* 4-byte pointers, PRIVATE_MEM >= 7112 appears adequate. * 4-byte pointers, PRIVATE_MEM >= 7112 appears adequate.
* #define INFNAN_CHECK on IEEE systems to cause strtod to check for * #define NO_INFNAN_CHECK if you do not wish to have INFNAN_CHECK
* Infinity and NaN (case insensitively). * #defined automatically on IEEE systems. On such systems,
* when INFNAN_CHECK is #defined, strtod checks
* for Infinity and NaN (case insensitively).
* When INFNAN_CHECK is #defined and No_Hex_NaN is not #defined, * When INFNAN_CHECK is #defined and No_Hex_NaN is not #defined,
* strtodg also accepts (case insensitively) strings of the form * strtodg also accepts (case insensitively) strings of the form
* NaN(x), where x is a string of hexadecimal digits and spaces; * NaN(x), where x is a string of hexadecimal digits (optionally
* if there is only one string of hexadecimal digits, it is taken * preceded by 0x or 0X) and spaces; if there is only one string
* for the fraction bits of the resulting NaN; if there are two or * of hexadecimal digits, it is taken for the fraction bits of the
* more strings of hexadecimal digits, each string is assigned * resulting NaN; if there are two or more strings of hexadecimal
* to the next available sequence of 32-bit words of fractions * digits, each string is assigned to the next available sequence
* bits (starting with the most significant), right-aligned in * of 32-bit words of fractions bits (starting with the most
* each sequence. * significant), right-aligned in each sequence.
* Unless GDTOA_NON_PEDANTIC_NANCHECK is #defined, input "NaN(...)"
* is consumed even when ... has the wrong form (in which case the
* "(...)" is consumed but ignored).
* #define MULTIPLE_THREADS if the system offers preemptively scheduled * #define MULTIPLE_THREADS if the system offers preemptively scheduled
* multiple threads. In this case, you must provide (or suitably * multiple threads. In this case, you must provide (or suitably
* #define) two locks, acquired by ACQUIRE_DTOA_LOCK(n) and freed * #define) two locks, acquired by ACQUIRE_DTOA_LOCK(n) and freed
@ -157,11 +162,6 @@ THIS SOFTWARE.
* #define NO_STRING_H to use private versions of memcpy. * #define NO_STRING_H to use private versions of memcpy.
* On some K&R systems, it may also be necessary to * On some K&R systems, it may also be necessary to
* #define DECLARE_SIZE_T in this case. * #define DECLARE_SIZE_T in this case.
* #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 USE_LOCALE to use the current locale's decimal_point value.
*/ */
@ -170,9 +170,15 @@ THIS SOFTWARE.
#include "gdtoa.h" #include "gdtoa.h"
#include "gd_qnan.h" #include "gd_qnan.h"
#define INFNAN_CHECK 1 #if defined(__MINGW32__) || defined(__MINGW64__)
#define MULTIPLE_THREADS 1 #define MULTIPLE_THREADS 1
#define USE_LOCALE 1 #define USE_LOCALE 1
#define NO_LOCALE_CACHE 1
#endif /* MinGW */
#ifdef Honor_FLT_ROUNDS
#include <fenv.h>
#endif
#ifdef DEBUG #ifdef DEBUG
#include <stdio.h> #include <stdio.h>
@ -182,14 +188,8 @@ THIS SOFTWARE.
#include <stdlib.h> #include <stdlib.h>
#include <string.h> #include <string.h>
#ifdef KR_headers
#define Char char
#else
#define Char void
#endif
#ifdef MALLOC #ifdef MALLOC
extern Char *MALLOC ANSI((size_t)); extern void *MALLOC (size_t);
#else #else
#define MALLOC malloc #define MALLOC malloc
#endif #endif
@ -204,6 +204,14 @@ extern Char *MALLOC ANSI((size_t));
#endif #endif
#include <errno.h> #include <errno.h>
#ifdef NO_ERRNO
#define SET_ERRNO(x)
#else
#define SET_ERRNO(x) \
errno = (x)
#endif
#ifdef Bad_float_h #ifdef Bad_float_h
#ifdef IEEE_Arith #ifdef IEEE_Arith
@ -264,27 +272,16 @@ extern "C" {
Exactly one of IEEE_8087, IEEE_MC68k, VAX, or IBM should be defined. Exactly one of IEEE_8087, IEEE_MC68k, VAX, or IBM should be defined.
#endif #endif
typedef union { double d; ULong L[2]; } U; typedef union _dbl_union { double d; ULong L[2]; } dbl_union;
#ifdef YES_ALIAS
#define dval(x) x
#ifdef IEEE_8087 #ifdef IEEE_8087
#define word0(x) ((ULong *)&x)[1] #define word0(x) (x)->L[1]
#define word1(x) ((ULong *)&x)[0] #define word1(x) (x)->L[0]
#else #else
#define word0(x) ((ULong *)&x)[0] #define word0(x) (x)->L[0]
#define word1(x) ((ULong *)&x)[1] #define word1(x) (x)->L[1]
#endif #endif
#else /* !YES_ALIAS */ #define dval(x) (x)->d
#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]
#endif
#define dval(x) ((U*)&x)->d
#endif /* YES_ALIAS */
/* The following definition of Storeinc is appropriate for MIPS processors. /* The following definition of Storeinc is appropriate for MIPS processors.
* An alternative that might be better on some machines is * An alternative that might be better on some machines is
@ -403,11 +400,7 @@ typedef union { double d; ULong L[2]; } U;
#ifdef RND_PRODQUOT #ifdef RND_PRODQUOT
#define rounded_product(a,b) a = rnd_prod(a, b) #define rounded_product(a,b) a = rnd_prod(a, b)
#define rounded_quotient(a,b) a = rnd_quot(a, b) #define rounded_quotient(a,b) a = rnd_quot(a, b)
#ifdef KR_headers
extern double rnd_prod(), rnd_quot();
#else
extern double rnd_prod(double, double), rnd_quot(double, double); extern double rnd_prod(double, double), rnd_quot(double, double);
#endif
#else #else
#define rounded_product(a,b) a *= b #define rounded_product(a,b) a *= b
#define rounded_quotient(a,b) a /= b #define rounded_quotient(a,b) a /= b
@ -458,23 +451,22 @@ extern double rnd_prod(double, double), rnd_quot(double, double);
#define FREE_DTOA_LOCK(n) /*nothing*/ #define FREE_DTOA_LOCK(n) /*nothing*/
#endif #endif
#define Kmax 15 #define Kmax 9
#define Bigint __Bigint #define Bigint __Bigint
struct struct
Bigint { Bigint {
struct Bigint *next; struct Bigint *next;
int k, maxwds, sign, wds; int k, maxwds, sign, wds;
ULong x[1]; ULong x[1];
}; };
typedef struct Bigint Bigint;
typedef struct Bigint Bigint;
#ifdef NO_STRING_H #ifdef NO_STRING_H
#ifdef DECLARE_SIZE_T #ifdef DECLARE_SIZE_T
typedef unsigned int size_t; typedef unsigned int size_t;
#endif #endif
extern void memcpy_D2A ANSI((void*, const void*, size_t)); extern void memcpy_D2A (void*, const void*, size_t);
#define Bcopy(x,y) memcpy_D2A(&x->sign,&y->sign,y->wds*sizeof(ULong) + 2*sizeof(int)) #define Bcopy(x,y) memcpy_D2A(&x->sign,&y->sign,y->wds*sizeof(ULong) + 2*sizeof(int))
#else /* !NO_STRING_H */ #else /* !NO_STRING_H */
#define Bcopy(x,y) memcpy(&x->sign,&y->sign,y->wds*sizeof(ULong) + 2*sizeof(int)) #define Bcopy(x,y) memcpy(&x->sign,&y->sign,y->wds*sizeof(ULong) + 2*sizeof(int))
@ -484,15 +476,15 @@ extern void memcpy_D2A ANSI((void*, const void*, size_t));
static inline int static inline int
__lo0bits_D2A (ULong *y) __lo0bits_D2A (ULong *y)
{ {
int ret = __builtin_ctz(*y); int ret = __builtin_ctz(*y);
*y = *y >> ret; *y = *y >> ret;
return ret; return ret;
} }
static inline int static inline int
__hi0bits_D2A (ULong y) __hi0bits_D2A (ULong y)
{ {
return __builtin_clz(y); return __builtin_clz(y);
} }
#endif #endif
@ -543,48 +535,48 @@ __hi0bits_D2A (ULong y)
#define trailz __trailz_D2A #define trailz __trailz_D2A
#define ulp __ulp_D2A #define ulp __ulp_D2A
extern char *dtoa_result; extern char *dtoa_result;
extern CONST double bigtens[], tens[], tinytens[]; extern const double bigtens[], tens[], tinytens[];
extern unsigned char hexdig[]; extern unsigned char hexdig[];
extern Bigint *Balloc ANSI((int)); extern Bigint *Balloc (int);
extern void Bfree ANSI((Bigint*)); extern void Bfree (Bigint*);
extern void ULtof ANSI((ULong*, ULong*, Long, int)); extern void ULtof (ULong*, ULong*, Long, int);
extern void ULtod ANSI((ULong*, ULong*, Long, int)); extern void ULtod (ULong*, ULong*, Long, int);
extern void ULtodd ANSI((ULong*, ULong*, Long, int)); extern void ULtodd (ULong*, ULong*, Long, int);
extern void ULtoQ ANSI((ULong*, ULong*, Long, int)); extern void ULtoQ (ULong*, ULong*, Long, int);
extern void ULtox ANSI((UShort*, ULong*, Long, int)); extern void ULtox (UShort*, ULong*, Long, int);
extern void ULtoxL ANSI((ULong*, ULong*, Long, int)); extern void ULtoxL (ULong*, ULong*, Long, int);
extern ULong any_on ANSI((Bigint*, int)); extern ULong any_on (Bigint*, int);
extern double b2d ANSI((Bigint*, int*)); extern double b2d (Bigint*, int*);
extern int cmp ANSI((Bigint*, Bigint*)); extern int cmp (Bigint*, Bigint*);
extern void copybits ANSI((ULong*, int, Bigint*)); extern void copybits (ULong*, int, Bigint*);
extern Bigint *d2b ANSI((double, int*, int*)); extern Bigint *d2b (double, int*, int*);
extern int decrement ANSI((Bigint*)); extern void decrement (Bigint*);
extern Bigint *diff ANSI((Bigint*, Bigint*)); extern Bigint *diff (Bigint*, Bigint*);
extern int gethex ANSI((CONST char**, FPI*, Long*, Bigint**, int)); extern int gethex (const char**, FPI*, Long*, Bigint**, int);
extern void hexdig_init_D2A(Void); extern void hexdig_init_D2A(void);
extern int hexnan ANSI((CONST char**, FPI*, ULong*)); extern int hexnan (const char**, FPI*, ULong*);
extern int hi0bits_D2A ANSI((ULong)); extern int hi0bits_D2A (ULong);
extern Bigint *i2b ANSI((int)); extern Bigint *i2b (int);
extern Bigint *increment ANSI((Bigint*)); extern Bigint *increment (Bigint*);
extern int lo0bits ANSI((ULong*)); extern int lo0bits (ULong*);
extern Bigint *lshift ANSI((Bigint*, int)); extern Bigint *lshift (Bigint*, int);
extern int match ANSI((CONST char**, char*)); extern int match (const char**, char*);
extern Bigint *mult ANSI((Bigint*, Bigint*)); extern Bigint *mult (Bigint*, Bigint*);
extern Bigint *multadd ANSI((Bigint*, int, int)); extern Bigint *multadd (Bigint*, int, int);
extern char *nrv_alloc ANSI((char*, char **, int)); extern char *nrv_alloc (char*, char **, int);
extern Bigint *pow5mult ANSI((Bigint*, int)); extern Bigint *pow5mult (Bigint*, int);
extern int quorem ANSI((Bigint*, Bigint*)); extern int quorem (Bigint*, Bigint*);
extern double ratio ANSI((Bigint*, Bigint*)); extern double ratio (Bigint*, Bigint*);
extern void rshift ANSI((Bigint*, int)); extern void rshift (Bigint*, int);
extern char *rv_alloc ANSI((int)); extern char *rv_alloc (int);
extern Bigint *s2b ANSI((CONST char*, int, int, ULong)); extern Bigint *s2b (const char*, int, int, ULong, int);
extern Bigint *set_ones ANSI((Bigint*, int)); extern Bigint *set_ones (Bigint*, int);
extern char *strcp ANSI((char*, const char*)); extern char *strcp (char*, const char*);
extern Bigint *sum ANSI((Bigint*, Bigint*)); extern Bigint *sum (Bigint*, Bigint*);
extern int trailz ANSI((Bigint*)); extern int trailz (Bigint*);
extern double ulp ANSI((double)); extern double ulp (dbl_union *);
#ifdef __cplusplus #ifdef __cplusplus
} }
@ -599,6 +591,10 @@ __hi0bits_D2A (ULong y)
* (On HP Series 700/800 machines, -DNAN_WORD0=0x7ff40000 works.) * (On HP Series 700/800 machines, -DNAN_WORD0=0x7ff40000 works.)
*/ */
#ifdef IEEE_Arith #ifdef IEEE_Arith
#ifndef NO_INFNAN_CHECK
#undef INFNAN_CHECK
#define INFNAN_CHECK
#endif
#ifdef IEEE_MC68k #ifdef IEEE_MC68k
#define _0 0 #define _0 0
#define _1 1 #define _1 1

View File

@ -35,29 +35,38 @@ THIS SOFTWARE.
#include "locale.h" #include "locale.h"
#endif #endif
int int gethex (const char **sp, FPI *fpi, Long *exp, Bigint **bp, int sign)
#ifdef KR_headers
gethex(sp, fpi, exp, bp, sign)
CONST char **sp; FPI *fpi; Long *exp; Bigint **bp; int sign;
#else
gethex( CONST char **sp, FPI *fpi, Long *exp, Bigint **bp, int sign)
#endif
{ {
Bigint *b; Bigint *b;
CONST unsigned char *decpt, *s0, *s, *s1; const unsigned char *decpt, *s0, *s, *s1;
int esign, havedig, irv, k, n, nbits, up, zret; int big, esign, havedig, irv, j, k, n, n0, nbits, up, zret;
ULong L, lostbits, *x; ULong L, lostbits, *x;
Long e, e1; Long e, e1;
#ifdef USE_LOCALE #ifdef USE_LOCALE
unsigned char decimalpoint = *localeconv()->decimal_point; int i;
const unsigned char *decimalpoint;
#ifdef NO_LOCALE_CACHE
decimalpoint = (unsigned char *)localeconv()->decimal_point;
#else #else
#define decimalpoint '.' static unsigned char *decimalpoint_cache;
if (!(s0 = decimalpoint_cache)) {
s0 = (unsigned char *)localeconv()->decimal_point;
decimalpoint_cache = (unsigned char *)
MALLOC(strlen((char *)s0) + 1);
if (decimalpoint_cache) {
strcpy((char *)decimalpoint_cache, (char *)s0);
s0 = decimalpoint_cache;
}
}
decimalpoint = s0;
#endif
#endif #endif
if (!hexdig['0']) if (!hexdig['0'])
hexdig_init_D2A(); hexdig_init_D2A();
*bp = 0;
havedig = 0; havedig = 0;
s0 = *(CONST unsigned char **)sp + 2; s0 = *(const unsigned char **)sp + 2;
while(s0[havedig] == '0') while(s0[havedig] == '0')
havedig++; havedig++;
s0 += havedig; s0 += havedig;
@ -65,11 +74,21 @@ gethex( CONST char **sp, FPI *fpi, Long *exp, Bigint **bp, int sign)
decpt = 0; decpt = 0;
zret = 0; zret = 0;
e = 0; e = 0;
if (!hexdig[*s]) { if (hexdig[*s])
havedig++;
else {
zret = 1; zret = 1;
if (*s != decimalpoint) #ifdef USE_LOCALE
for(i = 0; decimalpoint[i]; ++i) {
if (s[i] != decimalpoint[i])
goto pcheck;
}
decpt = s += i;
#else
if (*s != '.')
goto pcheck; goto pcheck;
decpt = ++s; decpt = ++s;
#endif
if (!hexdig[*s]) if (!hexdig[*s])
goto pcheck; goto pcheck;
while(*s == '0') while(*s == '0')
@ -78,64 +97,134 @@ gethex( CONST char **sp, FPI *fpi, Long *exp, Bigint **bp, int sign)
zret = 0; zret = 0;
havedig = 1; havedig = 1;
s0 = s; s0 = s;
} }
while(hexdig[*s]) while(hexdig[*s])
s++; s++;
if (*s == decimalpoint && !decpt) { #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; decpt = ++s;
#endif
while(hexdig[*s]) while(hexdig[*s])
s++; s++;
} }/*}*/
if (decpt) if (decpt)
e = -(((Long)(s-decpt)) << 2); e = -(((Long)(s-decpt)) << 2);
pcheck: pcheck:
s1 = s; s1 = s;
big = esign = 0;
switch(*s) { switch(*s) {
case 'p': case 'p':
case 'P': case 'P':
esign = 0;
switch(*++s) { switch(*++s) {
case '-': case '-':
esign = 1; esign = 1;
/* no break */ /* no break */
case '+': case '+':
s++; s++;
} }
if ((n = hexdig[*s]) == 0 || n > 0x19) { if ((n = hexdig[*s]) == 0 || n > 0x19) {
s = s1; s = s1;
break; break;
} }
e1 = n - 0x10; e1 = n - 0x10;
while((n = hexdig[*++s]) !=0 && n <= 0x19) while((n = hexdig[*++s]) !=0 && n <= 0x19) {
if (e1 & 0xf8000000)
big = 1;
e1 = 10*e1 + n - 0x10; e1 = 10*e1 + n - 0x10;
}
if (esign) if (esign)
e1 = -e1; e1 = -e1;
e += e1; e += e1;
} }
*sp = (char*)s; *sp = (char*)s;
if (!havedig)
*sp = (char*)s0 - 1;
if (zret) if (zret)
return havedig ? STRTOG_Zero : STRTOG_NoNumber; return STRTOG_Zero;
if (big) {
if (esign) {
switch(fpi->rounding) {
case FPI_Round_up:
if (sign)
break;
goto ret_tiny;
case FPI_Round_down:
if (!sign)
break;
goto ret_tiny;
}
goto retz;
ret_tiny:
b = Balloc(0);
b->wds = 1;
b->x[0] = 1;
goto dret;
}
switch(fpi->rounding) {
case FPI_Round_near:
goto ovfl1;
case FPI_Round_up:
if (!sign)
goto ovfl1;
goto ret_big;
case FPI_Round_down:
if (sign)
goto ovfl1;
goto ret_big;
}
ret_big:
nbits = fpi->nbits;
n0 = n = nbits >> kshift;
if (nbits & kmask)
++n;
for(j = n, k = 0; j >>= 1; ++k);
*bp = b = Balloc(k);
b->wds = n;
for(j = 0; j < n0; ++j)
b->x[j] = ALL_ON;
if (n > n0)
b->x[j] = ULbits >> (ULbits - (nbits & kmask));
*exp = fpi->emin;
return STRTOG_Normal | STRTOG_Inexlo;
}
n = s1 - s0 - 1; n = s1 - s0 - 1;
for(k = 0; n > 7; n >>= 1) for(k = 0; n > (1 << (kshift-2)) - 1; n >>= 1)
k++; k++;
b = Balloc(k); b = Balloc(k);
x = b->x; x = b->x;
n = 0; n = 0;
L = 0; L = 0;
#ifdef USE_LOCALE
for(i = 0; decimalpoint[i+1]; ++i);
#endif
while(s1 > s0) { while(s1 > s0) {
if (*--s1 == decimalpoint) #ifdef USE_LOCALE
if (*--s1 == decimalpoint[i]) {
s1 -= i;
continue; continue;
if (n == 32) { }
#else
if (*--s1 == '.')
continue;
#endif
if (n == ULbits) {
*x++ = L; *x++ = L;
L = 0; L = 0;
n = 0; n = 0;
} }
L |= (hexdig[*s1] & 0x0f) << n; L |= (hexdig[*s1] & 0x0f) << n;
n += 4; n += 4;
} }
*x++ = L; *x++ = L;
b->wds = n = x - b->x; b->wds = n = x - b->x;
n = 32*n - hi0bits(L); n = ULbits*n - hi0bits(L);
nbits = fpi->nbits; nbits = fpi->nbits;
lostbits = 0; lostbits = 0;
x = b->x; x = b->x;
@ -146,25 +235,26 @@ gethex( CONST char **sp, FPI *fpi, Long *exp, Bigint **bp, int sign)
k = n - 1; k = n - 1;
if (x[k>>kshift] & 1 << (k & kmask)) { if (x[k>>kshift] & 1 << (k & kmask)) {
lostbits = 2; lostbits = 2;
if (k > 1 && any_on(b,k-1)) if (k > 0 && any_on(b,k))
lostbits = 3; lostbits = 3;
}
} }
}
rshift(b, n); rshift(b, n);
e += n; e += n;
} }
else if (n < nbits) { else if (n < nbits) {
n = nbits - n; n = nbits - n;
b = lshift(b, n); b = lshift(b, n);
e -= n; e -= n;
x = b->x; x = b->x;
} }
if (e > fpi->emax) { if (e > fpi->emax) {
ovfl: ovfl:
Bfree(b); Bfree(b);
*bp = 0; ovfl1:
SET_ERRNO(ERANGE);
return STRTOG_Infinite | STRTOG_Overflow | STRTOG_Inexhi; return STRTOG_Infinite | STRTOG_Overflow | STRTOG_Inexhi;
} }
irv = STRTOG_Normal; irv = STRTOG_Normal;
if (e < fpi->emin) { if (e < fpi->emin) {
irv = STRTOG_Denormal; irv = STRTOG_Denormal;
@ -182,17 +272,20 @@ gethex( CONST char **sp, FPI *fpi, Long *exp, Bigint **bp, int sign)
case FPI_Round_down: case FPI_Round_down:
if (sign) { if (sign) {
one_bit: one_bit:
*exp = fpi->emin;
x[0] = b->wds = 1; x[0] = b->wds = 1;
dret:
*bp = b; *bp = b;
*exp = fpi->emin;
SET_ERRNO(ERANGE);
return STRTOG_Denormal | STRTOG_Inexhi return STRTOG_Denormal | STRTOG_Inexhi
| STRTOG_Underflow; | STRTOG_Underflow;
} }
}
Bfree(b);
*bp = 0;
return STRTOG_Zero | STRTOG_Inexlo | STRTOG_Underflow;
} }
Bfree(b);
retz:
SET_ERRNO(ERANGE);
return STRTOG_Zero | STRTOG_Inexlo | STRTOG_Underflow;
}
k = n - 1; k = n - 1;
if (lostbits) if (lostbits)
lostbits = 1; lostbits = 1;
@ -203,7 +296,7 @@ gethex( CONST char **sp, FPI *fpi, Long *exp, Bigint **bp, int sign)
nbits -= n; nbits -= n;
rshift(b,n); rshift(b,n);
e = fpi->emin; e = fpi->emin;
} }
if (lostbits) { if (lostbits) {
up = 0; up = 0;
switch(fpi->rounding) { switch(fpi->rounding) {
@ -211,7 +304,7 @@ gethex( CONST char **sp, FPI *fpi, Long *exp, Bigint **bp, int sign)
break; break;
case FPI_Round_near: case FPI_Round_near:
if (lostbits & 2 if (lostbits & 2
&& (lostbits & 1) | (x[0] & 1)) && (lostbits | x[0]) & 1)
up = 1; up = 1;
break; break;
case FPI_Round_up: case FPI_Round_up:
@ -219,7 +312,7 @@ gethex( CONST char **sp, FPI *fpi, Long *exp, Bigint **bp, int sign)
break; break;
case FPI_Round_down: case FPI_Round_down:
up = sign; up = sign;
} }
if (up) { if (up) {
k = b->wds; k = b->wds;
b = increment(b); b = increment(b);
@ -228,20 +321,20 @@ gethex( CONST char **sp, FPI *fpi, Long *exp, Bigint **bp, int sign)
if (nbits == fpi->nbits - 1 if (nbits == fpi->nbits - 1
&& x[nbits >> kshift] & 1 << (nbits & kmask)) && x[nbits >> kshift] & 1 << (nbits & kmask))
irv = STRTOG_Normal; irv = STRTOG_Normal;
} }
else if (b->wds > k else if (b->wds > k
|| ((n = nbits & kmask) !=0 || ((n = nbits & kmask) !=0
&& hi0bits(x[k-1]) < 32-n)) { && hi0bits(x[k-1]) < 32-n)) {
rshift(b,1); rshift(b,1);
if (++e > fpi->emax) if (++e > fpi->emax)
goto ovfl; goto ovfl;
}
irv |= STRTOG_Inexhi;
} }
irv |= STRTOG_Inexhi;
}
else else
irv |= STRTOG_Inexlo; irv |= STRTOG_Inexlo;
} }
*bp = b; *bp = b;
*exp = e; *exp = e;
return irv; return irv;
} }

View File

@ -31,12 +31,7 @@ THIS SOFTWARE.
#include "gdtoaimp.h" #include "gdtoaimp.h"
void void rshift (Bigint *b, int k)
#ifdef KR_headers
rshift(b, k) Bigint *b; int k;
#else
rshift(Bigint *b, int k)
#endif
{ {
ULong *x, *x1, *xe, y; ULong *x, *x1, *xe, y;
int n; int n;
@ -52,24 +47,19 @@ rshift(Bigint *b, int k)
while(x < xe) { while(x < xe) {
*x1++ = (y | (*x << n)) & ALL_ON; *x1++ = (y | (*x << n)) & ALL_ON;
y = *x++ >> k; y = *x++ >> k;
} }
if ((*x1 = y) !=0) if ((*x1 = y) !=0)
x1++; x1++;
} }
else else
while(x < xe) while(x < xe)
*x1++ = *x++; *x1++ = *x++;
} }
if ((b->wds = x1 - b->x) == 0) if ((b->wds = x1 - b->x) == 0)
b->x[0] = 0; b->x[0] = 0;
} }
int int trailz (Bigint *b)
#ifdef KR_headers
trailz(b) Bigint *b;
#else
trailz(Bigint *b)
#endif
{ {
ULong L, *x, *xe; ULong L, *x, *xe;
int n = 0; int n = 0;
@ -81,6 +71,6 @@ trailz(Bigint *b)
if (x < xe) { if (x < xe) {
L = *x; L = *x;
n += lo0bits(&L); n += lo0bits(&L);
}
return n;
} }
return n;
}

View File

@ -31,25 +31,19 @@ THIS SOFTWARE.
#include "gdtoaimp.h" #include "gdtoaimp.h"
unsigned char hexdig[256]; unsigned char hexdig[256];
static void static void htinit (unsigned char *h, unsigned char *s, int inc)
#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; int i, j;
for(i = 0; (j = s[i]) !=0; i++) for(i = 0; (j = s[i]) !=0; i++)
h[j] = i + inc; h[j] = i + inc;
} }
void void hexdig_init_D2A (void)
hexdig_init_D2A(Void)
{ {
#define USC (unsigned char *) #define USC (unsigned char *)
htinit(hexdig, USC "0123456789", 0x10); htinit(hexdig, USC "0123456789", 0x10);
htinit(hexdig, USC "abcdef", 0x10 + 10); htinit(hexdig, USC "abcdef", 0x10 + 10);
htinit(hexdig, USC "ABCDEF", 0x10 + 10); htinit(hexdig, USC "ABCDEF", 0x10 + 10);
} }

View File

@ -31,12 +31,7 @@ THIS SOFTWARE.
#include "gdtoaimp.h" #include "gdtoaimp.h"
static void static void L_shift (ULong *x, ULong *x1, int i)
#ifdef KR_headers
L_shift(x, x1, i) ULong *x; ULong *x1; int i;
#else
L_shift(ULong *x, ULong *x1, int i)
#endif
{ {
int j; int j;
@ -46,19 +41,13 @@ L_shift(ULong *x, ULong *x1, int i)
do { do {
*x |= x[1] << j; *x |= x[1] << j;
x[1] >>= i; x[1] >>= i;
} while(++x < x1); } while(++x < x1);
} }
int int hexnan (const char **sp, FPI *fpi, ULong *x0)
#ifdef KR_headers
hexnan(sp, fpi, x0)
CONST char **sp; FPI *fpi; ULong *x0;
#else
hexnan( CONST char **sp, FPI *fpi, ULong *x0)
#endif
{ {
ULong c, h, *x, *x1, *xe; ULong c, h, *x, *x1, *xe;
CONST char *s; const char *s;
int havedig, hd0, i, nbits; int havedig, hd0, i, nbits;
if (!hexdig['0']) if (!hexdig['0'])
@ -71,7 +60,13 @@ hexnan( CONST char **sp, FPI *fpi, ULong *x0)
x1 = xe = x; x1 = xe = x;
havedig = hd0 = i = 0; havedig = hd0 = i = 0;
s = *sp; s = *sp;
while((c = *(CONST unsigned char*)++s)) { /* allow optional initial 0x or 0X */
while((c = *(const unsigned char*)(s+1)) && c <= ' ')
++s;
if (s[1] == '0' && (s[2] == 'x' || s[2] == 'X')
&& *(const unsigned char*)(s+3) > ' ')
s += 2;
while((c = *(const unsigned char*)++s)) {
if (!(h = hexdig[c])) { if (!(h = hexdig[c])) {
if (c <= ' ') { if (c <= ' ') {
if (hd0 < havedig) { if (hd0 < havedig) {
@ -80,29 +75,42 @@ hexnan( CONST char **sp, FPI *fpi, ULong *x0)
if (x <= x0) { if (x <= x0) {
i = 8; i = 8;
continue; continue;
} }
hd0 = havedig; hd0 = havedig;
*--x = 0; *--x = 0;
x1 = x; x1 = x;
i = 0; i = 0;
}
continue;
} }
while(*(const unsigned char*)(s+1) <= ' ')
++s;
if (s[1] == '0' && (s[2] == 'x' || s[2] == 'X')
&& *(const unsigned char*)(s+3) > ' ')
s += 2;
continue;
}
if (/*(*/ c == ')' && havedig) { if (/*(*/ c == ')' && havedig) {
*sp = s + 1; *sp = s + 1;
break; break;
}
return STRTOG_NaN;
} }
#ifndef GDTOA_NON_PEDANTIC_NANCHECK
do {
if (/*(*/ c == ')') {
*sp = s + 1;
break;
}
} while((c = *++s));
#endif
return STRTOG_NaN;
}
havedig++; havedig++;
if (++i > 8) { if (++i > 8) {
if (x <= x0) if (x <= x0)
continue; continue;
i = 1; i = 1;
*--x = 0; *--x = 0;
}
*x = (*x << 4) | (h & 0xf);
} }
*x = (*x << 4) | (h & 0xf);
}
if (!havedig) if (!havedig)
return STRTOG_NaN; return STRTOG_NaN;
if (x < x1 && i < 8) if (x < x1 && i < 8)
@ -113,19 +121,19 @@ hexnan( CONST char **sp, FPI *fpi, ULong *x0)
while(x <= xe); while(x <= xe);
do *x1++ = 0; do *x1++ = 0;
while(x1 <= xe); while(x1 <= xe);
} }
else { else {
/* truncate high-order word if necessary */ /* truncate high-order word if necessary */
if ( (i = nbits & (ULbits-1)) !=0) if ( (i = nbits & (ULbits-1)) !=0)
*xe &= ((ULong)0xffffffff) >> (ULbits - i); *xe &= ((ULong)0xffffffff) >> (ULbits - i);
} }
for(x1 = xe;; --x1) { for(x1 = xe;; --x1) {
if (*x1 != 0) if (*x1 != 0)
break; break;
if (x1 == x0) { if (x1 == x0) {
*x1 = 1; *x1 = 1;
break; break;
}
} }
return STRTOG_NaNbits;
} }
return STRTOG_NaNbits;
}

View File

@ -30,16 +30,16 @@ THIS SOFTWARE.
* with " at " changed at "@" and " dot " changed to "."). */ * with " at " changed at "@" and " dot " changed to "."). */
#ifdef __MINGW32__ #if defined(__MINGW32__) || defined(__MINGW64__)
/* we have to include windows.h before gdtoa headers, otherwise /* we have to include windows.h before gdtoa
defines cause conflicts. */ headers, otherwise defines cause conflicts. */
#define WIN32_LEAN_AND_MEAN #define WIN32_LEAN_AND_MEAN
#include <windows.h> #include <windows.h>
#define NLOCKS 2 #define NLOCKS 2
#ifdef USE_WIN32_SL #ifdef USE_WIN32_SL
/* Use spin locks. */ /* Use spin locks. */
static long dtoa_sl[NLOCKS]; static long dtoa_sl[NLOCKS];
#define ACQUIRE_DTOA_LOCK(n) \ #define ACQUIRE_DTOA_LOCK(n) \
@ -47,7 +47,8 @@ static long dtoa_sl[NLOCKS];
Sleep (0); Sleep (0);
#define FREE_DTOA_LOCK(n) InterlockedExchange (&dtoa_sl[n], 0); #define FREE_DTOA_LOCK(n) InterlockedExchange (&dtoa_sl[n], 0);
#else #else /* USE_WIN32_SL */
#include <stdlib.h> #include <stdlib.h>
static CRITICAL_SECTION dtoa_CritSec[NLOCKS]; static CRITICAL_SECTION dtoa_CritSec[NLOCKS];
static long dtoa_CS_init = 0; static long dtoa_CS_init = 0;
@ -55,69 +56,59 @@ static long dtoa_CS_init = 0;
1 = initializing 1 = initializing
2 = initialized 2 = initialized
3 = deleted 3 = deleted
*/ */
static void dtoa_lock_cleanup() static void dtoa_lock_cleanup (void)
{ {
long last_CS_init = InterlockedExchange (&dtoa_CS_init,3); long last_CS_init = InterlockedExchange (&dtoa_CS_init,3);
if (2 == last_CS_init) {
if (2 == last_CS_init) int i;
{ for (i = 0; i < NLOCKS; i++)
int i; DeleteCriticalSection (&dtoa_CritSec[i]);
for (i = 0; i < NLOCKS; i++) }
DeleteCriticalSection (&dtoa_CritSec[i]);
}
} }
static void dtoa_lock(int n) static void dtoa_lock (int n)
{ {
if (2 == dtoa_CS_init) if (2 == dtoa_CS_init) {
{ EnterCriticalSection (&dtoa_CritSec[n]);
EnterCriticalSection (&dtoa_CritSec[n]); return;
return; }
} else if (0 == dtoa_CS_init) {
long last_CS_init = InterlockedExchange (&dtoa_CS_init, 1);
if (0 == last_CS_init) {
int i;
for (i = 0; i < NLOCKS; i++)
InitializeCriticalSection (&dtoa_CritSec[i]);
atexit (dtoa_lock_cleanup);
dtoa_CS_init = 2;
}
else if (2 == last_CS_init)
dtoa_CS_init = 2;
}
/* Another thread is initializing. Wait. */
while (1 == dtoa_CS_init)
Sleep (1);
else if (0 == dtoa_CS_init) /* It had better be initialized now. */
{ if (2 == dtoa_CS_init)
long last_CS_init = InterlockedExchange (&dtoa_CS_init, 1); EnterCriticalSection(&dtoa_CritSec[n]);
if (0 == last_CS_init)
{
int i;
for (i = 0; i < NLOCKS; i++)
InitializeCriticalSection (&dtoa_CritSec[i]);
atexit (dtoa_lock_cleanup);
dtoa_CS_init = 2;
}
else if (2 == last_CS_init)
dtoa_CS_init = 2;
}
/* Another thread is initializing. Wait. */
while (1 == dtoa_CS_init)
Sleep (1);
/* It had better be initialized now. */
if (2 == dtoa_CS_init)
EnterCriticalSection(&dtoa_CritSec[n]);
} }
static void dtoa_unlock(int n) static void dtoa_unlock (int n)
{ {
if (2 == dtoa_CS_init) if (2 == dtoa_CS_init)
LeaveCriticalSection (&dtoa_CritSec[n]); LeaveCriticalSection (&dtoa_CritSec[n]);
} }
#define ACQUIRE_DTOA_LOCK(n) dtoa_lock(n) #define ACQUIRE_DTOA_LOCK(n) dtoa_lock(n)
#define FREE_DTOA_LOCK(n) dtoa_unlock(n) #define FREE_DTOA_LOCK(n) dtoa_unlock(n)
#endif #endif /* USE_WIN32_SL */
#endif /* __MINGW32__ */ #endif /* __MINGW32__ / __MINGW64__ */
#include "gdtoaimp.h" #include "gdtoaimp.h"
#ifndef MULTIPLE_THREADS static Bigint *freelist[Kmax+1];
char *dtoa_result;
#endif
static Bigint *freelist[Kmax+1];
#ifndef Omit_Private_Memory #ifndef Omit_Private_Memory
#ifndef PRIVATE_MEM #ifndef PRIVATE_MEM
#define PRIVATE_MEM 2304 #define PRIVATE_MEM 2304
@ -126,13 +117,7 @@ static void dtoa_unlock(int n)
static double private_mem[PRIVATE_mem], *pmem_next = private_mem; static double private_mem[PRIVATE_mem], *pmem_next = private_mem;
#endif #endif
Bigint * Bigint *Balloc (int k)
Balloc
#ifdef KR_headers
(k) int k;
#else
(int k)
#endif
{ {
int x; int x;
Bigint *rv; Bigint *rv;
@ -141,9 +126,11 @@ Balloc
#endif #endif
ACQUIRE_DTOA_LOCK(0); ACQUIRE_DTOA_LOCK(0);
if ( (rv = freelist[k]) !=0) { /* The k > Kmax case does not need ACQUIRE_DTOA_LOCK(0), */
/* but this case seems very unlikely. */
if (k <= Kmax && (rv = freelist[k]) !=0) {
freelist[k] = rv->next; freelist[k] = rv->next;
} }
else { else {
x = 1 << k; x = 1 << k;
#ifdef Omit_Private_Memory #ifdef Omit_Private_Memory
@ -151,51 +138,44 @@ Balloc
#else #else
len = (sizeof(Bigint) + (x-1)*sizeof(ULong) + sizeof(double) - 1) len = (sizeof(Bigint) + (x-1)*sizeof(ULong) + sizeof(double) - 1)
/sizeof(double); /sizeof(double);
if (pmem_next - private_mem + len <= PRIVATE_mem) { if (k <= Kmax && pmem_next - private_mem + len <= PRIVATE_mem) {
rv = (Bigint*)pmem_next; rv = (Bigint*)pmem_next;
pmem_next += len; pmem_next += len;
} }
else else
rv = (Bigint*)MALLOC(len*sizeof(double)); rv = (Bigint*)MALLOC(len*sizeof(double));
#endif #endif
rv->k = k; rv->k = k;
rv->maxwds = x; rv->maxwds = x;
} }
FREE_DTOA_LOCK(0); FREE_DTOA_LOCK(0);
rv->sign = rv->wds = 0; rv->sign = rv->wds = 0;
return rv; return rv;
} }
void void Bfree (Bigint *v)
Bfree
#ifdef KR_headers
(v) Bigint *v;
#else
(Bigint *v)
#endif
{ {
if (v) { if (v) {
ACQUIRE_DTOA_LOCK(0); if (v->k > Kmax)
v->next = freelist[v->k]; free((void*)v);
freelist[v->k] = v; else {
FREE_DTOA_LOCK(0); ACQUIRE_DTOA_LOCK(0);
v->next = freelist[v->k];
freelist[v->k] = v;
FREE_DTOA_LOCK(0);
} }
} }
}
// Shift y so lowest bit is 1 and return the number of bits y was /* lo0bits(): Shift y so lowest bit is 1 and return the
// shifted. * number of bits y was shifted.
// With __GNUC__, we use an inline wrapper for __builtin_clz() * With GCC, we use an inline wrapper for __builtin_clz()
*/
#ifndef __GNUC__ #ifndef __GNUC__
int int lo0bits (ULong *y)
lo0bits
#ifdef KR_headers
(y) ULong *y;
#else
(ULong *y)
#endif
{ {
register int k; int k;
register ULong x = *y; ULong x = *y;
if (x & 7) { if (x & 7) {
if (x & 1) if (x & 1)
@ -203,46 +183,39 @@ lo0bits
if (x & 2) { if (x & 2) {
*y = x >> 1; *y = x >> 1;
return 1; return 1;
} }
*y = x >> 2; *y = x >> 2;
return 2; return 2;
} }
k = 0; k = 0;
if (!(x & 0xffff)) { if (!(x & 0xffff)) {
k = 16; k = 16;
x >>= 16; x >>= 16;
} }
if (!(x & 0xff)) { if (!(x & 0xff)) {
k += 8; k += 8;
x >>= 8; x >>= 8;
} }
if (!(x & 0xf)) { if (!(x & 0xf)) {
k += 4; k += 4;
x >>= 4; x >>= 4;
} }
if (!(x & 0x3)) { if (!(x & 0x3)) {
k += 2; k += 2;
x >>= 2; x >>= 2;
} }
if (!(x & 1)) { if (!(x & 1)) {
k++; k++;
x >>= 1; x >>= 1;
if (!x) if (!x)
return 32; return 32;
} }
*y = x; *y = x;
return k; return k;
} }
#endif /* __GNUC__ */
#endif /* __GNUC__ */ Bigint *multadd (Bigint *b, int m, int a) /* multiply by m and add a */
Bigint *
multadd
#ifdef KR_headers
(b, m, a) Bigint *b; int m, a;
#else
(Bigint *b, int m, int a) /* multiply by m and add a */
#endif
{ {
int i, wds; int i, wds;
#ifdef ULLong #ifdef ULLong
@ -278,66 +251,54 @@ multadd
*x++ = y & 0xffff; *x++ = y & 0xffff;
#endif #endif
#endif #endif
} } while(++i < wds);
while(++i < wds);
if (carry) { if (carry) {
if (wds >= b->maxwds) { if (wds >= b->maxwds) {
b1 = Balloc(b->k+1); b1 = Balloc(b->k+1);
Bcopy(b1, b); Bcopy(b1, b);
Bfree(b); Bfree(b);
b = b1; b = b1;
} }
b->x[wds++] = carry; b->x[wds++] = carry;
b->wds = wds; b->wds = wds;
}
return b;
} }
return b;
}
// With __GNUC__, we use an inline wrapper for __builtin_clz() /* hi0bits();
* With GCC, we use an inline wrapper for __builtin_clz()
*/
#ifndef __GNUC__ #ifndef __GNUC__
int int hi0bits_D2A (ULong x)
hi0bits_D2A
#ifdef KR_headers
(x) register ULong x;
#else
(register ULong x)
#endif
{ {
register int k = 0; int k = 0;
if (!(x & 0xffff0000)) { if (!(x & 0xffff0000)) {
k = 16; k = 16;
x <<= 16; x <<= 16;
} }
if (!(x & 0xff000000)) { if (!(x & 0xff000000)) {
k += 8; k += 8;
x <<= 8; x <<= 8;
} }
if (!(x & 0xf0000000)) { if (!(x & 0xf0000000)) {
k += 4; k += 4;
x <<= 4; x <<= 4;
} }
if (!(x & 0xc0000000)) { if (!(x & 0xc0000000)) {
k += 2; k += 2;
x <<= 2; x <<= 2;
} }
if (!(x & 0x80000000)) { if (!(x & 0x80000000)) {
k++; k++;
if (!(x & 0x40000000)) if (!(x & 0x40000000))
return 32; return 32;
}
return k;
} }
return k;
}
#endif /* __GNUC__ */
#endif Bigint *i2b (int i)
Bigint *
i2b
#ifdef KR_headers
(i) int i;
#else
(int i)
#endif
{ {
Bigint *b; Bigint *b;
@ -345,15 +306,9 @@ i2b
b->x[0] = i; b->x[0] = i;
b->wds = 1; b->wds = 1;
return b; return b;
} }
Bigint * Bigint *mult (Bigint *a, Bigint *b)
mult
#ifdef KR_headers
(a, b) Bigint *a, *b;
#else
(Bigint *a, Bigint *b)
#endif
{ {
Bigint *c; Bigint *c;
int k, wa, wb, wc; int k, wa, wb, wc;
@ -372,7 +327,7 @@ mult
c = a; c = a;
a = b; a = b;
b = c; b = c;
} }
k = a->k; k = a->k;
wa = a->wds; wa = a->wds;
wb = b->wds; wb = b->wds;
@ -397,11 +352,10 @@ mult
z = *x++ * (ULLong)y + *xc + carry; z = *x++ * (ULLong)y + *xc + carry;
carry = z >> 32; carry = z >> 32;
*xc++ = z & 0xffffffffUL; *xc++ = z & 0xffffffffUL;
} } while(x < xae);
while(x < xae);
*xc = carry; *xc = carry;
}
} }
}
#else #else
#ifdef Pack_32 #ifdef Pack_32
for(; xb < xbe; xb++, xc0++) { for(; xb < xbe; xb++, xc0++) {
@ -415,10 +369,9 @@ mult
z2 = (*x++ >> 16) * y + (*xc >> 16) + carry; z2 = (*x++ >> 16) * y + (*xc >> 16) + carry;
carry = z2 >> 16; carry = z2 >> 16;
Storeinc(xc, z2, z); Storeinc(xc, z2, z);
} } while(x < xae);
while(x < xae);
*xc = carry; *xc = carry;
} }
if ( (y = *xb >> 16) !=0) { if ( (y = *xb >> 16) !=0) {
x = xa; x = xa;
xc = xc0; xc = xc0;
@ -430,11 +383,10 @@ mult
Storeinc(xc, z, z2); Storeinc(xc, z, z2);
z2 = (*x++ >> 16) * y + (*xc & 0xffff) + carry; z2 = (*x++ >> 16) * y + (*xc & 0xffff) + carry;
carry = z2 >> 16; carry = z2 >> 16;
} } while(x < xae);
while(x < xae);
*xc = z2; *xc = z2;
}
} }
}
#else #else
for(; xb < xbe; xc0++) { for(; xb < xbe; xc0++) {
if ( (y = *xb++) !=0) { if ( (y = *xb++) !=0) {
@ -445,27 +397,20 @@ mult
z = *x++ * y + *xc + carry; z = *x++ * y + *xc + carry;
carry = z >> 16; carry = z >> 16;
*xc++ = z & 0xffff; *xc++ = z & 0xffff;
} } while(x < xae);
while(x < xae);
*xc = carry; *xc = carry;
}
} }
}
#endif #endif
#endif #endif
for(xc0 = c->x, xc = xc0 + wc; wc > 0 && !*--xc; --wc) ; for(xc0 = c->x, xc = xc0 + wc; wc > 0 && !*--xc; --wc) ;
c->wds = wc; c->wds = wc;
return c; return c;
} }
static Bigint *p5s; static Bigint *p5s;
Bigint * Bigint *pow5mult (Bigint *b, int k)
pow5mult
#ifdef KR_headers
(b, k) Bigint *b; int k;
#else
(Bigint *b, int k)
#endif
{ {
Bigint *b1, *p5, *p51; Bigint *b1, *p5, *p51;
int i; int i;
@ -483,19 +428,19 @@ pow5mult
if (!(p5 = p5s)) { if (!(p5 = p5s)) {
p5 = p5s = i2b(625); p5 = p5s = i2b(625);
p5->next = 0; p5->next = 0;
} }
FREE_DTOA_LOCK(1); FREE_DTOA_LOCK(1);
#else #else
p5 = p5s = i2b(625); p5 = p5s = i2b(625);
p5->next = 0; p5->next = 0;
#endif #endif
} }
for(;;) { for(;;) {
if (k & 1) { if (k & 1) {
b1 = mult(b, p5); b1 = mult(b, p5);
Bfree(b); Bfree(b);
b = b1; b = b1;
} }
if (!(k >>= 1)) if (!(k >>= 1))
break; break;
if ((p51 = p5->next) == 0) { if ((p51 = p5->next) == 0) {
@ -504,26 +449,19 @@ pow5mult
if (!(p51 = p5->next)) { if (!(p51 = p5->next)) {
p51 = p5->next = mult(p5,p5); p51 = p5->next = mult(p5,p5);
p51->next = 0; p51->next = 0;
} }
FREE_DTOA_LOCK(1); FREE_DTOA_LOCK(1);
#else #else
p51 = p5->next = mult(p5,p5); p51 = p5->next = mult(p5,p5);
p51->next = 0; p51->next = 0;
#endif #endif
}
p5 = p51;
} }
return b; p5 = p51;
} }
return b;
}
Bigint *lshift (Bigint *b, int k)
Bigint *
lshift
#ifdef KR_headers
(b, k) Bigint *b; int k;
#else
(Bigint *b, int k)
#endif
{ {
int i, k1, n, n1; int i, k1, n, n1;
Bigint *b1; Bigint *b1;
@ -547,8 +485,7 @@ lshift
do { do {
*x1++ = *x << k | z; *x1++ = *x << k | z;
z = *x++ >> k1; z = *x++ >> k1;
} } while(x < xe);
while(x < xe);
if ((*x1 = z) !=0) if ((*x1 = z) !=0)
++n1; ++n1;
#else #else
@ -557,27 +494,20 @@ lshift
do { do {
*x1++ = *x << k & 0xffff | z; *x1++ = *x << k & 0xffff | z;
z = *x++ >> k1; z = *x++ >> k1;
} } while(x < xe);
while(x < xe);
if (*x1 = z) if (*x1 = z)
++n1; ++n1;
#endif #endif
} }
else do else do
*x1++ = *x++; *x1++ = *x++;
while(x < xe); while(x < xe);
b1->wds = n1 - 1; b1->wds = n1 - 1;
Bfree(b); Bfree(b);
return b1; return b1;
} }
int int cmp (Bigint *a, Bigint *b)
cmp
#ifdef KR_headers
(a, b) Bigint *a, *b;
#else
(Bigint *a, Bigint *b)
#endif
{ {
ULong *xa, *xa0, *xb, *xb0; ULong *xa, *xa0, *xb, *xb0;
int i, j; int i, j;
@ -601,17 +531,11 @@ cmp
return *xa < *xb ? -1 : 1; return *xa < *xb ? -1 : 1;
if (xa <= xa0) if (xa <= xa0)
break; break;
}
return 0;
} }
return 0;
}
Bigint * Bigint *diff (Bigint *a, Bigint *b)
diff
#ifdef KR_headers
(a, b) Bigint *a, *b;
#else
(Bigint *a, Bigint *b)
#endif
{ {
Bigint *c; Bigint *c;
int i, wa, wb; int i, wa, wb;
@ -631,13 +555,13 @@ diff
c->wds = 1; c->wds = 1;
c->x[0] = 0; c->x[0] = 0;
return c; return c;
} }
if (i < 0) { if (i < 0) {
c = a; c = a;
a = b; a = b;
b = c; b = c;
i = 1; i = 1;
} }
else else
i = 0; i = 0;
c = Balloc(a->k); c = Balloc(a->k);
@ -655,13 +579,12 @@ diff
y = (ULLong)*xa++ - *xb++ - borrow; y = (ULLong)*xa++ - *xb++ - borrow;
borrow = y >> 32 & 1UL; borrow = y >> 32 & 1UL;
*xc++ = y & 0xffffffffUL; *xc++ = y & 0xffffffffUL;
} } while(xb < xbe);
while(xb < xbe);
while(xa < xae) { while(xa < xae) {
y = *xa++ - borrow; y = *xa++ - borrow;
borrow = y >> 32 & 1UL; borrow = y >> 32 & 1UL;
*xc++ = y & 0xffffffffUL; *xc++ = y & 0xffffffffUL;
} }
#else #else
#ifdef Pack_32 #ifdef Pack_32
do { do {
@ -670,52 +593,40 @@ diff
z = (*xa++ >> 16) - (*xb++ >> 16) - borrow; z = (*xa++ >> 16) - (*xb++ >> 16) - borrow;
borrow = (z & 0x10000) >> 16; borrow = (z & 0x10000) >> 16;
Storeinc(xc, z, y); Storeinc(xc, z, y);
} } while(xb < xbe);
while(xb < xbe);
while(xa < xae) { while(xa < xae) {
y = (*xa & 0xffff) - borrow; y = (*xa & 0xffff) - borrow;
borrow = (y & 0x10000) >> 16; borrow = (y & 0x10000) >> 16;
z = (*xa++ >> 16) - borrow; z = (*xa++ >> 16) - borrow;
borrow = (z & 0x10000) >> 16; borrow = (z & 0x10000) >> 16;
Storeinc(xc, z, y); Storeinc(xc, z, y);
} }
#else #else
do { do {
y = *xa++ - *xb++ - borrow; y = *xa++ - *xb++ - borrow;
borrow = (y & 0x10000) >> 16; borrow = (y & 0x10000) >> 16;
*xc++ = y & 0xffff; *xc++ = y & 0xffff;
} } while(xb < xbe);
while(xb < xbe);
while(xa < xae) { while(xa < xae) {
y = *xa++ - borrow; y = *xa++ - borrow;
borrow = (y & 0x10000) >> 16; borrow = (y & 0x10000) >> 16;
*xc++ = y & 0xffff; *xc++ = y & 0xffff;
} }
#endif #endif
#endif #endif
while(!*--xc) while(!*--xc)
wa--; wa--;
c->wds = wa; c->wds = wa;
return c; return c;
} }
double double b2d (Bigint *a, int *e)
b2d
#ifdef KR_headers
(a, e) Bigint *a; int *e;
#else
(Bigint *a, int *e)
#endif
{ {
ULong *xa, *xa0, w, y, z; ULong *xa, *xa0, w, y, z;
int k; int k;
double d; union _dbl_union d;
#ifdef VAX #define d0 word0(&d)
ULong d0, d1; #define d1 word1(&d)
#else
#define d0 word0(d)
#define d1 word1(d)
#endif
xa0 = a->x; xa0 = a->x;
xa = xa0 + a->wds; xa = xa0 + a->wds;
@ -731,17 +642,17 @@ b2d
w = xa > xa0 ? *--xa : 0; w = xa > xa0 ? *--xa : 0;
d1 = y << ((32-Ebits) + k) | w >> (Ebits - k); d1 = y << ((32-Ebits) + k) | w >> (Ebits - k);
goto ret_d; goto ret_d;
} }
z = xa > xa0 ? *--xa : 0; z = xa > xa0 ? *--xa : 0;
if (k -= Ebits) { if (k -= Ebits) {
d0 = Exp_1 | y << k | z >> (32 - k); d0 = Exp_1 | y << k | z >> (32 - k);
y = xa > xa0 ? *--xa : 0; y = xa > xa0 ? *--xa : 0;
d1 = z << k | y >> (32 - k); d1 = z << k | y >> (32 - k);
} }
else { else {
d0 = Exp_1 | y; d0 = Exp_1 | y;
d1 = z; d1 = z;
} }
#else #else
if (k < Ebits + 16) { if (k < Ebits + 16) {
z = xa > xa0 ? *--xa : 0; z = xa > xa0 ? *--xa : 0;
@ -750,7 +661,7 @@ b2d
y = xa > xa0 ? *--xa : 0; y = xa > xa0 ? *--xa : 0;
d1 = z << k + 16 - Ebits | w << k - Ebits | y >> 16 + Ebits - k; d1 = z << k + 16 - Ebits | w << k - Ebits | y >> 16 + Ebits - k;
goto ret_d; goto ret_d;
} }
z = xa > xa0 ? *--xa : 0; z = xa > xa0 ? *--xa : 0;
w = xa > xa0 ? *--xa : 0; w = xa > xa0 ? *--xa : 0;
k -= Ebits + 16; k -= Ebits + 16;
@ -759,37 +670,23 @@ b2d
d1 = w << k + 16 | y << k; d1 = w << k + 16 | y << k;
#endif #endif
ret_d: ret_d:
#ifdef VAX return dval(&d);
word0(d) = d0 >> 16 | d0 << 16;
word1(d) = d1 >> 16 | d1 << 16;
#endif
return dval(d);
}
#undef d0 #undef d0
#undef d1 #undef d1
}
Bigint * Bigint *d2b (double dd, int *e, int *bits)
d2b
#ifdef KR_headers
(d, e, bits) double d; int *e, *bits;
#else
(double d, int *e, int *bits)
#endif
{ {
Bigint *b; Bigint *b;
union _dbl_union d;
#ifndef Sudden_Underflow #ifndef Sudden_Underflow
int i; int i;
#endif #endif
int de, k; int de, k;
ULong *x, y, z; ULong *x, y, z;
#ifdef VAX #define d0 word0(&d)
ULong d0, d1; #define d1 word1(&d)
d0 = word0(d) >> 16 | word0(d) << 16; d.d = dd;
d1 = word1(d) >> 16 | word1(d) << 16;
#else
#define d0 word0(d)
#define d1 word1(d)
#endif
#ifdef Pack_32 #ifdef Pack_32
b = Balloc(1); b = Balloc(1);
@ -802,9 +699,7 @@ d2b
d0 &= 0x7fffffff; /* clear sign bit, which we ignore */ d0 &= 0x7fffffff; /* clear sign bit, which we ignore */
#ifdef Sudden_Underflow #ifdef Sudden_Underflow
de = (int)(d0 >> Exp_shift); de = (int)(d0 >> Exp_shift);
#ifndef IBM
z |= Exp_msk11; z |= Exp_msk11;
#endif
#else #else
if ( (de = (int)(d0 >> Exp_shift)) !=0) if ( (de = (int)(d0 >> Exp_shift)) !=0)
z |= Exp_msk1; z |= Exp_msk1;
@ -814,19 +709,15 @@ d2b
if ( (k = lo0bits(&y)) !=0) { if ( (k = lo0bits(&y)) !=0) {
x[0] = y | z << (32 - k); x[0] = y | z << (32 - k);
z >>= k; z >>= k;
} }
else else
x[0] = y; x[0] = y;
#ifndef Sudden_Underflow #ifndef Sudden_Underflow
i = i =
#endif #endif
b->wds = (x[1] = z) !=0 ? 2 : 1; b->wds = (x[1] = z) !=0 ? 2 : 1;
} }
else { else {
#ifdef DEBUG
if (!z)
Bug("Zero passed to d2b");
#endif
k = lo0bits(&z); k = lo0bits(&z);
x[0] = z; x[0] = z;
#ifndef Sudden_Underflow #ifndef Sudden_Underflow
@ -834,7 +725,7 @@ d2b
#endif #endif
b->wds = 1; b->wds = 1;
k += 32; k += 32;
} }
#else #else
if ( (y = d1) !=0) { if ( (y = d1) !=0) {
if ( (k = lo0bits(&y)) !=0) if ( (k = lo0bits(&y)) !=0)
@ -843,22 +734,22 @@ d2b
x[1] = z >> k - 16 & 0xffff; x[1] = z >> k - 16 & 0xffff;
x[2] = z >> k; x[2] = z >> k;
i = 2; i = 2;
} }
else { else {
x[0] = y & 0xffff; x[0] = y & 0xffff;
x[1] = y >> 16 | z << 16 - k & 0xffff; x[1] = y >> 16 | z << 16 - k & 0xffff;
x[2] = z >> k & 0xffff; x[2] = z >> k & 0xffff;
x[3] = z >> k+16; x[3] = z >> k+16;
i = 3; i = 3;
} }
else { else {
x[0] = y & 0xffff; x[0] = y & 0xffff;
x[1] = y >> 16; x[1] = y >> 16;
x[2] = z & 0xffff; x[2] = z & 0xffff;
x[3] = z >> 16; x[3] = z >> 16;
i = 3; i = 3;
}
} }
}
else { else {
#ifdef DEBUG #ifdef DEBUG
if (!z) if (!z)
@ -868,14 +759,14 @@ d2b
if (k >= 16) { if (k >= 16) {
x[0] = z; x[0] = z;
i = 0; i = 0;
} }
else { else {
x[0] = z & 0xffff; x[0] = z & 0xffff;
x[1] = z >> 16; x[1] = z >> 16;
i = 1; i = 1;
}
k += 32;
} }
k += 32;
}
while(!x[i]) while(!x[i])
--i; --i;
b->wds = i + 1; b->wds = i + 1;
@ -883,15 +774,10 @@ d2b
#ifndef Sudden_Underflow #ifndef Sudden_Underflow
if (de) { if (de) {
#endif #endif
#ifdef IBM
*e = (de - Bias - (P-1) << 2) + k;
*bits = 4*P + 8 - k - hi0bits(word0(d) & Frac_mask);
#else
*e = de - Bias - (P-1) + k; *e = de - Bias - (P-1) + k;
*bits = P - k; *bits = P - k;
#endif
#ifndef Sudden_Underflow #ifndef Sudden_Underflow
} }
else { else {
*e = de - Bias - (P-1) + 1 + k; *e = de - Bias - (P-1) + 1 + k;
#ifdef Pack_32 #ifdef Pack_32
@ -899,64 +785,39 @@ d2b
#else #else
*bits = (i+2)*16 - hi0bits(x[i]); *bits = (i+2)*16 - hi0bits(x[i]);
#endif #endif
} }
#endif #endif
return b; return b;
}
#undef d0 #undef d0
#undef d1 #undef d1
}
CONST double const double
#ifdef IEEE_Arith
bigtens[] = { 1e16, 1e32, 1e64, 1e128, 1e256 }; bigtens[] = { 1e16, 1e32, 1e64, 1e128, 1e256 };
CONST double tinytens[] = { 1e-16, 1e-32, 1e-64, 1e-128, 1e-256 const double tinytens[] = { 1e-16, 1e-32, 1e-64, 1e-128, 1e-256 };
};
#else
#ifdef IBM
bigtens[] = { 1e16, 1e32, 1e64 };
CONST double tinytens[] = { 1e-16, 1e-32, 1e-64 };
#else
bigtens[] = { 1e16, 1e32 };
CONST double tinytens[] = { 1e-16, 1e-32 };
#endif
#endif
CONST double const double
tens[] = { tens[] = {
1e0, 1e1, 1e2, 1e3, 1e4, 1e5, 1e6, 1e7, 1e8, 1e9, 1e0, 1e1, 1e2, 1e3, 1e4, 1e5, 1e6, 1e7, 1e8, 1e9,
1e10, 1e11, 1e12, 1e13, 1e14, 1e15, 1e16, 1e17, 1e18, 1e19, 1e10, 1e11, 1e12, 1e13, 1e14, 1e15, 1e16, 1e17, 1e18, 1e19,
1e20, 1e21, 1e22 1e20, 1e21, 1e22
#ifdef VAX };
, 1e23, 1e24
#endif
};
char * char *strcp_D2A (char *a, const char *b)
#ifdef KR_headers
strcp_D2A(a, b) char *a; char *b;
#else
strcp_D2A(char *a, CONST char *b)
#endif
{ {
while((*a = *b++)) while((*a = *b++))
a++; a++;
return a; return a;
} }
#ifdef NO_STRING_H #ifdef NO_STRING_H
void *memcpy_D2A (void *a1, void *b1, size_t len)
Char *
#ifdef KR_headers
memcpy_D2A(a, b, len) Char *a; Char *b; size_t len;
#else
memcpy_D2A(void *a1, void *b1, size_t len)
#endif
{ {
register char *a = (char*)a1, *ae = a + len; char *a = (char*)a1, *ae = a + len;
register char *b = (char*)b1, *a0 = a; char *b = (char*)b1, *a0 = a;
while(a < ae) while(a < ae)
*a++ = *b++; *a++ = *b++;
return a0; return a0;
} }
#endif /* NO_STRING_H */ #endif /* NO_STRING_H */

View File

@ -74,12 +74,16 @@ main(void)
double d; double d;
Ulong L[4]; Ulong L[4];
#ifndef NO_LONG_LONG #ifndef NO_LONG_LONG
unsigned short u[5]; /* need u[8] instead of u[5] for 64 bit */
unsigned short u[8];
long double D; long double D;
#endif #endif
} U; } U;
U a, b, c; U a, b, c;
int i; int i;
a.L[0]=a.L[1]=a.L[2]=a.L[3]=0;
b.L[0]=b.L[1]=b.L[2]=b.L[3]=0;
c.L[0]=c.L[1]=c.L[2]=c.L[3]=0;
a.L[0] = b.L[0] = 0x7f800000; a.L[0] = b.L[0] = 0x7f800000;
c.f = a.f - b.f; c.f = a.f - b.f;

View File

@ -31,13 +31,7 @@ THIS SOFTWARE.
#include "gdtoaimp.h" #include "gdtoaimp.h"
Bigint * Bigint *s2b (const char *s, int nd0, int nd, ULong y9, int dplen)
s2b
#ifdef KR_headers
(s, nd0, nd, y9) CONST char *s; int nd0, nd; ULong y9;
#else
(CONST char *s, int nd0, int nd, ULong y9)
#endif
{ {
Bigint *b; Bigint *b;
int i, k; int i, k;
@ -60,82 +54,51 @@ s2b
s += 9; s += 9;
do b = multadd(b, 10, *s++ - '0'); do b = multadd(b, 10, *s++ - '0');
while(++i < nd0); while(++i < nd0);
s++; s += dplen;
} }
else else
s += 10; s += dplen + 9;
for(; i < nd; i++) for(; i < nd; i++)
b = multadd(b, 10, *s++ - '0'); b = multadd(b, 10, *s++ - '0');
return b; return b;
} }
double double ratio (Bigint *a, Bigint *b)
ratio
#ifdef KR_headers
(a, b) Bigint *a, *b;
#else
(Bigint *a, Bigint *b)
#endif
{ {
double da, db; union _dbl_union da, db;
int k, ka, kb; int k, ka, kb;
dval(da) = b2d(a, &ka); dval(&da) = b2d(a, &ka);
dval(db) = b2d(b, &kb); dval(&db) = b2d(b, &kb);
k = ka - kb + ULbits*(a->wds - b->wds); k = ka - kb + ULbits*(a->wds - b->wds);
#ifdef IBM
if (k > 0) {
word0(da) += (k >> 2)*Exp_msk1;
if (k &= 3)
dval(da) *= 1 << k;
}
else {
k = -k;
word0(db) += (k >> 2)*Exp_msk1;
if (k &= 3)
dval(db) *= 1 << k;
}
#else
if (k > 0) if (k > 0)
word0(da) += k*Exp_msk1; word0(&da) += k*Exp_msk1;
else { else {
k = -k; k = -k;
word0(db) += k*Exp_msk1; word0(&db) += k*Exp_msk1;
}
#endif
return dval(da) / dval(db);
} }
return dval(&da) / dval(&db);
}
#ifdef INFNAN_CHECK #ifdef INFNAN_CHECK
int int match (const char **sp, char *t)
match
#ifdef KR_headers
(sp, t) char **sp, *t;
#else
(CONST char **sp, char *t)
#endif
{ {
int c, d; int c, d;
CONST char *s = *sp; const char *s = *sp;
while( (d = *t++) !=0) { while( (d = *t++) !=0) {
if ((c = *++s) >= 'A' && c <= 'Z') if ((c = *++s) >= 'A' && c <= 'Z')
c += 'a' - 'A'; c += 'a' - 'A';
if (c != d) if (c != d)
return 0; return 0;
} }
*sp = s + 1; *sp = s + 1;
return 1; return 1;
} }
#endif /* INFNAN_CHECK */ #endif /* INFNAN_CHECK */
void void copybits (ULong *c, int n, Bigint *b)
#ifdef KR_headers
copybits(c, n, b) ULong *c; int n; Bigint *b;
#else
copybits(ULong *c, int n, Bigint *b)
#endif
{ {
ULong *ce, *x, *xe; ULong *ce, *x, *xe;
#ifdef Pack_16 #ifdef Pack_16
@ -158,14 +121,9 @@ copybits(ULong *c, int n, Bigint *b)
#endif #endif
while(c < ce) while(c < ce)
*c++ = 0; *c++ = 0;
} }
ULong ULong any_on (Bigint *b, int k)
#ifdef KR_headers
any_on(b, k) Bigint *b; int k;
#else
any_on(Bigint *b, int k)
#endif
{ {
int n, nwds; int n, nwds;
ULong *x, *x0, x1, x2; ULong *x, *x0, x1, x2;
@ -181,11 +139,11 @@ any_on(Bigint *b, int k)
x1 <<= k; x1 <<= k;
if (x1 != x2) if (x1 != x2)
return 1; return 1;
} }
x0 = x; x0 = x;
x += n; x += n;
while(x > x0) while(x > x0)
if (*--x) if (*--x)
return 1; return 1;
return 0; return 0;
} }

View File

@ -35,21 +35,13 @@ THIS SOFTWARE.
#include "locale.h" #include "locale.h"
#endif #endif
static CONST int static const int
fivesbits[] = { 0, 3, 5, 7, 10, 12, 14, 17, 19, 21, fivesbits[] = { 0, 3, 5, 7, 10, 12, 14, 17, 19, 21,
24, 26, 28, 31, 33, 35, 38, 40, 42, 45, 24, 26, 28, 31, 33, 35, 38, 40, 42, 45,
47, 49, 52 47, 49, 52
#ifdef VAX };
, 54, 56
#endif
};
Bigint * Bigint *increment (Bigint *b)
#ifdef KR_headers
increment(b) Bigint *b;
#else
increment(Bigint *b)
#endif
{ {
ULong *x, *xe; ULong *x, *xe;
Bigint *b1; Bigint *b1;
@ -64,9 +56,9 @@ increment(Bigint *b)
if (*x < (ULong)0xffffffffL) { if (*x < (ULong)0xffffffffL) {
++*x; ++*x;
return b; return b;
} }
*x++ = 0; *x++ = 0;
} while(x < xe); } while(x < xe);
#else #else
do { do {
y = *x + carry; y = *x + carry;
@ -74,7 +66,7 @@ increment(Bigint *b)
*x++ = y & 0xffff; *x++ = y & 0xffff;
if (!carry) if (!carry)
return b; return b;
} while(x < xe); } while(x < xe);
if (carry) if (carry)
#endif #endif
{ {
@ -83,18 +75,13 @@ increment(Bigint *b)
Bcopy(b1,b); Bcopy(b1,b);
Bfree(b); Bfree(b);
b = b1; b = b1;
}
b->x[b->wds++] = 1;
} }
return b; b->x[b->wds++] = 1;
} }
return b;
}
int void decrement (Bigint *b)
#ifdef KR_headers
decrement(b) Bigint *b;
#else
decrement(Bigint *b)
#endif
{ {
ULong *x, *xe; ULong *x, *xe;
#ifdef Pack_16 #ifdef Pack_16
@ -108,26 +95,19 @@ decrement(Bigint *b)
if (*x) { if (*x) {
--*x; --*x;
break; break;
}
*x++ = 0xffffffffL;
} }
while(x < xe); *x++ = 0xffffffffL;
} while(x < xe);
#else #else
do { do {
y = *x - borrow; y = *x - borrow;
borrow = (y & 0x10000) >> 16; borrow = (y & 0x10000) >> 16;
*x++ = y & 0xffff; *x++ = y & 0xffff;
} while(borrow && x < xe); } while(borrow && x < xe);
#endif #endif
return STRTOG_Inexlo; }
}
static int static int all_on (Bigint *b, int n)
#ifdef KR_headers
all_on(b, n) Bigint *b; int n;
#else
all_on(Bigint *b, int n)
#endif
{ {
ULong *x, *xe; ULong *x, *xe;
@ -139,14 +119,9 @@ all_on(Bigint *b, int n)
if (n &= kmask) if (n &= kmask)
return ((*x | (ALL_ON << n)) & ALL_ON) == ALL_ON; return ((*x | (ALL_ON << n)) & ALL_ON) == ALL_ON;
return 1; return 1;
} }
Bigint * Bigint *set_ones (Bigint *b, int n)
#ifdef KR_headers
set_ones(b, n) Bigint *b; int n;
#else
set_ones(Bigint *b, int n)
#endif
{ {
int k; int k;
ULong *x, *xe; ULong *x, *xe;
@ -155,7 +130,7 @@ set_ones(Bigint *b, int n)
if (b->k < k) { if (b->k < k) {
Bfree(b); Bfree(b);
b = Balloc(k); b = Balloc(k);
} }
k = n >> kshift; k = n >> kshift;
if (n &= kmask) if (n &= kmask)
k++; k++;
@ -167,30 +142,24 @@ set_ones(Bigint *b, int n)
if (n) if (n)
x[-1] >>= ULbits - n; x[-1] >>= ULbits - n;
return b; return b;
} }
static int static int rvOK (dbl_union *d, FPI *fpi, Long *exp, ULong *bits,
rvOK int exact, int rd, int *irv)
#ifdef KR_headers
(d, fpi, exp, bits, exact, rd, irv)
double d; 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)
#endif
{ {
Bigint *b; Bigint *b;
ULong carry, inex, lostbits; ULong carry, inex, lostbits;
int bdif, e, j, k, k1, nb, rv; int bdif, e, j, k, k1, nb, rv;
carry = rv = 0; carry = rv = 0;
b = d2b(d, &e, &bdif); b = d2b(dval(d), &e, &bdif);
bdif -= nb = fpi->nbits; bdif -= nb = fpi->nbits;
e += bdif; e += bdif;
if (bdif <= 0) { if (bdif <= 0) {
if (exact) if (exact)
goto trunc; goto trunc;
goto ret; goto ret;
} }
if (P == nb) { if (P == nb) {
if ( if (
#ifndef IMPRECISE_INEXACT #ifndef IMPRECISE_INEXACT
@ -204,11 +173,11 @@ rvOK
#endif #endif
) goto trunc; ) goto trunc;
goto ret; goto ret;
} }
switch(rd) { switch(rd) {
case 1: case 1: /* round down (toward -Infinity) */
goto trunc; goto trunc;
case 2: case 2: /* round up (toward +Infinity) */
break; break;
default: /* round near */ default: /* round near */
k = bdif - 1; k = bdif - 1;
@ -220,11 +189,11 @@ rvOK
if (b->x[0] & 2) if (b->x[0] & 2)
break; break;
goto trunc; goto trunc;
} }
if (b->x[k>>kshift] & ((ULong)1 << (k & kmask))) if (b->x[k>>kshift] & ((ULong)1 << (k & kmask)))
break; break;
goto trunc; goto trunc;
} }
/* "break" cases: round up 1 bit, then truncate; bdif > 0 */ /* "break" cases: round up 1 bit, then truncate; bdif > 0 */
carry = 1; carry = 1;
trunc: trunc:
@ -243,9 +212,9 @@ rvOK
lostbits = b->x[0] & 1; lostbits = b->x[0] & 1;
rshift(b, 1); rshift(b, 1);
e++; e++;
}
} }
} }
}
else if (bdif < 0) else if (bdif < 0)
b = lshift(b, -bdif); b = lshift(b, -bdif);
if (e < fpi->emin) { if (e < fpi->emin) {
@ -254,7 +223,7 @@ rvOK
if (k > nb || fpi->sudden_underflow) { if (k > nb || fpi->sudden_underflow) {
b->wds = inex = 0; b->wds = inex = 0;
*irv = STRTOG_Underflow | STRTOG_Inexlo; *irv = STRTOG_Underflow | STRTOG_Inexlo;
} }
else { else {
k1 = k - 1; k1 = k - 1;
if (k1 > 0 && !lostbits) if (k1 > 0 && !lostbits)
@ -268,19 +237,17 @@ rvOK
if (carry) { if (carry) {
b = increment(b); b = increment(b);
inex = STRTOG_Inexhi | STRTOG_Underflow; inex = STRTOG_Inexhi | STRTOG_Underflow;
} }
else if (lostbits) else if (lostbits)
inex = STRTOG_Inexlo | STRTOG_Underflow; inex = STRTOG_Inexlo | STRTOG_Underflow;
}
} }
}
else if (e > fpi->emax) { else if (e > fpi->emax) {
e = fpi->emax + 1; e = fpi->emax + 1;
*irv = STRTOG_Infinite | STRTOG_Overflow | STRTOG_Inexhi; *irv = STRTOG_Infinite | STRTOG_Overflow | STRTOG_Inexhi;
#ifndef NO_ERRNO SET_ERRNO(ERANGE);
errno = ERANGE;
#endif
b->wds = inex = 0; b->wds = inex = 0;
} }
*exp = e; *exp = e;
copybits(bits, nb, b); copybits(bits, nb, b);
*irv |= inex; *irv |= inex;
@ -288,54 +255,55 @@ rvOK
ret: ret:
Bfree(b); Bfree(b);
return rv; return rv;
} }
static int static int mantbits (dbl_union *d)
#ifdef KR_headers
mantbits(d) double d;
#else
mantbits(double d)
#endif
{ {
ULong L; ULong L;
#ifdef VAX
L = word1(d) << 16 | word1(d) >> 16;
if (L)
#else
if ( (L = word1(d)) !=0) if ( (L = word1(d)) !=0)
#endif
return P - lo0bits(&L); return P - lo0bits(&L);
#ifdef VAX
L = word0(d) << 16 | word0(d) >> 16 | Exp_msk11;
#else
L = word0(d) | Exp_msk1; L = word0(d) | Exp_msk1;
#endif
return P - 32 - lo0bits(&L); return P - 32 - lo0bits(&L);
} }
int int __strtodg (const char *s00, char **se, FPI *fpi, Long *exp, ULong *bits)
__strtodg
#ifdef KR_headers
(s00, se, fpi, exp, bits)
CONST char *s00; char **se; FPI *fpi; Long *exp; ULong *bits;
#else
(CONST char *s00, char **se, FPI *fpi, Long *exp, ULong *bits)
#endif
{ {
int abe, abits, asub; int abe, abits, asub;
int bb0, bb2, bb5, bbe, bd2, bd5, bbbits, bs2, c, decpt, denorm; int bb0, bb2, bb5, bbe, bd2, bd5, bbbits, bs2, c, decpt, denorm;
int dsign, e, e1, e2, emin, esign, finished, i, inex, irv; int dsign, e, e1, e2, emin, esign, finished, i, inex, irv;
int j, k, nbits, nd, nd0, nf, nz, nz0, rd, rvbits, rve, rve1, sign; int j, k, nbits, nd, nd0, nf, nz, nz0, rd, rvbits, rve, rve1, sign;
int sudden_underflow; int sudden_underflow;
CONST char *s, *s0, *s1; const char *s, *s0, *s1;
double adj, adj0, rv, tol; double adj0, tol;
Long L; Long L;
ULong y, z; union _dbl_union adj, rv;
ULong *b, *be, y, z;
Bigint *ab, *bb, *bb1, *bd, *bd0, *bs, *delta, *rvb, *rvb0; Bigint *ab, *bb, *bb1, *bd, *bd0, *bs, *delta, *rvb, *rvb0;
#ifdef USE_LOCALE /*{{*/
#ifdef NO_LOCALE_CACHE
char *decimalpoint = localeconv()->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))) {
strcpy(decimalpoint_cache, s0);
s0 = decimalpoint_cache;
}
dplen = strlen(s0);
}
decimalpoint = (char*)s0;
#endif /*NO_LOCALE_CACHE*/
#else /*USE_LOCALE}{*/
#define dplen 1
#endif /*USE_LOCALE}}*/
irv = STRTOG_Zero; irv = STRTOG_Zero;
denorm = sign = nz0 = nz = 0; denorm = sign = nz0 = nz = 0;
dval(rv) = 0.; dval(&rv) = 0.;
rvb = 0; rvb = 0;
nbits = fpi->nbits; nbits = fpi->nbits;
for(s = s00;;s++) switch(*s) { for(s = s00;;s++) switch(*s) {
@ -360,7 +328,7 @@ __strtodg
continue; continue;
default: default:
goto break2; goto break2;
} }
break2: break2:
if (*s == '0') { if (*s == '0') {
#ifndef NO_HEX_FP #ifndef NO_HEX_FP
@ -371,15 +339,15 @@ __strtodg
if (irv == STRTOG_NoNumber) { if (irv == STRTOG_NoNumber) {
s = s00; s = s00;
sign = 0; sign = 0;
} }
goto ret; goto ret;
} }
#endif #endif
nz0 = 1; nz0 = 1;
while(*++s == '0') ; while(*++s == '0') ;
if (!*s) if (!*s)
goto ret; goto ret;
} }
sudden_underflow = fpi->sudden_underflow; sudden_underflow = fpi->sudden_underflow;
s0 = s; s0 = s;
y = z = 0; y = z = 0;
@ -390,13 +358,17 @@ __strtodg
z = 10*z + c - '0'; z = 10*z + c - '0';
nd0 = nd; nd0 = nd;
#ifdef USE_LOCALE #ifdef USE_LOCALE
if (c == *localeconv()->decimal_point) if (c == *decimalpoint) {
for(i = 1; decimalpoint[i]; ++i)
if (s[i] != decimalpoint[i])
goto dig_done;
s += i;
c = *s;
#else #else
if (c == '.') if (c == '.') {
#endif
{
decpt = 1;
c = *++s; c = *++s;
#endif
decpt = 1;
if (!nd) { if (!nd) {
for(; c == '0'; c = *++s) for(; c == '0'; c = *++s)
nz++; nz++;
@ -405,9 +377,9 @@ __strtodg
nf += nz; nf += nz;
nz = 0; nz = 0;
goto have_dig; goto have_dig;
}
goto dig_done;
} }
goto dig_done;
}
for(; c >= '0' && c <= '9'; c = *++s) { for(; c >= '0' && c <= '9'; c = *++s) {
have_dig: have_dig:
nz++; nz++;
@ -423,9 +395,9 @@ __strtodg
else if (nd <= DBL_DIG + 1) else if (nd <= DBL_DIG + 1)
z = 10*z + c; z = 10*z + c;
nz = 0; nz = 0;
}
} }
} }
}/*}*/
dig_done: dig_done:
e = 0; e = 0;
if (c == 'e' || c == 'E') { if (c == 'e' || c == 'E') {
@ -433,7 +405,7 @@ __strtodg
irv = STRTOG_NoNumber; irv = STRTOG_NoNumber;
s = s00; s = s00;
goto ret; goto ret;
} }
s00 = s; s00 = s;
esign = 0; esign = 0;
switch(c = *++s) { switch(c = *++s) {
@ -441,7 +413,7 @@ __strtodg
esign = 1; esign = 1;
case '+': case '+':
c = *++s; c = *++s;
} }
if (c >= '0' && c <= '9') { if (c >= '0' && c <= '9') {
while(c == '0') while(c == '0')
c = *++s; c = *++s;
@ -459,13 +431,13 @@ __strtodg
e = (int)L; e = (int)L;
if (esign) if (esign)
e = -e; e = -e;
} }
else else
e = 0; e = 0;
} }
else else
s = s00; s = s00;
} }
if (!nd) { if (!nd) {
if (!nz && !nz0) { if (!nz && !nz0) {
#ifdef INFNAN_CHECK #ifdef INFNAN_CHECK
@ -480,7 +452,7 @@ __strtodg
++s; ++s;
irv = STRTOG_Infinite; irv = STRTOG_Infinite;
goto infnanexp; goto infnanexp;
} }
break; break;
case 'n': case 'n':
case 'N': case 'N':
@ -492,14 +464,14 @@ __strtodg
irv = hexnan(&s, fpi, bits); irv = hexnan(&s, fpi, bits);
#endif #endif
goto infnanexp; goto infnanexp;
} }
} }
#endif /* INFNAN_CHECK */ #endif /* INFNAN_CHECK */
irv = STRTOG_NoNumber; irv = STRTOG_NoNumber;
s = s00; s = s00;
}
goto ret;
} }
goto ret;
}
irv = STRTOG_Normal; irv = STRTOG_Normal;
e1 = e -= nf; e1 = e -= nf;
@ -513,7 +485,7 @@ __strtodg
break; break;
case FPI_Round_down: case FPI_Round_down:
rd = 1 + sign; rd = 1 + sign;
} }
/* Now we have nd0 digits, starting at s0, followed by a /* Now we have nd0 digits, starting at s0, followed by a
* decimal point, followed by nd-nd0 digits. The number we're * decimal point, followed by nd-nd0 digits. The number we're
@ -523,28 +495,24 @@ __strtodg
if (!nd0) if (!nd0)
nd0 = nd; nd0 = nd;
k = nd < DBL_DIG + 1 ? nd : DBL_DIG + 1; k = nd < DBL_DIG + 1 ? nd : DBL_DIG + 1;
dval(rv) = y; dval(&rv) = y;
if (k > 9) if (k > 9)
dval(rv) = tens[k - 9] * dval(rv) + z; dval(&rv) = tens[k - 9] * dval(&rv) + z;
bd0 = 0; bd0 = 0;
if (nbits <= P && nd <= DBL_DIG) { if (nbits <= P && nd <= DBL_DIG) {
if (!e) { if (!e) {
if (rvOK(dval(rv), fpi, exp, bits, 1, rd, &irv)) if (rvOK(&rv, fpi, exp, bits, 1, rd, &irv))
goto ret; goto ret;
} }
else if (e > 0) { else if (e > 0) {
if (e <= Ten_pmax) { if (e <= Ten_pmax) {
#ifdef VAX i = fivesbits[e] + mantbits(&rv) <= P;
goto vax_ovfl_check; /* rv = */ rounded_product(dval(&rv), tens[e]);
#else if (rvOK(&rv, fpi, exp, bits, i, rd, &irv))
i = fivesbits[e] + mantbits(dval(rv)) <= P;
/* rv = */ rounded_product(dval(rv), tens[e]);
if (rvOK(dval(rv), fpi, exp, bits, i, rd, &irv))
goto ret; goto ret;
e1 -= e; e1 -= e;
goto rv_notOK; goto rv_notOK;
#endif }
}
i = DBL_DIG - nd; i = DBL_DIG - nd;
if (e <= Ten_pmax + i) { if (e <= Ten_pmax + i) {
/* A fancier test would sometimes let us do /* A fancier test would sometimes let us do
@ -552,37 +520,22 @@ __strtodg
*/ */
e2 = e - i; e2 = e - i;
e1 -= i; e1 -= i;
dval(rv) *= tens[i]; dval(&rv) *= tens[i];
#ifdef VAX /* rv = */ rounded_product(dval(&rv), tens[e2]);
/* VAX exponent range is so narrow we must if (rvOK(&rv, fpi, exp, bits, 0, rd, &irv))
* 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)
> Exp_msk1*(DBL_MAX_EXP+Bias-1-P))
goto rv_notOK;
word0(adj) += P*Exp_msk1;
dval(rv) = dval(adj);
#else
/* rv = */ rounded_product(dval(rv), tens[e2]);
#endif
if (rvOK(dval(rv), fpi, exp, bits, 0, rd, &irv))
goto ret; goto ret;
e1 -= e2; e1 -= e2;
}
} }
}
#ifndef Inaccurate_Divide #ifndef Inaccurate_Divide
else if (e >= -Ten_pmax) { else if (e >= -Ten_pmax) {
/* rv = */ rounded_quotient(dval(rv), tens[-e]); /* rv = */ rounded_quotient(dval(&rv), tens[-e]);
if (rvOK(dval(rv), fpi, exp, bits, 0, rd, &irv)) if (rvOK(&rv, fpi, exp, bits, 0, rd, &irv))
goto ret; goto ret;
e1 -= e; e1 -= e;
}
#endif
} }
#endif
}
rv_notOK: rv_notOK:
e1 += nd - k; e1 += nd - k;
@ -591,62 +544,54 @@ __strtodg
e2 = 0; e2 = 0;
if (e1 > 0) { if (e1 > 0) {
if ( (i = e1 & 15) !=0) if ( (i = e1 & 15) !=0)
dval(rv) *= tens[i]; dval(&rv) *= tens[i];
if (e1 &= ~15) { if (e1 &= ~15) {
e1 >>= 4; e1 >>= 4;
while(e1 >= (1 << (n_bigtens-1))) { while(e1 >= (1 << (n_bigtens-1))) {
e2 += ((word0(rv) & Exp_mask) e2 += ((word0(&rv) & Exp_mask)
>> Exp_shift1) - Bias; >> Exp_shift1) - Bias;
word0(rv) &= ~Exp_mask; word0(&rv) &= ~Exp_mask;
word0(rv) |= Bias << Exp_shift1; word0(&rv) |= Bias << Exp_shift1;
dval(rv) *= bigtens[n_bigtens-1]; dval(&rv) *= bigtens[n_bigtens-1];
e1 -= 1 << (n_bigtens-1); e1 -= 1 << (n_bigtens-1);
} }
e2 += ((word0(rv) & Exp_mask) >> Exp_shift1) - Bias; e2 += ((word0(&rv) & Exp_mask) >> Exp_shift1) - Bias;
word0(rv) &= ~Exp_mask; word0(&rv) &= ~Exp_mask;
word0(rv) |= Bias << Exp_shift1; word0(&rv) |= Bias << Exp_shift1;
for(j = 0; e1 > 0; j++, e1 >>= 1) for(j = 0; e1 > 0; j++, e1 >>= 1)
if (e1 & 1) if (e1 & 1)
dval(rv) *= bigtens[j]; dval(&rv) *= bigtens[j];
}
} }
}
else if (e1 < 0) { else if (e1 < 0) {
e1 = -e1; e1 = -e1;
if ( (i = e1 & 15) !=0) if ( (i = e1 & 15) !=0)
dval(rv) /= tens[i]; dval(&rv) /= tens[i];
if (e1 &= ~15) { if (e1 &= ~15) {
e1 >>= 4; e1 >>= 4;
while(e1 >= (1 << (n_bigtens-1))) { while(e1 >= (1 << (n_bigtens-1))) {
e2 += ((word0(rv) & Exp_mask) e2 += ((word0(&rv) & Exp_mask)
>> Exp_shift1) - Bias; >> Exp_shift1) - Bias;
word0(rv) &= ~Exp_mask; word0(&rv) &= ~Exp_mask;
word0(rv) |= Bias << Exp_shift1; word0(&rv) |= Bias << Exp_shift1;
dval(rv) *= tinytens[n_bigtens-1]; dval(&rv) *= tinytens[n_bigtens-1];
e1 -= 1 << (n_bigtens-1); e1 -= 1 << (n_bigtens-1);
} }
e2 += ((word0(rv) & Exp_mask) >> Exp_shift1) - Bias; e2 += ((word0(&rv) & Exp_mask) >> Exp_shift1) - Bias;
word0(rv) &= ~Exp_mask; word0(&rv) &= ~Exp_mask;
word0(rv) |= Bias << Exp_shift1; word0(&rv) |= Bias << Exp_shift1;
for(j = 0; e1 > 0; j++, e1 >>= 1) for(j = 0; e1 > 0; j++, e1 >>= 1)
if (e1 & 1) if (e1 & 1)
dval(rv) *= tinytens[j]; dval(&rv) *= tinytens[j];
}
} }
#ifdef IBM }
/* e2 is a correction to the (base 2) exponent of the return rvb = d2b(dval(&rv), &rve, &rvbits); /* rv = rvb * 2^rve */
* value, reflecting adjustments above to avoid overflow in the
* native arithmetic. For native IBM (base 16) arithmetic, we
* must multiply e2 by 4 to change from base 16 to 2.
*/
e2 <<= 2;
#endif
rvb = d2b(dval(rv), &rve, &rvbits); /* rv = rvb * 2^rve */
rve += e2; rve += e2;
if ((j = rvbits - nbits) > 0) { if ((j = rvbits - nbits) > 0) {
rshift(rvb, j); rshift(rvb, j);
rvbits = nbits; rvbits = nbits;
rve += j; rve += j;
} }
bb0 = 0; /* trailing zero bits in rvb */ bb0 = 0; /* trailing zero bits in rvb */
e2 = rve + rvbits - nbits; e2 = rve + rvbits - nbits;
if (e2 > fpi->emax + 1) if (e2 > fpi->emax + 1)
@ -658,7 +603,7 @@ __strtodg
if (j > 0) { if (j > 0) {
rvb = lshift(rvb, j); rvb = lshift(rvb, j);
rvbits += j; rvbits += j;
} }
else if (j < 0) { else if (j < 0) {
rvbits += j; rvbits += j;
if (rvbits <= 0) { if (rvbits <= 0) {
@ -669,22 +614,22 @@ __strtodg
*exp = emin; *exp = emin;
irv = STRTOG_Underflow | STRTOG_Inexlo; irv = STRTOG_Underflow | STRTOG_Inexlo;
goto ret; goto ret;
}
rvb->x[0] = rvb->wds = rvbits = 1;
} }
rvb->x[0] = rvb->wds = rvbits = 1;
}
else else
rshift(rvb, -j); rshift(rvb, -j);
} }
rve = rve1 = emin; rve = rve1 = emin;
if (sudden_underflow && e2 + 1 < emin) if (sudden_underflow && e2 + 1 < emin)
goto ufl; goto ufl;
} }
/* Now the hard part -- adjusting rv to the correct value.*/ /* Now the hard part -- adjusting rv to the correct value.*/
/* Put digits into bd: true value = bd * 10^e */ /* Put digits into bd: true value = bd * 10^e */
bd0 = s2b(s0, nd0, nd, y); bd0 = s2b(s0, nd0, nd, y, dplen);
for(;;) { for(;;) {
bd = Balloc(bd0->k); bd = Balloc(bd0->k);
@ -698,11 +643,11 @@ __strtodg
if (e >= 0) { if (e >= 0) {
bb2 = bb5 = 0; bb2 = bb5 = 0;
bd2 = bd5 = e; bd2 = bd5 = e;
} }
else { else {
bb2 = bb5 = -e; bb2 = bb5 = -e;
bd2 = bd5 = 0; bd2 = bd5 = 0;
} }
if (bbe >= 0) if (bbe >= 0)
bb2 += bbe; bb2 += bbe;
else else
@ -721,13 +666,13 @@ __strtodg
bb2 -= i; bb2 -= i;
bd2 -= i; bd2 -= i;
bs2 -= i; bs2 -= i;
} }
if (bb5 > 0) { if (bb5 > 0) {
bs = pow5mult(bs, bb5); bs = pow5mult(bs, bb5);
bb1 = mult(bs, bb); bb1 = mult(bs, bb);
Bfree(bb); Bfree(bb);
bb = bb1; bb = bb1;
} }
bb2 -= bb0; bb2 -= bb0;
if (bb2 > 0) if (bb2 > 0)
bb = lshift(bb, bb2); bb = lshift(bb, bb2);
@ -754,7 +699,7 @@ __strtodg
if (dsign != 0) { if (dsign != 0) {
irv |= STRTOG_Inexhi; irv |= STRTOG_Inexhi;
goto adj1; goto adj1;
} }
irv |= STRTOG_Inexlo; irv |= STRTOG_Inexlo;
if (rve1 == emin) if (rve1 == emin)
goto adj1; goto adj1;
@ -762,16 +707,16 @@ __strtodg
i++, j -= ULbits) { i++, j -= ULbits) {
if (rvb->x[i] & ALL_ON) if (rvb->x[i] & ALL_ON)
goto adj1; goto adj1;
} }
if (j > 1 && lo0bits(rvb->x + i) < j - 1) if (j > 1 && lo0bits(rvb->x + i) < j - 1)
goto adj1; goto adj1;
rve = rve1 - 1; rve = rve1 - 1;
rvb = set_ones(rvb, rvbits = nbits); rvb = set_ones(rvb, rvbits = nbits);
break; break;
} }
irv |= dsign ? STRTOG_Inexlo : STRTOG_Inexhi; irv |= dsign ? STRTOG_Inexlo : STRTOG_Inexhi;
break; break;
} }
if (i < 0) { if (i < 0) {
/* Error is less than half an ulp -- check for /* Error is less than half an ulp -- check for
* special case of mantissa a power of two. * special case of mantissa a power of two.
@ -785,9 +730,9 @@ __strtodg
if (cmp(delta, bs) > 0) { if (cmp(delta, bs) > 0) {
irv = STRTOG_Normal | STRTOG_Inexlo; irv = STRTOG_Normal | STRTOG_Inexlo;
goto drop_down; goto drop_down;
}
break;
} }
break;
}
if (i == 0) { if (i == 0) {
/* exactly half-way between */ /* exactly half-way between */
if (dsign) { if (dsign) {
@ -799,9 +744,9 @@ __strtodg
irv = STRTOG_Normal | STRTOG_Inexhi; irv = STRTOG_Normal | STRTOG_Inexhi;
denorm = 0; denorm = 0;
break; break;
}
irv = STRTOG_Normal | STRTOG_Inexlo;
} }
irv = STRTOG_Normal | STRTOG_Inexlo;
}
else if (bbbits == 1) { else if (bbbits == 1) {
irv = STRTOG_Normal; irv = STRTOG_Normal;
drop_down: drop_down:
@ -811,55 +756,53 @@ __strtodg
if (rvb->wds == 1 && rvb->x[0] == 1) if (rvb->wds == 1 && rvb->x[0] == 1)
sudden_underflow = 1; sudden_underflow = 1;
break; break;
} }
rve -= nbits; rve -= nbits;
rvb = set_ones(rvb, rvbits = nbits); rvb = set_ones(rvb, rvbits = nbits);
break; break;
} }
else else
irv = STRTOG_Normal | STRTOG_Inexhi; irv = STRTOG_Normal | STRTOG_Inexhi;
if ((bbbits < nbits && !denorm) || !(rvb->x[0] & 1)) if ((bbbits < nbits && !denorm) || !(rvb->x[0] & 1))
break; break;
if (dsign) { if (dsign) {
rvb = increment(rvb); rvb = increment(rvb);
if ( (j = rvbits & kmask) !=0) j = kmask & (ULbits - (rvbits & kmask));
j = ULbits - j; if (hi0bits(rvb->x[rvb->wds - 1]) != j)
if (hi0bits(rvb->x[(rvb->wds - 1) >> kshift])
!= j)
rvbits++; rvbits++;
irv = STRTOG_Normal | STRTOG_Inexhi; irv = STRTOG_Normal | STRTOG_Inexhi;
} }
else { else {
if (bbbits == 1) if (bbbits == 1)
goto undfl; goto undfl;
decrement(rvb); decrement(rvb);
irv = STRTOG_Normal | STRTOG_Inexlo; irv = STRTOG_Normal | STRTOG_Inexlo;
}
break;
} }
if ((dval(adj) = ratio(delta, bs)) <= 2.) { break;
}
if ((dval(&adj) = ratio(delta, bs)) <= 2.) {
adj1: adj1:
inex = STRTOG_Inexlo; inex = STRTOG_Inexlo;
if (dsign) { if (dsign) {
asub = 0; asub = 0;
inex = STRTOG_Inexhi; inex = STRTOG_Inexhi;
} }
else if (denorm && bbbits <= 1) { else if (denorm && bbbits <= 1) {
undfl: undfl:
rvb->wds = 0; rvb->wds = 0;
rve = emin; rve = emin;
irv = STRTOG_Underflow | STRTOG_Inexlo; irv = STRTOG_Underflow | STRTOG_Inexlo;
break; break;
}
adj0 = dval(adj) = 1.;
} }
adj0 = dval(&adj) = 1.;
}
else { else {
adj0 = dval(adj) *= 0.5; adj0 = dval(&adj) *= 0.5;
if (dsign) { if (dsign) {
asub = 0; asub = 0;
inex = STRTOG_Inexlo; inex = STRTOG_Inexlo;
} }
if (dval(adj) < 2147483647.) { if (dval(&adj) < 2147483647.) {
L = adj0; L = adj0;
adj0 -= L; adj0 -= L;
switch(rd) { switch(rd) {
@ -876,22 +819,22 @@ __strtodg
inc_L: inc_L:
L++; L++;
inex = STRTOG_Inexact - inex; inex = STRTOG_Inexact - inex;
} }
}
dval(adj) = L;
} }
dval(&adj) = L;
} }
}
y = rve + rvbits; y = rve + rvbits;
/* adj *= ulp(dval(rv)); */ /* adj *= ulp(&rv); */
/* if (asub) rv -= adj; else rv += adj; */ /* if (asub) rv -= adj; else rv += adj; */
if (!denorm && rvbits < nbits) { if (!denorm && rvbits < nbits) {
rvb = lshift(rvb, j = nbits - rvbits); rvb = lshift(rvb, j = nbits - rvbits);
rve -= j; rve -= j;
rvbits = nbits; rvbits = nbits;
} }
ab = d2b(dval(adj), &abe, &abits); ab = d2b(dval(&adj), &abe, &abits);
if (abe < 0) if (abe < 0)
rshift(ab, -abe); rshift(ab, -abe);
else if (abe > 0) else if (abe > 0)
@ -911,15 +854,15 @@ __strtodg
if (rve1 == emin) { if (rve1 == emin) {
--rvbits; --rvbits;
denorm = 1; denorm = 1;
} }
else { else {
rvb = lshift(rvb, 1); rvb = lshift(rvb, 1);
--rve; --rve;
--rve1; --rve1;
L = finished = 0; L = finished = 0;
}
} }
} }
}
else { else {
rvb = sum(rvb, ab); rvb = sum(rvb, ab);
k = rvb->wds - 1; k = rvb->wds - 1;
@ -928,15 +871,15 @@ __strtodg
if (denorm) { if (denorm) {
if (++rvbits == nbits) if (++rvbits == nbits)
denorm = 0; denorm = 0;
} }
else { else {
rshift(rvb, 1); rshift(rvb, 1);
rve++; rve++;
rve1++; rve1++;
L = 0; L = 0;
}
} }
} }
}
Bfree(ab); Bfree(ab);
Bfree(rvb0); Bfree(rvb0);
if (finished) if (finished)
@ -945,32 +888,32 @@ __strtodg
z = rve + rvbits; z = rve + rvbits;
if (y == z && L) { if (y == z && L) {
/* Can we stop now? */ /* Can we stop now? */
tol = dval(adj) * 5e-16; /* > max rel error */ tol = dval(&adj) * 5e-16; /* > max rel error */
dval(adj) = adj0 - .5; dval(&adj) = adj0 - .5;
if (dval(adj) < -tol) { if (dval(&adj) < -tol) {
if (adj0 > tol) { if (adj0 > tol) {
irv |= inex; irv |= inex;
break; break;
}
}
else if (dval(adj) > tol && adj0 < 1. - tol) {
irv |= inex;
break;
} }
} }
else if (dval(&adj) > tol && adj0 < 1. - tol) {
irv |= inex;
break;
}
}
bb0 = denorm ? 0 : trailz(rvb); bb0 = denorm ? 0 : trailz(rvb);
Bfree(bb); Bfree(bb);
Bfree(bd); Bfree(bd);
Bfree(bs); Bfree(bs);
Bfree(delta); Bfree(delta);
} }
if (!denorm && (j = nbits - rvbits)) { if (!denorm && (j = nbits - rvbits)) {
if (j > 0) if (j > 0)
rvb = lshift(rvb, j); rvb = lshift(rvb, j);
else else
rshift(rvb, -j); rshift(rvb, -j);
rve -= j; rve -= j;
} }
*exp = rve; *exp = rve;
Bfree(bb); Bfree(bb);
Bfree(bd); Bfree(bd);
@ -978,28 +921,52 @@ __strtodg
Bfree(bd0); Bfree(bd0);
Bfree(delta); Bfree(delta);
if (rve > fpi->emax) { if (rve > fpi->emax) {
switch(fpi->rounding & 3) {
case FPI_Round_near:
goto huge;
case FPI_Round_up:
if (!sign)
goto huge;
break;
case FPI_Round_down:
if (sign)
goto huge;
}
/* Round to largest representable magnitude */
Bfree(rvb);
rvb = 0;
irv = STRTOG_Normal | STRTOG_Inexlo;
*exp = fpi->emax;
b = bits;
be = b + ((fpi->nbits + 31) >> 5);
while(b < be)
*b++ = -1;
if ((j = fpi->nbits & 0x1f))
*--be >>= (32 - j);
goto ret;
huge: huge:
rvb->wds = 0; rvb->wds = 0;
irv = STRTOG_Infinite | STRTOG_Overflow | STRTOG_Inexhi; irv = STRTOG_Infinite | STRTOG_Overflow | STRTOG_Inexhi;
#ifndef NO_ERRNO SET_ERRNO(ERANGE);
errno = ERANGE;
#endif
infnanexp: infnanexp:
*exp = fpi->emax + 1; *exp = fpi->emax + 1;
} }
ret: ret:
if (denorm) { if (denorm) {
if (sudden_underflow) { if (sudden_underflow) {
rvb->wds = 0; rvb->wds = 0;
irv = STRTOG_Underflow | STRTOG_Inexlo; irv = STRTOG_Underflow | STRTOG_Inexlo;
} SET_ERRNO(ERANGE);
}
else { else {
irv = (irv & ~STRTOG_Retmask) | irv = (irv & ~STRTOG_Retmask) |
(rvb->wds > 0 ? STRTOG_Denormal : STRTOG_Zero); (rvb->wds > 0 ? STRTOG_Denormal : STRTOG_Zero);
if (irv & STRTOG_Inexact) if (irv & STRTOG_Inexact) {
irv |= STRTOG_Underflow; irv |= STRTOG_Underflow;
SET_ERRNO(ERANGE);
} }
} }
}
if (se) if (se)
*se = (char *)s; *se = (char *)s;
if (sign) if (sign)
@ -1007,6 +974,6 @@ __strtodg
if (rvb) { if (rvb) {
copybits(bits, nbits, rvb); copybits(bits, nbits, rvb);
Bfree(rvb); Bfree(rvb);
}
return irv;
} }
return irv;
}

View File

@ -37,12 +37,7 @@ THIS SOFTWARE.
#include "gdtoaimp.h" #include "gdtoaimp.h"
double double __strtod (const char *s, char **sp)
#ifdef KR_headers
__strtod(s, sp) CONST char *s; char **sp;
#else
__strtod(CONST char *s, char **sp)
#endif
{ {
static FPI fpi = { 53, 1-1023-53+1, 2046-1023-53+1, 1, SI }; static FPI fpi = { 53, 1-1023-53+1, 2046-1023-53+1, 1, SI };
ULong bits[2]; ULong bits[2];
@ -80,8 +75,8 @@ __strtod(CONST char *s, char **sp)
case STRTOG_NaNbits: case STRTOG_NaNbits:
u.L[_0] = 0x7ff00000 | bits[1]; u.L[_0] = 0x7ff00000 | bits[1];
u.L[_1] = bits[0]; u.L[_1] = bits[0];
} }
if (k & STRTOG_Neg) if (k & STRTOG_Neg)
u.L[_0] |= 0x80000000L; u.L[_0] |= 0x80000000L;
return u.d; return u.d;
} }

View File

@ -31,20 +31,20 @@ THIS SOFTWARE.
#include "gdtoaimp.h" #include "gdtoaimp.h"
float float __strtof (const char *s, char **sp)
#ifdef KR_headers
__strtof(s, sp) CONST char *s; char **sp;
#else
__strtof(CONST char *s, char **sp)
#endif
{ {
static FPI fpi = { 24, 1-127-24+1, 254-127-24+1, 1, SI }; static FPI fpi0 = { 24, 1-127-24+1, 254-127-24+1, 1, SI };
ULong bits[1]; ULong bits[1];
Long exp; Long exp;
int k; int k;
union { ULong L[1]; float f; } u; union { ULong L[1]; float f; } u = { { 0 } };
#ifdef Honor_FLT_ROUNDS
#include "gdtoa_fltrnds.h"
#else
#define fpi &fpi0
#endif
k = __strtodg(s, sp, &fpi, &exp, bits); k = __strtodg(s, sp, fpi, &exp, bits);
switch(k & STRTOG_Retmask) { switch(k & STRTOG_Retmask) {
case STRTOG_NoNumber: case STRTOG_NoNumber:
case STRTOG_Zero: case STRTOG_Zero:
@ -53,7 +53,7 @@ __strtof(CONST char *s, char **sp)
case STRTOG_Normal: case STRTOG_Normal:
case STRTOG_NaNbits: case STRTOG_NaNbits:
u.L[0] = (bits[0] & 0x7fffff) | (exp + 0x7f + 23) << 23; u.L[0] = (bits[0] & 0x7fffff) | ((exp + 0x7f + 23) << 23);
break; break;
case STRTOG_Denormal: case STRTOG_Denormal:
@ -66,11 +66,11 @@ __strtof(CONST char *s, char **sp)
case STRTOG_NaN: case STRTOG_NaN:
u.L[0] = f_QNAN; u.L[0] = f_QNAN;
} }
if (k & STRTOG_Neg) if (k & STRTOG_Neg)
u.L[0] |= 0x80000000L; u.L[0] |= 0x80000000L;
return u.f; return u.f;
} }
float __cdecl float __cdecl
strtof (const char * __restrict__ src, char ** __restrict__ endptr) strtof (const char * __restrict__ src, char ** __restrict__ endptr)

View File

@ -51,20 +51,26 @@ THIS SOFTWARE.
#define _4 0 #define _4 0
#endif #endif
static int typedef union lD {
#ifdef KR_headers UShort L[5];
__strtopx(s, sp, V) CONST char *s; char **sp; long double *V; long double D;
#else } lD;
__strtopx(CONST char *s, char **sp, long double *V)
#endif static int __strtopx (const char *s, char **sp, lD *V)
{ {
static FPI fpi = { 64, 1-16383-64+1, 32766 - 16383 - 64 + 1, 1, SI }; static FPI fpi0 = { 64, 1-16383-64+1, 32766 - 16383 - 64 + 1, 1, SI };
ULong bits[2]; ULong bits[2];
Long exp; Long exp;
int k; int k;
UShort *L = (UShort*)V; UShort *L = & (V->L[0]);
#ifdef Honor_FLT_ROUNDS
#include "gdtoa_fltrnds.h"
#else
#define fpi &fpi0
#endif
V->D = 0.0L;
k = __strtodg(s, sp, &fpi, &exp, bits); k = __strtodg(s, sp, fpi, &exp, bits);
switch(k & STRTOG_Retmask) { switch(k & STRTOG_Retmask) {
case STRTOG_NoNumber: case STRTOG_NoNumber:
case STRTOG_Zero: case STRTOG_Zero:
@ -97,23 +103,22 @@ __strtopx(CONST char *s, char **sp, long double *V)
L[2] = ldus_QNAN2; L[2] = ldus_QNAN2;
L[3] = ldus_QNAN3; L[3] = ldus_QNAN3;
L[4] = ldus_QNAN4; L[4] = ldus_QNAN4;
} }
if (k & STRTOG_Neg) if (k & STRTOG_Neg)
L[_0] |= 0x8000; L[_0] |= 0x8000;
return k; return k;
}
long double
__cdecl
__strtold (const char * __restrict__ src, char ** __restrict__ endptr)
{
long double ret;
__strtopx(src, endptr, &ret);
return ret;
} }
long double long double __cdecl
__cdecl __strtold (const char * __restrict__ src, char ** __restrict__ endptr)
{
lD ret;
ret.D = 0.0L;
__strtopx(src, endptr, &ret);
return ret.D;
}
long double __cdecl
strtold (const char * __restrict__ src, char ** __restrict__ endptr) strtold (const char * __restrict__ src, char ** __restrict__ endptr)
__attribute__((alias("__strtold"))); __attribute__((alias("__strtold")));

View File

@ -31,12 +31,7 @@ THIS SOFTWARE.
#include "gdtoaimp.h" #include "gdtoaimp.h"
Bigint * Bigint *sum (Bigint *a, Bigint *b)
#ifdef KR_headers
sum(a, b) Bigint *a; Bigint *b;
#else
sum(Bigint *a, Bigint *b)
#endif
{ {
Bigint *c; Bigint *c;
ULong carry, *xc, *xa, *xb, *xe, y; ULong carry, *xc, *xa, *xb, *xe, y;
@ -46,7 +41,7 @@ sum(Bigint *a, Bigint *b)
if (a->wds < b->wds) { if (a->wds < b->wds) {
c = b; b = a; a = c; c = b; b = a; a = c;
} }
c = Balloc(a->k); c = Balloc(a->k);
c->wds = a->wds; c->wds = a->wds;
carry = 0; carry = 0;
@ -61,8 +56,7 @@ sum(Bigint *a, Bigint *b)
z = (*xa++ >> 16) + (*xb++ >> 16) + carry; z = (*xa++ >> 16) + (*xb++ >> 16) + carry;
carry = (z & 0x10000) >> 16; carry = (z & 0x10000) >> 16;
Storeinc(xc, z, y); Storeinc(xc, z, y);
} } while(xc < xe);
while(xc < xe);
xe += a->wds - b->wds; xe += a->wds - b->wds;
while(xc < xe) { while(xc < xe) {
y = (*xa & 0xffff) + carry; y = (*xa & 0xffff) + carry;
@ -70,20 +64,19 @@ sum(Bigint *a, Bigint *b)
z = (*xa++ >> 16) + carry; z = (*xa++ >> 16) + carry;
carry = (z & 0x10000) >> 16; carry = (z & 0x10000) >> 16;
Storeinc(xc, z, y); Storeinc(xc, z, y);
} }
#else #else
do { do {
y = *xa++ + *xb++ + carry; y = *xa++ + *xb++ + carry;
carry = (y & 0x10000) >> 16; carry = (y & 0x10000) >> 16;
*xc++ = y & 0xffff; *xc++ = y & 0xffff;
} } while(xc < xe);
while(xc < xe);
xe += a->wds - b->wds; xe += a->wds - b->wds;
while(xc < xe) { while(xc < xe) {
y = *xa++ + carry; y = *xa++ + carry;
carry = (y & 0x10000) >> 16; carry = (y & 0x10000) >> 16;
*xc++ = y & 0xffff; *xc++ = y & 0xffff;
} }
#endif #endif
if (carry) { if (carry) {
if (c->wds == c->maxwds) { if (c->wds == c->maxwds) {
@ -91,8 +84,8 @@ sum(Bigint *a, Bigint *b)
Bcopy(b, c); Bcopy(b, c);
Bfree(c); Bfree(c);
c = b; c = b;
}
c->x[c->wds++] = 1;
} }
return c; c->x[c->wds++] = 1;
} }
return c;
}

View File

@ -31,40 +31,31 @@ THIS SOFTWARE.
#include "gdtoaimp.h" #include "gdtoaimp.h"
double double ulp (dbl_union *x)
ulp
#ifdef KR_headers
(x) double x;
#else
(double x)
#endif
{ {
Long L; Long L;
double a; union _dbl_union a;
L = (word0(x) & Exp_mask) - (P-1)*Exp_msk1; L = (word0(x) & Exp_mask) - (P-1)*Exp_msk1;
#ifndef Sudden_Underflow #ifndef Sudden_Underflow
if (L > 0) { if (L > 0) {
#endif #endif
#ifdef IBM word0(&a) = L;
L |= Exp_msk1 >> 4; word1(&a) = 0;
#endif
word0(a) = L;
word1(a) = 0;
#ifndef Sudden_Underflow #ifndef Sudden_Underflow
} }
else { else {
L = -L >> Exp_shift; L = -L >> Exp_shift;
if (L < Exp_shift) { if (L < Exp_shift) {
word0(a) = 0x80000 >> L; word0(&a) = 0x80000 >> L;
word1(a) = 0; word1(&a) = 0;
} }
else { else {
word0(a) = 0; word0(&a) = 0;
L -= Exp_shift; L -= Exp_shift;
word1(a) = L >= 31 ? 1 : 1 << (31 - L); word1(&a) = L >= 31 ? 1 : 1 << (31 - L);
}
} }
#endif
return a;
} }
#endif
return dval(&a);
}