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>
* include/stdlib.h (_wtof): Define.

View File

@ -56,7 +56,9 @@ two letters:
whose sum is the desired value
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
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
style and conversions with direction of rounding specified (so that, if
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
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
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 "
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"
char *
#ifdef KR_headers
rv_alloc(i) int i;
#else
rv_alloc(int i)
#ifndef MULTIPLE_THREADS
char *dtoa_result;
#endif
char *rv_alloc (int i)
{
int j, k, *r;
@ -54,12 +53,7 @@ rv_alloc(int i)
(char *)(r+1);
}
char *
#ifdef KR_headers
nrv_alloc(s, rve, n) char *s, **rve; int n;
#else
nrv_alloc(char *s, char **rve, int n)
#endif
char *nrv_alloc (char *s, char **rve, int n)
{
char *rv, *t;
@ -77,12 +71,7 @@ nrv_alloc(char *s, char **rve, int n)
* when MULTIPLE_THREADS is not defined.
*/
void
#ifdef KR_headers
__freedtoa(s) char *s;
#else
__freedtoa(char *s)
#endif
void __freedtoa (char *s)
{
Bigint *b = (Bigint *)((int *)s - 1);
b->maxwds = 1 << (b->k = *(int*)b);
@ -93,13 +82,7 @@ __freedtoa(char *s)
#endif
}
int
quorem
#ifdef KR_headers
(b, S) Bigint *b, *S;
#else
(Bigint *b, Bigint *S)
#endif
int quorem (Bigint *b, Bigint *S)
{
int n;
ULong *bx, *bxe, q, *sx, *sxe;
@ -157,8 +140,8 @@ quorem
*bx++ = y & 0xffff;
#endif
#endif
}
while(sx <= sxe);
} while(sx <= sxe);
if (!*bxe) {
bx = b->x;
while(--bxe > bx && !*bxe)
@ -166,6 +149,7 @@ quorem
b->wds = n;
}
}
if (cmp(b, S) >= 0) {
q++;
borrow = 0;
@ -198,8 +182,8 @@ quorem
*bx++ = y & 0xffff;
#endif
#endif
}
while(sx <= sxe);
} while(sx <= sxe);
bx = b->x;
bxe = bx + n;
if (!*bxe) {

View File

@ -66,21 +66,13 @@ THIS SOFTWARE.
*/
#ifdef Honor_FLT_ROUNDS
#define Rounding rounding
#undef Check_FLT_ROUNDS
#define Check_FLT_ROUNDS
#else
#define Rounding Flt_Rounds
#endif
char *
__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
char *__dtoa (double d0, int mode, int ndigits, int *decpt, int *sign, char **rve)
{
/* Arguments ndigits, decpt, sign are similar to those
of ecvt and fcvt; trailing zeros are suppressed from
@ -116,7 +108,7 @@ __dtoa
to hold the suppressed trailing zeros.
*/
int bbits, b2, b5, be, dig, i, ieps, ilim = 0, ilim0, ilim1 = 0,
int bbits, b2, b5, be, dig, i, ieps, ilim, ilim0, ilim1,
j, j1, k, k0, k_check, leftright, m2, m5, s2, s5,
spec_case, try_quick;
Long L;
@ -125,14 +117,25 @@ __dtoa
ULong x;
#endif
Bigint *b, *b1, *delta, *mlo, *mhi, *S;
double d2, ds, eps;
union _dbl_union d, d2, eps;
double ds;
char *s, *s0;
#ifdef Honor_FLT_ROUNDS
int rounding;
#endif
#ifdef SET_INEXACT
int inexact, oldinexact;
#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
if (dtoa_result) {
@ -140,35 +143,24 @@ __dtoa
dtoa_result = 0;
}
#endif
if (word0(d) & Sign_bit) {
d.d = d0;
if (word0(&d) & Sign_bit) {
/* set sign for everything, including 0's and NaNs */
*sign = 1;
word0(d) &= ~Sign_bit; /* clear sign bit */
word0(&d) &= ~Sign_bit; /* clear sign bit */
}
else
*sign = 0;
#if defined(IEEE_Arith) + defined(VAX)
#ifdef IEEE_Arith
if ((word0(d) & Exp_mask) == Exp_mask)
#else
if (word0(d) == 0x8000)
#endif
if ((word0(&d) & Exp_mask) == Exp_mask)
{
/* Infinity or NaN */
*decpt = 9999;
#ifdef IEEE_Arith
if (!word1(d) && !(word0(d) & 0xfffff))
if (!word1(&d) && !(word0(&d) & 0xfffff))
return nrv_alloc("Infinity", rve, 8);
#endif
return nrv_alloc("NaN", rve, 3);
}
#endif
#ifdef IBM
dval(d) += 0; /* normalize */
#endif
if (!dval(d)) {
if (!dval(&d)) {
*decpt = 1;
return nrv_alloc("0", rve, 1);
}
@ -178,35 +170,31 @@ __dtoa
inexact = 1;
#endif
#ifdef Honor_FLT_ROUNDS
if ((rounding = Flt_Rounds) >= 2) {
if (Rounding >= 2) {
if (*sign)
rounding = rounding == 2 ? 0 : 2;
Rounding = Rounding == 2 ? 0 : 2;
else
if (rounding != 2)
rounding = 0;
if (Rounding != 2)
Rounding = 0;
}
#endif
b = d2b(dval(d), &be, &bbits);
b = d2b(dval(&d), &be, &bbits);
#ifdef Sudden_Underflow
i = (int)(word0(d) >> Exp_shift1 & (Exp_mask>>Exp_shift1));
i = (int)(word0(&d) >> Exp_shift1 & (Exp_mask>>Exp_shift1));
#else
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;
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;
/* log(x) ~=~ log(1.5) + (x-1.5)/1.5
* log10(x) = log(x) / 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
* + ( (d2-1.5)*0.289529654602168 + 0.176091259055681 );
@ -224,10 +212,6 @@ __dtoa
*/
i -= Bias;
#ifdef IBM
i <<= 2;
i += j;
#endif
#ifndef Sudden_Underflow
denorm = 0;
}
@ -235,21 +219,21 @@ __dtoa
/* d is denormalized */
i = bbits + be + (Bias + (P-1) - 1);
x = i > 32 ? word0(d) << (64 - i) | word1(d) >> (i - 32)
: word1(d) << (32 - i);
dval(d2) = x;
word0(d2) -= 31*Exp_msk1; /* adjust exponent */
x = i > 32 ? word0(&d) << (64 - i) | word1(&d) >> (i - 32)
: word1(&d) << (32 - i);
dval(&d2) = x;
word0(&d2) -= 31*Exp_msk1; /* adjust exponent */
i -= (Bias + (P-1) - 1) + 1;
denorm = 1;
}
#endif
ds = (dval(d2)-1.5)*0.289529654602168 + 0.1760912590558 + i*0.301029995663981;
ds = (dval(&d2)-1.5)*0.289529654602168 + 0.1760912590558 + i*0.301029995663981;
k = (int)ds;
if (ds < 0. && ds != k)
k--; /* want k = floor(ds) */
k_check = 1;
if (k >= 0 && k <= Ten_pmax) {
if (dval(d) < tens[k])
if (dval(&d) < tens[k])
k--;
k_check = 0;
}
@ -288,10 +272,11 @@ __dtoa
try_quick = 0;
}
leftright = 1;
ilim = ilim1 = -1; /* Values for cases 0 and 1; done here to */
/* silence erroneous "gcc -Wall" warning. */
switch(mode) {
case 0:
case 1:
ilim = ilim1 = -1;
i = 18;
ndigits = 0;
break;
@ -316,7 +301,7 @@ __dtoa
s = s0 = rv_alloc(i);
#ifdef Honor_FLT_ROUNDS
if (mode > 1 && rounding != 1)
if (mode > 1 && Rounding != 1)
leftright = 0;
#endif
@ -325,7 +310,7 @@ __dtoa
/* Try to get by with floating-point arithmetic. */
i = 0;
dval(d2) = dval(d);
dval(&d2) = dval(&d);
k0 = k;
ilim0 = ilim;
ieps = 2; /* conservative */
@ -335,7 +320,7 @@ __dtoa
if (j & Bletch) {
/* prevent overflows */
j &= Bletch - 1;
dval(d) /= bigtens[n_bigtens-1];
dval(&d) /= bigtens[n_bigtens-1];
ieps++;
}
for(; j; j >>= 1, i++)
@ -343,32 +328,32 @@ __dtoa
ieps++;
ds *= bigtens[i];
}
dval(d) /= ds;
dval(&d) /= ds;
}
else if (( j1 = -k )!=0) {
dval(d) *= tens[j1 & 0xf];
dval(&d) *= tens[j1 & 0xf];
for(j = j1 >> 4; j; j >>= 1, i++)
if (j & 1) {
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)
goto fast_failed;
ilim = ilim1;
k--;
dval(d) *= 10.;
dval(&d) *= 10.;
ieps++;
}
dval(eps) = ieps*dval(d) + 7.;
word0(eps) -= (P-1)*Exp_msk1;
dval(&eps) = ieps*dval(&d) + 7.;
word0(&eps) -= (P-1)*Exp_msk1;
if (ilim == 0) {
S = mhi = 0;
dval(d) -= 5.;
if (dval(d) > dval(eps))
dval(&d) -= 5.;
if (dval(&d) > dval(&eps))
goto one_digit;
if (dval(d) < -dval(eps))
if (dval(&d) < -dval(&eps))
goto no_digits;
goto fast_failed;
}
@ -377,34 +362,34 @@ __dtoa
/* Use Steele & White method of only
* generating digits needed.
*/
dval(eps) = 0.5/tens[ilim-1] - dval(eps);
dval(&eps) = 0.5/tens[ilim-1] - dval(&eps);
for(i = 0;;) {
L = dval(d);
dval(d) -= L;
L = dval(&d);
dval(&d) -= L;
*s++ = '0' + (int)L;
if (dval(d) < dval(eps))
if (dval(&d) < dval(&eps))
goto ret1;
if (1. - dval(d) < dval(eps))
if (1. - dval(&d) < dval(&eps))
goto bump_up;
if (++i >= ilim)
break;
dval(eps) *= 10.;
dval(d) *= 10.;
dval(&eps) *= 10.;
dval(&d) *= 10.;
}
}
else {
#endif
/* Generate ilim digits, then fix them up. */
dval(eps) *= tens[ilim-1];
for(i = 1;; i++, dval(d) *= 10.) {
L = (Long)(dval(d));
if (!(dval(d) -= L))
dval(&eps) *= tens[ilim-1];
for(i = 1;; i++, dval(&d) *= 10.) {
L = (Long)(dval(&d));
if (!(dval(&d) -= L))
ilim = i;
*s++ = '0' + (int)L;
if (i == ilim) {
if (dval(d) > 0.5 + dval(eps))
if (dval(&d) > 0.5 + dval(&eps))
goto bump_up;
else if (dval(d) < 0.5 - dval(eps)) {
else if (dval(&d) < 0.5 - dval(&eps)) {
while(*--s == '0');
s++;
goto ret1;
@ -417,7 +402,7 @@ __dtoa
#endif
fast_failed:
s = s0;
dval(d) = dval(d2);
dval(&d) = dval(&d2);
k = k0;
ilim = ilim0;
}
@ -429,22 +414,22 @@ __dtoa
ds = tens[k];
if (ndigits < 0 && ilim <= 0) {
S = mhi = 0;
if (ilim < 0 || dval(d) <= 5*ds)
if (ilim < 0 || dval(&d) <= 5*ds)
goto no_digits;
goto one_digit;
}
for(i = 1;; i++, dval(d) *= 10.) {
L = (Long)(dval(d) / ds);
dval(d) -= L*ds;
for(i = 1;; i++, dval(&d) *= 10.) {
L = (Long)(dval(&d) / ds);
dval(&d) -= L*ds;
#ifdef Check_FLT_ROUNDS
/* If FLT_ROUNDS == 2, L will usually be high by 1 */
if (dval(d) < 0) {
if (dval(&d) < 0) {
L--;
dval(d) += ds;
dval(&d) += ds;
}
#endif
*s++ = '0' + (int)L;
if (!dval(d)) {
if (!dval(&d)) {
#ifdef SET_INEXACT
inexact = 0;
#endif
@ -453,13 +438,13 @@ __dtoa
if (i == ilim) {
#ifdef Honor_FLT_ROUNDS
if (mode > 1)
switch(rounding) {
switch(Rounding) {
case 0: goto ret1;
case 2: goto bump_up;
}
#endif
dval(d) += dval(d);
if (dval(d) > ds || (dval(d) == ds && L & 1)) {
dval(&d) += dval(&d);
if (dval(&d) > ds || (dval(&d) == ds && L & 1)) {
bump_up:
while(*--s == '9')
if (s == s0) {
@ -483,11 +468,7 @@ __dtoa
#ifndef Sudden_Underflow
denorm ? be + (Bias + (P-1) - 1 + 1) :
#endif
#ifdef IBM
1 + 4*P - 3 - bbits + ((bbits + be - 1) & 3);
#else
1 + P - bbits;
#endif
b2 += i;
s2 += i;
mhi = i2b(1);
@ -521,12 +502,12 @@ __dtoa
spec_case = 0;
if ((mode < 2 || leftright)
#ifdef Honor_FLT_ROUNDS
&& rounding == 1
&& Rounding == 1
#endif
) {
if (!word1(d) && !(word0(d) & Bndry_mask)
if (!word1(&d) && !(word0(&d) & Bndry_mask)
#ifndef Sudden_Underflow
&& word0(d) & (Exp_mask & ~Exp_msk1)
&& word0(&d) & (Exp_mask & ~Exp_msk1)
#endif
) {
/* The special case */
@ -612,9 +593,9 @@ __dtoa
j1 = delta->sign ? 1 : cmp(b, delta);
Bfree(delta);
#ifndef ROUND_BIASED
if (j1 == 0 && mode != 1 && !(word1(d) & 1)
if (j1 == 0 && mode != 1 && !(word1(&d) & 1)
#ifdef Honor_FLT_ROUNDS
&& rounding >= 1
&& Rounding >= 1
#endif
) {
if (dig == '9')
@ -631,7 +612,7 @@ __dtoa
#endif
if (j < 0 || (j == 0 && mode != 1
#ifndef ROUND_BIASED
&& !(word1(d) & 1)
&& !(word1(&d) & 1)
#endif
)) {
if (!b->x[0] && b->wds <= 1) {
@ -642,7 +623,7 @@ __dtoa
}
#ifdef Honor_FLT_ROUNDS
if (mode > 1)
switch(rounding) {
switch(Rounding) {
case 0: goto accept_dig;
case 2: goto keep_dig;
}
@ -660,7 +641,7 @@ __dtoa
}
if (j1 > 0) {
#ifdef Honor_FLT_ROUNDS
if (!rounding)
if (!Rounding)
goto accept_dig;
#endif
if (dig == '9') { /* possible if i == 1 */
@ -703,7 +684,7 @@ __dtoa
/* Round off last digit */
#ifdef Honor_FLT_ROUNDS
switch(rounding) {
switch(Rounding) {
case 0: goto trimzeros;
case 2: goto roundoff;
}
@ -721,7 +702,9 @@ __dtoa
++*s++;
}
else {
// trimzeros:
#ifdef Honor_FLT_ROUNDS
trimzeros:
#endif
while(*--s == '0');
s++;
}
@ -736,9 +719,9 @@ __dtoa
#ifdef SET_INEXACT
if (inexact) {
if (!oldinexact) {
word0(d) = Exp_1 + (70 << Exp_shift);
word1(d) = 0;
dval(d) += 1.;
word0(&d) = Exp_1 + (70 << Exp_shift);
word1(&d) = 0;
dval(&d) += 1.;
}
}
else if (!oldinexact)

View File

@ -35,26 +35,48 @@ THIS SOFTWARE.
#include "locale.h"
#endif
char *
#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
char *__g__fmt (char *b, char *s, char *se, int decpt, ULong sign, size_t blen)
{
int i, j, k;
char *s0 = s;
char *be, *s0;
size_t len;
#ifdef USE_LOCALE
char decimalpoint = *localeconv()->decimal_point;
#ifdef NO_LOCALE_CACHE
char *decimalpoint = localeconv()->decimal_point;
size_t dlen = strlen(decimalpoint);
#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
#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)
*b++ = '-';
if (decpt <= -4 || decpt > se - s + 5) {
*b++ = *s++;
if (*s) {
*b++ = decimalpoint;
#ifdef USE_LOCALE
while((*b = *decimalpoint++))
++b;
#else
*b++ = '.';
#endif
while((*b = *s++) !=0)
b++;
}
@ -69,6 +91,8 @@ __g__fmt(char *b, char *s, char *se, int decpt, ULong sign)
for(j = 2, k = 10; 10*k <= decpt; j++, k *= 10){}
for(;;) {
i = decpt / k;
if (b >= be)
goto ret0;
*b++ = i + '0';
if (--j <= 0)
break;
@ -78,7 +102,14 @@ __g__fmt(char *b, char *s, char *se, int decpt, ULong sign)
*b = 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++)
*b++ = '0';
while((*b = *s++) != 0)
@ -87,13 +118,25 @@ __g__fmt(char *b, char *s, char *se, int decpt, ULong sign)
else {
while((*b = *s++) != 0) {
b++;
if (--decpt == 0 && *s)
*b++ = decimalpoint;
if (--decpt == 0 && *s) {
#ifdef USE_LOCALE
while((*b = *decimalpoint++))
++b;
#else
*b++ = '.';
#endif
}
}
if (b + decpt > be) {
ret0:
b = 0;
goto ret;
}
for(; decpt > 0; decpt--)
*b++ = '0';
*b = 0;
}
ret:
__freedtoa(s0);
return b;
}

View File

@ -31,17 +31,17 @@ THIS SOFTWARE.
#include "gdtoaimp.h"
char*
#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
char *__g_dfmt (char *buf, double *d, int ndig, size_t bufsize)
{
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;
ULong bits[2], *L, sign;
int decpt, ex, i, mode;
#ifdef Honor_FLT_ROUNDS
#include "gdtoa_fltrnds.h"
#else
#define fpi &fpi0
#endif
if (ndig < 0)
ndig = 0;
@ -52,6 +52,8 @@ __g_dfmt(char *buf, double *d, int ndig, unsigned bufsize)
sign = L[_0] & 0x80000000L;
if ((L[_0] & 0x7ff00000) == 0x7ff00000) {
/* Infinity or NaN */
if (bufsize < 10)
return 0;
if (L[_0] & 0xfffff || L[_1]) {
return strcp(buf, "NaN");
}
@ -78,12 +80,9 @@ __g_dfmt(char *buf, double *d, int ndig, unsigned bufsize)
ex = 1;
ex -= 0x3ff + 52;
mode = 2;
if (ndig <= 0) {
if (bufsize < 25)
return 0;
if (ndig <= 0)
mode = 0;
}
i = STRTOG_Normal;
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

@ -31,17 +31,17 @@ THIS SOFTWARE.
#include "gdtoaimp.h"
char*
#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
char *__g_ffmt (char *buf, float *f, int ndig, size_t bufsize)
{
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;
ULong bits[1], *L, sign;
int decpt, ex, i, mode;
#ifdef Honor_FLT_ROUNDS
#include "gdtoa_fltrnds.h"
#else
#define fpi &fpi0
#endif
if (ndig < 0)
ndig = 0;
@ -83,6 +83,6 @@ __g_ffmt(char *buf, float *f, int ndig, unsigned bufsize)
mode = 0;
}
i = STRTOG_Normal;
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

@ -51,20 +51,21 @@ THIS SOFTWARE.
#define _4 0
#endif
char*
#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
char *__g_xfmt (char *buf, void *V, int ndig, size_t bufsize)
{
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;
ULong bits[2], sign;
UShort *L;
int decpt, ex, i, mode;
#if defined(__MINGW32__) || defined(__MINGW64__)
int fptype = __fpclassifyl (*(long double*) V);
#endif /* MinGW */
#ifdef Honor_FLT_ROUNDS
#include "gdtoa_fltrnds.h"
#else
#define fpi &fpi0
#endif
if (ndig < 0)
ndig = 0;
@ -74,14 +75,13 @@ __g_xfmt(char *buf, void *V, int ndig, unsigned bufsize)
L = (UShort *)V;
sign = L[_0] & 0x8000;
ex = L[_0] & 0x7fff;
bits[1] = (L[_1] << 16) | L[_2];
bits[0] = (L[_3] << 16) | L[_4];
if (fptype & FP_NAN) /* NaN or Inf */
{
if (fptype & FP_NORMAL)
{
#if defined(__MINGW32__) || defined(__MINGW64__)
if (fptype & FP_NAN) {
/* NaN or Inf */
if (fptype & FP_NORMAL) {
b = buf;
*b++ = sign ? '-': '+';
strncpy (b, "Infinity", ndig ? ndig : 8);
@ -90,19 +90,38 @@ __g_xfmt(char *buf, void *V, int ndig, unsigned bufsize)
strncpy (buf, "NaN", ndig ? ndig : 3);
return (buf + strlen (buf));
}
else if (fptype & FP_NORMAL) /* Normal or subnormal */
{
if (fptype & FP_ZERO)
{
else if (fptype & FP_NORMAL) {
/* Normal or subnormal */
if (fptype & FP_ZERO) {
i = STRTOG_Denormal;
ex = 1;
}
else
i = STRTOG_Normal;
}
#else
if (ex != 0) {
if (ex == 0x7fff) {
/* Infinity or NaN */
if (bits[0] | bits[1])
b = strcp(buf, "NaN");
else {
i = STRTOG_Zero;
b = buf;
if (sign)
*b++ = '-';
b = strcp(b, "Infinity");
}
return b;
}
i = STRTOG_Normal;
}
else if (bits[0] | bits[1]) {
i = STRTOG_Denormal;
ex = 1;
}
#endif
else {
/* i = STRTOG_Zero; */
b = buf;
#ifndef IGNORE_ZERO_SIGN
if (sign)
@ -112,7 +131,6 @@ __g_xfmt(char *buf, void *V, int ndig, unsigned bufsize)
*b = 0;
return b;
}
ex -= 0x3fff + 63;
mode = 2;
if (ndig <= 0) {
@ -120,6 +138,6 @@ __g_xfmt(char *buf, void *V, int ndig, unsigned bufsize)
return 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 Arith_Kind_ASL 1
#define Double_Align
#ifdef _WIN64
#define X64_bit_pointers
#endif /* w64 */

View File

@ -31,12 +31,7 @@ THIS SOFTWARE.
#include "gdtoaimp.h"
static Bigint *
#ifdef KR_headers
bitstob(bits, nbits, bbits) ULong *bits; int nbits; int *bbits;
#else
bitstob(ULong *bits, int nbits, int *bbits)
#endif
static Bigint *bitstob (ULong *bits, int nbits, int *bbits)
{
int i, k;
Bigint *b;
@ -108,15 +103,8 @@ bitstob(ULong *bits, int nbits, int *bbits)
* calculation.
*/
char *
__gdtoa
#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
char *__gdtoa (FPI *fpi, int be, ULong *bits, int *kindp, int mode, int ndigits,
int *decpt, char **rve)
{
/* Arguments ndigits and decpt are similar to the second and third
arguments of ecvt and fcvt; trailing zeros are suppressed from
@ -152,13 +140,14 @@ __gdtoa
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 rdir, s2, s5, spec_case, try_quick;
Long L;
Bigint *b, *b1, *delta, *mlo, *mhi, *mhi1, *S;
double d, d2, ds, eps;
double d2, ds;
char *s, *s0;
union _dbl_union d, eps;
#ifndef MULTIPLE_THREADS
if (dtoa_result) {
@ -197,21 +186,17 @@ __gdtoa
return nrv_alloc("0", rve, 1);
}
dval(d) = b2d(b, &i);
dval(&d) = b2d(b, &i);
i = be + bbits - 1;
word0(d) &= Frac_mask1;
word0(d) |= Exp_11;
#ifdef IBM
if ( (j = 11 - hi0bits(word0(d) & Frac_mask)) !=0)
dval(d) /= 1 << j;
#endif
word0(&d) &= Frac_mask1;
word0(&d) |= Exp_11;
/* log(x) ~=~ log(1.5) + (x-1.5)/1.5
* log10(x) = log(x) / 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
* + ( (d2-1.5)*0.289529654602168 + 0.176091259055681 );
@ -227,11 +212,7 @@ __gdtoa
* (We could get a more accurate k by invoking log10,
* but this is probably not worthwhile.)
*/
#ifdef IBM
i <<= 2;
i += j;
#endif
ds = (dval(d)-1.5)*0.289529654602168 + 0.1760912590558 + i*0.301029995663981;
ds = (dval(&d)-1.5)*0.289529654602168 + 0.1760912590558 + i*0.301029995663981;
/* correct assumption about exponent range */
if ((j = i) < 0)
@ -243,16 +224,9 @@ __gdtoa
if (ds < 0. && ds != k)
k--; /* want k = floor(ds) */
k_check = 1;
#ifdef IBM
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
word0(&d) += (be + bbits - 1) << Exp_shift;
if (k >= 0 && k <= Ten_pmax) {
if (dval(d) < tens[k])
if (dval(&d) < tens[k])
k--;
k_check = 0;
}
@ -283,10 +257,11 @@ __gdtoa
try_quick = 0;
}
leftright = 1;
ilim = ilim1 = -1; /* Values for cases 0 and 1; done here to */
/* silence erroneous "gcc -Wall" warning. */
switch(mode) {
case 0:
case 1:
ilim = ilim1 = -1;
i = (int)(nbits * .30103) + 3;
ndigits = 0;
break;
@ -328,11 +303,7 @@ __gdtoa
/* Try to get by with floating-point arithmetic. */
i = 0;
d2 = dval(d);
#ifdef IBM
if ( (j = 11 - hi0bits(word0(d) & Frac_mask)) !=0)
dval(d) /= 1 << j;
#endif
d2 = dval(&d);
k0 = k;
ilim0 = ilim;
ieps = 2; /* conservative */
@ -342,7 +313,7 @@ __gdtoa
if (j & Bletch) {
/* prevent overflows */
j &= Bletch - 1;
dval(d) /= bigtens[n_bigtens-1];
dval(&d) /= bigtens[n_bigtens-1];
ieps++;
}
for(; j; j >>= 1, i++)
@ -354,30 +325,30 @@ __gdtoa
else {
ds = 1.;
if ( (j1 = -k) !=0) {
dval(d) *= tens[j1 & 0xf];
dval(&d) *= tens[j1 & 0xf];
for(j = j1 >> 4; j; j >>= 1, i++)
if (j & 1) {
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)
goto fast_failed;
ilim = ilim1;
k--;
dval(d) *= 10.;
dval(&d) *= 10.;
ieps++;
}
dval(eps) = ieps*dval(d) + 7.;
word0(eps) -= (P-1)*Exp_msk1;
dval(&eps) = ieps*dval(&d) + 7.;
word0(&eps) -= (P-1)*Exp_msk1;
if (ilim == 0) {
S = mhi = 0;
dval(d) -= 5.;
if (dval(d) > dval(eps))
dval(&d) -= 5.;
if (dval(&d) > dval(&eps))
goto one_digit;
if (dval(d) < -dval(eps))
if (dval(&d) < -dval(&eps))
goto no_digits;
goto fast_failed;
}
@ -386,42 +357,40 @@ __gdtoa
/* Use Steele & White method of only
* 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;;) {
L = (Long)(dval(d)/ds);
dval(d) -= L*ds;
L = (Long)(dval(&d)/ds);
dval(&d) -= L*ds;
*s++ = '0' + (int)L;
if (dval(d) < dval(eps)) {
if (dval(d))
if (dval(&d) < dval(&eps)) {
if (dval(&d))
inex = STRTOG_Inexlo;
goto ret1;
}
if (ds - dval(d) < dval(eps))
if (ds - dval(&d) < dval(&eps))
goto bump_up;
if (++i >= ilim)
break;
dval(eps) *= 10.;
dval(d) *= 10.;
dval(&eps) *= 10.;
dval(&d) *= 10.;
}
}
else {
#endif
/* Generate ilim digits, then fix them up. */
dval(eps) *= tens[ilim-1];
for(i = 1;; i++, dval(d) *= 10.) {
if ( (L = (Long)(dval(d)/ds)) !=0)
dval(d) -= L*ds;
dval(&eps) *= tens[ilim-1];
for(i = 1;; i++, dval(&d) *= 10.) {
if ( (L = (Long)(dval(&d)/ds)) !=0)
dval(&d) -= L*ds;
*s++ = '0' + (int)L;
if (i == ilim) {
ds *= 0.5;
if (dval(d) > ds + dval(eps))
if (dval(&d) > ds + dval(&eps))
goto bump_up;
else if (dval(d) < ds - dval(eps)) {
while(*--s == '0'){}
s++;
if (dval(d))
else if (dval(&d) < ds - dval(&eps)) {
if (dval(&d))
inex = STRTOG_Inexlo;
goto ret1;
goto clear_trailing0;
}
break;
}
@ -431,7 +400,7 @@ __gdtoa
#endif
fast_failed:
s = s0;
dval(d) = d2;
dval(&d) = d2;
k = k0;
ilim = ilim0;
}
@ -443,22 +412,22 @@ __gdtoa
ds = tens[k];
if (ndigits < 0 && ilim <= 0) {
S = mhi = 0;
if (ilim < 0 || dval(d) <= 5*ds)
if (ilim < 0 || dval(&d) <= 5*ds)
goto no_digits;
goto one_digit;
}
for(i = 1;; i++, dval(d) *= 10.) {
L = dval(d) / ds;
dval(d) -= L*ds;
for(i = 1;; i++, dval(&d) *= 10.) {
L = dval(&d) / ds;
dval(&d) -= L*ds;
#ifdef Check_FLT_ROUNDS
/* If FLT_ROUNDS == 2, L will usually be high by 1 */
if (dval(d) < 0) {
if (dval(&d) < 0) {
L--;
dval(d) += ds;
dval(&d) += ds;
}
#endif
*s++ = '0' + (int)L;
if (dval(d) == 0.)
if (dval(&d) == 0.)
break;
if (i == ilim) {
if (rdir) {
@ -467,8 +436,8 @@ __gdtoa
inex = STRTOG_Inexlo;
goto ret1;
}
dval(d) += dval(d);
if (dval(d) > ds || (dval(d) == ds && L & 1)) {
dval(&d) += dval(&d);
if (dval(&d) > ds || (dval(&d) == ds && L & 1)) {
bump_up:
inex = STRTOG_Inexhi;
while(*--s == '9')
@ -479,8 +448,12 @@ __gdtoa
}
++*s++;
}
else
else {
inex = STRTOG_Inexlo;
clear_trailing0:
while(*--s == '0'){}
++s;
}
break;
}
}
@ -558,28 +531,11 @@ __gdtoa
* and for all and pass them and a shift to quorem, so it
* can do shifts and ors to compute the numerator for q.
*/
#ifdef Pack_32
if ( (i = ((s5 ? 32 - hi0bits(S->x[S->wds-1]) : 1) + s2) & 0x1f) !=0)
i = 32 - i;
#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;
i = ((s5 ? hi0bits(S->x[S->wds-1]) : ULbits - 1) - s2 - 4) & kmask;
m2 += i;
s2 += i;
}
else if (i < 4) {
i += 28;
b2 += i;
m2 += i;
s2 += i;
}
if (b2 > 0)
if ((b2 += i) > 0)
b = lshift(b, b2);
if (s2 > 0)
if ((s2 += i) > 0)
S = lshift(S, s2);
if (k_check) {
if (cmp(b,S) < 0) {
@ -738,7 +694,7 @@ __gdtoa
if (b->wds > 1 || b->x[0])
inex = STRTOG_Inexlo;
while(*--s == '0'){}
s++;
++s;
}
ret:
Bfree(S);

View File

@ -36,6 +36,15 @@ THIS SOFTWARE.
#define GDTOA_H_INCLUDED
#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
#define Long long
@ -47,24 +56,6 @@ typedef unsigned Long ULong;
typedef unsigned short UShort;
#endif
#ifndef ANSI
#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_Normal = 1,
@ -77,9 +68,9 @@ typedef unsigned short UShort;
/* The following may be or-ed into one of the above values. */
STRTOG_Neg = 0x08,
STRTOG_Inexlo = 0x10,
STRTOG_Inexhi = 0x20,
STRTOG_Neg = 0x08, /* does not affect STRTOG_Inexlo or STRTOG_Inexhi */
STRTOG_Inexlo = 0x10, /* returned result rounded toward zero */
STRTOG_Inexhi = 0x20, /* returned result rounded away from zero */
STRTOG_Inexact = 0x30,
STRTOG_Underflow= 0x40,
STRTOG_Overflow = 0x80
@ -105,21 +96,21 @@ enum { /* FPI.rounding values: same as FLT_ROUNDS */
extern "C" {
#endif
extern char* __dtoa ANSI((double d, int mode, int ndigits, int *decpt,
int *sign, char **rve));
extern char* __gdtoa ANSI((FPI *fpi, int be, ULong *bits, int *kindp,
int mode, int ndigits, int *decpt, char **rve));
extern void __freedtoa ANSI((char*));
extern char* __dtoa (double d, int mode, int ndigits, int *decpt,
int *sign, char **rve);
extern char* __gdtoa (FPI *fpi, int be, ULong *bits, int *kindp,
int mode, int ndigits, int *decpt, char **rve);
extern void __freedtoa (char *);
extern int __strtodg ANSI((CONST char*, char**, FPI*, Long*, ULong*));
extern float __strtof ANSI((CONST char *, char **));
extern double __strtod ANSI((CONST char *, char **));
extern long double strtold ANSI((CONST char *, char **));
extern float __strtof (const char *, char **);
extern double __strtod (const char *, char **);
extern long double __strtold (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_dfmt ANSI((char*, double*, int, unsigned));
extern char* __g_ffmt ANSI((char*, float*, int, unsigned));
extern char* __g_xfmt ANSI((char*, void*, int, unsigned));
extern char* __g__fmt (char*, char*, char*, int, ULong, size_t);
extern char* __g_dfmt (char*, double*, int, size_t);
extern char* __g_ffmt (char*, float*, int, size_t);
extern char* __g_xfmt (char*, void*, int, size_t);
#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.
Copyright (C) 1998-2008 by Lucent Technologies
Copyright (C) 1998-2000 by Lucent Technologies
All Rights Reserved
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
* 8-byte pointers, PRIVATE_MEM >= 7400 appears to suffice; with
* 4-byte pointers, PRIVATE_MEM >= 7112 appears adequate.
* #define INFNAN_CHECK on IEEE systems to cause strtod to check for
* Infinity and NaN (case insensitively).
* #define NO_INFNAN_CHECK if you do not wish to have INFNAN_CHECK
* #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,
* strtodg also accepts (case insensitively) strings of the form
* NaN(x), where x is a string of hexadecimal digits and spaces;
* if there is only one string of hexadecimal digits, it is taken
* for the fraction bits of the resulting NaN; if there are two or
* more strings of hexadecimal digits, each string is assigned
* to the next available sequence of 32-bit words of fractions
* bits (starting with the most significant), right-aligned in
* each sequence.
* NaN(x), where x is a string of hexadecimal digits (optionally
* preceded by 0x or 0X) and spaces; if there is only one string
* of hexadecimal digits, it is taken for the fraction bits of the
* resulting NaN; if there are two or more strings of hexadecimal
* digits, each string is assigned to the next available sequence
* of 32-bit words of fractions bits (starting with the most
* 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
* multiple threads. In this case, you must provide (or suitably
* #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.
* On some K&R systems, it may also be necessary to
* #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.
*/
@ -170,9 +170,15 @@ THIS SOFTWARE.
#include "gdtoa.h"
#include "gd_qnan.h"
#define INFNAN_CHECK 1
#if defined(__MINGW32__) || defined(__MINGW64__)
#define MULTIPLE_THREADS 1
#define USE_LOCALE 1
#define NO_LOCALE_CACHE 1
#endif /* MinGW */
#ifdef Honor_FLT_ROUNDS
#include <fenv.h>
#endif
#ifdef DEBUG
#include <stdio.h>
@ -182,14 +188,8 @@ THIS SOFTWARE.
#include <stdlib.h>
#include <string.h>
#ifdef KR_headers
#define Char char
#else
#define Char void
#endif
#ifdef MALLOC
extern Char *MALLOC ANSI((size_t));
extern void *MALLOC (size_t);
#else
#define MALLOC malloc
#endif
@ -204,6 +204,14 @@ extern Char *MALLOC ANSI((size_t));
#endif
#include <errno.h>
#ifdef NO_ERRNO
#define SET_ERRNO(x)
#else
#define SET_ERRNO(x) \
errno = (x)
#endif
#ifdef Bad_float_h
#ifdef IEEE_Arith
@ -264,27 +272,16 @@ extern "C" {
Exactly one of IEEE_8087, IEEE_MC68k, VAX, or IBM should be defined.
#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
#define word0(x) ((ULong *)&x)[1]
#define word1(x) ((ULong *)&x)[0]
#define word0(x) (x)->L[1]
#define word1(x) (x)->L[0]
#else
#define word0(x) ((ULong *)&x)[0]
#define word1(x) ((ULong *)&x)[1]
#define word0(x) (x)->L[0]
#define word1(x) (x)->L[1]
#endif
#else /* !YES_ALIAS */
#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 */
#define dval(x) (x)->d
/* The following definition of Storeinc is appropriate for MIPS processors.
* 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
#define rounded_product(a,b) a = rnd_prod(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);
#endif
#else
#define rounded_product(a,b) a *= b
#define rounded_quotient(a,b) a /= b
@ -458,7 +451,7 @@ extern double rnd_prod(double, double), rnd_quot(double, double);
#define FREE_DTOA_LOCK(n) /*nothing*/
#endif
#define Kmax 15
#define Kmax 9
#define Bigint __Bigint
struct
@ -467,14 +460,13 @@ Bigint {
int k, maxwds, sign, wds;
ULong x[1];
};
typedef struct Bigint Bigint;
#ifdef NO_STRING_H
#ifdef DECLARE_SIZE_T
typedef unsigned int size_t;
#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))
#else /* !NO_STRING_H */
#define Bcopy(x,y) memcpy(&x->sign,&y->sign,y->wds*sizeof(ULong) + 2*sizeof(int))
@ -544,47 +536,47 @@ __hi0bits_D2A (ULong y)
#define ulp __ulp_D2A
extern char *dtoa_result;
extern CONST double bigtens[], tens[], tinytens[];
extern const double bigtens[], tens[], tinytens[];
extern unsigned char hexdig[];
extern Bigint *Balloc ANSI((int));
extern void Bfree ANSI((Bigint*));
extern void ULtof ANSI((ULong*, ULong*, Long, int));
extern void ULtod ANSI((ULong*, ULong*, Long, int));
extern void ULtodd ANSI((ULong*, ULong*, Long, int));
extern void ULtoQ ANSI((ULong*, ULong*, Long, int));
extern void ULtox ANSI((UShort*, ULong*, Long, int));
extern void ULtoxL ANSI((ULong*, ULong*, Long, int));
extern ULong any_on ANSI((Bigint*, int));
extern double b2d ANSI((Bigint*, int*));
extern int cmp ANSI((Bigint*, Bigint*));
extern void copybits ANSI((ULong*, int, Bigint*));
extern Bigint *d2b ANSI((double, int*, int*));
extern int decrement ANSI((Bigint*));
extern Bigint *diff ANSI((Bigint*, Bigint*));
extern int gethex ANSI((CONST char**, FPI*, Long*, Bigint**, int));
extern void hexdig_init_D2A(Void);
extern int hexnan ANSI((CONST char**, FPI*, ULong*));
extern int hi0bits_D2A ANSI((ULong));
extern Bigint *i2b ANSI((int));
extern Bigint *increment ANSI((Bigint*));
extern int lo0bits ANSI((ULong*));
extern Bigint *lshift ANSI((Bigint*, int));
extern int match ANSI((CONST char**, char*));
extern Bigint *mult ANSI((Bigint*, Bigint*));
extern Bigint *multadd ANSI((Bigint*, int, int));
extern char *nrv_alloc ANSI((char*, char **, int));
extern Bigint *pow5mult ANSI((Bigint*, int));
extern int quorem ANSI((Bigint*, Bigint*));
extern double ratio ANSI((Bigint*, Bigint*));
extern void rshift ANSI((Bigint*, int));
extern char *rv_alloc ANSI((int));
extern Bigint *s2b ANSI((CONST char*, int, int, ULong));
extern Bigint *set_ones ANSI((Bigint*, int));
extern char *strcp ANSI((char*, const char*));
extern Bigint *sum ANSI((Bigint*, Bigint*));
extern int trailz ANSI((Bigint*));
extern double ulp ANSI((double));
extern Bigint *Balloc (int);
extern void Bfree (Bigint*);
extern void ULtof (ULong*, ULong*, Long, int);
extern void ULtod (ULong*, ULong*, Long, int);
extern void ULtodd (ULong*, ULong*, Long, int);
extern void ULtoQ (ULong*, ULong*, Long, int);
extern void ULtox (UShort*, ULong*, Long, int);
extern void ULtoxL (ULong*, ULong*, Long, int);
extern ULong any_on (Bigint*, int);
extern double b2d (Bigint*, int*);
extern int cmp (Bigint*, Bigint*);
extern void copybits (ULong*, int, Bigint*);
extern Bigint *d2b (double, int*, int*);
extern void decrement (Bigint*);
extern Bigint *diff (Bigint*, Bigint*);
extern int gethex (const char**, FPI*, Long*, Bigint**, int);
extern void hexdig_init_D2A(void);
extern int hexnan (const char**, FPI*, ULong*);
extern int hi0bits_D2A (ULong);
extern Bigint *i2b (int);
extern Bigint *increment (Bigint*);
extern int lo0bits (ULong*);
extern Bigint *lshift (Bigint*, int);
extern int match (const char**, char*);
extern Bigint *mult (Bigint*, Bigint*);
extern Bigint *multadd (Bigint*, int, int);
extern char *nrv_alloc (char*, char **, int);
extern Bigint *pow5mult (Bigint*, int);
extern int quorem (Bigint*, Bigint*);
extern double ratio (Bigint*, Bigint*);
extern void rshift (Bigint*, int);
extern char *rv_alloc (int);
extern Bigint *s2b (const char*, int, int, ULong, int);
extern Bigint *set_ones (Bigint*, int);
extern char *strcp (char*, const char*);
extern Bigint *sum (Bigint*, Bigint*);
extern int trailz (Bigint*);
extern double ulp (dbl_union *);
#ifdef __cplusplus
}
@ -599,6 +591,10 @@ __hi0bits_D2A (ULong y)
* (On HP Series 700/800 machines, -DNAN_WORD0=0x7ff40000 works.)
*/
#ifdef IEEE_Arith
#ifndef NO_INFNAN_CHECK
#undef INFNAN_CHECK
#define INFNAN_CHECK
#endif
#ifdef IEEE_MC68k
#define _0 0
#define _1 1

View File

@ -35,29 +35,38 @@ THIS SOFTWARE.
#include "locale.h"
#endif
int
#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
int gethex (const char **sp, FPI *fpi, Long *exp, Bigint **bp, int sign)
{
Bigint *b;
CONST unsigned char *decpt, *s0, *s, *s1;
int esign, havedig, irv, k, n, nbits, up, zret;
const unsigned char *decpt, *s0, *s, *s1;
int big, esign, havedig, irv, j, k, n, n0, nbits, up, zret;
ULong L, lostbits, *x;
Long e, e1;
#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
#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
if (!hexdig['0'])
hexdig_init_D2A();
*bp = 0;
havedig = 0;
s0 = *(CONST unsigned char **)sp + 2;
s0 = *(const unsigned char **)sp + 2;
while(s0[havedig] == '0')
havedig++;
s0 += havedig;
@ -65,11 +74,21 @@ gethex( CONST char **sp, FPI *fpi, Long *exp, Bigint **bp, int sign)
decpt = 0;
zret = 0;
e = 0;
if (!hexdig[*s]) {
if (hexdig[*s])
havedig++;
else {
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;
decpt = ++s;
#endif
if (!hexdig[*s])
goto pcheck;
while(*s == '0')
@ -81,19 +100,28 @@ gethex( CONST char **sp, FPI *fpi, Long *exp, Bigint **bp, int sign)
}
while(hexdig[*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;
#endif
while(hexdig[*s])
s++;
}
}/*}*/
if (decpt)
e = -(((Long)(s-decpt)) << 2);
pcheck:
s1 = s;
big = esign = 0;
switch(*s) {
case 'p':
case 'P':
esign = 0;
switch(*++s) {
case '-':
esign = 1;
@ -106,26 +134,87 @@ gethex( CONST char **sp, FPI *fpi, Long *exp, Bigint **bp, int sign)
break;
}
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;
}
if (esign)
e1 = -e1;
e += e1;
}
*sp = (char*)s;
if (!havedig)
*sp = (char*)s0 - 1;
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;
for(k = 0; n > 7; n >>= 1)
for(k = 0; n > (1 << (kshift-2)) - 1; n >>= 1)
k++;
b = Balloc(k);
x = b->x;
n = 0;
L = 0;
#ifdef USE_LOCALE
for(i = 0; decimalpoint[i+1]; ++i);
#endif
while(s1 > s0) {
if (*--s1 == decimalpoint)
#ifdef USE_LOCALE
if (*--s1 == decimalpoint[i]) {
s1 -= i;
continue;
if (n == 32) {
}
#else
if (*--s1 == '.')
continue;
#endif
if (n == ULbits) {
*x++ = L;
L = 0;
n = 0;
@ -135,7 +224,7 @@ gethex( CONST char **sp, FPI *fpi, Long *exp, Bigint **bp, int sign)
}
*x++ = L;
b->wds = n = x - b->x;
n = 32*n - hi0bits(L);
n = ULbits*n - hi0bits(L);
nbits = fpi->nbits;
lostbits = 0;
x = b->x;
@ -146,7 +235,7 @@ gethex( CONST char **sp, FPI *fpi, Long *exp, Bigint **bp, int sign)
k = n - 1;
if (x[k>>kshift] & 1 << (k & kmask)) {
lostbits = 2;
if (k > 1 && any_on(b,k-1))
if (k > 0 && any_on(b,k))
lostbits = 3;
}
}
@ -162,7 +251,8 @@ gethex( CONST char **sp, FPI *fpi, Long *exp, Bigint **bp, int sign)
if (e > fpi->emax) {
ovfl:
Bfree(b);
*bp = 0;
ovfl1:
SET_ERRNO(ERANGE);
return STRTOG_Infinite | STRTOG_Overflow | STRTOG_Inexhi;
}
irv = STRTOG_Normal;
@ -182,15 +272,18 @@ gethex( CONST char **sp, FPI *fpi, Long *exp, Bigint **bp, int sign)
case FPI_Round_down:
if (sign) {
one_bit:
*exp = fpi->emin;
x[0] = b->wds = 1;
dret:
*bp = b;
*exp = fpi->emin;
SET_ERRNO(ERANGE);
return STRTOG_Denormal | STRTOG_Inexhi
| STRTOG_Underflow;
}
}
Bfree(b);
*bp = 0;
retz:
SET_ERRNO(ERANGE);
return STRTOG_Zero | STRTOG_Inexlo | STRTOG_Underflow;
}
k = n - 1;
@ -211,7 +304,7 @@ gethex( CONST char **sp, FPI *fpi, Long *exp, Bigint **bp, int sign)
break;
case FPI_Round_near:
if (lostbits & 2
&& (lostbits & 1) | (x[0] & 1))
&& (lostbits | x[0]) & 1)
up = 1;
break;
case FPI_Round_up:

View File

@ -31,12 +31,7 @@ THIS SOFTWARE.
#include "gdtoaimp.h"
void
#ifdef KR_headers
rshift(b, k) Bigint *b; int k;
#else
rshift(Bigint *b, int k)
#endif
void rshift (Bigint *b, int k)
{
ULong *x, *x1, *xe, y;
int n;
@ -64,12 +59,7 @@ rshift(Bigint *b, int k)
b->x[0] = 0;
}
int
#ifdef KR_headers
trailz(b) Bigint *b;
#else
trailz(Bigint *b)
#endif
int trailz (Bigint *b)
{
ULong L, *x, *xe;
int n = 0;

View File

@ -33,20 +33,14 @@ THIS SOFTWARE.
unsigned char hexdig[256];
static void
#ifdef KR_headers
htinit(h, s, inc) unsigned char *h; unsigned char *s; int inc;
#else
htinit(unsigned char *h, unsigned char *s, int inc)
#endif
static void htinit (unsigned char *h, unsigned char *s, int inc)
{
int i, j;
for(i = 0; (j = s[i]) !=0; i++)
h[j] = i + inc;
}
void
hexdig_init_D2A(Void)
void hexdig_init_D2A (void)
{
#define USC (unsigned char *)
htinit(hexdig, USC "0123456789", 0x10);

View File

@ -31,12 +31,7 @@ THIS SOFTWARE.
#include "gdtoaimp.h"
static void
#ifdef KR_headers
L_shift(x, x1, i) ULong *x; ULong *x1; int i;
#else
L_shift(ULong *x, ULong *x1, int i)
#endif
static void L_shift (ULong *x, ULong *x1, int i)
{
int j;
@ -49,16 +44,10 @@ L_shift(ULong *x, ULong *x1, int i)
} while(++x < x1);
}
int
#ifdef KR_headers
hexnan(sp, fpi, x0)
CONST char **sp; FPI *fpi; ULong *x0;
#else
hexnan( CONST char **sp, FPI *fpi, ULong *x0)
#endif
int hexnan (const char **sp, FPI *fpi, ULong *x0)
{
ULong c, h, *x, *x1, *xe;
CONST char *s;
const char *s;
int havedig, hd0, i, nbits;
if (!hexdig['0'])
@ -71,7 +60,13 @@ hexnan( CONST char **sp, FPI *fpi, ULong *x0)
x1 = xe = x;
havedig = hd0 = i = 0;
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 (c <= ' ') {
if (hd0 < havedig) {
@ -86,12 +81,25 @@ hexnan( CONST char **sp, FPI *fpi, ULong *x0)
x1 = x;
i = 0;
}
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) {
*sp = s + 1;
break;
}
#ifndef GDTOA_NON_PEDANTIC_NANCHECK
do {
if (/*(*/ c == ')') {
*sp = s + 1;
break;
}
} while((c = *++s));
#endif
return STRTOG_NaN;
}
havedig++;

View File

@ -30,9 +30,9 @@ THIS SOFTWARE.
* with " at " changed at "@" and " dot " changed to "."). */
#ifdef __MINGW32__
/* we have to include windows.h before gdtoa headers, otherwise
defines cause conflicts. */
#if defined(__MINGW32__) || defined(__MINGW64__)
/* we have to include windows.h before gdtoa
headers, otherwise defines cause conflicts. */
#define WIN32_LEAN_AND_MEAN
#include <windows.h>
@ -47,7 +47,8 @@ static long dtoa_sl[NLOCKS];
Sleep (0);
#define FREE_DTOA_LOCK(n) InterlockedExchange (&dtoa_sl[n], 0);
#else
#else /* USE_WIN32_SL */
#include <stdlib.h>
static CRITICAL_SECTION dtoa_CritSec[NLOCKS];
static long dtoa_CS_init = 0;
@ -56,12 +57,10 @@ static long dtoa_CS_init = 0;
2 = initialized
3 = deleted
*/
static void dtoa_lock_cleanup()
static void dtoa_lock_cleanup (void)
{
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++)
DeleteCriticalSection (&dtoa_CritSec[i]);
@ -70,17 +69,13 @@ static void dtoa_lock_cleanup()
static void dtoa_lock (int n)
{
if (2 == dtoa_CS_init)
{
if (2 == dtoa_CS_init) {
EnterCriticalSection (&dtoa_CritSec[n]);
return;
}
else if (0 == dtoa_CS_init)
{
else if (0 == dtoa_CS_init) {
long last_CS_init = InterlockedExchange (&dtoa_CS_init, 1);
if (0 == last_CS_init)
{
if (0 == last_CS_init) {
int i;
for (i = 0; i < NLOCKS; i++)
InitializeCriticalSection (&dtoa_CritSec[i]);
@ -107,16 +102,12 @@ static void dtoa_unlock(int n)
#define ACQUIRE_DTOA_LOCK(n) dtoa_lock(n)
#define FREE_DTOA_LOCK(n) dtoa_unlock(n)
#endif
#endif /* USE_WIN32_SL */
#endif /* __MINGW32__ */
#endif /* __MINGW32__ / __MINGW64__ */
#include "gdtoaimp.h"
#ifndef MULTIPLE_THREADS
char *dtoa_result;
#endif
static Bigint *freelist[Kmax+1];
#ifndef Omit_Private_Memory
#ifndef PRIVATE_MEM
@ -126,13 +117,7 @@ static void dtoa_unlock(int n)
static double private_mem[PRIVATE_mem], *pmem_next = private_mem;
#endif
Bigint *
Balloc
#ifdef KR_headers
(k) int k;
#else
(int k)
#endif
Bigint *Balloc (int k)
{
int x;
Bigint *rv;
@ -141,7 +126,9 @@ Balloc
#endif
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;
}
else {
@ -151,7 +138,7 @@ Balloc
#else
len = (sizeof(Bigint) + (x-1)*sizeof(ULong) + sizeof(double) - 1)
/sizeof(double);
if (pmem_next - private_mem + len <= PRIVATE_mem) {
if (k <= Kmax && pmem_next - private_mem + len <= PRIVATE_mem) {
rv = (Bigint*)pmem_next;
pmem_next += len;
}
@ -166,36 +153,29 @@ Balloc
return rv;
}
void
Bfree
#ifdef KR_headers
(v) Bigint *v;
#else
(Bigint *v)
#endif
void Bfree (Bigint *v)
{
if (v) {
if (v->k > Kmax)
free((void*)v);
else {
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
// shifted.
// With __GNUC__, we use an inline wrapper for __builtin_clz()
/* lo0bits(): Shift y so lowest bit is 1 and return the
* number of bits y was shifted.
* With GCC, we use an inline wrapper for __builtin_clz()
*/
#ifndef __GNUC__
int
lo0bits
#ifdef KR_headers
(y) ULong *y;
#else
(ULong *y)
#endif
int lo0bits (ULong *y)
{
register int k;
register ULong x = *y;
int k;
ULong x = *y;
if (x & 7) {
if (x & 1)
@ -233,16 +213,9 @@ lo0bits
*y = x;
return k;
}
#endif /* __GNUC__ */
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
Bigint *multadd (Bigint *b, int m, int a) /* multiply by m and add a */
{
int i, wds;
#ifdef ULLong
@ -278,8 +251,7 @@ multadd
*x++ = y & 0xffff;
#endif
#endif
}
while(++i < wds);
} while(++i < wds);
if (carry) {
if (wds >= b->maxwds) {
b1 = Balloc(b->k+1);
@ -293,17 +265,13 @@ multadd
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__
int
hi0bits_D2A
#ifdef KR_headers
(x) register ULong x;
#else
(register ULong x)
#endif
int hi0bits_D2A (ULong x)
{
register int k = 0;
int k = 0;
if (!(x & 0xffff0000)) {
k = 16;
@ -328,16 +296,9 @@ hi0bits_D2A
}
return k;
}
#endif /* __GNUC__ */
#endif
Bigint *
i2b
#ifdef KR_headers
(i) int i;
#else
(int i)
#endif
Bigint *i2b (int i)
{
Bigint *b;
@ -347,13 +308,7 @@ i2b
return b;
}
Bigint *
mult
#ifdef KR_headers
(a, b) Bigint *a, *b;
#else
(Bigint *a, Bigint *b)
#endif
Bigint *mult (Bigint *a, Bigint *b)
{
Bigint *c;
int k, wa, wb, wc;
@ -397,8 +352,7 @@ mult
z = *x++ * (ULLong)y + *xc + carry;
carry = z >> 32;
*xc++ = z & 0xffffffffUL;
}
while(x < xae);
} while(x < xae);
*xc = carry;
}
}
@ -415,8 +369,7 @@ mult
z2 = (*x++ >> 16) * y + (*xc >> 16) + carry;
carry = z2 >> 16;
Storeinc(xc, z2, z);
}
while(x < xae);
} while(x < xae);
*xc = carry;
}
if ( (y = *xb >> 16) !=0) {
@ -430,8 +383,7 @@ mult
Storeinc(xc, z, z2);
z2 = (*x++ >> 16) * y + (*xc & 0xffff) + carry;
carry = z2 >> 16;
}
while(x < xae);
} while(x < xae);
*xc = z2;
}
}
@ -445,8 +397,7 @@ mult
z = *x++ * y + *xc + carry;
carry = z >> 16;
*xc++ = z & 0xffff;
}
while(x < xae);
} while(x < xae);
*xc = carry;
}
}
@ -459,13 +410,7 @@ mult
static Bigint *p5s;
Bigint *
pow5mult
#ifdef KR_headers
(b, k) Bigint *b; int k;
#else
(Bigint *b, int k)
#endif
Bigint *pow5mult (Bigint *b, int k)
{
Bigint *b1, *p5, *p51;
int i;
@ -516,14 +461,7 @@ pow5mult
return b;
}
Bigint *
lshift
#ifdef KR_headers
(b, k) Bigint *b; int k;
#else
(Bigint *b, int k)
#endif
Bigint *lshift (Bigint *b, int k)
{
int i, k1, n, n1;
Bigint *b1;
@ -547,8 +485,7 @@ lshift
do {
*x1++ = *x << k | z;
z = *x++ >> k1;
}
while(x < xe);
} while(x < xe);
if ((*x1 = z) !=0)
++n1;
#else
@ -557,8 +494,7 @@ lshift
do {
*x1++ = *x << k & 0xffff | z;
z = *x++ >> k1;
}
while(x < xe);
} while(x < xe);
if (*x1 = z)
++n1;
#endif
@ -571,13 +507,7 @@ lshift
return b1;
}
int
cmp
#ifdef KR_headers
(a, b) Bigint *a, *b;
#else
(Bigint *a, Bigint *b)
#endif
int cmp (Bigint *a, Bigint *b)
{
ULong *xa, *xa0, *xb, *xb0;
int i, j;
@ -605,13 +535,7 @@ cmp
return 0;
}
Bigint *
diff
#ifdef KR_headers
(a, b) Bigint *a, *b;
#else
(Bigint *a, Bigint *b)
#endif
Bigint *diff (Bigint *a, Bigint *b)
{
Bigint *c;
int i, wa, wb;
@ -655,8 +579,7 @@ diff
y = (ULLong)*xa++ - *xb++ - borrow;
borrow = y >> 32 & 1UL;
*xc++ = y & 0xffffffffUL;
}
while(xb < xbe);
} while(xb < xbe);
while(xa < xae) {
y = *xa++ - borrow;
borrow = y >> 32 & 1UL;
@ -670,8 +593,7 @@ diff
z = (*xa++ >> 16) - (*xb++ >> 16) - borrow;
borrow = (z & 0x10000) >> 16;
Storeinc(xc, z, y);
}
while(xb < xbe);
} while(xb < xbe);
while(xa < xae) {
y = (*xa & 0xffff) - borrow;
borrow = (y & 0x10000) >> 16;
@ -684,8 +606,7 @@ diff
y = *xa++ - *xb++ - borrow;
borrow = (y & 0x10000) >> 16;
*xc++ = y & 0xffff;
}
while(xb < xbe);
} while(xb < xbe);
while(xa < xae) {
y = *xa++ - borrow;
borrow = (y & 0x10000) >> 16;
@ -699,23 +620,13 @@ diff
return c;
}
double
b2d
#ifdef KR_headers
(a, e) Bigint *a; int *e;
#else
(Bigint *a, int *e)
#endif
double b2d (Bigint *a, int *e)
{
ULong *xa, *xa0, w, y, z;
int k;
double d;
#ifdef VAX
ULong d0, d1;
#else
#define d0 word0(d)
#define d1 word1(d)
#endif
union _dbl_union d;
#define d0 word0(&d)
#define d1 word1(&d)
xa0 = a->x;
xa = xa0 + a->wds;
@ -759,37 +670,23 @@ b2d
d1 = w << k + 16 | y << k;
#endif
ret_d:
#ifdef VAX
word0(d) = d0 >> 16 | d0 << 16;
word1(d) = d1 >> 16 | d1 << 16;
#endif
return dval(d);
}
return dval(&d);
#undef d0
#undef d1
}
Bigint *
d2b
#ifdef KR_headers
(d, e, bits) double d; int *e, *bits;
#else
(double d, int *e, int *bits)
#endif
Bigint *d2b (double dd, int *e, int *bits)
{
Bigint *b;
union _dbl_union d;
#ifndef Sudden_Underflow
int i;
#endif
int de, k;
ULong *x, y, z;
#ifdef VAX
ULong d0, d1;
d0 = word0(d) >> 16 | word0(d) << 16;
d1 = word1(d) >> 16 | word1(d) << 16;
#else
#define d0 word0(d)
#define d1 word1(d)
#endif
#define d0 word0(&d)
#define d1 word1(&d)
d.d = dd;
#ifdef Pack_32
b = Balloc(1);
@ -802,9 +699,7 @@ d2b
d0 &= 0x7fffffff; /* clear sign bit, which we ignore */
#ifdef Sudden_Underflow
de = (int)(d0 >> Exp_shift);
#ifndef IBM
z |= Exp_msk11;
#endif
#else
if ( (de = (int)(d0 >> Exp_shift)) !=0)
z |= Exp_msk1;
@ -823,10 +718,6 @@ d2b
b->wds = (x[1] = z) !=0 ? 2 : 1;
}
else {
#ifdef DEBUG
if (!z)
Bug("Zero passed to d2b");
#endif
k = lo0bits(&z);
x[0] = z;
#ifndef Sudden_Underflow
@ -883,13 +774,8 @@ d2b
#ifndef Sudden_Underflow
if (de) {
#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;
*bits = P - k;
#endif
#ifndef Sudden_Underflow
}
else {
@ -902,41 +788,22 @@ d2b
}
#endif
return b;
}
#undef d0
#undef d1
}
CONST double
#ifdef IEEE_Arith
const double
bigtens[] = { 1e16, 1e32, 1e64, 1e128, 1e256 };
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 tinytens[] = { 1e-16, 1e-32, 1e-64, 1e-128, 1e-256 };
CONST double
const double
tens[] = {
1e0, 1e1, 1e2, 1e3, 1e4, 1e5, 1e6, 1e7, 1e8, 1e9,
1e10, 1e11, 1e12, 1e13, 1e14, 1e15, 1e16, 1e17, 1e18, 1e19,
1e20, 1e21, 1e22
#ifdef VAX
, 1e23, 1e24
#endif
};
char *
#ifdef KR_headers
strcp_D2A(a, b) char *a; char *b;
#else
strcp_D2A(char *a, CONST char *b)
#endif
char *strcp_D2A (char *a, const char *b)
{
while((*a = *b++))
a++;
@ -944,19 +811,13 @@ strcp_D2A(char *a, CONST char *b)
}
#ifdef NO_STRING_H
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
void *memcpy_D2A (void *a1, void *b1, size_t len)
{
register char *a = (char*)a1, *ae = a + len;
register char *b = (char*)b1, *a0 = a;
char *a = (char*)a1, *ae = a + len;
char *b = (char*)b1, *a0 = a;
while(a < ae)
*a++ = *b++;
return a0;
}
#endif /* NO_STRING_H */

View File

@ -74,12 +74,16 @@ main(void)
double d;
Ulong L[4];
#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;
#endif
} U;
U a, b, c;
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;
c.f = a.f - b.f;

View File

@ -31,13 +31,7 @@ THIS SOFTWARE.
#include "gdtoaimp.h"
Bigint *
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 *s2b (const char *s, int nd0, int nd, ULong y9, int dplen)
{
Bigint *b;
int i, k;
@ -60,64 +54,38 @@ s2b
s += 9;
do b = multadd(b, 10, *s++ - '0');
while(++i < nd0);
s++;
s += dplen;
}
else
s += 10;
s += dplen + 9;
for(; i < nd; i++)
b = multadd(b, 10, *s++ - '0');
return b;
}
double
ratio
#ifdef KR_headers
(a, b) Bigint *a, *b;
#else
(Bigint *a, Bigint *b)
#endif
double ratio (Bigint *a, Bigint *b)
{
double da, db;
union _dbl_union da, db;
int k, ka, kb;
dval(da) = b2d(a, &ka);
dval(db) = b2d(b, &kb);
dval(&da) = b2d(a, &ka);
dval(&db) = b2d(b, &kb);
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)
word0(da) += k*Exp_msk1;
word0(&da) += k*Exp_msk1;
else {
k = -k;
word0(db) += k*Exp_msk1;
word0(&db) += k*Exp_msk1;
}
#endif
return dval(da) / dval(db);
return dval(&da) / dval(&db);
}
#ifdef INFNAN_CHECK
int
match
#ifdef KR_headers
(sp, t) char **sp, *t;
#else
(CONST char **sp, char *t)
#endif
int match (const char **sp, char *t)
{
int c, d;
CONST char *s = *sp;
const char *s = *sp;
while( (d = *t++) !=0) {
if ((c = *++s) >= 'A' && c <= 'Z')
@ -130,12 +98,7 @@ match
}
#endif /* INFNAN_CHECK */
void
#ifdef KR_headers
copybits(c, n, b) ULong *c; int n; Bigint *b;
#else
copybits(ULong *c, int n, Bigint *b)
#endif
void copybits (ULong *c, int n, Bigint *b)
{
ULong *ce, *x, *xe;
#ifdef Pack_16
@ -160,12 +123,7 @@ copybits(ULong *c, int n, Bigint *b)
*c++ = 0;
}
ULong
#ifdef KR_headers
any_on(b, k) Bigint *b; int k;
#else
any_on(Bigint *b, int k)
#endif
ULong any_on (Bigint *b, int k)
{
int n, nwds;
ULong *x, *x0, x1, x2;

View File

@ -35,21 +35,13 @@ THIS SOFTWARE.
#include "locale.h"
#endif
static CONST int
static const int
fivesbits[] = { 0, 3, 5, 7, 10, 12, 14, 17, 19, 21,
24, 26, 28, 31, 33, 35, 38, 40, 42, 45,
47, 49, 52
#ifdef VAX
, 54, 56
#endif
};
Bigint *
#ifdef KR_headers
increment(b) Bigint *b;
#else
increment(Bigint *b)
#endif
Bigint *increment (Bigint *b)
{
ULong *x, *xe;
Bigint *b1;
@ -89,12 +81,7 @@ increment(Bigint *b)
return b;
}
int
#ifdef KR_headers
decrement(b) Bigint *b;
#else
decrement(Bigint *b)
#endif
void decrement (Bigint *b)
{
ULong *x, *xe;
#ifdef Pack_16
@ -110,8 +97,7 @@ decrement(Bigint *b)
break;
}
*x++ = 0xffffffffL;
}
while(x < xe);
} while(x < xe);
#else
do {
y = *x - borrow;
@ -119,15 +105,9 @@ decrement(Bigint *b)
*x++ = y & 0xffff;
} while(borrow && x < xe);
#endif
return STRTOG_Inexlo;
}
static int
#ifdef KR_headers
all_on(b, n) Bigint *b; int n;
#else
all_on(Bigint *b, int n)
#endif
static int all_on (Bigint *b, int n)
{
ULong *x, *xe;
@ -141,12 +121,7 @@ all_on(Bigint *b, int n)
return 1;
}
Bigint *
#ifdef KR_headers
set_ones(b, n) Bigint *b; int n;
#else
set_ones(Bigint *b, int n)
#endif
Bigint *set_ones (Bigint *b, int n)
{
int k;
ULong *x, *xe;
@ -169,21 +144,15 @@ set_ones(Bigint *b, int n)
return b;
}
static int
rvOK
#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
static int rvOK (dbl_union *d, FPI *fpi, Long *exp, ULong *bits,
int exact, int rd, int *irv)
{
Bigint *b;
ULong carry, inex, lostbits;
int bdif, e, j, k, k1, nb, rv;
carry = rv = 0;
b = d2b(d, &e, &bdif);
b = d2b(dval(d), &e, &bdif);
bdif -= nb = fpi->nbits;
e += bdif;
if (bdif <= 0) {
@ -206,9 +175,9 @@ rvOK
goto ret;
}
switch(rd) {
case 1:
case 1: /* round down (toward -Infinity) */
goto trunc;
case 2:
case 2: /* round up (toward +Infinity) */
break;
default: /* round near */
k = bdif - 1;
@ -276,9 +245,7 @@ rvOK
else if (e > fpi->emax) {
e = fpi->emax + 1;
*irv = STRTOG_Infinite | STRTOG_Overflow | STRTOG_Inexhi;
#ifndef NO_ERRNO
errno = ERANGE;
#endif
SET_ERRNO(ERANGE);
b->wds = inex = 0;
}
*exp = e;
@ -290,52 +257,53 @@ rvOK
return rv;
}
static int
#ifdef KR_headers
mantbits(d) double d;
#else
mantbits(double d)
#endif
static int mantbits (dbl_union *d)
{
ULong L;
#ifdef VAX
L = word1(d) << 16 | word1(d) >> 16;
if (L)
#else
if ( (L = word1(d)) !=0)
#endif
return P - lo0bits(&L);
#ifdef VAX
L = word0(d) << 16 | word0(d) >> 16 | Exp_msk11;
#else
L = word0(d) | Exp_msk1;
#endif
return P - 32 - lo0bits(&L);
}
int
__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 __strtodg (const char *s00, char **se, FPI *fpi, Long *exp, ULong *bits)
{
int abe, abits, asub;
int bb0, bb2, bb5, bbe, bd2, bd5, bbbits, bs2, c, decpt, denorm;
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 sudden_underflow;
CONST char *s, *s0, *s1;
double adj, adj0, rv, tol;
const char *s, *s0, *s1;
double adj0, tol;
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;
#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;
denorm = sign = nz0 = nz = 0;
dval(rv) = 0.;
dval(&rv) = 0.;
rvb = 0;
nbits = fpi->nbits;
for(s = s00;;s++) switch(*s) {
@ -390,13 +358,17 @@ __strtodg
z = 10*z + c - '0';
nd0 = nd;
#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
if (c == '.')
#endif
{
decpt = 1;
if (c == '.') {
c = *++s;
#endif
decpt = 1;
if (!nd) {
for(; c == '0'; c = *++s)
nz++;
@ -425,7 +397,7 @@ __strtodg
nz = 0;
}
}
}
}/*}*/
dig_done:
e = 0;
if (c == 'e' || c == 'E') {
@ -523,27 +495,23 @@ __strtodg
if (!nd0)
nd0 = nd;
k = nd < DBL_DIG + 1 ? nd : DBL_DIG + 1;
dval(rv) = y;
dval(&rv) = y;
if (k > 9)
dval(rv) = tens[k - 9] * dval(rv) + z;
dval(&rv) = tens[k - 9] * dval(&rv) + z;
bd0 = 0;
if (nbits <= P && nd <= DBL_DIG) {
if (!e) {
if (rvOK(dval(rv), fpi, exp, bits, 1, rd, &irv))
if (rvOK(&rv, fpi, exp, bits, 1, rd, &irv))
goto ret;
}
else if (e > 0) {
if (e <= Ten_pmax) {
#ifdef VAX
goto vax_ovfl_check;
#else
i = fivesbits[e] + mantbits(dval(rv)) <= P;
/* rv = */ rounded_product(dval(rv), tens[e]);
if (rvOK(dval(rv), fpi, exp, bits, i, rd, &irv))
i = fivesbits[e] + mantbits(&rv) <= P;
/* rv = */ rounded_product(dval(&rv), tens[e]);
if (rvOK(&rv, fpi, exp, bits, i, rd, &irv))
goto ret;
e1 -= e;
goto rv_notOK;
#endif
}
i = DBL_DIG - nd;
if (e <= Ten_pmax + i) {
@ -552,32 +520,17 @@ __strtodg
*/
e2 = e - i;
e1 -= i;
dval(rv) *= tens[i];
#ifdef VAX
/* VAX exponent range is so narrow we must
* worry about overflow here...
*/
vax_ovfl_check:
dval(adj) = dval(rv);
word0(adj) -= P*Exp_msk1;
/* adj = */ rounded_product(dval(adj), tens[e2]);
if ((word0(adj) & Exp_mask)
> 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))
dval(&rv) *= tens[i];
/* rv = */ rounded_product(dval(&rv), tens[e2]);
if (rvOK(&rv, fpi, exp, bits, 0, rd, &irv))
goto ret;
e1 -= e2;
}
}
#ifndef Inaccurate_Divide
else if (e >= -Ten_pmax) {
/* rv = */ rounded_quotient(dval(rv), tens[-e]);
if (rvOK(dval(rv), fpi, exp, bits, 0, rd, &irv))
/* rv = */ rounded_quotient(dval(&rv), tens[-e]);
if (rvOK(&rv, fpi, exp, bits, 0, rd, &irv))
goto ret;
e1 -= e;
}
@ -591,56 +544,48 @@ __strtodg
e2 = 0;
if (e1 > 0) {
if ( (i = e1 & 15) !=0)
dval(rv) *= tens[i];
dval(&rv) *= tens[i];
if (e1 &= ~15) {
e1 >>= 4;
while(e1 >= (1 << (n_bigtens-1))) {
e2 += ((word0(rv) & Exp_mask)
e2 += ((word0(&rv) & Exp_mask)
>> Exp_shift1) - Bias;
word0(rv) &= ~Exp_mask;
word0(rv) |= Bias << Exp_shift1;
dval(rv) *= bigtens[n_bigtens-1];
word0(&rv) &= ~Exp_mask;
word0(&rv) |= Bias << Exp_shift1;
dval(&rv) *= bigtens[n_bigtens-1];
e1 -= 1 << (n_bigtens-1);
}
e2 += ((word0(rv) & Exp_mask) >> Exp_shift1) - Bias;
word0(rv) &= ~Exp_mask;
word0(rv) |= Bias << Exp_shift1;
e2 += ((word0(&rv) & Exp_mask) >> Exp_shift1) - Bias;
word0(&rv) &= ~Exp_mask;
word0(&rv) |= Bias << Exp_shift1;
for(j = 0; e1 > 0; j++, e1 >>= 1)
if (e1 & 1)
dval(rv) *= bigtens[j];
dval(&rv) *= bigtens[j];
}
}
else if (e1 < 0) {
e1 = -e1;
if ( (i = e1 & 15) !=0)
dval(rv) /= tens[i];
dval(&rv) /= tens[i];
if (e1 &= ~15) {
e1 >>= 4;
while(e1 >= (1 << (n_bigtens-1))) {
e2 += ((word0(rv) & Exp_mask)
e2 += ((word0(&rv) & Exp_mask)
>> Exp_shift1) - Bias;
word0(rv) &= ~Exp_mask;
word0(rv) |= Bias << Exp_shift1;
dval(rv) *= tinytens[n_bigtens-1];
word0(&rv) &= ~Exp_mask;
word0(&rv) |= Bias << Exp_shift1;
dval(&rv) *= tinytens[n_bigtens-1];
e1 -= 1 << (n_bigtens-1);
}
e2 += ((word0(rv) & Exp_mask) >> Exp_shift1) - Bias;
word0(rv) &= ~Exp_mask;
word0(rv) |= Bias << Exp_shift1;
e2 += ((word0(&rv) & Exp_mask) >> Exp_shift1) - Bias;
word0(&rv) &= ~Exp_mask;
word0(&rv) |= Bias << Exp_shift1;
for(j = 0; e1 > 0; j++, e1 >>= 1)
if (e1 & 1)
dval(rv) *= tinytens[j];
dval(&rv) *= tinytens[j];
}
}
#ifdef IBM
/* e2 is a correction to the (base 2) exponent of the return
* 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 */
rvb = d2b(dval(&rv), &rve, &rvbits); /* rv = rvb * 2^rve */
rve += e2;
if ((j = rvbits - nbits) > 0) {
rshift(rvb, j);
@ -684,7 +629,7 @@ __strtodg
/* Put digits into bd: true value = bd * 10^e */
bd0 = s2b(s0, nd0, nd, y);
bd0 = s2b(s0, nd0, nd, y, dplen);
for(;;) {
bd = Balloc(bd0->k);
@ -822,10 +767,8 @@ __strtodg
break;
if (dsign) {
rvb = increment(rvb);
if ( (j = rvbits & kmask) !=0)
j = ULbits - j;
if (hi0bits(rvb->x[(rvb->wds - 1) >> kshift])
!= j)
j = kmask & (ULbits - (rvbits & kmask));
if (hi0bits(rvb->x[rvb->wds - 1]) != j)
rvbits++;
irv = STRTOG_Normal | STRTOG_Inexhi;
}
@ -837,7 +780,7 @@ __strtodg
}
break;
}
if ((dval(adj) = ratio(delta, bs)) <= 2.) {
if ((dval(&adj) = ratio(delta, bs)) <= 2.) {
adj1:
inex = STRTOG_Inexlo;
if (dsign) {
@ -851,15 +794,15 @@ __strtodg
irv = STRTOG_Underflow | STRTOG_Inexlo;
break;
}
adj0 = dval(adj) = 1.;
adj0 = dval(&adj) = 1.;
}
else {
adj0 = dval(adj) *= 0.5;
adj0 = dval(&adj) *= 0.5;
if (dsign) {
asub = 0;
inex = STRTOG_Inexlo;
}
if (dval(adj) < 2147483647.) {
if (dval(&adj) < 2147483647.) {
L = adj0;
adj0 -= L;
switch(rd) {
@ -878,12 +821,12 @@ __strtodg
inex = STRTOG_Inexact - inex;
}
}
dval(adj) = L;
dval(&adj) = L;
}
}
y = rve + rvbits;
/* adj *= ulp(dval(rv)); */
/* adj *= ulp(&rv); */
/* if (asub) rv -= adj; else rv += adj; */
if (!denorm && rvbits < nbits) {
@ -891,7 +834,7 @@ __strtodg
rve -= j;
rvbits = nbits;
}
ab = d2b(dval(adj), &abe, &abits);
ab = d2b(dval(&adj), &abe, &abits);
if (abe < 0)
rshift(ab, -abe);
else if (abe > 0)
@ -945,15 +888,15 @@ __strtodg
z = rve + rvbits;
if (y == z && L) {
/* Can we stop now? */
tol = dval(adj) * 5e-16; /* > max rel error */
dval(adj) = adj0 - .5;
if (dval(adj) < -tol) {
tol = dval(&adj) * 5e-16; /* > max rel error */
dval(&adj) = adj0 - .5;
if (dval(&adj) < -tol) {
if (adj0 > tol) {
irv |= inex;
break;
}
}
else if (dval(adj) > tol && adj0 < 1. - tol) {
else if (dval(&adj) > tol && adj0 < 1. - tol) {
irv |= inex;
break;
}
@ -978,12 +921,33 @@ __strtodg
Bfree(bd0);
Bfree(delta);
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:
rvb->wds = 0;
irv = STRTOG_Infinite | STRTOG_Overflow | STRTOG_Inexhi;
#ifndef NO_ERRNO
errno = ERANGE;
#endif
SET_ERRNO(ERANGE);
infnanexp:
*exp = fpi->emax + 1;
}
@ -992,12 +956,15 @@ __strtodg
if (sudden_underflow) {
rvb->wds = 0;
irv = STRTOG_Underflow | STRTOG_Inexlo;
SET_ERRNO(ERANGE);
}
else {
irv = (irv & ~STRTOG_Retmask) |
(rvb->wds > 0 ? STRTOG_Denormal : STRTOG_Zero);
if (irv & STRTOG_Inexact)
if (irv & STRTOG_Inexact) {
irv |= STRTOG_Underflow;
SET_ERRNO(ERANGE);
}
}
}
if (se)

View File

@ -37,12 +37,7 @@ THIS SOFTWARE.
#include "gdtoaimp.h"
double
#ifdef KR_headers
__strtod(s, sp) CONST char *s; char **sp;
#else
__strtod(CONST char *s, char **sp)
#endif
double __strtod (const char *s, char **sp)
{
static FPI fpi = { 53, 1-1023-53+1, 2046-1023-53+1, 1, SI };
ULong bits[2];

View File

@ -31,20 +31,20 @@ THIS SOFTWARE.
#include "gdtoaimp.h"
float
#ifdef KR_headers
__strtof(s, sp) CONST char *s; char **sp;
#else
__strtof(CONST char *s, char **sp)
#endif
float __strtof (const char *s, char **sp)
{
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];
Long exp;
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) {
case STRTOG_NoNumber:
case STRTOG_Zero:
@ -53,7 +53,7 @@ __strtof(CONST char *s, char **sp)
case STRTOG_Normal:
case STRTOG_NaNbits:
u.L[0] = (bits[0] & 0x7fffff) | (exp + 0x7f + 23) << 23;
u.L[0] = (bits[0] & 0x7fffff) | ((exp + 0x7f + 23) << 23);
break;
case STRTOG_Denormal:

View File

@ -51,20 +51,26 @@ THIS SOFTWARE.
#define _4 0
#endif
static int
#ifdef KR_headers
__strtopx(s, sp, V) CONST char *s; char **sp; long double *V;
#else
__strtopx(CONST char *s, char **sp, long double *V)
#endif
typedef union lD {
UShort L[5];
long double D;
} lD;
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];
Long exp;
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) {
case STRTOG_NoNumber:
case STRTOG_Zero:
@ -103,17 +109,16 @@ __strtopx(CONST char *s, char **sp, long double *V)
return k;
}
long double
__cdecl
long double __cdecl
__strtold (const char * __restrict__ src, char ** __restrict__ endptr)
{
long double ret;
lD ret;
ret.D = 0.0L;
__strtopx(src, endptr, &ret);
return ret;
return ret.D;
}
long double
__cdecl
long double __cdecl
strtold (const char * __restrict__ src, char ** __restrict__ endptr)
__attribute__((alias("__strtold")));

View File

@ -31,12 +31,7 @@ THIS SOFTWARE.
#include "gdtoaimp.h"
Bigint *
#ifdef KR_headers
sum(a, b) Bigint *a; Bigint *b;
#else
sum(Bigint *a, Bigint *b)
#endif
Bigint *sum (Bigint *a, Bigint *b)
{
Bigint *c;
ULong carry, *xc, *xa, *xb, *xe, y;
@ -61,8 +56,7 @@ sum(Bigint *a, Bigint *b)
z = (*xa++ >> 16) + (*xb++ >> 16) + carry;
carry = (z & 0x10000) >> 16;
Storeinc(xc, z, y);
}
while(xc < xe);
} while(xc < xe);
xe += a->wds - b->wds;
while(xc < xe) {
y = (*xa & 0xffff) + carry;
@ -76,8 +70,7 @@ sum(Bigint *a, Bigint *b)
y = *xa++ + *xb++ + carry;
carry = (y & 0x10000) >> 16;
*xc++ = y & 0xffff;
}
while(xc < xe);
} while(xc < xe);
xe += a->wds - b->wds;
while(xc < xe) {
y = *xa++ + carry;

View File

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