2006-06-22 Jeff Johnston <jjohnstn@redhat.com>

* libc/stdlib/Makefile.am: Add new gdtoa routines.
        * libc/stdlib/Makefile.in: Regenerated.
        * libc/stdlib/gd_qnan.h: New file.
        * libc/stdlib/gdtoa-gethex.c: Ditto.
        * libc/stdlib/gdtoa-hexnan.c: Ditto.
        * libc/stdlib/gdtoa.h: Ditto.
        * libc/stdlib/mprec.c: Add new helper routines needed by
        the new gdtoa code.
        * libc/stdlib/mprec.h: Integrate some defines and prototypes
        used by gdtoa routines here.
        * libc/stdlib/strtod.c: Rebased on David M. Gay's gdtoa-strtod.c
        which adds C99 support such as nan, inf, and hexadecimal input
        format.
This commit is contained in:
Jeff Johnston 2006-06-22 17:59:52 +00:00
parent 09fd280ca4
commit f489b5943c
10 changed files with 1832 additions and 635 deletions

View File

@ -1,3 +1,19 @@
2006-06-22 Jeff Johnston <jjohnstn@redhat.com>
* libc/stdlib/Makefile.am: Add new gdtoa routines.
* libc/stdlib/Makefile.in: Regenerated.
* libc/stdlib/gd_qnan.h: New file.
* libc/stdlib/gdtoa-gethex.c: Ditto.
* libc/stdlib/gdtoa-hexnan.c: Ditto.
* libc/stdlib/gdtoa.h: Ditto.
* libc/stdlib/mprec.c: Add new helper routines needed by
the new gdtoa code.
* libc/stdlib/mprec.h: Integrate some defines and prototypes
used by gdtoa routines here.
* libc/stdlib/strtod.c: Rebased on David M. Gay's gdtoa-strtod.c
which adds C99 support such as nan, inf, and hexadecimal input
format.
2006-06-15 Corinna Vinschen <corinna@vinschen.de> 2006-06-15 Corinna Vinschen <corinna@vinschen.de>
* libc/include/stdio.h (__sgetc_r): Fix typo. * libc/include/stdio.h (__sgetc_r): Fix typo.

View File

@ -27,6 +27,8 @@ GENERAL_SOURCES = \
envlock.c \ envlock.c \
eprintf.c \ eprintf.c \
exit.c \ exit.c \
gdtoa-gethex.c \
gdtoa-hexnan.c \
getenv.c \ getenv.c \
getenv_r.c \ getenv_r.c \
labs.c \ labs.c \
@ -256,6 +258,8 @@ $(lpfx)mbtowc_r.$(oext): mbtowc_r.c mbctype.h
$(lpfx)mprec.$(oext): mprec.c mprec.h $(lpfx)mprec.$(oext): mprec.c mprec.h
$(lpfx)strtod.$(oext): strtod.c mprec.h $(lpfx)strtod.$(oext): strtod.c mprec.h
$(lpfx)gdtoa-gethex.$(oext): gdtoa-gethex.c mprec.h
$(lpfx)gdtoa-hexnan.$(oext): gdtoa-hexnan.c mprec.h
$(lpfx)wctomb_r.$(oext): wctomb_r.c mbctype.h $(lpfx)wctomb_r.$(oext): wctomb_r.c mbctype.h
$(lpfx)drand48.$(oext): drand48.c rand48.h $(lpfx)drand48.$(oext): drand48.c rand48.h
$(lpfx)erand48.$(oext): erand48.c rand48.h $(lpfx)erand48.$(oext): erand48.c rand48.h

View File

