diff options
author | Takashi Yano <takashi.yano@nifty.ne.jp> | 2021-12-01 00:11:32 +0300 |
---|---|---|
committer | Takashi Yano <takashi.yano@nifty.ne.jp> | 2021-12-03 13:20:17 +0300 |
commit | a4705d387f7874f9a5de3ee67861773a17691643 (patch) | |
tree | 31d03557be1b010bf3511edef48321fb2c7341d6 /newlib/libc | |
parent | 34876c05a527a7295920979fce69cec6b4cb613c (diff) |
ldtoa: Import gdtoa from OpenBSD.
- This patch uses gdtoa imported from OpenBSD if newlib configure
option "--enable-newlib-use-gdtoa=no" is NOT specified. gdtoa
provides more accurate output and faster conversion than legacy
ldtoa, while it requires more heap memory.
Diffstat (limited to 'newlib/libc')
-rw-r--r-- | newlib/libc/include/machine/ieee.h | 127 | ||||
-rw-r--r-- | newlib/libc/include/sys/config.h | 6 | ||||
-rw-r--r-- | newlib/libc/stdlib/Makefile.am | 10 | ||||
-rw-r--r-- | newlib/libc/stdlib/Makefile.in | 51 | ||||
-rw-r--r-- | newlib/libc/stdlib/gdtoa-dmisc.c | 230 | ||||
-rw-r--r-- | newlib/libc/stdlib/gdtoa-gdtoa.c | 837 | ||||
-rw-r--r-- | newlib/libc/stdlib/gdtoa-gmisc.c | 91 | ||||
-rw-r--r-- | newlib/libc/stdlib/gdtoa-ldtoa.c | 159 | ||||
-rw-r--r-- | newlib/libc/stdlib/gdtoa.h | 130 | ||||
-rw-r--r-- | newlib/libc/stdlib/gdtoaimp.h | 206 | ||||
-rw-r--r-- | newlib/libc/stdlib/ldtoa.c | 6 | ||||
-rw-r--r-- | newlib/libc/stdlib/mprec.h | 2 |
12 files changed, 1828 insertions, 27 deletions
diff --git a/newlib/libc/include/machine/ieee.h b/newlib/libc/include/machine/ieee.h new file mode 100644 index 000000000..0656909ab --- /dev/null +++ b/newlib/libc/include/machine/ieee.h @@ -0,0 +1,127 @@ +#ifndef _MACHINE_IEEE_H_ +#define _MACHINE_IEEE_H_ +#include <sys/types.h> +#include <sys/cdefs.h> +#include <machine/ieeefp.h> +#include <float.h> + +#if LDBL_MANT_DIG == 24 +#define EXT_IMPLICIT_NBIT +#define EXT_TO_ARRAY32(p, a) do { \ + (a)[0] = (p)->ext_frac; \ +} while (0) +#ifdef __IEEE_LITTLE_ENDIAN +struct ieee_ext { + uint32_t ext_frac:23; + uint32_t ext_exp:8; + uint32_t ext_sign:1; +}; +#endif +#ifdef __IEEE_BIG_ENDIAN +struct ieee_ext { +#ifndef ___IEEE_BYTES_LITTLE_ENDIAN + uint32_t ext_sign:1; + uint32_t ext_exp:8; + uint32_t ext_frac:23; +#else /* ARMEL without __VFP_FP__ */ + uint32_t ext_frac:23; + uint32_t ext_exp:8; + uint32_t ext_sign:1; +#endif +}; +#endif +#elif LDBL_MANT_DIG == 53 +#define EXT_IMPLICIT_NBIT +#define EXT_TO_ARRAY32(p, a) do { \ + (a)[0] = (p)->ext_fracl; \ + (a)[1] = (p)->ext_frach; \ +} while (0) +#ifdef __IEEE_LITTLE_ENDIAN +struct ieee_ext { + uint32_t ext_fracl; + uint32_t ext_frach:20; + uint32_t ext_exp:11; + uint32_t ext_sign:1; +}; +#endif +#ifdef __IEEE_BIG_ENDIAN +struct ieee_ext { +#ifndef ___IEEE_BYTES_LITTLE_ENDIAN + uint32_t ext_sign:1; + uint32_t ext_exp:11; + uint32_t ext_frach:20; +#else /* ARMEL without __VFP_FP__ */ + uint32_t ext_frach:20; + uint32_t ext_exp:11; + uint32_t ext_sign:1; +#endif + uint32_t ext_fracl; +}; +#endif +#elif LDBL_MANT_DIG == 64 +#define EXT_TO_ARRAY32(p, a) do { \ + (a)[0] = (p)->ext_fracl; \ + (a)[1] = (p)->ext_frach; \ +} while (0) +#ifdef __IEEE_LITTLE_ENDIAN /* for Intel CPU */ +struct ieee_ext { + uint32_t ext_fracl; + uint32_t ext_frach; + uint32_t ext_exp:15; + uint32_t ext_sign:1; + uint32_t ext_padl:16; + uint32_t ext_padh; +}; +#endif +#ifdef __IEEE_BIG_ENDIAN +struct ieee_ext { +#ifndef ___IEEE_BYTES_LITTLE_ENDIAN /* for m68k */ + uint32_t ext_sign:1; + uint32_t ext_exp:15; + uint32_t ext_pad:16; +#else /* ARM FPA10 math coprocessor */ + uint32_t ext_exp:15; + uint32_t ext_pad:16; + uint32_t ext_sign:1; +#endif + uint32_t ext_frach; + uint32_t ext_fracl; +}; +#endif +#elif LDBL_MANT_DIG == 113 +#define EXT_IMPLICIT_NBIT +#define EXT_TO_ARRAY32(p, a) do { \ + (a)[0] = (p)->ext_fracl; \ + (a)[1] = (p)->ext_fraclm; \ + (a)[2] = (p)->ext_frachm; \ + (a)[3] = (p)->ext_frach; \ +} while (0) +#ifdef __IEEE_LITTLE_ENDIAN +struct ieee_ext { + uint32_t ext_fracl; + uint32_t ext_fraclm; + uint32_t ext_frachm; + uint32_t ext_frach:16; + uint32_t ext_exp:15; + uint32_t ext_sign:1; +}; +#endif +#ifdef __IEEE_BIG_ENDIAN +struct ieee_ext { +#ifndef ___IEEE_BYTES_LITTLE_ENDIAN + uint32_t ext_sign:1; + uint32_t ext_exp:15; + uint32_t ext_frach:16; +#else /* ARMEL without __VFP_FP__ */ + uint32_t ext_frach:16; + uint32_t ext_exp:15; + uint32_t ext_sign:1; +#endif + uint32_t ext_frachm; + uint32_t ext_fraclm; + uint32_t ext_fracl; +}; +#endif +#endif + +#endif /* _MACHINE_IEEE_H_ */ diff --git a/newlib/libc/include/sys/config.h b/newlib/libc/include/sys/config.h index b9dff88ff..61a6f95d8 100644 --- a/newlib/libc/include/sys/config.h +++ b/newlib/libc/include/sys/config.h @@ -293,6 +293,12 @@ #endif #endif +#ifdef _WANT_USE_GDTOA +#ifndef _USE_GDTOA +#define _USE_GDTOA +#endif +#endif + /* If _MB_EXTENDED_CHARSETS_ALL is set, we want all of the extended charsets. The extended charsets add a few functions and a couple of tables of a few K each. */ diff --git a/newlib/libc/stdlib/Makefile.am b/newlib/libc/stdlib/Makefile.am index 357e37beb..2f46c837c 100644 --- a/newlib/libc/stdlib/Makefile.am +++ b/newlib/libc/stdlib/Makefile.am @@ -38,6 +38,10 @@ GENERAL_SOURCES = \ labs.c \ ldiv.c \ ldtoa.c \ + gdtoa-ldtoa.c \ + gdtoa-gdtoa.c \ + gdtoa-dmisc.c \ + gdtoa-gmisc.c \ malloc.c \ mblen.c \ mblen_r.c \ @@ -311,7 +315,11 @@ CHEWOUT_FILES= \ CHAPTERS = stdlib.tex $(lpfx)dtoa.$(oext): dtoa.c mprec.h -$(lpfx)ldtoa.$(oext): ldtoa.c mprec.h +$(lpfx)ldtoa.$(oext): ldtoa.c mprec.h gdtoa.h +$(lpfx)gdtoa-ldtoa.$(oext): gdtoa-ldtoa.c mprec.h gdtoaimp.h gdtoa.h +$(lpfx)gdtoa-gdtoa.$(oext): gdtoa-gdtoa.c mprec.h gdtoaimp.h gdtoa.h +$(lpfx)gdtoa-dmisc.$(oext): gdtoa-dmisc.c mprec.h gdtoaimp.h gdtoa.h +$(lpfx)gdtoa-gmisc.$(oext): gdtoa-gmisc.c mprec.h gdtoaimp.h gdtoa.h $(lpfx)ecvtbuf.$(oext): ecvtbuf.c mprec.h $(lpfx)mbtowc_r.$(oext): mbtowc_r.c mbctype.h $(lpfx)mprec.$(oext): mprec.c mprec.h diff --git a/newlib/libc/stdlib/Makefile.in b/newlib/libc/stdlib/Makefile.in index a812b6a95..7d3342a67 100644 --- a/newlib/libc/stdlib/Makefile.in +++ b/newlib/libc/stdlib/Makefile.in @@ -101,7 +101,9 @@ am__objects_2 = lib_a-__adjust.$(OBJEXT) lib_a-__atexit.$(OBJEXT) \ lib_a-getenv_r.$(OBJEXT) lib_a-imaxabs.$(OBJEXT) \ lib_a-imaxdiv.$(OBJEXT) lib_a-itoa.$(OBJEXT) \ lib_a-labs.$(OBJEXT) lib_a-ldiv.$(OBJEXT) \ - lib_a-ldtoa.$(OBJEXT) lib_a-malloc.$(OBJEXT) \ + lib_a-ldtoa.$(OBJEXT) lib_a-gdtoa-ldtoa.$(OBJEXT) \ + lib_a-gdtoa-gdtoa.$(OBJEXT) lib_a-gdtoa-dmisc.$(OBJEXT) \ + lib_a-gdtoa-gmisc.$(OBJEXT) lib_a-malloc.$(OBJEXT) \ lib_a-mblen.$(OBJEXT) lib_a-mblen_r.$(OBJEXT) \ lib_a-mbstowcs.$(OBJEXT) lib_a-mbstowcs_r.$(OBJEXT) \ lib_a-mbtowc.$(OBJEXT) lib_a-mbtowc_r.$(OBJEXT) \ @@ -165,6 +167,7 @@ am__objects_9 = __adjust.lo __atexit.lo __call_atexit.lo __exp10.lo \ div.lo dtoa.lo dtoastub.lo environ.lo envlock.lo eprintf.lo \ exit.lo gdtoa-gethex.lo gdtoa-hexnan.lo getenv.lo getenv_r.lo \ imaxabs.lo imaxdiv.lo itoa.lo labs.lo ldiv.lo ldtoa.lo \ + gdtoa-ldtoa.lo gdtoa-gdtoa.lo gdtoa-dmisc.lo gdtoa-gmisc.lo \ malloc.lo mblen.lo mblen_r.lo mbstowcs.lo mbstowcs_r.lo \ mbtowc.lo mbtowc_r.lo mlock.lo mprec.lo mstats.lo \ on_exit_args.lo quick_exit.lo rand.lo rand_r.lo random.lo \ @@ -354,6 +357,7 @@ pdfdir = @pdfdir@ prefix = @prefix@ program_transform_name = @program_transform_name@ psdir = @psdir@ +runstatedir = @runstatedir@ sbindir = @sbindir@ shared_machine_dir = @shared_machine_dir@ sharedstatedir = @sharedstatedir@ @@ -372,13 +376,14 @@ GENERAL_SOURCES = __adjust.c __atexit.c __call_atexit.c __exp10.c \ atexit.c atof.c atoff.c atoi.c atol.c calloc.c div.c dtoa.c \ dtoastub.c environ.c envlock.c eprintf.c exit.c gdtoa-gethex.c \ gdtoa-hexnan.c getenv.c getenv_r.c imaxabs.c imaxdiv.c itoa.c \ - labs.c ldiv.c ldtoa.c malloc.c mblen.c mblen_r.c mbstowcs.c \ - mbstowcs_r.c mbtowc.c mbtowc_r.c mlock.c mprec.c mstats.c \ - on_exit_args.c quick_exit.c rand.c rand_r.c random.c realloc.c \ - reallocarray.c reallocf.c sb_charsets.c strtod.c strtoimax.c \ - strtol.c strtoul.c strtoumax.c utoa.c wcstod.c wcstoimax.c \ - wcstol.c wcstoul.c wcstoumax.c wcstombs.c wcstombs_r.c \ - wctomb.c wctomb_r.c $(am__append_1) + labs.c ldiv.c ldtoa.c gdtoa-ldtoa.c gdtoa-gdtoa.c \ + gdtoa-dmisc.c gdtoa-gmisc.c malloc.c mblen.c mblen_r.c \ + mbstowcs.c mbstowcs_r.c mbtowc.c mbtowc_r.c mlock.c mprec.c \ + mstats.c on_exit_args.c quick_exit.c rand.c rand_r.c random.c \ + realloc.c reallocarray.c reallocf.c sb_charsets.c strtod.c \ + strtoimax.c strtol.c strtoul.c strtoumax.c utoa.c wcstod.c \ + wcstoimax.c wcstol.c wcstoul.c wcstoumax.c wcstombs.c \ + wcstombs_r.c wctomb.c wctomb_r.c $(am__append_1) @NEWLIB_NANO_MALLOC_FALSE@MALIGNR = malignr @NEWLIB_NANO_MALLOC_TRUE@MALIGNR = nano-malignr @NEWLIB_NANO_MALLOC_FALSE@MALLOPTR = malloptr @@ -827,6 +832,30 @@ lib_a-ldtoa.o: ldtoa.c lib_a-ldtoa.obj: ldtoa.c $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(lib_a_CFLAGS) $(CFLAGS) -c -o lib_a-ldtoa.obj `if test -f 'ldtoa.c'; then $(CYGPATH_W) 'ldtoa.c'; else $(CYGPATH_W) '$(srcdir)/ldtoa.c'; fi` +lib_a-gdtoa-ldtoa.o: gdtoa-ldtoa.c + $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(lib_a_CFLAGS) $(CFLAGS) -c -o lib_a-gdtoa-ldtoa.o `test -f 'gdtoa-ldtoa.c' || echo '$(srcdir)/'`gdtoa-ldtoa.c + +lib_a-gdtoa-ldtoa.obj: gdtoa-ldtoa.c + $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(lib_a_CFLAGS) $(CFLAGS) -c -o lib_a-gdtoa-ldtoa.obj `if test -f 'gdtoa-ldtoa.c'; then $(CYGPATH_W) 'gdtoa-ldtoa.c'; else $(CYGPATH_W) '$(srcdir)/gdtoa-ldtoa.c'; fi` + +lib_a-gdtoa-gdtoa.o: gdtoa-gdtoa.c + $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(lib_a_CFLAGS) $(CFLAGS) -c -o lib_a-gdtoa-gdtoa.o `test -f 'gdtoa-gdtoa.c' || echo '$(srcdir)/'`gdtoa-gdtoa.c + +lib_a-gdtoa-gdtoa.obj: gdtoa-gdtoa.c + $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(lib_a_CFLAGS) $(CFLAGS) -c -o lib_a-gdtoa-gdtoa.obj `if test -f 'gdtoa-gdtoa.c'; then $(CYGPATH_W) 'gdtoa-gdtoa.c'; else $(CYGPATH_W) '$(srcdir)/gdtoa-gdtoa.c'; fi` + +lib_a-gdtoa-dmisc.o: gdtoa-dmisc.c + $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(lib_a_CFLAGS) $(CFLAGS) -c -o lib_a-gdtoa-dmisc.o `test -f 'gdtoa-dmisc.c' || echo '$(srcdir)/'`gdtoa-dmisc.c + +lib_a-gdtoa-dmisc.obj: gdtoa-dmisc.c + $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(lib_a_CFLAGS) $(CFLAGS) -c -o lib_a-gdtoa-dmisc.obj `if test -f 'gdtoa-dmisc.c'; then $(CYGPATH_W) 'gdtoa-dmisc.c'; else $(CYGPATH_W) '$(srcdir)/gdtoa-dmisc.c'; fi` + +lib_a-gdtoa-gmisc.o: gdtoa-gmisc.c + $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(lib_a_CFLAGS) $(CFLAGS) -c -o lib_a-gdtoa-gmisc.o `test -f 'gdtoa-gmisc.c' || echo '$(srcdir)/'`gdtoa-gmisc.c + +lib_a-gdtoa-gmisc.obj: gdtoa-gmisc.c + $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(lib_a_CFLAGS) $(CFLAGS) -c -o lib_a-gdtoa-gmisc.obj `if test -f 'gdtoa-gmisc.c'; then $(CYGPATH_W) 'gdtoa-gmisc.c'; else $(CYGPATH_W) '$(srcdir)/gdtoa-gmisc.c'; fi` + lib_a-malloc.o: malloc.c $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(lib_a_CFLAGS) $(CFLAGS) -c -o lib_a-malloc.o `test -f 'malloc.c' || echo '$(srcdir)/'`malloc.c @@ -1610,7 +1639,11 @@ $(lpfx)$(MALLOPTR).$(oext): $(MALLOCR).c $(MALLOC_COMPILE) -DDEFINE_MALLOPT -c $(srcdir)/$(MALLOCR).c -o $@ $(lpfx)dtoa.$(oext): dtoa.c mprec.h -$(lpfx)ldtoa.$(oext): ldtoa.c mprec.h +$(lpfx)ldtoa.$(oext): ldtoa.c mprec.h gdtoa.h +$(lpfx)gdtoa-ldtoa.$(oext): gdtoa-ldtoa.c mprec.h gdtoaimp.h gdtoa.h +$(lpfx)gdtoa-gdtoa.$(oext): gdtoa-gdtoa.c mprec.h gdtoaimp.h gdtoa.h +$(lpfx)gdtoa-dmisc.$(oext): gdtoa-dmisc.c mprec.h gdtoaimp.h gdtoa.h +$(lpfx)gdtoa-gmisc.$(oext): gdtoa-gmisc.c mprec.h gdtoaimp.h gdtoa.h $(lpfx)ecvtbuf.$(oext): ecvtbuf.c mprec.h $(lpfx)mbtowc_r.$(oext): mbtowc_r.c mbctype.h $(lpfx)mprec.$(oext): mprec.c mprec.h diff --git a/newlib/libc/stdlib/gdtoa-dmisc.c b/newlib/libc/stdlib/gdtoa-dmisc.c new file mode 100644 index 000000000..332023dae --- /dev/null +++ b/newlib/libc/stdlib/gdtoa-dmisc.c @@ -0,0 +1,230 @@ +/**************************************************************** + +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 <newlib.h> +#include <sys/config.h> + +#ifdef _USE_GDTOA +#include "gdtoaimp.h" + +#ifndef MULTIPLE_THREADS + char *dtoa_result; +#endif + + char * +#ifdef KR_headers +rv_alloc(ptr, i) struct _reent *ptr, int i; +#else +rv_alloc(struct _reent *ptr, int i) +#endif +{ + int j, k, *r; + + j = sizeof(ULong); + for(k = 0; + sizeof(Bigint) - sizeof(ULong) - sizeof(int) + j <= i; + j <<= 1) + k++; + r = (int*)Balloc(ptr, k); + if (r == NULL) + return ( +#ifndef MULTIPLE_THREADS + dtoa_result = +#endif + NULL); + *r = k; + return +#ifndef MULTIPLE_THREADS + dtoa_result = +#endif + (char *)(r+1); + } + + char * +#ifdef KR_headers +nrv_alloc(ptr, s, rve, n) struct _reent *ptr, char *s, **rve; int n; +#else +nrv_alloc(struct _reent *ptr, char *s, char **rve, int n) +#endif +{ + char *rv, *t; + + t = rv = rv_alloc(ptr, n); + if (t == NULL) + return (NULL); + while((*t = *s++) !=0) + t++; + if (rve) + *rve = t; + return rv; + } + +/* freedtoa(s) must be used to free values s returned by dtoa + * when MULTIPLE_THREADS is #defined. It should be used in all cases, + * but for consistency with earlier versions of dtoa, it is optional + * when MULTIPLE_THREADS is not defined. + */ + + void +#ifdef KR_headers +freedtoa(ptr, s) struct _reent *ptr, char *s; +#else +freedtoa(struct _reent *ptr, char *s) +#endif +{ + Bigint *b = (Bigint *)((int *)s - 1); + b->_maxwds = 1 << (b->_k = *(int*)b); + Bfree(ptr, b); +#ifndef MULTIPLE_THREADS + if (s == dtoa_result) + dtoa_result = 0; +#endif + } +DEF_STRONG(freedtoa); + + int +quorem +#ifdef KR_headers + (b, S) Bigint *b, *S; +#else + (Bigint *b, Bigint *S) +#endif +{ + int n; + ULong *bx, *bxe, q, *sx, *sxe; +#ifdef ULLong + ULLong borrow, carry, y, ys; +#else + ULong borrow, carry, y, ys; +#ifdef Pack_32 + ULong si, z, zs; +#endif +#endif + + n = S->_wds; +#ifdef DEBUG + /*debug*/ if (b->_wds > n) + /*debug*/ Bug("oversize b in quorem"); +#endif + if (b->_wds < n) + return 0; + sx = S->_x; + sxe = sx + --n; + bx = b->_x; + bxe = bx + n; + q = *bxe / (*sxe + 1); /* ensure q <= true quotient */ +#ifdef DEBUG + /*debug*/ if (q > 9) + /*debug*/ Bug("oversized quotient in quorem"); +#endif + if (q) { + borrow = 0; + carry = 0; + do { +#ifdef ULLong + ys = *sx++ * (ULLong)q + carry; + carry = ys >> 32; + y = *bx - (ys & 0xffffffffUL) - borrow; + borrow = y >> 32 & 1UL; + *bx++ = y & 0xffffffffUL; +#else +#ifdef Pack_32 + si = *sx++; + ys = (si & 0xffff) * q + carry; + zs = (si >> 16) * q + (ys >> 16); + carry = zs >> 16; + y = (*bx & 0xffff) - (ys & 0xffff) - borrow; + borrow = (y & 0x10000) >> 16; + z = (*bx >> 16) - (zs & 0xffff) - borrow; + borrow = (z & 0x10000) >> 16; + Storeinc(bx, z, y); +#else + ys = *sx++ * q + carry; + carry = ys >> 16; + y = *bx - (ys & 0xffff) - borrow; + borrow = (y & 0x10000) >> 16; + *bx++ = y & 0xffff; +#endif +#endif + } + while(sx <= sxe); + if (!*bxe) { + bx = b->_x; + while(--bxe > bx && !*bxe) + --n; + b->_wds = n; + } + } + if (cmp(b, S) >= 0) { + q++; + borrow = 0; + carry = 0; + bx = b->_x; + sx = S->_x; + do { +#ifdef ULLong + ys = *sx++ + carry; + carry = ys >> 32; + y = *bx - (ys & 0xffffffffUL) - borrow; + borrow = y >> 32 & 1UL; + *bx++ = y & 0xffffffffUL; +#else +#ifdef Pack_32 + si = *sx++; + ys = (si & 0xffff) + carry; + zs = (si >> 16) + (ys >> 16); + carry = zs >> 16; + y = (*bx & 0xffff) - (ys & 0xffff) - borrow; + borrow = (y & 0x10000) >> 16; + z = (*bx >> 16) - (zs & 0xffff) - borrow; + borrow = (z & 0x10000) >> 16; + Storeinc(bx, z, y); +#else + ys = *sx++ + carry; + carry = ys >> 16; + y = *bx - (ys & 0xffff) - borrow; + borrow = (y & 0x10000) >> 16; + *bx++ = y & 0xffff; +#endif +#endif + } + while(sx <= sxe); + bx = b->_x; + bxe = bx + n; + if (!*bxe) { + while(--bxe > bx && !*bxe) + --n; + b->_wds = n; + } + } + return q; + } +#endif /* _USE_GDTOA */ diff --git a/newlib/libc/stdlib/gdtoa-gdtoa.c b/newlib/libc/stdlib/gdtoa-gdtoa.c new file mode 100644 index 000000000..da2338c48 --- /dev/null +++ b/newlib/libc/stdlib/gdtoa-gdtoa.c @@ -0,0 +1,837 @@ +/**************************************************************** + +The author of this software is David M. Gay. + +Copyright (C) 1998, 1999 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 <newlib.h> +#include <sys/config.h> + +#ifdef _USE_GDTOA +#include "gdtoaimp.h" + + static Bigint * +#ifdef KR_headers +bitstob(ptr, bits, nbits, bbits) ULong *bits; +struct _reent ptr, int nbits; int *bbits; +#else +bitstob(struct _reent *ptr, ULong *bits, int nbits, int *bbits) +#endif +{ + int i, k; + Bigint *b; + ULong *be, *x, *x0; + + i = ULbits; + k = 0; + while(i < nbits) { + i <<= 1; + k++; + } +#ifndef Pack_32 + if (!k) + k = 1; +#endif + b = Balloc(ptr, k); + if (b == NULL) + return (NULL); + be = bits + ((nbits - 1) >> kshift); + x = x0 = b->_x; + do { + *x++ = *bits & ALL_ON; +#ifdef Pack_16 + *x++ = (*bits >> 16) & ALL_ON; +#endif + } while(++bits <= be); + i = x - x0; + while(!x0[--i]) + if (!i) { + b->_wds = 0; + *bbits = 0; + goto ret; + } + b->_wds = i + 1; + *bbits = i*ULbits + 32 - hi0bits(b->_x[i]); + ret: + return b; + } + +/* dtoa for IEEE arithmetic (dmg): convert double to ASCII string. + * + * Inspired by "How to Print Floating-Point Numbers Accurately" by + * Guy L. Steele, Jr. and Jon L. White [Proc. ACM SIGPLAN '90, pp. 112-126]. + * + * Modifications: + * 1. Rather than iterating, we use a simple numeric overestimate + * to determine k = floor(log10(d)). We scale relevant + * quantities using O(log2(k)) rather than O(k) multiplications. + * 2. For some modes > 2 (corresponding to ecvt and fcvt), we don't + * try to generate digits strictly left to right. Instead, we + * compute with fewer bits and propagate the carry if necessary + * when rounding the final digit up. This is often faster. + * 3. Under the assumption that input will be rounded nearest, + * mode 0 renders 1e23 as 1e23 rather than 9.999999999999999e22. + * That is, we allow equality in stopping tests when the + * round-nearest rule will give the same floating-point value + * as would satisfaction of the stopping test with strict + * inequality. + * 4. We remove common factors of powers of 2 from relevant + * quantities. + * 5. When converting floating-point integers less than 1e16, + * we use floating-point arithmetic rather than resorting + * to multiple-precision integers. + * 6. When asked to produce fewer than 15 digits, we first try + * to get by with floating-point arithmetic; we resort to + * multiple-precision integer arithmetic only if we cannot + * guarantee that the floating-point calculation has given + * the correctly rounded result. For k requested digits and + * "uniformly" distributed input, the probability is + * something like 10^(k-15) that we must resort to the Long + * calculation. + */ + + char * +gdtoa +#ifdef KR_headers + (ptr, fpi, be, bits, kindp, mode, ndigits, decpt, rve) + struct _reent *ptr, FPI *fpi; int be; ULong *bits; + int *kindp, mode, ndigits, *decpt; char **rve; +#else + (struct _reent *ptr, FPI *fpi, int be, ULong *bits, int *kindp, + int mode, int ndigits, int *decpt, char **rve) +#endif +{ + /* Arguments ndigits and decpt are similar to the second and third + arguments of ecvt and fcvt; trailing zeros are suppressed from + the returned string. If not null, *rve is set to point + to the end of the return value. If d is +-Infinity or NaN, + then *decpt is set to 9999. + be = exponent: value = (integer represented by bits) * (2 to the power of be). + + mode: + 0 ==> shortest string that yields d when read in + and rounded to nearest. + 1 ==> like 0, but with Steele & White stopping rule; + e.g. with IEEE P754 arithmetic , mode 0 gives + 1e23 whereas mode 1 gives 9.999999999999999e22. + 2 ==> max(1,ndigits) significant digits. This gives a + return value similar to that of ecvt, except + that trailing zeros are suppressed. + 3 ==> through ndigits past the decimal point. This + gives a return value similar to that from fcvt, + except that trailing zeros are suppressed, and + ndigits can be negative. + 4-9 should give the same return values as 2-3, i.e., + 4 <= mode <= 9 ==> same return as mode + 2 + (mode & 1). These modes are mainly for + debugging; often they run slower but sometimes + faster than modes 2-3. + 4,5,8,9 ==> left-to-right digit generation. + 6-9 ==> don't try fast floating-point estimate + (if applicable). + + Values of mode other than 0-9 are treated as mode 0. + + Sufficient space is allocated to the return value + to hold the suppressed trailing zeros. + */ + + int bbits, b2, b5, be0, dig, i, ieps, ilim, ilim0, ilim1, inex; + int j, j1, k, k0, k_check, kind, leftright, m2, m5, nbits; + int rdir, s2, s5, spec_case, try_quick; + Long L; + Bigint *b, *b1, *delta, *mlo, *mhi, *mhi1, *S; + double d2, ds; + char *s, *s0; + U d, eps; + +#ifndef MULTIPLE_THREADS + if (dtoa_result) { + freedtoa(ptr, dtoa_result); + dtoa_result = 0; + } +#endif + inex = 0; + kind = *kindp &= ~STRTOG_Inexact; + switch(kind & STRTOG_Retmask) { + case STRTOG_Zero: + goto ret_zero; + case STRTOG_Normal: + case STRTOG_Denormal: + break; + case STRTOG_Infinite: + *decpt = -32768; + return nrv_alloc(ptr, "Infinity", rve, 8); + case STRTOG_NaN: + *decpt = -32768; + return nrv_alloc(ptr, "NaN", rve, 3); + default: + return 0; + } + b = bitstob(ptr, bits, nbits = fpi->nbits, &bbits); + if (b == NULL) + return (NULL); + be0 = be; + if ( (i = trailz(b)) !=0) { + rshift(b, i); + be += i; + bbits -= i; + } + if (!b->_wds) { + Bfree(ptr, b); + ret_zero: + *decpt = 1; + return nrv_alloc(ptr, "0", rve, 1); + } + + dval(d) = b2d(b, &i); + i = be + bbits - 1; + word0(d) &= Frac_mask1; + word0(d) |= Exp_11; +#ifdef IBM + if ( (j = 11 - hi0bits(word0(d) & Frac_mask)) !=0) + dval(d) /= 1 << j; +#endif + + /* log(x) ~=~ log(1.5) + (x-1.5)/1.5 + * log10(x) = log(x) / log(10) + * ~=~ log(1.5)/log(10) + (x-1.5)/(1.5*log(10)) + * log10(&d) = (i-Bias)*log(2)/log(10) + log10(d2) + * + * This suggests computing an approximation k to log10(&d) by + * + * k = (i - Bias)*0.301029995663981 + * + ( (d2-1.5)*0.289529654602168 + 0.176091259055681 ); + * + * We want k to be too large rather than too small. + * The error in the first-order Taylor series approximation + * is in our favor, so we just round up the constant enough + * to compensate for any error in the multiplication of + * (i - Bias) by 0.301029995663981; since |i - Bias| <= 1077, + * and 1077 * 0.30103 * 2^-52 ~=~ 7.2e-14, + * adding 1e-13 to the constant term more than suffices. + * Hence we adjust the constant term to 0.1760912590558. + * (We could get a more accurate k by invoking log10, + * but this is probably not worthwhile.) + */ +#ifdef IBM + i <<= 2; + i += j; +#endif + ds = (dval(d)-1.5)*0.289529654602168 + 0.1760912590558 + i*0.301029995663981; + + /* correct assumption about exponent range */ + if ((j = i) < 0) + j = -j; + if ((j -= 1077) > 0) + ds += j * 7e-17; + + k = (int)ds; + if (ds < 0. && ds != k) + k--; /* want k = floor(ds) */ + k_check = 1; +#ifdef IBM + j = be + bbits - 1; + if ( (j1 = j & 3) !=0) + dval(d) *= 1 << j1; + word0(d) += j << Exp_shift - 2 & Exp_mask; +#else + word0(d) += (be + bbits - 1) << Exp_shift; +#endif + if (k >= 0 && k <= Ten_pmax) { + if (dval(d) < tens[k]) + k--; + k_check = 0; + } + j = bbits - i - 1; + if (j >= 0) { + b2 = 0; + s2 = j; + } + else { + b2 = -j; + s2 = 0; + } + if (k >= 0) { + b5 = 0; + s5 = k; + s2 += k; + } + else { + b2 -= k; + b5 = -k; + s5 = 0; + } + if (mode < 0 || mode > 9) + mode = 0; + try_quick = 1; + if (mode > 5) { + mode -= 4; + try_quick = 0; + } + else if (i >= -4 - Emin || i < Emin) + try_quick = 0; + leftright = 1; + ilim = ilim1 = -1; /* Values for cases 0 and 1; done here to */ + /* silence erroneous "gcc -Wall" warning. */ + switch(mode) { + case 0: + case 1: + i = (int)(nbits * .30103) + 3; + ndigits = 0; + break; + case 2: + leftright = 0; + /* no break */ + case 4: + if (ndigits <= 0) + ndigits = 1; + ilim = ilim1 = i = ndigits; + break; + case 3: + leftright = 0; + /* no break */ + case 5: + i = ndigits + k + 1; + ilim = i; + ilim1 = i - 1; + if (i <= 0) + i = 1; + } + s = s0 = rv_alloc(ptr, i); + if (s == NULL) + return (NULL); + + if ( (rdir = fpi->rounding - 1) !=0) { + if (rdir < 0) + rdir = 2; + if (kind & STRTOG_Neg) + rdir = 3 - rdir; + } + + /* Now rdir = 0 ==> round near, 1 ==> round up, 2 ==> round down. */ + + if (ilim >= 0 && ilim <= Quick_max && try_quick && !rdir +#ifndef IMPRECISE_INEXACT + && k == 0 +#endif + ) { + + /* Try to get by with floating-point arithmetic. */ + + i = 0; + d2 = dval(d); +#ifdef IBM + if ( (j = 11 - hi0bits(word0(d) & Frac_mask)) !=0) + dval(d) /= 1 << j; +#endif + k0 = k; + ilim0 = ilim; + ieps = 2; /* conservative */ + if (k > 0) { + ds = tens[k&0xf]; + j = k >> 4; + if (j & Bletch) { + /* prevent overflows */ + j &= Bletch - 1; + dval(d) /= bigtens[n_bigtens-1]; + ieps++; + } + for(; j; j >>= 1, i++) + if (j & 1) { + ieps++; + ds *= bigtens[i]; + } + } + else { + ds = 1.; + if ( (j1 = -k) !=0) { + dval(d) *= tens[j1 & 0xf]; + for(j = j1 >> 4; j; j >>= 1, i++) + if (j & 1) { + ieps++; + dval(d) *= bigtens[i]; + } + } + } + if (k_check && dval(d) < 1. && ilim > 0) { + if (ilim1 <= 0) + goto fast_failed; + ilim = ilim1; + k--; + dval(d) *= 10.; + ieps++; + } + dval(eps) = ieps*dval(d) + 7.; + word0(eps) -= (P-1)*Exp_msk1; + if (ilim == 0) { + S = mhi = 0; + dval(d) -= 5.; + if (dval(d) > dval(eps)) + goto one_digit; + if (dval(d) < -dval(eps)) + goto no_digits; + goto fast_failed; + } +#ifndef No_leftright + if (leftright) { + /* Use Steele & White method of only + * generating digits needed. + */ + dval(eps) = ds*0.5/tens[ilim-1] - dval(eps); + for(i = 0;;) { + L = (Long)(dval(d)/ds); + dval(d) -= L*ds; + *s++ = '0' + (int)L; + if (dval(d) < dval(eps)) { + if (dval(d)) + inex = STRTOG_Inexlo; + goto ret1; + } + if (ds - dval(d) < dval(eps)) + goto bump_up; + if (++i >= ilim) + break; + dval(eps) *= 10.; + dval(d) *= 10.; + } + } + else { +#endif + /* Generate ilim digits, then fix them up. */ + dval(eps) *= tens[ilim-1]; + for(i = 1;; i++, dval(d) *= 10.) { + if ( (L = (Long)(dval(d)/ds)) !=0) + dval(d) -= L*ds; + *s++ = '0' + (int)L; + if (i == ilim) { + ds *= 0.5; + if (dval(d) > ds + dval(eps)) + goto bump_up; + else if (dval(d) < ds - dval(eps)) { + if (dval(d)) + inex = STRTOG_Inexlo; + goto clear_trailing0; + } + break; + } + } +#ifndef No_leftright + } +#endif + fast_failed: + s = s0; + dval(d) = d2; + k = k0; + ilim = ilim0; + } + + /* Do we have a "small" integer? */ + + if (be >= 0 && k <= Int_max) { + /* Yes. */ + ds = tens[k]; + if (ndigits < 0 && ilim <= 0) { + S = mhi = 0; + if (ilim < 0 || dval(d) <= 5*ds) + goto no_digits; + goto one_digit; + } + for(i = 1;; i++, dval(d) *= 10.) { + L = dval(d) / ds; + dval(d) -= L*ds; +#ifdef Check_FLT_ROUNDS + /* If FLT_ROUNDS == 2, L will usually be high by 1 */ + if (dval(d) < 0) { + L--; + dval(d) += ds; + } +#endif + *s++ = '0' + (int)L; + if (dval(d) == 0.) + break; + if (i == ilim) { + if (rdir) { + if (rdir == 1) + goto bump_up; + inex = STRTOG_Inexlo; + goto ret1; + } + dval(d) += dval(d); +#ifdef ROUND_BIASED + if (dval(d) >= ds) +#else + if (dval(d) > ds || (dval(d) == ds && L & 1)) +#endif + { + bump_up: + inex = STRTOG_Inexhi; + while(*--s == '9') + if (s == s0) { + k++; + *s = '0'; + break; + } + ++*s++; + } + else { + inex = STRTOG_Inexlo; + clear_trailing0: + while(*--s == '0'){} + ++s; + } + break; + } + } + goto ret1; + } + + m2 = b2; + m5 = b5; + mhi = mlo = 0; + if (leftright) { + i = nbits - bbits; + if (be - i++ < fpi->emin && mode != 3 && mode != 5) { + /* denormal */ + i = be - fpi->emin + 1; + if (mode >= 2 && ilim > 0 && ilim < i) + goto small_ilim; + } + else if (mode >= 2) { + small_ilim: + j = ilim - 1; + if (m5 >= j) + m5 -= j; + else { + s5 += j -= m5; + b5 += j; + m5 = 0; + } + if ((i = ilim) < 0) { + m2 -= i; + i = 0; + } + } + b2 += i; + s2 += i; + mhi = i2b(ptr, 1); + if (mhi == NULL) + return (NULL); + } + if (m2 > 0 && s2 > 0) { + i = m2 < s2 ? m2 : s2; + b2 -= i; + m2 -= i; + s2 -= i; + } + if (b5 > 0) { + if (leftright) { + if (m5 > 0) { + mhi = pow5mult(ptr, mhi, m5); + if (mhi == NULL) + return (NULL); + b1 = mult(ptr, mhi, b); + if (b1 == NULL) + return (NULL); + Bfree(ptr, b); + b = b1; + } + if ( (j = b5 - m5) !=0) { + b = pow5mult(ptr, b, j); + if (b == NULL) + return (NULL); + } + } + else { + b = pow5mult(ptr, b, b5); + if (b == NULL) + return (NULL); + } + } + S = i2b(ptr, 1); + if (S == NULL) + return (NULL); + if (s5 > 0) { + S = pow5mult(ptr, S, s5); + if (S == NULL) + return (NULL); + } + + /* Check for special case that d is a normalized power of 2. */ + + spec_case = 0; + if (mode < 2) { + if (bbits == 1 && be0 > fpi->emin + 1) { + /* The special case */ + b2++; + s2++; + spec_case = 1; + } + } + + /* Arrange for convenient computation of quotients: + * shift left if necessary so divisor has 4 leading 0 bits. + * + * Perhaps we should just compute leading 28 bits of S once + * and for all and pass them and a shift to quorem, so it + * can do shifts and ors to compute the numerator for q. + */ + i = ((s5 ? hi0bits(S->_x[S->_wds-1]) : ULbits - 1) - s2 - 4) & kmask; + m2 += i; + if ((b2 += i) > 0) { + b = lshift(ptr, b, b2); + if (b == NULL) + return (NULL); + } + if ((s2 += i) > 0) { + S = lshift(ptr, S, s2); + if (S == NULL) + return (NULL); + } + if (k_check) { + if (cmp(b,S) < 0) { + k--; + b = multadd(ptr, b, 10, 0); /* we botched the k estimate */ + if (b == NULL) + return (NULL); + if (leftright) { + mhi = multadd(ptr, mhi, 10, 0); + if (mhi == NULL) + return (NULL); + } + ilim = ilim1; + } + } + if (ilim <= 0 && mode > 2) { + S = multadd(ptr, S,5,0); + if (S == NULL) + return (NULL); + if (ilim < 0 || cmp(b,S) <= 0) { + /* no digits, fcvt style */ + no_digits: + k = -1 - ndigits; + inex = STRTOG_Inexlo; + goto ret; + } + one_digit: + inex = STRTOG_Inexhi; + *s++ = '1'; + k++; + goto ret; + } + if (leftright) { + if (m2 > 0) { + mhi = lshift(ptr, mhi, m2); + if (mhi == NULL) + return (NULL); + } + + /* Compute mlo -- check for special case + * that d is a normalized power of 2. + */ + + mlo = mhi; + if (spec_case) { + mhi = Balloc(ptr, mhi->_k); + if (mhi == NULL) + return (NULL); + Bcopy(mhi, mlo); + mhi = lshift(ptr, mhi, 1); + if (mhi == NULL) + return (NULL); + } + + for(i = 1;;i++) { + dig = quorem(b,S) + '0'; + /* Do we yet have the shortest decimal string + * that will round to d? + */ + j = cmp(b, mlo); + delta = diff(ptr, S, mhi); + if (delta == NULL) + return (NULL); + j1 = delta->_sign ? 1 : cmp(b, delta); + Bfree(ptr, delta); +#ifndef ROUND_BIASED + if (j1 == 0 && !mode && !(bits[0] & 1) && !rdir) { + if (dig == '9') + goto round_9_up; + if (j <= 0) { + if (b->_wds > 1 || b->_x[0]) + inex = STRTOG_Inexlo; + } + else { + dig++; + inex = STRTOG_Inexhi; + } + *s++ = dig; + goto ret; + } +#endif + if (j < 0 || (j == 0 && !mode +#ifndef ROUND_BIASED + && !(bits[0] & 1) +#endif + )) { + if (rdir && (b->_wds > 1 || b->_x[0])) { + if (rdir == 2) { + inex = STRTOG_Inexlo; + goto accept; + } + while (cmp(S,mhi) > 0) { + *s++ = dig; + mhi1 = multadd(ptr, mhi, 10, 0); + if (mhi1 == NULL) + return (NULL); + if (mlo == mhi) + mlo = mhi1; + mhi = mhi1; + b = multadd(ptr, b, 10, 0); + if (b == NULL) + return (NULL); + dig = quorem(b,S) + '0'; + } + if (dig++ == '9') + goto round_9_up; + inex = STRTOG_Inexhi; + goto accept; + } + if (j1 > 0) { + b = lshift(ptr, b, 1); + if (b == NULL) + return (NULL); + j1 = cmp(b, S); +#ifdef ROUND_BIASED + if (j1 >= 0 /*)*/ +#else + if ((j1 > 0 || (j1 == 0 && dig & 1)) +#endif + && dig++ == '9') + goto round_9_up; + inex = STRTOG_Inexhi; + } + if (b->_wds > 1 || b->_x[0]) + inex = STRTOG_Inexlo; + accept: + *s++ = dig; + goto ret; + } + if (j1 > 0 && rdir != 2) { + if (dig == '9') { /* possible if i == 1 */ + round_9_up: + *s++ = '9'; + inex = STRTOG_Inexhi; + goto roundoff; + } + inex = STRTOG_Inexhi; + *s++ = dig + 1; + goto ret; + } + *s++ = dig; + if (i == ilim) + break; + b = multadd(ptr, b, 10, 0); + if (b == NULL) + return (NULL); + if (mlo == mhi) { + mlo = mhi = multadd(ptr, mhi, 10, 0); + if (mlo == NULL) + return (NULL); + } + else { + mlo = multadd(ptr, mlo, 10, 0); + if (mlo == NULL) + return (NULL); + mhi = multadd(ptr, mhi, 10, 0); + if (mhi == NULL) + return (NULL); + } + } + } + else + for(i = 1;; i++) { + *s++ = dig = quorem(b,S) + '0'; + if (i >= ilim) + break; + b = multadd(ptr, b, 10, 0); + if (b == NULL) + return (NULL); + } + + /* Round off last digit */ + + if (rdir) { + if (rdir == 2 || (b->_wds <= 1 && !b->_x[0])) + goto chopzeros; + goto roundoff; + } + b = lshift(ptr, b, 1); + if (b == NULL) + return (NULL); + j = cmp(b, S); +#ifdef ROUND_BIASED + if (j >= 0) +#else + if (j > 0 || (j == 0 && dig & 1)) +#endif + { + roundoff: + inex = STRTOG_Inexhi; + while(*--s == '9') + if (s == s0) { + k++; + *s++ = '1'; + goto ret; + } + ++*s++; + } + else { + chopzeros: + if (b->_wds > 1 || b->_x[0]) + inex = STRTOG_Inexlo; + while(*--s == '0'){} + ++s; + } + ret: + Bfree(ptr, S); + if (mhi) { + if (mlo && mlo != mhi) + Bfree(ptr, mlo); + Bfree(ptr, mhi); + } + ret1: + Bfree(ptr, b); + *s = 0; + *decpt = k + 1; + if (rve) + *rve = s; + *kindp |= inex; + return s0; + } +DEF_STRONG(gdtoa); +#endif /* _USE_GDTOA */ diff --git a/newlib/libc/stdlib/gdtoa-gmisc.c b/newlib/libc/stdlib/gdtoa-gmisc.c new file mode 100644 index 000000000..40c3c2d13 --- /dev/null +++ b/newlib/libc/stdlib/gdtoa-gmisc.c @@ -0,0 +1,91 @@ +/**************************************************************** + +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 <newlib.h> +#include <sys/config.h> + +#ifdef _USE_GDTOA +#include "gdtoaimp.h" + + void +#ifdef KR_headers +rshift(b, k) Bigint *b; int k; +#else +rshift(Bigint *b, int k) +#endif +{ + 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; + } + + int +#ifdef KR_headers +trailz(b) Bigint *b; +#else +trailz(Bigint *b) +#endif +{ + ULong L, *x, *xe; + int n = 0; + + x = b->_x; + xe = x + b->_wds; + for(n = 0; x < xe && !*x; x++) + n += ULbits; + if (x < xe) { + L = *x; + n += lo0bits(&L); + } + return n; + } +#endif /* _USE_GDTOA */ diff --git a/newlib/libc/stdlib/gdtoa-ldtoa.c b/newlib/libc/stdlib/gdtoa-ldtoa.c new file mode 100644 index 000000000..14b99042c --- /dev/null +++ b/newlib/libc/stdlib/gdtoa-ldtoa.c @@ -0,0 +1,159 @@ +/* $OpenBSD: ldtoa.c,v 1.4 2016/03/09 16:28:47 deraadt Exp $ */ +/*- + * Copyright (c) 2003 David Schultz <das@FreeBSD.ORG> + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include <newlib.h> +#include <sys/config.h> + +#ifdef _USE_GDTOA +#include <sys/types.h> +#include <machine/ieee.h> +#include <float.h> +#include <stdint.h> +#include <limits.h> +#include <math.h> +#include <stdlib.h> +#include "gdtoaimp.h" + +#if (LDBL_MANT_DIG > DBL_MANT_DIG) + +/* + * ldtoa() is a wrapper for gdtoa() that makes it smell like dtoa(), + * except that the floating point argument is passed by reference. + * When dtoa() is passed a NaN or infinity, it sets expt to 9999. + * However, a long double could have a valid exponent of 9999, so we + * use INT_MAX in ldtoa() instead. + */ +char * +_ldtoa_r(struct _reent *ptr, + long double ld, int mode, int ndigits, int *decpt, int *sign, char **rve) +{ + FPI fpi = { + LDBL_MANT_DIG, /* nbits */ + LDBL_MIN_EXP - LDBL_MANT_DIG, /* emin */ + LDBL_MAX_EXP - LDBL_MANT_DIG, /* emax */ + FLT_ROUNDS, /* rounding */ +#ifdef Sudden_Underflow /* unused, but correct anyway */ + 1 +#else + 0 +#endif + }; + int be, kind; + char *ret; + struct ieee_ext *p = (struct ieee_ext *)&ld; + uint32_t bits[(LDBL_MANT_DIG + 31) / 32]; + void *vbits = bits; + + _REENT_CHECK_MP (ptr); + + /* reentrancy addition to use mprec storage pool */ + if (_REENT_MP_RESULT (ptr)) { + _REENT_MP_RESULT (ptr)->_k = _REENT_MP_RESULT_K (ptr); + _REENT_MP_RESULT (ptr)->_maxwds = 1 << _REENT_MP_RESULT_K (ptr); + Bfree (ptr, _REENT_MP_RESULT (ptr)); + _REENT_MP_RESULT (ptr) = 0; + } + + /* + * gdtoa doesn't know anything about the sign of the number, so + * if the number is negative, we need to swap rounding modes of + * 2 (upwards) and 3 (downwards). + */ + *sign = p->ext_sign; + fpi.rounding ^= (fpi.rounding >> 1) & p->ext_sign; + + be = p->ext_exp - (LDBL_MAX_EXP - 1) - (LDBL_MANT_DIG - 1); + EXT_TO_ARRAY32(p, bits); + + switch (fpclassify(ld)) { + case FP_NORMAL: + kind = STRTOG_Normal; +#ifdef EXT_IMPLICIT_NBIT + bits[LDBL_MANT_DIG / 32] |= 1 << ((LDBL_MANT_DIG - 1) % 32); +#endif /* EXT_IMPLICIT_NBIT */ + break; + case FP_ZERO: + kind = STRTOG_Zero; + break; + case FP_SUBNORMAL: + kind = STRTOG_Denormal; + be++; + break; + case FP_INFINITE: + kind = STRTOG_Infinite; + break; + case FP_NAN: + kind = STRTOG_NaN; + break; + default: + abort(); + } + + ret = gdtoa(ptr, &fpi, be, vbits, &kind, mode, ndigits, decpt, rve); + if (*decpt == -32768) + *decpt = INT_MAX; + return ret; +} +DEF_STRONG(_ldtoa_r); + +#else /* (LDBL_MANT_DIG == DBL_MANT_DIG) */ + +char * +_ldtoa_r(struct _reent *ptr, + long double ld, int mode, int ndigits, int *decpt, int *sign, + char **rve) +{ + char *ret; + + ret = _dtoa_r(ptr, (double)ld, mode, ndigits, decpt, sign, rve); + if (*decpt == 9999) + *decpt = INT_MAX; + return ret; +} +DEF_STRONG(_ldtoa_r); + +#endif /* (LDBL_MANT_DIG == DBL_MANT_DIG) */ + +/* Routine used to tell if long double is NaN or Infinity or regular number. + Returns: 0 = regular number + 1 = Nan + 2 = Infinity +*/ +int +_ldcheck (long double *d) +{ + switch (fpclassify(*d)) { + case FP_NAN: + return 1; + case FP_INFINITE: + return 2; + default: + return 0; + } +} + +#endif /* _USE_GDTOA */ diff --git a/newlib/libc/stdlib/gdtoa.h b/newlib/libc/stdlib/gdtoa.h index 07506aac1..f4d2a56db 100644 --- a/newlib/libc/stdlib/gdtoa.h +++ b/newlib/libc/stdlib/gdtoa.h @@ -32,25 +32,55 @@ THIS SOFTWARE. #ifndef GDTOA_H_INCLUDED #define GDTOA_H_INCLUDED +#include <stddef.h> /* for size_t */ +#include <reent.h> + +#define PROTO_NORMAL(x) +#define __BEGIN_HIDDEN_DECLS +#define __END_HIDDEN_DECLS +#define DEF_STRONG(x) + +#ifndef ULong +#define ULong __ULong +#endif + +#ifndef ANSI +#ifdef KR_headers +#define ANSI(x) () +#define Void /*nothing*/ +#else +#define ANSI(x) x +#define Void void +#endif +#endif /* ANSI */ + +#ifndef CONST +#ifdef KR_headers +#define CONST /* blank */ +#else +#define CONST const +#endif +#endif /* CONST */ 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, + STRTOG_Zero = 0x000, + STRTOG_Normal = 0x001, + STRTOG_Denormal = 0x002, + STRTOG_Infinite = 0x003, + STRTOG_NaN = 0x004, + STRTOG_NaNbits = 0x005, + STRTOG_NoNumber = 0x006, + STRTOG_NoMemory = 0x007, + STRTOG_Retmask = 0x00f, /* 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 + STRTOG_Inexlo = 0x010, /* returned result rounded toward zero */ + STRTOG_Inexhi = 0x020, /* returned result rounded away from zero */ + STRTOG_Inexact = 0x030, + STRTOG_Underflow= 0x040, + STRTOG_Overflow = 0x080, + STRTOG_Neg = 0x100 /* does not affect STRTOG_Inexlo or STRTOG_Inexhi */ }; typedef struct @@ -69,6 +99,74 @@ enum { /* FPI.rounding values: same as FLT_ROUNDS */ FPI_Round_down = 3 }; -#endif /* GDTOA_H_INCLUDED */ - typedef unsigned short __UShort; +typedef struct _Bigint Bigint; + +#ifdef __cplusplus +extern "C" { +#endif + +extern char* __dtoa ANSI((struct _reent *ptr, + double d, int mode, int ndigits, int *decpt, + int *sign, char **rve)); +extern char* __gdtoa ANSI((struct _reent *ptr, + FPI *fpi, int be, ULong *bits, int *kindp, + int mode, int ndigits, int *decpt, char **rve)); +extern void __freedtoa ANSI((struct _reent *, char*)); +extern float strtof ANSI((CONST char *, char **)); +extern double strtod ANSI((CONST char *, char **)); +extern int __strtodg ANSI((CONST char*, char**, FPI*, Long*, ULong*)); +char *__hdtoa(double, const char *, int, int *, int *, char **); +char *__hldtoa(long double, const char *, int, int *, int *, char **); +char *__ldtoa(struct _reent *ptr, + long double *, int, int, int *, int *, char **); + +PROTO_NORMAL(__dtoa); +PROTO_NORMAL(__gdtoa); +PROTO_NORMAL(__freedtoa); +PROTO_NORMAL(__hdtoa); +PROTO_NORMAL(__hldtoa); +PROTO_NORMAL(__ldtoa); + +__BEGIN_HIDDEN_DECLS +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*)); +extern int __strtoIf ANSI((CONST char*, char**, float*, float*)); +extern int __strtoIQ ANSI((CONST char*, char**, void*, void*)); +extern int __strtoIx ANSI((CONST char*, char**, void*, void*)); +extern int __strtoIxL ANSI((CONST char*, char**, void*, void*)); +extern int __strtord ANSI((CONST char*, char**, int, double*)); +extern int __strtordd ANSI((CONST char*, char**, int, double*)); +extern int __strtorf ANSI((CONST char*, char**, int, float*)); +extern int __strtorQ ANSI((CONST char*, char**, int, void*)); +extern int __strtorx ANSI((CONST char*, char**, int, void*)); +extern int __strtorxL ANSI((CONST char*, char**, int, void*)); +#if 1 +extern int __strtodI ANSI((CONST char*, char**, double*)); +extern int __strtopd ANSI((CONST char*, char**, double*)); +extern int __strtopdd ANSI((CONST char*, char**, double*)); +extern int __strtopf ANSI((CONST char*, char**, float*)); +extern int __strtopQ ANSI((CONST char*, char**, void*)); +extern int __strtopx ANSI((CONST char*, char**, void*)); +extern int __strtopxL ANSI((CONST char*, char**, void*)); +#else +#define __strtopd(s,se,x) strtord(s,se,1,x) +#define __strtopdd(s,se,x) strtordd(s,se,1,x) +#define __strtopf(s,se,x) strtorf(s,se,1,x) +#define __strtopQ(s,se,x) strtorQ(s,se,1,x) +#define __strtopx(s,se,x) strtorx(s,se,1,x) +#define __strtopxL(s,se,x) strtorxL(s,se,1,x) +#endif +__END_HIDDEN_DECLS + +#ifdef __cplusplus +} +#endif +#endif /* GDTOA_H_INCLUDED */ diff --git a/newlib/libc/stdlib/gdtoaimp.h b/newlib/libc/stdlib/gdtoaimp.h new file mode 100644 index 000000000..f2da3fc67 --- /dev/null +++ b/newlib/libc/stdlib/gdtoaimp.h @@ -0,0 +1,206 @@ +/**************************************************************** + +The author of this software is David M. Gay. + +Copyright (C) 1998-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. + +****************************************************************/ + +/* This is a variation on dtoa.c that converts arbitary binary + floating-point formats to and from decimal notation. It uses + double-precision arithmetic internally, so there are still + various #ifdefs that adapt the calculations to the native + double-precision arithmetic (any of IEEE, VAX D_floating, + or IBM mainframe arithmetic). + + Please send bug reports to David M. Gay (dmg at acm dot org, + with " at " changed at "@" and " dot " changed to "."). + */ + +/* On a machine with IEEE extended-precision registers, it is + * necessary to specify double-precision (53-bit) rounding precision + * before invoking strtod or dtoa. If the machine uses (the equivalent + * of) Intel 80x87 arithmetic, the call + * _control87(PC_53, MCW_PC); + * does this with many compilers. Whether this or another call is + * appropriate depends on the compiler; for this to work, it may be + * necessary to #include "float.h" or another system-dependent header + * file. + */ + +/* strtod for IEEE-, VAX-, and IBM-arithmetic machines. + * + * This strtod returns a nearest machine number to the input decimal + * string (or sets errno to ERANGE). With IEEE arithmetic, ties are + * broken by the IEEE round-even rule. Otherwise ties are broken by + * biased rounding (add half and chop). + * + * Inspired loosely by William D. Clinger's paper "How to Read Floating + * Point Numbers Accurately" [Proc. ACM SIGPLAN '90, pp. 112-126]. + * + * Modifications: + * + * 1. We only require IEEE, IBM, or VAX double-precision + * arithmetic (not IEEE double-extended). + * 2. We get by with floating-point arithmetic in a case that + * Clinger missed -- when we're computing d * 10^n + * for a small integer d and the integer n is not too + * much larger than 22 (the maximum integer k for which + * we can represent 10^k exactly), we may be able to + * compute (d*10^k) * 10^(e-k) with just one roundoff. + * 3. Rather than a bit-at-a-time adjustment of the binary + * result in the hard case, we use floating-point + * arithmetic to determine the adjustment to within + * one bit; only in really hard cases do we need to + * compute a second residual. + * 4. Because of 3., we don't need a large table of powers of 10 + * for ten-to-e (just some small tables, e.g. of 10^k + * for 0 <= k <= 22). + */ + +/* + * #define IEEE_8087 for IEEE-arithmetic machines where the least + * significant byte has the lowest address. + * #define IEEE_MC68k for IEEE-arithmetic machines where the most + * significant byte has the lowest address. + * #define Long int on machines with 32-bit ints and 64-bit longs. + * #define Sudden_Underflow for IEEE-format machines without gradual + * underflow (i.e., that flush to zero on underflow). + * #define IBM for IBM mainframe-style floating-point arithmetic. + * #define VAX for VAX-style floating-point arithmetic (D_floating). + * #define No_leftright to omit left-right logic in fast floating-point + * computation of dtoa and gdtoa. This will cause modes 4 and 5 to be + * treated the same as modes 2 and 3 for some inputs. + * #define Check_FLT_ROUNDS if FLT_ROUNDS can assume the values 2 or 3. + * #define RND_PRODQUOT to use rnd_prod and rnd_quot (assembly routines + * that use extended-precision instructions to compute rounded + * products and quotients) with IBM. + * #define ROUND_BIASED for IEEE-format with biased rounding and arithmetic + * that rounds toward +Infinity. + * #define ROUND_BIASED_without_Round_Up for IEEE-format with biased + * rounding when the underlying floating-point arithmetic uses + * unbiased rounding. This prevent using ordinary floating-point + * arithmetic when the result could be computed with one rounding error. + * #define Inaccurate_Divide for IEEE-format with correctly rounded + * products but inaccurate quotients, e.g., for Intel i860. + * #define NO_LONG_LONG on machines that do not have a "long long" + * integer type (of >= 64 bits). On such machines, you can + * #define Just_16 to store 16 bits per 32-bit Long when doing + * high-precision integer arithmetic. Whether this speeds things + * up or slows things down depends on the machine and the number + * being converted. If long long is available and the name is + * something other than "long long", #define Llong to be the name, + * and if "unsigned Llong" does not work as an unsigned version of + * Llong, #define #ULLong to be the corresponding unsigned type. + * #define KR_headers for old-style C function headers. + * #define Bad_float_h if your system lacks a float.h or if it does not + * define some or all of DBL_DIG, DBL_MAX_10_EXP, DBL_MAX_EXP, + * FLT_RADIX, FLT_ROUNDS, and DBL_MAX. + * #define MALLOC your_malloc, where your_malloc(n) acts like malloc(n) + * if memory is available and otherwise does something you deem + * appropriate. If MALLOC is undefined, malloc will be invoked + * directly -- and assumed always to succeed. Similarly, if you + * want something other than the system's free() to be called to + * recycle memory acquired from MALLOC, #define FREE to be the + * name of the alternate routine. (FREE or free is only called in + * pathological cases, e.g., in a gdtoa call after a gdtoa return in + * mode 3 with thousands of digits requested.) + * #define Omit_Private_Memory to omit logic (added Jan. 1998) for making + * memory allocations from a private pool of memory when possible. + * When used, the private pool is PRIVATE_MEM bytes long: 2304 bytes, + * unless #defined to be a different length. This default length + * suffices to get rid of MALLOC calls except for unusual cases, + * such as decimal-to-binary conversion of a very long string of + * digits. When converting IEEE double precision values, the + * longest string gdtoa can return is about 751 bytes long. For + * conversions by strtod of strings of 800 digits and all gdtoa + * 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 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 + * preceded by 0x or 0X) and spaces; if there is only one string + * of hexadecimal digits, it is taken for the fraction bits of the + * resulting NaN; if there are two or more strings of hexadecimal + * digits, each string is assigned to the next available sequence + * of 32-bit words of fractions bits (starting with the most + * significant), right-aligned in each sequence. + * Unless GDTOA_NON_PEDANTIC_NANCHECK is #defined, input "NaN(...)" + * is consumed even when ... has the wrong form (in which case the + * "(...)" is consumed but ignored). + * #define MULTIPLE_THREADS if the system offers preemptively scheduled + * multiple threads. In this case, you must provide (or suitably + * #define) two locks, acquired by ACQUIRE_DTOA_LOCK(n) and freed + * by FREE_DTOA_LOCK(n) for n = 0 or 1. (The second lock, accessed + * in pow5mult, ensures lazy evaluation of only one copy of high + * powers of 5; omitting this lock would introduce a small + * probability of wasting memory, but would otherwise be harmless.) + * You must also invoke freedtoa(s) to free the value s returned by + * dtoa. You may do so whether or not MULTIPLE_THREADS is #defined. + * #define IMPRECISE_INEXACT if you do not care about the setting of + * the STRTOG_Inexact bits in the special case of doing IEEE double + * precision conversions (which could also be done by the strtod in + * dtoa.c). + * #define NO_HEX_FP to disable recognition of C9x's hexadecimal + * floating-point constants. + * #define -DNO_ERRNO to suppress setting errno (in strtod.c and + * strtodg.c). + * #define NO_STRING_H to use private versions of memcpy. + * On some K&R systems, it may also be necessary to + * #define DECLARE_SIZE_T in this case. + * #define USE_LOCALE to use the current locale's decimal_point value. + */ + +#ifndef GDTOAIMP_H_INCLUDED +#define GDTOAIMP_H_INCLUDED +#include "mprec.h" +#include "gdtoa.h" + +#ifndef __SINGLE_THREAD__ +#define MULTIPLE_THREADS +#endif + +#define dtoa __dtoa +#define gdtoa __gdtoa +#define freedtoa __freedtoa + +#define dtoa_result __dtoa_result_D2A +#define nrv_alloc __nrv_alloc_D2A +#define quorem __quorem_D2A +#define rshift __rshift_D2A +#define rv_alloc __rv_alloc_D2A +#define trailz __trailz_D2A + +extern char *dtoa_result; +extern char *nrv_alloc ANSI((struct _reent *, char*, char **, int)); +extern int quorem ANSI((Bigint*, Bigint*)); +extern void rshift ANSI((Bigint*, int)); +extern char *rv_alloc ANSI((struct _reent *, int)); +extern int trailz ANSI((Bigint*)); + +#endif /* GDTOAIMP_H_INCLUDED */ diff --git a/newlib/libc/stdlib/ldtoa.c b/newlib/libc/stdlib/ldtoa.c index 26c61948b..36613faad 100644 --- a/newlib/libc/stdlib/ldtoa.c +++ b/newlib/libc/stdlib/ldtoa.c @@ -2,6 +2,10 @@ * This program has been placed in the public domain. */ +#include <newlib.h> +#include <sys/config.h> + +#ifndef _USE_GDTOA #include <_ansi.h> #include <reent.h> #include <string.h> @@ -3900,3 +3904,5 @@ enan (short unsigned int *nan, int size) for (i = 0; i < n; i++) *nan++ = *p++; } + +#endif /* !_USE_GDTOA */ diff --git a/newlib/libc/stdlib/mprec.h b/newlib/libc/stdlib/mprec.h index a1492aa38..83de932c2 100644 --- a/newlib/libc/stdlib/mprec.h +++ b/newlib/libc/stdlib/mprec.h @@ -26,7 +26,7 @@ dmg@research.att.com or research!dmg */ -#include <ieeefp.h> +#include <machine/ieeefp.h> #include <math.h> #include <float.h> #include <errno.h> |