Import gdtoa sources dated 2008-12-05. Notable changes include a fix
for a regression in strtod() and support for multibyte decimal points.
This commit is contained in:
parent
e12da90037
commit
9ea4d2a874
Notes:
svn2git
2020-12-20 02:59:44 +00:00
svn path=/vendor/gdtoa/dist/; revision=187806 svn path=/vendor/gdtoa/20081205/; revision=187807; tag=vendor/gdtoa/20081205
13
README
13
README
@ -56,7 +56,9 @@ two letters:
|
||||
whose sum is the desired value
|
||||
|
||||
For decimal -> binary conversions, there are three families of
|
||||
helper routines: one for round-nearest:
|
||||
helper routines: one for round-nearest (or the current rounding
|
||||
mode on IEEE-arithmetic systems that provide the C99 fegetround()
|
||||
function, if compiled with -DHonor_FLT_ROUNDS):
|
||||
|
||||
strtof
|
||||
strtod
|
||||
@ -191,6 +193,9 @@ in the buffer, if the buffer was long enough, or 0. Other forms of
|
||||
conversion are easily done with the help of gdtoa(), such as %e or %f
|
||||
style and conversions with direction of rounding specified (so that, if
|
||||
desired, the decimal value is either >= or <= the binary value).
|
||||
On IEEE-arithmetic systems that provide the C99 fegetround() function,
|
||||
if compiled with -DHonor_FLT_ROUNDS, these routines honor the current
|
||||
rounding mode.
|
||||
|
||||
For an example of more general conversions based on dtoa(), see
|
||||
netlib's "printf.c from ampl/solvers".
|
||||
@ -342,5 +347,11 @@ standard says it should -- when Honor_FLT_ROUNDS is #defined, the
|
||||
current rounding mode is obtained from fegetround() rather than from
|
||||
FLT_ROUNDS, unless Trust_FLT_ROUNDS is also #defined.
|
||||
|
||||
Compile with -DUSE_LOCALE to use the current locale; otherwise
|
||||
decimal points are assumed to be '.'. With -DUSE_LOCALE, unless
|
||||
you also compile with -DNO_LOCALE_CACHE, the details about the
|
||||
current "decimal point" character string are cached and assumed not
|
||||
to change during the program's execution.
|
||||
|
||||
Please send comments to David M. Gay (dmg at acm dot org, with " at "
|
||||
changed at "@" and " dot " changed to ".").
|
||||
|
15
g_Qfmt.c
15
g_Qfmt.c
@ -51,15 +51,20 @@ THIS SOFTWARE.
|
||||
|
||||
char*
|
||||
#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
|
||||
g_Qfmt(char *buf, void *V, int ndig, unsigned bufsize)
|
||||
g_Qfmt(char *buf, void *V, int ndig, size_t bufsize)
|
||||
#endif
|
||||
{
|
||||
static 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 };
|
||||
char *b, *s, *se;
|
||||
ULong bits[4], *L, sign;
|
||||
int decpt, ex, i, mode;
|
||||
#ifdef Honor_FLT_ROUNDS
|
||||
#include "gdtoa_fltrnds.h"
|
||||
#else
|
||||
#define fpi &fpi0
|
||||
#endif
|
||||
|
||||
if (ndig < 0)
|
||||
ndig = 0;
|
||||
@ -109,6 +114,6 @@ g_Qfmt(char *buf, void *V, int ndig, unsigned bufsize)
|
||||
return 0;
|
||||
mode = 0;
|
||||
}
|
||||
s = gdtoa(&fpi, ex, bits, &i, mode, ndig, &decpt, &se);
|
||||
return g__fmt(buf, s, se, decpt, sign);
|
||||
s = gdtoa(fpi, ex, bits, &i, mode, ndig, &decpt, &se);
|
||||
return g__fmt(buf, s, se, decpt, sign, bufsize);
|
||||
}
|
||||
|
70
g__fmt.c
70
g__fmt.c
@ -37,24 +37,51 @@ THIS SOFTWARE.
|
||||
|
||||
char *
|
||||
#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
|
||||
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
|
||||
{
|
||||
int i, j, k;
|
||||
char *s0 = s;
|
||||
char *be, *s0;
|
||||
size_t len;
|
||||
#ifdef USE_LOCALE
|
||||
char decimalpoint = *localeconv()->decimal_point;
|
||||
#ifdef NO_LOCALE_CACHE
|
||||
char *decimalpoint = localeconv()->decimal_point;
|
||||
size_t dlen = strlen(decimalpoint);
|
||||
#else
|
||||
#define decimalpoint '.'
|
||||
char *decimalpoint;
|
||||
static char *decimalpoint_cache;
|
||||
static size_t dlen;
|
||||
if (!(s0 = decimalpoint_cache)) {
|
||||
s0 = localeconv()->decimal_point;
|
||||
dlen = strlen(s0);
|
||||
if ((decimalpoint_cache = (char*)malloc(strlen(s0) + 1))) {
|
||||
strcpy(decimalpoint_cache, s0);
|
||||
s0 = decimalpoint_cache;
|
||||
}
|
||||
}
|
||||
decimalpoint = s0;
|
||||
#endif
|
||||
#else
|
||||
#define dlen 0
|
||||
#endif
|
||||
s0 = s;
|
||||
len = (se-s) + dlen + 6; /* 6 = sign + e+dd + trailing null */
|
||||
if (blen < len)
|
||||
goto ret0;
|
||||
be = b + blen - 1;
|
||||
if (sign)
|
||||
*b++ = '-';
|
||||
if (decpt <= -4 || decpt > se - s + 5) {
|
||||
*b++ = *s++;
|
||||
if (*s) {
|
||||
*b++ = decimalpoint;
|
||||
#ifdef USE_LOCALE
|
||||
while((*b = *decimalpoint++))
|
||||
++b;
|
||||
#else
|
||||
*b++ = '.';
|
||||
#endif
|
||||
while((*b = *s++) !=0)
|
||||
b++;
|
||||
}
|
||||
@ -69,6 +96,8 @@ g__fmt(char *b, char *s, char *se, int decpt, ULong sign)
|
||||
for(j = 2, k = 10; 10*k <= decpt; j++, k *= 10){}
|
||||
for(;;) {
|
||||
i = decpt / k;
|
||||
if (b >= be)
|
||||
goto ret0;
|
||||
*b++ = i + '0';
|
||||
if (--j <= 0)
|
||||
break;
|
||||
@ -78,22 +107,41 @@ g__fmt(char *b, char *s, char *se, int decpt, ULong sign)
|
||||
*b = 0;
|
||||
}
|
||||
else if (decpt <= 0) {
|
||||
*b++ = decimalpoint;
|
||||
#ifdef USE_LOCALE
|
||||
while((*b = *decimalpoint++))
|
||||
++b;
|
||||
#else
|
||||
*b++ = '.';
|
||||
#endif
|
||||
if (be < b - decpt + (se - s))
|
||||
goto ret0;
|
||||
for(; decpt < 0; decpt++)
|
||||
*b++ = '0';
|
||||
while((*b = *s++) !=0)
|
||||
while((*b = *s++) != 0)
|
||||
b++;
|
||||
}
|
||||
else {
|
||||
while((*b = *s++) !=0) {
|
||||
while((*b = *s++) != 0) {
|
||||
b++;
|
||||
if (--decpt == 0 && *s)
|
||||
*b++ = decimalpoint;
|
||||
if (--decpt == 0 && *s) {
|
||||
#ifdef USE_LOCALE
|
||||
while(*b = *decimalpoint++)
|
||||
++b;
|
||||
#else
|
||||
*b++ = '.';
|
||||
#endif
|
||||
}
|
||||
}
|
||||
if (b + decpt > be) {
|
||||
ret0:
|
||||
b = 0;
|
||||
goto ret;
|
||||
}
|
||||
for(; decpt > 0; decpt--)
|
||||
*b++ = '0';
|
||||
*b = 0;
|
||||
}
|
||||
ret:
|
||||
freedtoa(s0);
|
||||
return b;
|
||||
}
|
||||
|
23
g_ddfmt.c
23
g_ddfmt.c
@ -33,9 +33,9 @@ THIS SOFTWARE.
|
||||
|
||||
char *
|
||||
#ifdef KR_headers
|
||||
g_ddfmt(buf, dd, ndig, bufsize) char *buf; double *dd; int ndig; unsigned bufsize;
|
||||
g_ddfmt(buf, dd, ndig, bufsize) char *buf; double *dd; int ndig; size_t bufsize;
|
||||
#else
|
||||
g_ddfmt(char *buf, double *dd, int ndig, unsigned bufsize)
|
||||
g_ddfmt(char *buf, double *dd, int ndig, size_t bufsize)
|
||||
#endif
|
||||
{
|
||||
FPI fpi;
|
||||
@ -44,6 +44,21 @@ g_ddfmt(char *buf, double *dd, int ndig, unsigned bufsize)
|
||||
int bx, by, decpt, ex, ey, i, j, mode;
|
||||
Bigint *x, *y, *z;
|
||||
double 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 < ndig + 8)
|
||||
return 0;
|
||||
@ -144,11 +159,11 @@ g_ddfmt(char *buf, double *dd, int ndig, unsigned bufsize)
|
||||
}
|
||||
fpi.emin = 1-1023-53+1;
|
||||
fpi.emax = 2046-1023-106+1;
|
||||
fpi.rounding = FPI_Round_near;
|
||||
fpi.rounding = Rounding;
|
||||
fpi.sudden_underflow = 0;
|
||||
i = STRTOG_Normal;
|
||||
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);
|
||||
return b;
|
||||
}
|
||||
|
22
g_dfmt.c
22
g_dfmt.c
@ -33,15 +33,20 @@ THIS SOFTWARE.
|
||||
|
||||
char*
|
||||
#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
|
||||
g_dfmt(char *buf, double *d, int ndig, unsigned bufsize)
|
||||
g_dfmt(char *buf, double *d, int ndig, size_t bufsize)
|
||||
#endif
|
||||
{
|
||||
static FPI fpi = { 53, 1-1023-53+1, 2046-1023-53+1, 1, 0 };
|
||||
static FPI fpi0 = { 53, 1-1023-53+1, 2046-1023-53+1, 1, 0 };
|
||||
char *b, *s, *se;
|
||||
ULong bits[2], *L, sign;
|
||||
int decpt, ex, i, mode;
|
||||
#ifdef Honor_FLT_ROUNDS
|
||||
#include "gdtoa_fltrnds.h"
|
||||
#else
|
||||
#define fpi &fpi0
|
||||
#endif
|
||||
|
||||
if (ndig < 0)
|
||||
ndig = 0;
|
||||
@ -52,6 +57,8 @@ g_dfmt(char *buf, double *d, int ndig, unsigned bufsize)
|
||||
sign = L[_0] & 0x80000000L;
|
||||
if ((L[_0] & 0x7ff00000) == 0x7ff00000) {
|
||||
/* Infinity or NaN */
|
||||
if (bufsize < 10)
|
||||
return 0;
|
||||
if (L[_0] & 0xfffff || L[_1]) {
|
||||
return strcp(buf, "NaN");
|
||||
}
|
||||
@ -78,12 +85,9 @@ g_dfmt(char *buf, double *d, int ndig, unsigned bufsize)
|
||||
ex = 1;
|
||||
ex -= 0x3ff + 52;
|
||||
mode = 2;
|
||||
if (ndig <= 0) {
|
||||
if (bufsize < 25)
|
||||
return 0;
|
||||
if (ndig <= 0)
|
||||
mode = 0;
|
||||
}
|
||||
i = STRTOG_Normal;
|
||||
s = gdtoa(&fpi, ex, bits, &i, mode, ndig, &decpt, &se);
|
||||
return g__fmt(buf, s, se, decpt, sign);
|
||||
s = gdtoa(fpi, ex, bits, &i, mode, ndig, &decpt, &se);
|
||||
return g__fmt(buf, s, se, decpt, sign, bufsize);
|
||||
}
|
||||
|
15
g_ffmt.c
15
g_ffmt.c
@ -33,15 +33,20 @@ THIS SOFTWARE.
|
||||
|
||||
char*
|
||||
#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
|
||||
g_ffmt(char *buf, float *f, int ndig, unsigned bufsize)
|
||||
g_ffmt(char *buf, float *f, int ndig, size_t bufsize)
|
||||
#endif
|
||||
{
|
||||
static FPI fpi = { 24, 1-127-24+1, 254-127-24+1, 1, 0 };
|
||||
static FPI fpi0 = { 24, 1-127-24+1, 254-127-24+1, 1, 0 };
|
||||
char *b, *s, *se;
|
||||
ULong bits[1], *L, sign;
|
||||
int decpt, ex, i, mode;
|
||||
#ifdef Honor_FLT_ROUNDS
|
||||
#include "gdtoa_fltrnds.h"
|
||||
#else
|
||||
#define fpi &fpi0
|
||||
#endif
|
||||
|
||||
if (ndig < 0)
|
||||
ndig = 0;
|
||||
@ -83,6 +88,6 @@ g_ffmt(char *buf, float *f, int ndig, unsigned bufsize)
|
||||
mode = 0;
|
||||
}
|
||||
i = STRTOG_Normal;
|
||||
s = gdtoa(&fpi, ex, bits, &i, mode, ndig, &decpt, &se);
|
||||
return g__fmt(buf, s, se, decpt, sign);
|
||||
s = gdtoa(fpi, ex, bits, &i, mode, ndig, &decpt, &se);
|
||||
return g__fmt(buf, s, se, decpt, sign, bufsize);
|
||||
}
|
||||
|
15
g_xLfmt.c
15
g_xLfmt.c
@ -49,15 +49,20 @@ THIS SOFTWARE.
|
||||
|
||||
char*
|
||||
#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
|
||||
g_xLfmt(char *buf, void *V, int ndig, unsigned bufsize)
|
||||
g_xLfmt(char *buf, void *V, int ndig, size_t bufsize)
|
||||
#endif
|
||||
{
|
||||
static FPI fpi = { 64, 1-16383-64+1, 32766 - 16383 - 64 + 1, 1, 0 };
|
||||
static FPI fpi0 = { 64, 1-16383-64+1, 32766 - 16383 - 64 + 1, 1, 0 };
|
||||
char *b, *s, *se;
|
||||
ULong bits[2], *L, sign;
|
||||
int decpt, ex, i, mode;
|
||||
#ifdef Honor_FLT_ROUNDS
|
||||
#include "gdtoa_fltrnds.h"
|
||||
#else
|
||||
#define fpi &fpi0
|
||||
#endif
|
||||
|
||||
if (ndig < 0)
|
||||
ndig = 0;
|
||||
@ -103,6 +108,6 @@ g_xLfmt(char *buf, void *V, int ndig, unsigned bufsize)
|
||||
return 0;
|
||||
mode = 0;
|
||||
}
|
||||
s = gdtoa(&fpi, ex, bits, &i, mode, ndig, &decpt, &se);
|
||||
return g__fmt(buf, s, se, decpt, sign);
|
||||
s = gdtoa(fpi, ex, bits, &i, mode, ndig, &decpt, &se);
|
||||
return g__fmt(buf, s, se, decpt, sign, bufsize);
|
||||
}
|
||||
|
15
g_xfmt.c
15
g_xfmt.c
@ -53,16 +53,21 @@ THIS SOFTWARE.
|
||||
|
||||
char*
|
||||
#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
|
||||
g_xfmt(char *buf, void *V, int ndig, unsigned bufsize)
|
||||
g_xfmt(char *buf, void *V, int ndig, size_t bufsize)
|
||||
#endif
|
||||
{
|
||||
static FPI fpi = { 64, 1-16383-64+1, 32766 - 16383 - 64 + 1, 1, 0 };
|
||||
static FPI fpi0 = { 64, 1-16383-64+1, 32766 - 16383 - 64 + 1, 1, 0 };
|
||||
char *b, *s, *se;
|
||||
ULong bits[2], sign;
|
||||
UShort *L;
|
||||
int decpt, ex, i, mode;
|
||||
#ifdef Honor_FLT_ROUNDS
|
||||
#include "gdtoa_fltrnds.h"
|
||||
#else
|
||||
#define fpi &fpi0
|
||||
#endif
|
||||
|
||||
if (ndig < 0)
|
||||
ndig = 0;
|
||||
@ -109,6 +114,6 @@ g_xfmt(char *buf, void *V, int ndig, unsigned bufsize)
|
||||
return 0;
|
||||
mode = 0;
|
||||
}
|
||||
s = gdtoa(&fpi, ex, bits, &i, mode, ndig, &decpt, &se);
|
||||
return g__fmt(buf, s, se, decpt, sign);
|
||||
s = gdtoa(fpi, ex, bits, &i, mode, ndig, &decpt, &se);
|
||||
return g__fmt(buf, s, se, decpt, sign, bufsize);
|
||||
}
|
||||
|
12
gdtoa.c
12
gdtoa.c
@ -417,11 +417,9 @@ gdtoa
|
||||
if (dval(d) > ds + dval(eps))
|
||||
goto bump_up;
|
||||
else if (dval(d) < ds - dval(eps)) {
|
||||
while(*--s == '0'){}
|
||||
s++;
|
||||
if (dval(d))
|
||||
inex = STRTOG_Inexlo;
|
||||
goto ret1;
|
||||
goto clear_trailing0;
|
||||
}
|
||||
break;
|
||||
}
|
||||
@ -479,8 +477,12 @@ gdtoa
|
||||
}
|
||||
++*s++;
|
||||
}
|
||||
else
|
||||
else {
|
||||
inex = STRTOG_Inexlo;
|
||||
clear_trailing0:
|
||||
while(*--s == '0'){}
|
||||
++s;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
@ -738,7 +740,7 @@ gdtoa
|
||||
if (b->wds > 1 || b->x[0])
|
||||
inex = STRTOG_Inexlo;
|
||||
while(*--s == '0'){}
|
||||
s++;
|
||||
++s;
|
||||
}
|
||||
ret:
|
||||
Bfree(S);
|
||||
|
13
gdtoa.h
13
gdtoa.h
@ -33,6 +33,7 @@ THIS SOFTWARE.
|
||||
#define GDTOA_H_INCLUDED
|
||||
|
||||
#include "arith.h"
|
||||
#include <stddef.h> /* for size_t */
|
||||
|
||||
#ifndef Long
|
||||
#define Long long
|
||||
@ -111,12 +112,12 @@ extern float strtof ANSI((CONST char *, char **));
|
||||
extern double strtod ANSI((CONST char *, char **));
|
||||
extern int strtodg ANSI((CONST char*, char**, FPI*, Long*, ULong*));
|
||||
|
||||
extern char* g_ddfmt ANSI((char*, double*, int, unsigned));
|
||||
extern char* g_dfmt ANSI((char*, double*, int, unsigned));
|
||||
extern char* g_ffmt ANSI((char*, float*, int, unsigned));
|
||||
extern char* g_Qfmt ANSI((char*, void*, int, unsigned));
|
||||
extern char* g_xfmt ANSI((char*, void*, int, unsigned));
|
||||
extern char* g_xLfmt ANSI((char*, void*, int, unsigned));
|
||||
extern char* g_ddfmt ANSI((char*, double*, int, size_t));
|
||||
extern char* g_dfmt ANSI((char*, double*, int, size_t));
|
||||
extern char* g_ffmt ANSI((char*, float*, int, size_t));
|
||||
extern char* g_Qfmt ANSI((char*, void*, int, size_t));
|
||||
extern char* g_xfmt ANSI((char*, void*, int, size_t));
|
||||
extern char* g_xLfmt ANSI((char*, void*, int, size_t));
|
||||
|
||||
extern int strtoId ANSI((CONST char*, char**, double*, double*));
|
||||
extern int strtoIdd ANSI((CONST char*, char**, double*, double*));
|
||||
|
18
gdtoa_fltrnds.h
Normal file
18
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;
|
||||
}
|
17
gdtoaimp.h
17
gdtoaimp.h
@ -126,8 +126,10 @@ THIS SOFTWARE.
|
||||
* conversions of IEEE doubles in single-threaded executions with
|
||||
* 8-byte pointers, PRIVATE_MEM >= 7400 appears to suffice; with
|
||||
* 4-byte pointers, PRIVATE_MEM >= 7112 appears adequate.
|
||||
* #define INFNAN_CHECK on IEEE systems to cause strtod to check for
|
||||
* Infinity and NaN (case insensitively).
|
||||
* #define NO_INFNAN_CHECK if you do not wish to have INFNAN_CHECK
|
||||
* #defined automatically on IEEE systems. On such systems,
|
||||
* when INFNAN_CHECK is #defined, strtod checks
|
||||
* for Infinity and NaN (case insensitively).
|
||||
* When INFNAN_CHECK is #defined and No_Hex_NaN is not #defined,
|
||||
* strtodg also accepts (case insensitively) strings of the form
|
||||
* NaN(x), where x is a string of hexadecimal digits (optionally
|
||||
@ -172,6 +174,9 @@ THIS SOFTWARE.
|
||||
#define GDTOAIMP_H_INCLUDED
|
||||
#include "gdtoa.h"
|
||||
#include "gd_qnan.h"
|
||||
#ifdef Honor_FLT_ROUNDS
|
||||
#include <fenv.h>
|
||||
#endif
|
||||
|
||||
#ifdef DEBUG
|
||||
#include "stdio.h"
|
||||
@ -545,7 +550,7 @@ extern void memcpy_D2A ANSI((void*, const void*, size_t));
|
||||
extern Bigint *diff ANSI((Bigint*, Bigint*));
|
||||
extern char *dtoa ANSI((double d, int mode, int ndigits,
|
||||
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**, FPI*, Long*, Bigint**, int));
|
||||
extern void hexdig_init_D2A(Void);
|
||||
extern int hexnan ANSI((CONST char**, FPI*, ULong*));
|
||||
@ -563,7 +568,7 @@ extern void memcpy_D2A ANSI((void*, const void*, size_t));
|
||||
extern double ratio ANSI((Bigint*, Bigint*));
|
||||
extern void rshift ANSI((Bigint*, int));
|
||||
extern char *rv_alloc ANSI((int));
|
||||
extern Bigint *s2b ANSI((CONST char*, int, int, ULong));
|
||||
extern Bigint *s2b ANSI((CONST char*, int, int, ULong, int));
|
||||
extern Bigint *set_ones ANSI((Bigint*, int));
|
||||
extern char *strcp ANSI((char*, const char*));
|
||||
extern int strtoIg ANSI((CONST char*, char**, FPI*, Long*, Bigint**, int*));
|
||||
@ -585,6 +590,10 @@ extern void memcpy_D2A ANSI((void*, const void*, size_t));
|
||||
* (On HP Series 700/800 machines, -DNAN_WORD0=0x7ff40000 works.)
|
||||
*/
|
||||
#ifdef IEEE_Arith
|
||||
#ifndef NO_INFNAN_CHECK
|
||||
#undef INFNAN_CHECK
|
||||
#define INFNAN_CHECK
|
||||
#endif
|
||||
#ifdef IEEE_MC68k
|
||||
#define _0 0
|
||||
#define _1 1
|
||||
|
63
gethex.c
63
gethex.c
@ -49,9 +49,21 @@ gethex( CONST char **sp, FPI *fpi, Long *exp, Bigint **bp, int sign)
|
||||
ULong L, lostbits, *x;
|
||||
Long e, e1;
|
||||
#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
|
||||
#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
|
||||
|
||||
if (!hexdig['0'])
|
||||
@ -66,11 +78,21 @@ gethex( CONST char **sp, FPI *fpi, Long *exp, Bigint **bp, int sign)
|
||||
decpt = 0;
|
||||
zret = 0;
|
||||
e = 0;
|
||||
if (!hexdig[*s]) {
|
||||
if (hexdig[*s])
|
||||
havedig++;
|
||||
else {
|
||||
zret = 1;
|
||||
if (*s != decimalpoint)
|
||||
#ifdef USE_LOCALE
|
||||
for(i = 0; decimalpoint[i]; ++i) {
|
||||
if (s[i] != decimalpoint[i])
|
||||
goto pcheck;
|
||||
}
|
||||
decpt = s += i;
|
||||
#else
|
||||
if (*s != '.')
|
||||
goto pcheck;
|
||||
decpt = ++s;
|
||||
#endif
|
||||
if (!hexdig[*s])
|
||||
goto pcheck;
|
||||
while(*s == '0')
|
||||
@ -82,11 +104,20 @@ gethex( CONST char **sp, FPI *fpi, Long *exp, Bigint **bp, int sign)
|
||||
}
|
||||
while(hexdig[*s])
|
||||
s++;
|
||||
if (*s == decimalpoint && !decpt) {
|
||||
#ifdef USE_LOCALE
|
||||
if (*s == *decimalpoint && !decpt) {
|
||||
for(i = 1; decimalpoint[i]; ++i) {
|
||||
if (s[i] != decimalpoint[i])
|
||||
goto pcheck;
|
||||
}
|
||||
decpt = s += i;
|
||||
#else
|
||||
if (*s == '.' && !decpt) {
|
||||
decpt = ++s;
|
||||
#endif
|
||||
while(hexdig[*s])
|
||||
s++;
|
||||
}
|
||||
}/*}*/
|
||||
if (decpt)
|
||||
e = -(((Long)(s-decpt)) << 2);
|
||||
pcheck:
|
||||
@ -118,7 +149,7 @@ gethex( CONST char **sp, FPI *fpi, Long *exp, Bigint **bp, int sign)
|
||||
}
|
||||
*sp = (char*)s;
|
||||
if (!havedig)
|
||||
*sp = s0 - 1;
|
||||
*sp = (char*)s0 - 1;
|
||||
if (zret)
|
||||
return STRTOG_Zero;
|
||||
if (big) {
|
||||
@ -168,16 +199,26 @@ gethex( CONST char **sp, FPI *fpi, Long *exp, Bigint **bp, int sign)
|
||||
return STRTOG_Normal | STRTOG_Inexlo;
|
||||
}
|
||||
n = s1 - s0 - 1;
|
||||
for(k = 0; n > 7; n >>= 1)
|
||||
for(k = 0; n > (1 << kshift-2) - 1; n >>= 1)
|
||||
k++;
|
||||
b = Balloc(k);
|
||||
x = b->x;
|
||||
n = 0;
|
||||
L = 0;
|
||||
#ifdef USE_LOCALE
|
||||
for(i = 0; decimalpoint[i+1]; ++i);
|
||||
#endif
|
||||
while(s1 > s0) {
|
||||
if (*--s1 == decimalpoint)
|
||||
#ifdef USE_LOCALE
|
||||
if (*--s1 == decimalpoint[i]) {
|
||||
s1 -= i;
|
||||
continue;
|
||||
if (n == 32) {
|
||||
}
|
||||
#else
|
||||
if (*--s1 == '.')
|
||||
continue;
|
||||
#endif
|
||||
if (n == ULbits) {
|
||||
*x++ = L;
|
||||
L = 0;
|
||||
n = 0;
|
||||
@ -187,7 +228,7 @@ gethex( CONST char **sp, FPI *fpi, Long *exp, Bigint **bp, int sign)
|
||||
}
|
||||
*x++ = L;
|
||||
b->wds = n = x - b->x;
|
||||
n = 32*n - hi0bits(L);
|
||||
n = ULbits*n - hi0bits(L);
|
||||
nbits = fpi->nbits;
|
||||
lostbits = 0;
|
||||
x = b->x;
|
||||
|
8
makefile
8
makefile
@ -25,7 +25,7 @@
|
||||
|
||||
.SUFFIXES: .c .o
|
||||
CC = cc
|
||||
CFLAGS = -g -DINFNAN_CHECK
|
||||
CFLAGS = -g
|
||||
|
||||
.c.o:
|
||||
$(CC) -c $(CFLAGS) $*.c
|
||||
@ -55,9 +55,9 @@ gdtoa.a: dmisc.c dtoa.c g_Qfmt.c g__fmt.c g_ddfmt.c g_dfmt.c g_ffmt.c\
|
||||
# If your system lacks ranlib, you do not need it.
|
||||
|
||||
xs0 = README arithchk.c dmisc.c dtoa.c g_Qfmt.c g__fmt.c g_ddfmt.c g_dfmt.c\
|
||||
g_ffmt.c g_xLfmt.c g_xfmt.c gdtoa.c gdtoa.h gdtoaimp.h gethex.c\
|
||||
gmisc.c hd_init.c hexnan.c makefile misc.c qnan.c smisc.c strtoIQ.c\
|
||||
strtoId.c strtoIdd.c strtoIf.c strtoIg.c strtoIx.c strtoIxL.c\
|
||||
g_ffmt.c g_xLfmt.c g_xfmt.c gdtoa.c gdtoa.h gdtoa_fltrnds.h gdtoaimp.h\
|
||||
gethex.c gmisc.c hd_init.c hexnan.c makefile misc.c qnan.c smisc.c\
|
||||
strtoIQ.c strtoId.c strtoIdd.c strtoIf.c strtoIg.c strtoIx.c strtoIxL.c\
|
||||
strtod.c strtodI.c strtodg.c strtodnrp.c strtof.c strtopQ.c strtopd.c\
|
||||
strtopdd.c strtopf.c strtopx.c strtopxL.c strtorQ.c strtord.c strtordd.c\
|
||||
strtorf.c strtorx.c strtorxL.c sum.c ulp.c
|
||||
|
8
smisc.c
8
smisc.c
@ -34,9 +34,9 @@ THIS SOFTWARE.
|
||||
Bigint *
|
||||
s2b
|
||||
#ifdef KR_headers
|
||||
(s, nd0, nd, y9) CONST char *s; int nd0, nd; ULong y9;
|
||||
(s, nd0, nd, y9, dplen) CONST char *s; int dplen, nd0, nd; ULong y9;
|
||||
#else
|
||||
(CONST char *s, int nd0, int nd, ULong y9)
|
||||
(CONST char *s, int nd0, int nd, ULong y9, int dplen)
|
||||
#endif
|
||||
{
|
||||
Bigint *b;
|
||||
@ -60,10 +60,10 @@ s2b
|
||||
s += 9;
|
||||
do b = multadd(b, 10, *s++ - '0');
|
||||
while(++i < nd0);
|
||||
s++;
|
||||
s += dplen;
|
||||
}
|
||||
else
|
||||
s += 10;
|
||||
s += dplen + 9;
|
||||
for(; i < nd; i++)
|
||||
b = multadd(b, 10, *s++ - '0');
|
||||
return b;
|
||||
|
48
strtod.c
48
strtod.c
@ -78,6 +78,28 @@ strtod
|
||||
#ifdef SET_INEXACT
|
||||
int inexact, oldinexact;
|
||||
#endif
|
||||
#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}}*/
|
||||
|
||||
#ifdef Honor_FLT_ROUNDS /*{*/
|
||||
int Rounding;
|
||||
#ifdef Trust_FLT_ROUNDS /*{{ only define this if FLT_ROUNDS really works! */
|
||||
@ -116,7 +138,7 @@ strtod
|
||||
}
|
||||
break2:
|
||||
if (*s == '0') {
|
||||
#ifndef NO_HEX_FP /*{{*/
|
||||
#ifndef NO_HEX_FP /*{*/
|
||||
{
|
||||
static FPI fpi = { 53, 1-1023-53+1, 2046-1023-53+1, 1, SI };
|
||||
Long exp;
|
||||
@ -155,7 +177,7 @@ strtod
|
||||
goto ret;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
#endif /*}*/
|
||||
nz0 = 1;
|
||||
while(*++s == '0') ;
|
||||
if (!*s)
|
||||
@ -170,13 +192,17 @@ strtod
|
||||
z = 10*z + c - '0';
|
||||
nd0 = nd;
|
||||
#ifdef USE_LOCALE
|
||||
if (c == *localeconv()->decimal_point)
|
||||
if (c == *decimalpoint) {
|
||||
for(i = 1; decimalpoint[i]; ++i)
|
||||
if (s[i] != decimalpoint[i])
|
||||
goto dig_done;
|
||||
s += i;
|
||||
c = *s;
|
||||
#else
|
||||
if (c == '.')
|
||||
#endif
|
||||
{
|
||||
decpt = 1;
|
||||
if (c == '.') {
|
||||
c = *++s;
|
||||
#endif
|
||||
decpt = 1;
|
||||
if (!nd) {
|
||||
for(; c == '0'; c = *++s)
|
||||
nz++;
|
||||
@ -205,7 +231,7 @@ strtod
|
||||
nz = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
}/*}*/
|
||||
dig_done:
|
||||
e = 0;
|
||||
if (c == 'e' || c == 'E') {
|
||||
@ -525,7 +551,7 @@ strtod
|
||||
|
||||
/* Put digits into bd: true value = bd * 10^e */
|
||||
|
||||
bd0 = s2b(s0, nd0, nd, y);
|
||||
bd0 = s2b(s0, nd0, nd, y, dplen);
|
||||
|
||||
for(;;) {
|
||||
bd = Balloc(bd0->k);
|
||||
@ -972,7 +998,11 @@ strtod
|
||||
dval(rv) *= dval(rv0);
|
||||
#ifndef NO_ERRNO
|
||||
/* try to avoid the bug of testing an 8087 register value */
|
||||
#ifdef IEEE_Arith
|
||||
if (!(word0(rv) & Exp_mask))
|
||||
#else
|
||||
if (word0(rv) == 0 && word1(rv) == 0)
|
||||
#endif
|
||||
errno = ERANGE;
|
||||
#endif
|
||||
}
|
||||
|
41
strtodg.c
41
strtodg.c
@ -331,6 +331,27 @@ strtodg
|
||||
Long L;
|
||||
ULong *b, *be, y, z;
|
||||
Bigint *ab, *bb, *bb1, *bd, *bd0, *bs, *delta, *rvb, *rvb0;
|
||||
#ifdef USE_LOCALE /*{{*/
|
||||
#ifdef NO_LOCALE_CACHE
|
||||
char *decimalpoint = localeconv()->decimal_point;
|
||||
int dplen = strlen(decimalpoint);
|
||||
#else
|
||||
char *decimalpoint;
|
||||
static char *decimalpoint_cache;
|
||||
static int dplen;
|
||||
if (!(s0 = decimalpoint_cache)) {
|
||||
s0 = localeconv()->decimal_point;
|
||||
if ((decimalpoint_cache = (char*)malloc(strlen(s0) + 1))) {
|
||||
strcpy(decimalpoint_cache, s0);
|
||||
s0 = decimalpoint_cache;
|
||||
}
|
||||
dplen = strlen(s0);
|
||||
}
|
||||
decimalpoint = (char*)s0;
|
||||
#endif /*NO_LOCALE_CACHE*/
|
||||
#else /*USE_LOCALE}{*/
|
||||
#define dplen 1
|
||||
#endif /*USE_LOCALE}}*/
|
||||
|
||||
irv = STRTOG_Zero;
|
||||
denorm = sign = nz0 = nz = 0;
|
||||
@ -389,13 +410,17 @@ strtodg
|
||||
z = 10*z + c - '0';
|
||||
nd0 = nd;
|
||||
#ifdef USE_LOCALE
|
||||
if (c == *localeconv()->decimal_point)
|
||||
if (c == *decimalpoint) {
|
||||
for(i = 1; decimalpoint[i]; ++i)
|
||||
if (s[i] != decimalpoint[i])
|
||||
goto dig_done;
|
||||
s += i;
|
||||
c = *s;
|
||||
#else
|
||||
if (c == '.')
|
||||
#endif
|
||||
{
|
||||
decpt = 1;
|
||||
if (c == '.') {
|
||||
c = *++s;
|
||||
#endif
|
||||
decpt = 1;
|
||||
if (!nd) {
|
||||
for(; c == '0'; c = *++s)
|
||||
nz++;
|
||||
@ -424,7 +449,7 @@ strtodg
|
||||
nz = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
}/*}*/
|
||||
dig_done:
|
||||
e = 0;
|
||||
if (c == 'e' || c == 'E') {
|
||||
@ -683,7 +708,7 @@ strtodg
|
||||
|
||||
/* Put digits into bd: true value = bd * 10^e */
|
||||
|
||||
bd0 = s2b(s0, nd0, nd, y);
|
||||
bd0 = s2b(s0, nd0, nd, y, dplen);
|
||||
|
||||
for(;;) {
|
||||
bd = Balloc(bd0->k);
|
||||
@ -992,7 +1017,7 @@ strtodg
|
||||
irv = STRTOG_Normal | STRTOG_Inexlo;
|
||||
*exp = fpi->emax;
|
||||
b = bits;
|
||||
be = b + (fpi->nbits >> 5) + 1;
|
||||
be = b + ((fpi->nbits + 31) >> 5);
|
||||
while(b < be)
|
||||
*b++ = -1;
|
||||
if ((j = fpi->nbits & 0x1f))
|
||||
|
9
strtof.c
9
strtof.c
@ -38,13 +38,18 @@ strtof(s, sp) CONST char *s; char **sp;
|
||||
strtof(CONST char *s, char **sp)
|
||||
#endif
|
||||
{
|
||||
static FPI fpi = { 24, 1-127-24+1, 254-127-24+1, 1, SI };
|
||||
static FPI fpi0 = { 24, 1-127-24+1, 254-127-24+1, 1, SI };
|
||||
ULong bits[1];
|
||||
Long exp;
|
||||
int k;
|
||||
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) {
|
||||
case STRTOG_NoNumber:
|
||||
case STRTOG_Zero:
|
||||
|
@ -56,13 +56,18 @@ strtopQ(s, sp, V) CONST char *s; char **sp; void *V;
|
||||
strtopQ(CONST char *s, char **sp, void *V)
|
||||
#endif
|
||||
{
|
||||
static 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];
|
||||
Long exp;
|
||||
int k;
|
||||
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) {
|
||||
case STRTOG_NoNumber:
|
||||
case STRTOG_Zero:
|
||||
|
@ -42,8 +42,13 @@ strtopd(CONST char *s, char **sp, double *d)
|
||||
ULong bits[2];
|
||||
Long exp;
|
||||
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);
|
||||
return k;
|
||||
}
|
||||
|
11
strtopdd.c
11
strtopdd.c
@ -39,9 +39,9 @@ strtopdd(CONST char *s, char **sp, double *dd)
|
||||
#endif
|
||||
{
|
||||
#ifdef Sudden_Underflow
|
||||
static FPI fpi = { 106, 1-1023, 2046-1023-106+1, 1, 1 };
|
||||
static FPI fpi0 = { 106, 1-1023, 2046-1023-106+1, 1, 1 };
|
||||
#else
|
||||
static 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
|
||||
ULong bits[4];
|
||||
Long exp;
|
||||
@ -51,8 +51,13 @@ strtopdd(CONST char *s, char **sp, double *dd)
|
||||
ULong L[4];
|
||||
} 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;
|
||||
switch(rv & STRTOG_Retmask) {
|
||||
case STRTOG_NoNumber:
|
||||
|
@ -38,12 +38,17 @@ strtopf(s, sp, f) CONST char *s; char **sp; float *f;
|
||||
strtopf(CONST char *s, char **sp, float *f)
|
||||
#endif
|
||||
{
|
||||
static FPI fpi = { 24, 1-127-24+1, 254-127-24+1, 1, SI };
|
||||
static FPI fpi0 = { 24, 1-127-24+1, 254-127-24+1, 1, SI };
|
||||
ULong bits[1], *L;
|
||||
Long exp;
|
||||
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;
|
||||
switch(k & STRTOG_Retmask) {
|
||||
case STRTOG_NoNumber:
|
||||
|
@ -58,13 +58,18 @@ strtopx(s, sp, V) CONST char *s; char **sp; void *V;
|
||||
strtopx(CONST char *s, char **sp, void *V)
|
||||
#endif
|
||||
{
|
||||
static FPI fpi = { 64, 1-16383-64+1, 32766 - 16383 - 64 + 1, 1, SI };
|
||||
static FPI fpi0 = { 64, 1-16383-64+1, 32766 - 16383 - 64 + 1, 1, SI };
|
||||
ULong bits[2];
|
||||
Long exp;
|
||||
int k;
|
||||
UShort *L = (UShort*)V;
|
||||
#ifdef Honor_FLT_ROUNDS
|
||||
#include "gdtoa_fltrnds.h"
|
||||
#else
|
||||
#define fpi &fpi0
|
||||
#endif
|
||||
|
||||
k = strtodg(s, sp, &fpi, &exp, bits);
|
||||
k = strtodg(s, sp, fpi, &exp, bits);
|
||||
switch(k & STRTOG_Retmask) {
|
||||
case STRTOG_NoNumber:
|
||||
case STRTOG_Zero:
|
||||
|
@ -54,13 +54,18 @@ strtopxL(s, sp, V) CONST char *s; char **sp; void *V;
|
||||
strtopxL(CONST char *s, char **sp, void *V)
|
||||
#endif
|
||||
{
|
||||
static FPI fpi = { 64, 1-16383-64+1, 32766 - 16383 - 64 + 1, 1, SI };
|
||||
static FPI fpi0 = { 64, 1-16383-64+1, 32766 - 16383 - 64 + 1, 1, SI };
|
||||
ULong bits[2];
|
||||
Long exp;
|
||||
int k;
|
||||
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) {
|
||||
case STRTOG_NoNumber:
|
||||
case STRTOG_Zero:
|
||||
|
@ -60,6 +60,15 @@ must be set to 53 bits. This can be done, e.g., by invoking
|
||||
fpinit_ASL(), whose source appears in
|
||||
http://www.netlib.org/ampl/solvers/fpinit.c .
|
||||
|
||||
The obad directory shows results expected on (at least some) Intel x86
|
||||
Linux systems and may not be relevant to other systems.
|
||||
|
||||
You can optionally compile getround.c with -DHonor_FLT_ROUNDS
|
||||
to manually test strtof, strtod, etc., using fegetround().
|
||||
You can also or alternatively compile getround.c with
|
||||
-DUSE_MY_LOCALE (when ../gdtoa.a is compiled with -DUSE_LOCALE)
|
||||
to test multi-byte decimal points.
|
||||
|
||||
These are simple test programs, not meant for exhaustive testing,
|
||||
but for manually testing "interesting" cases. Paxson's testbase
|
||||
is good for more exhaustive testing, in part with random inputs.
|
||||
|
@ -35,6 +35,11 @@ THIS SOFTWARE.
|
||||
static char *dir[4] = { "toward zero", "nearest", "toward +Infinity",
|
||||
"toward -Infinity" };
|
||||
|
||||
#ifdef Honor_FLT_ROUNDS
|
||||
#include <fenv.h>
|
||||
static int fe_conv[4] = {FE_TOWARDZERO, FE_TONEAREST, FE_UPWARD, FE_DOWNWARD };
|
||||
#endif
|
||||
|
||||
int
|
||||
#ifdef KR_headers
|
||||
getround(r, s) int r; char *s;
|
||||
@ -59,6 +64,9 @@ getround(int r, char *s)
|
||||
else
|
||||
printf("changed from %d (%s) to %d (%s)\n",
|
||||
r, dir[r], i, dir[i]);
|
||||
#ifdef Honor_FLT_ROUNDS
|
||||
fesetround(fe_conv[i]);
|
||||
#endif
|
||||
return i;
|
||||
}
|
||||
printf("Bad rounding direction %d: choose among\n", i);
|
||||
@ -67,3 +75,16 @@ getround(int r, char *s)
|
||||
printf("Leaving rounding mode for strtor... at %d (%s)\n", r, dir[r]);
|
||||
return r;
|
||||
}
|
||||
|
||||
#ifdef USE_MY_LOCALE
|
||||
#include <locale.h>
|
||||
|
||||
struct lconv *
|
||||
localeconv(void)
|
||||
{
|
||||
static struct lconv mylocale;
|
||||
mylocale.decimal_point = "<Pt>";
|
||||
return &mylocale;
|
||||
}
|
||||
#endif
|
||||
|
||||
|
@ -28,6 +28,8 @@ CC = cc
|
||||
CFLAGS = -g -I..
|
||||
A = ../gdtoa.a
|
||||
L = -lm
|
||||
L1 =
|
||||
#use "L1=-lm" when compiled with -DHonor_FLTP_ROUNDS or -DUSE_LOCALE
|
||||
INFFIX = | sed 's/[Ii][Nn][Ff][intyINTY]*/Infinity/g'
|
||||
|
||||
.c.o:
|
||||
@ -41,7 +43,7 @@ dt: $(dt)
|
||||
|
||||
dItest = dItest.o getround.o $A
|
||||
dItest: $(dItest)
|
||||
$(CC) -o dItest $(dItest)
|
||||
$(CC) -o dItest $(dItest) $(L1)
|
||||
|
||||
ddtest = ddtest.o getround.o $A
|
||||
ddtest: $(ddtest)
|
||||
@ -53,19 +55,19 @@ dtest: $(dtest)
|
||||
|
||||
ftest = ftest.o getround.o $A
|
||||
ftest: $(ftest)
|
||||
$(CC) -o ftest $(ftest)
|
||||
$(CC) -o ftest $(ftest) $(L1)
|
||||
|
||||
Qtest = Qtest.o getround.o $A
|
||||
Qtest: $(Qtest)
|
||||
$(CC) -o Qtest $(Qtest)
|
||||
$(CC) -o Qtest $(Qtest) $(L1)
|
||||
|
||||
xtest = xtest.o getround.o $A
|
||||
xtest: $(xtest)
|
||||
$(CC) -o xtest $(xtest)
|
||||
$(CC) -o xtest $(xtest) $(L1)
|
||||
|
||||
xLtest = xLtest.o getround.o $A
|
||||
xLtest: $(xLtest)
|
||||
$(CC) -o xLtest $(xLtest)
|
||||
$(CC) -o xLtest $(xLtest) $(L1)
|
||||
|
||||
strtopddSI.o: strtopddSI.c ../strtopdd.c
|
||||
|
||||
@ -83,7 +85,7 @@ ddtestsi: $(ddtestsi)
|
||||
|
||||
dItestsi = dItest.o strtodISI.o strtoIdSI.o getround.o $A
|
||||
dItestsi: $(dItestsi)
|
||||
$(CC) -o dItestsi $(dItestsi)
|
||||
$(CC) -o dItestsi $(dItestsi) $(L1)
|
||||
|
||||
strtodt = strtodt.o $A
|
||||
strtodt: $(strtodt)
|
||||
@ -132,7 +134,8 @@ tests: Q.out x.out xL.out dt dItest ddtest dtest ftest Qtest xLtest xtest ddtest
|
||||
cat bad/strtodt.out
|
||||
./strtodtnrp testnos3 >bad/strtodtnrp.out && rm bad/strtodtnrp.out || \
|
||||
cat bad/strtodtnrp.out
|
||||
rmdir bad
|
||||
rmdir bad 2>/dev/null || \
|
||||
(cd bad; for i in *; do cmp -s $$i ../obad/$$i && rm $$i;done; cd ..; rmdir bad)
|
||||
touch tests
|
||||
|
||||
xs0 = README Qtest.c dItest.c ddtest.c dtest.c dt.c ftest.c getround.c \
|
||||
|
6
test/obad/strtodt.out
Normal file
6
test/obad/strtodt.out
Normal file
@ -0,0 +1,6 @@
|
||||
Line 31 of testnos3: got 4585747a b143e354; expected 4585747a b143e353
|
||||
Line 46 of testnos3: got 64fdcf7d f8f573b8; expected 64fdcf7d f8f573b7
|
||||
Line 47 of testnos3: got 650dcf7d f8f573b8; expected 650dcf7d f8f573b7
|
||||
Line 72 of testnos3: got 3cc70385 6844bdbe; expected 3cc70385 6844bdbf
|
||||
Line 73 of testnos3: got 3cb70385 6844bdbe; expected 3cb70385 6844bdbf
|
||||
5 bad conversions
|
1460
test/obad/xL.out
Normal file
1460
test/obad/xL.out
Normal file
File diff suppressed because it is too large
Load Diff
@ -1,11 +1,11 @@
|
||||
README e86e9133 2692
|
||||
README e3adb571 3095
|
||||
Qtest.c e8353ffc 5046
|
||||
dItest.c e33800ce 2371
|
||||
ddtest.c f9d06e7b 4984
|
||||
dtest.c ee533ac3 4078
|
||||
dt.c 7eeda57 6384
|
||||
ftest.c ec8a6654 3999
|
||||
getround.c 161043dd 2143
|
||||
getround.c fe659fe7 2503
|
||||
strtoIdSI.c 7bfb88b 49
|
||||
strtoIddSI.c 72e8852 50
|
||||
strtodISI.c ed08b740 49
|
||||
@ -32,4 +32,4 @@ x.ou1 f1af5a00 34581
|
||||
xL.ou1 e349e5c 37165
|
||||
Q.ou0 e4592b85 28742
|
||||
Q.ou1 ea0b344d 39572
|
||||
makefile b77232c 4939
|
||||
makefile 13d36c85 5148
|
||||
|
47
xsum0.out
47
xsum0.out
@ -1,25 +1,26 @@
|
||||
README 1d9fab5a 14790
|
||||
README ee32ce1c 15386
|
||||
arithchk.c ebbe5bc7 4075
|
||||
dmisc.c c8daa18 4682
|
||||
dtoa.c 14f5b9e1 17138
|
||||
g_Qfmt.c f791d807 2839
|
||||
g__fmt.c 14dca85 2504
|
||||
g_ddfmt.c 10eae12a 3695
|
||||
g_dfmt.c f36c1014 2503
|
||||
g_ffmt.c fb83cfb5 2429
|
||||
g_xLfmt.c f216a096 2686
|
||||
g_xfmt.c ed824bf3 2775
|
||||
gdtoa.c e29409a6 16988
|
||||
gdtoa.h fd46e927 4920
|
||||
gdtoaimp.h e753264b 19648
|
||||
gethex.c f42e6bdf 6247
|
||||
g_Qfmt.c f6aad16c 2926
|
||||
g__fmt.c 1b8e8cd8 3401
|
||||
g_ddfmt.c eb4d0889 4090
|
||||
g_dfmt.c 10d694eb 2584
|
||||
g_ffmt.c 197652f1 2516
|
||||
g_xLfmt.c 3fd29c5 2773
|
||||
g_xfmt.c f6a580a 2862
|
||||
gdtoa.c eabc1bc5 17024
|
||||
gdtoa.h f3c171cc 4945
|
||||
gdtoa_fltrnds.h 1aaf5112 421
|
||||
gdtoaimp.h 490a372 19893
|
||||
gethex.c e7327648 7106
|
||||
gmisc.c 1859d016 2084
|
||||
hd_init.c efdbe921 1797
|
||||
hexnan.c 13f362b7 3462
|
||||
makefile f890b12 2932
|
||||
makefile 3cd7ae 2933
|
||||
misc.c 1757f7fc 14252
|
||||
qnan.c efd33d64 3417
|
||||
smisc.c e282e715 3655
|
||||
smisc.c 1064c213 3694
|
||||
strtoIQ.c 1809dfcf 1939
|
||||
strtoId.c f41ddac2 1931
|
||||
strtoIdd.c f13e3bc3 2105
|
||||
@ -27,17 +28,17 @@ strtoIf.c f12c6af4 1875
|
||||
strtoIg.c fd8c1bcf 3589
|
||||
strtoIx.c e50f716d 1960
|
||||
strtoIxL.c ea0b821b 1931
|
||||
strtod.c f6943e52 21001
|
||||
strtod.c e7e4addc 21731
|
||||
strtodI.c 1c2440ce 3915
|
||||
strtodg.c 1c1bb220 20499
|
||||
strtodg.c f74828cc 21164
|
||||
strtodnrp.c af895e9 2538
|
||||
strtof.c 1c5192d3 2073
|
||||
strtopQ.c f116d4f0 2563
|
||||
strtopd.c f7681c7a 1671
|
||||
strtopdd.c 9864fba 4497
|
||||
strtopf.c eb15b627 2067
|
||||
strtopx.c 1cafe482 2618
|
||||
strtopxL.c 1e4b77e9 2373
|
||||
strtof.c 1db524d 2155
|
||||
strtopQ.c f244b012 2645
|
||||
strtopd.c 1c3c9ce 1751
|
||||
strtopdd.c 125d6c19 4580
|
||||
strtopf.c 1939f590 2149
|
||||
strtopx.c f78a816e 2700
|
||||
strtopxL.c b77b701 2455
|
||||
strtorQ.c 9360a0b 2885
|
||||
strtord.c af5c50e 2491
|
||||
strtordd.c 1b266865 4936
|
||||
|
Loading…
Reference in New Issue
Block a user