@ -74,6 +74,7 @@ am__objects_1 = lib_a-__adjust.$(OBJEXT) lib_a-__atexit.$(OBJEXT) \
lib_a-dtoa.$(OBJEXT) lib_a-dtoastub.$(OBJEXT) \ lib_a-dtoa.$(OBJEXT) lib_a-dtoastub.$(OBJEXT) \
lib_a-environ.$(OBJEXT) lib_a-envlock.$(OBJEXT) \ lib_a-environ.$(OBJEXT) lib_a-envlock.$(OBJEXT) \
lib_a-eprintf.$(OBJEXT) lib_a-exit.$(OBJEXT) \ lib_a-eprintf.$(OBJEXT) lib_a-exit.$(OBJEXT) \
lib_a-gdtoa-gethex.$(OBJEXT) lib_a-gdtoa-hexnan.$(OBJEXT) \
lib_a-getenv.$(OBJEXT) lib_a-getenv_r.$(OBJEXT) \ lib_a-getenv.$(OBJEXT) lib_a-getenv_r.$(OBJEXT) \
lib_a-labs.$(OBJEXT) lib_a-ldiv.$(OBJEXT) \ lib_a-labs.$(OBJEXT) lib_a-ldiv.$(OBJEXT) \
lib_a-ldtoa.$(OBJEXT) lib_a-malloc.$(OBJEXT) \ lib_a-ldtoa.$(OBJEXT) lib_a-malloc.$(OBJEXT) \
@ -124,12 +125,12 @@ LTLIBRARIES = $(noinst_LTLIBRARIES)
am__objects_7 = __adjust.lo __atexit.lo __call_atexit.lo __exp10.lo \ am__objects_7 = __adjust.lo __atexit.lo __call_atexit.lo __exp10.lo \
__ten_mu.lo _Exit.lo abort.lo abs.lo assert.lo atexit.lo \ __ten_mu.lo _Exit.lo abort.lo abs.lo assert.lo atexit.lo \
atof.lo atoff.lo atoi.lo atol.lo calloc.lo div.lo dtoa.lo \ atof.lo atoff.lo atoi.lo atol.lo calloc.lo div.lo dtoa.lo \
dtoastub.lo environ.lo envlock.lo eprintf.lo exit.lo getenv.lo \ dtoastub.lo environ.lo envlock.lo eprintf.lo exit.lo \
getenv_r.lo labs.lo ldiv.lo ldtoa.lo malloc.lo mblen.lo \ gdtoa-gethex.lo gdtoa-hexnan.lo getenv.lo getenv_r.lo labs.lo \
mblen_r.lo mbstowcs.lo mbstowcs_r.lo mbtowc.lo mbtowc_r.lo \ ldiv.lo ldtoa.lo malloc.lo mblen.lo mblen_r.lo mbstowcs.lo \
mlock.lo mprec.lo mstats.lo rand.lo rand_r.lo realloc.lo \ mbstowcs_r.lo mbtowc.lo mbtowc_r.lo mlock.lo mprec.lo \
strtod.lo strtol.lo strtoul.lo wcstombs.lo wcstombs_r.lo \ mstats.lo rand.lo rand_r.lo realloc.lo strtod.lo strtol.lo \
wctomb.lo wctomb_r.lo strtoul.lo wcstombs.lo wcstombs_r.lo wctomb.lo wctomb_r.lo
am__objects_8 = cxa_atexit.lo cxa_finalize.lo drand48.lo ecvtbuf.lo \ am__objects_8 = cxa_atexit.lo cxa_finalize.lo drand48.lo ecvtbuf.lo \
efgcvt.lo erand48.lo jrand48.lo lcong48.lo lrand48.lo \ efgcvt.lo erand48.lo jrand48.lo lcong48.lo lrand48.lo \
mrand48.lo msize.lo mtrim.lo nrand48.lo rand48.lo seed48.lo \ mrand48.lo msize.lo mtrim.lo nrand48.lo rand48.lo seed48.lo \
@ -249,6 +250,7 @@ PACKAGE_TARNAME = @PACKAGE_TARNAME@
PACKAGE_VERSION = @PACKAGE_VERSION@ PACKAGE_VERSION = @PACKAGE_VERSION@
PATH_SEPARATOR = @PATH_SEPARATOR@ PATH_SEPARATOR = @PATH_SEPARATOR@
RANLIB = @RANLIB@ RANLIB = @RANLIB@
READELF = @READELF@
SET_MAKE = @SET_MAKE@ SET_MAKE = @SET_MAKE@
SHELL = @SHELL@ SHELL = @SHELL@
STRIP = @STRIP@ STRIP = @STRIP@
@ -259,6 +261,7 @@ ac_ct_AR = @ac_ct_AR@
ac_ct_AS = @ac_ct_AS@ ac_ct_AS = @ac_ct_AS@
ac_ct_CC = @ac_ct_CC@ ac_ct_CC = @ac_ct_CC@
ac_ct_RANLIB = @ac_ct_RANLIB@ ac_ct_RANLIB = @ac_ct_RANLIB@
ac_ct_READELF = @ac_ct_READELF@
ac_ct_STRIP = @ac_ct_STRIP@ ac_ct_STRIP = @ac_ct_STRIP@
aext = @aext@ aext = @aext@
am__fastdepCC_FALSE = @am__fastdepCC_FALSE@ am__fastdepCC_FALSE = @am__fastdepCC_FALSE@
@ -329,6 +332,8 @@ GENERAL_SOURCES = \
envlock.c \ envlock.c \
eprintf.c \ eprintf.c \
exit.c \ exit.c \
gdtoa-gethex.c \
gdtoa-hexnan.c \
getenv.c \ getenv.c \
getenv_r.c \ getenv_r.c \
labs.c \ labs.c \
@ -685,6 +690,18 @@ lib_a-exit.o: exit.c
lib_a-exit.obj: exit.c lib_a-exit.obj: exit.c
$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(lib_a_CFLAGS) $(CFLAGS) -c -o lib_a-exit.obj `if test -f 'exit.c'; then $(CYGPATH_W) 'exit.c'; else $(CYGPATH_W) '$(srcdir)/exit.c'; fi` $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(lib_a_CFLAGS) $(CFLAGS) -c -o lib_a-exit.obj `if test -f 'exit.c'; then $(CYGPATH_W) 'exit.c'; else $(CYGPATH_W) '$(srcdir)/exit.c'; fi`
lib_a-gdtoa-gethex.o: gdtoa-gethex.c
$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(lib_a_CFLAGS) $(CFLAGS) -c -o lib_a-gdtoa-gethex.o `test -f 'gdtoa-gethex.c' || echo '$(srcdir)/'`gdtoa-gethex.c
lib_a-gdtoa-gethex.obj: gdtoa-gethex.c
$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(lib_a_CFLAGS) $(CFLAGS) -c -o lib_a-gdtoa-gethex.obj `if test -f 'gdtoa-gethex.c'; then $(CYGPATH_W) 'gdtoa-gethex.c'; else $(CYGPATH_W) '$(srcdir)/gdtoa-gethex.c'; fi`
lib_a-gdtoa-hexnan.o: gdtoa-hexnan.c
$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(lib_a_CFLAGS) $(CFLAGS) -c -o lib_a-gdtoa-hexnan.o `test -f 'gdtoa-hexnan.c' || echo '$(srcdir)/'`gdtoa-hexnan.c
lib_a-gdtoa-hexnan.obj: gdtoa-hexnan.c
$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(lib_a_CFLAGS) $(CFLAGS) -c -o lib_a-gdtoa-hexnan.obj `if test -f 'gdtoa-hexnan.c'; then $(CYGPATH_W) 'gdtoa-hexnan.c'; else $(CYGPATH_W) '$(srcdir)/gdtoa-hexnan.c'; fi`
lib_a-getenv.o: getenv.c lib_a-getenv.o: getenv.c
$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(lib_a_CFLAGS) $(CFLAGS) -c -o lib_a-getenv.o `test -f 'getenv.c' || echo '$(srcdir)/'`getenv.c $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(lib_a_CFLAGS) $(CFLAGS) -c -o lib_a-getenv.o `test -f 'getenv.c' || echo '$(srcdir)/'`getenv.c
@ -1298,6 +1315,8 @@ $(lpfx)mbtowc_r.$(oext): mbtowc_r.c mbctype.h
$(lpfx)mprec.$(oext): mprec.c mprec.h $(lpfx)mprec.$(oext): mprec.c mprec.h
$(lpfx)strtod.$(oext): strtod.c mprec.h $(lpfx)strtod.$(oext): strtod.c mprec.h
$(lpfx)gdtoa-gethex.$(oext): gdtoa-gethex.c mprec.h
$(lpfx)gdtoa-hexnan.$(oext): gdtoa-hexnan.c mprec.h
$(lpfx)wctomb_r.$(oext): wctomb_r.c mbctype.h $(lpfx)wctomb_r.$(oext): wctomb_r.c mbctype.h
$(lpfx)drand48.$(oext): drand48.c rand48.h $(lpfx)drand48.$(oext): drand48.c rand48.h
$(lpfx)erand48.$(oext): erand48.c rand48.h $(lpfx)erand48.$(oext): erand48.c rand48.h

View File

@ -0,0 +1,33 @@
#ifdef __IEEE_BIG_ENDIAN
#define f_QNAN 0x7fc00000
#define d_QNAN0 0x7ff80000
#define d_QNAN1 0x0
#define ld_QNAN0 0x7ff80000
#define ld_QNAN1 0x0
#define ld_QNAN2 0x0
#define ld_QNAN3 0x0
#define ldus_QNAN0 0x7ff8
#define ldus_QNAN1 0x0
#define ldus_QNAN2 0x0
#define ldus_QNAN3 0x0
#define ldus_QNAN4 0x0
#elif defined(__IEEE_LITTLE_ENDIAN)
#define f_QNAN 0xffc00000
#define d_QNAN0 0x0
#define d_QNAN1 0xfff80000
#define ld_QNAN0 0x0
#define ld_QNAN1 0xc0000000
#define ld_QNAN2 0xffff
#define ld_QNAN3 0x0
#define ldus_QNAN0 0x0
#define ldus_QNAN1 0x0
#define ldus_QNAN2 0x0
#define ldus_QNAN3 0xc000
#define ldus_QNAN4 0xffff
#else
#error IEEE endian not defined
#endif

View File

@ -0,0 +1,351 @@
/****************************************************************
The author of this software is David M. Gay.
Copyright (C) 1998 by Lucent Technologies
All Rights Reserved
Permission to use, copy, modify, and distribute this software and
its documentation for any purpose and without fee is hereby
granted, provided that the above copyright notice appear in all
copies and that both that the copyright notice and this
permission notice and warranty disclaimer appear in supporting
documentation, and that the name of Lucent or any of its entities
not be used in advertising or publicity pertaining to
distribution of the software without specific, written prior
permission.
LUCENT DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS.
IN NO EVENT SHALL LUCENT OR ANY OF ITS ENTITIES BE LIABLE FOR ANY
SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER
IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF
THIS SOFTWARE.
****************************************************************/
/* Please send bug reports to David M. Gay (dmg at acm dot org,
* with " at " changed at "@" and " dot " changed to "."). */
#include <_ansi.h>
#include <reent.h>
#include <string.h>
#include "mprec.h"
#include "gdtoa.h"
#include "gd_qnan.h"
#ifdef USE_LOCALE
#include "locale.h"
#endif
unsigned char hexdig[256];
static void
_DEFUN (htinit, (h, s, inc),
unsigned char *h _AND
unsigned char *s _AND
int inc)
{
int i, j;
for(i = 0; (j = s[i]) !=0; i++)
h[j] = i + inc;
}
void
_DEFUN_VOID (hexdig_init)
{
#define USC (unsigned char *)
htinit(hexdig, USC "0123456789", 0x10);
htinit(hexdig, USC "abcdef", 0x10 + 10);
htinit(hexdig, USC "ABCDEF", 0x10 + 10);
}
static void
_DEFUN(rshift, (b, k),
_Bigint *b _AND
int k)
{
__ULong *x, *x1, *xe, y;
int n;
x = x1 = b->_x;
n = k >> kshift;
if (n < b->_wds) {
xe = x + b->_wds;
x += n;
if (k &= kmask) {
n = ULbits - k;
y = *x++ >> k;
while(x < xe) {
*x1++ = (y | (*x << n)) & ALL_ON;
y = *x++ >> k;
}
if ((*x1 = y) !=0)
x1++;
}
else
while(x < xe)
*x1++ = *x++;
}
if ((b->_wds = x1 - b->_x) == 0)
b->_x[0] = 0;
}
static _Bigint *
_DEFUN (increment, (ptr, b),
struct _reent *ptr _AND
_Bigint *b)
{
__ULong *x, *xe;
_Bigint *b1;
#ifdef Pack_16
__ULong carry = 1, y;
#endif
x = b->_x;
xe = x + b->_wds;
#ifdef Pack_32
do {
if (*x < (__ULong)0xffffffffL) {
++*x;
return b;
}
*x++ = 0;
} while(x < xe);
#else
do {
y = *x + carry;
carry = y >> 16;
*x++ = y & 0xffff;
if (!carry)
return b;
} while(x < xe);
if (carry)
#endif
{
if (b->_wds >= b->_maxwds) {
b1 = Balloc(ptr, b->_k+1);
Bcopy(b1, b);
Bfree(ptr, b);
b = b1;
}
b->_x[b->_wds++] = 1;
}
return b;
}
int
_DEFUN(gethex, (ptr, sp, fpi, exp, bp, sign),
struct _reent *ptr _AND
_CONST char **sp _AND
FPI *fpi _AND
Long *exp _AND
_Bigint **bp _AND
int sign)
{
_Bigint *b;
_CONST unsigned char *decpt, *s0, *s, *s1;
int esign, havedig, irv, k, n, nbits, up, zret;
__ULong L, lostbits, *x;
Long e, e1;
#ifdef USE_LOCALE
unsigned char decimalpoint = *localeconv()->decimal_point;
#else
#define decimalpoint '.'
#endif
if (!hexdig['0'])
hexdig_init();
havedig = 0;
s0 = *(_CONST unsigned char **)sp + 2;
while(s0[havedig] == '0')
havedig++;
s0 += havedig;
s = s0;
decpt = 0;
zret = 0;
e = 0;
if (!hexdig[*s]) {
zret = 1;
if (*s != decimalpoint)
goto pcheck;
decpt = ++s;
if (!hexdig[*s])
goto pcheck;
while(*s == '0')
s++;
if (hexdig[*s])
zret = 0;
havedig = 1;
s0 = s;
}
while(hexdig[*s])
s++;
if (*s == decimalpoint && !decpt) {
decpt = ++s;
while(hexdig[*s])
s++;
}
if (decpt)
e = -(((Long)(s-decpt)) << 2);
pcheck:
s1 = s;
switch(*s) {
case 'p':
case 'P':
esign = 0;
switch(*++s) {
case '-':
esign = 1;
/* no break */
case '+':
s++;
}
if ((n = hexdig[*s]) == 0 || n > 0x19) {
s = s1;
break;
}
e1 = n - 0x10;
while((n = hexdig[*++s]) !=0 && n <= 0x19)
e1 = 10*e1 + n - 0x10;
if (esign)
e1 = -e1;
e += e1;
}
*sp = (char*)s;
if (zret)
return havedig ? STRTOG_Zero : STRTOG_NoNumber;
n = s1 - s0 - 1;
for(k = 0; n > 7; n >>= 1)
k++;
b = Balloc(ptr, k);
x = b->_x;
n = 0;
L = 0;
while(s1 > s0) {
if (*--s1 == decimalpoint)
continue;
if (n == 32) {
*x++ = L;
L = 0;
n = 0;
}
L |= (hexdig[*s1] & 0x0f) << n;
n += 4;
}
*x++ = L;
b->_wds = n = x - b->_x;
n = 32*n - hi0bits(L);
nbits = fpi->nbits;
lostbits = 0;
x = b->_x;
if (n > nbits) {
n -= nbits;
if (any_on(b,n)) {
lostbits = 1;
k = n - 1;
if (x[k>>kshift] & 1 << (k & kmask)) {
lostbits = 2;
if (k > 1 && any_on(b,k-1))
lostbits = 3;
}
}
rshift(b, n);
e += n;
}
else if (n < nbits) {
n = nbits - n;
b = lshift(ptr, b, n);
e -= n;
x = b->_x;
}
if (e > fpi->emax) {
ovfl:
Bfree(ptr, b);
*bp = 0;
return STRTOG_Infinite | STRTOG_Overflow | STRTOG_Inexhi;
}
irv = STRTOG_Normal;
if (e < fpi->emin) {
irv = STRTOG_Denormal;
n = fpi->emin - e;
if (n >= nbits) {
switch (fpi->rounding) {
case FPI_Round_near:
if (n == nbits && (n < 2 || any_on(b,n-1)))
goto one_bit;
break;
case FPI_Round_up:
if (!sign)
goto one_bit;
break;
case FPI_Round_down:
if (sign) {
one_bit:
*exp = fpi->emin;
x[0] = b->_wds = 1;
*bp = b;
return STRTOG_Denormal | STRTOG_Inexhi
| STRTOG_Underflow;
}
}
Bfree(ptr, b);
*bp = 0;
return STRTOG_Zero | STRTOG_Inexlo | STRTOG_Underflow;
}
k = n - 1;
if (lostbits)
lostbits = 1;
else if (k > 0)
lostbits = any_on(b,k);
if (x[k>>kshift] & 1 << (k & kmask))
lostbits |= 2;
nbits -= n;
rshift(b,n);
e = fpi->emin;
}
if (lostbits) {
up = 0;
switch(fpi->rounding) {
case FPI_Round_zero:
break;
case FPI_Round_near:
if ((lostbits & 2)
&& ((lostbits & 1) | (x[0] & 1)))
up = 1;
break;
case FPI_Round_up:
up = 1 - sign;
break;
case FPI_Round_down:
up = sign;
}
if (up) {
k = b->_wds;
b = increment(ptr, b);
x = b->_x;
if (irv == STRTOG_Denormal) {
if (nbits == fpi->nbits - 1
&& x[nbits >> kshift] & 1 << (nbits & kmask))
irv = STRTOG_Normal;
}
else if ((b->_wds > k)
|| ((n = nbits & kmask) !=0
&& (hi0bits(x[k-1]) < 32-n))) {
rshift(b,1);
if (++e > fpi->emax)
goto ovfl;
}
irv |= STRTOG_Inexhi;
}
else
irv |= STRTOG_Inexlo;
}
*bp = b;
*exp = e;
return irv;
}

View File

@ -0,0 +1,142 @@
/****************************************************************
The author of this software is David M. Gay.
Copyright (C) 2000 by Lucent Technologies
All Rights Reserved
Permission to use, copy, modify, and distribute this software and
its documentation for any purpose and without fee is hereby
granted, provided that the above copyright notice appear in all
copies and that both that the copyright notice and this
permission notice and warranty disclaimer appear in supporting
documentation, and that the name of Lucent or any of its entities
not be used in advertising or publicity pertaining to
distribution of the software without specific, written prior
permission.
LUCENT DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS.
IN NO EVENT SHALL LUCENT OR ANY OF ITS ENTITIES BE LIABLE FOR ANY
SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER
IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF
THIS SOFTWARE.
****************************************************************/
/* Please send bug reports to
David M. Gay
Bell Laboratories, Room 2C-463
600 Mountain Avenue
Murray Hill, NJ 07974-0636
U.S.A.
dmg@bell-labs.com
*/
/* Modified 06-21-2006 by Jeff Johnston to work with newlib. */
#include <_ansi.h>
#include <reent.h>
#include <string.h>
#include "mprec.h"
#include "gdtoa.h"
#ifdef INFNAN_CHECK
static void
_DEFUN (L_shift, (x, x1, i),
__ULong *x _AND
__ULong *x1 _AND
int i)
{
int j;
i = 8 - i;
i <<= 2;
j = ULbits - i;
do {
*x |= x[1] << j;
x[1] >>= i;
} while(++x < x1);
}
int
_DEFUN (hexnan, (sp, fpi, x0),
_CONST char **sp _AND
FPI *fpi _AND
__ULong *x0)
{
__ULong c, h, *x, *x1, *xe;
_CONST char *s;
int havedig, hd0, i, nbits;
if (!hexdig['0'])
hexdig_init();
nbits = fpi->nbits;
x = x0 + (nbits >> kshift);
if (nbits & kmask)
x++;
*--x = 0;
x1 = xe = x;
havedig = hd0 = i = 0;
s = *sp;
while((c = *(_CONST unsigned char*)++s)) {
if (!(h = hexdig[c])) {
if (c <= ' ') {
if (hd0 < havedig) {
if (x < x1 && i < 8)
L_shift(x, x1, i);
if (x <= x0) {
i = 8;
continue;
}
hd0 = havedig;
*--x = 0;
x1 = x;
i = 0;
}
continue;
}
if (/*(*/ c == ')' && havedig) {
*sp = s + 1;
break;
}
return STRTOG_NaN;
}
havedig++;
if (++i > 8) {
if (x <= x0)
continue;
i = 1;
*--x = 0;
}
*x = ((*x << 4) | (h & 0xf));
}
if (!havedig)
return STRTOG_NaN;
if (x < x1 && i < 8)
L_shift(x, x1, i);
if (x > x0) {
x1 = x0;
do *x1++ = *x++;
while(x <= xe);
do *x1++ = 0;
while(x1 <= xe);
}
else {
/* truncate high-order word if necessary */
if ( (i = nbits & (ULbits-1)) !=0)
*xe &= ((__ULong)0xffffffff) >> (ULbits - i);
}
for(x1 = xe;; --x1) {
if (*x1 != 0)
break;
if (x1 == x0) {
*x1 = 1;
break;
}
}
return STRTOG_NaNbits;
}
#endif /* INFNAN_CHECK */

View File

@ -0,0 +1,72 @@
/****************************************************************
The author of this software is David M. Gay.
Copyright (C) 1998 by Lucent Technologies
All Rights Reserved
Permission to use, copy, modify, and distribute this software and
its documentation for any purpose and without fee is hereby
granted, provided that the above copyright notice appear in all
copies and that both that the copyright notice and this
permission notice and warranty disclaimer appear in supporting
documentation, and that the name of Lucent or any of its entities
not be used in advertising or publicity pertaining to
distribution of the software without specific, written prior
permission.
LUCENT DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS.
IN NO EVENT SHALL LUCENT OR ANY OF ITS ENTITIES BE LIABLE FOR ANY
SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER
IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF
THIS SOFTWARE.
****************************************************************/
/* Please send bug reports to David M. Gay (dmg at acm dot org,
* with " at " changed at "@" and " dot " changed to "."). */
#ifndef GDTOA_H_INCLUDED
#define GDTOA_H_INCLUDED
enum { /* return values from strtodg */
STRTOG_Zero = 0,
STRTOG_Normal = 1,
STRTOG_Denormal = 2,
STRTOG_Infinite = 3,
STRTOG_NaN = 4,
STRTOG_NaNbits = 5,
STRTOG_NoNumber = 6,
STRTOG_Retmask = 7,
/* The following may be or-ed into one of the above values. */
STRTOG_Neg = 0x08,
STRTOG_Inexlo = 0x10,
STRTOG_Inexhi = 0x20,
STRTOG_Inexact = 0x30,
STRTOG_Underflow= 0x40,
STRTOG_Overflow = 0x80
};
typedef struct
FPI {
int nbits;
int emin;
int emax;
int rounding;
int sudden_underflow;
} FPI;
enum { /* FPI.rounding values: same as FLT_ROUNDS */
FPI_Round_zero = 0,
FPI_Round_near = 1,
FPI_Round_up = 2,
FPI_Round_down = 3
};
#endif /* GDTOA_H_INCLUDED */

View File

@ -985,3 +985,61 @@ _DEFUN (_mprec_log10, (dig),
} }
return v; return v;
} }
void
_DEFUN (copybits, (c, n, b),
__ULong *c _AND
int n _AND
_Bigint *b)
{
__ULong *ce, *x, *xe;
#ifdef Pack_16
int nw, nw1;
#endif
ce = c + ((n-1) >> kshift) + 1;
x = b->_x;
#ifdef Pack_32
xe = x + b->_wds;
while(x < xe)
*c++ = *x++;
#else
nw = b->_wds;
nw1 = nw & 1;
for(xe = x + (nw - nw1); x < xe; x += 2)
Storeinc(c, x[1], x[0]);
if (nw1)
*c++ = *x;
#endif
while(c < ce)
*c++ = 0;
}
__ULong
_DEFUN (any_on, (b, k),
_Bigint *b _AND
int k)
{
int n, nwds;
__ULong *x, *x0, x1, x2;
x = b->_x;
nwds = b->_wds;
n = k >> kshift;
if (n > nwds)
n = nwds;
else if (n < nwds && (k &= kmask)) {
x1 = x2 = x[n];
x1 >>= k;
x1 <<= k;
if (x1 != x2)
return 1;
}
x0 = x;
x += n;
while(x > x0)
if (*--x)
return 1;
return 0;
}

