mirror of
https://github.com/ZDoom/gzdoom.git
synced 2024-11-25 13:31:37 +00:00
- Updated gdtoa in order to fix clang warnings.
This commit is contained in:
parent
b0f40c0733
commit
cd3f5db16a
47 changed files with 1528 additions and 956 deletions
84
gdtoa/README
84
gdtoa/README
|
@ -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
|
||||||
|
@ -150,12 +152,14 @@ suffer double rounding due to use of extended-precision registers.
|
||||||
For some conversions this variant of strtod is less efficient than the
|
For some conversions this variant of strtod is less efficient than the
|
||||||
one in strtod.c when the latter is run with 53-bit rounding precision.
|
one in strtod.c when the latter is run with 53-bit rounding precision.
|
||||||
|
|
||||||
The values that the strto* routines return for NaNs are determined by
|
When float or double are involved, the values that the strto* routines
|
||||||
gd_qnan.h, which the makefile generates by running the program whose
|
return for NaNs are determined by gd_qnan.h, which the makefile
|
||||||
source is qnan.c. Note that the rules for distinguishing signaling
|
generates by running the program whose source is qnan.c. For other
|
||||||
from quiet NaNs are system-dependent. For cross-compilation, you need
|
types, default NaN values are specified in g__fmt.c and may need
|
||||||
to determine arith.h and gd_qnan.h suitably, e.g., using the
|
adjusting. Note that the rules for distinguishing signaling from
|
||||||
arithmetic of the target machine.
|
quiet NaNs are system-dependent. For cross-compilation, you need to
|
||||||
|
determine arith.h and gd_qnan.h suitably, e.g., using the arithmetic
|
||||||
|
of the target machine.
|
||||||
|
|
||||||
C99's hexadecimal floating-point constants are recognized by the
|
C99's hexadecimal floating-point constants are recognized by the
|
||||||
strto* routines (but this feature has not yet been heavily tested).
|
strto* routines (but this feature has not yet been heavily tested).
|
||||||
|
@ -170,10 +174,11 @@ hexadecimal digits, it is taken for the fraction bits of the resulting
|
||||||
NaN; if there are two or more strings of hexadecimal digits, each
|
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
|
string is assigned to the next available sequence of 32-bit words of
|
||||||
fractions bits (starting with the most significant), right-aligned in
|
fractions bits (starting with the most significant), right-aligned in
|
||||||
each sequence.
|
each sequence. Strings of hexadecimal digits may be preceded by "0x"
|
||||||
|
or "0X".
|
||||||
|
|
||||||
For binary -> decimal conversions, I've provided just one family
|
For binary -> decimal conversions, I've provided a family of helper
|
||||||
of helper routines:
|
routines:
|
||||||
|
|
||||||
g_ffmt
|
g_ffmt
|
||||||
g_dfmt
|
g_dfmt
|
||||||
|
@ -181,6 +186,12 @@ of helper routines:
|
||||||
g_xfmt
|
g_xfmt
|
||||||
g_xLfmt
|
g_xLfmt
|
||||||
g_Qfmt
|
g_Qfmt
|
||||||
|
g_ffmt_p
|
||||||
|
g_dfmt_p
|
||||||
|
g_ddfmt_p
|
||||||
|
g_xfmt_p
|
||||||
|
g_xLfmt_p
|
||||||
|
g_Qfmt_p
|
||||||
|
|
||||||
which do a "%g" style conversion either to a specified number of decimal
|
which do a "%g" style conversion either to a specified number of decimal
|
||||||
places (if their ndig argument is positive), or to the shortest
|
places (if their ndig argument is positive), or to the shortest
|
||||||
|
@ -191,6 +202,36 @@ 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 pedants, the ...fmt_p() routines are similar to the
|
||||||
|
...fmt() routines, but have an additional final int argument, nik,
|
||||||
|
that for conversions of Infinity or NaN, determines whether upper,
|
||||||
|
lower, or mixed case is used, whether (...) is added to NaN values,
|
||||||
|
and whether the sign of a NaN is reported or suppressed:
|
||||||
|
|
||||||
|
nik = ic + 6*(nb + 3*ns),
|
||||||
|
|
||||||
|
where ic with 0 <= ic < 6 controls the rendering of Infinity and NaN:
|
||||||
|
|
||||||
|
0 ==> Infinity or NaN
|
||||||
|
1 ==> infinity or nan
|
||||||
|
2 ==> INFINITY or NAN
|
||||||
|
3 ==> Inf or NaN
|
||||||
|
4 ==> inf or nan
|
||||||
|
5 ==> INF or NAN
|
||||||
|
|
||||||
|
nb with 0 <= nb < 3 determines whether NaN values are rendered
|
||||||
|
as NaN(...):
|
||||||
|
|
||||||
|
0 ==> no
|
||||||
|
1 ==> yes
|
||||||
|
2 ==> no for default NaN values; yes otherwise
|
||||||
|
|
||||||
|
ns = 0 or 1 determines whether the sign of NaN values reported:
|
||||||
|
|
||||||
|
0 ==> distinguish NaN and -NaN
|
||||||
|
1 ==> report both as NaN
|
||||||
|
|
||||||
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 +373,28 @@ 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.
|
||||||
|
|
||||||
|
On machines with a 64-bit long double and perhaps a 113-bit "quad"
|
||||||
|
type, you can invoke "make Printf" to add Printf (and variants, such
|
||||||
|
as Fprintf) to gdtoa.a. These are analogs, declared in stdio1.h, of
|
||||||
|
printf and fprintf, etc. in which %La, %Le, %Lf, and %Lg are for long
|
||||||
|
double and (if appropriate) %Lqa, %Lqe, %Lqf, and %Lqg are for quad
|
||||||
|
precision printing.
|
||||||
|
|
||||||
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 ".").
|
||||||
|
|
|
@ -106,7 +106,7 @@ ccheck()
|
||||||
long Cray1;
|
long Cray1;
|
||||||
|
|
||||||
/* Cray1 = 4617762693716115456 -- without overflow on non-Crays */
|
/* Cray1 = 4617762693716115456 -- without overflow on non-Crays */
|
||||||
Cray1 = printf(emptyfmt) < 0 ? 0 : 4617762;
|
Cray1 = printf("%s", emptyfmt) < 0 ? 0 : 4617762;
|
||||||
if (printf(emptyfmt, Cray1) >= 0)
|
if (printf(emptyfmt, Cray1) >= 0)
|
||||||
Cray1 = 1000000*Cray1 + 693716;
|
Cray1 = 1000000*Cray1 + 693716;
|
||||||
if (printf(emptyfmt, Cray1) >= 0)
|
if (printf(emptyfmt, Cray1) >= 0)
|
||||||
|
|
|
@ -46,7 +46,7 @@ rv_alloc(int i)
|
||||||
|
|
||||||
j = sizeof(ULong);
|
j = sizeof(ULong);
|
||||||
for(k = 0;
|
for(k = 0;
|
||||||
sizeof(Bigint) - sizeof(ULong) - sizeof(int) + j <= (size_t)i;
|
sizeof(Bigint) - sizeof(ULong) - sizeof(int) + j <= (size_t)(i);
|
||||||
j <<= 1)
|
j <<= 1)
|
||||||
k++;
|
k++;
|
||||||
r = (int*)Balloc(k);
|
r = (int*)Balloc(k);
|
||||||
|
|
210
gdtoa/dtoa.c
210
gdtoa/dtoa.c
|
@ -30,7 +30,6 @@ THIS SOFTWARE.
|
||||||
* with " at " changed at "@" and " dot " changed to "."). */
|
* with " at " changed at "@" and " dot " changed to "."). */
|
||||||
|
|
||||||
#include "gdtoaimp.h"
|
#include "gdtoaimp.h"
|
||||||
#include <limits.h>
|
|
||||||
|
|
||||||
/* dtoa for IEEE arithmetic (dmg): convert double to ASCII string.
|
/* dtoa for IEEE arithmetic (dmg): convert double to ASCII string.
|
||||||
*
|
*
|
||||||
|
@ -67,7 +66,6 @@ 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
|
||||||
|
@ -77,17 +75,17 @@ THIS SOFTWARE.
|
||||||
char *
|
char *
|
||||||
dtoa
|
dtoa
|
||||||
#ifdef KR_headers
|
#ifdef KR_headers
|
||||||
(d, mode, ndigits, decpt, sign, rve)
|
(d0, mode, ndigits, decpt, sign, rve)
|
||||||
double d; int mode, ndigits, *decpt, *sign; char **rve;
|
double d0; int mode, ndigits, *decpt, *sign; char **rve;
|
||||||
#else
|
#else
|
||||||
(double _d, int mode, int ndigits, int *decpt, int *sign, char **rve)
|
(double d0, int mode, int ndigits, int *decpt, int *sign, char **rve)
|
||||||
#endif
|
#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
|
||||||
the returned string. If not null, *rve is set to point
|
the returned string. If not null, *rve is set to point
|
||||||
to the end of the return value. If d is +-Infinity or NaN,
|
to the end of the return value. If d is +-Infinity or NaN,
|
||||||
then *decpt is set to INT_MAX.
|
then *decpt is set to 9999.
|
||||||
|
|
||||||
mode:
|
mode:
|
||||||
0 ==> shortest string that yields d when read in
|
0 ==> shortest string that yields d when read in
|
||||||
|
@ -129,12 +127,22 @@ dtoa
|
||||||
U d, d2, eps;
|
U d, d2, eps;
|
||||||
double ds;
|
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) {
|
||||||
|
@ -142,36 +150,35 @@ dtoa
|
||||||
dtoa_result = 0;
|
dtoa_result = 0;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
d.d = d0;
|
||||||
dval(d) = _d;
|
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 defined(IEEE_Arith) + defined(VAX)
|
||||||
#ifdef IEEE_Arith
|
#ifdef IEEE_Arith
|
||||||
if ((word0(d) & Exp_mask) == Exp_mask)
|
if ((word0(&d) & Exp_mask) == Exp_mask)
|
||||||
#else
|
#else
|
||||||
if (word0(d) == 0x8000)
|
if (word0(&d) == 0x8000)
|
||||||
#endif
|
#endif
|
||||||
{
|
{
|
||||||
/* Infinity or NaN */
|
/* Infinity or NaN */
|
||||||
*decpt = INT_MAX;
|
*decpt = 9999;
|
||||||
#ifdef IEEE_Arith
|
#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
|
#endif
|
||||||
return nrv_alloc("NaN", rve, 3);
|
return nrv_alloc("NaN", rve, 3);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
#ifdef IBM
|
#ifdef IBM
|
||||||
dval(d) += 0; /* normalize */
|
dval(&d) += 0; /* normalize */
|
||||||
#endif
|
#endif
|
||||||
if (!dval(d)) {
|
if (!dval(&d)) {
|
||||||
*decpt = 1;
|
*decpt = 1;
|
||||||
return nrv_alloc("0", rve, 1);
|
return nrv_alloc("0", rve, 1);
|
||||||
}
|
}
|
||||||
|
@ -181,35 +188,35 @@ dtoa
|
||||||
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
|
#endif
|
||||||
dval(d2) = dval(d);
|
dval(&d2) = dval(&d);
|
||||||
word0(d2) &= Frac_mask1;
|
word0(&d2) &= Frac_mask1;
|
||||||
word0(d2) |= Exp_11;
|
word0(&d2) |= Exp_11;
|
||||||
#ifdef IBM
|
#ifdef IBM
|
||||||
if (( j = 11 - hi0bits(word0(d2) & Frac_mask) )!=0)
|
if (( j = 11 - hi0bits(word0(&d2) & Frac_mask) )!=0)
|
||||||
dval(d2) /= 1 << j;
|
dval(&d2) /= 1 << j;
|
||||||
#endif
|
#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 );
|
||||||
|
@ -238,21 +245,21 @@ dtoa
|
||||||
/* 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;
|
||||||
}
|
}
|
||||||
|
@ -291,10 +298,11 @@ dtoa
|
||||||
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;
|
||||||
|
@ -319,7 +327,7 @@ dtoa
|
||||||
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
|
||||||
|
|
||||||
|
@ -328,7 +336,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 */
|
||||||
|
@ -338,7 +346,7 @@ 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++)
|
||||||
|
@ -346,32 +354,32 @@ dtoa
|
||||||
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;
|
||||||
}
|
}
|
||||||
|
@ -380,34 +388,34 @@ dtoa
|
||||||
/* 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 = (Long)dval(d);
|
L = (Long)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;
|
||||||
|
@ -420,7 +428,7 @@ dtoa
|
||||||
#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;
|
||||||
}
|
}
|
||||||
|
@ -432,22 +440,22 @@ 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
|
||||||
|
@ -456,13 +464,18 @@ dtoa
|
||||||
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) {
|
#ifdef ROUND_BIASED
|
||||||
|
if (dval(&d) >= ds)
|
||||||
|
#else
|
||||||
|
if (dval(&d) > ds || (dval(&d) == ds && L & 1))
|
||||||
|
#endif
|
||||||
|
{
|
||||||
bump_up:
|
bump_up:
|
||||||
while(*--s == '9')
|
while(*--s == '9')
|
||||||
if (s == s0) {
|
if (s == s0) {
|
||||||
|
@ -524,12 +537,12 @@ 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 */
|
||||||
|
@ -615,9 +628,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')
|
||||||
|
@ -632,11 +645,11 @@ dtoa
|
||||||
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) {
|
||||||
#ifdef SET_INEXACT
|
#ifdef SET_INEXACT
|
||||||
inexact = 0;
|
inexact = 0;
|
||||||
|
@ -645,7 +658,7 @@ dtoa
|
||||||
}
|
}
|
||||||
#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;
|
||||||
}
|
}
|
||||||
|
@ -653,7 +666,11 @@ dtoa
|
||||||
if (j1 > 0) {
|
if (j1 > 0) {
|
||||||
b = lshift(b, 1);
|
b = lshift(b, 1);
|
||||||
j1 = cmp(b, S);
|
j1 = cmp(b, S);
|
||||||
if ((j1 > 0 || j1 == 0 && dig & 1)
|
#ifdef ROUND_BIASED
|
||||||
|
if (j1 >= 0 /*)*/
|
||||||
|
#else
|
||||||
|
if ((j1 > 0 || (j1 == 0 && dig & 1))
|
||||||
|
#endif
|
||||||
&& dig++ == '9')
|
&& dig++ == '9')
|
||||||
goto round_9_up;
|
goto round_9_up;
|
||||||
}
|
}
|
||||||
|
@ -663,7 +680,7 @@ dtoa
|
||||||
}
|
}
|
||||||
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 */
|
||||||
|
@ -706,14 +723,19 @@ dtoa
|
||||||
/* 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);
|
||||||
if (j > 0 || j == 0 && dig & 1) {
|
#ifdef ROUND_BIASED
|
||||||
|
if (j >= 0)
|
||||||
|
#else
|
||||||
|
if (j > 0 || (j == 0 && dig & 1))
|
||||||
|
#endif
|
||||||
|
{
|
||||||
roundoff:
|
roundoff:
|
||||||
while(*--s == '9')
|
while(*--s == '9')
|
||||||
if (s == s0) {
|
if (s == s0) {
|
||||||
|
@ -724,7 +746,9 @@ dtoa
|
||||||
++*s++;
|
++*s++;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
|
#ifdef Honor_FLT_ROUNDS
|
||||||
trimzeros:
|
trimzeros:
|
||||||
|
#endif
|
||||||
while(*--s == '0');
|
while(*--s == '0');
|
||||||
s++;
|
s++;
|
||||||
}
|
}
|
||||||
|
@ -739,9 +763,9 @@ dtoa
|
||||||
#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)
|
||||||
|
|
|
@ -51,19 +51,24 @@ THIS SOFTWARE.
|
||||||
|
|
||||||
char*
|
char*
|
||||||
#ifdef KR_headers
|
#ifdef KR_headers
|
||||||
g_Qfmt(buf, V, ndig, bufsize) char *buf; char *V; int ndig; unsigned bufsize;
|
g_Qfmt(buf, V, ndig, bufsize) char *buf; char *V; int ndig; size_t bufsize;
|
||||||
#else
|
#else
|
||||||
g_Qfmt(char *buf, void *V, int ndig, unsigned bufsize)
|
g_Qfmt(char *buf, void *V, int ndig, size_t bufsize)
|
||||||
#endif
|
#endif
|
||||||
{
|
{
|
||||||
static CONST FPI fpi = { 113, 1-16383-113+1, 32766 - 16383 - 113 + 1, 1, 0 };
|
static FPI fpi0 = { 113, 1-16383-113+1, 32766 - 16383 - 113 + 1, 1, 0, Int_max };
|
||||||
char *b, *s, *se;
|
char *b, *s, *se;
|
||||||
ULong bits[4], *L, sign;
|
ULong bits[4], *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;
|
||||||
if (bufsize < (unsigned)(ndig + 10))
|
if (bufsize < (size_t)(ndig + 10))
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
L = (ULong*)V;
|
L = (ULong*)V;
|
||||||
|
@ -109,6 +114,6 @@ g_Qfmt(char *buf, void *V, int ndig, unsigned bufsize)
|
||||||
return 0;
|
return 0;
|
||||||
mode = 0;
|
mode = 0;
|
||||||
}
|
}
|
||||||
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);
|
||||||
}
|
}
|
||||||
|
|
122
gdtoa/g__fmt.c
122
gdtoa/g__fmt.c
|
@ -35,26 +35,77 @@ THIS SOFTWARE.
|
||||||
#include "locale.h"
|
#include "locale.h"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#ifndef ldus_QNAN0
|
||||||
|
#define ldus_QNAN0 0x7fff
|
||||||
|
#endif
|
||||||
|
#ifndef ldus_QNAN1
|
||||||
|
#define ldus_QNAN1 0xc000
|
||||||
|
#endif
|
||||||
|
#ifndef ldus_QNAN2
|
||||||
|
#define ldus_QNAN2 0
|
||||||
|
#endif
|
||||||
|
#ifndef ldus_QNAN3
|
||||||
|
#define ldus_QNAN3 0
|
||||||
|
#endif
|
||||||
|
#ifndef ldus_QNAN4
|
||||||
|
#define ldus_QNAN4 0
|
||||||
|
#endif
|
||||||
|
|
||||||
|
const char *InfName[6] = { "Infinity", "infinity", "INFINITY", "Inf", "inf", "INF" };
|
||||||
|
const char *NanName[3] = { "NaN", "nan", "NAN" };
|
||||||
|
ULong NanDflt_Q_D2A[4] = { 0xffffffff, 0xffffffff, 0xffffffff, 0x7fffffff };
|
||||||
|
ULong NanDflt_d_D2A[2] = { d_QNAN1, d_QNAN0 };
|
||||||
|
ULong NanDflt_f_D2A[1] = { f_QNAN };
|
||||||
|
ULong NanDflt_xL_D2A[3] = { 1, 0x80000000, 0x7fff0000 };
|
||||||
|
UShort NanDflt_ldus_D2A[5] = { ldus_QNAN4, ldus_QNAN3, ldus_QNAN2, ldus_QNAN1, ldus_QNAN0 };
|
||||||
|
|
||||||
char *
|
char *
|
||||||
#ifdef KR_headers
|
#ifdef KR_headers
|
||||||
g__fmt(b, s, se, decpt, sign) char *b; char *s; char *se; int decpt; ULong sign;
|
g__fmt(b, s, se, decpt, sign, blen) char *b; char *s; char *se; int decpt; ULong sign; size_t blen;
|
||||||
#else
|
#else
|
||||||
g__fmt(char *b, char *s, char *se, int decpt, ULong sign)
|
g__fmt(char *b, char *s, char *se, int decpt, ULong sign, size_t blen)
|
||||||
#endif
|
#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++;
|
||||||
}
|
}
|
||||||
|
@ -69,6 +120,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(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;
|
||||||
|
@ -78,7 +131,14 @@ g__fmt(char *b, char *s, char *se, int decpt, ULong sign)
|
||||||
*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)
|
||||||
|
@ -87,13 +147,57 @@ g__fmt(char *b, char *s, char *se, int decpt, ULong sign)
|
||||||
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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
char *
|
||||||
|
add_nanbits_D2A(char *b, size_t blen, ULong *bits, int nb)
|
||||||
|
{
|
||||||
|
ULong t;
|
||||||
|
char *rv;
|
||||||
|
int i, j;
|
||||||
|
size_t L;
|
||||||
|
static char Hexdig[16] = "0123456789abcdef";
|
||||||
|
|
||||||
|
while(!bits[--nb])
|
||||||
|
if (!nb)
|
||||||
|
return b;
|
||||||
|
L = 8*nb + 3;
|
||||||
|
t = bits[nb];
|
||||||
|
do ++L; while((t >>= 4));
|
||||||
|
if (L > blen)
|
||||||
|
return b;
|
||||||
|
b += L;
|
||||||
|
*--b = 0;
|
||||||
|
rv = b;
|
||||||
|
*--b = /*(*/ ')';
|
||||||
|
for(i = 0; i < nb; ++i) {
|
||||||
|
t = bits[i];
|
||||||
|
for(j = 0; j < 8; ++j, t >>= 4)
|
||||||
|
*--b = Hexdig[t & 0xf];
|
||||||
|
}
|
||||||
|
t = bits[nb];
|
||||||
|
do *--b = Hexdig[t & 0xf]; while(t >>= 4);
|
||||||
|
*--b = '('; /*)*/
|
||||||
|
return rv;
|
||||||
|
}
|
||||||
|
|
|
@ -33,9 +33,9 @@ THIS SOFTWARE.
|
||||||
|
|
||||||
char *
|
char *
|
||||||
#ifdef KR_headers
|
#ifdef KR_headers
|
||||||
g_ddfmt(buf, dd, ndig, bufsize) char *buf; double *dd; int ndig; unsigned bufsize;
|
g_ddfmt(buf, dd0, ndig, bufsize) char *buf; double *dd0; int ndig; size_t bufsize;
|
||||||
#else
|
#else
|
||||||
g_ddfmt(char *buf, double *dd, int ndig, unsigned bufsize)
|
g_ddfmt(char *buf, double *dd0, int ndig, size_t bufsize)
|
||||||
#endif
|
#endif
|
||||||
{
|
{
|
||||||
FPI fpi;
|
FPI fpi;
|
||||||
|
@ -43,12 +43,28 @@ g_ddfmt(char *buf, double *dd, int ndig, unsigned bufsize)
|
||||||
ULong *L, bits0[4], *bits, *zx;
|
ULong *L, bits0[4], *bits, *zx;
|
||||||
int bx, by, decpt, ex, ey, i, j, mode;
|
int bx, by, decpt, ex, ey, i, j, mode;
|
||||||
Bigint *x, *y, *z;
|
Bigint *x, *y, *z;
|
||||||
double ddx[2];
|
U *dd, ddx[2];
|
||||||
|
#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 /*}}*/
|
||||||
|
#else /*}{*/
|
||||||
|
#define Rounding FPI_Round_near
|
||||||
|
#endif /*}}*/
|
||||||
|
|
||||||
if (bufsize < 10 || bufsize < (unsigned)(ndig + 8))
|
if (bufsize < 10 || bufsize < (size_t)(ndig + 8))
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
L = (ULong*)dd;
|
dd = (U*)dd0;
|
||||||
|
L = dd->L;
|
||||||
if ((L[_0] & 0x7ff00000L) == 0x7ff00000L) {
|
if ((L[_0] & 0x7ff00000L) == 0x7ff00000L) {
|
||||||
/* Infinity or NaN */
|
/* Infinity or NaN */
|
||||||
if (L[_0] & 0xfffff || L[_1]) {
|
if (L[_0] & 0xfffff || L[_1]) {
|
||||||
|
@ -73,7 +89,7 @@ g_ddfmt(char *buf, double *dd, int ndig, unsigned bufsize)
|
||||||
goto nanret;
|
goto nanret;
|
||||||
goto infret;
|
goto infret;
|
||||||
}
|
}
|
||||||
if (dd[0] + dd[1] == 0.) {
|
if (dval(&dd[0]) + dval(&dd[1]) == 0.) {
|
||||||
b = buf;
|
b = buf;
|
||||||
#ifndef IGNORE_ZERO_SIGN
|
#ifndef IGNORE_ZERO_SIGN
|
||||||
if (L[_0] & L[2+_0] & 0x80000000L)
|
if (L[_0] & L[2+_0] & 0x80000000L)
|
||||||
|
@ -84,16 +100,16 @@ g_ddfmt(char *buf, double *dd, int ndig, unsigned bufsize)
|
||||||
return b;
|
return b;
|
||||||
}
|
}
|
||||||
if ((L[_0] & 0x7ff00000L) < (L[2+_0] & 0x7ff00000L)) {
|
if ((L[_0] & 0x7ff00000L) < (L[2+_0] & 0x7ff00000L)) {
|
||||||
ddx[1] = dd[0];
|
dval(&ddx[1]) = dval(&dd[0]);
|
||||||
ddx[0] = dd[1];
|
dval(&ddx[0]) = dval(&dd[1]);
|
||||||
dd = ddx;
|
dd = ddx;
|
||||||
L = (ULong*)dd;
|
L = dd->L;
|
||||||
}
|
}
|
||||||
z = d2b(dd[0], &ex, &bx);
|
z = d2b(dval(&dd[0]), &ex, &bx);
|
||||||
if (dd[1] == 0.)
|
if (dval(&dd[1]) == 0.)
|
||||||
goto no_y;
|
goto no_y;
|
||||||
x = z;
|
x = z;
|
||||||
y = d2b(dd[1], &ey, &by);
|
y = d2b(dval(&dd[1]), &ey, &by);
|
||||||
if ( (i = ex - ey) !=0) {
|
if ( (i = ex - ey) !=0) {
|
||||||
if (i > 0) {
|
if (i > 0) {
|
||||||
x = lshift(x, i);
|
x = lshift(x, i);
|
||||||
|
@ -136,7 +152,7 @@ g_ddfmt(char *buf, double *dd, int ndig, unsigned bufsize)
|
||||||
}
|
}
|
||||||
mode = 2;
|
mode = 2;
|
||||||
if (ndig <= 0) {
|
if (ndig <= 0) {
|
||||||
if (bufsize < (unsigned)((int)(fpi.nbits * .301029995664) + 10)) {
|
if (bufsize < (size_t)((int)(fpi.nbits * .301029995664) + 10)) {
|
||||||
Bfree(z);
|
Bfree(z);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@ -144,11 +160,12 @@ g_ddfmt(char *buf, double *dd, int ndig, unsigned bufsize)
|
||||||
}
|
}
|
||||||
fpi.emin = 1-1023-53+1;
|
fpi.emin = 1-1023-53+1;
|
||||||
fpi.emax = 2046-1023-106+1;
|
fpi.emax = 2046-1023-106+1;
|
||||||
fpi.rounding = FPI_Round_near;
|
fpi.rounding = Rounding;
|
||||||
fpi.sudden_underflow = 0;
|
fpi.sudden_underflow = 0;
|
||||||
|
fpi.int_max = Int_max;
|
||||||
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);
|
||||||
b = g__fmt(buf, s, se, decpt, z->sign);
|
b = g__fmt(buf, s, se, decpt, z->sign, bufsize);
|
||||||
Bfree(z);
|
Bfree(z);
|
||||||
return b;
|
return b;
|
||||||
}
|
}
|
||||||
|
|
|
@ -33,25 +33,32 @@ THIS SOFTWARE.
|
||||||
|
|
||||||
char*
|
char*
|
||||||
#ifdef KR_headers
|
#ifdef KR_headers
|
||||||
g_dfmt(buf, d, ndig, bufsize) char *buf; double *d; int ndig; unsigned bufsize;
|
g_dfmt(buf, d, ndig, bufsize) char *buf; double *d; int ndig; size_t bufsize;
|
||||||
#else
|
#else
|
||||||
g_dfmt(char *buf, double *d, int ndig, unsigned bufsize)
|
g_dfmt(char *buf, double *d, int ndig, size_t bufsize)
|
||||||
#endif
|
#endif
|
||||||
{
|
{
|
||||||
static CONST 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, Int_max };
|
||||||
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;
|
||||||
if (bufsize < (unsigned)(ndig + 10))
|
if (bufsize < (size_t)(ndig + 10))
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
L = (ULong*)d;
|
L = (ULong*)d;
|
||||||
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");
|
||||||
}
|
}
|
||||||
|
@ -78,12 +85,11 @@ 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);
|
if (sign)
|
||||||
return g__fmt(buf, s, se, decpt, sign);
|
i = STRTOG_Normal | STRTOG_Neg;
|
||||||
|
s = gdtoa(fpi, ex, bits, &i, mode, ndig, &decpt, &se);
|
||||||
|
return g__fmt(buf, s, se, decpt, sign, bufsize);
|
||||||
}
|
}
|
||||||
|
|
|
@ -33,19 +33,24 @@ THIS SOFTWARE.
|
||||||
|
|
||||||
char*
|
char*
|
||||||
#ifdef KR_headers
|
#ifdef KR_headers
|
||||||
g_ffmt(buf, f, ndig, bufsize) char *buf; float *f; int ndig; unsigned bufsize;
|
g_ffmt(buf, f, ndig, bufsize) char *buf; float *f; int ndig; size_t bufsize;
|
||||||
#else
|
#else
|
||||||
g_ffmt(char *buf, float *f, int ndig, unsigned bufsize)
|
g_ffmt(char *buf, float *f, int ndig, size_t bufsize)
|
||||||
#endif
|
#endif
|
||||||
{
|
{
|
||||||
static CONST 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, 6 };
|
||||||
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;
|
||||||
if (bufsize < (unsigned)(ndig + 10))
|
if (bufsize < (size_t)(ndig + 10))
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
L = (ULong*)f;
|
L = (ULong*)f;
|
||||||
|
@ -83,6 +88,6 @@ g_ffmt(char *buf, float *f, int ndig, unsigned bufsize)
|
||||||
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);
|
||||||
}
|
}
|
||||||
|
|
|
@ -49,19 +49,24 @@ THIS SOFTWARE.
|
||||||
|
|
||||||
char*
|
char*
|
||||||
#ifdef KR_headers
|
#ifdef KR_headers
|
||||||
g_xLfmt(buf, V, ndig, bufsize) char *buf; char *V; int ndig; unsigned bufsize;
|
g_xLfmt(buf, V, ndig, bufsize) char *buf; char *V; int ndig; size_t bufsize;
|
||||||
#else
|
#else
|
||||||
g_xLfmt(char *buf, void *V, int ndig, unsigned bufsize)
|
g_xLfmt(char *buf, void *V, int ndig, size_t bufsize)
|
||||||
#endif
|
#endif
|
||||||
{
|
{
|
||||||
static CONST 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, Int_max };
|
||||||
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;
|
||||||
if (bufsize < (unsigned)(ndig + 10))
|
if (bufsize < (size_t)(ndig + 10))
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
L = (ULong*)V;
|
L = (ULong*)V;
|
||||||
|
@ -103,6 +108,6 @@ g_xLfmt(char *buf, void *V, int ndig, unsigned bufsize)
|
||||||
return 0;
|
return 0;
|
||||||
mode = 0;
|
mode = 0;
|
||||||
}
|
}
|
||||||
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);
|
||||||
}
|
}
|
||||||
|
|
|
@ -53,20 +53,25 @@ THIS SOFTWARE.
|
||||||
|
|
||||||
char*
|
char*
|
||||||
#ifdef KR_headers
|
#ifdef KR_headers
|
||||||
g_xfmt(buf, V, ndig, bufsize) char *buf; char *V; int ndig; unsigned bufsize;
|
g_xfmt(buf, V, ndig, bufsize) char *buf; char *V; int ndig; size_t bufsize;
|
||||||
#else
|
#else
|
||||||
g_xfmt(char *buf, void *V, int ndig, unsigned bufsize)
|
g_xfmt(char *buf, void *V, int ndig, size_t bufsize)
|
||||||
#endif
|
#endif
|
||||||
{
|
{
|
||||||
static CONST 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, Int_max };
|
||||||
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;
|
||||||
|
#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 < (unsigned)(ndig + 10))
|
if (bufsize < (size_t)(ndig + 10))
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
L = (UShort *)V;
|
L = (UShort *)V;
|
||||||
|
@ -76,14 +81,14 @@ g_xfmt(char *buf, void *V, int ndig, unsigned bufsize)
|
||||||
if ( (ex = L[_0] & 0x7fff) !=0) {
|
if ( (ex = L[_0] & 0x7fff) !=0) {
|
||||||
if (ex == 0x7fff) {
|
if (ex == 0x7fff) {
|
||||||
/* Infinity or NaN */
|
/* Infinity or NaN */
|
||||||
if (bits[0] | bits[1])
|
if (!bits[0] && bits[1]== 0x80000000) {
|
||||||
b = strcp(buf, "NaN");
|
|
||||||
else {
|
|
||||||
b = buf;
|
b = buf;
|
||||||
if (sign)
|
if (sign)
|
||||||
*b++ = '-';
|
*b++ = '-';
|
||||||
b = strcp(b, "Infinity");
|
b = strcp(b, "Infinity");
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
b = strcp(buf, "NaN");
|
||||||
return b;
|
return b;
|
||||||
}
|
}
|
||||||
i = STRTOG_Normal;
|
i = STRTOG_Normal;
|
||||||
|
@ -109,6 +114,6 @@ g_xfmt(char *buf, void *V, int ndig, unsigned bufsize)
|
||||||
return 0;
|
return 0;
|
||||||
mode = 0;
|
mode = 0;
|
||||||
}
|
}
|
||||||
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);
|
||||||
}
|
}
|
||||||
|
|
188
gdtoa/gdtoa.c
188
gdtoa/gdtoa.c
|
@ -30,7 +30,6 @@ THIS SOFTWARE.
|
||||||
* with " at " changed at "@" and " dot " changed to "."). */
|
* with " at " changed at "@" and " dot " changed to "."). */
|
||||||
|
|
||||||
#include "gdtoaimp.h"
|
#include "gdtoaimp.h"
|
||||||
#include <limits.h>
|
|
||||||
|
|
||||||
static Bigint *
|
static Bigint *
|
||||||
#ifdef KR_headers
|
#ifdef KR_headers
|
||||||
|
@ -62,7 +61,7 @@ bitstob(ULong *bits, int nbits, int *bbits)
|
||||||
*x++ = (*bits >> 16) & ALL_ON;
|
*x++ = (*bits >> 16) & ALL_ON;
|
||||||
#endif
|
#endif
|
||||||
} while(++bits <= be);
|
} while(++bits <= be);
|
||||||
i = (int)(x - x0);
|
i = x - x0;
|
||||||
while(!x0[--i])
|
while(!x0[--i])
|
||||||
if (!i) {
|
if (!i) {
|
||||||
b->wds = 0;
|
b->wds = 0;
|
||||||
|
@ -116,14 +115,15 @@ gdtoa
|
||||||
FPI *fpi; int be; ULong *bits;
|
FPI *fpi; int be; ULong *bits;
|
||||||
int *kindp, mode, ndigits, *decpt; char **rve;
|
int *kindp, mode, ndigits, *decpt; char **rve;
|
||||||
#else
|
#else
|
||||||
(CONST FPI *fpi, int be, ULong *bits, int *kindp, int mode, int ndigits, int *decpt, char **rve)
|
(FPI *fpi, int be, ULong *bits, int *kindp, int mode, int ndigits, int *decpt, char **rve)
|
||||||
#endif
|
#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
|
||||||
the returned string. If not null, *rve is set to point
|
the returned string. If not null, *rve is set to point
|
||||||
to the end of the return value. If d is +-Infinity or NaN,
|
to the end of the return value. If d is +-Infinity or NaN,
|
||||||
then *decpt is set to INT_MAX.
|
then *decpt is set to 9999.
|
||||||
|
be = exponent: value = (integer represented by bits) * (2 to the power of be).
|
||||||
|
|
||||||
mode:
|
mode:
|
||||||
0 ==> shortest string that yields d when read in
|
0 ==> shortest string that yields d when read in
|
||||||
|
@ -159,8 +159,8 @@ gdtoa
|
||||||
Long L;
|
Long L;
|
||||||
Bigint *b, *b1, *delta, *mlo, *mhi, *mhi1, *S;
|
Bigint *b, *b1, *delta, *mlo, *mhi, *mhi1, *S;
|
||||||
double d2, ds;
|
double d2, ds;
|
||||||
U d, eps;
|
|
||||||
char *s, *s0;
|
char *s, *s0;
|
||||||
|
U d, eps;
|
||||||
|
|
||||||
#ifndef MULTIPLE_THREADS
|
#ifndef MULTIPLE_THREADS
|
||||||
if (dtoa_result) {
|
if (dtoa_result) {
|
||||||
|
@ -177,10 +177,10 @@ gdtoa
|
||||||
case STRTOG_Denormal:
|
case STRTOG_Denormal:
|
||||||
break;
|
break;
|
||||||
case STRTOG_Infinite:
|
case STRTOG_Infinite:
|
||||||
*decpt = INT_MAX;
|
*decpt = -32768;
|
||||||
return nrv_alloc("Infinity", rve, 8);
|
return nrv_alloc("Infinity", rve, 8);
|
||||||
case STRTOG_NaN:
|
case STRTOG_NaN:
|
||||||
*decpt = INT_MAX;
|
*decpt = -32768;
|
||||||
return nrv_alloc("NaN", rve, 3);
|
return nrv_alloc("NaN", rve, 3);
|
||||||
default:
|
default:
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -199,21 +199,21 @@ gdtoa
|
||||||
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
|
#ifdef IBM
|
||||||
if ( (j = 11 - hi0bits(word0(d) & Frac_mask)) !=0)
|
if ( (j = 11 - hi0bits(word0(&d) & Frac_mask)) !=0)
|
||||||
dval(d) /= 1 << j;
|
dval(&d) /= 1 << j;
|
||||||
#endif
|
#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 );
|
||||||
|
@ -233,7 +233,7 @@ gdtoa
|
||||||
i <<= 2;
|
i <<= 2;
|
||||||
i += j;
|
i += j;
|
||||||
#endif
|
#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 */
|
/* correct assumption about exponent range */
|
||||||
if ((j = i) < 0)
|
if ((j = i) < 0)
|
||||||
|
@ -248,13 +248,13 @@ gdtoa
|
||||||
#ifdef IBM
|
#ifdef IBM
|
||||||
j = be + bbits - 1;
|
j = be + bbits - 1;
|
||||||
if ( (j1 = j & 3) !=0)
|
if ( (j1 = j & 3) !=0)
|
||||||
dval(d) *= 1 << j1;
|
dval(&d) *= 1 << j1;
|
||||||
word0(d) += j << Exp_shift - 2 & Exp_mask;
|
word0(&d) += j << Exp_shift - 2 & Exp_mask;
|
||||||
#else
|
#else
|
||||||
word0(d) += (be + bbits - 1) << Exp_shift;
|
word0(&d) += (be + bbits - 1) << Exp_shift;
|
||||||
#endif
|
#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;
|
||||||
}
|
}
|
||||||
|
@ -284,11 +284,14 @@ gdtoa
|
||||||
mode -= 4;
|
mode -= 4;
|
||||||
try_quick = 0;
|
try_quick = 0;
|
||||||
}
|
}
|
||||||
|
else if (i >= -4 - Emin || i < Emin)
|
||||||
|
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;
|
||||||
|
@ -330,10 +333,10 @@ 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
|
#ifdef IBM
|
||||||
if ( (j = 11 - hi0bits(word0(d) & Frac_mask)) !=0)
|
if ( (j = 11 - hi0bits(word0(&d) & Frac_mask)) !=0)
|
||||||
dval(d) /= 1 << j;
|
dval(&d) /= 1 << j;
|
||||||
#endif
|
#endif
|
||||||
k0 = k;
|
k0 = k;
|
||||||
ilim0 = ilim;
|
ilim0 = ilim;
|
||||||
|
@ -344,7 +347,7 @@ 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++)
|
||||||
|
@ -356,30 +359,30 @@ gdtoa
|
||||||
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;
|
||||||
}
|
}
|
||||||
|
@ -388,42 +391,40 @@ gdtoa
|
||||||
/* 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;
|
||||||
}
|
}
|
||||||
|
@ -433,34 +434,34 @@ gdtoa
|
||||||
#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? */
|
||||||
|
|
||||||
if (be >= 0 && k <= Int_max) {
|
if (be >= 0 && k <= fpi->int_max) {
|
||||||
/* Yes. */
|
/* Yes. */
|
||||||
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) == 0.)
|
if (dval(&d) == 0.)
|
||||||
break;
|
break;
|
||||||
if (i == ilim) {
|
if (i == ilim) {
|
||||||
if (rdir) {
|
if (rdir) {
|
||||||
|
@ -469,8 +470,13 @@ gdtoa
|
||||||
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) {
|
#ifdef ROUND_BIASED
|
||||||
|
if (dval(&d) >= ds)
|
||||||
|
#else
|
||||||
|
if (dval(&d) > ds || (dval(&d) == ds && L & 1))
|
||||||
|
#endif
|
||||||
|
{
|
||||||
bump_up:
|
bump_up:
|
||||||
inex = STRTOG_Inexhi;
|
inex = STRTOG_Inexhi;
|
||||||
while(*--s == '9')
|
while(*--s == '9')
|
||||||
|
@ -481,8 +487,12 @@ gdtoa
|
||||||
}
|
}
|
||||||
++*s++;
|
++*s++;
|
||||||
}
|
}
|
||||||
else
|
else {
|
||||||
inex = STRTOG_Inexlo;
|
inex = STRTOG_Inexlo;
|
||||||
|
clear_trailing0:
|
||||||
|
while(*--s == '0'){}
|
||||||
|
++s;
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -493,13 +503,15 @@ gdtoa
|
||||||
m5 = b5;
|
m5 = b5;
|
||||||
mhi = mlo = 0;
|
mhi = mlo = 0;
|
||||||
if (leftright) {
|
if (leftright) {
|
||||||
if (mode < 2) {
|
|
||||||
i = nbits - bbits;
|
i = nbits - bbits;
|
||||||
if (be - i++ < fpi->emin)
|
if (be - i++ < fpi->emin && mode != 3 && mode != 5) {
|
||||||
/* denormal */
|
/* denormal */
|
||||||
i = be - fpi->emin + 1;
|
i = be - fpi->emin + 1;
|
||||||
|
if (mode >= 2 && ilim > 0 && ilim < i)
|
||||||
|
goto small_ilim;
|
||||||
}
|
}
|
||||||
else {
|
else if (mode >= 2) {
|
||||||
|
small_ilim:
|
||||||
j = ilim - 1;
|
j = ilim - 1;
|
||||||
if (m5 >= j)
|
if (m5 >= j)
|
||||||
m5 -= j;
|
m5 -= j;
|
||||||
|
@ -560,28 +572,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)
|
|
||||||
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;
|
|
||||||
m2 += i;
|
m2 += i;
|
||||||
s2 += i;
|
if ((b2 += i) > 0)
|
||||||
}
|
|
||||||
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) {
|
||||||
|
@ -646,11 +641,11 @@ gdtoa
|
||||||
goto ret;
|
goto ret;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
if (j < 0 || j == 0 && !mode
|
if (j < 0 || (j == 0 && !mode
|
||||||
#ifndef ROUND_BIASED
|
#ifndef ROUND_BIASED
|
||||||
&& !(bits[0] & 1)
|
&& !(bits[0] & 1)
|
||||||
#endif
|
#endif
|
||||||
) {
|
)) {
|
||||||
if (rdir && (b->wds > 1 || b->x[0])) {
|
if (rdir && (b->wds > 1 || b->x[0])) {
|
||||||
if (rdir == 2) {
|
if (rdir == 2) {
|
||||||
inex = STRTOG_Inexlo;
|
inex = STRTOG_Inexlo;
|
||||||
|
@ -673,7 +668,11 @@ gdtoa
|
||||||
if (j1 > 0) {
|
if (j1 > 0) {
|
||||||
b = lshift(b, 1);
|
b = lshift(b, 1);
|
||||||
j1 = cmp(b, S);
|
j1 = cmp(b, S);
|
||||||
if ((j1 > 0 || j1 == 0 && dig & 1)
|
#ifdef ROUND_BIASED
|
||||||
|
if (j1 >= 0 /*)*/
|
||||||
|
#else
|
||||||
|
if ((j1 > 0 || (j1 == 0 && dig & 1))
|
||||||
|
#endif
|
||||||
&& dig++ == '9')
|
&& dig++ == '9')
|
||||||
goto round_9_up;
|
goto round_9_up;
|
||||||
inex = STRTOG_Inexhi;
|
inex = STRTOG_Inexhi;
|
||||||
|
@ -718,13 +717,18 @@ gdtoa
|
||||||
/* Round off last digit */
|
/* Round off last digit */
|
||||||
|
|
||||||
if (rdir) {
|
if (rdir) {
|
||||||
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) {
|
#ifdef ROUND_BIASED
|
||||||
|
if (j >= 0)
|
||||||
|
#else
|
||||||
|
if (j > 0 || (j == 0 && dig & 1))
|
||||||
|
#endif
|
||||||
|
{
|
||||||
roundoff:
|
roundoff:
|
||||||
inex = STRTOG_Inexhi;
|
inex = STRTOG_Inexhi;
|
||||||
while(*--s == '9')
|
while(*--s == '9')
|
||||||
|
@ -740,7 +744,7 @@ gdtoa
|
||||||
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);
|
||||||
|
|
|
@ -66,16 +66,13 @@ THIS SOFTWARE.
|
||||||
#else
|
#else
|
||||||
#include "arith.h"
|
#include "arith.h"
|
||||||
#endif
|
#endif
|
||||||
|
#include <stddef.h> /* for size_t */
|
||||||
|
|
||||||
/* [RH] On 64-bit Unix systems, long is a 64-bit type. I do not that is
|
|
||||||
* is what is desired here, so I sacrifice compatibility with systems
|
|
||||||
* that use 16-bit ints (oh no!) and make Long an int instead.
|
|
||||||
*/
|
|
||||||
#ifndef Long
|
#ifndef Long
|
||||||
typedef int Long;
|
#define Long int
|
||||||
#endif
|
#endif
|
||||||
#ifndef ULong
|
#ifndef ULong
|
||||||
typedef unsigned int ULong;
|
typedef unsigned Long ULong;
|
||||||
#endif
|
#endif
|
||||||
#ifndef UShort
|
#ifndef UShort
|
||||||
typedef unsigned short UShort;
|
typedef unsigned short UShort;
|
||||||
|
@ -111,9 +108,9 @@ 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
|
||||||
|
@ -126,6 +123,7 @@ FPI {
|
||||||
int emax;
|
int emax;
|
||||||
int rounding;
|
int rounding;
|
||||||
int sudden_underflow;
|
int sudden_underflow;
|
||||||
|
int int_max;
|
||||||
} FPI;
|
} FPI;
|
||||||
|
|
||||||
enum { /* FPI.rounding values: same as FLT_ROUNDS */
|
enum { /* FPI.rounding values: same as FLT_ROUNDS */
|
||||||
|
@ -135,29 +133,31 @@ enum { /* FPI.rounding values: same as FLT_ROUNDS */
|
||||||
FPI_Round_down = 3
|
FPI_Round_down = 3
|
||||||
};
|
};
|
||||||
|
|
||||||
// Our strtod is not the CRT's strtod.
|
|
||||||
#include <stdlib.h>
|
|
||||||
#define strtod mystrtod
|
|
||||||
|
|
||||||
#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 ANSI((double d, int mode, int ndigits, int *decpt,
|
||||||
int *sign, char **rve));
|
int *sign, char **rve));
|
||||||
extern char* gdtoa ANSI((CONST FPI *fpi, int be, ULong *bits, int *kindp,
|
extern char* gdtoa ANSI((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 ANSI((char*));
|
||||||
extern float strtof ANSI((CONST char *, char **));
|
extern float strtof ANSI((CONST char *, char **));
|
||||||
extern double strtod ANSI((CONST char *, char **));
|
extern double strtod ANSI((CONST char *, char **));
|
||||||
extern int strtodg ANSI((CONST char*, char**, CONST FPI*, Long*, ULong*));
|
extern int strtodg ANSI((CONST char*, char**, FPI*, Long*, ULong*));
|
||||||
|
|
||||||
extern char* g_ddfmt ANSI((char*, double*, int, unsigned));
|
extern char* g_ddfmt ANSI((char*, double*, int, size_t));
|
||||||
extern char* g_dfmt ANSI((char*, double*, int, unsigned));
|
extern char* g_ddfmt_p ANSI((char*, double*, int, size_t, int));
|
||||||
extern char* g_ffmt ANSI((char*, float*, int, unsigned));
|
extern char* g_dfmt ANSI((char*, double*, int, size_t));
|
||||||
extern char* g_Qfmt ANSI((char*, void*, int, unsigned));
|
extern char* g_dfmt_p ANSI((char*, double*, int, size_t, int));
|
||||||
extern char* g_xfmt ANSI((char*, void*, int, unsigned));
|
extern char* g_ffmt ANSI((char*, float*, int, size_t));
|
||||||
extern char* g_xLfmt ANSI((char*, void*, int, unsigned));
|
extern char* g_ffmt_p ANSI((char*, float*, int, size_t, int));
|
||||||
|
extern char* g_Qfmt ANSI((char*, void*, int, size_t));
|
||||||
|
extern char* g_Qfmt_p ANSI((char*, void*, int, size_t, int));
|
||||||
|
extern char* g_xfmt ANSI((char*, void*, int, size_t));
|
||||||
|
extern char* g_xfmt_p ANSI((char*, void*, int, size_t, int));
|
||||||
|
extern char* g_xLfmt ANSI((char*, void*, int, size_t));
|
||||||
|
extern char* g_xLfmt_p ANSI((char*, void*, int, size_t, int));
|
||||||
|
|
||||||
extern int strtoId ANSI((CONST char*, char**, double*, double*));
|
extern int strtoId ANSI((CONST char*, char**, double*, double*));
|
||||||
extern int strtoIdd ANSI((CONST char*, char**, double*, double*));
|
extern int strtoIdd ANSI((CONST char*, char**, double*, double*));
|
||||||
|
|
18
gdtoa/gdtoa_fltrnds.h
Normal file
18
gdtoa/gdtoa_fltrnds.h
Normal 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;
|
||||||
|
}
|
|
@ -89,12 +89,18 @@ THIS SOFTWARE.
|
||||||
* #define IBM for IBM mainframe-style floating-point arithmetic.
|
* #define IBM for IBM mainframe-style floating-point arithmetic.
|
||||||
* #define VAX for VAX-style floating-point arithmetic (D_floating).
|
* #define VAX for VAX-style floating-point arithmetic (D_floating).
|
||||||
* #define No_leftright to omit left-right logic in fast floating-point
|
* #define No_leftright to omit left-right logic in fast floating-point
|
||||||
* computation of dtoa.
|
* computation of dtoa and gdtoa. This will cause modes 4 and 5 to be
|
||||||
|
* treated the same as modes 2 and 3 for some inputs.
|
||||||
* #define Check_FLT_ROUNDS if FLT_ROUNDS can assume the values 2 or 3.
|
* #define Check_FLT_ROUNDS if FLT_ROUNDS can assume the values 2 or 3.
|
||||||
* #define RND_PRODQUOT to use rnd_prod and rnd_quot (assembly routines
|
* #define RND_PRODQUOT to use rnd_prod and rnd_quot (assembly routines
|
||||||
* that use extended-precision instructions to compute rounded
|
* that use extended-precision instructions to compute rounded
|
||||||
* products and quotients) with IBM.
|
* products and quotients) with IBM.
|
||||||
* #define ROUND_BIASED for IEEE-format with biased rounding.
|
* #define ROUND_BIASED for IEEE-format with biased rounding and arithmetic
|
||||||
|
* that rounds toward +Infinity.
|
||||||
|
* #define ROUND_BIASED_without_Round_Up for IEEE-format with biased
|
||||||
|
* rounding when the underlying floating-point arithmetic uses
|
||||||
|
* unbiased rounding. This prevent using ordinary floating-point
|
||||||
|
* arithmetic when the result could be computed with one rounding error.
|
||||||
* #define Inaccurate_Divide for IEEE-format with correctly rounded
|
* #define Inaccurate_Divide for IEEE-format with correctly rounded
|
||||||
* products but inaccurate quotients, e.g., for Intel i860.
|
* products but inaccurate quotients, e.g., for Intel i860.
|
||||||
* #define NO_LONG_LONG on machines that do not have a "long long"
|
* #define NO_LONG_LONG on machines that do not have a "long long"
|
||||||
|
@ -113,7 +119,12 @@ THIS SOFTWARE.
|
||||||
* #define MALLOC your_malloc, where your_malloc(n) acts like malloc(n)
|
* #define MALLOC your_malloc, where your_malloc(n) acts like malloc(n)
|
||||||
* if memory is available and otherwise does something you deem
|
* if memory is available and otherwise does something you deem
|
||||||
* appropriate. If MALLOC is undefined, malloc will be invoked
|
* appropriate. If MALLOC is undefined, malloc will be invoked
|
||||||
* directly -- and assumed always to succeed.
|
* directly -- and assumed always to succeed. Similarly, if you
|
||||||
|
* want something other than the system's free() to be called to
|
||||||
|
* recycle memory acquired from MALLOC, #define FREE to be the
|
||||||
|
* name of the alternate routine. (FREE or free is only called in
|
||||||
|
* pathological cases, e.g., in a gdtoa call after a gdtoa return in
|
||||||
|
* mode 3 with thousands of digits requested.)
|
||||||
* #define Omit_Private_Memory to omit logic (added Jan. 1998) for making
|
* #define Omit_Private_Memory to omit logic (added Jan. 1998) for making
|
||||||
* memory allocations from a private pool of memory when possible.
|
* memory allocations from a private pool of memory when possible.
|
||||||
* When used, the private pool is PRIVATE_MEM bytes long: 2304 bytes,
|
* When used, the private pool is PRIVATE_MEM bytes long: 2304 bytes,
|
||||||
|
@ -126,8 +137,10 @@ 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 (optionally
|
* NaN(x), where x is a string of hexadecimal digits (optionally
|
||||||
|
@ -151,7 +164,7 @@ THIS SOFTWARE.
|
||||||
* dtoa. You may do so whether or not MULTIPLE_THREADS is #defined.
|
* dtoa. You may do so whether or not MULTIPLE_THREADS is #defined.
|
||||||
* #define IMPRECISE_INEXACT if you do not care about the setting of
|
* #define IMPRECISE_INEXACT if you do not care about the setting of
|
||||||
* the STRTOG_Inexact bits in the special case of doing IEEE double
|
* the STRTOG_Inexact bits in the special case of doing IEEE double
|
||||||
* precision conversions (which could also be done by the strtog in
|
* precision conversions (which could also be done by the strtod in
|
||||||
* dtoa.c).
|
* dtoa.c).
|
||||||
* #define NO_HEX_FP to disable recognition of C9x's hexadecimal
|
* #define NO_HEX_FP to disable recognition of C9x's hexadecimal
|
||||||
* floating-point constants.
|
* floating-point constants.
|
||||||
|
@ -220,6 +233,10 @@ THIS SOFTWARE.
|
||||||
#include "gd_qnan.h"
|
#include "gd_qnan.h"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#ifdef Honor_FLT_ROUNDS
|
||||||
|
#include <fenv.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
#ifdef DEBUG
|
#ifdef DEBUG
|
||||||
#include "stdio.h"
|
#include "stdio.h"
|
||||||
#define Bug(x) {fprintf(stderr, "%s\n", x); exit(1);}
|
#define Bug(x) {fprintf(stderr, "%s\n", x); exit(1);}
|
||||||
|
@ -229,13 +246,13 @@ THIS SOFTWARE.
|
||||||
#include "string.h"
|
#include "string.h"
|
||||||
|
|
||||||
#ifdef KR_headers
|
#ifdef KR_headers
|
||||||
#define KR_VOID char
|
#define Char char
|
||||||
#else
|
#else
|
||||||
#define KR_VOID void
|
#define Char void
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef MALLOC
|
#ifdef MALLOC
|
||||||
extern KR_VOID *MALLOC ANSI((size_t));
|
extern Char *MALLOC ANSI((size_t));
|
||||||
#else
|
#else
|
||||||
#define MALLOC malloc
|
#define MALLOC malloc
|
||||||
#endif
|
#endif
|
||||||
|
@ -307,19 +324,19 @@ extern "C" {
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if defined(IEEE_8087) + defined(IEEE_MC68k) + defined(VAX) + defined(IBM) != 1
|
#if defined(IEEE_8087) + defined(IEEE_MC68k) + defined(VAX) + defined(IBM) != 1
|
||||||
#error 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 { double d; ULong L[2]; } U;
|
||||||
|
|
||||||
#ifdef IEEE_8087
|
#ifdef IEEE_8087
|
||||||
#define word0(x) x.L[1]
|
#define word0(x) (x)->L[1]
|
||||||
#define word1(x) x.L[0]
|
#define word1(x) (x)->L[0]
|
||||||
#else
|
#else
|
||||||
#define word0(x) x.L[0]
|
#define word0(x) (x)->L[0]
|
||||||
#define word1(x) x.L[1]
|
#define word1(x) (x)->L[1]
|
||||||
#endif
|
#endif
|
||||||
#define dval(x) x.d
|
#define dval(x) (x)->d
|
||||||
|
|
||||||
/* 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
|
||||||
|
@ -433,6 +450,11 @@ typedef union { double d; ULong L[2]; } U;
|
||||||
|
|
||||||
#ifndef IEEE_Arith
|
#ifndef IEEE_Arith
|
||||||
#define ROUND_BIASED
|
#define ROUND_BIASED
|
||||||
|
#else
|
||||||
|
#ifdef ROUND_BIASED_without_Round_Up
|
||||||
|
#undef ROUND_BIASED
|
||||||
|
#define ROUND_BIASED
|
||||||
|
#endif
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef RND_PRODQUOT
|
#ifdef RND_PRODQUOT
|
||||||
|
@ -488,12 +510,12 @@ extern double rnd_prod(double, double), rnd_quot(double, double);
|
||||||
#define ALL_ON 0xffff
|
#define ALL_ON 0xffff
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifndef MULTIPLE_THREADS
|
//#ifndef MULTIPLE_THREADS
|
||||||
#define ACQUIRE_DTOA_LOCK(n) /*nothing*/
|
#define ACQUIRE_DTOA_LOCK(n) /*nothing*/
|
||||||
#define FREE_DTOA_LOCK(n) /*nothing*/
|
#define FREE_DTOA_LOCK(n) /*nothing*/
|
||||||
#endif
|
//#endif
|
||||||
|
|
||||||
#define Kmax (sizeof(size_t) << 3)
|
#define Kmax 9
|
||||||
|
|
||||||
struct
|
struct
|
||||||
Bigint {
|
Bigint {
|
||||||
|
@ -516,12 +538,15 @@ extern void memcpy_D2A ANSI((void*, const void*, size_t));
|
||||||
|
|
||||||
#define Balloc Balloc_D2A
|
#define Balloc Balloc_D2A
|
||||||
#define Bfree Bfree_D2A
|
#define Bfree Bfree_D2A
|
||||||
|
#define InfName InfName_D2A
|
||||||
|
#define NanName NanName_D2A
|
||||||
#define ULtoQ ULtoQ_D2A
|
#define ULtoQ ULtoQ_D2A
|
||||||
#define ULtof ULtof_D2A
|
#define ULtof ULtof_D2A
|
||||||
#define ULtod ULtod_D2A
|
#define ULtod ULtod_D2A
|
||||||
#define ULtodd ULtodd_D2A
|
#define ULtodd ULtodd_D2A
|
||||||
#define ULtox ULtox_D2A
|
#define ULtox ULtox_D2A
|
||||||
#define ULtoxL ULtoxL_D2A
|
#define ULtoxL ULtoxL_D2A
|
||||||
|
#define add_nanbits add_nanbits_D2A
|
||||||
#define any_on any_on_D2A
|
#define any_on any_on_D2A
|
||||||
#define b2d b2d_D2A
|
#define b2d b2d_D2A
|
||||||
#define bigtens bigtens_D2A
|
#define bigtens bigtens_D2A
|
||||||
|
@ -560,9 +585,11 @@ extern void memcpy_D2A ANSI((void*, const void*, size_t));
|
||||||
#define trailz trailz_D2A
|
#define trailz trailz_D2A
|
||||||
#define ulp ulp_D2A
|
#define ulp ulp_D2A
|
||||||
|
|
||||||
|
extern char *add_nanbits ANSI((char*, size_t, ULong*, int));
|
||||||
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 const char *InfName[6], *NanName[3];
|
||||||
|
|
||||||
extern Bigint *Balloc ANSI((int));
|
extern Bigint *Balloc ANSI((int));
|
||||||
extern void Bfree ANSI((Bigint*));
|
extern void Bfree ANSI((Bigint*));
|
||||||
|
@ -577,14 +604,14 @@ extern void memcpy_D2A ANSI((void*, const void*, size_t));
|
||||||
extern int cmp ANSI((Bigint*, Bigint*));
|
extern int cmp ANSI((Bigint*, Bigint*));
|
||||||
extern void copybits ANSI((ULong*, int, Bigint*));
|
extern void copybits ANSI((ULong*, int, Bigint*));
|
||||||
extern Bigint *d2b ANSI((double, int*, int*));
|
extern Bigint *d2b ANSI((double, int*, int*));
|
||||||
extern int decrement ANSI((Bigint*));
|
extern void decrement ANSI((Bigint*));
|
||||||
extern Bigint *diff ANSI((Bigint*, Bigint*));
|
extern Bigint *diff ANSI((Bigint*, Bigint*));
|
||||||
extern char *dtoa ANSI((double d, int mode, int ndigits,
|
extern char *dtoa ANSI((double d, int mode, int ndigits,
|
||||||
int *decpt, int *sign, char **rve));
|
int *decpt, int *sign, char **rve));
|
||||||
extern char *g__fmt ANSI((char*, char*, char*, int, ULong));
|
extern char *g__fmt ANSI((char*, char*, char*, int, ULong, size_t));
|
||||||
extern int gethex ANSI((CONST char**, CONST FPI*, Long*, Bigint**, int));
|
extern int gethex ANSI((CONST char**, FPI*, Long*, Bigint**, int));
|
||||||
extern void hexdig_init_D2A(Void);
|
extern void hexdig_init_D2A(Void);
|
||||||
extern int hexnan ANSI((CONST char**, CONST FPI*, ULong*));
|
extern int hexnan ANSI((CONST char**, FPI*, ULong*));
|
||||||
extern int hi0bits_D2A ANSI((ULong));
|
extern int hi0bits_D2A ANSI((ULong));
|
||||||
extern Bigint *i2b ANSI((int));
|
extern Bigint *i2b ANSI((int));
|
||||||
extern Bigint *increment ANSI((Bigint*));
|
extern Bigint *increment ANSI((Bigint*));
|
||||||
|
@ -599,14 +626,14 @@ extern void memcpy_D2A ANSI((void*, const void*, size_t));
|
||||||
extern double ratio ANSI((Bigint*, Bigint*));
|
extern double ratio ANSI((Bigint*, Bigint*));
|
||||||
extern void rshift ANSI((Bigint*, int));
|
extern void rshift ANSI((Bigint*, int));
|
||||||
extern char *rv_alloc ANSI((int));
|
extern char *rv_alloc ANSI((int));
|
||||||
extern Bigint *s2b ANSI((CONST char*, int, int, ULong));
|
extern Bigint *s2b ANSI((CONST char*, int, int, ULong, int));
|
||||||
extern Bigint *set_ones ANSI((Bigint*, int));
|
extern Bigint *set_ones ANSI((Bigint*, int));
|
||||||
extern char *strcp ANSI((char*, const char*));
|
extern char *strcp ANSI((char*, const char*));
|
||||||
extern int strtoIg ANSI((CONST char*, char**, CONST FPI*, Long*, Bigint**, int*));
|
extern int strtoIg ANSI((CONST char*, char**, FPI*, Long*, Bigint**, int*));
|
||||||
extern double strtod ANSI((const char *s00, char **se));
|
extern double strtod ANSI((const char *s00, char **se));
|
||||||
extern Bigint *sum ANSI((Bigint*, Bigint*));
|
extern Bigint *sum ANSI((Bigint*, Bigint*));
|
||||||
extern int trailz ANSI((Bigint*));
|
extern int trailz ANSI((Bigint*));
|
||||||
extern double ulp ANSI((double));
|
extern double ulp ANSI((U*));
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
|
@ -621,6 +648,10 @@ extern void memcpy_D2A ANSI((void*, const void*, size_t));
|
||||||
* (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
|
||||||
|
|
153
gdtoa/gethex.c
153
gdtoa/gethex.c
|
@ -40,22 +40,34 @@ THIS SOFTWARE.
|
||||||
gethex(sp, fpi, exp, bp, sign)
|
gethex(sp, fpi, exp, bp, sign)
|
||||||
CONST char **sp; FPI *fpi; Long *exp; Bigint **bp; int sign;
|
CONST char **sp; FPI *fpi; Long *exp; Bigint **bp; int sign;
|
||||||
#else
|
#else
|
||||||
gethex( CONST char **sp, CONST FPI *fpi, Long *exp, Bigint **bp, int sign)
|
gethex( CONST char **sp, FPI *fpi, Long *exp, Bigint **bp, int sign)
|
||||||
#endif
|
#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;
|
||||||
|
#ifdef NO_LOCALE_CACHE
|
||||||
|
const unsigned char *decimalpoint = (unsigned char*)localeconv()->decimal_point;
|
||||||
#else
|
#else
|
||||||
#define decimalpoint '.'
|
const unsigned char *decimalpoint;
|
||||||
|
static unsigned char *decimalpoint_cache;
|
||||||
|
if (!(s0 = decimalpoint_cache)) {
|
||||||
|
s0 = (unsigned char*)localeconv()->decimal_point;
|
||||||
|
if ((decimalpoint_cache = (char*)MALLOC(strlen(s0) + 1))) {
|
||||||
|
strcpy(decimalpoint_cache, 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')
|
||||||
|
@ -65,11 +77,21 @@ gethex( CONST char **sp, CONST 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')
|
||||||
|
@ -81,19 +103,28 @@ gethex( CONST char **sp, CONST FPI *fpi, Long *exp, Bigint **bp, int sign)
|
||||||
}
|
}
|
||||||
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;
|
||||||
|
@ -106,29 +137,87 @@ gethex( CONST char **sp, CONST FPI *fpi, Long *exp, Bigint **bp, int sign)
|
||||||
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 (zret) {
|
|
||||||
if (!havedig)
|
if (!havedig)
|
||||||
*sp = s0 - 1;
|
*sp = (char*)s0 - 1;
|
||||||
|
if (zret)
|
||||||
return STRTOG_Zero;
|
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;
|
||||||
}
|
}
|
||||||
n = (int)(s1 - s0 - 1);
|
goto retz;
|
||||||
for(k = 0; n > 7; n >>= 1)
|
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 > (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;
|
||||||
|
@ -137,8 +226,8 @@ gethex( CONST char **sp, CONST FPI *fpi, Long *exp, Bigint **bp, int sign)
|
||||||
n += 4;
|
n += 4;
|
||||||
}
|
}
|
||||||
*x++ = L;
|
*x++ = L;
|
||||||
b->wds = n = (int)(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;
|
||||||
|
@ -149,7 +238,7 @@ gethex( CONST char **sp, CONST 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;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -165,7 +254,10 @@ gethex( CONST char **sp, CONST FPI *fpi, Long *exp, Bigint **bp, int sign)
|
||||||
if (e > fpi->emax) {
|
if (e > fpi->emax) {
|
||||||
ovfl:
|
ovfl:
|
||||||
Bfree(b);
|
Bfree(b);
|
||||||
*bp = 0;
|
ovfl1:
|
||||||
|
#ifndef NO_ERRNO
|
||||||
|
errno = ERANGE;
|
||||||
|
#endif
|
||||||
return STRTOG_Infinite | STRTOG_Overflow | STRTOG_Inexhi;
|
return STRTOG_Infinite | STRTOG_Overflow | STRTOG_Inexhi;
|
||||||
}
|
}
|
||||||
irv = STRTOG_Normal;
|
irv = STRTOG_Normal;
|
||||||
|
@ -185,15 +277,22 @@ gethex( CONST char **sp, CONST 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;
|
||||||
|
#ifndef NO_ERRNO
|
||||||
|
errno = ERANGE;
|
||||||
|
#endif
|
||||||
return STRTOG_Denormal | STRTOG_Inexhi
|
return STRTOG_Denormal | STRTOG_Inexhi
|
||||||
| STRTOG_Underflow;
|
| STRTOG_Underflow;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Bfree(b);
|
Bfree(b);
|
||||||
*bp = 0;
|
retz:
|
||||||
|
#ifndef NO_ERRNO
|
||||||
|
errno = ERANGE;
|
||||||
|
#endif
|
||||||
return STRTOG_Zero | STRTOG_Inexlo | STRTOG_Underflow;
|
return STRTOG_Zero | STRTOG_Inexlo | STRTOG_Underflow;
|
||||||
}
|
}
|
||||||
k = n - 1;
|
k = n - 1;
|
||||||
|
@ -214,7 +313,7 @@ gethex( CONST char **sp, CONST 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:
|
||||||
|
@ -233,8 +332,8 @@ gethex( CONST char **sp, CONST FPI *fpi, Long *exp, Bigint **bp, int sign)
|
||||||
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;
|
||||||
|
|
|
@ -60,7 +60,7 @@ rshift(Bigint *b, int k)
|
||||||
while(x < xe)
|
while(x < xe)
|
||||||
*x1++ = *x++;
|
*x1++ = *x++;
|
||||||
}
|
}
|
||||||
if ((b->wds = (int)(x1 - b->x)) == 0)
|
if ((b->wds = x1 - b->x) == 0)
|
||||||
b->x[0] = 0;
|
b->x[0] = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -31,6 +31,7 @@ THIS SOFTWARE.
|
||||||
|
|
||||||
#include "gdtoaimp.h"
|
#include "gdtoaimp.h"
|
||||||
|
|
||||||
|
#if 0
|
||||||
unsigned char hexdig[256];
|
unsigned char hexdig[256];
|
||||||
|
|
||||||
static void
|
static void
|
||||||
|
@ -46,10 +47,31 @@ htinit(unsigned char *h, unsigned char *s, int inc)
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
hexdig_init_D2A(Void)
|
hexdig_init_D2A(Void) /* Use of hexdig_init omitted 20121220 to avoid a */
|
||||||
|
/* race condition when multiple threads are used. */
|
||||||
{
|
{
|
||||||
#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);
|
||||||
}
|
}
|
||||||
|
#else
|
||||||
|
unsigned char hexdig[256] = {
|
||||||
|
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
||||||
|
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
||||||
|
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
||||||
|
16,17,18,19,20,21,22,23,24,25,0,0,0,0,0,0,
|
||||||
|
0,26,27,28,29,30,31,0,0,0,0,0,0,0,0,0,
|
||||||
|
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
||||||
|
0,26,27,28,29,30,31,0,0,0,0,0,0,0,0,0,
|
||||||
|
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
||||||
|
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
||||||
|
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
||||||
|
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
||||||
|
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
||||||
|
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
||||||
|
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
||||||
|
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
||||||
|
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
|
||||||
|
};
|
||||||
|
#endif
|
||||||
|
|
|
@ -54,15 +54,14 @@ L_shift(ULong *x, ULong *x1, int i)
|
||||||
hexnan(sp, fpi, x0)
|
hexnan(sp, fpi, x0)
|
||||||
CONST char **sp; FPI *fpi; ULong *x0;
|
CONST char **sp; FPI *fpi; ULong *x0;
|
||||||
#else
|
#else
|
||||||
hexnan( CONST char **sp, CONST FPI *fpi, ULong *x0)
|
hexnan( CONST char **sp, FPI *fpi, ULong *x0)
|
||||||
#endif
|
#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']) hexdig_init_D2A(); ****/
|
||||||
hexdig_init_D2A();
|
|
||||||
nbits = fpi->nbits;
|
nbits = fpi->nbits;
|
||||||
x = x0 + (nbits >> kshift);
|
x = x0 + (nbits >> kshift);
|
||||||
if (nbits & kmask)
|
if (nbits & kmask)
|
||||||
|
@ -72,12 +71,15 @@ hexnan( CONST char **sp, CONST FPI *fpi, ULong *x0)
|
||||||
havedig = hd0 = i = 0;
|
havedig = hd0 = i = 0;
|
||||||
s = *sp;
|
s = *sp;
|
||||||
/* allow optional initial 0x or 0X */
|
/* allow optional initial 0x or 0X */
|
||||||
while((c = *(CONST unsigned char*)(s+1)) && c <= ' ')
|
while((c = *(CONST unsigned char*)(s+1)) && c <= ' ') {
|
||||||
|
if (!c)
|
||||||
|
goto retnan;
|
||||||
++s;
|
++s;
|
||||||
|
}
|
||||||
if (s[1] == '0' && (s[2] == 'x' || s[2] == 'X')
|
if (s[1] == '0' && (s[2] == 'x' || s[2] == 'X')
|
||||||
&& *(CONST unsigned char*)(s+3) > ' ')
|
&& *(CONST unsigned char*)(s+3) > ' ')
|
||||||
s += 2;
|
s += 2;
|
||||||
while(c = *(CONST unsigned char*)++s) {
|
while((c = *(CONST unsigned char*)++s)) {
|
||||||
if (!(h = hexdig[c])) {
|
if (!(h = hexdig[c])) {
|
||||||
if (c <= ' ') {
|
if (c <= ' ') {
|
||||||
if (hd0 < havedig) {
|
if (hd0 < havedig) {
|
||||||
|
@ -92,8 +94,11 @@ hexnan( CONST char **sp, CONST FPI *fpi, ULong *x0)
|
||||||
x1 = x;
|
x1 = x;
|
||||||
i = 0;
|
i = 0;
|
||||||
}
|
}
|
||||||
while(*(CONST unsigned char*)(s+1) <= ' ')
|
while((c = *(CONST unsigned char*)(s+1)) <= ' ') {
|
||||||
|
if (!c)
|
||||||
|
goto retnan;
|
||||||
++s;
|
++s;
|
||||||
|
}
|
||||||
if (s[1] == '0' && (s[2] == 'x' || s[2] == 'X')
|
if (s[1] == '0' && (s[2] == 'x' || s[2] == 'X')
|
||||||
&& *(CONST unsigned char*)(s+3) > ' ')
|
&& *(CONST unsigned char*)(s+3) > ' ')
|
||||||
s += 2;
|
s += 2;
|
||||||
|
@ -107,10 +112,11 @@ hexnan( CONST char **sp, CONST FPI *fpi, ULong *x0)
|
||||||
do {
|
do {
|
||||||
if (/*(*/ c == ')') {
|
if (/*(*/ c == ')') {
|
||||||
*sp = s + 1;
|
*sp = s + 1;
|
||||||
break;
|
goto break2;
|
||||||
}
|
}
|
||||||
} while(c = *++s);
|
} while((c = *++s));
|
||||||
#endif
|
#endif
|
||||||
|
retnan:
|
||||||
return STRTOG_NaN;
|
return STRTOG_NaN;
|
||||||
}
|
}
|
||||||
havedig++;
|
havedig++;
|
||||||
|
@ -120,8 +126,11 @@ hexnan( CONST char **sp, CONST FPI *fpi, ULong *x0)
|
||||||
i = 1;
|
i = 1;
|
||||||
*--x = 0;
|
*--x = 0;
|
||||||
}
|
}
|
||||||
*x = (*x << 4) | h & 0xf;
|
*x = (*x << 4) | (h & 0xf);
|
||||||
}
|
}
|
||||||
|
#ifndef GDTOA_NON_PEDANTIC_NANCHECK
|
||||||
|
break2:
|
||||||
|
#endif
|
||||||
if (!havedig)
|
if (!havedig)
|
||||||
return STRTOG_NaN;
|
return STRTOG_NaN;
|
||||||
if (x < x1 && i < 8)
|
if (x < x1 && i < 8)
|
||||||
|
|
128
gdtoa/misc.c
128
gdtoa/misc.c
|
@ -38,11 +38,6 @@ THIS SOFTWARE.
|
||||||
#endif
|
#endif
|
||||||
#define PRIVATE_mem ((PRIVATE_MEM+sizeof(double)-1)/sizeof(double))
|
#define PRIVATE_mem ((PRIVATE_MEM+sizeof(double)-1)/sizeof(double))
|
||||||
static double private_mem[PRIVATE_mem], *pmem_next = private_mem;
|
static double private_mem[PRIVATE_mem], *pmem_next = private_mem;
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifdef MULTIPLE_THREADS
|
|
||||||
static void ACQUIRE_DTOA_LOCK(int n);
|
|
||||||
static void FREE_DTOA_LOCK(int n);
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
Bigint *
|
Bigint *
|
||||||
|
@ -60,7 +55,9 @@ 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 {
|
||||||
|
@ -70,7 +67,7 @@ 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;
|
||||||
}
|
}
|
||||||
|
@ -94,12 +91,20 @@ Bfree
|
||||||
#endif
|
#endif
|
||||||
{
|
{
|
||||||
if (v) {
|
if (v) {
|
||||||
|
if (v->k > Kmax)
|
||||||
|
#ifdef FREE
|
||||||
|
FREE((void*)v);
|
||||||
|
#else
|
||||||
|
free((void*)v);
|
||||||
|
#endif
|
||||||
|
else {
|
||||||
ACQUIRE_DTOA_LOCK(0);
|
ACQUIRE_DTOA_LOCK(0);
|
||||||
v->next = freelist[v->k];
|
v->next = freelist[v->k];
|
||||||
freelist[v->k] = v;
|
freelist[v->k] = v;
|
||||||
FREE_DTOA_LOCK(0);
|
FREE_DTOA_LOCK(0);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
lo0bits
|
lo0bits
|
||||||
|
@ -109,8 +114,8 @@ lo0bits
|
||||||
(ULong *y)
|
(ULong *y)
|
||||||
#endif
|
#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)
|
||||||
|
@ -209,12 +214,12 @@ multadd
|
||||||
int
|
int
|
||||||
hi0bits_D2A
|
hi0bits_D2A
|
||||||
#ifdef KR_headers
|
#ifdef KR_headers
|
||||||
(x) register ULong x;
|
(x) ULong x;
|
||||||
#else
|
#else
|
||||||
(register ULong x)
|
(ULong x)
|
||||||
#endif
|
#endif
|
||||||
{
|
{
|
||||||
register int k = 0;
|
int k = 0;
|
||||||
|
|
||||||
if (!(x & 0xffff0000)) {
|
if (!(x & 0xffff0000)) {
|
||||||
k = 16;
|
k = 16;
|
||||||
|
@ -621,8 +626,8 @@ b2d
|
||||||
#ifdef VAX
|
#ifdef VAX
|
||||||
ULong d0, d1;
|
ULong d0, d1;
|
||||||
#else
|
#else
|
||||||
#define d0 word0(d)
|
#define d0 word0(&d)
|
||||||
#define d1 word1(d)
|
#define d1 word1(&d)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
xa0 = a->x;
|
xa0 = a->x;
|
||||||
|
@ -635,16 +640,16 @@ b2d
|
||||||
*e = 32 - k;
|
*e = 32 - k;
|
||||||
#ifdef Pack_32
|
#ifdef Pack_32
|
||||||
if (k < Ebits) {
|
if (k < Ebits) {
|
||||||
d0 = Exp_1 | y >> Ebits - k;
|
d0 = Exp_1 | y >> (Ebits - k);
|
||||||
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;
|
||||||
|
@ -668,10 +673,10 @@ b2d
|
||||||
#endif
|
#endif
|
||||||
ret_d:
|
ret_d:
|
||||||
#ifdef VAX
|
#ifdef VAX
|
||||||
word0(d) = d0 >> 16 | d0 << 16;
|
word0(&d) = d0 >> 16 | d0 << 16;
|
||||||
word1(d) = d1 >> 16 | d1 << 16;
|
word1(&d) = d1 >> 16 | d1 << 16;
|
||||||
#endif
|
#endif
|
||||||
return dval(d);
|
return dval(&d);
|
||||||
}
|
}
|
||||||
#undef d0
|
#undef d0
|
||||||
#undef d1
|
#undef d1
|
||||||
|
@ -679,29 +684,28 @@ b2d
|
||||||
Bigint *
|
Bigint *
|
||||||
d2b
|
d2b
|
||||||
#ifdef KR_headers
|
#ifdef KR_headers
|
||||||
(d, e, bits) double d; int *e, *bits;
|
(dd, e, bits) double dd; int *e, *bits;
|
||||||
#else
|
#else
|
||||||
(double _d, int *e, int *bits)
|
(double dd, int *e, int *bits)
|
||||||
#endif
|
#endif
|
||||||
{
|
{
|
||||||
Bigint *b;
|
Bigint *b;
|
||||||
|
U 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;
|
||||||
U d;
|
|
||||||
#ifdef VAX
|
#ifdef VAX
|
||||||
ULong d0, d1;
|
ULong d0, d1;
|
||||||
#else
|
#else
|
||||||
#define d0 word0(d)
|
#define d0 word0(&d)
|
||||||
#define d1 word1(d)
|
#define d1 word1(&d)
|
||||||
#endif
|
#endif
|
||||||
|
d.d = dd;
|
||||||
dval(d) = _d;
|
|
||||||
#ifdef VAX
|
#ifdef VAX
|
||||||
d0 = word0(d) >> 16 | word0(d) << 16;
|
d0 = word0(&d) >> 16 | word0(&d) << 16;
|
||||||
d1 = word1(d) >> 16 | word1(d) << 16;
|
d1 = word1(&d) >> 16 | word1(&d) << 16;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef Pack_32
|
#ifdef Pack_32
|
||||||
|
@ -725,7 +729,7 @@ d2b
|
||||||
#ifdef Pack_32
|
#ifdef Pack_32
|
||||||
if ( (y = d1) !=0) {
|
if ( (y = d1) !=0) {
|
||||||
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
|
||||||
|
@ -736,10 +740,6 @@ d2b
|
||||||
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
|
||||||
|
@ -798,7 +798,7 @@ d2b
|
||||||
#endif
|
#endif
|
||||||
#ifdef IBM
|
#ifdef IBM
|
||||||
*e = (de - Bias - (P-1) << 2) + k;
|
*e = (de - Bias - (P-1) << 2) + k;
|
||||||
*bits = 4*P + 8 - k - hi0bits(word0(d) & Frac_mask);
|
*bits = 4*P + 8 - k - hi0bits(word0(&d) & Frac_mask);
|
||||||
#else
|
#else
|
||||||
*e = de - Bias - (P-1) + k;
|
*e = de - Bias - (P-1) + k;
|
||||||
*bits = P - k;
|
*bits = P - k;
|
||||||
|
@ -851,71 +851,25 @@ strcp_D2A(a, b) char *a; char *b;
|
||||||
strcp_D2A(char *a, CONST char *b)
|
strcp_D2A(char *a, CONST char *b)
|
||||||
#endif
|
#endif
|
||||||
{
|
{
|
||||||
while(*a = *b++)
|
while((*a = *b++))
|
||||||
a++;
|
a++;
|
||||||
return a;
|
return a;
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef NO_STRING_H
|
#ifdef NO_STRING_H
|
||||||
|
|
||||||
KR_VOID *
|
Char *
|
||||||
#ifdef KR_headers
|
#ifdef KR_headers
|
||||||
memcpy_D2A(a, b, len) char *a; char *b; size_t len;
|
memcpy_D2A(a, b, len) Char *a; Char *b; size_t len;
|
||||||
#else
|
#else
|
||||||
memcpy_D2A(void *a1, void *b1, size_t len)
|
memcpy_D2A(void *a1, void *b1, size_t len)
|
||||||
#endif
|
#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 */
|
||||||
|
|
||||||
|
|
||||||
#ifdef MULTIPLE_THREADS
|
|
||||||
#ifdef _WIN32
|
|
||||||
|
|
||||||
#undef Bias
|
|
||||||
#define WIN32_LEAN_AND_MEAN
|
|
||||||
#include <windows.h>
|
|
||||||
|
|
||||||
static CRITICAL_SECTION dtoa_lock[2];
|
|
||||||
static int did_init;
|
|
||||||
|
|
||||||
void ACQUIRE_DTOA_LOCK(int n)
|
|
||||||
{
|
|
||||||
if (!did_init)
|
|
||||||
{
|
|
||||||
did_init = 1;
|
|
||||||
InitializeCriticalSection(&dtoa_lock[0]);
|
|
||||||
InitializeCriticalSection(&dtoa_lock[1]);
|
|
||||||
}
|
|
||||||
EnterCriticalSection(&dtoa_lock[n]);
|
|
||||||
}
|
|
||||||
|
|
||||||
void FREE_DTOA_LOCK(int n)
|
|
||||||
{
|
|
||||||
LeaveCriticalSection(&dtoa_lock[n]);
|
|
||||||
}
|
|
||||||
|
|
||||||
#else
|
|
||||||
|
|
||||||
#include <pthread.h>
|
|
||||||
|
|
||||||
static pthread_mutex_t dtoa_lock[2] = { PTHREAD_MUTEX_INITIALIZER, PTHREAD_MUTEX_INITIALIZER };
|
|
||||||
|
|
||||||
void ACQUIRE_DTOA_LOCK(int n)
|
|
||||||
{
|
|
||||||
pthread_mutex_lock(&dtoa_lock[n]);
|
|
||||||
}
|
|
||||||
|
|
||||||
void FREE_DTOA_LOCK(int n)
|
|
||||||
{
|
|
||||||
pthread_mutex_unlock(&dtoa_lock[n]);
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif
|
|
||||||
#endif
|
|
||||||
|
|
35
gdtoa/qnan.c
35
gdtoa/qnan.c
|
@ -55,11 +55,19 @@ typedef unsigned Long Ulong;
|
||||||
#ifdef IEEE_8087
|
#ifdef IEEE_8087
|
||||||
#define _0 1
|
#define _0 1
|
||||||
#define _1 0
|
#define _1 0
|
||||||
|
#define _3 3
|
||||||
|
#if defined(Gen_ld_QNAN) && !defined(NO_LONG_LONG)
|
||||||
|
static int perm[4] = { 0, 1, 2, 3 };
|
||||||
|
#endif
|
||||||
#define HAVE_IEEE
|
#define HAVE_IEEE
|
||||||
#endif
|
#endif
|
||||||
#ifdef IEEE_MC68k
|
#ifdef IEEE_MC68k
|
||||||
#define _0 0
|
#define _0 0
|
||||||
#define _1 1
|
#define _1 1
|
||||||
|
#define _3 0
|
||||||
|
#if defined(Gen_ld_QNAN) && !defined(NO_LONG_LONG)
|
||||||
|
static int perm[4] = { 3, 2, 1, 0 };
|
||||||
|
#endif
|
||||||
#define HAVE_IEEE
|
#define HAVE_IEEE
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
@ -79,31 +87,32 @@ main(void)
|
||||||
#endif
|
#endif
|
||||||
} U;
|
} U;
|
||||||
U a, b, c;
|
U a, b, c;
|
||||||
|
#if defined(Gen_ld_QNAN) && !defined(NO_LONG_LONG)
|
||||||
int i;
|
int i;
|
||||||
|
#endif
|
||||||
|
|
||||||
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;
|
||||||
printf("#define f_QNAN 0x%lx\n", UL c.L[0]);
|
printf("#define f_QNAN 0x%lx\n", UL (c.L[0] & 0x7fffffff));
|
||||||
a.L[_0] = b.L[_0] = 0x7ff00000;
|
a.L[_0] = b.L[_0] = 0x7ff00000;
|
||||||
a.L[_1] = b.L[_1] = 0;
|
a.L[_1] = b.L[_1] = 0;
|
||||||
c.d = a.d - b.d; /* quiet NaN */
|
c.d = a.d - b.d; /* quiet NaN */
|
||||||
printf("#define d_QNAN0 0x%lx\n", UL c.L[0]);
|
c.L[_0] &= 0x7fffffff;
|
||||||
printf("#define d_QNAN1 0x%lx\n", UL c.L[1]);
|
printf("#define d_QNAN0 0x%lx\n", UL c.L[_0]);
|
||||||
#ifdef NO_LONG_LONG
|
printf("#define d_QNAN1 0x%lx\n", UL c.L[_1]);
|
||||||
for(i = 0; i < 4; i++)
|
#ifndef NO_LONG_LONG
|
||||||
printf("#define ld_QNAN%d 0xffffffff\n", i);
|
#ifdef Gen_ld_QNAN
|
||||||
for(i = 0; i < 5; i++)
|
if (sizeof(a.D) >= 16) {
|
||||||
printf("#define ldus_QNAN%d 0xffff\n", i);
|
|
||||||
#else
|
|
||||||
b.D = c.D = a.d;
|
b.D = c.D = a.d;
|
||||||
if (printf("") < 0)
|
if (printf("") < 0)
|
||||||
c.D = 37; /* never executed; just defeat optimization */
|
c.D = 37; /* never executed; just defeat optimization */
|
||||||
a.L[2] = a.L[3] = 0;
|
a.L[0] = a.L[1] = a.L[2] = a.L[3] = 0;
|
||||||
a.D = b.D - c.D;
|
a.D = b.D - c.D;
|
||||||
|
a.L[_3] &= 0x7fffffff;
|
||||||
for(i = 0; i < 4; i++)
|
for(i = 0; i < 4; i++)
|
||||||
printf("#define ld_QNAN%d 0x%lx\n", i, UL a.L[i]);
|
printf("#define ld_QNAN%d 0x%lx\n", i, UL a.L[perm[i]]);
|
||||||
for(i = 0; i < 5; i++)
|
}
|
||||||
printf("#define ldus_QNAN%d 0x%x\n", i, a.u[i]);
|
#endif
|
||||||
#endif
|
#endif
|
||||||
#endif /* HAVE_IEEE */
|
#endif /* HAVE_IEEE */
|
||||||
return 0;
|
return 0;
|
||||||
|
|
|
@ -34,9 +34,9 @@ THIS SOFTWARE.
|
||||||
Bigint *
|
Bigint *
|
||||||
s2b
|
s2b
|
||||||
#ifdef KR_headers
|
#ifdef KR_headers
|
||||||
(s, nd0, nd, y9) CONST char *s; int nd0, nd; ULong y9;
|
(s, nd0, nd, y9, dplen) CONST char *s; int dplen, nd0, nd; ULong y9;
|
||||||
#else
|
#else
|
||||||
(CONST char *s, int nd0, int nd, ULong y9)
|
(CONST char *s, int nd0, int nd, ULong y9, int dplen)
|
||||||
#endif
|
#endif
|
||||||
{
|
{
|
||||||
Bigint *b;
|
Bigint *b;
|
||||||
|
@ -60,10 +60,10 @@ 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;
|
||||||
|
@ -80,30 +80,30 @@ ratio
|
||||||
U da, db;
|
U 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
|
#ifdef IBM
|
||||||
if (k > 0) {
|
if (k > 0) {
|
||||||
word0(da) += (k >> 2)*Exp_msk1;
|
word0(&da) += (k >> 2)*Exp_msk1;
|
||||||
if (k &= 3)
|
if (k &= 3)
|
||||||
dval(da) *= 1 << k;
|
dval(&da) *= 1 << k;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
k = -k;
|
k = -k;
|
||||||
word0(db) += (k >> 2)*Exp_msk1;
|
word0(&db) += (k >> 2)*Exp_msk1;
|
||||||
if (k &= 3)
|
if (k &= 3)
|
||||||
dval(db) *= 1 << k;
|
dval(&db) *= 1 << k;
|
||||||
}
|
}
|
||||||
#else
|
#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
|
#endif
|
||||||
return dval(da) / dval(db);
|
return dval(&da) / dval(&db);
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef INFNAN_CHECK
|
#ifdef INFNAN_CHECK
|
||||||
|
|
|
@ -38,7 +38,7 @@ strtoIQ(s, sp, a, b) CONST char *s; char **sp; void *a; void *b;
|
||||||
strtoIQ(CONST char *s, char **sp, void *a, void *b)
|
strtoIQ(CONST char *s, char **sp, void *a, void *b)
|
||||||
#endif
|
#endif
|
||||||
{
|
{
|
||||||
static CONST FPI fpi = { 113, 1-16383-113+1, 32766-16383-113+1, 1, SI };
|
static FPI fpi = { 113, 1-16383-113+1, 32766-16383-113+1, 1, SI };
|
||||||
Long exp[2];
|
Long exp[2];
|
||||||
Bigint *B[2];
|
Bigint *B[2];
|
||||||
int k, rv[2];
|
int k, rv[2];
|
||||||
|
|
|
@ -38,7 +38,7 @@ strtoId(s, sp, f0, f1) CONST char *s; char **sp; double *f0, *f1;
|
||||||
strtoId(CONST char *s, char **sp, double *f0, double *f1)
|
strtoId(CONST char *s, char **sp, double *f0, double *f1)
|
||||||
#endif
|
#endif
|
||||||
{
|
{
|
||||||
static CONST 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 };
|
||||||
Long exp[2];
|
Long exp[2];
|
||||||
Bigint *B[2];
|
Bigint *B[2];
|
||||||
int k, rv[2];
|
int k, rv[2];
|
||||||
|
|
|
@ -39,9 +39,9 @@ strtoIdd(CONST char *s, char **sp, double *f0, double *f1)
|
||||||
#endif
|
#endif
|
||||||
{
|
{
|
||||||
#ifdef Sudden_Underflow
|
#ifdef Sudden_Underflow
|
||||||
static CONST FPI fpi = { 106, 1-1023, 2046-1023-106+1, 1, 1 };
|
static FPI fpi = { 106, 1-1023, 2046-1023-106+1, 1, 1 };
|
||||||
#else
|
#else
|
||||||
static CONST FPI fpi = { 106, 1-1023-53+1, 2046-1023-106+1, 1, 0 };
|
static FPI fpi = { 106, 1-1023-53+1, 2046-1023-106+1, 1, 0 };
|
||||||
#endif
|
#endif
|
||||||
Long exp[2];
|
Long exp[2];
|
||||||
Bigint *B[2];
|
Bigint *B[2];
|
||||||
|
|
|
@ -38,7 +38,7 @@ strtoIf(s, sp, f0, f1) CONST char *s; char **sp; float *f0, *f1;
|
||||||
strtoIf(CONST char *s, char **sp, float *f0, float *f1)
|
strtoIf(CONST char *s, char **sp, float *f0, float *f1)
|
||||||
#endif
|
#endif
|
||||||
{
|
{
|
||||||
static CONST FPI fpi = { 24, 1-127-24+1, 254-127-24+1, 1, SI };
|
static FPI fpi = { 24, 1-127-24+1, 254-127-24+1, 1, SI };
|
||||||
Long exp[2];
|
Long exp[2];
|
||||||
Bigint *B[2];
|
Bigint *B[2];
|
||||||
int k, rv[2];
|
int k, rv[2];
|
||||||
|
|
|
@ -35,7 +35,7 @@ THIS SOFTWARE.
|
||||||
#ifdef KR_headers
|
#ifdef KR_headers
|
||||||
strtoIg(s00, se, fpi, exp, B, rvp) CONST char *s00; char **se; FPI *fpi; Long *exp; Bigint **B; int *rvp;
|
strtoIg(s00, se, fpi, exp, B, rvp) CONST char *s00; char **se; FPI *fpi; Long *exp; Bigint **B; int *rvp;
|
||||||
#else
|
#else
|
||||||
strtoIg(CONST char *s00, char **se, CONST FPI *fpi, Long *exp, Bigint **B, int *rvp)
|
strtoIg(CONST char *s00, char **se, FPI *fpi, Long *exp, Bigint **B, int *rvp)
|
||||||
#endif
|
#endif
|
||||||
{
|
{
|
||||||
Bigint *b, *b1;
|
Bigint *b, *b1;
|
||||||
|
@ -61,16 +61,20 @@ strtoIg(CONST char *s00, char **se, CONST FPI *fpi, Long *exp, Bigint **B, int *
|
||||||
if (rv & STRTOG_Inexlo) {
|
if (rv & STRTOG_Inexlo) {
|
||||||
swap = 0;
|
swap = 0;
|
||||||
b1 = increment(b1);
|
b1 = increment(b1);
|
||||||
if (fpi->sudden_underflow
|
if ((rv & STRTOG_Retmask) == STRTOG_Zero) {
|
||||||
&& (rv & STRTOG_Retmask) == STRTOG_Zero) {
|
if (fpi->sudden_underflow) {
|
||||||
b1->x[0] = 0;
|
b1->x[0] = 0;
|
||||||
b1->x[nw1] = 1L << nb11;
|
b1->x[nw1] = 1L << nb11;
|
||||||
rv1 += STRTOG_Normal - STRTOG_Zero;
|
rv1 += STRTOG_Normal - STRTOG_Zero;
|
||||||
rv1 &= ~STRTOG_Underflow;
|
rv1 &= ~STRTOG_Underflow;
|
||||||
goto swapcheck;
|
goto swapcheck;
|
||||||
}
|
}
|
||||||
|
rv1 &= STRTOG_Inexlo | STRTOG_Underflow | STRTOG_Zero;
|
||||||
|
rv1 |= STRTOG_Inexhi | STRTOG_Denormal;
|
||||||
|
goto swapcheck;
|
||||||
|
}
|
||||||
if (b1->wds > nw
|
if (b1->wds > nw
|
||||||
|| nb1 && b1->x[nw1] & 1L << nb1) {
|
|| (nb1 && b1->x[nw1] & 1L << nb1)) {
|
||||||
if (++e1 > fpi->emax)
|
if (++e1 > fpi->emax)
|
||||||
rv1 = STRTOG_Infinite | STRTOG_Inexhi;
|
rv1 = STRTOG_Infinite | STRTOG_Inexhi;
|
||||||
rshift(b1, 1);
|
rshift(b1, 1);
|
||||||
|
|
|
@ -38,7 +38,7 @@ strtoIx(s, sp, a, b) CONST char *s; char **sp; void *a; void *b;
|
||||||
strtoIx(CONST char *s, char **sp, void *a, void *b)
|
strtoIx(CONST char *s, char **sp, void *a, void *b)
|
||||||
#endif
|
#endif
|
||||||
{
|
{
|
||||||
static CONST FPI fpi = { 64, 1-16383-64+1, 32766 - 16383 - 64 + 1, 1, SI };
|
static FPI fpi = { 64, 1-16383-64+1, 32766 - 16383 - 64 + 1, 1, SI };
|
||||||
Long exp[2];
|
Long exp[2];
|
||||||
Bigint *B[2];
|
Bigint *B[2];
|
||||||
int k, rv[2];
|
int k, rv[2];
|
||||||
|
|
|
@ -38,7 +38,7 @@ strtoIxL(s, sp, a, b) CONST char *s; char **sp; void *a; void *b;
|
||||||
strtoIxL(CONST char *s, char **sp, void *a, void *b)
|
strtoIxL(CONST char *s, char **sp, void *a, void *b)
|
||||||
#endif
|
#endif
|
||||||
{
|
{
|
||||||
static CONST FPI fpi = { 64, 1-16383-64+1, 32766 - 16383 - 64 + 1, 1, SI };
|
static FPI fpi = { 64, 1-16383-64+1, 32766 - 16383 - 64 + 1, 1, SI };
|
||||||
Long exp[2];
|
Long exp[2];
|
||||||
Bigint *B[2];
|
Bigint *B[2];
|
||||||
int k, rv[2];
|
int k, rv[2];
|
||||||
|
|
534
gdtoa/strtod.c
534
gdtoa/strtod.c
|
@ -42,24 +42,43 @@ THIS SOFTWARE.
|
||||||
#ifndef NO_IEEE_Scale
|
#ifndef NO_IEEE_Scale
|
||||||
#define Avoid_Underflow
|
#define Avoid_Underflow
|
||||||
#undef tinytens
|
#undef tinytens
|
||||||
/* The factor of 2^53 in tinytens[4] helps us avoid setting the underflow */
|
/* The factor of 2^106 in tinytens[4] helps us avoid setting the underflow */
|
||||||
/* flag unnecessarily. It leads to a song and dance at the end of strtod. */
|
/* flag unnecessarily. It leads to a song and dance at the end of strtod. */
|
||||||
static CONST double tinytens[] = { 1e-16, 1e-32, 1e-64, 1e-128,
|
static CONST double tinytens[] = { 1e-16, 1e-32, 1e-64, 1e-128,
|
||||||
9007199254740992.e-256
|
9007199254740992.*9007199254740992.e-256
|
||||||
};
|
};
|
||||||
#endif
|
#endif
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#include <float.h>
|
|
||||||
|
|
||||||
#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
|
||||||
|
|
||||||
|
#ifdef Avoid_Underflow /*{*/
|
||||||
|
static double
|
||||||
|
sulp
|
||||||
|
#ifdef KR_headers
|
||||||
|
(x, scale) U *x; int scale;
|
||||||
|
#else
|
||||||
|
(U *x, int scale)
|
||||||
|
#endif
|
||||||
|
{
|
||||||
|
U u;
|
||||||
|
double rv;
|
||||||
|
int i;
|
||||||
|
|
||||||
|
rv = ulp(x);
|
||||||
|
if (!scale || (i = 2*P + 1 - ((word0(x) & Exp_mask) >> Exp_shift)) <= 0)
|
||||||
|
return rv; /* Is there an example where i <= 0 ? */
|
||||||
|
word0(&u) = Exp_1 + (i << Exp_shift);
|
||||||
|
word1(&u) = 0;
|
||||||
|
return rv * u.d;
|
||||||
|
}
|
||||||
|
#endif /*}*/
|
||||||
|
|
||||||
double
|
double
|
||||||
strtod
|
strtod
|
||||||
#ifdef KR_headers
|
#ifdef KR_headers
|
||||||
|
@ -74,21 +93,55 @@ strtod
|
||||||
int bb2, bb5, bbe, bd2, bd5, bbbits, bs2, c, decpt, dsign,
|
int bb2, bb5, bbe, bd2, bd5, bbbits, bs2, c, decpt, dsign,
|
||||||
e, e1, esign, i, j, k, nd, nd0, nf, nz, nz0, sign;
|
e, e1, esign, i, j, k, nd, nd0, nf, nz, nz0, sign;
|
||||||
CONST char *s, *s0, *s1;
|
CONST char *s, *s0, *s1;
|
||||||
double aadj, adj;
|
double aadj;
|
||||||
U rv, rv0, aadj1;
|
|
||||||
Long L;
|
Long L;
|
||||||
|
U adj, aadj1, rv, rv0;
|
||||||
ULong y, z;
|
ULong y, z;
|
||||||
Bigint *bb, *bb1, *bd, *bd0, *bs, *delta;
|
Bigint *bb, *bb1, *bd, *bd0, *bs, *delta;
|
||||||
|
#ifdef Avoid_Underflow
|
||||||
|
ULong Lsb, Lsb1;
|
||||||
|
#endif
|
||||||
#ifdef SET_INEXACT
|
#ifdef SET_INEXACT
|
||||||
int inexact, oldinexact;
|
int inexact, oldinexact;
|
||||||
#endif
|
#endif
|
||||||
#ifdef Honor_FLT_ROUNDS
|
#ifdef USE_LOCALE /*{{*/
|
||||||
int rounding;
|
#ifdef NO_LOCALE_CACHE
|
||||||
#endif
|
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}}*/
|
||||||
|
|
||||||
|
#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 /*}*/
|
||||||
|
|
||||||
//_control87(_PC_53, _MCW_PC);
|
|
||||||
sign = nz0 = nz = decpt = 0;
|
sign = nz0 = nz = decpt = 0;
|
||||||
dval(rv) = 0.;
|
dval(&rv) = 0.;
|
||||||
for(s = s00;;s++) switch(*s) {
|
for(s = s00;;s++) switch(*s) {
|
||||||
case '-':
|
case '-':
|
||||||
sign = 1;
|
sign = 1;
|
||||||
|
@ -111,22 +164,18 @@ strtod
|
||||||
}
|
}
|
||||||
break2:
|
break2:
|
||||||
if (*s == '0') {
|
if (*s == '0') {
|
||||||
#ifndef NO_HEX_FP
|
#ifndef NO_HEX_FP /*{*/
|
||||||
{
|
{
|
||||||
static CONST 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 };
|
||||||
Long exp;
|
Long exp;
|
||||||
ULong bits[2];
|
ULong bits[2];
|
||||||
switch(s[1]) {
|
switch(s[1]) {
|
||||||
case 'x':
|
case 'x':
|
||||||
case 'X':
|
case 'X':
|
||||||
{
|
{
|
||||||
#if defined(FE_DOWNWARD) && defined(FE_TONEAREST) && defined(FE_TOWARDZERO) && defined(FE_UPWARD)
|
#ifdef Honor_FLT_ROUNDS
|
||||||
FPI fpi1 = fpi;
|
FPI fpi1 = fpi;
|
||||||
switch(fegetround()) {
|
fpi1.rounding = Rounding;
|
||||||
case FE_TOWARDZERO: fpi1.rounding = 0; break;
|
|
||||||
case FE_UPWARD: fpi1.rounding = 2; break;
|
|
||||||
case FE_DOWNWARD: fpi1.rounding = 3;
|
|
||||||
}
|
|
||||||
#else
|
#else
|
||||||
#define fpi1 fpi
|
#define fpi1 fpi
|
||||||
#endif
|
#endif
|
||||||
|
@ -146,7 +195,7 @@ strtod
|
||||||
goto ret;
|
goto ret;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#endif
|
#endif /*}*/
|
||||||
nz0 = 1;
|
nz0 = 1;
|
||||||
while(*++s == '0') ;
|
while(*++s == '0') ;
|
||||||
if (!*s)
|
if (!*s)
|
||||||
|
@ -161,13 +210,17 @@ strtod
|
||||||
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++;
|
||||||
|
@ -196,7 +249,7 @@ strtod
|
||||||
nz = 0;
|
nz = 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}/*}*/
|
||||||
dig_done:
|
dig_done:
|
||||||
e = 0;
|
e = 0;
|
||||||
if (c == 'e' || c == 'E') {
|
if (c == 'e' || c == 'E') {
|
||||||
|
@ -240,7 +293,7 @@ strtod
|
||||||
#ifdef INFNAN_CHECK
|
#ifdef INFNAN_CHECK
|
||||||
/* Check for Nan and Infinity */
|
/* Check for Nan and Infinity */
|
||||||
ULong bits[2];
|
ULong bits[2];
|
||||||
static CONST FPI fpinan = /* only 52 explicit bits */
|
static FPI fpinan = /* only 52 explicit bits */
|
||||||
{ 52, 1-1023-53+1, 2046-1023-53+1, 1, SI };
|
{ 52, 1-1023-53+1, 2046-1023-53+1, 1, SI };
|
||||||
if (!decpt)
|
if (!decpt)
|
||||||
switch(c) {
|
switch(c) {
|
||||||
|
@ -250,8 +303,8 @@ strtod
|
||||||
--s;
|
--s;
|
||||||
if (!match(&s,"inity"))
|
if (!match(&s,"inity"))
|
||||||
++s;
|
++s;
|
||||||
word0(rv) = 0x7ff00000;
|
word0(&rv) = 0x7ff00000;
|
||||||
word1(rv) = 0;
|
word1(&rv) = 0;
|
||||||
goto ret;
|
goto ret;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
@ -262,13 +315,13 @@ strtod
|
||||||
if (*s == '(' /*)*/
|
if (*s == '(' /*)*/
|
||||||
&& hexnan(&s, &fpinan, bits)
|
&& hexnan(&s, &fpinan, bits)
|
||||||
== STRTOG_NaNbits) {
|
== STRTOG_NaNbits) {
|
||||||
word0(rv) = 0x7ff00000 | bits[1];
|
word0(&rv) = 0x7ff00000 | bits[1];
|
||||||
word1(rv) = bits[0];
|
word1(&rv) = bits[0];
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
#endif
|
#endif
|
||||||
word0(rv) = NAN_WORD0;
|
word0(&rv) = NAN_WORD0;
|
||||||
word1(rv) = NAN_WORD1;
|
word1(&rv) = NAN_WORD1;
|
||||||
#ifndef No_Hex_NaN
|
#ifndef No_Hex_NaN
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
@ -292,13 +345,13 @@ strtod
|
||||||
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) {
|
||||||
#ifdef SET_INEXACT
|
#ifdef SET_INEXACT
|
||||||
if (k > DBL_DIG)
|
if (k > DBL_DIG)
|
||||||
oldinexact = get_inexact();
|
oldinexact = get_inexact();
|
||||||
#endif
|
#endif
|
||||||
dval(rv) = tens[k - 9] * dval(rv) + z;
|
dval(&rv) = tens[k - 9] * dval(&rv) + z;
|
||||||
}
|
}
|
||||||
bd0 = 0;
|
bd0 = 0;
|
||||||
if (nd <= DBL_DIG
|
if (nd <= DBL_DIG
|
||||||
|
@ -310,6 +363,7 @@ strtod
|
||||||
) {
|
) {
|
||||||
if (!e)
|
if (!e)
|
||||||
goto ret;
|
goto ret;
|
||||||
|
#ifndef ROUND_BIASED_without_Round_Up
|
||||||
if (e > 0) {
|
if (e > 0) {
|
||||||
if (e <= Ten_pmax) {
|
if (e <= Ten_pmax) {
|
||||||
#ifdef VAX
|
#ifdef VAX
|
||||||
|
@ -318,11 +372,11 @@ strtod
|
||||||
#ifdef Honor_FLT_ROUNDS
|
#ifdef Honor_FLT_ROUNDS
|
||||||
/* round correctly FLT_ROUNDS = 2 or 3 */
|
/* round correctly FLT_ROUNDS = 2 or 3 */
|
||||||
if (sign) {
|
if (sign) {
|
||||||
rv = -rv;
|
rv.d = -rv.d;
|
||||||
sign = 0;
|
sign = 0;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
/* rv = */ rounded_product(dval(rv), tens[e]);
|
/* rv = */ rounded_product(dval(&rv), tens[e]);
|
||||||
goto ret;
|
goto ret;
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
@ -334,25 +388,25 @@ strtod
|
||||||
#ifdef Honor_FLT_ROUNDS
|
#ifdef Honor_FLT_ROUNDS
|
||||||
/* round correctly FLT_ROUNDS = 2 or 3 */
|
/* round correctly FLT_ROUNDS = 2 or 3 */
|
||||||
if (sign) {
|
if (sign) {
|
||||||
rv = -rv;
|
rv.d = -rv.d;
|
||||||
sign = 0;
|
sign = 0;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
e -= i;
|
e -= i;
|
||||||
dval(rv) *= tens[i];
|
dval(&rv) *= tens[i];
|
||||||
#ifdef VAX
|
#ifdef VAX
|
||||||
/* VAX exponent range is so narrow we must
|
/* VAX exponent range is so narrow we must
|
||||||
* worry about overflow here...
|
* worry about overflow here...
|
||||||
*/
|
*/
|
||||||
vax_ovfl_check:
|
vax_ovfl_check:
|
||||||
word0(rv) -= P*Exp_msk1;
|
word0(&rv) -= P*Exp_msk1;
|
||||||
/* rv = */ rounded_product(dval(rv), tens[e]);
|
/* rv = */ rounded_product(dval(&rv), tens[e]);
|
||||||
if ((word0(rv) & Exp_mask)
|
if ((word0(&rv) & Exp_mask)
|
||||||
> Exp_msk1*(DBL_MAX_EXP+Bias-1-P))
|
> Exp_msk1*(DBL_MAX_EXP+Bias-1-P))
|
||||||
goto ovfl;
|
goto ovfl;
|
||||||
word0(rv) += P*Exp_msk1;
|
word0(&rv) += P*Exp_msk1;
|
||||||
#else
|
#else
|
||||||
/* rv = */ rounded_product(dval(rv), tens[e]);
|
/* rv = */ rounded_product(dval(&rv), tens[e]);
|
||||||
#endif
|
#endif
|
||||||
goto ret;
|
goto ret;
|
||||||
}
|
}
|
||||||
|
@ -362,14 +416,15 @@ strtod
|
||||||
#ifdef Honor_FLT_ROUNDS
|
#ifdef Honor_FLT_ROUNDS
|
||||||
/* round correctly FLT_ROUNDS = 2 or 3 */
|
/* round correctly FLT_ROUNDS = 2 or 3 */
|
||||||
if (sign) {
|
if (sign) {
|
||||||
rv = -rv;
|
rv.d = -rv.d;
|
||||||
sign = 0;
|
sign = 0;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
/* rv = */ rounded_quotient(dval(rv), tens[-e]);
|
/* rv = */ rounded_quotient(dval(&rv), tens[-e]);
|
||||||
goto ret;
|
goto ret;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
#endif /* ROUND_BIASED_without_Round_Up */
|
||||||
}
|
}
|
||||||
e1 += nd - k;
|
e1 += nd - k;
|
||||||
|
|
||||||
|
@ -383,12 +438,12 @@ strtod
|
||||||
scale = 0;
|
scale = 0;
|
||||||
#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
|
||||||
#endif /*IEEE_Arith*/
|
#endif /*IEEE_Arith*/
|
||||||
|
@ -397,67 +452,73 @@ strtod
|
||||||
|
|
||||||
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) {
|
||||||
if (e1 > DBL_MAX_10_EXP) {
|
if (e1 > DBL_MAX_10_EXP) {
|
||||||
ovfl:
|
ovfl:
|
||||||
#ifndef NO_ERRNO
|
|
||||||
errno = ERANGE;
|
|
||||||
#endif
|
|
||||||
/* Can't trust HUGE_VAL */
|
/* Can't trust HUGE_VAL */
|
||||||
#ifdef IEEE_Arith
|
#ifdef IEEE_Arith
|
||||||
#ifdef Honor_FLT_ROUNDS
|
#ifdef Honor_FLT_ROUNDS
|
||||||
switch(rounding) {
|
switch(Rounding) {
|
||||||
case 0: /* toward 0 */
|
case 0: /* toward 0 */
|
||||||
case 3: /* toward -infinity */
|
case 3: /* toward -infinity */
|
||||||
word0(rv) = Big0;
|
word0(&rv) = Big0;
|
||||||
word1(rv) = Big1;
|
word1(&rv) = Big1;
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
word0(rv) = Exp_mask;
|
word0(&rv) = Exp_mask;
|
||||||
word1(rv) = 0;
|
word1(&rv) = 0;
|
||||||
}
|
}
|
||||||
#else /*Honor_FLT_ROUNDS*/
|
#else /*Honor_FLT_ROUNDS*/
|
||||||
word0(rv) = Exp_mask;
|
word0(&rv) = Exp_mask;
|
||||||
word1(rv) = 0;
|
word1(&rv) = 0;
|
||||||
#endif /*Honor_FLT_ROUNDS*/
|
#endif /*Honor_FLT_ROUNDS*/
|
||||||
#ifdef SET_INEXACT
|
#ifdef SET_INEXACT
|
||||||
/* set overflow bit */
|
/* set overflow bit */
|
||||||
dval(rv0) = 1e300;
|
dval(&rv0) = 1e300;
|
||||||
dval(rv0) *= dval(rv0);
|
dval(&rv0) *= dval(&rv0);
|
||||||
#endif
|
#endif
|
||||||
#else /*IEEE_Arith*/
|
#else /*IEEE_Arith*/
|
||||||
word0(rv) = Big0;
|
word0(&rv) = Big0;
|
||||||
word1(rv) = Big1;
|
word1(&rv) = Big1;
|
||||||
#endif /*IEEE_Arith*/
|
#endif /*IEEE_Arith*/
|
||||||
if (bd0)
|
range_err:
|
||||||
goto retfree;
|
if (bd0) {
|
||||||
|
Bfree(bb);
|
||||||
|
Bfree(bd);
|
||||||
|
Bfree(bs);
|
||||||
|
Bfree(bd0);
|
||||||
|
Bfree(delta);
|
||||||
|
}
|
||||||
|
#ifndef NO_ERRNO
|
||||||
|
errno = ERANGE;
|
||||||
|
#endif
|
||||||
goto ret;
|
goto ret;
|
||||||
}
|
}
|
||||||
e1 >>= 4;
|
e1 >>= 4;
|
||||||
for(j = 0; e1 > 1; j++, e1 >>= 1)
|
for(j = 0; e1 > 1; j++, e1 >>= 1)
|
||||||
if (e1 & 1)
|
if (e1 & 1)
|
||||||
dval(rv) *= bigtens[j];
|
dval(&rv) *= bigtens[j];
|
||||||
/* The last multiplication could overflow. */
|
/* The last multiplication could overflow. */
|
||||||
word0(rv) -= P*Exp_msk1;
|
word0(&rv) -= P*Exp_msk1;
|
||||||
dval(rv) *= bigtens[j];
|
dval(&rv) *= bigtens[j];
|
||||||
if ((z = word0(rv) & Exp_mask)
|
if ((z = word0(&rv) & Exp_mask)
|
||||||
> Exp_msk1*(DBL_MAX_EXP+Bias-P))
|
> Exp_msk1*(DBL_MAX_EXP+Bias-P))
|
||||||
goto ovfl;
|
goto ovfl;
|
||||||
if (z > Exp_msk1*(DBL_MAX_EXP+Bias-1-P)) {
|
if (z > Exp_msk1*(DBL_MAX_EXP+Bias-1-P)) {
|
||||||
/* set to largest number */
|
/* set to largest number */
|
||||||
/* (Can't trust DBL_MAX) */
|
/* (Can't trust DBL_MAX) */
|
||||||
word0(rv) = Big0;
|
word0(&rv) = Big0;
|
||||||
word1(rv) = Big1;
|
word1(&rv) = Big1;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
word0(rv) += P*Exp_msk1;
|
word0(&rv) += P*Exp_msk1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
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 >>= 4) {
|
if (e1 >>= 4) {
|
||||||
if (e1 >= 1 << n_bigtens)
|
if (e1 >= 1 << n_bigtens)
|
||||||
goto undfl;
|
goto undfl;
|
||||||
|
@ -466,44 +527,39 @@ strtod
|
||||||
scale = 2*P;
|
scale = 2*P;
|
||||||
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];
|
||||||
if (scale && (j = 2*P + 1 - ((word0(rv) & Exp_mask)
|
if (scale && (j = 2*P + 1 - ((word0(&rv) & Exp_mask)
|
||||||
>> Exp_shift)) > 0) {
|
>> Exp_shift)) > 0) {
|
||||||
/* scaled rv is denormal; zap j low bits */
|
/* scaled rv is denormal; zap j low bits */
|
||||||
if (j >= 32) {
|
if (j >= 32) {
|
||||||
word1(rv) = 0;
|
word1(&rv) = 0;
|
||||||
if (j >= 53)
|
if (j >= 53)
|
||||||
word0(rv) = (P+2)*Exp_msk1;
|
word0(&rv) = (P+2)*Exp_msk1;
|
||||||
else
|
else
|
||||||
word0(rv) &= 0xffffffff << j-32;
|
word0(&rv) &= 0xffffffff << (j-32);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
word1(rv) &= 0xffffffff << j;
|
word1(&rv) &= 0xffffffff << j;
|
||||||
}
|
}
|
||||||
#else
|
#else
|
||||||
for(j = 0; e1 > 1; j++, e1 >>= 1)
|
for(j = 0; e1 > 1; j++, e1 >>= 1)
|
||||||
if (e1 & 1)
|
if (e1 & 1)
|
||||||
dval(rv) *= tinytens[j];
|
dval(&rv) *= tinytens[j];
|
||||||
/* The last multiplication could underflow. */
|
/* The last multiplication could underflow. */
|
||||||
dval(rv0) = dval(rv);
|
dval(&rv0) = dval(&rv);
|
||||||
dval(rv) *= tinytens[j];
|
dval(&rv) *= tinytens[j];
|
||||||
if (!dval(rv)) {
|
if (!dval(&rv)) {
|
||||||
dval(rv) = 2.*dval(rv0);
|
dval(&rv) = 2.*dval(&rv0);
|
||||||
dval(rv) *= tinytens[j];
|
dval(&rv) *= tinytens[j];
|
||||||
#endif
|
#endif
|
||||||
if (!dval(rv)) {
|
if (!dval(&rv)) {
|
||||||
undfl:
|
undfl:
|
||||||
dval(rv) = 0.;
|
dval(&rv) = 0.;
|
||||||
#ifndef NO_ERRNO
|
goto range_err;
|
||||||
errno = ERANGE;
|
|
||||||
#endif
|
|
||||||
if (bd0)
|
|
||||||
goto retfree;
|
|
||||||
goto ret;
|
|
||||||
}
|
}
|
||||||
#ifndef Avoid_Underflow
|
#ifndef Avoid_Underflow
|
||||||
word0(rv) = Tiny0;
|
word0(&rv) = Tiny0;
|
||||||
word1(rv) = Tiny1;
|
word1(&rv) = Tiny1;
|
||||||
/* The refinement below will clean
|
/* The refinement below will clean
|
||||||
* this approximation up.
|
* this approximation up.
|
||||||
*/
|
*/
|
||||||
|
@ -516,12 +572,12 @@ strtod
|
||||||
|
|
||||||
/* 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);
|
||||||
Bcopy(bd, bd0);
|
Bcopy(bd, bd0);
|
||||||
bb = d2b(dval(rv), &bbe, &bbbits); /* rv = bb * 2^bbe */
|
bb = d2b(dval(&rv), &bbe, &bbbits); /* rv = bb * 2^bbe */
|
||||||
bs = i2b(1);
|
bs = i2b(1);
|
||||||
|
|
||||||
if (e >= 0) {
|
if (e >= 0) {
|
||||||
|
@ -538,16 +594,23 @@ strtod
|
||||||
bd2 -= bbe;
|
bd2 -= bbe;
|
||||||
bs2 = bb2;
|
bs2 = bb2;
|
||||||
#ifdef Honor_FLT_ROUNDS
|
#ifdef Honor_FLT_ROUNDS
|
||||||
if (rounding != 1)
|
if (Rounding != 1)
|
||||||
bs2++;
|
bs2++;
|
||||||
#endif
|
#endif
|
||||||
#ifdef Avoid_Underflow
|
#ifdef Avoid_Underflow
|
||||||
|
Lsb = LSB;
|
||||||
|
Lsb1 = 0;
|
||||||
j = bbe - scale;
|
j = bbe - scale;
|
||||||
i = j + bbbits - 1; /* logb(rv) */
|
i = j + bbbits - 1; /* logb(rv) */
|
||||||
if (i < Emin) /* denormal */
|
|
||||||
j += P - Emin;
|
|
||||||
else
|
|
||||||
j = P + 1 - bbbits;
|
j = P + 1 - bbbits;
|
||||||
|
if (i < Emin) { /* denormal */
|
||||||
|
i = Emin - i;
|
||||||
|
j -= i;
|
||||||
|
if (i < 32)
|
||||||
|
Lsb <<= i;
|
||||||
|
else
|
||||||
|
Lsb1 = Lsb << (i-32);
|
||||||
|
}
|
||||||
#else /*Avoid_Underflow*/
|
#else /*Avoid_Underflow*/
|
||||||
#ifdef Sudden_Underflow
|
#ifdef Sudden_Underflow
|
||||||
#ifdef IBM
|
#ifdef IBM
|
||||||
|
@ -557,7 +620,7 @@ strtod
|
||||||
#endif
|
#endif
|
||||||
#else /*Sudden_Underflow*/
|
#else /*Sudden_Underflow*/
|
||||||
j = bbe;
|
j = bbe;
|
||||||
i = j + bbbits - 1; /* logb(rv) */
|
i = j + bbbits - 1; /* logb(&rv) */
|
||||||
if (i < Emin) /* denormal */
|
if (i < Emin) /* denormal */
|
||||||
j += P - Emin;
|
j += P - Emin;
|
||||||
else
|
else
|
||||||
|
@ -596,7 +659,7 @@ strtod
|
||||||
delta->sign = 0;
|
delta->sign = 0;
|
||||||
i = cmp(delta, bs);
|
i = cmp(delta, bs);
|
||||||
#ifdef Honor_FLT_ROUNDS
|
#ifdef Honor_FLT_ROUNDS
|
||||||
if (rounding != 1) {
|
if (Rounding != 1) {
|
||||||
if (i < 0) {
|
if (i < 0) {
|
||||||
/* Error is less than an ulp */
|
/* Error is less than an ulp */
|
||||||
if (!delta->x[0] && delta->wds <= 1) {
|
if (!delta->x[0] && delta->wds <= 1) {
|
||||||
|
@ -606,17 +669,17 @@ strtod
|
||||||
#endif
|
#endif
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
if (rounding) {
|
if (Rounding) {
|
||||||
if (dsign) {
|
if (dsign) {
|
||||||
adj = 1.;
|
dval(&adj) = 1.;
|
||||||
goto apply_adj;
|
goto apply_adj;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (!dsign) {
|
else if (!dsign) {
|
||||||
adj = -1.;
|
dval(&adj) = -1.;
|
||||||
if (!word1(rv)
|
if (!word1(&rv)
|
||||||
&& !(word0(rv) & Frac_mask)) {
|
&& !(word0(&rv) & Frac_mask)) {
|
||||||
y = word0(rv) & Exp_mask;
|
y = word0(&rv) & Exp_mask;
|
||||||
#ifdef Avoid_Underflow
|
#ifdef Avoid_Underflow
|
||||||
if (!scale || y > 2*P*Exp_msk1)
|
if (!scale || y > 2*P*Exp_msk1)
|
||||||
#else
|
#else
|
||||||
|
@ -625,63 +688,66 @@ strtod
|
||||||
{
|
{
|
||||||
delta = lshift(delta,Log2P);
|
delta = lshift(delta,Log2P);
|
||||||
if (cmp(delta, bs) <= 0)
|
if (cmp(delta, bs) <= 0)
|
||||||
adj = -0.5;
|
dval(&adj) = -0.5;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
apply_adj:
|
apply_adj:
|
||||||
#ifdef Avoid_Underflow
|
#ifdef Avoid_Underflow
|
||||||
if (scale && (y = word0(rv) & Exp_mask)
|
if (scale && (y = word0(&rv) & Exp_mask)
|
||||||
<= 2*P*Exp_msk1)
|
<= 2*P*Exp_msk1)
|
||||||
word0(adj) += (2*P+1)*Exp_msk1 - y;
|
word0(&adj) += (2*P+1)*Exp_msk1 - y;
|
||||||
#else
|
#else
|
||||||
#ifdef Sudden_Underflow
|
#ifdef Sudden_Underflow
|
||||||
if ((word0(rv) & Exp_mask) <=
|
if ((word0(&rv) & Exp_mask) <=
|
||||||
P*Exp_msk1) {
|
P*Exp_msk1) {
|
||||||
word0(rv) += P*Exp_msk1;
|
word0(&rv) += P*Exp_msk1;
|
||||||
dval(rv) += adj*ulp(dval(rv));
|
dval(&rv) += adj*ulp(&rv);
|
||||||
word0(rv) -= P*Exp_msk1;
|
word0(&rv) -= P*Exp_msk1;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
#endif /*Sudden_Underflow*/
|
#endif /*Sudden_Underflow*/
|
||||||
#endif /*Avoid_Underflow*/
|
#endif /*Avoid_Underflow*/
|
||||||
dval(rv) += adj*ulp(dval(rv));
|
dval(&rv) += adj.d*ulp(&rv);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
adj = ratio(delta, bs);
|
dval(&adj) = ratio(delta, bs);
|
||||||
if (adj < 1.)
|
if (adj.d < 1.)
|
||||||
adj = 1.;
|
dval(&adj) = 1.;
|
||||||
if (adj <= 0x7ffffffe) {
|
if (adj.d <= 0x7ffffffe) {
|
||||||
/* adj = rounding ? ceil(adj) : floor(adj); */
|
/* dval(&adj) = Rounding ? ceil(&adj) : floor(&adj); */
|
||||||
y = adj;
|
y = adj.d;
|
||||||
if (y != adj) {
|
if (y != adj.d) {
|
||||||
if (!((rounding>>1) ^ dsign))
|
if (!((Rounding>>1) ^ dsign))
|
||||||
y++;
|
y++;
|
||||||
adj = y;
|
dval(&adj) = y;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#ifdef Avoid_Underflow
|
#ifdef Avoid_Underflow
|
||||||
if (scale && (y = word0(rv) & Exp_mask) <= 2*P*Exp_msk1)
|
if (scale && (y = word0(&rv) & Exp_mask) <= 2*P*Exp_msk1)
|
||||||
word0(adj) += (2*P+1)*Exp_msk1 - y;
|
word0(&adj) += (2*P+1)*Exp_msk1 - y;
|
||||||
#else
|
#else
|
||||||
#ifdef Sudden_Underflow
|
#ifdef Sudden_Underflow
|
||||||
if ((word0(rv) & Exp_mask) <= P*Exp_msk1) {
|
if ((word0(&rv) & Exp_mask) <= P*Exp_msk1) {
|
||||||
word0(rv) += P*Exp_msk1;
|
word0(&rv) += P*Exp_msk1;
|
||||||
adj *= ulp(dval(rv));
|
dval(&adj) *= ulp(&rv);
|
||||||
if (dsign)
|
if (dsign)
|
||||||
dval(rv) += adj;
|
dval(&rv) += adj;
|
||||||
else
|
else
|
||||||
dval(rv) -= adj;
|
dval(&rv) -= adj;
|
||||||
word0(rv) -= P*Exp_msk1;
|
word0(&rv) -= P*Exp_msk1;
|
||||||
goto cont;
|
goto cont;
|
||||||
}
|
}
|
||||||
#endif /*Sudden_Underflow*/
|
#endif /*Sudden_Underflow*/
|
||||||
#endif /*Avoid_Underflow*/
|
#endif /*Avoid_Underflow*/
|
||||||
adj *= ulp(dval(rv));
|
dval(&adj) *= ulp(&rv);
|
||||||
if (dsign)
|
if (dsign) {
|
||||||
dval(rv) += adj;
|
if (word0(&rv) == Big0 && word1(&rv) == Big1)
|
||||||
|
goto ovfl;
|
||||||
|
dval(&rv) += adj.d;
|
||||||
|
}
|
||||||
else
|
else
|
||||||
dval(rv) -= adj;
|
dval(&rv) -= adj.d;
|
||||||
goto cont;
|
goto cont;
|
||||||
}
|
}
|
||||||
#endif /*Honor_FLT_ROUNDS*/
|
#endif /*Honor_FLT_ROUNDS*/
|
||||||
|
@ -690,12 +756,12 @@ strtod
|
||||||
/* 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.
|
||||||
*/
|
*/
|
||||||
if (dsign || word1(rv) || word0(rv) & Bndry_mask
|
if (dsign || word1(&rv) || word0(&rv) & Bndry_mask
|
||||||
#ifdef IEEE_Arith
|
#ifdef IEEE_Arith
|
||||||
#ifdef Avoid_Underflow
|
#ifdef Avoid_Underflow
|
||||||
|| (word0(rv) & Exp_mask) <= (2*P+1)*Exp_msk1
|
|| (word0(&rv) & Exp_mask) <= (2*P+1)*Exp_msk1
|
||||||
#else
|
#else
|
||||||
|| (word0(rv) & Exp_mask) <= Exp_msk1
|
|| (word0(&rv) & Exp_mask) <= Exp_msk1
|
||||||
#endif
|
#endif
|
||||||
#endif
|
#endif
|
||||||
) {
|
) {
|
||||||
|
@ -720,32 +786,34 @@ strtod
|
||||||
if (i == 0) {
|
if (i == 0) {
|
||||||
/* exactly half-way between */
|
/* exactly half-way between */
|
||||||
if (dsign) {
|
if (dsign) {
|
||||||
if ((word0(rv) & Bndry_mask1) == Bndry_mask1
|
if ((word0(&rv) & Bndry_mask1) == Bndry_mask1
|
||||||
&& word1(rv) == (
|
&& word1(&rv) == (
|
||||||
#ifdef Avoid_Underflow
|
#ifdef Avoid_Underflow
|
||||||
(scale && (y = word0(rv) & Exp_mask) <= 2*P*Exp_msk1)
|
(scale && (y = word0(&rv) & Exp_mask) <= 2*P*Exp_msk1)
|
||||||
? (0xffffffff & (0xffffffff << (2*P+1-(y>>Exp_shift)))) :
|
? (0xffffffff & (0xffffffff << (2*P+1-(y>>Exp_shift)))) :
|
||||||
#endif
|
#endif
|
||||||
0xffffffff)) {
|
0xffffffff)) {
|
||||||
/*boundary case -- increment exponent*/
|
/*boundary case -- increment exponent*/
|
||||||
word0(rv) = (word0(rv) & Exp_mask)
|
if (word0(&rv) == Big0 && word1(&rv) == Big1)
|
||||||
|
goto ovfl;
|
||||||
|
word0(&rv) = (word0(&rv) & Exp_mask)
|
||||||
+ Exp_msk1
|
+ Exp_msk1
|
||||||
#ifdef IBM
|
#ifdef IBM
|
||||||
| Exp_msk1 >> 4
|
| Exp_msk1 >> 4
|
||||||
#endif
|
#endif
|
||||||
;
|
;
|
||||||
word1(rv) = 0;
|
word1(&rv) = 0;
|
||||||
#ifdef Avoid_Underflow
|
#ifdef Avoid_Underflow
|
||||||
dsign = 0;
|
dsign = 0;
|
||||||
#endif
|
#endif
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (!(word0(rv) & Bndry_mask) && !word1(rv)) {
|
else if (!(word0(&rv) & Bndry_mask) && !word1(&rv)) {
|
||||||
drop_down:
|
drop_down:
|
||||||
/* boundary case -- decrement exponent */
|
/* boundary case -- decrement exponent */
|
||||||
#ifdef Sudden_Underflow /*{{*/
|
#ifdef Sudden_Underflow /*{{*/
|
||||||
L = word0(rv) & Exp_mask;
|
L = word0(&rv) & Exp_mask;
|
||||||
#ifdef IBM
|
#ifdef IBM
|
||||||
if (L < Exp_msk1)
|
if (L < Exp_msk1)
|
||||||
#else
|
#else
|
||||||
|
@ -760,7 +828,7 @@ strtod
|
||||||
#else /*Sudden_Underflow}{*/
|
#else /*Sudden_Underflow}{*/
|
||||||
#ifdef Avoid_Underflow
|
#ifdef Avoid_Underflow
|
||||||
if (scale) {
|
if (scale) {
|
||||||
L = word0(rv) & Exp_mask;
|
L = word0(&rv) & Exp_mask;
|
||||||
if (L <= (2*P+1)*Exp_msk1) {
|
if (L <= (2*P+1)*Exp_msk1) {
|
||||||
if (L > (P+2)*Exp_msk1)
|
if (L > (P+2)*Exp_msk1)
|
||||||
/* round even ==> */
|
/* round even ==> */
|
||||||
|
@ -771,10 +839,10 @@ strtod
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#endif /*Avoid_Underflow*/
|
#endif /*Avoid_Underflow*/
|
||||||
L = (word0(rv) & Exp_mask) - Exp_msk1;
|
L = (word0(&rv) & Exp_mask) - Exp_msk1;
|
||||||
#endif /*Sudden_Underflow}*/
|
#endif /*Sudden_Underflow}}*/
|
||||||
word0(rv) = L | Bndry_mask1;
|
word0(&rv) = L | Bndry_mask1;
|
||||||
word1(rv) = 0xffffffff;
|
word1(&rv) = 0xffffffff;
|
||||||
#ifdef IBM
|
#ifdef IBM
|
||||||
goto cont;
|
goto cont;
|
||||||
#else
|
#else
|
||||||
|
@ -782,16 +850,33 @@ strtod
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
#ifndef ROUND_BIASED
|
#ifndef ROUND_BIASED
|
||||||
if (!(word1(rv) & LSB))
|
#ifdef Avoid_Underflow
|
||||||
|
if (Lsb1) {
|
||||||
|
if (!(word0(&rv) & Lsb1))
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
else if (!(word1(&rv) & Lsb))
|
||||||
|
break;
|
||||||
|
#else
|
||||||
|
if (!(word1(&rv) & LSB))
|
||||||
break;
|
break;
|
||||||
|
#endif
|
||||||
#endif
|
#endif
|
||||||
if (dsign)
|
if (dsign)
|
||||||
dval(rv) += ulp(dval(rv));
|
#ifdef Avoid_Underflow
|
||||||
|
dval(&rv) += sulp(&rv, scale);
|
||||||
|
#else
|
||||||
|
dval(&rv) += ulp(&rv);
|
||||||
|
#endif
|
||||||
#ifndef ROUND_BIASED
|
#ifndef ROUND_BIASED
|
||||||
else {
|
else {
|
||||||
dval(rv) -= ulp(dval(rv));
|
#ifdef Avoid_Underflow
|
||||||
|
dval(&rv) -= sulp(&rv, scale);
|
||||||
|
#else
|
||||||
|
dval(&rv) -= ulp(&rv);
|
||||||
|
#endif
|
||||||
#ifndef Sudden_Underflow
|
#ifndef Sudden_Underflow
|
||||||
if (!dval(rv))
|
if (!dval(&rv))
|
||||||
goto undfl;
|
goto undfl;
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
@ -803,14 +888,14 @@ strtod
|
||||||
}
|
}
|
||||||
if ((aadj = ratio(delta, bs)) <= 2.) {
|
if ((aadj = ratio(delta, bs)) <= 2.) {
|
||||||
if (dsign)
|
if (dsign)
|
||||||
aadj = dval(aadj1) = 1.;
|
aadj = dval(&aadj1) = 1.;
|
||||||
else if (word1(rv) || word0(rv) & Bndry_mask) {
|
else if (word1(&rv) || word0(&rv) & Bndry_mask) {
|
||||||
#ifndef Sudden_Underflow
|
#ifndef Sudden_Underflow
|
||||||
if (word1(rv) == Tiny1 && !word0(rv))
|
if (word1(&rv) == Tiny1 && !word0(&rv))
|
||||||
goto undfl;
|
goto undfl;
|
||||||
#endif
|
#endif
|
||||||
aadj = 1.;
|
aadj = 1.;
|
||||||
dval(aadj1) = -1.;
|
dval(&aadj1) = -1.;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
/* special case -- power of FLT_RADIX to be */
|
/* special case -- power of FLT_RADIX to be */
|
||||||
|
@ -820,45 +905,45 @@ strtod
|
||||||
aadj = 1./FLT_RADIX;
|
aadj = 1./FLT_RADIX;
|
||||||
else
|
else
|
||||||
aadj *= 0.5;
|
aadj *= 0.5;
|
||||||
dval(aadj1) = -aadj;
|
dval(&aadj1) = -aadj;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
aadj *= 0.5;
|
aadj *= 0.5;
|
||||||
dval(aadj1) = dsign ? aadj : -aadj;
|
dval(&aadj1) = dsign ? aadj : -aadj;
|
||||||
#ifdef Check_FLT_ROUNDS
|
#ifdef Check_FLT_ROUNDS
|
||||||
switch(Rounding) {
|
switch(Rounding) {
|
||||||
case 2: /* towards +infinity */
|
case 2: /* towards +infinity */
|
||||||
aadj1 -= 0.5;
|
dval(&aadj1) -= 0.5;
|
||||||
break;
|
break;
|
||||||
case 0: /* towards 0 */
|
case 0: /* towards 0 */
|
||||||
case 3: /* towards -infinity */
|
case 3: /* towards -infinity */
|
||||||
aadj1 += 0.5;
|
dval(&aadj1) += 0.5;
|
||||||
}
|
}
|
||||||
#else
|
#else
|
||||||
if (Flt_Rounds == 0)
|
if (Flt_Rounds == 0)
|
||||||
dval(aadj1) += 0.5;
|
dval(&aadj1) += 0.5;
|
||||||
#endif /*Check_FLT_ROUNDS*/
|
#endif /*Check_FLT_ROUNDS*/
|
||||||
}
|
}
|
||||||
y = word0(rv) & Exp_mask;
|
y = word0(&rv) & Exp_mask;
|
||||||
|
|
||||||
/* Check for overflow */
|
/* Check for overflow */
|
||||||
|
|
||||||
if (y == Exp_msk1*(DBL_MAX_EXP+Bias-1)) {
|
if (y == Exp_msk1*(DBL_MAX_EXP+Bias-1)) {
|
||||||
dval(rv0) = dval(rv);
|
dval(&rv0) = dval(&rv);
|
||||||
word0(rv) -= P*Exp_msk1;
|
word0(&rv) -= P*Exp_msk1;
|
||||||
adj = dval(aadj1) * ulp(dval(rv));
|
dval(&adj) = dval(&aadj1) * ulp(&rv);
|
||||||
dval(rv) += adj;
|
dval(&rv) += dval(&adj);
|
||||||
if ((word0(rv) & Exp_mask) >=
|
if ((word0(&rv) & Exp_mask) >=
|
||||||
Exp_msk1*(DBL_MAX_EXP+Bias-P)) {
|
Exp_msk1*(DBL_MAX_EXP+Bias-P)) {
|
||||||
if (word0(rv0) == Big0 && word1(rv0) == Big1)
|
if (word0(&rv0) == Big0 && word1(&rv0) == Big1)
|
||||||
goto ovfl;
|
goto ovfl;
|
||||||
word0(rv) = Big0;
|
word0(&rv) = Big0;
|
||||||
word1(rv) = Big1;
|
word1(&rv) = Big1;
|
||||||
goto cont;
|
goto cont;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
word0(rv) += P*Exp_msk1;
|
word0(&rv) += P*Exp_msk1;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
#ifdef Avoid_Underflow
|
#ifdef Avoid_Underflow
|
||||||
|
@ -867,58 +952,58 @@ strtod
|
||||||
if ((z = (ULong)aadj) <= 0)
|
if ((z = (ULong)aadj) <= 0)
|
||||||
z = 1;
|
z = 1;
|
||||||
aadj = z;
|
aadj = z;
|
||||||
dval(aadj1) = dsign ? aadj : -aadj;
|
dval(&aadj1) = dsign ? aadj : -aadj;
|
||||||
}
|
}
|
||||||
word0(aadj1) += (2*P+1)*Exp_msk1 - y;
|
word0(&aadj1) += (2*P+1)*Exp_msk1 - y;
|
||||||
}
|
}
|
||||||
adj = dval(aadj1) * ulp(dval(rv));
|
dval(&adj) = dval(&aadj1) * ulp(&rv);
|
||||||
dval(rv) += adj;
|
dval(&rv) += dval(&adj);
|
||||||
#else
|
#else
|
||||||
#ifdef Sudden_Underflow
|
#ifdef Sudden_Underflow
|
||||||
if ((word0(rv) & Exp_mask) <= P*Exp_msk1) {
|
if ((word0(&rv) & Exp_mask) <= P*Exp_msk1) {
|
||||||
dval(rv0) = dval(rv);
|
dval(&rv0) = dval(&rv);
|
||||||
word0(rv) += P*Exp_msk1;
|
word0(&rv) += P*Exp_msk1;
|
||||||
adj = aadj1 * ulp(dval(rv));
|
dval(&adj) = dval(&aadj1) * ulp(&rv);
|
||||||
dval(rv) += adj;
|
dval(&rv) += adj;
|
||||||
#ifdef IBM
|
#ifdef IBM
|
||||||
if ((word0(rv) & Exp_mask) < P*Exp_msk1)
|
if ((word0(&rv) & Exp_mask) < P*Exp_msk1)
|
||||||
#else
|
#else
|
||||||
if ((word0(rv) & Exp_mask) <= P*Exp_msk1)
|
if ((word0(&rv) & Exp_mask) <= P*Exp_msk1)
|
||||||
#endif
|
#endif
|
||||||
{
|
{
|
||||||
if (word0(rv0) == Tiny0
|
if (word0(&rv0) == Tiny0
|
||||||
&& word1(rv0) == Tiny1)
|
&& word1(&rv0) == Tiny1)
|
||||||
goto undfl;
|
goto undfl;
|
||||||
word0(rv) = Tiny0;
|
word0(&rv) = Tiny0;
|
||||||
word1(rv) = Tiny1;
|
word1(&rv) = Tiny1;
|
||||||
goto cont;
|
goto cont;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
word0(rv) -= P*Exp_msk1;
|
word0(&rv) -= P*Exp_msk1;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
adj = aadj1 * ulp(dval(rv));
|
dval(&adj) = dval(&aadj1) * ulp(&rv);
|
||||||
dval(rv) += adj;
|
dval(&rv) += adj;
|
||||||
}
|
}
|
||||||
#else /*Sudden_Underflow*/
|
#else /*Sudden_Underflow*/
|
||||||
/* Compute adj so that the IEEE rounding rules will
|
/* Compute dval(&adj) so that the IEEE rounding rules will
|
||||||
* correctly round rv + adj in some half-way cases.
|
* correctly round rv + dval(&adj) in some half-way cases.
|
||||||
* If rv * ulp(rv) is denormalized (i.e.,
|
* If rv * ulp(&rv) is denormalized (i.e.,
|
||||||
* y <= (P-1)*Exp_msk1), we must adjust aadj to avoid
|
* y <= (P-1)*Exp_msk1), we must adjust aadj to avoid
|
||||||
* trouble from bits lost to denormalization;
|
* trouble from bits lost to denormalization;
|
||||||
* example: 1.2e-307 .
|
* example: 1.2e-307 .
|
||||||
*/
|
*/
|
||||||
if (y <= (P-1)*Exp_msk1 && aadj > 1.) {
|
if (y <= (P-1)*Exp_msk1 && aadj > 1.) {
|
||||||
aadj1 = (double)(int)(aadj + 0.5);
|
dval(&aadj1) = (double)(int)(aadj + 0.5);
|
||||||
if (!dsign)
|
if (!dsign)
|
||||||
aadj1 = -aadj1;
|
dval(&aadj1) = -dval(&aadj1);
|
||||||
}
|
}
|
||||||
adj = aadj1 * ulp(dval(rv));
|
dval(&adj) = dval(&aadj1) * ulp(&rv);
|
||||||
dval(rv) += adj;
|
dval(&rv) += adj;
|
||||||
#endif /*Sudden_Underflow*/
|
#endif /*Sudden_Underflow*/
|
||||||
#endif /*Avoid_Underflow*/
|
#endif /*Avoid_Underflow*/
|
||||||
}
|
}
|
||||||
z = word0(rv) & Exp_mask;
|
z = word0(&rv) & Exp_mask;
|
||||||
#ifndef SET_INEXACT
|
#ifndef SET_INEXACT
|
||||||
#ifdef Avoid_Underflow
|
#ifdef Avoid_Underflow
|
||||||
if (!scale)
|
if (!scale)
|
||||||
|
@ -928,7 +1013,7 @@ strtod
|
||||||
L = (Long)aadj;
|
L = (Long)aadj;
|
||||||
aadj -= L;
|
aadj -= L;
|
||||||
/* The tolerances below are conservative. */
|
/* The tolerances below are conservative. */
|
||||||
if (dsign || word1(rv) || word0(rv) & Bndry_mask) {
|
if (dsign || word1(&rv) || word0(&rv) & Bndry_mask) {
|
||||||
if (aadj < .4999999 || aadj > .5000001)
|
if (aadj < .4999999 || aadj > .5000001)
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -942,12 +1027,17 @@ strtod
|
||||||
Bfree(bs);
|
Bfree(bs);
|
||||||
Bfree(delta);
|
Bfree(delta);
|
||||||
}
|
}
|
||||||
|
Bfree(bb);
|
||||||
|
Bfree(bd);
|
||||||
|
Bfree(bs);
|
||||||
|
Bfree(bd0);
|
||||||
|
Bfree(delta);
|
||||||
#ifdef SET_INEXACT
|
#ifdef SET_INEXACT
|
||||||
if (inexact) {
|
if (inexact) {
|
||||||
if (!oldinexact) {
|
if (!oldinexact) {
|
||||||
word0(rv0) = Exp_1 + (70 << Exp_shift);
|
word0(&rv0) = Exp_1 + (70 << Exp_shift);
|
||||||
word1(rv0) = 0;
|
word1(&rv0) = 0;
|
||||||
dval(rv0) += 1.;
|
dval(&rv0) += 1.;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (!oldinexact)
|
else if (!oldinexact)
|
||||||
|
@ -955,32 +1045,30 @@ strtod
|
||||||
#endif
|
#endif
|
||||||
#ifdef Avoid_Underflow
|
#ifdef Avoid_Underflow
|
||||||
if (scale) {
|
if (scale) {
|
||||||
word0(rv0) = Exp_1 - 2*P*Exp_msk1;
|
word0(&rv0) = Exp_1 - 2*P*Exp_msk1;
|
||||||
word1(rv0) = 0;
|
word1(&rv0) = 0;
|
||||||
dval(rv) *= dval(rv0);
|
dval(&rv) *= dval(&rv0);
|
||||||
#ifndef NO_ERRNO
|
#ifndef NO_ERRNO
|
||||||
/* try to avoid the bug of testing an 8087 register value */
|
/* try to avoid the bug of testing an 8087 register value */
|
||||||
if (word0(rv) == 0 && word1(rv) == 0)
|
#ifdef IEEE_Arith
|
||||||
|
if (!(word0(&rv) & Exp_mask))
|
||||||
|
#else
|
||||||
|
if (word0(&rv) == 0 && word1(&rv) == 0)
|
||||||
|
#endif
|
||||||
errno = ERANGE;
|
errno = ERANGE;
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
#endif /* Avoid_Underflow */
|
#endif /* Avoid_Underflow */
|
||||||
#ifdef SET_INEXACT
|
#ifdef SET_INEXACT
|
||||||
if (inexact && !(word0(rv) & Exp_mask)) {
|
if (inexact && !(word0(&rv) & Exp_mask)) {
|
||||||
/* set underflow bit */
|
/* set underflow bit */
|
||||||
dval(rv0) = 1e-300;
|
dval(&rv0) = 1e-300;
|
||||||
dval(rv0) *= dval(rv0);
|
dval(&rv0) *= dval(&rv0);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
retfree:
|
|
||||||
Bfree(bb);
|
|
||||||
Bfree(bd);
|
|
||||||
Bfree(bs);
|
|
||||||
Bfree(bd0);
|
|
||||||
Bfree(delta);
|
|
||||||
ret:
|
ret:
|
||||||
if (se)
|
if (se)
|
||||||
*se = (char *)s;
|
*se = (char *)s;
|
||||||
return sign ? -dval(rv) : dval(rv);
|
return sign ? -dval(&rv) : dval(&rv);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -33,16 +33,16 @@ THIS SOFTWARE.
|
||||||
|
|
||||||
static double
|
static double
|
||||||
#ifdef KR_headers
|
#ifdef KR_headers
|
||||||
ulpdown(d) double *d;
|
ulpdown(d) U *d;
|
||||||
#else
|
#else
|
||||||
ulpdown(double *d)
|
ulpdown(U *d)
|
||||||
#endif
|
#endif
|
||||||
{
|
{
|
||||||
double u;
|
double u;
|
||||||
ULong *L = (ULong*)d;
|
ULong *L = d->L;
|
||||||
|
|
||||||
u = ulp(*d);
|
u = ulp(d);
|
||||||
if (!(L[_1] | L[_0] & 0xfffff)
|
if (!(L[_1] | (L[_0] & 0xfffff))
|
||||||
&& (L[_0] & 0x7ff00000) > 0x00100000)
|
&& (L[_0] & 0x7ff00000) > 0x00100000)
|
||||||
u *= 0.5;
|
u *= 0.5;
|
||||||
return u;
|
return u;
|
||||||
|
@ -55,14 +55,10 @@ strtodI(s, sp, dd) CONST char *s; char **sp; double *dd;
|
||||||
strtodI(CONST char *s, char **sp, double *dd)
|
strtodI(CONST char *s, char **sp, double *dd)
|
||||||
#endif
|
#endif
|
||||||
{
|
{
|
||||||
static CONST 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], sign;
|
ULong bits[2], sign;
|
||||||
Long exp;
|
Long exp;
|
||||||
int j, k;
|
int j, k;
|
||||||
typedef union {
|
|
||||||
double d[2];
|
|
||||||
ULong L[4];
|
|
||||||
} U;
|
|
||||||
U *u;
|
U *u;
|
||||||
|
|
||||||
k = strtodg(s, sp, &fpi, &exp, bits);
|
k = strtodg(s, sp, &fpi, &exp, bits);
|
||||||
|
@ -70,17 +66,17 @@ strtodI(CONST char *s, char **sp, double *dd)
|
||||||
sign = k & STRTOG_Neg ? 0x80000000L : 0;
|
sign = k & STRTOG_Neg ? 0x80000000L : 0;
|
||||||
switch(k & STRTOG_Retmask) {
|
switch(k & STRTOG_Retmask) {
|
||||||
case STRTOG_NoNumber:
|
case STRTOG_NoNumber:
|
||||||
u->d[0] = u->d[1] = 0.;
|
dval(&u[0]) = dval(&u[1]) = 0.;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case STRTOG_Zero:
|
case STRTOG_Zero:
|
||||||
u->d[0] = u->d[1] = 0.;
|
dval(&u[0]) = dval(&u[1]) = 0.;
|
||||||
#ifdef Sudden_Underflow
|
#ifdef Sudden_Underflow
|
||||||
if (k & STRTOG_Inexact) {
|
if (k & STRTOG_Inexact) {
|
||||||
if (sign)
|
if (sign)
|
||||||
u->L[_0] = 0x80100000L;
|
word0(&u[0]) = 0x80100000L;
|
||||||
else
|
else
|
||||||
u->L[2+_0] = 0x100000L;
|
word0(&u[1]) = 0x100000L;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
#else
|
#else
|
||||||
|
@ -88,80 +84,80 @@ strtodI(CONST char *s, char **sp, double *dd)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
case STRTOG_Denormal:
|
case STRTOG_Denormal:
|
||||||
u->L[_1] = bits[0];
|
word1(&u[0]) = bits[0];
|
||||||
u->L[_0] = bits[1];
|
word0(&u[0]) = bits[1];
|
||||||
goto contain;
|
goto contain;
|
||||||
|
|
||||||
case STRTOG_Normal:
|
case STRTOG_Normal:
|
||||||
u->L[_1] = bits[0];
|
word1(&u[0]) = bits[0];
|
||||||
u->L[_0] = (bits[1] & ~0x100000) | ((exp + 0x3ff + 52) << 20);
|
word0(&u[0]) = (bits[1] & ~0x100000) | ((exp + 0x3ff + 52) << 20);
|
||||||
contain:
|
contain:
|
||||||
j = k & STRTOG_Inexact;
|
j = k & STRTOG_Inexact;
|
||||||
if (sign) {
|
if (sign) {
|
||||||
u->L[_0] |= sign;
|
word0(&u[0]) |= sign;
|
||||||
j = STRTOG_Inexact - j;
|
j = STRTOG_Inexact - j;
|
||||||
}
|
}
|
||||||
switch(j) {
|
switch(j) {
|
||||||
case STRTOG_Inexlo:
|
case STRTOG_Inexlo:
|
||||||
#ifdef Sudden_Underflow
|
#ifdef Sudden_Underflow
|
||||||
if ((u->L[_0] & 0x7ff00000) < 0x3500000) {
|
if ((u->L[_0] & 0x7ff00000) < 0x3500000) {
|
||||||
u->L[2+_0] = u->L[_0] + 0x3500000;
|
word0(&u[1]) = word0(&u[0]) + 0x3500000;
|
||||||
u->L[2+_1] = u->L[_1];
|
word1(&u[1]) = word1(&u[0]);
|
||||||
u->d[1] += ulp(u->d[1]);
|
dval(&u[1]) += ulp(&u[1]);
|
||||||
u->L[2+_0] -= 0x3500000;
|
word0(&u[1]) -= 0x3500000;
|
||||||
if (!(u->L[2+_0] & 0x7ff00000)) {
|
if (!(word0(&u[1]) & 0x7ff00000)) {
|
||||||
u->L[2+_0] = sign;
|
word0(&u[1]) = sign;
|
||||||
u->L[2+_1] = 0;
|
word1(&u[1]) = 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
#endif
|
#endif
|
||||||
u->d[1] = u->d[0] + ulp(u->d[0]);
|
dval(&u[1]) = dval(&u[0]) + ulp(&u[0]);
|
||||||
break;
|
break;
|
||||||
case STRTOG_Inexhi:
|
case STRTOG_Inexhi:
|
||||||
u->d[1] = u->d[0];
|
dval(&u[1]) = dval(&u[0]);
|
||||||
#ifdef Sudden_Underflow
|
#ifdef Sudden_Underflow
|
||||||
if ((u->L[_0] & 0x7ff00000) < 0x3500000) {
|
if ((word0(&u[0]) & 0x7ff00000) < 0x3500000) {
|
||||||
u->L[_0] += 0x3500000;
|
word0(&u[0]) += 0x3500000;
|
||||||
u->d[0] -= ulpdown(u->d);
|
dval(&u[0]) -= ulpdown(u);
|
||||||
u->L[_0] -= 0x3500000;
|
word0(&u[0]) -= 0x3500000;
|
||||||
if (!(u->L[_0] & 0x7ff00000)) {
|
if (!(word0(&u[0]) & 0x7ff00000)) {
|
||||||
u->L[_0] = sign;
|
word0(&u[0]) = sign;
|
||||||
u->L[_1] = 0;
|
word1(&u[0]) = 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
#endif
|
#endif
|
||||||
u->d[0] -= ulpdown(u->d);
|
dval(&u[0]) -= ulpdown(u);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
u->d[1] = u->d[0];
|
dval(&u[1]) = dval(&u[0]);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case STRTOG_Infinite:
|
case STRTOG_Infinite:
|
||||||
u->L[_0] = u->L[2+_0] = sign | 0x7ff00000;
|
word0(&u[0]) = word0(&u[1]) = sign | 0x7ff00000;
|
||||||
u->L[_1] = u->L[2+_1] = 0;
|
word1(&u[0]) = word1(&u[1]) = 0;
|
||||||
if (k & STRTOG_Inexact) {
|
if (k & STRTOG_Inexact) {
|
||||||
if (sign) {
|
if (sign) {
|
||||||
u->L[2+_0] = 0xffefffffL;
|
word0(&u[1]) = 0xffefffffL;
|
||||||
u->L[2+_1] = 0xffffffffL;
|
word1(&u[1]) = 0xffffffffL;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
u->L[_0] = 0x7fefffffL;
|
word0(&u[0]) = 0x7fefffffL;
|
||||||
u->L[_1] = 0xffffffffL;
|
word1(&u[0]) = 0xffffffffL;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case STRTOG_NaN:
|
case STRTOG_NaN:
|
||||||
u->L[0] = u->L[2] = d_QNAN0;
|
u->L[0] = (u+1)->L[0] = d_QNAN0;
|
||||||
u->L[1] = u->L[3] = d_QNAN1;
|
u->L[1] = (u+1)->L[1] = d_QNAN1;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case STRTOG_NaNbits:
|
case STRTOG_NaNbits:
|
||||||
u->L[_0] = u->L[2+_0] = 0x7ff00000 | sign | bits[1];
|
word0(&u[0]) = word0(&u[1]) = 0x7ff00000 | sign | bits[1];
|
||||||
u->L[_1] = u->L[2+_1] = bits[0];
|
word1(&u[0]) = word1(&u[1]) = bits[0];
|
||||||
}
|
}
|
||||||
return k;
|
return k;
|
||||||
}
|
}
|
||||||
|
|
203
gdtoa/strtodg.c
203
gdtoa/strtodg.c
|
@ -89,7 +89,7 @@ increment(Bigint *b)
|
||||||
return b;
|
return b;
|
||||||
}
|
}
|
||||||
|
|
||||||
int
|
void
|
||||||
#ifdef KR_headers
|
#ifdef KR_headers
|
||||||
decrement(b) Bigint *b;
|
decrement(b) Bigint *b;
|
||||||
#else
|
#else
|
||||||
|
@ -119,7 +119,6 @@ decrement(Bigint *b)
|
||||||
*x++ = y & 0xffff;
|
*x++ = y & 0xffff;
|
||||||
} while(borrow && x < xe);
|
} while(borrow && x < xe);
|
||||||
#endif
|
#endif
|
||||||
return STRTOG_Inexlo;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static int
|
static int
|
||||||
|
@ -173,9 +172,9 @@ set_ones(Bigint *b, int n)
|
||||||
rvOK
|
rvOK
|
||||||
#ifdef KR_headers
|
#ifdef KR_headers
|
||||||
(d, fpi, exp, bits, exact, rd, irv)
|
(d, fpi, exp, bits, exact, rd, irv)
|
||||||
double d; FPI *fpi; Long *exp; ULong *bits; int exact, rd, *irv;
|
U *d; FPI *fpi; Long *exp; ULong *bits; int exact, rd, *irv;
|
||||||
#else
|
#else
|
||||||
(double d, CONST FPI *fpi, Long *exp, ULong *bits, int exact, int rd, int *irv)
|
(U *d, FPI *fpi, Long *exp, ULong *bits, int exact, int rd, int *irv)
|
||||||
#endif
|
#endif
|
||||||
{
|
{
|
||||||
Bigint *b;
|
Bigint *b;
|
||||||
|
@ -183,7 +182,7 @@ rvOK
|
||||||
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) {
|
||||||
|
@ -206,9 +205,9 @@ rvOK
|
||||||
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;
|
||||||
|
@ -292,15 +291,12 @@ rvOK
|
||||||
|
|
||||||
static int
|
static int
|
||||||
#ifdef KR_headers
|
#ifdef KR_headers
|
||||||
mantbits(d) double d;
|
mantbits(d) U *d;
|
||||||
#else
|
#else
|
||||||
mantbits(double _d)
|
mantbits(U *d)
|
||||||
#endif
|
#endif
|
||||||
{
|
{
|
||||||
ULong L;
|
ULong L;
|
||||||
U d;
|
|
||||||
|
|
||||||
dval(d) = _d;
|
|
||||||
#ifdef VAX
|
#ifdef VAX
|
||||||
L = word1(d) << 16 | word1(d) >> 16;
|
L = word1(d) << 16 | word1(d) >> 16;
|
||||||
if (L)
|
if (L)
|
||||||
|
@ -322,7 +318,7 @@ strtodg
|
||||||
(s00, se, fpi, exp, bits)
|
(s00, se, fpi, exp, bits)
|
||||||
CONST char *s00; char **se; FPI *fpi; Long *exp; ULong *bits;
|
CONST char *s00; char **se; FPI *fpi; Long *exp; ULong *bits;
|
||||||
#else
|
#else
|
||||||
(CONST char *s00, char **se, CONST FPI *fpi, Long *exp, ULong *bits)
|
(CONST char *s00, char **se, FPI *fpi, Long *exp, ULong *bits)
|
||||||
#endif
|
#endif
|
||||||
{
|
{
|
||||||
int abe, abits, asub;
|
int abe, abits, asub;
|
||||||
|
@ -332,14 +328,35 @@ strtodg
|
||||||
int sudden_underflow;
|
int sudden_underflow;
|
||||||
CONST char *s, *s0, *s1;
|
CONST char *s, *s0, *s1;
|
||||||
double adj0, tol;
|
double adj0, tol;
|
||||||
U adj, rv;
|
|
||||||
Long L;
|
Long L;
|
||||||
ULong y, z;
|
U 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) {
|
||||||
|
@ -394,13 +411,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++;
|
||||||
|
@ -429,7 +450,7 @@ strtodg
|
||||||
nz = 0;
|
nz = 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}/*}*/
|
||||||
dig_done:
|
dig_done:
|
||||||
e = 0;
|
e = 0;
|
||||||
if (c == 'e' || c == 'E') {
|
if (c == 'e' || c == 'E') {
|
||||||
|
@ -527,13 +548,13 @@ 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) {
|
||||||
|
@ -541,9 +562,9 @@ strtodg
|
||||||
#ifdef VAX
|
#ifdef VAX
|
||||||
goto vax_ovfl_check;
|
goto vax_ovfl_check;
|
||||||
#else
|
#else
|
||||||
i = fivesbits[e] + mantbits(dval(rv)) <= P;
|
i = fivesbits[e] + mantbits(&rv) <= P;
|
||||||
/* rv = */ rounded_product(dval(rv), tens[e]);
|
/* rv = */ rounded_product(dval(&rv), tens[e]);
|
||||||
if (rvOK(dval(rv), fpi, exp, bits, i, rd, &irv))
|
if (rvOK(&rv, fpi, exp, bits, i, rd, &irv))
|
||||||
goto ret;
|
goto ret;
|
||||||
e1 -= e;
|
e1 -= e;
|
||||||
goto rv_notOK;
|
goto rv_notOK;
|
||||||
|
@ -556,32 +577,32 @@ strtodg
|
||||||
*/
|
*/
|
||||||
e2 = e - i;
|
e2 = e - i;
|
||||||
e1 -= i;
|
e1 -= i;
|
||||||
dval(rv) *= tens[i];
|
dval(&rv) *= tens[i];
|
||||||
#ifdef VAX
|
#ifdef VAX
|
||||||
/* VAX exponent range is so narrow we must
|
/* VAX exponent range is so narrow we must
|
||||||
* worry about overflow here...
|
* worry about overflow here...
|
||||||
*/
|
*/
|
||||||
vax_ovfl_check:
|
vax_ovfl_check:
|
||||||
dval(adj) = dval(rv);
|
dval(&adj) = dval(&rv);
|
||||||
word0(adj) -= P*Exp_msk1;
|
word0(&adj) -= P*Exp_msk1;
|
||||||
/* adj = */ rounded_product(dval(adj), tens[e2]);
|
/* adj = */ rounded_product(dval(&adj), tens[e2]);
|
||||||
if ((word0(adj) & Exp_mask)
|
if ((word0(&adj) & Exp_mask)
|
||||||
> Exp_msk1*(DBL_MAX_EXP+Bias-1-P))
|
> Exp_msk1*(DBL_MAX_EXP+Bias-1-P))
|
||||||
goto rv_notOK;
|
goto rv_notOK;
|
||||||
word0(adj) += P*Exp_msk1;
|
word0(&adj) += P*Exp_msk1;
|
||||||
dval(rv) = dval(adj);
|
dval(&rv) = dval(&adj);
|
||||||
#else
|
#else
|
||||||
/* rv = */ rounded_product(dval(rv), tens[e2]);
|
/* rv = */ rounded_product(dval(&rv), tens[e2]);
|
||||||
#endif
|
#endif
|
||||||
if (rvOK(dval(rv), fpi, exp, bits, 0, rd, &irv))
|
if (rvOK(&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;
|
||||||
}
|
}
|
||||||
|
@ -595,45 +616,45 @@ 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
|
#ifdef IBM
|
||||||
|
@ -644,7 +665,7 @@ strtodg
|
||||||
*/
|
*/
|
||||||
e2 <<= 2;
|
e2 <<= 2;
|
||||||
#endif
|
#endif
|
||||||
rvb = d2b(dval(rv), &rve, &rvbits); /* rv = rvb * 2^rve */
|
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);
|
||||||
|
@ -688,7 +709,7 @@ strtodg
|
||||||
|
|
||||||
/* 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);
|
||||||
|
@ -822,7 +843,7 @@ strtodg
|
||||||
}
|
}
|
||||||
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);
|
||||||
|
@ -839,7 +860,7 @@ strtodg
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
if ((dval(adj) = ratio(delta, bs)) <= 2.) {
|
if ((dval(&adj) = ratio(delta, bs)) <= 2.) {
|
||||||
adj1:
|
adj1:
|
||||||
inex = STRTOG_Inexlo;
|
inex = STRTOG_Inexlo;
|
||||||
if (dsign) {
|
if (dsign) {
|
||||||
|
@ -853,15 +874,15 @@ strtodg
|
||||||
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 = (Long)adj0;
|
L = (Long)adj0;
|
||||||
adj0 -= L;
|
adj0 -= L;
|
||||||
switch(rd) {
|
switch(rd) {
|
||||||
|
@ -880,12 +901,12 @@ strtodg
|
||||||
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(dval(&rv)); */
|
||||||
/* if (asub) rv -= adj; else rv += adj; */
|
/* if (asub) rv -= adj; else rv += adj; */
|
||||||
|
|
||||||
if (!denorm && rvbits < nbits) {
|
if (!denorm && rvbits < nbits) {
|
||||||
|
@ -893,7 +914,7 @@ strtodg
|
||||||
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)
|
||||||
|
@ -947,15 +968,15 @@ 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) {
|
else if (dval(&adj) > tol && adj0 < 1. - tol) {
|
||||||
irv |= inex;
|
irv |= inex;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -980,6 +1001,29 @@ 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;
|
||||||
|
@ -994,12 +1038,19 @@ strtodg
|
||||||
if (sudden_underflow) {
|
if (sudden_underflow) {
|
||||||
rvb->wds = 0;
|
rvb->wds = 0;
|
||||||
irv = STRTOG_Underflow | STRTOG_Inexlo;
|
irv = STRTOG_Underflow | STRTOG_Inexlo;
|
||||||
|
#ifndef NO_ERRNO
|
||||||
|
errno = ERANGE;
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
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;
|
||||||
|
#ifndef NO_ERRNO
|
||||||
|
errno = ERANGE;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (se)
|
if (se)
|
||||||
|
|
|
@ -44,7 +44,7 @@ strtod(s, sp) CONST char *s; char **sp;
|
||||||
strtod(CONST char *s, char **sp)
|
strtod(CONST char *s, char **sp)
|
||||||
#endif
|
#endif
|
||||||
{
|
{
|
||||||
static CONST 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];
|
||||||
Long exp;
|
Long exp;
|
||||||
int k;
|
int k;
|
||||||
|
|
|
@ -38,13 +38,18 @@ strtof(s, sp) CONST char *s; char **sp;
|
||||||
strtof(CONST char *s, char **sp)
|
strtof(CONST char *s, char **sp)
|
||||||
#endif
|
#endif
|
||||||
{
|
{
|
||||||
static CONST 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;
|
||||||
|
#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 +58,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:
|
||||||
|
|
|
@ -49,6 +49,9 @@ THIS SOFTWARE.
|
||||||
#define _3 0
|
#define _3 0
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
extern ULong NanDflt_Q_D2A[4];
|
||||||
|
|
||||||
|
|
||||||
int
|
int
|
||||||
#ifdef KR_headers
|
#ifdef KR_headers
|
||||||
strtopQ(s, sp, V) CONST char *s; char **sp; void *V;
|
strtopQ(s, sp, V) CONST char *s; char **sp; void *V;
|
||||||
|
@ -56,13 +59,18 @@ strtopQ(s, sp, V) CONST char *s; char **sp; void *V;
|
||||||
strtopQ(CONST char *s, char **sp, void *V)
|
strtopQ(CONST char *s, char **sp, void *V)
|
||||||
#endif
|
#endif
|
||||||
{
|
{
|
||||||
static CONST FPI fpi = { 113, 1-16383-113+1, 32766 - 16383 - 113 + 1, 1, SI };
|
static FPI fpi0 = { 113, 1-16383-113+1, 32766 - 16383 - 113 + 1, 1, SI };
|
||||||
ULong bits[4];
|
ULong bits[4];
|
||||||
Long exp;
|
Long exp;
|
||||||
int k;
|
int k;
|
||||||
ULong *L = (ULong*)V;
|
ULong *L = (ULong*)V;
|
||||||
|
#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:
|
||||||
|
@ -90,10 +98,10 @@ strtopQ(CONST char *s, char **sp, void *V)
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case STRTOG_NaN:
|
case STRTOG_NaN:
|
||||||
L[0] = ld_QNAN0;
|
L[_0] = NanDflt_Q_D2A[3];
|
||||||
L[1] = ld_QNAN1;
|
L[_1] = NanDflt_Q_D2A[2];
|
||||||
L[2] = ld_QNAN2;
|
L[_2] = NanDflt_Q_D2A[1];
|
||||||
L[3] = ld_QNAN3;
|
L[_3] = NanDflt_Q_D2A[0];
|
||||||
}
|
}
|
||||||
if (k & STRTOG_Neg)
|
if (k & STRTOG_Neg)
|
||||||
L[_0] |= 0x80000000L;
|
L[_0] |= 0x80000000L;
|
||||||
|
|
|
@ -38,12 +38,17 @@ strtopd(s, sp, d) char *s; char **sp; double *d;
|
||||||
strtopd(CONST char *s, char **sp, double *d)
|
strtopd(CONST char *s, char **sp, double *d)
|
||||||
#endif
|
#endif
|
||||||
{
|
{
|
||||||
static CONST FPI fpi0 = { 53, 1-1023-53+1, 2046-1023-53+1, 1, SI };
|
static FPI fpi0 = { 53, 1-1023-53+1, 2046-1023-53+1, 1, SI };
|
||||||
ULong bits[2];
|
ULong bits[2];
|
||||||
Long exp;
|
Long exp;
|
||||||
int k;
|
int k;
|
||||||
|
#ifdef Honor_FLT_ROUNDS
|
||||||
|
#include "gdtoa_fltrnds.h"
|
||||||
|
#else
|
||||||
|
#define fpi &fpi0
|
||||||
|
#endif
|
||||||
|
|
||||||
k = strtodg(s, sp, &fpi0, &exp, bits);
|
k = strtodg(s, sp, fpi, &exp, bits);
|
||||||
ULtod((ULong*)d, bits, exp, k);
|
ULtod((ULong*)d, bits, exp, k);
|
||||||
return k;
|
return k;
|
||||||
}
|
}
|
||||||
|
|
|
@ -39,9 +39,9 @@ strtopdd(CONST char *s, char **sp, double *dd)
|
||||||
#endif
|
#endif
|
||||||
{
|
{
|
||||||
#ifdef Sudden_Underflow
|
#ifdef Sudden_Underflow
|
||||||
static CONST FPI fpi = { 106, 1-1023, 2046-1023-106+1, 1, 1 };
|
static FPI fpi0 = { 106, 1-1023, 2046-1023-106+1, 1, 1 };
|
||||||
#else
|
#else
|
||||||
static CONST FPI fpi = { 106, 1-1023-53+1, 2046-1023-106+1, 1, 0 };
|
static FPI fpi0 = { 106, 1-1023-53+1, 2046-1023-106+1, 1, 0 };
|
||||||
#endif
|
#endif
|
||||||
ULong bits[4];
|
ULong bits[4];
|
||||||
Long exp;
|
Long exp;
|
||||||
|
@ -51,8 +51,13 @@ strtopdd(CONST char *s, char **sp, double *dd)
|
||||||
ULong L[4];
|
ULong L[4];
|
||||||
} U;
|
} U;
|
||||||
U *u;
|
U *u;
|
||||||
|
#ifdef Honor_FLT_ROUNDS
|
||||||
|
#include "gdtoa_fltrnds.h"
|
||||||
|
#else
|
||||||
|
#define fpi &fpi0
|
||||||
|
#endif
|
||||||
|
|
||||||
rv = strtodg(s, sp, &fpi, &exp, bits);
|
rv = strtodg(s, sp, fpi, &exp, bits);
|
||||||
u = (U*)dd;
|
u = (U*)dd;
|
||||||
switch(rv & STRTOG_Retmask) {
|
switch(rv & STRTOG_Retmask) {
|
||||||
case STRTOG_NoNumber:
|
case STRTOG_NoNumber:
|
||||||
|
@ -62,8 +67,8 @@ strtopdd(CONST char *s, char **sp, double *dd)
|
||||||
|
|
||||||
case STRTOG_Normal:
|
case STRTOG_Normal:
|
||||||
u->L[_1] = (bits[1] >> 21 | bits[2] << 11) & 0xffffffffL;
|
u->L[_1] = (bits[1] >> 21 | bits[2] << 11) & 0xffffffffL;
|
||||||
u->L[_0] = bits[2] >> 21 | bits[3] << 11 & 0xfffff
|
u->L[_0] = (bits[2] >> 21) | ((bits[3] << 11) & 0xfffff)
|
||||||
| exp + 0x3ff + 105 << 20;
|
| ((exp + 0x3ff + 105) << 20);
|
||||||
exp += 0x3ff + 52;
|
exp += 0x3ff + 52;
|
||||||
if (bits[1] &= 0x1fffff) {
|
if (bits[1] &= 0x1fffff) {
|
||||||
i = hi0bits(bits[1]) - 11;
|
i = hi0bits(bits[1]) - 11;
|
||||||
|
@ -74,7 +79,7 @@ strtopdd(CONST char *s, char **sp, double *dd)
|
||||||
else
|
else
|
||||||
exp -= i;
|
exp -= i;
|
||||||
if (i > 0) {
|
if (i > 0) {
|
||||||
bits[1] = bits[1] << i | bits[0] >> 32-i;
|
bits[1] = bits[1] << i | bits[0] >> (32-i);
|
||||||
bits[0] = bits[0] << i & 0xffffffffL;
|
bits[0] = bits[0] << i & 0xffffffffL;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -87,11 +92,11 @@ strtopdd(CONST char *s, char **sp, double *dd)
|
||||||
else
|
else
|
||||||
exp -= i;
|
exp -= i;
|
||||||
if (i < 32) {
|
if (i < 32) {
|
||||||
bits[1] = bits[0] >> 32 - i;
|
bits[1] = bits[0] >> (32 - i);
|
||||||
bits[0] = bits[0] << i & 0xffffffffL;
|
bits[0] = bits[0] << i & 0xffffffffL;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
bits[1] = bits[0] << i - 32;
|
bits[1] = bits[0] << (i - 32);
|
||||||
bits[0] = 0;
|
bits[0] = 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -100,7 +105,7 @@ strtopdd(CONST char *s, char **sp, double *dd)
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
u->L[2+_1] = bits[0];
|
u->L[2+_1] = bits[0];
|
||||||
u->L[2+_0] = bits[1] & 0xfffff | exp << 20;
|
u->L[2+_0] = (bits[1] & 0xfffff) | (exp << 20);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case STRTOG_Denormal:
|
case STRTOG_Denormal:
|
||||||
|
@ -119,10 +124,10 @@ strtopdd(CONST char *s, char **sp, double *dd)
|
||||||
nearly_normal:
|
nearly_normal:
|
||||||
i = hi0bits(bits[3]) - 11; /* i >= 12 */
|
i = hi0bits(bits[3]) - 11; /* i >= 12 */
|
||||||
j = 32 - i;
|
j = 32 - i;
|
||||||
u->L[_0] = (bits[3] << i | bits[2] >> j) & 0xfffff
|
u->L[_0] = ((bits[3] << i | bits[2] >> j) & 0xfffff)
|
||||||
| 65 - i << 20;
|
| ((65 - i) << 20);
|
||||||
u->L[_1] = (bits[2] << i | bits[1] >> j) & 0xffffffffL;
|
u->L[_1] = (bits[2] << i | bits[1] >> j) & 0xffffffffL;
|
||||||
u->L[2+_0] = bits[1] & (1L << j) - 1;
|
u->L[2+_0] = bits[1] & ((1L << j) - 1);
|
||||||
u->L[2+_1] = bits[0];
|
u->L[2+_1] = bits[0];
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
@ -131,34 +136,34 @@ strtopdd(CONST char *s, char **sp, double *dd)
|
||||||
if (i < 0) {
|
if (i < 0) {
|
||||||
j = -i;
|
j = -i;
|
||||||
i += 32;
|
i += 32;
|
||||||
u->L[_0] = bits[2] >> j & 0xfffff | (33 + j) << 20;
|
u->L[_0] = (bits[2] >> j & 0xfffff) | (33 + j) << 20;
|
||||||
u->L[_1] = (bits[2] << i | bits[1] >> j) & 0xffffffffL;
|
u->L[_1] = ((bits[2] << i) | (bits[1] >> j)) & 0xffffffffL;
|
||||||
u->L[2+_0] = bits[1] & (1L << j) - 1;
|
u->L[2+_0] = bits[1] & ((1L << j) - 1);
|
||||||
u->L[2+_1] = bits[0];
|
u->L[2+_1] = bits[0];
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
if (i == 0) {
|
if (i == 0) {
|
||||||
u->L[_0] = bits[2] & 0xfffff | 33 << 20;
|
u->L[_0] = (bits[2] & 0xfffff) | (33 << 20);
|
||||||
u->L[_1] = bits[1];
|
u->L[_1] = bits[1];
|
||||||
u->L[2+_0] = 0;
|
u->L[2+_0] = 0;
|
||||||
u->L[2+_1] = bits[0];
|
u->L[2+_1] = bits[0];
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
j = 32 - i;
|
j = 32 - i;
|
||||||
u->L[_0] = (bits[2] << i | bits[1] >> j) & 0xfffff
|
u->L[_0] = (((bits[2] << i) | (bits[1] >> j)) & 0xfffff)
|
||||||
| j + 1 << 20;
|
| ((j + 1) << 20);
|
||||||
u->L[_1] = (bits[1] << i | bits[0] >> j) & 0xffffffffL;
|
u->L[_1] = (bits[1] << i | bits[0] >> j) & 0xffffffffL;
|
||||||
u->L[2+_0] = 0;
|
u->L[2+_0] = 0;
|
||||||
u->L[2+_1] = bits[0] & (1L << j) - 1;
|
u->L[2+_1] = bits[0] & ((1L << j) - 1);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
hardly_normal:
|
hardly_normal:
|
||||||
j = 11 - hi0bits(bits[1]);
|
j = 11 - hi0bits(bits[1]);
|
||||||
i = 32 - j;
|
i = 32 - j;
|
||||||
u->L[_0] = bits[1] >> j & 0xfffff | j + 1 << 20;
|
u->L[_0] = (bits[1] >> j & 0xfffff) | ((j + 1) << 20);
|
||||||
u->L[_1] = (bits[1] << i | bits[0] >> j) & 0xffffffffL;
|
u->L[_1] = (bits[1] << i | bits[0] >> j) & 0xffffffffL;
|
||||||
u->L[2+_0] = 0;
|
u->L[2+_0] = 0;
|
||||||
u->L[2+_1] = bits[0] & (1L << j) - 1;
|
u->L[2+_1] = bits[0] & ((1L << j) - 1);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case STRTOG_Infinite:
|
case STRTOG_Infinite:
|
||||||
|
|
|
@ -38,12 +38,17 @@ strtopf(s, sp, f) CONST char *s; char **sp; float *f;
|
||||||
strtopf(CONST char *s, char **sp, float *f)
|
strtopf(CONST char *s, char **sp, float *f)
|
||||||
#endif
|
#endif
|
||||||
{
|
{
|
||||||
static CONST 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], *L;
|
ULong bits[1], *L;
|
||||||
Long exp;
|
Long exp;
|
||||||
int k;
|
int k;
|
||||||
|
#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);
|
||||||
L = (ULong*)f;
|
L = (ULong*)f;
|
||||||
switch(k & STRTOG_Retmask) {
|
switch(k & STRTOG_Retmask) {
|
||||||
case STRTOG_NoNumber:
|
case STRTOG_NoNumber:
|
||||||
|
@ -53,7 +58,7 @@ strtopf(CONST char *s, char **sp, float *f)
|
||||||
|
|
||||||
case STRTOG_Normal:
|
case STRTOG_Normal:
|
||||||
case STRTOG_NaNbits:
|
case STRTOG_NaNbits:
|
||||||
L[0] = bits[0] & 0x7fffff | exp + 0x7f + 23 << 23;
|
L[0] = (bits[0] & 0x7fffff) | ((exp + 0x7f + 23) << 23);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case STRTOG_Denormal:
|
case STRTOG_Denormal:
|
||||||
|
|
|
@ -31,6 +31,8 @@ THIS SOFTWARE.
|
||||||
|
|
||||||
#include "gdtoaimp.h"
|
#include "gdtoaimp.h"
|
||||||
|
|
||||||
|
extern UShort NanDflt_ldus_D2A[5];
|
||||||
|
|
||||||
#undef _0
|
#undef _0
|
||||||
#undef _1
|
#undef _1
|
||||||
|
|
||||||
|
@ -58,13 +60,18 @@ strtopx(s, sp, V) CONST char *s; char **sp; void *V;
|
||||||
strtopx(CONST char *s, char **sp, void *V)
|
strtopx(CONST char *s, char **sp, void *V)
|
||||||
#endif
|
#endif
|
||||||
{
|
{
|
||||||
static CONST 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 = (UShort*)V;
|
||||||
|
#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:
|
||||||
|
@ -87,15 +94,16 @@ strtopx(CONST char *s, char **sp, void *V)
|
||||||
|
|
||||||
case STRTOG_Infinite:
|
case STRTOG_Infinite:
|
||||||
L[_0] = 0x7fff;
|
L[_0] = 0x7fff;
|
||||||
L[_1] = L[_2] = L[_3] = L[_4] = 0;
|
L[_1] = 0x8000;
|
||||||
|
L[_2] = L[_3] = L[_4] = 0;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case STRTOG_NaN:
|
case STRTOG_NaN:
|
||||||
L[0] = ldus_QNAN0;
|
L[_4] = NanDflt_ldus_D2A[0];
|
||||||
L[1] = ldus_QNAN1;
|
L[_3] = NanDflt_ldus_D2A[1];
|
||||||
L[2] = ldus_QNAN2;
|
L[_2] = NanDflt_ldus_D2A[2];
|
||||||
L[3] = ldus_QNAN3;
|
L[_1] = NanDflt_ldus_D2A[3];
|
||||||
L[4] = ldus_QNAN4;
|
L[_0] = NanDflt_ldus_D2A[4];
|
||||||
}
|
}
|
||||||
if (k & STRTOG_Neg)
|
if (k & STRTOG_Neg)
|
||||||
L[_0] |= 0x8000;
|
L[_0] |= 0x8000;
|
||||||
|
|
|
@ -31,6 +31,8 @@ THIS SOFTWARE.
|
||||||
|
|
||||||
#include "gdtoaimp.h"
|
#include "gdtoaimp.h"
|
||||||
|
|
||||||
|
extern ULong NanDflt_xL_D2A[3];
|
||||||
|
|
||||||
#undef _0
|
#undef _0
|
||||||
#undef _1
|
#undef _1
|
||||||
|
|
||||||
|
@ -54,13 +56,18 @@ strtopxL(s, sp, V) CONST char *s; char **sp; void *V;
|
||||||
strtopxL(CONST char *s, char **sp, void *V)
|
strtopxL(CONST char *s, char **sp, void *V)
|
||||||
#endif
|
#endif
|
||||||
{
|
{
|
||||||
static CONST 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;
|
||||||
ULong *L = (ULong*)V;
|
ULong *L = (ULong*)V;
|
||||||
|
#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:
|
||||||
|
@ -77,13 +84,14 @@ strtopxL(CONST char *s, char **sp, void *V)
|
||||||
|
|
||||||
case STRTOG_Infinite:
|
case STRTOG_Infinite:
|
||||||
L[_0] = 0x7fff << 16;
|
L[_0] = 0x7fff << 16;
|
||||||
L[_1] = L[_2] = 0;
|
L[_1] = 0x80000000;
|
||||||
|
L[_2] = 0;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case STRTOG_NaN:
|
case STRTOG_NaN:
|
||||||
L[0] = ld_QNAN0;
|
L[_0] = NanDflt_xL_D2A[2];
|
||||||
L[1] = ld_QNAN1;
|
L[_1] = NanDflt_xL_D2A[1];
|
||||||
L[2] = ld_QNAN2;
|
L[_2] = NanDflt_xL_D2A[0];
|
||||||
}
|
}
|
||||||
if (k & STRTOG_Neg)
|
if (k & STRTOG_Neg)
|
||||||
L[_0] |= 0x80000000L;
|
L[_0] |= 0x80000000L;
|
||||||
|
|
|
@ -49,6 +49,8 @@ THIS SOFTWARE.
|
||||||
#define _3 0
|
#define _3 0
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
extern ULong NanDflt_Q_D2A[4];
|
||||||
|
|
||||||
void
|
void
|
||||||
#ifdef KR_headers
|
#ifdef KR_headers
|
||||||
ULtoQ(L, bits, exp, k) ULong *L; ULong *bits; Long exp; int k;
|
ULtoQ(L, bits, exp, k) ULong *L; ULong *bits; Long exp; int k;
|
||||||
|
@ -83,10 +85,10 @@ ULtoQ(ULong *L, ULong *bits, Long exp, int k)
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case STRTOG_NaN:
|
case STRTOG_NaN:
|
||||||
L[0] = ld_QNAN0;
|
L[_0] = NanDflt_Q_D2A[3];
|
||||||
L[1] = ld_QNAN1;
|
L[_1] = NanDflt_Q_D2A[2];
|
||||||
L[2] = ld_QNAN2;
|
L[_2] = NanDflt_Q_D2A[1];
|
||||||
L[3] = ld_QNAN3;
|
L[_3] = NanDflt_Q_D2A[0];
|
||||||
}
|
}
|
||||||
if (k & STRTOG_Neg)
|
if (k & STRTOG_Neg)
|
||||||
L[_0] |= 0x80000000L;
|
L[_0] |= 0x80000000L;
|
||||||
|
@ -99,9 +101,8 @@ strtorQ(s, sp, rounding, L) CONST char *s; char **sp; int rounding; void *L;
|
||||||
strtorQ(CONST char *s, char **sp, int rounding, void *L)
|
strtorQ(CONST char *s, char **sp, int rounding, void *L)
|
||||||
#endif
|
#endif
|
||||||
{
|
{
|
||||||
static CONST FPI fpi0 = { 113, 1-16383-113+1, 32766-16383-113+1, 1, SI };
|
static FPI fpi0 = { 113, 1-16383-113+1, 32766-16383-113+1, 1, SI };
|
||||||
CONST FPI *fpi;
|
FPI *fpi, fpi1;
|
||||||
FPI fpi1;
|
|
||||||
ULong bits[4];
|
ULong bits[4];
|
||||||
Long exp;
|
Long exp;
|
||||||
int k;
|
int k;
|
||||||
|
|
|
@ -31,6 +31,8 @@ THIS SOFTWARE.
|
||||||
|
|
||||||
#include "gdtoaimp.h"
|
#include "gdtoaimp.h"
|
||||||
|
|
||||||
|
extern ULong NanDflt_d_D2A[2];
|
||||||
|
|
||||||
void
|
void
|
||||||
#ifdef KR_headers
|
#ifdef KR_headers
|
||||||
ULtod(L, bits, exp, k) ULong *L; ULong *bits; Long exp; int k;
|
ULtod(L, bits, exp, k) ULong *L; ULong *bits; Long exp; int k;
|
||||||
|
@ -61,8 +63,8 @@ ULtod(ULong *L, ULong *bits, Long exp, int k)
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case STRTOG_NaN:
|
case STRTOG_NaN:
|
||||||
L[0] = d_QNAN0;
|
L[_0] = NanDflt_d_D2A[1];
|
||||||
L[1] = d_QNAN1;
|
L[_1] = NanDflt_d_D2A[0];
|
||||||
}
|
}
|
||||||
if (k & STRTOG_Neg)
|
if (k & STRTOG_Neg)
|
||||||
L[_0] |= 0x80000000L;
|
L[_0] |= 0x80000000L;
|
||||||
|
@ -75,9 +77,8 @@ strtord(s, sp, rounding, d) CONST char *s; char **sp; int rounding; double *d;
|
||||||
strtord(CONST char *s, char **sp, int rounding, double *d)
|
strtord(CONST char *s, char **sp, int rounding, double *d)
|
||||||
#endif
|
#endif
|
||||||
{
|
{
|
||||||
static CONST FPI fpi0 = { 53, 1-1023-53+1, 2046-1023-53+1, 1, SI };
|
static FPI fpi0 = { 53, 1-1023-53+1, 2046-1023-53+1, 1, SI };
|
||||||
CONST FPI *fpi;
|
FPI *fpi, fpi1;
|
||||||
FPI fpi1;
|
|
||||||
ULong bits[2];
|
ULong bits[2];
|
||||||
Long exp;
|
Long exp;
|
||||||
int k;
|
int k;
|
||||||
|
|
|
@ -31,6 +31,8 @@ THIS SOFTWARE.
|
||||||
|
|
||||||
#include "gdtoaimp.h"
|
#include "gdtoaimp.h"
|
||||||
|
|
||||||
|
extern ULong NanDflt_d_D2A[2];
|
||||||
|
|
||||||
void
|
void
|
||||||
#ifdef KR_headers
|
#ifdef KR_headers
|
||||||
ULtodd(L, bits, exp, k) ULong *L; ULong *bits; Long exp; int k;
|
ULtodd(L, bits, exp, k) ULong *L; ULong *bits; Long exp; int k;
|
||||||
|
@ -48,8 +50,8 @@ ULtodd(ULong *L, ULong *bits, Long exp, int k)
|
||||||
|
|
||||||
case STRTOG_Normal:
|
case STRTOG_Normal:
|
||||||
L[_1] = (bits[1] >> 21 | bits[2] << 11) & (ULong)0xffffffffL;
|
L[_1] = (bits[1] >> 21 | bits[2] << 11) & (ULong)0xffffffffL;
|
||||||
L[_0] = bits[2] >> 21 | bits[3] << 11 & 0xfffff
|
L[_0] = (bits[2] >> 21) | (bits[3] << 11 & 0xfffff)
|
||||||
| exp + 0x3ff + 105 << 20;
|
| ((exp + 0x3ff + 105) << 20);
|
||||||
exp += 0x3ff + 52;
|
exp += 0x3ff + 52;
|
||||||
if (bits[1] &= 0x1fffff) {
|
if (bits[1] &= 0x1fffff) {
|
||||||
i = hi0bits(bits[1]) - 11;
|
i = hi0bits(bits[1]) - 11;
|
||||||
|
@ -60,7 +62,7 @@ ULtodd(ULong *L, ULong *bits, Long exp, int k)
|
||||||
else
|
else
|
||||||
exp -= i;
|
exp -= i;
|
||||||
if (i > 0) {
|
if (i > 0) {
|
||||||
bits[1] = bits[1] << i | bits[0] >> 32-i;
|
bits[1] = bits[1] << i | bits[0] >> (32-i);
|
||||||
bits[0] = bits[0] << i & (ULong)0xffffffffL;
|
bits[0] = bits[0] << i & (ULong)0xffffffffL;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -73,11 +75,11 @@ ULtodd(ULong *L, ULong *bits, Long exp, int k)
|
||||||
else
|
else
|
||||||
exp -= i;
|
exp -= i;
|
||||||
if (i < 32) {
|
if (i < 32) {
|
||||||
bits[1] = bits[0] >> 32 - i;
|
bits[1] = bits[0] >> (32 - i);
|
||||||
bits[0] = bits[0] << i & (ULong)0xffffffffL;
|
bits[0] = bits[0] << i & (ULong)0xffffffffL;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
bits[1] = bits[0] << i - 32;
|
bits[1] = bits[0] << (i - 32);
|
||||||
bits[0] = 0;
|
bits[0] = 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -86,7 +88,7 @@ ULtodd(ULong *L, ULong *bits, Long exp, int k)
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
L[2+_1] = bits[0];
|
L[2+_1] = bits[0];
|
||||||
L[2+_0] = bits[1] & 0xfffff | exp << 20;
|
L[2+_0] = (bits[1] & 0xfffff) | (exp << 20);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case STRTOG_Denormal:
|
case STRTOG_Denormal:
|
||||||
|
@ -105,10 +107,10 @@ ULtodd(ULong *L, ULong *bits, Long exp, int k)
|
||||||
nearly_normal:
|
nearly_normal:
|
||||||
i = hi0bits(bits[3]) - 11; /* i >= 12 */
|
i = hi0bits(bits[3]) - 11; /* i >= 12 */
|
||||||
j = 32 - i;
|
j = 32 - i;
|
||||||
L[_0] = (bits[3] << i | bits[2] >> j) & 0xfffff
|
L[_0] = ((bits[3] << i | bits[2] >> j) & 0xfffff)
|
||||||
| 65 - i << 20;
|
| ((65 - i) << 20);
|
||||||
L[_1] = (bits[2] << i | bits[1] >> j) & 0xffffffffL;
|
L[_1] = (bits[2] << i | bits[1] >> j) & 0xffffffffL;
|
||||||
L[2+_0] = bits[1] & ((ULong)1L << j) - 1;
|
L[2+_0] = bits[1] & (((ULong)1L << j) - 1);
|
||||||
L[2+_1] = bits[0];
|
L[2+_1] = bits[0];
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
@ -117,34 +119,34 @@ ULtodd(ULong *L, ULong *bits, Long exp, int k)
|
||||||
if (i < 0) {
|
if (i < 0) {
|
||||||
j = -i;
|
j = -i;
|
||||||
i += 32;
|
i += 32;
|
||||||
L[_0] = bits[2] >> j & 0xfffff | (33 + j) << 20;
|
L[_0] = (bits[2] >> j & 0xfffff) | ((33 + j) << 20);
|
||||||
L[_1] = (bits[2] << i | bits[1] >> j) & 0xffffffffL;
|
L[_1] = (bits[2] << i | bits[1] >> j) & 0xffffffffL;
|
||||||
L[2+_0] = bits[1] & ((ULong)1L << j) - 1;
|
L[2+_0] = bits[1] & (((ULong)1L << j) - 1);
|
||||||
L[2+_1] = bits[0];
|
L[2+_1] = bits[0];
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
if (i == 0) {
|
if (i == 0) {
|
||||||
L[_0] = bits[2] & 0xfffff | 33 << 20;
|
L[_0] = (bits[2] & 0xfffff) | (33 << 20);
|
||||||
L[_1] = bits[1];
|
L[_1] = bits[1];
|
||||||
L[2+_0] = 0;
|
L[2+_0] = 0;
|
||||||
L[2+_1] = bits[0];
|
L[2+_1] = bits[0];
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
j = 32 - i;
|
j = 32 - i;
|
||||||
L[_0] = (bits[2] << i | bits[1] >> j) & 0xfffff
|
L[_0] = (((bits[2] << i) | (bits[1] >> j)) & 0xfffff)
|
||||||
| j + 1 << 20;
|
| ((j + 1) << 20);
|
||||||
L[_1] = (bits[1] << i | bits[0] >> j) & 0xffffffffL;
|
L[_1] = (bits[1] << i | bits[0] >> j) & 0xffffffffL;
|
||||||
L[2+_0] = 0;
|
L[2+_0] = 0;
|
||||||
L[2+_1] = bits[0] & (1L << j) - 1;
|
L[2+_1] = bits[0] & ((1L << j) - 1);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
hardly_normal:
|
hardly_normal:
|
||||||
j = 11 - hi0bits(bits[1]);
|
j = 11 - hi0bits(bits[1]);
|
||||||
i = 32 - j;
|
i = 32 - j;
|
||||||
L[_0] = bits[1] >> j & 0xfffff | j + 1 << 20;
|
L[_0] = (bits[1] >> j & 0xfffff) | ((j + 1) << 20);
|
||||||
L[_1] = (bits[1] << i | bits[0] >> j) & 0xffffffffL;
|
L[_1] = (bits[1] << i | bits[0] >> j) & 0xffffffffL;
|
||||||
L[2+_0] = 0;
|
L[2+_0] = 0;
|
||||||
L[2+_1] = bits[0] & ((ULong)1L << j) - 1;
|
L[2+_1] = bits[0] & (((ULong)1L << j) - 1);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case STRTOG_Infinite:
|
case STRTOG_Infinite:
|
||||||
|
@ -153,16 +155,17 @@ ULtodd(ULong *L, ULong *bits, Long exp, int k)
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case STRTOG_NaN:
|
case STRTOG_NaN:
|
||||||
L[0] = L[2] = d_QNAN0;
|
L[_0] = L[_0+2] = NanDflt_d_D2A[1];
|
||||||
L[1] = L[3] = d_QNAN1;
|
L[_1] = L[_1+2] = NanDflt_d_D2A[0];
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case STRTOG_NaNbits:
|
case STRTOG_NaNbits:
|
||||||
L[_1] = (bits[1] >> 21 | bits[2] << 11) & (ULong)0xffffffffL;
|
L[_1] = (bits[1] >> 20 | bits[2] << 12) & (ULong)0xffffffffL;
|
||||||
L[_0] = bits[2] >> 21 | bits[3] << 11
|
L[_0] = bits[2] >> 20 | bits[3] << 12;
|
||||||
| (ULong)0x7ff00000L;
|
L[_0] |= (L[_1] | L[_0]) ? (ULong)0x7ff00000L : (ULong)0x7ff80000L;
|
||||||
L[2+_1] = bits[0];
|
L[2+_1] = bits[0] & (ULong)0xffffffffL;
|
||||||
L[2+_0] = bits[1] | (ULong)0x7ff00000L;
|
L[2+_0] = bits[1] & 0xfffffL;
|
||||||
|
L[2+_0] |= (L[2+_1] | L[2+_0]) ? (ULong)0x7ff00000L : (ULong)0x7ff80000L;
|
||||||
}
|
}
|
||||||
if (k & STRTOG_Neg) {
|
if (k & STRTOG_Neg) {
|
||||||
L[_0] |= 0x80000000L;
|
L[_0] |= 0x80000000L;
|
||||||
|
@ -178,12 +181,11 @@ strtordd(CONST char *s, char **sp, int rounding, double *dd)
|
||||||
#endif
|
#endif
|
||||||
{
|
{
|
||||||
#ifdef Sudden_Underflow
|
#ifdef Sudden_Underflow
|
||||||
static CONST FPI fpi0 = { 106, 1-1023, 2046-1023-106+1, 1, 1 };
|
static FPI fpi0 = { 106, 1-1023, 2046-1023-106+1, 1, 1 };
|
||||||
#else
|
#else
|
||||||
static CONST FPI fpi0 = { 106, 1-1023-53+1, 2046-1023-106+1, 1, 0 };
|
static FPI fpi0 = { 106, 1-1023-53+1, 2046-1023-106+1, 1, 0 };
|
||||||
#endif
|
#endif
|
||||||
CONST FPI *fpi;
|
FPI *fpi, fpi1;
|
||||||
FPI fpi1;
|
|
||||||
ULong bits[4];
|
ULong bits[4];
|
||||||
Long exp;
|
Long exp;
|
||||||
int k;
|
int k;
|
||||||
|
|
|
@ -31,6 +31,8 @@ THIS SOFTWARE.
|
||||||
|
|
||||||
#include "gdtoaimp.h"
|
#include "gdtoaimp.h"
|
||||||
|
|
||||||
|
extern ULong NanDflt_f_D2A[1];
|
||||||
|
|
||||||
void
|
void
|
||||||
#ifdef KR_headers
|
#ifdef KR_headers
|
||||||
ULtof(L, bits, exp, k) ULong *L; ULong *bits; Long exp; int k;
|
ULtof(L, bits, exp, k) ULong *L; ULong *bits; Long exp; int k;
|
||||||
|
@ -46,7 +48,7 @@ ULtof(ULong *L, ULong *bits, Long exp, int k)
|
||||||
|
|
||||||
case STRTOG_Normal:
|
case STRTOG_Normal:
|
||||||
case STRTOG_NaNbits:
|
case STRTOG_NaNbits:
|
||||||
L[0] = bits[0] & 0x7fffff | exp + 0x7f + 23 << 23;
|
L[0] = (bits[0] & 0x7fffff) | ((exp + 0x7f + 23) << 23);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case STRTOG_Denormal:
|
case STRTOG_Denormal:
|
||||||
|
@ -58,7 +60,7 @@ ULtof(ULong *L, ULong *bits, Long exp, int k)
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case STRTOG_NaN:
|
case STRTOG_NaN:
|
||||||
L[0] = f_QNAN;
|
L[0] = NanDflt_f_D2A[0];
|
||||||
}
|
}
|
||||||
if (k & STRTOG_Neg)
|
if (k & STRTOG_Neg)
|
||||||
L[0] |= 0x80000000L;
|
L[0] |= 0x80000000L;
|
||||||
|
@ -71,9 +73,8 @@ strtorf(s, sp, rounding, f) CONST char *s; char **sp; int rounding; float *f;
|
||||||
strtorf(CONST char *s, char **sp, int rounding, float *f)
|
strtorf(CONST char *s, char **sp, int rounding, float *f)
|
||||||
#endif
|
#endif
|
||||||
{
|
{
|
||||||
static CONST FPI fpi0 = { 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 };
|
||||||
CONST FPI *fpi;
|
FPI *fpi, fpi1;
|
||||||
FPI fpi1;
|
|
||||||
ULong bits[1];
|
ULong bits[1];
|
||||||
Long exp;
|
Long exp;
|
||||||
int k;
|
int k;
|
||||||
|
|
|
@ -51,6 +51,8 @@ THIS SOFTWARE.
|
||||||
#define _4 0
|
#define _4 0
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
extern UShort NanDflt_ldus_D2A[5];
|
||||||
|
|
||||||
void
|
void
|
||||||
#ifdef KR_headers
|
#ifdef KR_headers
|
||||||
ULtox(L, bits, exp, k) UShort *L; ULong *bits; Long exp; int k;
|
ULtox(L, bits, exp, k) UShort *L; ULong *bits; Long exp; int k;
|
||||||
|
@ -80,15 +82,16 @@ ULtox(UShort *L, ULong *bits, Long exp, int k)
|
||||||
|
|
||||||
case STRTOG_Infinite:
|
case STRTOG_Infinite:
|
||||||
L[_0] = 0x7fff;
|
L[_0] = 0x7fff;
|
||||||
L[_1] = L[_2] = L[_3] = L[_4] = 0;
|
L[_1] = 0x8000;
|
||||||
|
L[_2] = L[_3] = L[_4] = 0;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case STRTOG_NaN:
|
case STRTOG_NaN:
|
||||||
L[0] = ldus_QNAN0;
|
L[_4] = NanDflt_ldus_D2A[0];
|
||||||
L[1] = ldus_QNAN1;
|
L[_3] = NanDflt_ldus_D2A[1];
|
||||||
L[2] = ldus_QNAN2;
|
L[_2] = NanDflt_ldus_D2A[2];
|
||||||
L[3] = ldus_QNAN3;
|
L[_1] = NanDflt_ldus_D2A[3];
|
||||||
L[4] = ldus_QNAN4;
|
L[_0] = NanDflt_ldus_D2A[4];
|
||||||
}
|
}
|
||||||
if (k & STRTOG_Neg)
|
if (k & STRTOG_Neg)
|
||||||
L[_0] |= 0x8000;
|
L[_0] |= 0x8000;
|
||||||
|
@ -101,9 +104,8 @@ strtorx(s, sp, rounding, L) CONST char *s; char **sp; int rounding; void *L;
|
||||||
strtorx(CONST char *s, char **sp, int rounding, void *L)
|
strtorx(CONST char *s, char **sp, int rounding, void *L)
|
||||||
#endif
|
#endif
|
||||||
{
|
{
|
||||||
static CONST FPI fpi0 = { 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 };
|
||||||
CONST FPI *fpi;
|
FPI *fpi, fpi1;
|
||||||
FPI fpi1;
|
|
||||||
ULong bits[2];
|
ULong bits[2];
|
||||||
Long exp;
|
Long exp;
|
||||||
int k;
|
int k;
|
||||||
|
|
|
@ -47,6 +47,8 @@ THIS SOFTWARE.
|
||||||
#define _2 0
|
#define _2 0
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
extern ULong NanDflt_xL_D2A[3];
|
||||||
|
|
||||||
void
|
void
|
||||||
#ifdef KR_headers
|
#ifdef KR_headers
|
||||||
ULtoxL(L, bits, exp, k) ULong *L; ULong *bits; Long exp; int k;
|
ULtoxL(L, bits, exp, k) ULong *L; ULong *bits; Long exp; int k;
|
||||||
|
@ -69,14 +71,15 @@ ULtoxL(ULong *L, ULong *bits, Long exp, int k)
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case STRTOG_Infinite:
|
case STRTOG_Infinite:
|
||||||
L[_0] = 0x7fff << 16;
|
L[_0] = 0x7fff0000;
|
||||||
L[_1] = L[_2] = 0;
|
L[_1] = 0x80000000;
|
||||||
|
L[_2] = 0;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case STRTOG_NaN:
|
case STRTOG_NaN:
|
||||||
L[0] = ld_QNAN0;
|
L[_0] = NanDflt_xL_D2A[2];
|
||||||
L[1] = ld_QNAN1;
|
L[_1] = NanDflt_xL_D2A[1];
|
||||||
L[2] = ld_QNAN2;
|
L[_2] = NanDflt_xL_D2A[0];
|
||||||
}
|
}
|
||||||
if (k & STRTOG_Neg)
|
if (k & STRTOG_Neg)
|
||||||
L[_0] |= 0x80000000L;
|
L[_0] |= 0x80000000L;
|
||||||
|
@ -89,9 +92,8 @@ strtorxL(s, sp, rounding, L) CONST char *s; char **sp; int rounding; void *L;
|
||||||
strtorxL(CONST char *s, char **sp, int rounding, void *L)
|
strtorxL(CONST char *s, char **sp, int rounding, void *L)
|
||||||
#endif
|
#endif
|
||||||
{
|
{
|
||||||
static CONST FPI fpi0 = { 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 };
|
||||||
CONST FPI *fpi;
|
FPI *fpi, fpi1;
|
||||||
FPI fpi1;
|
|
||||||
ULong bits[2];
|
ULong bits[2];
|
||||||
Long exp;
|
Long exp;
|
||||||
int k;
|
int k;
|
||||||
|
|
21
gdtoa/ulp.c
21
gdtoa/ulp.c
|
@ -34,15 +34,14 @@ THIS SOFTWARE.
|
||||||
double
|
double
|
||||||
ulp
|
ulp
|
||||||
#ifdef KR_headers
|
#ifdef KR_headers
|
||||||
(x) double x;
|
(x) U *x;
|
||||||
#else
|
#else
|
||||||
(double _x)
|
(U *x)
|
||||||
#endif
|
#endif
|
||||||
{
|
{
|
||||||
Long L;
|
Long L;
|
||||||
U x, a;
|
U a;
|
||||||
|
|
||||||
dval(x) = _x;
|
|
||||||
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) {
|
||||||
|
@ -50,22 +49,22 @@ ulp
|
||||||
#ifdef IBM
|
#ifdef IBM
|
||||||
L |= Exp_msk1 >> 4;
|
L |= Exp_msk1 >> 4;
|
||||||
#endif
|
#endif
|
||||||
word0(a) = L;
|
word0(&a) = L;
|
||||||
word1(a) = 0;
|
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
|
#endif
|
||||||
return dval(a);
|
return dval(&a);
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue