Vendor import of gdtoa 20081205.

This commit is contained in:
David Schultz 2009-01-28 04:36:34 +00:00
commit 4848dd0858
31 changed files with 1901 additions and 149 deletions

View File

@ -56,7 +56,9 @@ two letters:
whose sum is the desired value
For decimal -> binary conversions, there are three families of
helper routines: one for round-nearest:
helper routines: one for round-nearest (or the current rounding
mode on IEEE-arithmetic systems that provide the C99 fegetround()
function, if compiled with -DHonor_FLT_ROUNDS):
strtof
strtod
@ -191,6 +193,9 @@ in the buffer, if the buffer was long enough, or 0. Other forms of
conversion are easily done with the help of gdtoa(), such as %e or %f
style and conversions with direction of rounding specified (so that, if
desired, the decimal value is either >= or <= the binary value).
On IEEE-arithmetic systems that provide the C99 fegetround() function,
if compiled with -DHonor_FLT_ROUNDS, these routines honor the current
rounding mode.
For an example of more general conversions based on dtoa(), see
netlib's "printf.c from ampl/solvers".
@ -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 ".").

View File

@ -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);
}

View File

@ -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;
}

View File

@ -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;
}

View File

@ -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);
}

View File

@ -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);
}

View File

@ -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);
}

View File

@ -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);
}

View File

@ -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);

View File

@ -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*));

View File

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

View File

@ -128,8 +128,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
@ -177,6 +179,9 @@ THIS SOFTWARE.
#include "gdtoa.h"
#include "gd_qnan.h"
#ifdef Honor_FLT_ROUNDS
#include <fenv.h>
#endif
#ifdef DEBUG
#include "stdio.h"
@ -206,6 +211,7 @@ extern Char *MALLOC ANSI((size_t));
#define INFNAN_CHECK
#define USE_LOCALE
#define NO_LOCALE_CACHE
#define Honor_FLT_ROUNDS
#define Trust_FLT_ROUNDS
@ -608,7 +614,7 @@ extern void memcpy_D2A ANSI((void*, const void*, size_t));
extern void freedtoa ANSI((char*));
extern char *gdtoa ANSI((FPI *fpi, int be, ULong *bits, int *kindp,
int mode, int ndigits, int *decpt, 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*));
@ -626,7 +632,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 strtodg ANSI((CONST char*, char**, FPI*, Long*, ULong*));
@ -668,6 +674,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

View File

@ -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;

View File

@ -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

View File

@ -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;

View File

@ -80,6 +80,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! */
@ -118,7 +140,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;
@ -157,7 +179,7 @@ strtod
goto ret;
}
}
#endif
#endif /*}*/
nz0 = 1;
while(*++s == '0') ;
if (!*s)
@ -172,13 +194,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++;
@ -207,7 +233,7 @@ strtod
nz = 0;
}
}
}
}/*}*/
dig_done:
e = 0;
if (c == 'e' || c == 'E') {
@ -527,7 +553,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);
@ -974,7 +1000,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
}

View File

@ -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))

View File

@ -41,19 +41,16 @@ strtof(CONST char *s, char **sp)
#endif
{
static FPI fpi0 = { 24, 1-127-24+1, 254-127-24+1, 1, SI };
FPI *fpi, fpi1;
ULong bits[1];
Long exp;
int k;
int Rounding = Flt_Rounds;
union { ULong L[1]; float f; } u;
#ifdef Honor_FLT_ROUNDS
#include "gdtoa_fltrnds.h"
#else
#define fpi &fpi0
#endif
fpi = &fpi0;
if (Rounding != FPI_Round_near) {
fpi1 = fpi0;
fpi1.rounding = Rounding;
fpi = &fpi1;
}
k = strtodg(s, sp, fpi, &exp, bits);
switch(k & STRTOG_Retmask) {
case STRTOG_NoNumber:

View File

@ -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:

View File

@ -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;
}

View File

@ -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:

View File

@ -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:

View File

@ -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:

View File

@ -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:

View File

@ -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.

View File

@ -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

View File

@ -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 \

View 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

File diff suppressed because it is too large Load Diff

View File

@ -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

View File

@ -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