View File

@ -78,6 +78,39 @@ union double_union
#define word1(x) (x.i[1]) #define word1(x) (x.i[1])
#endif #endif
/* The following is taken from gdtoaimp.h for use with new strtod. */
typedef __int32_t Long;
typedef union { double d; __ULong L[2]; } U;
#ifdef YES_ALIAS
#define dval(x) x
#ifdef IEEE_8087
#define dword0(x) ((__ULong *)&x)[1]
#define dword1(x) ((__ULong *)&x)[0]
#else
#define dword0(x) ((__ULong *)&x)[0]
#define dword1(x) ((__ULong *)&x)[1]
#endif
#else /* !YES_ALIAS */
#ifdef IEEE_8087
#define dword0(x) ((U*)&x)->L[1]
#define dword1(x) ((U*)&x)->L[0]
#else
#define dword0(x) ((U*)&x)->L[0]
#define dword1(x) ((U*)&x)->L[1]
#endif
#define dval(x) ((U*)&x)->d
#endif /* YES_ALIAS */
#undef SI
#ifdef Sudden_Underflow
#define SI 1
#else
#define SI 0
#endif
/* 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
* #define Storeinc(a,b,c) (*a++ = b << 16 | c & 0xffff) * #define Storeinc(a,b,c) (*a++ = b << 16 | c & 0xffff)
@ -161,12 +194,22 @@ union double_union
#define Quick_max 14 #define Quick_max 14
#define Int_max 14 #define Int_max 14
#define Infinite(x) (word0(x) == ((__uint32_t)0x7ff00000L)) /* sufficient test for here */ #define Infinite(x) (word0(x) == ((__uint32_t)0x7ff00000L)) /* sufficient test for here */
#ifndef Flt_Rounds
#ifdef FLT_ROUNDS
#define Flt_Rounds FLT_ROUNDS
#else
#define Flt_Rounds 1
#endif
#endif /*Flt_Rounds*/
#endif #endif
#else #else
#undef Sudden_Underflow #undef Sudden_Underflow
#define Sudden_Underflow #define Sudden_Underflow
#ifdef IBM #ifdef IBM
#define Flt_Rounds 0
#define Exp_shift 24 #define Exp_shift 24
#define Exp_shift1 24 #define Exp_shift1 24
#define Exp_msk1 ((__uint32_t)0x1000000L) #define Exp_msk1 ((__uint32_t)0x1000000L)
@ -191,6 +234,7 @@ union double_union
#define Quick_max 14 #define Quick_max 14
#define Int_max 15 #define Int_max 15
#else /* VAX */ #else /* VAX */
#define Flt_Rounds 1
#define Exp_shift 23 #define Exp_shift 23
#define Exp_shift1 7 #define Exp_shift1 7
#define Exp_msk1 0x80 #define Exp_msk1 0x80
@ -219,6 +263,58 @@ union double_union
#ifndef IEEE_Arith #ifndef IEEE_Arith
#define ROUND_BIASED #define ROUND_BIASED
#else
#define Scale_Bit 0x10
#if defined(_DOUBLE_IS_32BITS) && defined(__v800)
#define n_bigtens 2
#else
#define n_bigtens 5
#endif
#endif
#ifdef IBM
#define n_bigtens 3
#endif
#ifdef VAX
#define n_bigtens 2
#endif
#ifndef __NO_INFNAN_CHECK
#define INFNAN_CHECK
#endif
/*
* NAN_WORD0 and NAN_WORD1 are only referenced in strtod.c. Prior to
* 20050115, they used to be hard-wired here (to 0x7ff80000 and 0,
* respectively), but now are determined by compiling and running
* qnan.c to generate gd_qnan.h, which specifies d_QNAN0 and d_QNAN1.
* Formerly gdtoaimp.h recommended supplying suitable -DNAN_WORD0=...
* and -DNAN_WORD1=... values if necessary. This should still work.
* (On HP Series 700/800 machines, -DNAN_WORD0=0x7ff40000 works.)
*/
#ifdef IEEE_Arith
#ifdef IEEE_MC68k
#define _0 0
#define _1 1
#ifndef NAN_WORD0
#define NAN_WORD0 d_QNAN0
#endif
#ifndef NAN_WORD1
#define NAN_WORD1 d_QNAN1
#endif
#else
#define _0 1
#define _1 0
#ifndef NAN_WORD0
#define NAN_WORD0 d_QNAN1
#endif
#ifndef NAN_WORD1
#define NAN_WORD1 d_QNAN0
#endif
#endif
#else
#undef INFNAN_CHECK
#endif #endif
#ifdef RND_PRODQUOT #ifdef RND_PRODQUOT
@ -249,6 +345,17 @@ extern double rnd_prod(double, double), rnd_quot(double, double);
#endif #endif
#endif #endif
#ifdef Pack_32
#define ULbits 32
#define kshift 5
#define kmask 31
#define ALL_ON 0xffffffff
#else
#define ULbits 16
#define kshift 4
#define kmask 15
#define ALL_ON 0xffff
#endif
#ifdef __cplusplus #ifdef __cplusplus
extern "C" double strtod(const char *s00, char **se); extern "C" double strtod(const char *s00, char **se);
@ -261,26 +368,34 @@ typedef struct _Bigint _Bigint;
#define Balloc _Balloc #define Balloc _Balloc
#define Bfree _Bfree #define Bfree _Bfree
#define multadd _multadd #define multadd __multadd
#define s2b _s2b #define s2b __s2b
#define lo0bits _lo0bits #define lo0bits __lo0bits
#define hi0bits _hi0bits #define hi0bits __hi0bits
#define i2b _i2b #define i2b __i2b
#define mult _multiply #define mult __multiply
#define pow5mult _pow5mult #define pow5mult __pow5mult
#define lshift _lshift #define lshift __lshift
#define cmp __mcmp #define cmp __mcmp
#define diff __mdiff #define diff __mdiff
#define ulp _ulp #define ulp __ulp
#define b2d _b2d #define b2d __b2d
#define d2b _d2b #define d2b __d2b
#define ratio _ratio #define ratio __ratio
#define any_on __any_on
#define gethex __gethex
#define copybits __copybits
#define hexnan __hexnan
#define hexdig_init __hexdig_init
#define hexdig __hexdig
#define tens __mprec_tens #define tens __mprec_tens
#define bigtens __mprec_bigtens #define bigtens __mprec_bigtens
#define tinytens __mprec_tinytens #define tinytens __mprec_tinytens
struct _reent ; struct _reent ;
struct FPI;
double _EXFUN(ulp,(double x)); double _EXFUN(ulp,(double x));
double _EXFUN(b2d,(_Bigint *a , int *e)); double _EXFUN(b2d,(_Bigint *a , int *e));
_Bigint * _EXFUN(Balloc,(struct _reent *p, int k)); _Bigint * _EXFUN(Balloc,(struct _reent *p, int k));
@ -296,19 +411,21 @@ _Bigint * _EXFUN(d2b,(struct _reent *p, double d, int *e, int *bits));
_Bigint * _EXFUN(lshift,(struct _reent *p, _Bigint *b, int k)); _Bigint * _EXFUN(lshift,(struct _reent *p, _Bigint *b, int k));
_Bigint * _EXFUN(diff,(struct _reent *p, _Bigint *a, _Bigint *b)); _Bigint * _EXFUN(diff,(struct _reent *p, _Bigint *a, _Bigint *b));
int _EXFUN(cmp,(_Bigint *a, _Bigint *b)); int _EXFUN(cmp,(_Bigint *a, _Bigint *b));
int _EXFUN(gethex,(struct _reent *p, _CONST char **sp, struct FPI *fpi, Long *exp, _Bigint **bp, int sign));
double _EXFUN(ratio,(_Bigint *a, _Bigint *b)); double _EXFUN(ratio,(_Bigint *a, _Bigint *b));
#define Bcopy(x,y) memcpy((char *)&x->_sign, (char *)&y->_sign, y->_wds*sizeof(__Long) + 2*sizeof(int)) __ULong _EXFUN(any_on,(_Bigint *b, int k));
void _EXFUN(copybits,(__ULong *c, int n, _Bigint *b));
#if defined(_DOUBLE_IS_32BITS) && defined(__v800) void _EXFUN(hexdig_init,(void));
#define n_bigtens 2 #ifdef INFNAN_CHECK
#else int _EXFUN(hexnan,(_CONST char **sp, struct FPI *fpi, __ULong *x0));
#define n_bigtens 5
#endif #endif
#define Bcopy(x,y) memcpy((char *)&x->_sign, (char *)&y->_sign, y->_wds*sizeof(__Long) + 2*sizeof(int))
extern _CONST double tinytens[]; extern _CONST double tinytens[];
extern _CONST double bigtens[]; extern _CONST double bigtens[];
extern _CONST double tens[]; extern _CONST double tens[];
extern unsigned char hexdig[];
double _EXFUN(_mprec_log10,(int)); double _EXFUN(_mprec_log10,(int));

File diff suppressed because it is too large Load Diff