From fef98cff077e7fda31677073df47c73e891f65e7 Mon Sep 17 00:00:00 2001 From: Ozkan Sezer Date: Wed, 15 Apr 2009 09:53:14 +0000 Subject: [PATCH] 2009-04-15 Ozkan Sezer * gdtoa/gdtoa_fltrnds.h: New. * gdtoa/README, gdtoa/g_dfmt.c, gdtoa/g_ffmt.c, gdtoa/g_xfmt.c, gdtoa/gdtoaimp.h, gdtoa/strtof.c, gdtoa/strtopx.c: Merged in the Honor_FLT_ROUNDS/fegetround() bits from the current netlib.org sources. git-svn-id: svn+ssh://svn.code.sf.net/p/mingw-w64/code/trunk@776 4407c894-4637-0410-b4f5-ada5f102cad1 --- mingw-w64-crt/ChangeLog | 5 +++++ mingw-w64-crt/gdtoa/README | 17 ++++++++++++++++- mingw-w64-crt/gdtoa/g_dfmt.c | 9 +++++++-- mingw-w64-crt/gdtoa/g_ffmt.c | 11 ++++++++--- mingw-w64-crt/gdtoa/g_xfmt.c | 16 +++++++++------- mingw-w64-crt/gdtoa/gdtoa_fltrnds.h | 18 ++++++++++++++++++ mingw-w64-crt/gdtoa/gdtoaimp.h | 6 +++++- mingw-w64-crt/gdtoa/strtof.c | 9 +++++++-- mingw-w64-crt/gdtoa/strtopx.c | 9 +++++++-- 9 files changed, 82 insertions(+), 18 deletions(-) create mode 100644 mingw-w64-crt/gdtoa/gdtoa_fltrnds.h diff --git a/mingw-w64-crt/ChangeLog b/mingw-w64-crt/ChangeLog index 65d59750e..afcf8cc9f 100644 --- a/mingw-w64-crt/ChangeLog +++ b/mingw-w64-crt/ChangeLog @@ -3,6 +3,11 @@ * gdtoa/dtoa.c, gdtoa/gdtoa.c: Sync'ed with the netlib.org sources. * gdtoa/gdtoa.h: Minor cleanup. + * gdtoa/gdtoa_fltrnds.h: New. + * gdtoa/README, gdtoa/g_dfmt.c, gdtoa/g_ffmt.c, gdtoa/g_xfmt.c, + gdtoa/gdtoaimp.h, gdtoa/strtof.c, gdtoa/strtopx.c: Merged in the + Honor_FLT_ROUNDS/fegetround() bits from the current netlib.org sources. + 2009-04-14 Ozkan Sezer * gdtoa/dmisc.c, gdtoa/dtoa.c, gdtoa/gdtoa.c, gdtoa/gdtoa.h, diff --git a/mingw-w64-crt/gdtoa/README b/mingw-w64-crt/gdtoa/README index cf1947aa2..1a7e1b20d 100644 --- a/mingw-w64-crt/gdtoa/README +++ b/mingw-w64-crt/gdtoa/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". @@ -332,5 +337,15 @@ Compiling g__fmt.c, strtod.c, and strtodg.c with -DUSE_LOCALE causes the decimal-point character to be taken from the current locale; otherwise it is '.'. +Source files dtoa.c and strtod.c in this directory are derived from +netlib's "dtoa.c from fp" and are meant to function equivalently. +When compiled with Honor_FLT_ROUNDS #defined (on systems that provide +FLT_ROUNDS and fegetround() as specified in the C99 standard), they +honor the current rounding mode. Because FLT_ROUNDS is buggy on some +(Linux) systems -- not reflecting calls on fesetround(), as the C99 +standard says it should -- when Honor_FLT_ROUNDS is #defined, the +current rounding mode is obtained from fegetround() rather than from +FLT_ROUNDS, unless Trust_FLT_ROUNDS is also #defined. + Please send comments to David M. Gay (dmg at acm dot org, with " at " changed at "@" and " dot " changed to "."). diff --git a/mingw-w64-crt/gdtoa/g_dfmt.c b/mingw-w64-crt/gdtoa/g_dfmt.c index 22e312af1..07b0e5d2f 100644 --- a/mingw-w64-crt/gdtoa/g_dfmt.c +++ b/mingw-w64-crt/gdtoa/g_dfmt.c @@ -33,10 +33,15 @@ THIS SOFTWARE. char *__g_dfmt (char *buf, double *d, int ndig, unsigned bufsize) { - static FPI fpi = { 53, 1-1023-53+1, 2046-1023-53+1, 1, 0 }; + static FPI fpi0 = { 53, 1-1023-53+1, 2046-1023-53+1, 1, 0 }; char *b, *s, *se; ULong bits[2], *L, sign; int decpt, ex, i, mode; +#ifdef Honor_FLT_ROUNDS +#include "gdtoa_fltrnds.h" +#else +#define fpi &fpi0 +#endif if (ndig < 0) ndig = 0; @@ -79,6 +84,6 @@ char *__g_dfmt (char *buf, double *d, int ndig, unsigned bufsize) mode = 0; } 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); } diff --git a/mingw-w64-crt/gdtoa/g_ffmt.c b/mingw-w64-crt/gdtoa/g_ffmt.c index cf039c621..51475e1a2 100644 --- a/mingw-w64-crt/gdtoa/g_ffmt.c +++ b/mingw-w64-crt/gdtoa/g_ffmt.c @@ -33,10 +33,15 @@ THIS SOFTWARE. char *__g_ffmt (char *buf, float *f, int ndig, unsigned bufsize) { - static FPI fpi = { 24, 1-127-24+1, 254-127-24+1, 1, 0 }; + static FPI fpi0 = { 24, 1-127-24+1, 254-127-24+1, 1, 0 }; char *b, *s, *se; ULong bits[1], *L, sign; int decpt, ex, i, mode; +#ifdef Honor_FLT_ROUNDS +#include "gdtoa_fltrnds.h" +#else +#define fpi &fpi0 +#endif if (ndig < 0) ndig = 0; @@ -49,7 +54,7 @@ char *__g_ffmt (char *buf, float *f, int ndig, unsigned bufsize) /* Infinity or NaN */ if (L[0] & 0x7fffff) { return strcp(buf, "NaN"); - } + } b = buf; if (sign) *b++ = '-'; @@ -78,6 +83,6 @@ char *__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); + s = __gdtoa(fpi, ex, bits, &i, mode, ndig, &decpt, &se); return __g__fmt(buf, s, se, decpt, sign); } diff --git a/mingw-w64-crt/gdtoa/g_xfmt.c b/mingw-w64-crt/gdtoa/g_xfmt.c index a1554d363..28de97852 100644 --- a/mingw-w64-crt/gdtoa/g_xfmt.c +++ b/mingw-w64-crt/gdtoa/g_xfmt.c @@ -53,14 +53,18 @@ THIS SOFTWARE. char *__g_xfmt (char *buf, void *V, int ndig, unsigned bufsize) { - static FPI fpi = { 64, 1-16383-64+1, 32766 - 16383 - 64 + 1, 1, 0 }; + static FPI fpi0 = { 64, 1-16383-64+1, 32766 - 16383 - 64 + 1, 1, 0 }; char *b, *s, *se; ULong bits[2], sign; UShort *L; int decpt, ex, i, mode; - int fptype = __fpclassifyl (*(long double*) V); - +#ifdef Honor_FLT_ROUNDS +#include "gdtoa_fltrnds.h" +#else +#define fpi &fpi0 +#endif + if (ndig < 0) ndig = 0; if (bufsize < ndig + 10) @@ -68,8 +72,7 @@ char *__g_xfmt (char *buf, void *V, int ndig, unsigned bufsize) L = (UShort *)V; sign = L[_0] & 0x8000; - ex = L[_0] & 0x7fff; - + ex = L[_0] & 0x7fff; bits[1] = (L[_1] << 16) | L[_2]; bits[0] = (L[_3] << 16) | L[_4]; @@ -102,7 +105,6 @@ char *__g_xfmt (char *buf, void *V, int ndig, unsigned bufsize) *b = 0; return b; } - ex -= 0x3fff + 63; mode = 2; if (ndig <= 0) { @@ -110,6 +112,6 @@ char *__g_xfmt (char *buf, void *V, int ndig, unsigned bufsize) return 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); } diff --git a/mingw-w64-crt/gdtoa/gdtoa_fltrnds.h b/mingw-w64-crt/gdtoa/gdtoa_fltrnds.h new file mode 100644 index 000000000..28c474e2c --- /dev/null +++ b/mingw-w64-crt/gdtoa/gdtoa_fltrnds.h @@ -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; + } diff --git a/mingw-w64-crt/gdtoa/gdtoaimp.h b/mingw-w64-crt/gdtoa/gdtoaimp.h index 6b1e04689..1379e7640 100644 --- a/mingw-w64-crt/gdtoa/gdtoaimp.h +++ b/mingw-w64-crt/gdtoa/gdtoaimp.h @@ -170,6 +170,10 @@ THIS SOFTWARE. #define USE_LOCALE 1 #endif /* MinGW */ +#ifdef Honor_FLT_ROUNDS +#include +#endif + #ifdef DEBUG #include #define Bug(x) {fprintf(stderr, "%s\n", x); exit(1);} @@ -448,7 +452,7 @@ typedef struct Bigint Bigint; #ifdef DECLARE_SIZE_T typedef unsigned int size_t; #endif -extern void memcpy_D2A (void *, const void *, size_t); +extern void memcpy_D2A (void*, const void*, size_t); #define Bcopy(x,y) memcpy_D2A(&x->sign,&y->sign,y->wds*sizeof(ULong) + 2*sizeof(int)) #else /* !NO_STRING_H */ #define Bcopy(x,y) memcpy(&x->sign,&y->sign,y->wds*sizeof(ULong) + 2*sizeof(int)) diff --git a/mingw-w64-crt/gdtoa/strtof.c b/mingw-w64-crt/gdtoa/strtof.c index d9c69d651..5b117859a 100644 --- a/mingw-w64-crt/gdtoa/strtof.c +++ b/mingw-w64-crt/gdtoa/strtof.c @@ -33,13 +33,18 @@ THIS SOFTWARE. float __strtof (const char *s, char **sp) { - static FPI fpi = { 24, 1-127-24+1, 254-127-24+1, 1, SI }; + static FPI fpi0 = { 24, 1-127-24+1, 254-127-24+1, 1, SI }; ULong bits[1]; Long exp; int k; union { ULong L[1]; float f; } u; +#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: diff --git a/mingw-w64-crt/gdtoa/strtopx.c b/mingw-w64-crt/gdtoa/strtopx.c index 21971a1e2..c15919689 100644 --- a/mingw-w64-crt/gdtoa/strtopx.c +++ b/mingw-w64-crt/gdtoa/strtopx.c @@ -58,14 +58,19 @@ typedef union lD { static int __strtopx (const char *s, char **sp, lD *V) { - static FPI fpi = { 64, 1-16383-64+1, 32766 - 16383 - 64 + 1, 1, SI }; + static FPI fpi0 = { 64, 1-16383-64+1, 32766 - 16383 - 64 + 1, 1, SI }; ULong bits[2]; Long exp; int k; UShort *L = & (V->L[0]); +#ifdef Honor_FLT_ROUNDS +#include "gdtoa_fltrnds.h" +#else +#define fpi &fpi0 +#endif V->D = 0.0L; - k = __strtodg(s, sp, &fpi, &exp, bits); + k = __strtodg(s, sp, fpi, &exp, bits); switch(k & STRTOG_Retmask) { case STRTOG_NoNumber: case STRTOG_Zero: