aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDavid Schultz <das@FreeBSD.org>2011-03-09 06:14:33 +0000
committerDavid Schultz <das@FreeBSD.org>2011-03-09 06:14:33 +0000
commit21a2b1c905e6a3ae73e3ca075627e81a2ccac58f (patch)
tree80228e2b243573cbd695c52e7a912cc1643cd1b2
parent9ea4d2a87415d5928272c15f22583103f2ccfe30 (diff)
downloadsrc-vendor/gdtoa.tar.gz
src-vendor/gdtoa.zip
Import gdtoa sources dated 2011-03-04. This version includes a numbervendor/gdtoa/20110304vendor/gdtoa
of bugfixes, although I believe we already have local patches for the ones people are likely to notice. Per a request from arundel@, I also added the vendor's change log, which is available separately from ftp://ftp.netlib.org/fp/.
Notes
Notes: svn path=/vendor/gdtoa/dist/; revision=219422 svn path=/vendor/gdtoa/20110304/; revision=219423; tag=vendor/gdtoa/20110304
-rw-r--r--README7
-rw-r--r--changes672
-rw-r--r--dtoa.c168
-rw-r--r--g__fmt.c2
-rw-r--r--g_ddfmt.c23
-rw-r--r--g_dfmt.c2
-rw-r--r--gdtoa.c172
-rw-r--r--gdtoa.h2
-rw-r--r--gdtoaimp.h49
-rw-r--r--gethex.c10
-rw-r--r--hexnan.c6
-rw-r--r--makefile41
-rw-r--r--misc.c82
-rw-r--r--printf.c8
-rw-r--r--printf.c01669
-rw-r--r--smisc.c20
-rw-r--r--stdio1.h103
-rw-r--r--strtoIg.c2
-rw-r--r--strtod.c446
-rw-r--r--strtodI.c88
-rw-r--r--strtodg.c121
-rw-r--r--strtof.c2
-rw-r--r--strtopdd.c36
-rw-r--r--strtopf.c2
-rw-r--r--strtopx.c3
-rw-r--r--strtopxL.c3
-rw-r--r--strtordd.c34
-rw-r--r--strtorf.c2
-rw-r--r--strtorx.c3
-rw-r--r--strtorxL.c3
-rw-r--r--test/Qtest.c23
-rw-r--r--test/README6
-rw-r--r--test/ddtest.c2
-rw-r--r--test/dt.c112
-rw-r--r--test/dtest.c2
-rw-r--r--test/ftest.c2
-rw-r--r--test/getround.c2
-rw-r--r--test/makefile31
-rw-r--r--test/pfLqtestnos13
-rw-r--r--test/pftest.c158
-rw-r--r--test/pftestLq.out13
-rw-r--r--test/pftestQ.out15
-rw-r--r--test/pftestnos15
-rw-r--r--test/pftestx.out15
-rw-r--r--test/strtodt.c8
-rw-r--r--test/testnos324
-rw-r--r--test/xLtest.c8
-rw-r--r--test/xQtest.c22
-rw-r--r--test/xsum0.out54
-rw-r--r--test/xtest.c4
-rw-r--r--ulp.c20
-rw-r--r--xsum0.out57
52 files changed, 3629 insertions, 758 deletions
diff --git a/README b/README
index ce8be5588816..0c034f1bf19d 100644
--- a/README
+++ b/README
@@ -353,5 +353,12 @@ you also compile with -DNO_LOCALE_CACHE, the details about the
current "decimal point" character string are cached and assumed not
to change during the program's execution.
+On machines with a 64-bit long double and perhaps a 113-bit "quad"
+type, you can invoke "make Printf" to add Printf (and variants, such
+as Fprintf) to gdtoa.a. These are analogs, declared in stdio1.h, of
+printf and fprintf, etc. in which %La, %Le, %Lf, and %Lg are for long
+double and (if appropriate) %Lqa, %Lqe, %Lqf, and %Lqg are for quad
+precision printing.
+
Please send comments to David M. Gay (dmg at acm dot org, with " at "
changed at "@" and " dot " changed to ".").
diff --git a/changes b/changes
new file mode 100644
index 000000000000..3eb8138c0642
--- /dev/null
+++ b/changes
@@ -0,0 +1,672 @@
+Sun Jun 30 13:48:26 EDT 1991:
+ dtoa.c: adjust dtoa to allow negative ndigits for modes 3,5,7,9
+(fixed-point mode); fix rounding bug in these modes when the input
+d (to be converted) satisfies 10^-(ndigits+1) <= |d| < 10^-ndigits ,
+i.e., when the result, before rounding, would be empty but might
+round to one digit. Adjust the decpt returned in these modes when
+the result is empty (i.e., when |d| <= 5 * 10^-ndigits).
+
+Tue Jul 2 21:44:00 EDT 1991
+ Correct an inefficiency introduced 2 days ago in dtoa's handling of
+integers in modes 0, 1.
+
+Mon Sep 9 23:29:38 EDT 1991
+ dtoa.c: remove superfluous declaration of size_t.
+
+Sun Oct 6 15:34:15 EDT 1991
+ dtoa.c: fix another bug in modes 3,5,7,9 when the result, before
+rounding, would be empty, but rounds to one digit: *decpt was low by
+one.
+
+Sat Jan 18 12:30:04 EST 1992
+ dtoa.c: add some #ifdef KR_headers lines relevant only if IBM is
+defined; for input decimal strings representing numbers too large, have
+strtod return HUGE_VAL only if __STDC__ is defined; otherwise have it
+return +-Infinity for IEEE arithmetic, +- the largest machine number
+for IBM and VAX arithmetic. (If __STDC__ is not defined, HUGE_VAL may
+not be defined either, or it may be wrong.)
+
+Mon Apr 27 23:13:43 EDT 1992
+ dtoa.c: tweak strtod (one-line addition) so the end-pointer = start
+pointer when the input has, e.g., only white space.
+
+Thu May 7 18:04:46 EDT 1992
+ dtoa.c: adjust treatment of exponent field (in strtod) to behave
+reasonably with huge numbers and 16-bit ints.
+
+Fri Jun 19 08:29:02 EDT 1992
+ dtoa.c: fix a botch in placement of #ifdef __cplusplus (which only
+matters if you're using a C++ compiler).
+
+Wed Oct 21 11:23:07 EDT 1992
+ dtoa.c: add #ifdef Bad_float_h lines for systems with missing or
+inferior float.h .
+
+Thu Apr 22 07:54:48 EDT 1993
+ dtoa.c: change < to <= in line 2059:
+< for(result_k = 0; sizeof(Bigint) - sizeof(unsigned long) + j < i;
+---
+> for(result_k = 0; sizeof(Bigint) - sizeof(unsigned long) + j <= i;
+With 32-bit ints, the former could give too small a block for the return
+value when, e.g., mode = 2 or 4 and ndigits = 24 (16 for 16-bit ints).
+
+Mon Jun 21 12:56:42 EDT 1993
+ dtoa.c: tweak to work with 32-bit ints and 64-bit longs
+when compiled with -DLong=int .
+
+Wed Jan 26 11:09:16 EST 1994
+ dtoa.c: fix bug in strtod's handling of numbers with very
+negative exponents (e.g. 1.8826e-512), which should underflow to 0;
+fix storage leak in strtod with underflows and overflows near
+the underflow and overflow thresholds.
+
+Mon Feb 28 11:37:30 EST 1994
+ dtoa.c:
+85a86,89
+> * #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.
+87a92,95
+> #ifndef MALLOC
+> #define MALLOC malloc
+> #endif
+>
+352c360
+< rv = (Bigint *)malloc(sizeof(Bigint) + (x-1)*sizeof(Long));
+---
+> rv = (Bigint *)MALLOC(sizeof(Bigint) + (x-1)*sizeof(Long));
+
+Thu Mar 3 16:56:39 EST 1994
+ dtoa.c: if MALLOC is #defined, declare it.
+
+Wed Jan 4 15:45:34 EST 1995
+ dtoa.c: add CONST qualification to tens, bigtens, tinytens (for use
+on embedded systems with little spare RAM).
+
+Fri Mar 1 08:55:39 EST 1996
+ g_fmt.c: honor the sign of 0 and return the first argument (buf).
+
+Sat Jul 6 07:59:28 EDT 1996
+ dtoa.c: cosmetic changes: "ULong" rather than "unsigned Long";
+update comments to reflect AT&T breakup.
+
+Mon Aug 5 23:31:24 EDT 1996
+ dtoa.c: add comment about invoking _control87(PC_53, MCW_PC)
+(or the equivalent) on 80x87 machines before calling strtod or dtoa.
+
+Tue Dec 17 15:01:56 EST 1996
+ dtoa.c: new #define possibilities: #define INFNAN_CHECK to have
+strtod check (case insensitively) for "Infinity" and "NaN" on machines
+with IEEE arithmetic; #define MULTIPLE_THREADS if the system offers
+preemptively scheduled multiple threads, in which case you must supply
+routines ACQUIRE_DTOA_LOCK(n) and FREE_DTOA_LOCK(n) (n = 0 or 1).
+New void freedtoa(char*) for freeing values returned by dtoa; use of
+freedtoa() is required if MULTIPLE_THREADS is #defined, and is merely
+recommended otherwise.
+ g_fmt.c: adjusted to invoke freedtoa().
+
+Wed Feb 12 00:40:01 EST 1997
+ dtoa.c: strtod: on IEEE systems, scale to avoid intermediate
+underflows when the result does not underflow; compiling with
+-DNO_IEEE_Scale restores the old logic. Fix a bug, revealed by
+input string 2.2250738585072012e-308, in treating input just less
+than the smallest normalized number. (The bug introduced an extra
+ULP of error in this special case.)
+
+Tue May 12 11:13:04 EDT 1998
+ dtoa.c: strtod: fix a glitch introduced with the scaling of 19970212
+that caused one-bit rounding errors in certain denormal numbers, such
+as 8.44291197326099e-309, which was read as 8.442911973260987e-309.
+Remove #ifdef Unsigned_Shifts logic in favor of unsigned arithmetic.
+Unless compiled with -DNO_LONG_LONG, use 64-bit arithmetic where
+possible.
+
+Fri May 15 07:49:07 EDT 1998
+ dtoa.c: strtod: fix another glitch with scaling to avoid underflow
+with IEEE arithmetic, again revealed by the input string
+2.2250738585072012e-308, which was rounded to the largest denormal
+rather than the smallest normal double precision number.
+
+Wed Aug 5 23:27:26 EDT 1998
+ gdtoa.tar.gz: tweaks in response to comments from Shawn C. Sheridan
+(with no effect on the resulting .o files except when strtod.c is
+compiled with -DNO_ERRNO); bigtens --> bigtens_D2A (a symbol meant
+to be private to gdtoa.a).
+
+Sat Sep 12 17:05:15 EDT 1998
+ gdtoa.tar.gz: more changes in response to comments from Shawn C.
+Sheridan (including repair of a glitch in g_ffmt.c). For consistency
+and possible convenience, there are some new functions and some name
+changes to existing ones:
+ Old New
+ --- g_xLfmt
+ strtoQ strtopQ
+ --- strtopd
+ strtodd strtopdd
+ --- strtopf
+ strtox strtopx
+ --- strtopxL
+ --- strtorxL
+ --- strtoIxL
+Functions strtopd and strtopf are variations of strtod and strtof,
+respectively, which write their results to their final (pointer)
+arguments. Functions strtorf and strtord are now analogous to the
+other strtor* functions in that they now have a final pointer
+argument to which they write their results, and they return the
+int value they get from strtodg.
+ The xL family (g_xLfmt, strto[Irp]xL) is a variation of the old x
+family (for 80-bit IEEE double-extended precision) that assumes the
+storage layout of the Motorola 68881's double-extended format: 80
+interesting bits stored in 3 unsigned 32-bit ints (with a "hole", 16
+zero bits, in the word that holds the sign and exponent). The x
+family now deals with 80-bit (5 unsigned 16-bit ints) rather than
+96-bit arrays (3 unsigned 32-bit ints) that hold its 80-bit
+double-extended values. (This relaxes the alignment requirements of
+the x family and results in strto[Ipr]x writing 80 rather than 96 bits
+to their final arguments.)
+ Each g_*fmt routine now returns a pointer to the null character
+that terminates the strings it writes, rather than a pointer to
+the beginning of that string (the first argument). These routines
+still return 0 (NULL) if the first argument is too short.
+ The second argument to g_dfmt is now pointer (to a double) rather
+than a double value.
+
+Thu Oct 29 21:54:00 EST 1998
+ dtoa.c: Fix bug in strtod under -DSudden_Underflow and (the default)
+-DAvoid_Underflow: some numbers that should have suffered sudden
+underflow were scaled inappropriately (giving nonzero return values).
+Example: "1e-320" gave -3.6304123742133376e+280 rather than 0.
+
+Mon Nov 2 15:41:16 EST 1998
+ dtoa.c: tweak to remove LL suffixes from numeric constants (for
+compilers that offer a 64-bit long long type but do not recognize the
+LL constants prescribed by C9x, the proposed update to the ANSI/ISO C
+standard). Thanks to Earl Chew for pointing out the existence of such
+compilers.
+ gdtoa.tar.gz: renamed gdtoa.tgz and updated to incorporate the above
+changes (of 29 Oct. and 2 Nov. 1998) to dtoa.c.
+
+Thu Mar 25 17:56:44 EST 1999
+ dtoa.c, gdtoa.tgz: fix a bug in strtod's reading of 4.9e-324:
+it returned 0 rather than the smallest denormal.
+
+Mon Apr 12 10:39:25 EDT 1999
+ gdtoa.tgz: test/ftest.c: change %.7g to %.8g throughout.
+
+Fri Aug 20 19:17:52 EDT 1999
+ gdtoa.tgz: gdtoa.c: fix two bugs reported by David Chase (thanks!):
+1. An adjustment for denormalized numbers around 503 was off by one.
+2. A check for "The special case" around line 551 omitted the condition
+that we not be at the bottom of the exponent range.
+
+Mon Sep 13 10:53:34 EDT 1999
+ dtoa.c: computationally invisible tweak for the benefit of people
+who actually read the code:
+
+2671c2671
+< && word0(d) & Exp_mask
+---
+> && word0(d) & (Exp_mask & Exp_mask << 1)
+
+I.e., in dtoa(), the "special case" does not arise for the smallest
+normalized IEEE double. Thanks to Waldemar Horwat for pointing this
+out and suggesting the modified test above. Also, some tweaks for
+compilation with -DKR_headers.
+ gdtoa.tgz: gdtoa.c: analogous change:
+
+552c552
+< if (bbits == 1 && be0 > fpi->emin) {
+---
+> if (bbits == 1 && be0 > fpi->emin + 1) {
+
+This has no effect on the g*fmt.c routines, but might affect the
+computation of the shortest decimal string that rounds to the
+smallest normalized floating-point number of other precisions.
+ gdota.tgz: test/d.out test/dI.out test/dd.out: updated to reflect
+previous changes (of 19990820); test/*.c: most test programs modified
+to permit #hex input. See the comments.
+
+Fri Sep 17 01:39:25 EDT 1999
+ Try again to update dtoa.c: somehow dtoa.c got put back to a version
+from 3 years ago after this "changes" file was updated on 13 Sept. 1999.
+One more tweak to omit a warning on some systems:
+2671c2671
+< && word0(d) & (Exp_mask & Exp_mask << 1)
+---
+> && word0(d) & (Exp_mask & ~Exp_msk1)
+Plus changes to avoid trouble with aggressively optimizing compilers
+(e.g., gcc 2.95.1 under -O2). On some systems, these changes do not
+affect the resulting machine code; on others, the old way of viewing
+a double as a pair of ULongs is available with -DYES_ALIAS.
+
+Tue Sep 21 09:21:25 EDT 1999
+ gdtoa.tgz: changes analogous to those of 17 Sept. 1999 to dtoa.c to
+avoid trouble with aggressively optimizing compilers.
+
+Wed Dec 15 13:14:38 EST 1999
+ dtoa.c: tweak to bypass a bug with HUGE_VAL on HP systems.
+
+Mon Jan 17 18:32:52 EST 2000
+ dtoa.c and gdtoa.tgz: strtod: set errno = ERANGE on all inputs that
+underflow to zero (not just those sufficiently less than the smallest
+positive denormalized number).
+ gdtoa.tgz: README: point out that compiling with -DNO_ERRNO inhibits
+errno assignments (by strtod and the core converter, strtodg).
+
+Tue Jan 18 16:35:31 EST 2000
+ dtoa.c and gdtoa.tgz: strtod: modify the test inserted yesterday so
+it may work correctly with buggy 80x87 compilers. (The change matters,
+e.g., to Microsoft Visual C++ 4.2 and 6.0.)
+
+Thu Nov 2 21:00:45 EST 2000
+ dtoa.c and gdtoa.tgz:
+1. Fix bug in test for exact half-way cases of denormalized numbers
+ (without -DNO_IEEE_Scale).
+2. Compilation with -DNO_ERRNO prevents strtod from assigning
+ errno = ERANGE when the result overflows or underflows to 0.
+3. With IEEE arithmetic and no -DNO_IEEE_Scale, adjust scaling so
+ ulp(d) never returns a denormalized number. This and other tweaks
+ permit strtod and dtoa to work correctly on machines that flush
+ underflows to zero but otherwise use IEEE arithmetic without
+ Sudden_Underflow being #defined (and with strtod simply returning 0
+ instead of denormalized numbers).
+4. Compilations with -DUSE_LOCALE causes strtod to use the current
+ locale's decimal_point value.
+5. Under compilations with -DINFNAN_CHECK, strtod and strtodg (case
+ insensitively) treat "inf" the same as "infinity" and, unless
+ compiled with -DNo_Hex_NaN, accept "nan(x)", where x is a string of
+ hexadecimal digits and spaces, as a NaN whose value is constructed
+ from x (as explained in comments near the top of dtoa.c and in
+ gdtoaimp.h).
+6. The default PRIVATE_MEM is increased slightly (to 2304), and comments
+ near the top of dtoa.c provide more discussion of PRIVATE_MEM.
+7. Meanings of dtoa modes 4,5,8,9 changed. See comments in dtoa.c and
+ gdtoa.c; modes 4 and 5 may now provide shorter strings that round
+ (in round-nearest mode) to the given double value. (Paxson's
+ testbase program is unhappy with this new rounding, as it can
+ introduce an error of more than one base-10 ulp when 17 or more
+ decimal digits are requested.)
+8. With IEEE arithmetic, compilation with -DHonor_FLT_ROUNDS causes
+ strtod and dtoa to round according to FLT_ROUNDS:
+ 0 ==> towards 0,
+ 1 ==> nearest,
+ 2 ==> towards +Infinity,
+ 3 ==> towards -Infinity.
+9. With IEEE arithmetic, compilation with -DSET_INEXACT causes extra
+ computation (and sometimes slower conversions in dtoa and strtod,
+ particularly for dtoa in cases where otherwise some simple floating-
+ point computations would suffice) to set the IEEE inexact flag
+ correctly. As comments in dtoa.c explain in more detail, this
+ requires compilation in an environment (such as #include "dtoa.c"
+ in suitable source) that provides
+ int get_inexact(void);
+ void clear_inexact(void);
+10. On input "-x", return 0 rather than -0.
+
+gdtoa.tgz: gethex.c: adjust logic for reading hex constants to accord
+with current wording of the C99 standard. Previously, I thought hex
+constants read by strtod and friends had to have either a decimal point
+or an exponent field; p. 307 of the C99 standard states that both are
+optional. Because of the complexity of this reading, it is available
+only in the variant of strtod that appears in gdtoa.tgz.
+
+strtodg (gdtoa.tgz): New return value STRTOG_NaNbits (with
+STRTOG_NoNumber renumbered). Allow STRTOG_Neg bit in strtodg returns
+for STRTOG_NaN and STRTOG_NaNbits.
+
+gdtoa.tgz: Fix uninitialized variable bug in g_Qfmt.c's handling of NaNs.
+
+Mon Nov 13 14:00:05 EST 2000
+ gdtoa.tgz: strtodg: fix a storage leak and an apparently rare infinite
+loop with a boundary case of directed rounding. Example input to
+gdtoa/test/Qtest where the loop bug bit:
+ r 3
+ 35184372088831.999999999999999999999999999999999999
+This was revealed by testbase for quad precision Solaris arithmetic;
+it did not show up in several other testbase configurations.
+
+Wed Feb 7 12:56:11 EST 2001
+ dtoa.c: fix bug (possible infinite loop, e.g., with
+2.47032822920623272e-324) introduced 20001113 in handling the special
+case of a power of 2 to be rounded down one ulp. Add test (required
+by changes of 20001113) for the extra special case of 2^-1075 (half
+the smallest denormal).
+ gdtoa.tgz: corresponding adjustments to strtod.c and strtodg.c.
+
+Tue Mar 13 00:46:09 EST 2001
+ gdtoa.tgz: gdtoa/strtodg.c: fix bug in handling values exactly half
+an ulp less than the smallest normal floating-point number;
+gdtoa/*test.c: fix glitch in handling "n ..." lines (intended to
+change "ndig").
+
+Wed Mar 6 10:13:52 EST 2002
+ gdtoa.tgz: add gdtoa/test/strtodt.c and gdtoa/test/testnos3 to test
+strtod on hard cases posted by Fred Tydeman to comp.arch.arithmetic on
+26 Feb. 1996. Add comment to gdtoa/README about strtod requiring true
+IEEE arithmetic (with 53-bit rounding precision on 80x87 chips).
+In gdtoa/test, automate selection of expected output files [xQ]*.out.
+
+Wed Mar 5 10:35:41 EST 2003
+ gdtoa.tgz: fix a bug in strtod's handling of 0-valued 0x... "decimal"
+strings. A fault was possible. Thanks to David Shultz for reporting
+this bug.
+
+Tue Mar 18 09:38:28 EST 2003
+ gdtoa.tgz: fix a glitch in strtodg.c with -DUSE_LOCALE; add #ifdef
+USE_LOCALE lines to g__fmt.c (to affect binary --> decimal conversions
+via the g*fmt routines), and add comments about -DUSE_LOCALE to README.
+In short, compiling strtod.c, strtodg.c, and g__fmt.c with -DUSE_LOCALE
+causes them to determine the decimal-point character from the current
+locale. (Otherwise it is '.'.)
+
+Fri Mar 21 16:36:27 EST 2003
+ gdtoa.tgz: gethex.c: add #ifdef USE_LOCAL logic; strtod.c: fix a
+glitch in handling 0x... input (the return from gethex was ignored).
+
+Wed Mar 26 15:35:10 EST 2003
+ gdtoa.tgz: gethex.c: pedantic (and normally invisible) change:
+use unsigned char for decimalpoint variable (under -DUSE_LOCALE).
+
+Sat Jan 17 23:58:52 MST 2004
+ gdtoa.tgz: gethex.c: supply missing parens in test for whether a
+denormal result should be zero, correct logic for rounding up when the
+result is denormal, and when returning zero or Infinity, set *bp = 0;
+strtod.c: switch on gethex(...) & STRTOG_Retmask rather than just on
+gethex(), and only copybits(..., bb) when bb is nonzero. This
+mattered for underflows and overflows in 0x notation.
+
+Thu Mar 25 22:34:56 MST 2004
+ dtoa.c and gdtoa.c/misc.c: change "(!x & 1)" to "(!x)" to avoid
+confusion by human readers -- the object code is unaffected (with
+reasonable compilers).
+
+Mon Apr 12 00:44:22 MDT 2004
+ dtoa.c and gdtoa.tar.gz: update contact info. for dmg and correct
+page numbers in comment on Steele & White (1990).
+ gdtoa.tgz: add strtodnrp.c for a variant of strtod that is slower
+but does not require 53-bit rounding precision on Intel IA32 systems.
+
+Tue Apr 13 00:28:14 MDT 2004
+ gdtoa.tgz: strtod.c: fix glitch when both INFNAN_CHECK and No_Hex_NaN
+are #defined. Thanks to David Mendenhall for pointing this bug out.
+
+Wed Jan 5 22:39:17 MST 2005
+ gdtoa.tgz:
+ gethex.c: fix the bug reported by Stefan Farfeleder of ignoring a
+binary-exponent-part if the converted number is zero.
+ strto[pr]x.c: fix bug reported by Stefan Farfeleder in setting the
+exponent of denormals (which should be 0, not 1).
+ g_xfmt.c: fix a corresponding bug with denormals.
+ strtodg.c: fix a bug under IBM (base 16) arithemtic reported
+by Greg Alexander: a correction to the binary exponent for changes to
+the exponent of a native double value for avoiding overflow had to be
+multiplied by 4 ("e2 <<= 2;").
+ Various files: minor tweaks for portability.
+
+Sat Jan 15 15:36:03 MST 2005
+ gdtoa.tgz: gethex.c: fix a glitch introduced last week (and reported
+by Stefan Farfelder) with 0x forms with no nonzero digits before the "."
+character, e.g., 0x.1 (which was rendered as 0 rather than .0625).
+ gdtoa.tgz: many files: add automatic computation of gd_qnan.h for
+giving the system-dependent format of a quiet NaN (the one generated
+for Infinity - Infinity). Tweak test/makefile so differences in the
+spelling of Infinity ("INF" or "Inf" on some systems) do not matter.
+Fix bug in strtod.c and strtodg.c under which, e.g., -.nan was read
+as NaN rather than unacceptable input (causing return 0). Adjust
+comments in README about nan(...). Fix glitch in test/dt.c.
+
+Sun Jan 16 18:22:13 MST 2005
+ gdtoa.tgz: strtodg.c: fix long-standing bug in handling input
+that rounds up to 2^nbits, e.g., strtof("16777215.5"). Thanks to
+Edward Moy for reporting this problem.
+ gdtoa.tgz: Fix some bugs with -DJust_16.
+
+Thu Sep 22 22:40:16 MDT 2005
+gdtoa.tgz:
+ strtod.c: unless prevented by -DNO_FENV_H, include C99's fenv.h
+and with hex input, get the current rounding mode from fegetround().
+With decimal input, strtod honors the rounding mode automatically.
+Thanks to David Schultz (das at FreeBSD dot ORG) for pointing
+ strtodg.c: fix a bug with handling numbers very near the largest
+possible one, which were sometimes incorrectly converted to Infinity.
+Thanks to Edward Moy (emoy at apple dot com) for pointing this out.
+ g_Qfmt.c: change strcpy to strcp. Thanks to J. T. Conklin
+(jtc at acorntoolworks dot com) for pointing this out.
+ test/xtest.c: fix some subscript bugs.
+ test/x.ou0, test/x.ou1, test/xL.: update in response to the above fix to
+test/xtest.c.
+ test/makefile: add -lm to some link lines (needed for fegetround).
+
+Sun Jan 21 20:26:44 MST 2007
+gdtoa.tgz:
+ strtodg.c: fix a botch in the test of whether to increase rvbits
+before terminating the big for(;;) loop with dsign true: change
+ if (hi0bits(rvb->x[(rvb->wds - 1) >> kshift])
+ != j)
+ rvbits++;
+to
+ if (hi0bits(rvb->x[rvb->wds - 1]) != j)
+ rvbits++;
+Example of input where this bug bit: 1.9e27. Thanks to Edward Moy
+<emoy@apple.com> for providing this example. Also, simplify the
+preceding computation of j.
+ test/README: add comment that strtodt needs to operate with 53-bit
+rounding precision on Intel x86 systems, and add a pointer to Paxson's
+paper.
+
+Sat Mar 15 11:44:31 MDT 2008
+ dtoa.c and gdtoa.tgz: with -DINFNAN_CHECK and without
+-DGDOTA_NON_PEDANTIC_NANCHECK, conform to the ill-advised prescription
+in the C99 standard of consuming (...) in "nan(...)" even when ...
+is not of the expected form. Allow an optional 0x or 0X to precede
+the string of hex digits in the expected form of ... .
+ gdtoa.tgz: gethex.c: have, e.g., strtod("0xyz",&se) set se to "xyz".
+Previously it was incorrectly set to "0xyz".
+
+Thu Aug 28 22:37:35 MDT 2008
+ dtoa.c and gdtoa.tgz: Fix a bug in strtod when compiled with
+-DHonor_FLT_ROUNDS: in rounding modes other than "to nearest",
+strtod looped on input larger than and within a factor of 2 of
+the largest finite floating-point number. Since FLT_ROUNDS is buggy
+on some (Linux) systems in that it does not reflect calls on
+fesetround(), when Honor_FLT_ROUNDS is #defined, get the curren
+rounding mode from fegetround() rather than FLT_ROUNDS, unless
+Trust_FLT_ROUNDS is also #defined.
+ gdtoa/test/getround.c in gdtoa.tgz: simply report the current
+rounding mode when the input line is "r" by itself. (Previously it
+did so, but also complained of invalid input.)
+ gdtoa/gethex.c: fix an off-by-one bug in a rounding test; detect and
+deal with huge exponents (positive or negative). This affected the
+reading of hexadecimal floating-point values (0x...). Also set errno
+to ERANGE on out-of-range values (unless compiled with -DNO_ERRNO).
+ gdtoa/strtod.c: adjust scaling of tinytens[4] (as in dtoa.c) to
+avoid double rounding when dealing with numbers near the bottom of
+the exponent range.
+
+Sat Aug 30 23:37:07 MDT 2008
+ gdtoa/gethex.c: ensure *bp is set to something (NULL if nothing else).
+ Bring gdtoa/xsum0.out and gdtoa/test/xsum0.out up to date.
+
+Tue Sep 9 22:08:30 MDT 2008
+ gdtoa/strto*.c and gdtoa/*fmt.c: if compiled with -DUSE_LOCALE, use
+the current locale's decimal point character string.
+ gdtoa/gdtoa.c: trim trailing zeros in a missed case (e.g., ndigits = 6
+on 1020302).
+ dtoa.c and gdtoa/strtod.c: on systems with IEEE arithmetic (and without
+NO_ERRNO being defined) set ERANGE for denormal values as well as real
+underflows.
+ gdtoa/strtodg.c: fix an off-by-one bug in rounding to the largest
+representable magnitude when nbits is a multiple of 32.
+ gdtoa/*fmt.c and gdtoa/gdtoa.h: bufsize changed from unsigned to size_t.
+ gdtoaimp.h, *fmt.c: change in calling sequence to internal g__fmt(),
+which now explicitly checks bufsize.
+ Relevant routines (see README) honor the current rounding mode if
+compiled with -DHonor_FLT_ROUNDS on IEEE-arithmetic systems that provide
+the C99 fegetround() function.
+ gdtoa/test/getround.c can optionally be compiled with
+-DHonor_FLT_ROUNDS and/or -DUSE_MY_LOCALE for manual testing of gdtoa.a
+compiled with -DHonor_FLT_ROUNDS or -DUSE_LOCALE.
+
+Fri Oct 10 20:07:15 MDT 2008
+ gdtoa/gethex.c: fix a bug reading hexadecimal floating-point values
+starting with "0xd" for a nonzero digit d (such as "0x1.0002p3"). The
+bug caused the values to be read as zero with endptr set incorrectly.
+
+Tue Oct 28 00:14:08 MDT 2008
+ gdtoa/strtod.c: fix a comment glitch (with commented {}).
+
+Tue Nov 11 23:05:25 MST 2008
+ gdtoa: fix a glitch in the strto* routines when compiled with
+-DUSE_LOCALE and the locale's decimal-point string is two or more
+characters long. Wrong conversions were then possible.
+
+Fri Dec 5 18:20:36 MST 2008
+ gdtoa.tgz: fix bugs with reading C99-style hexadecimal floating-point
+values when compiled with -DPack_16; on IEEE-arithmetic systems, make
+INFNAN_CHECK the default unless NO_INFNAN_CHECK is #defined. (This is
+consistent with dtoa.c, which has worked this way for a while.)
+ dtoa.c: add recognition of C99-style hexadecimal floating-point
+values (unless compiled with NO_HEX_FP is #defined).
+
+Thu Dec 11 23:10:23 MST 2008
+ dtoa.c: omit an unused variable.
+
+Fri Jan 2 22:45:33 MST 2009
+ dtoa.c: tweak to banish some compiler warnings.
+
+Sun Mar 1 20:57:22 MST 2009
+ dtoa.c, gdtoa/{g__fmt.c, gethex.c, strtod.c, strtodg.c}: change malloc
+to MALLOC.
+ dtoa.c and gdtoa/gdtoaimp.h and gdtoa/misc.c: reduce Kmax, and use
+MALLOC and FREE or free for huge blocks, which are possible only in
+pathological cases, such as dtoa calls in mode 3 with thousands of
+digits requested, or strtod() calls with thousand of digits. For the
+latter case, I have an alternate approach that runs much faster
+and uses less memory, but finding time to get it ready for distribution
+may take a while.
+
+Mon Mar 16 00:32:43 MDT 2009
+ dtoa.c: Fix a bug under -DUSE_LOCALE in handling "decimal point"
+strings more than one character long.
+ dtoa.c and gdtoa/misc.c: Remove a buggy test activated with
+-DDEBUG.
+ dtoa.c and gdtoa/gdtoa.c: simplify logic for "4 leading 0 bits".
+ dtoa.c: Add logic (that can be disabled with -DNO_STRTOD_BIGCOMP
+and that) to strtod for more efficiently handling a very long input
+string. It proceeds by initially truncating the input string, then if
+necessary comparing the whole string with a decimal expansion to
+decide close cases. This logic is only used for input more than
+STRTOD_DIGLIM digits long (default 40), and for now only applies to
+IEEE arithmetic (for want of other kinds of platforms on which to run
+tests). This only appears worthwhile for absurdly long input strings,
+so a corresponding update to gdtoa does not seem warranted.
+ dtoa.c, gdtoa.tgz: tweaks (mostly adding unnecessary parens) to
+silence "gcc -Wall" warnings. Aside from a couple of minor changes
+to banish erroneous warnings about uninitialized variables, the tweaks
+do not affect the generated object code.
+
+Sat Apr 11 23:25:58 MDT 2009
+ dtoa.c: fix glitch in compiling with -DNo_Hex_NaN and the bug of
+accepting (e.g.) ".nan" or ".inf" as NaN or Infinity.
+ gdtoa.tgz: tweaks to silence warnings from "gcc -Wstrict-aliasing=2";
+update xsum0.out files.
+
+Sun Apr 19 23:40:24 MDT 2009
+ dtoa.c, gdtoa/misc.c: do not attempt to allocate large memory blocks
+from the private memory pool (which was an unlikely event, but a bug).
+ gdtoa/strtopx.c, gdtoa/strtopxL.c, gdtoa/strtorx.c, gdtoa/strtorxL.c:
+supply explicit bit for Infinity. Note that the Q routines (which do
+not supply this bit) are appropriate for Sparc quad precision (probably
+known as long double with most current compilers).
+
+Wed Dec 9 08:14:52 MST 2009
+ gdtoa.tgz: add gdtoa/printf.c* and modify makefile so "make Printf"
+adds a printf to gdtoa.a (to be accessed with #include "stdio1.h" to
+get gdtoa/stdio1.h, which you might install in some standard place).
+On Intel/AMD i386, x86_64, and Sparc systems, this adds formats %La,
+%Le, %Lf and %Lg to handle long double. On x86_64 systems, it also
+adds %Lqa, %Lqe, %Lqf and %Lqg to handle 128-bit bit types (called
+__float128 by gcc and _Quad by the Intel compiler). In gdtoa/test,
+"make pf_test" tests this printf (provided the system is an i386,
+x86_64, or Sparc system). On x86_64 systems, "make pf_testLq" tests
+the %Lq... formats (briefly).
+
+Mon Jan 11 22:25:17 MST 2010
+ dtoa.c: fix a minor performance bug and, under compilation with -DDEBUG,
+an erroneous error message "oversize b in quorem" in strtod's processing
+of some input that underflows to zero. Also fix a bug in bigcomp()'s
+handling of numbers that will scale to denormal values. The increments
+that bigcomp applied were ignoring the effects of denormalization.
+
+Sat Jan 23 00:25:54 MST 2010
+ dtoa.c: Fix some glitches in recently introduced changes meant to
+speed up returns in pedantic cases. In quorem, adjust #ifdef DEBUG
+stuff so it does not complain when bigcomp() calls quorem on input
+near the smallest representable number and rounding up by a bit causes
+a quorem return > 9 (which in this case is not a bug). Fix a memory
+leak in the unlikely case of overflow only being detected after some
+high-precision integer computations. Fix an off-by-one bug in
+handling a large number of digits with a few nonzero digits, followed
+by many zeros, and then some nonzero digits. (This does not happen
+with sensible input.) Fix an off-by-one bug in a recently introduced
+quick test for underflow (i.e., zero result) on input at the bottom of
+the exponent range. Thanks to Mark Dickinson for pointing these bugs
+out.
+
+ dtoa.c and gdtoa/strtod.c: Fix an obscure bug in strtod's handling
+of some inputs of many digits at the bottom of the exponent range:
+results were sometimes off by a bit when gdtoa/strtod.c or dtoa.c was
+compiled without -DNO_IEEE_SCALE and, for dtoa.c, when compiled with
+-DNO_STRTOD_BIGCOMP.
+
+ gdtoa/test/testnos3: add some examples that went wrong before
+the present changes.
+
+Sat Jan 23 23:29:02 MST 2010
+ dtoa.c: more tweaks relevant only to absurd input.
+
+Tue Feb 2 23:05:34 MST 2010
+ dtoa.c: add test for setting errno = ERANGE when input of many digits
+is rounded to Infinity or underflows to zero. Fix a memory leak in
+such instances.
+ gdtoa/strtod.c: make some corresponding changes.
+
+Wed Jul 7 09:25:46 MDT 2010
+ dtoa.c: adjust to use bigcomp when necessary when compiled with
+-DHonor_FLT_ROUNDS (and without -DNO_STRTOD_BIGCOMP), and the rounding
+mode is torwards +Infinity. An input (supplied by Rick Regan
+<exploringbinary@gmail.com>) where this matters is
+1.100000000000000088817841970012523233890533447265626
+ gdtoa/strtod.c: fix errors (introduced 20090411) when compiled
+with -DHonor_FLT_ROUNDS.
+
+Wed Sep 15 09:00:26 MDT 2010
+ dtoa.c, gdtoa/dtoa.c, gdtoa/gdtoa.c: fix bugs with -DROUND_BIASED
+pointed out by Jay Foad.
+
+Mon Sep 27 13:43:30 MDT 2010
+ gdtoa/gdtoa.c: fix a glitch (not revealed by compilation) in the
+changes of 15 Sept. 2010.
+
+Fri Nov 5 13:02:41 MDT 2010
+ dtoa.c: fix a bug related to bigcomp: decimal strings with all
+zeros before the decimal point more than 40 significant digits that
+required use of bigcomp might be converted very incorrectly.
+Example: .010000000000000000057612911342378542997169 .
+Thanks to Rick Regan <exploringbinary@gmail.com> for reporting the
+symptoms and providing an example.
+
+20110403:
+ dtoa.c, gdtoa/gdtoaimp.h, gdtoa/strtod.c: if
+ROUND_BIASED_without_Round_Up is #defined, assume ROUND_BIASED and
+omit the quick computation that would use ordinary arithmetic to
+compute the correctly rounded result with one rounding error. If you
+want biased rounding with IEEE-style format "double" and will operate
+with rounding toward +Infinity, it suffices to #define ROUND_BIASED
+(and thus retain the quick computation when it is appropriate).
+ gdtoa/gdtoa.h: change default Long from long to int (with the goal
+of portability when compiling without -DLong=... specified). On some
+64-bit systems, long is a 64-bit type; we need a 32-bit type here.
+ dtoa.c, gdtoa/gdtoa.c: fix a glith with ndigits with mode = 4 at
+the bottom of the exponent range, e.g., 1e-323.
diff --git a/dtoa.c b/dtoa.c
index 48fdf5efc2da..6e5de308aa7c 100644
--- a/dtoa.c
+++ b/dtoa.c
@@ -75,10 +75,10 @@ THIS SOFTWARE.
char *
dtoa
#ifdef KR_headers
- (d, mode, ndigits, decpt, sign, rve)
- double d; int mode, ndigits, *decpt, *sign; char **rve;
+ (d0, mode, ndigits, decpt, sign, rve)
+ double d0; int mode, ndigits, *decpt, *sign; char **rve;
#else
- (double d, int mode, int ndigits, int *decpt, int *sign, char **rve)
+ (double d0, int mode, int ndigits, int *decpt, int *sign, char **rve)
#endif
{
/* Arguments ndigits, decpt, sign are similar to those
@@ -124,7 +124,8 @@ dtoa
ULong x;
#endif
Bigint *b, *b1, *delta, *mlo, *mhi, *S;
- double d2, ds, eps;
+ U d, d2, eps;
+ double ds;
char *s, *s0;
#ifdef SET_INEXACT
int inexact, oldinexact;
@@ -149,35 +150,35 @@ dtoa
dtoa_result = 0;
}
#endif
-
- if (word0(d) & Sign_bit) {
+ d.d = d0;
+ if (word0(&d) & Sign_bit) {
/* set sign for everything, including 0's and NaNs */
*sign = 1;
- word0(d) &= ~Sign_bit; /* clear sign bit */
+ word0(&d) &= ~Sign_bit; /* clear sign bit */
}
else
*sign = 0;
#if defined(IEEE_Arith) + defined(VAX)
#ifdef IEEE_Arith
- if ((word0(d) & Exp_mask) == Exp_mask)
+ if ((word0(&d) & Exp_mask) == Exp_mask)
#else
- if (word0(d) == 0x8000)
+ if (word0(&d) == 0x8000)
#endif
{
/* Infinity or NaN */
*decpt = 9999;
#ifdef IEEE_Arith
- if (!word1(d) && !(word0(d) & 0xfffff))
+ if (!word1(&d) && !(word0(&d) & 0xfffff))
return nrv_alloc("Infinity", rve, 8);
#endif
return nrv_alloc("NaN", rve, 3);
}
#endif
#ifdef IBM
- dval(d) += 0; /* normalize */
+ dval(&d) += 0; /* normalize */
#endif
- if (!dval(d)) {
+ if (!dval(&d)) {
*decpt = 1;
return nrv_alloc("0", rve, 1);
}
@@ -196,26 +197,26 @@ dtoa
}
#endif
- b = d2b(dval(d), &be, &bbits);
+ b = d2b(dval(&d), &be, &bbits);
#ifdef Sudden_Underflow
- i = (int)(word0(d) >> Exp_shift1 & (Exp_mask>>Exp_shift1));
+ i = (int)(word0(&d) >> Exp_shift1 & (Exp_mask>>Exp_shift1));
#else
- if (( i = (int)(word0(d) >> Exp_shift1 & (Exp_mask>>Exp_shift1)) )!=0) {
+ if (( i = (int)(word0(&d) >> Exp_shift1 & (Exp_mask>>Exp_shift1)) )!=0) {
#endif
- dval(d2) = dval(d);
- word0(d2) &= Frac_mask1;
- word0(d2) |= Exp_11;
+ dval(&d2) = dval(&d);
+ word0(&d2) &= Frac_mask1;
+ word0(&d2) |= Exp_11;
#ifdef IBM
- if (( j = 11 - hi0bits(word0(d2) & Frac_mask) )!=0)
- dval(d2) /= 1 << j;
+ if (( j = 11 - hi0bits(word0(&d2) & Frac_mask) )!=0)
+ dval(&d2) /= 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)
+ * log10(&d) = (i-Bias)*log(2)/log(10) + log10(&d2)
*
- * This suggests computing an approximation k to log10(d) by
+ * This suggests computing an approximation k to log10(&d) by
*
* k = (i - Bias)*0.301029995663981
* + ( (d2-1.5)*0.289529654602168 + 0.176091259055681 );
@@ -244,21 +245,21 @@ dtoa
/* d is denormalized */
i = bbits + be + (Bias + (P-1) - 1);
- x = i > 32 ? word0(d) << 64 - i | word1(d) >> i - 32
- : word1(d) << 32 - i;
- dval(d2) = x;
- word0(d2) -= 31*Exp_msk1; /* adjust exponent */
+ x = i > 32 ? word0(&d) << (64 - i) | word1(&d) >> (i - 32)
+ : word1(&d) << (32 - i);
+ dval(&d2) = x;
+ word0(&d2) -= 31*Exp_msk1; /* adjust exponent */
i -= (Bias + (P-1) - 1) + 1;
denorm = 1;
}
#endif
- ds = (dval(d2)-1.5)*0.289529654602168 + 0.1760912590558 + i*0.301029995663981;
+ ds = (dval(&d2)-1.5)*0.289529654602168 + 0.1760912590558 + i*0.301029995663981;
k = (int)ds;
if (ds < 0. && ds != k)
k--; /* want k = floor(ds) */
k_check = 1;
if (k >= 0 && k <= Ten_pmax) {
- if (dval(d) < tens[k])
+ if (dval(&d) < tens[k])
k--;
k_check = 0;
}
@@ -297,10 +298,11 @@ dtoa
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:
- ilim = ilim1 = -1;
i = 18;
ndigits = 0;
break;
@@ -334,7 +336,7 @@ dtoa
/* Try to get by with floating-point arithmetic. */
i = 0;
- dval(d2) = dval(d);
+ dval(&d2) = dval(&d);
k0 = k;
ilim0 = ilim;
ieps = 2; /* conservative */
@@ -344,7 +346,7 @@ dtoa
if (j & Bletch) {
/* prevent overflows */
j &= Bletch - 1;
- dval(d) /= bigtens[n_bigtens-1];
+ dval(&d) /= bigtens[n_bigtens-1];
ieps++;
}
for(; j; j >>= 1, i++)
@@ -352,32 +354,32 @@ dtoa
ieps++;
ds *= bigtens[i];
}
- dval(d) /= ds;
+ dval(&d) /= ds;
}
else if (( j1 = -k )!=0) {
- dval(d) *= tens[j1 & 0xf];
+ dval(&d) *= tens[j1 & 0xf];
for(j = j1 >> 4; j; j >>= 1, i++)
if (j & 1) {
ieps++;
- dval(d) *= bigtens[i];
+ dval(&d) *= bigtens[i];
}
}
- if (k_check && dval(d) < 1. && ilim > 0) {
+ if (k_check && dval(&d) < 1. && ilim > 0) {
if (ilim1 <= 0)
goto fast_failed;
ilim = ilim1;
k--;
- dval(d) *= 10.;
+ dval(&d) *= 10.;
ieps++;
}
- dval(eps) = ieps*dval(d) + 7.;
- word0(eps) -= (P-1)*Exp_msk1;
+ 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))
+ dval(&d) -= 5.;
+ if (dval(&d) > dval(&eps))
goto one_digit;
- if (dval(d) < -dval(eps))
+ if (dval(&d) < -dval(&eps))
goto no_digits;
goto fast_failed;
}
@@ -386,34 +388,34 @@ dtoa
/* Use Steele & White method of only
* generating digits needed.
*/
- dval(eps) = 0.5/tens[ilim-1] - dval(eps);
+ dval(&eps) = 0.5/tens[ilim-1] - dval(&eps);
for(i = 0;;) {
- L = dval(d);
- dval(d) -= L;
+ L = dval(&d);
+ dval(&d) -= L;
*s++ = '0' + (int)L;
- if (dval(d) < dval(eps))
+ if (dval(&d) < dval(&eps))
goto ret1;
- if (1. - dval(d) < dval(eps))
+ if (1. - dval(&d) < dval(&eps))
goto bump_up;
if (++i >= ilim)
break;
- dval(eps) *= 10.;
- dval(d) *= 10.;
+ 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.) {
- L = (Long)(dval(d));
- if (!(dval(d) -= L))
+ dval(&eps) *= tens[ilim-1];
+ for(i = 1;; i++, dval(&d) *= 10.) {
+ L = (Long)(dval(&d));
+ if (!(dval(&d) -= L))
ilim = i;
*s++ = '0' + (int)L;
if (i == ilim) {
- if (dval(d) > 0.5 + dval(eps))
+ if (dval(&d) > 0.5 + dval(&eps))
goto bump_up;
- else if (dval(d) < 0.5 - dval(eps)) {
+ else if (dval(&d) < 0.5 - dval(&eps)) {
while(*--s == '0');
s++;
goto ret1;
@@ -426,7 +428,7 @@ dtoa
#endif
fast_failed:
s = s0;
- dval(d) = dval(d2);
+ dval(&d) = dval(&d2);
k = k0;
ilim = ilim0;
}
@@ -438,22 +440,22 @@ dtoa
ds = tens[k];
if (ndigits < 0 && ilim <= 0) {
S = mhi = 0;
- if (ilim < 0 || dval(d) <= 5*ds)
+ if (ilim < 0 || dval(&d) <= 5*ds)
goto no_digits;
goto one_digit;
}
- for(i = 1;; i++, dval(d) *= 10.) {
- L = (Long)(dval(d) / ds);
- dval(d) -= L*ds;
+ for(i = 1;; i++, dval(&d) *= 10.) {
+ L = (Long)(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) {
+ if (dval(&d) < 0) {
L--;
- dval(d) += ds;
+ dval(&d) += ds;
}
#endif
*s++ = '0' + (int)L;
- if (!dval(d)) {
+ if (!dval(&d)) {
#ifdef SET_INEXACT
inexact = 0;
#endif
@@ -467,8 +469,13 @@ dtoa
case 2: goto bump_up;
}
#endif
- dval(d) += dval(d);
- if (dval(d) > ds || dval(d) == ds && L & 1) {
+ dval(&d) += dval(&d);
+#ifdef ROUND_BIASED
+ if (dval(&d) >= ds)
+#else
+ if (dval(&d) > ds || (dval(&d) == ds && L & 1))
+#endif
+ {
bump_up:
while(*--s == '9')
if (s == s0) {
@@ -533,9 +540,9 @@ dtoa
&& Rounding == 1
#endif
) {
- if (!word1(d) && !(word0(d) & Bndry_mask)
+ if (!word1(&d) && !(word0(&d) & Bndry_mask)
#ifndef Sudden_Underflow
- && word0(d) & (Exp_mask & ~Exp_msk1)
+ && word0(&d) & (Exp_mask & ~Exp_msk1)
#endif
) {
/* The special case */
@@ -621,7 +628,7 @@ dtoa
j1 = delta->sign ? 1 : cmp(b, delta);
Bfree(delta);
#ifndef ROUND_BIASED
- if (j1 == 0 && mode != 1 && !(word1(d) & 1)
+ if (j1 == 0 && mode != 1 && !(word1(&d) & 1)
#ifdef Honor_FLT_ROUNDS
&& Rounding >= 1
#endif
@@ -638,11 +645,11 @@ dtoa
goto ret;
}
#endif
- if (j < 0 || j == 0 && mode != 1
+ if (j < 0 || (j == 0 && mode != 1
#ifndef ROUND_BIASED
- && !(word1(d) & 1)
+ && !(word1(&d) & 1)
#endif
- ) {
+ )) {
if (!b->x[0] && b->wds <= 1) {
#ifdef SET_INEXACT
inexact = 0;
@@ -659,7 +666,11 @@ dtoa
if (j1 > 0) {
b = lshift(b, 1);
j1 = cmp(b, S);
- if ((j1 > 0 || j1 == 0 && dig & 1)
+#ifdef ROUND_BIASED
+ if (j1 >= 0 /*)*/
+#else
+ if ((j1 > 0 || (j1 == 0 && dig & 1))
+#endif
&& dig++ == '9')
goto round_9_up;
}
@@ -719,7 +730,12 @@ dtoa
#endif
b = lshift(b, 1);
j = cmp(b, S);
- if (j > 0 || j == 0 && dig & 1) {
+#ifdef ROUND_BIASED
+ if (j >= 0)
+#else
+ if (j > 0 || (j == 0 && dig & 1))
+#endif
+ {
roundoff:
while(*--s == '9')
if (s == s0) {
@@ -730,7 +746,9 @@ dtoa
++*s++;
}
else {
+#ifdef Honor_FLT_ROUNDS
trimzeros:
+#endif
while(*--s == '0');
s++;
}
@@ -745,9 +763,9 @@ dtoa
#ifdef SET_INEXACT
if (inexact) {
if (!oldinexact) {
- word0(d) = Exp_1 + (70 << Exp_shift);
- word1(d) = 0;
- dval(d) += 1.;
+ word0(&d) = Exp_1 + (70 << Exp_shift);
+ word1(&d) = 0;
+ dval(&d) += 1.;
}
}
else if (!oldinexact)
diff --git a/g__fmt.c b/g__fmt.c
index fbccb7d98971..6c4b3d26fb2a 100644
--- a/g__fmt.c
+++ b/g__fmt.c
@@ -56,7 +56,7 @@ g__fmt(char *b, char *s, char *se, int decpt, ULong sign, size_t blen)
if (!(s0 = decimalpoint_cache)) {
s0 = localeconv()->decimal_point;
dlen = strlen(s0);
- if ((decimalpoint_cache = (char*)malloc(strlen(s0) + 1))) {
+ if ((decimalpoint_cache = (char*)MALLOC(strlen(s0) + 1))) {
strcpy(decimalpoint_cache, s0);
s0 = decimalpoint_cache;
}
diff --git a/g_ddfmt.c b/g_ddfmt.c
index b65d39d793c4..1256655eb282 100644
--- a/g_ddfmt.c
+++ b/g_ddfmt.c
@@ -33,9 +33,9 @@ THIS SOFTWARE.
char *
#ifdef KR_headers
-g_ddfmt(buf, dd, ndig, bufsize) char *buf; double *dd; int ndig; size_t bufsize;
+g_ddfmt(buf, dd0, ndig, bufsize) char *buf; double *dd0; int ndig; size_t bufsize;
#else
-g_ddfmt(char *buf, double *dd, int ndig, size_t bufsize)
+g_ddfmt(char *buf, double *dd0, int ndig, size_t bufsize)
#endif
{
FPI fpi;
@@ -43,7 +43,7 @@ g_ddfmt(char *buf, double *dd, int ndig, size_t bufsize)
ULong *L, bits0[4], *bits, *zx;
int bx, by, decpt, ex, ey, i, j, mode;
Bigint *x, *y, *z;
- double ddx[2];
+ U *dd, ddx[2];
#ifdef Honor_FLT_ROUNDS /*{{*/
int Rounding;
#ifdef Trust_FLT_ROUNDS /*{{ only define this if FLT_ROUNDS really works! */
@@ -63,7 +63,8 @@ g_ddfmt(char *buf, double *dd, int ndig, size_t bufsize)
if (bufsize < 10 || bufsize < ndig + 8)
return 0;
- L = (ULong*)dd;
+ dd = (U*)dd0;
+ L = dd->L;
if ((L[_0] & 0x7ff00000L) == 0x7ff00000L) {
/* Infinity or NaN */
if (L[_0] & 0xfffff || L[_1]) {
@@ -88,7 +89,7 @@ g_ddfmt(char *buf, double *dd, int ndig, size_t bufsize)
goto nanret;
goto infret;
}
- if (dd[0] + dd[1] == 0.) {
+ if (dval(&dd[0]) + dval(&dd[1]) == 0.) {
b = buf;
#ifndef IGNORE_ZERO_SIGN
if (L[_0] & L[2+_0] & 0x80000000L)
@@ -99,16 +100,16 @@ g_ddfmt(char *buf, double *dd, int ndig, size_t bufsize)
return b;
}
if ((L[_0] & 0x7ff00000L) < (L[2+_0] & 0x7ff00000L)) {
- ddx[1] = dd[0];
- ddx[0] = dd[1];
+ dval(&ddx[1]) = dval(&dd[0]);
+ dval(&ddx[0]) = dval(&dd[1]);
dd = ddx;
- L = (ULong*)dd;
+ L = dd->L;
}
- z = d2b(dd[0], &ex, &bx);
- if (dd[1] == 0.)
+ z = d2b(dval(&dd[0]), &ex, &bx);
+ if (dval(&dd[1]) == 0.)
goto no_y;
x = z;
- y = d2b(dd[1], &ey, &by);
+ y = d2b(dval(&dd[1]), &ey, &by);
if ( (i = ex - ey) !=0) {
if (i > 0) {
x = lshift(x, i);
diff --git a/g_dfmt.c b/g_dfmt.c
index 23d8b2470f4d..8367868f47c4 100644
--- a/g_dfmt.c
+++ b/g_dfmt.c
@@ -88,6 +88,8 @@ g_dfmt(char *buf, double *d, int ndig, size_t bufsize)
if (ndig <= 0)
mode = 0;
i = STRTOG_Normal;
+ if (sign)
+ i = STRTOG_Normal | STRTOG_Neg;
s = gdtoa(fpi, ex, bits, &i, mode, ndig, &decpt, &se);
return g__fmt(buf, s, se, decpt, sign, bufsize);
}
diff --git a/gdtoa.c b/gdtoa.c
index 3b642508fe93..e15bb2ad862e 100644
--- a/gdtoa.c
+++ b/gdtoa.c
@@ -123,6 +123,7 @@ gdtoa
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
@@ -157,8 +158,9 @@ gdtoa
int rdir, s2, s5, spec_case, try_quick;
Long L;
Bigint *b, *b1, *delta, *mlo, *mhi, *mhi1, *S;
- double d, d2, ds, eps;
+ double d2, ds;
char *s, *s0;
+ U d, eps;
#ifndef MULTIPLE_THREADS
if (dtoa_result) {
@@ -197,21 +199,21 @@ gdtoa
return nrv_alloc("0", rve, 1);
}
- dval(d) = b2d(b, &i);
+ dval(&d) = b2d(b, &i);
i = be + bbits - 1;
- word0(d) &= Frac_mask1;
- word0(d) |= Exp_11;
+ word0(&d) &= Frac_mask1;
+ word0(&d) |= Exp_11;
#ifdef IBM
- if ( (j = 11 - hi0bits(word0(d) & Frac_mask)) !=0)
- dval(d) /= 1 << j;
+ 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)
+ * log10(&d) = (i-Bias)*log(2)/log(10) + log10(d2)
*
- * This suggests computing an approximation k to log10(d) by
+ * This suggests computing an approximation k to log10(&d) by
*
* k = (i - Bias)*0.301029995663981
* + ( (d2-1.5)*0.289529654602168 + 0.176091259055681 );
@@ -231,7 +233,7 @@ gdtoa
i <<= 2;
i += j;
#endif
- ds = (dval(d)-1.5)*0.289529654602168 + 0.1760912590558 + i*0.301029995663981;
+ ds = (dval(&d)-1.5)*0.289529654602168 + 0.1760912590558 + i*0.301029995663981;
/* correct assumption about exponent range */
if ((j = i) < 0)
@@ -246,13 +248,13 @@ gdtoa
#ifdef IBM
j = be + bbits - 1;
if ( (j1 = j & 3) !=0)
- dval(d) *= 1 << j1;
- word0(d) += j << Exp_shift - 2 & Exp_mask;
+ dval(&d) *= 1 << j1;
+ word0(&d) += j << Exp_shift - 2 & Exp_mask;
#else
- word0(d) += (be + bbits - 1) << Exp_shift;
+ word0(&d) += (be + bbits - 1) << Exp_shift;
#endif
if (k >= 0 && k <= Ten_pmax) {
- if (dval(d) < tens[k])
+ if (dval(&d) < tens[k])
k--;
k_check = 0;
}
@@ -282,11 +284,14 @@ gdtoa
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:
- ilim = ilim1 = -1;
i = (int)(nbits * .30103) + 3;
ndigits = 0;
break;
@@ -328,10 +333,10 @@ gdtoa
/* Try to get by with floating-point arithmetic. */
i = 0;
- d2 = dval(d);
+ d2 = dval(&d);
#ifdef IBM
- if ( (j = 11 - hi0bits(word0(d) & Frac_mask)) !=0)
- dval(d) /= 1 << j;
+ if ( (j = 11 - hi0bits(word0(&d) & Frac_mask)) !=0)
+ dval(&d) /= 1 << j;
#endif
k0 = k;
ilim0 = ilim;
@@ -342,7 +347,7 @@ gdtoa
if (j & Bletch) {
/* prevent overflows */
j &= Bletch - 1;
- dval(d) /= bigtens[n_bigtens-1];
+ dval(&d) /= bigtens[n_bigtens-1];
ieps++;
}
for(; j; j >>= 1, i++)
@@ -354,30 +359,30 @@ gdtoa
else {
ds = 1.;
if ( (j1 = -k) !=0) {
- dval(d) *= tens[j1 & 0xf];
+ dval(&d) *= tens[j1 & 0xf];
for(j = j1 >> 4; j; j >>= 1, i++)
if (j & 1) {
ieps++;
- dval(d) *= bigtens[i];
+ dval(&d) *= bigtens[i];
}
}
}
- if (k_check && dval(d) < 1. && ilim > 0) {
+ if (k_check && dval(&d) < 1. && ilim > 0) {
if (ilim1 <= 0)
goto fast_failed;
ilim = ilim1;
k--;
- dval(d) *= 10.;
+ dval(&d) *= 10.;
ieps++;
}
- dval(eps) = ieps*dval(d) + 7.;
- word0(eps) -= (P-1)*Exp_msk1;
+ 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))
+ dval(&d) -= 5.;
+ if (dval(&d) > dval(&eps))
goto one_digit;
- if (dval(d) < -dval(eps))
+ if (dval(&d) < -dval(&eps))
goto no_digits;
goto fast_failed;
}
@@ -386,38 +391,38 @@ gdtoa
/* Use Steele & White method of only
* generating digits needed.
*/
- dval(eps) = ds*0.5/tens[ilim-1] - dval(eps);
+ dval(&eps) = ds*0.5/tens[ilim-1] - dval(&eps);
for(i = 0;;) {
- L = (Long)(dval(d)/ds);
- dval(d) -= L*ds;
+ L = (Long)(dval(&d)/ds);
+ dval(&d) -= L*ds;
*s++ = '0' + (int)L;
- if (dval(d) < dval(eps)) {
- if (dval(d))
+ if (dval(&d) < dval(&eps)) {
+ if (dval(&d))
inex = STRTOG_Inexlo;
goto ret1;
}
- if (ds - dval(d) < dval(eps))
+ if (ds - dval(&d) < dval(&eps))
goto bump_up;
if (++i >= ilim)
break;
- dval(eps) *= 10.;
- dval(d) *= 10.;
+ 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;
+ 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))
+ if (dval(&d) > ds + dval(&eps))
goto bump_up;
- else if (dval(d) < ds - dval(eps)) {
- if (dval(d))
+ else if (dval(&d) < ds - dval(&eps)) {
+ if (dval(&d))
inex = STRTOG_Inexlo;
goto clear_trailing0;
}
@@ -429,7 +434,7 @@ gdtoa
#endif
fast_failed:
s = s0;
- dval(d) = d2;
+ dval(&d) = d2;
k = k0;
ilim = ilim0;
}
@@ -441,22 +446,22 @@ gdtoa
ds = tens[k];
if (ndigits < 0 && ilim <= 0) {
S = mhi = 0;
- if (ilim < 0 || dval(d) <= 5*ds)
+ 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;
+ 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) {
+ if (dval(&d) < 0) {
L--;
- dval(d) += ds;
+ dval(&d) += ds;
}
#endif
*s++ = '0' + (int)L;
- if (dval(d) == 0.)
+ if (dval(&d) == 0.)
break;
if (i == ilim) {
if (rdir) {
@@ -465,8 +470,13 @@ gdtoa
inex = STRTOG_Inexlo;
goto ret1;
}
- dval(d) += dval(d);
- if (dval(d) > ds || dval(d) == ds && L & 1) {
+ 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')
@@ -493,13 +503,15 @@ gdtoa
m5 = b5;
mhi = mlo = 0;
if (leftright) {
- if (mode < 2) {
- i = nbits - bbits;
- if (be - i++ < fpi->emin)
- /* denormal */
- i = be - fpi->emin + 1;
+ 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 {
+ else if (mode >= 2) {
+ small_ilim:
j = ilim - 1;
if (m5 >= j)
m5 -= j;
@@ -560,28 +572,11 @@ gdtoa
* and for all and pass them and a shift to quorem, so it
* can do shifts and ors to compute the numerator for q.
*/
-#ifdef Pack_32
- if ( (i = ((s5 ? 32 - hi0bits(S->x[S->wds-1]) : 1) + s2) & 0x1f) !=0)
- i = 32 - i;
-#else
- if ( (i = ((s5 ? 32 - hi0bits(S->x[S->wds-1]) : 1) + s2) & 0xf) !=0)
- i = 16 - i;
-#endif
- if (i > 4) {
- i -= 4;
- b2 += i;
- m2 += i;
- s2 += i;
- }
- else if (i < 4) {
- i += 28;
- b2 += i;
- m2 += i;
- s2 += i;
- }
- if (b2 > 0)
+ i = ((s5 ? hi0bits(S->x[S->wds-1]) : ULbits - 1) - s2 - 4) & kmask;
+ m2 += i;
+ if ((b2 += i) > 0)
b = lshift(b, b2);
- if (s2 > 0)
+ if ((s2 += i) > 0)
S = lshift(S, s2);
if (k_check) {
if (cmp(b,S) < 0) {
@@ -646,11 +641,11 @@ gdtoa
goto ret;
}
#endif
- if (j < 0 || j == 0 && !mode
+ 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;
@@ -673,7 +668,11 @@ gdtoa
if (j1 > 0) {
b = lshift(b, 1);
j1 = cmp(b, S);
- if ((j1 > 0 || j1 == 0 && dig & 1)
+#ifdef ROUND_BIASED
+ if (j1 >= 0 /*)*/
+#else
+ if ((j1 > 0 || (j1 == 0 && dig & 1))
+#endif
&& dig++ == '9')
goto round_9_up;
inex = STRTOG_Inexhi;
@@ -718,13 +717,18 @@ gdtoa
/* Round off last digit */
if (rdir) {
- if (rdir == 2 || b->wds <= 1 && !b->x[0])
+ if (rdir == 2 || (b->wds <= 1 && !b->x[0]))
goto chopzeros;
goto roundoff;
}
b = lshift(b, 1);
j = cmp(b, S);
- if (j > 0 || j == 0 && dig & 1) {
+#ifdef ROUND_BIASED
+ if (j >= 0)
+#else
+ if (j > 0 || (j == 0 && dig & 1))
+#endif
+ {
roundoff:
inex = STRTOG_Inexhi;
while(*--s == '9')
diff --git a/gdtoa.h b/gdtoa.h
index e59ebf65d086..f004ec32746b 100644
--- a/gdtoa.h
+++ b/gdtoa.h
@@ -36,7 +36,7 @@ THIS SOFTWARE.
#include <stddef.h> /* for size_t */
#ifndef Long
-#define Long long
+#define Long int
#endif
#ifndef ULong
typedef unsigned Long ULong;
diff --git a/gdtoaimp.h b/gdtoaimp.h
index 3b038ff2ea75..89e190744f43 100644
--- a/gdtoaimp.h
+++ b/gdtoaimp.h
@@ -94,7 +94,12 @@ THIS SOFTWARE.
* #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.
+ * #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"
@@ -113,7 +118,12 @@ THIS SOFTWARE.
* #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.
+ * 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,
@@ -162,11 +172,6 @@ THIS SOFTWARE.
* #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 YES_ALIAS to permit aliasing certain double values with
- * arrays of ULongs. This leads to slightly better code with
- * some compilers and was always used prior to 19990916, but it
- * is not strictly legal and can cause trouble with aggressively
- * optimizing compilers (e.g., gcc 2.95.1 under -O2).
* #define USE_LOCALE to use the current locale's decimal_point value.
*/
@@ -270,25 +275,14 @@ Exactly one of IEEE_8087, IEEE_MC68k, VAX, or IBM should be defined.
typedef union { double d; ULong L[2]; } U;
-#ifdef YES_ALIAS
-#define dval(x) x
#ifdef IEEE_8087
-#define word0(x) ((ULong *)&x)[1]
-#define word1(x) ((ULong *)&x)[0]
+#define word0(x) (x)->L[1]
+#define word1(x) (x)->L[0]
#else
-#define word0(x) ((ULong *)&x)[0]
-#define word1(x) ((ULong *)&x)[1]
+#define word0(x) (x)->L[0]
+#define word1(x) (x)->L[1]
#endif
-#else /* !YES_ALIAS */
-#ifdef IEEE_8087
-#define word0(x) ((U*)&x)->L[1]
-#define word1(x) ((U*)&x)->L[0]
-#else
-#define word0(x) ((U*)&x)->L[0]
-#define word1(x) ((U*)&x)->L[1]
-#endif
-#define dval(x) ((U*)&x)->d
-#endif /* YES_ALIAS */
+#define dval(x) (x)->d
/* The following definition of Storeinc is appropriate for MIPS processors.
* An alternative that might be better on some machines is
@@ -402,6 +396,11 @@ typedef union { double d; ULong L[2]; } U;
#ifndef IEEE_Arith
#define ROUND_BIASED
+#else
+#ifdef ROUND_BIASED_without_Round_Up
+#undef ROUND_BIASED
+#define ROUND_BIASED
+#endif
#endif
#ifdef RND_PRODQUOT
@@ -462,7 +461,7 @@ extern double rnd_prod(double, double), rnd_quot(double, double);
#define FREE_DTOA_LOCK(n) /*nothing*/
#endif
-#define Kmax 15
+#define Kmax 9
struct
Bigint {
@@ -575,7 +574,7 @@ extern void memcpy_D2A ANSI((void*, const void*, size_t));
extern double strtod ANSI((const char *s00, char **se));
extern Bigint *sum ANSI((Bigint*, Bigint*));
extern int trailz ANSI((Bigint*));
- extern double ulp ANSI((double));
+ extern double ulp ANSI((U*));
#ifdef __cplusplus
}
diff --git a/gethex.c b/gethex.c
index c8ac8bac763e..a9982c9d33a7 100644
--- a/gethex.c
+++ b/gethex.c
@@ -57,7 +57,7 @@ gethex( CONST char **sp, FPI *fpi, Long *exp, Bigint **bp, int sign)
static unsigned char *decimalpoint_cache;
if (!(s0 = decimalpoint_cache)) {
s0 = (unsigned char*)localeconv()->decimal_point;
- if ((decimalpoint_cache = (char*)malloc(strlen(s0) + 1))) {
+ if ((decimalpoint_cache = (char*)MALLOC(strlen(s0) + 1))) {
strcpy(decimalpoint_cache, s0);
s0 = decimalpoint_cache;
}
@@ -199,7 +199,7 @@ gethex( CONST char **sp, FPI *fpi, Long *exp, Bigint **bp, int sign)
return STRTOG_Normal | STRTOG_Inexlo;
}
n = s1 - s0 - 1;
- for(k = 0; n > (1 << kshift-2) - 1; n >>= 1)
+ for(k = 0; n > (1 << (kshift-2)) - 1; n >>= 1)
k++;
b = Balloc(k);
x = b->x;
@@ -314,7 +314,7 @@ gethex( CONST char **sp, FPI *fpi, Long *exp, Bigint **bp, int sign)
break;
case FPI_Round_near:
if (lostbits & 2
- && (lostbits & 1) | x[0] & 1)
+ && (lostbits | x[0]) & 1)
up = 1;
break;
case FPI_Round_up:
@@ -333,8 +333,8 @@ gethex( CONST char **sp, FPI *fpi, Long *exp, Bigint **bp, int sign)
irv = STRTOG_Normal;
}
else if (b->wds > k
- || (n = nbits & kmask) !=0
- && hi0bits(x[k-1]) < 32-n) {
+ || ((n = nbits & kmask) !=0
+ && hi0bits(x[k-1]) < 32-n)) {
rshift(b,1);
if (++e > fpi->emax)
goto ovfl;
diff --git a/hexnan.c b/hexnan.c
index e07e069ad69e..a443721f52dd 100644
--- a/hexnan.c
+++ b/hexnan.c
@@ -77,7 +77,7 @@ hexnan( CONST char **sp, FPI *fpi, ULong *x0)
if (s[1] == '0' && (s[2] == 'x' || s[2] == 'X')
&& *(CONST unsigned char*)(s+3) > ' ')
s += 2;
- while(c = *(CONST unsigned char*)++s) {
+ while((c = *(CONST unsigned char*)++s)) {
if (!(h = hexdig[c])) {
if (c <= ' ') {
if (hd0 < havedig) {
@@ -109,7 +109,7 @@ hexnan( CONST char **sp, FPI *fpi, ULong *x0)
*sp = s + 1;
break;
}
- } while(c = *++s);
+ } while((c = *++s));
#endif
return STRTOG_NaN;
}
@@ -120,7 +120,7 @@ hexnan( CONST char **sp, FPI *fpi, ULong *x0)
i = 1;
*--x = 0;
}
- *x = (*x << 4) | h & 0xf;
+ *x = (*x << 4) | (h & 0xf);
}
if (!havedig)
return STRTOG_NaN;
diff --git a/makefile b/makefile
index 367eb9c2e132..b1f18cdf1094 100644
--- a/makefile
+++ b/makefile
@@ -30,6 +30,8 @@ CFLAGS = -g
.c.o:
$(CC) -c $(CFLAGS) $*.c
+# invoke "make Printf" to add printf.o to gdtoa.a (if desired)
+
all: arith.h gd_qnan.h gdtoa.a
arith.h: arithchk.c
@@ -42,27 +44,36 @@ gd_qnan.h: arith.h qnan.c
./a.out >gd_qnan.h
rm -f a.out qnan.o
-gdtoa.a: dmisc.c dtoa.c g_Qfmt.c g__fmt.c g_ddfmt.c g_dfmt.c g_ffmt.c\
- g_xLfmt.c g_xfmt.c gdtoa.c gethex.c gmisc.c hd_init.c hexnan.c\
- misc.c smisc.c strtoIQ.c strtoId.c strtoIdd.c strtoIf.c strtoIg.c\
- strtoIx.c strtoIxL.c strtod.c strtodI.c strtodg.c strtof.c strtopQ.c\
- strtopd.c strtopdd.c strtopf.c strtopx.c strtopxL.c strtorQ.c\
- strtord.c strtordd.c strtorf.c strtorx.c strtorxL.c sum.c ulp.c
+gdtoa.a: dmisc.c dtoa.c g_Qfmt.c g__fmt.c g_ddfmt.c g_dfmt.c\
+ g_ffmt.c g_xLfmt.c g_xfmt.c gdtoa.c gethex.c gmisc.c hd_init.c\
+ hexnan.c misc.c smisc.c strtoIQ.c strtoId.c strtoIdd.c\
+ strtoIf.c strtoIg.c strtoIx.c strtoIxL.c strtod.c strtodI.c\
+ strtodg.c strtof.c strtopQ.c strtopd.c strtopdd.c strtopf.c\
+ strtopx.c strtopxL.c strtorQ.c strtord.c strtordd.c strtorf.c\
+ strtorx.c strtorxL.c sum.c ulp.c
$(CC) -c $(CFLAGS) $?
x=`echo $? | sed 's/\.c/.o/g'` && ar ruv gdtoa.a $$x && rm $$x
ranlib gdtoa.a || true
+Printf: all printf.c
+ $(CC) -c $(CFLAGS) printf.c
+ ar ruv gdtoa.a printf.o
+ rm printf.o
+ touch Printf
+
# If your system lacks ranlib, you do not need it.
-xs0 = README arithchk.c dmisc.c dtoa.c g_Qfmt.c g__fmt.c g_ddfmt.c g_dfmt.c\
- g_ffmt.c g_xLfmt.c g_xfmt.c gdtoa.c gdtoa.h gdtoa_fltrnds.h gdtoaimp.h\
- gethex.c gmisc.c hd_init.c hexnan.c makefile misc.c qnan.c smisc.c\
- strtoIQ.c strtoId.c strtoIdd.c strtoIf.c strtoIg.c strtoIx.c strtoIxL.c\
- strtod.c strtodI.c strtodg.c strtodnrp.c strtof.c strtopQ.c strtopd.c\
- strtopdd.c strtopf.c strtopx.c strtopxL.c strtorQ.c strtord.c strtordd.c\
- strtorf.c strtorx.c strtorxL.c sum.c ulp.c
+xs0 = README arithchk.c dmisc.c dtoa.c g_Qfmt.c g__fmt.c g_ddfmt.c\
+ g_dfmt.c g_ffmt.c g_xLfmt.c g_xfmt.c gdtoa.c gdtoa.h\
+ gdtoa_fltrnds.h gdtoaimp.h gethex.c gmisc.c hd_init.c hexnan.c\
+ makefile misc.c printf.c printf.c0 qnan.c smisc.c stdio1.h\
+ strtoIQ.c strtoId.c strtoIdd.c strtoIf.c strtoIg.c strtoIx.c\
+ strtoIxL.c strtod.c strtodI.c strtodg.c strtodnrp.c strtof.c\
+ strtopQ.c strtopd.c strtopdd.c strtopf.c strtopx.c strtopxL.c\
+ strtorQ.c strtord.c strtordd.c strtorf.c strtorx.c strtorxL.c\
+ sum.c ulp.c
-# "make xsum.out" to check for transmission errors; source for xsum is
+# "make -r xsum.out" to check for transmission errors; source for xsum is
# netlib's "xsum.c from f2c", e.g.,
# ftp://netlib.bell-labs.com/netlib/f2c/xsum.c.gz
@@ -71,4 +82,4 @@ xsum.out: xsum0.out $(xs0)
cmp xsum0.out xsum1.out && mv xsum1.out xsum.out || diff xsum[01].out
clean:
- rm -f arith.h gd_qnan.h *.[ao] xsum.out xsum1.out
+ rm -f arith.h gd_qnan.h *.[ao] Printf xsum.out xsum1.out
diff --git a/misc.c b/misc.c
index b3ce7c9b8a4a..e5f7b046b2e8 100644
--- a/misc.c
+++ b/misc.c
@@ -55,7 +55,9 @@ Balloc
#endif
ACQUIRE_DTOA_LOCK(0);
- if ( (rv = freelist[k]) !=0) {
+ /* The k > Kmax case does not need ACQUIRE_DTOA_LOCK(0), */
+ /* but this case seems very unlikely. */
+ if (k <= Kmax && (rv = freelist[k]) !=0) {
freelist[k] = rv->next;
}
else {
@@ -65,7 +67,7 @@ Balloc
#else
len = (sizeof(Bigint) + (x-1)*sizeof(ULong) + sizeof(double) - 1)
/sizeof(double);
- if (pmem_next - private_mem + len <= PRIVATE_mem) {
+ if (k <= Kmax && pmem_next - private_mem + len <= PRIVATE_mem) {
rv = (Bigint*)pmem_next;
pmem_next += len;
}
@@ -89,10 +91,18 @@ Bfree
#endif
{
if (v) {
- ACQUIRE_DTOA_LOCK(0);
- v->next = freelist[v->k];
- freelist[v->k] = v;
- FREE_DTOA_LOCK(0);
+ if (v->k > Kmax)
+#ifdef FREE
+ FREE((void*)v);
+#else
+ free((void*)v);
+#endif
+ else {
+ ACQUIRE_DTOA_LOCK(0);
+ v->next = freelist[v->k];
+ freelist[v->k] = v;
+ FREE_DTOA_LOCK(0);
+ }
}
}
@@ -104,8 +114,8 @@ lo0bits
(ULong *y)
#endif
{
- register int k;
- register ULong x = *y;
+ int k;
+ ULong x = *y;
if (x & 7) {
if (x & 1)
@@ -204,12 +214,12 @@ multadd
int
hi0bits_D2A
#ifdef KR_headers
- (x) register ULong x;
+ (x) ULong x;
#else
- (register ULong x)
+ (ULong x)
#endif
{
- register int k = 0;
+ int k = 0;
if (!(x & 0xffff0000)) {
k = 16;
@@ -612,12 +622,12 @@ b2d
{
ULong *xa, *xa0, w, y, z;
int k;
- double d;
+ U d;
#ifdef VAX
ULong d0, d1;
#else
-#define d0 word0(d)
-#define d1 word1(d)
+#define d0 word0(&d)
+#define d1 word1(&d)
#endif
xa0 = a->x;
@@ -630,16 +640,16 @@ b2d
*e = 32 - k;
#ifdef Pack_32
if (k < Ebits) {
- d0 = Exp_1 | y >> Ebits - k;
+ d0 = Exp_1 | y >> (Ebits - k);
w = xa > xa0 ? *--xa : 0;
- d1 = y << (32-Ebits) + k | w >> Ebits - k;
+ d1 = y << ((32-Ebits) + k) | w >> (Ebits - k);
goto ret_d;
}
z = xa > xa0 ? *--xa : 0;
if (k -= Ebits) {
- d0 = Exp_1 | y << k | z >> 32 - k;
+ d0 = Exp_1 | y << k | z >> (32 - k);
y = xa > xa0 ? *--xa : 0;
- d1 = z << k | y >> 32 - k;
+ d1 = z << k | y >> (32 - k);
}
else {
d0 = Exp_1 | y;
@@ -663,10 +673,10 @@ b2d
#endif
ret_d:
#ifdef VAX
- word0(d) = d0 >> 16 | d0 << 16;
- word1(d) = d1 >> 16 | d1 << 16;
+ word0(&d) = d0 >> 16 | d0 << 16;
+ word1(&d) = d1 >> 16 | d1 << 16;
#endif
- return dval(d);
+ return dval(&d);
}
#undef d0
#undef d1
@@ -674,12 +684,13 @@ b2d
Bigint *
d2b
#ifdef KR_headers
- (d, e, bits) double d; int *e, *bits;
+ (dd, e, bits) double dd; int *e, *bits;
#else
- (double d, int *e, int *bits)
+ (double dd, int *e, int *bits)
#endif
{
Bigint *b;
+ U d;
#ifndef Sudden_Underflow
int i;
#endif
@@ -687,11 +698,14 @@ d2b
ULong *x, y, z;
#ifdef VAX
ULong d0, d1;
- d0 = word0(d) >> 16 | word0(d) << 16;
- d1 = word1(d) >> 16 | word1(d) << 16;
#else
-#define d0 word0(d)
-#define d1 word1(d)
+#define d0 word0(&d)
+#define d1 word1(&d)
+#endif
+ d.d = dd;
+#ifdef VAX
+ d0 = word0(&d) >> 16 | word0(&d) << 16;
+ d1 = word1(&d) >> 16 | word1(&d) << 16;
#endif
#ifdef Pack_32
@@ -715,7 +729,7 @@ d2b
#ifdef Pack_32
if ( (y = d1) !=0) {
if ( (k = lo0bits(&y)) !=0) {
- x[0] = y | z << 32 - k;
+ x[0] = y | z << (32 - k);
z >>= k;
}
else
@@ -726,10 +740,6 @@ d2b
b->wds = (x[1] = z) !=0 ? 2 : 1;
}
else {
-#ifdef DEBUG
- if (!z)
- Bug("Zero passed to d2b");
-#endif
k = lo0bits(&z);
x[0] = z;
#ifndef Sudden_Underflow
@@ -788,7 +798,7 @@ d2b
#endif
#ifdef IBM
*e = (de - Bias - (P-1) << 2) + k;
- *bits = 4*P + 8 - k - hi0bits(word0(d) & Frac_mask);
+ *bits = 4*P + 8 - k - hi0bits(word0(&d) & Frac_mask);
#else
*e = de - Bias - (P-1) + k;
*bits = P - k;
@@ -841,7 +851,7 @@ strcp_D2A(a, b) char *a; char *b;
strcp_D2A(char *a, CONST char *b)
#endif
{
- while(*a = *b++)
+ while((*a = *b++))
a++;
return a;
}
@@ -855,8 +865,8 @@ memcpy_D2A(a, b, len) Char *a; Char *b; size_t len;
memcpy_D2A(void *a1, void *b1, size_t len)
#endif
{
- register char *a = (char*)a1, *ae = a + len;
- register char *b = (char*)b1, *a0 = a;
+ char *a = (char*)a1, *ae = a + len;
+ char *b = (char*)b1, *a0 = a;
while(a < ae)
*a++ = *b++;
return a0;
diff --git a/printf.c b/printf.c
new file mode 100644
index 000000000000..02f1f3cd4de9
--- /dev/null
+++ b/printf.c
@@ -0,0 +1,8 @@
+#ifdef __sun
+#define Use_GDTOA_Qtype
+#else
+#if defined(__i386) || defined(__x86_64)
+#define Use_GDTOA_for_i386_long_double
+#endif
+#endif
+#include "printf.c0"
diff --git a/printf.c0 b/printf.c0
new file mode 100644
index 000000000000..c33bcc1a4f70
--- /dev/null
+++ b/printf.c0
@@ -0,0 +1,1669 @@
+/****************************************************************
+Copyright (C) 1997, 1999, 2001 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 implements most of ANSI C's printf, fprintf, and sprintf,
+ * omitting L, with %.0g and %.0G giving the shortest decimal string
+ * that rounds to the number being converted, and with negative
+ * precisions allowed for %f.
+ */
+
+#ifdef KR_headers
+#include "varargs.h"
+#else
+#include "stddef.h"
+#include "stdarg.h"
+#include "stdlib.h"
+#endif
+
+#ifdef Use_GDTOA_for_i386_long_double /*{{*/
+#include "gdtoa.h"
+#else /*}{*/
+#ifndef NO_PRINTF_A_FMT /*{*/
+#include "gdtoa.h"
+#endif /*}*/
+#endif /*}}*/
+
+#ifdef __i386
+#define NO_GDTOA_i386_Quad
+#endif
+
+#ifdef Use_GDTOA_for_i386_long_double /*{*/
+#ifndef NO_GDTOA_i386_Quad /*{*/
+#define GDTOA_both
+#define Use_GDTOA_Qtype
+#ifdef __ICC__ /* or __INTEL_COMPILER__ or __INTEL_COMPILER ?? */
+#define GDTOA_Qtype _Quad
+#else
+#define GDTOA_Qtype __float128
+#endif
+#endif /*} NO_GDTOA_i386_Quad */
+#endif /*} Use_GDTOA_for_i386_long_double */
+
+#ifdef Use_GDTOA_Qtype /*{*/
+#ifndef GDTOA_H_INCLUDED
+#include "gdtoa.h"
+#endif
+#ifndef GDTOA_Qtype
+#define GDTOA_Qtype long double
+#endif
+#endif /*}*/
+
+#ifndef 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};
+
+ 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 /*}*/
+
+#ifdef NO_PRINTF_A_FMT /*{{*/
+#define WANT_A_FMT(x) /*nothing*/
+#else /*}{*/
+#define WANT_A_FMT(x) x
+#endif /*}}*/
+
+#include "stdio1.h"
+#include "string.h"
+#include "errno.h"
+
+ typedef struct
+Finfo {
+ union { FILE *cf; char *sf; } u;
+ char *ob0, *obe1;
+ size_t lastlen;
+ } Finfo;
+
+ typedef char *(*pgdtoa) ANSI((FPI*, int be, ULong *bits, int *kind, int mode, int ndigits, int *decpt, char **rve));
+
+ typedef struct
+FPBits {
+ ULong bits[4]; /* sufficient for quad; modify if considering wider types */
+ FPI *fpi;
+ pgdtoa gdtoa;
+ int sign;
+ int ex; /* exponent */
+ int kind;
+ } FPBits;
+
+ typedef union U
+{
+ double d;
+ long double ld;
+#ifdef GDTOA_Qtype
+ GDTOA_Qtype Qd;
+#endif
+ unsigned int ui[4];
+ unsigned short us[5];
+ } U;
+
+ typedef char *(*Putfunc) ANSI((Finfo*, int*));
+ typedef void (*Fpbits) ANSI((U*, FPBits*));
+
+/* Would have preferred typedef void (*Fpbits)(va_list*, FPBits*)
+ * but gcc is buggy in this regard.
+ */
+
+#ifdef Use_GDTOA_for_i386_long_double /*{*/
+
+#ifdef IEEE_MC68k
+#define _0 0
+#define _1 1
+#define _2 2
+#define _3 3
+#define _4 4
+#endif
+#ifdef IEEE_8087
+#define _0 4
+#define _1 3
+#define _2 2
+#define _3 1
+#define _4 0
+#endif
+
+ static void
+xfpbits(U *u, FPBits *b)
+{
+ ULong *bits;
+ int ex, i;
+ static FPI fpi0 = { 64, 1-16383-64+1, 32766 - 16383 - 64 + 1, 1, 0 };
+
+ b->fpi = &fpi0;
+ b->gdtoa = gdtoa;
+ b->sign = u->us[_0] & 0x8000;
+ bits = b->bits;
+ bits[1] = (u->us[_1] << 16) | u->us[_2];
+ bits[0] = (u->us[_3] << 16) | u->us[_4];
+ if ( (ex = u->us[_0] & 0x7fff) !=0) {
+ i = STRTOG_Normal;
+ if (ex == 0x7fff)
+ /* Infinity or NaN */
+ i = bits[0] | bits[1] ? STRTOG_NaN : STRTOG_Infinite;
+ }
+ else if (bits[0] | bits[1]) {
+ i = STRTOG_Denormal;
+ ex = 1;
+ }
+ else
+ i = STRTOG_Zero;
+ b->kind = i;
+ b->ex = ex - (0x3fff + 63);
+ }
+
+#undef _0
+#undef _1
+#undef _2
+#undef _3
+#undef _4
+#define GDTOA_LD_fpbits xfpbits
+#endif /*} Use_GDTOA_for_i386_long_double */
+
+#ifdef Use_GDTOA_Qtype /*{*/
+#include "gdtoa.h"
+#ifndef GDTOA_Qtype
+#define GDTOA_Qtype long double
+#endif
+#ifdef GDTOA_LD_fpbits
+#define GDTOA_Q_fpbits Qfpbits
+#else
+#define GDTOA_LD_fpbits Qfpbits
+#endif
+
+#ifdef IEEE_MC68k
+#define _0 0
+#define _1 1
+#define _2 2
+#define _3 3
+#endif
+#ifdef IEEE_8087
+#define _0 3
+#define _1 2
+#define _2 1
+#define _3 0
+#endif
+
+ static void
+Qfpbits(U *u, FPBits *b)
+{
+ ULong *bits;
+ int ex, i;
+ static FPI fpi0 = { 113, 1-16383-113+1, 32766 - 16383 - 113 + 1, 1, 0 };
+
+ b->fpi = &fpi0;
+ b->gdtoa = gdtoa;
+ b->sign = u->ui[_0] & 0x80000000L;
+ bits = b->bits;
+ bits[3] = u->ui[_0] & 0xffff;
+ bits[2] = u->ui[_1];
+ bits[1] = u->ui[_2];
+ bits[0] = u->ui[_3];
+ if ( (ex = (u->ui[_0] & 0x7fff0000L) >> 16) !=0) {
+ if (ex == 0x7fff) {
+ /* Infinity or NaN */
+ i = bits[0] | bits[1] | bits[2] | bits[3]
+ ? STRTOG_NaN : STRTOG_Infinite;
+ }
+ else {
+ i = STRTOG_Normal;
+ bits[3] |= 0x10000;
+ }
+ }
+ else if (bits[0] | bits[1] | bits[2] | bits[3]) {
+ i = STRTOG_Denormal;
+ ex = 1;
+ }
+ else
+ i = STRTOG_Zero;
+ b->kind = i;
+ b->ex = ex - (0x3fff + 112);
+ }
+
+#undef _0
+#undef _1
+#undef _2
+#undef _3
+#endif /*} GDTOA_Qtype */
+
+#ifdef KR_headers
+#define Const /* const */
+#define Voidptr char*
+#ifndef size_t__
+#define size_t int
+#define size_t__
+#endif
+
+#else
+
+#define Const const
+#define Voidptr void*
+
+#endif
+
+#undef MESS
+#ifndef Stderr
+#define Stderr stderr
+#endif
+
+#ifdef _windows_
+#undef PF_BUF
+#define MESS
+#include "mux0.h"
+#define stdout_or_err(f) (f == stdout)
+#else
+#define stdout_or_err(f) (f == Stderr || f == stdout)
+#endif
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+ extern char *dtoa ANSI((double, int, int, int*, int*, char **));
+ extern void freedtoa ANSI((char*));
+
+
+
+#ifdef USE_ULDIV
+/* This is for avoiding 64-bit divisions on the DEC Alpha, since */
+/* they are not portable among variants of OSF1 (DEC's Unix). */
+
+#define ULDIV(a,b) uldiv_ASL(a,(unsigned long)(b))
+
+#ifndef LLBITS
+#define LLBITS 6
+#endif
+#ifndef ULONG
+#define ULONG unsigned long
+#endif
+
+ static int
+klog(ULONG x)
+{
+ int k, rv = 0;
+
+ if (x > 1L)
+ for(k = 1 << LLBITS-1;;) {
+ if (x >= (1L << k)) {
+ rv |= k;
+ x >>= k;
+ }
+ if (!(k >>= 1))
+ break;
+ }
+ return rv;
+ }
+
+ ULONG
+uldiv_ASL(ULONG a, ULONG b)
+{
+ int ka;
+ ULONG c, k;
+ static ULONG b0;
+ static int kb;
+
+ if (a < b)
+ return 0;
+ if (b != b0) {
+ b0 = b;
+ kb = klog(b);
+ }
+ k = 1;
+ if ((ka = klog(a) - kb) > 0) {
+ k <<= ka;
+ b <<= ka;
+ }
+ c = 0;
+ for(;;) {
+ if (a >= b) {
+ a -= b;
+ c |= k;
+ }
+ if (!(k >>= 1))
+ break;
+ a <<= 1;
+ }
+ return c;
+ }
+
+#else
+#define ULDIV(a,b) a / b
+#endif /* USE_ULDIV */
+
+#ifdef PF_BUF
+FILE *stderr_ASL = (FILE*)&stderr_ASL;
+void (*pfbuf_print_ASL) ANSI((char*));
+char *pfbuf_ASL;
+static char *pfbuf_next;
+static size_t pfbuf_len;
+extern Char *mymalloc_ASL ANSI((size_t));
+extern Char *myralloc_ASL ANSI((void *, size_t));
+
+#undef fflush
+#ifdef old_fflush_ASL
+#define fflush old_fflush_ASL
+#endif
+
+ void
+fflush_ASL(FILE *f)
+{
+ if (f == stderr_ASL) {
+ if (pfbuf_ASL && pfbuf_print_ASL) {
+ (*pfbuf_print_ASL)(pfbuf_ASL);
+ free(pfbuf_ASL);
+ pfbuf_ASL = 0;
+ }
+ }
+ else
+ fflush(f);
+ }
+
+ static void
+pf_put(char *buf, int len)
+{
+ size_t x, y;
+ if (!pfbuf_ASL) {
+ x = len + 256;
+ if (x < 512)
+ x = 512;
+ pfbuf_ASL = pfbuf_next = (char*)mymalloc_ASL(pfbuf_len = x);
+ }
+ else if ((y = (pfbuf_next - pfbuf_ASL) + len) >= pfbuf_len) {
+ x = pfbuf_len;
+ while((x <<= 1) <= y);
+ y = pfbuf_next - pfbuf_ASL;
+ pfbuf_ASL = (char*)myralloc_ASL(pfbuf_ASL, x);
+ pfbuf_next = pfbuf_ASL + y;
+ pfbuf_len = x;
+ }
+ memcpy(pfbuf_next, buf, len);
+ pfbuf_next += len;
+ *pfbuf_next = 0;
+ }
+
+ static char *
+pfput(Finfo *f, int *rvp)
+{
+ int n;
+ char *ob0 = f->ob0;
+ *rvp += n = (int)(f->obe1 - ob0);
+ pf_put(ob0, n);
+ return ob0;
+ }
+#endif /* PF_BUF */
+
+ static char *
+Fput
+#ifdef KR_headers
+ (f, rvp) Finfo *f; int *rvp;
+#else
+ (Finfo *f, int *rvp)
+#endif
+{
+ char *ob0 = f->ob0;
+
+ *rvp += f->obe1 - ob0;
+ *f->obe1 = 0;
+ fputs(ob0, f->u.cf);
+ return ob0;
+ }
+
+
+#ifdef _windows_
+int stdout_fileno_ASL = 1;
+
+ static char *
+Wput
+#ifdef KR_headers
+ (f, rvp) Finfo *f; int *rvp;
+#else
+ (Finfo *f, int *rvp)
+#endif
+{
+ char *ob0 = f->ob0;
+
+ *rvp += f->obe1 - ob0;
+ *f->obe1 = 0;
+ mwrite(ob0, f->obe1 - ob0);
+ return ob0;
+ }
+#endif /*_windows_*/
+
+
+#ifdef IEEE_MC68k
+#define _0 0
+#define _1 1
+#endif
+#ifdef IEEE_8087
+#define _0 1
+#define _1 0
+#endif
+
+ static void
+dfpbits(U *u, FPBits *b)
+{
+ ULong *bits;
+ int ex, i;
+ static FPI fpi0 = { 53, 1-1023-53+1, 2046-1023-53+1, 1, 0 };
+
+ b->fpi = &fpi0;
+ b->gdtoa = gdtoa;
+ b->sign = u->ui[_0] & 0x80000000L;
+ bits = b->bits;
+ bits[1] = u->ui[_0] & 0xfffff;
+ bits[0] = u->ui[_1];
+ if ( (ex = (u->ui[_0] & 0x7ff00000L) >> 20) !=0) {
+ if (ex == 0x7ff) {
+ /* Infinity or NaN */
+ i = bits[0] | bits[1] ? STRTOG_NaN : STRTOG_Infinite;
+ }
+ else {
+ i = STRTOG_Normal;
+ bits[1] |= 0x100000;
+ }
+ }
+ else if (bits[0] | bits[1]) {
+ i = STRTOG_Denormal;
+ ex = 1;
+ }
+ else
+ i = STRTOG_Zero;
+ b->kind = i;
+ b->ex = ex - (0x3ff + 52);
+ }
+
+#undef _0
+#undef _1
+
+#ifdef Honor_FLT_ROUNDS /*{{*/
+#ifdef Trust_FLT_ROUNDS /*{{*/
+#define RoundCheck if (Rounding == -1) Rounding = Flt_Rounds; if (Rounding != 1){\
+ fpi1 = *fpb.fpi; fpi1.rounding = Rounding; fpb.fpi = &fpi1;}
+#else /*}{*/
+#define RoundCheck if (Rounding == -1) { Rounding = 1; switch((fegetround()) {\
+ case FE_TOWARDZERO: Rounding = 0; break;\
+ case FE_UPWARD: Rounding = 2; break;\
+ case FE_DOWNWARD: Rounding = 3; }}\
+ if (Rounding != 1){\
+ fpi1 = *fpb.fpi; fpi1.rounding = Rounding; fpb.fpi = &fpi1;}
+#endif /*}}*/
+#else /*}{*/
+#define RoundCheck /*nothing*/
+#endif /*}}*/
+
+#ifndef NO_PRINTF_A_FMT /*{*/
+ static int
+fpiprec(FPBits *b) /* return number of hex digits minus 1, or 0 for zero */
+{
+ FPI *fpi;
+ ULong *bits;
+ int i, j, k, m;
+
+ if (b->kind == STRTOG_Zero)
+ return b->ex = 0;
+ fpi = b->fpi;
+ bits = b->bits;
+ for(k = (fpi->nbits - 1) >> 2; k > 0; --k)
+ if ((bits[k >> 3] >> 4*(k & 7)) & 0xf) {
+ m = k >> 3;
+ for(i = 0; i <= m; ++i)
+ if (bits[i]) {
+ if (i > 0) {
+ k -= 8*i;
+ b->ex += 32*i;
+ for(j = i; j <= m; ++j)
+ bits[j-i] = bits[j];
+ }
+ break;
+ }
+ for(i = 0; i < 28 && !((bits[0] >> i) & 0xf); i += 4);
+ if (i) {
+ b->ex += i;
+ m = k >> 3;
+ k -= (i >> 2);
+ for(j = 0;;++j) {
+ bits[j] >>= i;
+ if (j == m)
+ break;
+ bits[j] |= bits[j+1] << (32 - i);
+ }
+ }
+ break;
+ }
+ return k;
+ }
+
+ static int
+bround(FPBits *b, int prec, int prec1) /* round to prec hex digits after the "." */
+{ /* prec1 = incoming precision (after ".") */
+ FPI *fpi = b->fpi;
+ ULong *bits, t;
+ int i, inc, j, k, m, n;
+#ifdef Honor_FLT_ROUNDS
+ int rounding = fpi->rounding;
+
+ if (rounding > FPI_Round_near && b->sign)
+ rounding = FPI_Round_up + FPI_Round_down - rounding;
+ if (rounding == FPI_Round_down)
+ rounding = FPI_Round_zero;
+#endif
+ m = prec1 - prec;
+ bits = b->bits;
+ inc = 0;
+#ifdef Honor_FLT_ROUNDS
+ switch(rounding) {
+ case FPI_Round_up:
+ for(i = 0; i < m; i += 8)
+ if (bits[i>>3])
+ goto inc1;
+ if ((j = i - m) > 0 && bits[(i-8)>>3] << j*4)
+ goto inc1;
+ break;
+ case FPI_Round_near:
+#endif
+ k = m - 1;
+ if ((t = bits[k >> 3] >> (j = (k&7)*4)) & 8) {
+ if (t & 7)
+ goto inc1;
+ if (j && bits[k >> 3] << (32 - j))
+ goto inc1;
+ while(k >= 8) {
+ k -= 8;
+ if (bits[k>>3]) {
+ inc1:
+ inc = 1;
+ goto haveinc;
+ }
+ }
+ }
+#ifdef Honor_FLT_ROUNDS
+ }
+#endif
+ haveinc:
+ b->ex += m*4;
+ i = m >> 3;
+ k = prec1 >> 3;
+ j = i;
+ if ((n = 4*(m & 7)))
+ for(;; ++j) {
+ bits[j-i] = bits[j] >> n;
+ if (j == k)
+ break;
+ bits[j-i] |= bits[j+1] << (32-n);
+ }
+ else
+ for(;; ++j) {
+ bits[j-i] = bits[j];
+ if (j == k)
+ break;
+ }
+ k = prec >> 3;
+ if (inc) {
+ for(j = 0; !(++bits[j] & 0xffffffff); ++j);
+ if (j > k) {
+ onebit:
+ bits[0] = 1;
+ b->ex += 4*prec;
+ return 1;
+ }
+ if ((j = prec & 7) < 7 && bits[k] >> (j+1)*4)
+ goto onebit;
+ }
+ for(i = 0; !(bits[i >> 3] & (0xf << 4*(i&7))); ++i);
+ if (i) {
+ b->ex += 4*i;
+ prec -= i;
+ j = i >> 3;
+ i &= 7;
+ i *= 4;
+ for(m = j; ; ++m) {
+ bits[m-j] = bits[m] >> i;
+ if (m == k)
+ break;
+ bits[m-j] |= bits[m+1] << (32 - i);
+ }
+ }
+ return prec;
+ }
+#endif /*}NO_PRINTF_A_FMT*/
+
+#define put(x) { *outbuf++ = x; if (outbuf == obe) outbuf = (*fput)(f,&rv); }
+
+ static int
+x_sprintf
+#ifdef KR_headers
+ (obe, fput, f, fmt, ap)
+ char *obe, *fmt; Finfo *f; Putfunc fput; va_list ap;
+#else
+ (char *obe, Putfunc fput, Finfo *f, const char *fmt, va_list ap)
+#endif
+{
+ FPBits fpb;
+ Fpbits fpbits;
+ U u;
+ char *digits, *ob0, *outbuf, *s, *s0, *se;
+ Const char *fmt0;
+ char buf[32];
+ long i;
+ unsigned long j, ul;
+ double x;
+ int alt, base, c, decpt, dot, conv, i1, k, lead0, left,
+ len, prec, prec1, psign, rv, sign, width;
+ long Ltmp, *ip;
+ short sh;
+ unsigned short us;
+ unsigned int ui;
+#ifdef Honor_FLT_ROUNDS
+ FPI fpi1;
+ int Rounding = -1;
+#endif
+#ifndef NO_PRINTF_A_FMT /*{*/
+ int bex, bw;
+#endif /*} NO_PRINTF_A_FMT */
+ static char hex[] = "0123456789abcdefpx";
+ static char Hex[] = "0123456789ABCDEFPX";
+
+ ob0 = outbuf = f->ob0;
+ rv = 0;
+ for(;;) {
+ for(;;) {
+ switch(c = *fmt++) {
+ case 0:
+ goto done;
+ case '%':
+ break;
+ default:
+ put(c)
+ continue;
+ }
+ break;
+ }
+ alt=dot=lead0=left=len=prec=psign=sign=width=0;
+ fpbits = dfpbits;
+ fmt0 = fmt;
+ fmtloop:
+ switch(conv = *fmt++) {
+ case ' ':
+ case '+':
+ sign = conv;
+ goto fmtloop;
+ case '-':
+ if (dot)
+ psign = 1;
+ else
+ left = 1;
+ goto fmtloop;
+ case '#':
+ alt = 1;
+ goto fmtloop;
+ case '0':
+ if (!lead0 && !dot) {
+ lead0 = 1;
+ goto fmtloop;
+ }
+ case '1':
+ case '2':
+ case '3':
+ case '4':
+ case '5':
+ case '6':
+ case '7':
+ case '8':
+ case '9':
+ k = conv - '0';
+ while((c = *fmt) >= '0' && c <= '9') {
+ k = 10*k + c - '0';
+ fmt++;
+ }
+ if (dot)
+ prec = psign ? -k : k;
+ else
+ width = k;
+ goto fmtloop;
+ case 'h':
+ len = 2;
+ goto fmtloop;
+ case 'L':
+#ifdef GDTOA_LD_fpbits /*{*/
+ fpbits = GDTOA_LD_fpbits;
+#ifdef GDTOA_Q_fpbits
+ if (*fmt == 'q') {
+ ++fmt;
+ fpbits = Qfpbits;
+ }
+#endif
+#endif /*}*/
+ goto fmtloop;
+ case 'l':
+ len = 1;
+ goto fmtloop;
+ case '.':
+ dot = 1;
+ goto fmtloop;
+ case '*':
+ k = va_arg(ap, int);
+ if (dot)
+ prec = k;
+ else {
+ if (k < 0) {
+ sign = '-';
+ k = -k;
+ }
+ width = k;
+ }
+ goto fmtloop;
+ case 'c':
+ c = va_arg(ap, int);
+ put(c)
+ continue;
+ case '%':
+ put(conv)
+ continue;
+ case 'u':
+ switch(len) {
+ case 0:
+ ui = va_arg(ap, int);
+ i = ui;
+ break;
+ case 1:
+ i = va_arg(ap, long);
+ break;
+ case 2:
+ us = va_arg(ap, int);
+ i = us;
+ }
+ sign = 0;
+ goto have_i;
+ case 'i':
+ case 'd':
+ switch(len) {
+ case 0:
+ k = va_arg(ap, int);
+ i = k;
+ break;
+ case 1:
+ i = va_arg(ap, long);
+ break;
+ case 2:
+ sh = va_arg(ap, int);
+ i = sh;
+ }
+ if (i < 0) {
+ sign = '-';
+ i = -i;
+ }
+ have_i:
+ base = 10;
+ ul = i;
+ digits = hex;
+ baseloop:
+ if (dot)
+ lead0 = 0;
+ s = buf;
+ if (!ul)
+ alt = 0;
+ do {
+ j = ULDIV(ul, base);
+ *s++ = digits[ul - base*j];
+ }
+ while((ul = j));
+ prec -= c = s - buf;
+ if (alt && conv == 'o' && prec <= 0)
+ prec = 1;
+ if ((width -= c) > 0) {
+ if (prec > 0)
+ width -= prec;
+ if (sign)
+ width--;
+ if (alt == 2)
+ width--;
+ }
+ if (left) {
+ if (alt == 2)
+ put('0') /* for 0x */
+ if (sign)
+ put(sign)
+ while(--prec >= 0)
+ put('0')
+ do put(*--s)
+ while(s > buf);
+ while(--width >= 0)
+ put(' ')
+ continue;
+ }
+ if (width > 0) {
+ if (lead0) {
+ if (alt == 2)
+ put('0')
+ if (sign)
+ put(sign)
+ while(--width >= 0)
+ put('0')
+ goto s_loop;
+ }
+ else
+ while(--width >= 0)
+ put(' ')
+ }
+ if (alt == 2)
+ put('0')
+ if (sign)
+ put(sign)
+ s_loop:
+ while(--prec >= 0)
+ put('0')
+ do put(*--s)
+ while(s > buf);
+ continue;
+ case 'n':
+ ip = va_arg(ap, long*);
+ if (!ip)
+ ip = &Ltmp;
+ c = outbuf - ob0 + rv;
+ switch(len) {
+ case 0:
+ *(int*)ip = c;
+ break;
+ case 1:
+ *ip = c;
+ break;
+ case 2:
+ *(short*)ip = c;
+ }
+ break;
+ case 'p':
+ len = alt = 1;
+ /* no break */
+ case 'x':
+ digits = hex;
+ goto more_x;
+ case 'X':
+ digits = Hex;
+ more_x:
+ if (alt) {
+ alt = 2;
+ sign = conv;
+ }
+ else
+ sign = 0;
+ base = 16;
+ get_u:
+ switch(len) {
+ case 0:
+ ui = va_arg(ap, int);
+ ul = ui;
+ break;
+ case 1:
+ ul = va_arg(ap, long);
+ break;
+ case 2:
+ us = va_arg(ap, int);
+ ul = us;
+ }
+ if (!ul)
+ sign = alt = 0;
+ goto baseloop;
+ case 'o':
+ base = 8;
+ digits = hex;
+ goto get_u;
+ case 's':
+ s0 = 0;
+ s = va_arg(ap, char*);
+ if (!s)
+ s = "<NULL>";
+ if (prec < 0)
+ prec = 0;
+ have_s:
+ if (dot) {
+ for(c = 0; c < prec; c++)
+ if (!s[c])
+ break;
+ prec = c;
+ }
+ else
+ prec = strlen(s);
+ width -= prec;
+ if (!left)
+ while(--width >= 0)
+ put(' ')
+ while(--prec >= 0)
+ put(*s++)
+ while(--width >= 0)
+ put(' ')
+ if (s0)
+ freedtoa(s0);
+ continue;
+ case 'f':
+ if (!dot)
+ prec = 6;
+#ifdef GDTOA_H_INCLUDED
+ if (fpbits == dfpbits) {
+#endif
+ x = va_arg(ap, double);
+ s = s0 = dtoa(x, 3, prec, &decpt, &fpb.sign, &se);
+#ifdef GDTOA_H_INCLUDED
+ }
+ else {
+#ifdef GDTOA_both
+ if (fpbits == GDTOA_LD_fpbits)
+ u.ld = va_arg(ap, long double);
+ else
+ u.Qd = va_arg(ap, GDTOA_Qtype);
+#else
+ u.ld = va_arg(ap, long double);
+#endif
+ fpbits(&u, &fpb);
+ RoundCheck
+ s = s0 = fpb.gdtoa(fpb.fpi, fpb.ex, fpb.bits,
+ &fpb.kind, 3, prec, &decpt, &se);
+ }
+#endif
+ if (decpt == 9999) {
+ fmt9999:
+ dot = prec = alt = 0;
+ if (*s == 'N')
+ goto have_s;
+ decpt = strlen(s);
+ }
+ f_fmt:
+ if (fpb.sign && (x||sign))
+ sign = '-';
+ if (prec > 0)
+ width -= prec;
+ if (width > 0) {
+ if (sign)
+ --width;
+ if (decpt <= 0) {
+ --width;
+ if (prec > 0)
+ --width;
+ }
+ else {
+ if (s == se)
+ decpt = 1;
+ width -= decpt;
+ if (prec > 0 || alt)
+ --width;
+ }
+ }
+ if (width > 0 && !left) {
+ if (lead0) {
+ if (sign)
+ put(sign)
+ sign = 0;
+ do put('0')
+ while(--width > 0);
+ }
+ else do put(' ')
+ while(--width > 0);
+ }
+ if (sign)
+ put(sign)
+ if (decpt <= 0) {
+ put('0')
+ if (prec > 0 || alt)
+ put('.')
+ while(decpt < 0) {
+ put('0')
+ prec--;
+ decpt++;
+ }
+ }
+ else {
+ do {
+ if ((c = *s))
+ s++;
+ else
+ c = '0';
+ put(c)
+ }
+ while(--decpt > 0);
+ if (prec > 0 || alt)
+ put('.')
+ }
+ while(--prec >= 0) {
+ if ((c = *s))
+ s++;
+ else
+ c = '0';
+ put(c)
+ }
+ while(--width >= 0)
+ put(' ')
+ if (s0)
+ freedtoa(s0);
+ continue;
+ case 'G':
+ case 'g':
+ if (!dot)
+ prec = 6;
+ if (prec < 0)
+ prec = 0;
+#ifdef GDTOA_H_INCLUDED
+ if (fpbits == dfpbits) {
+#endif
+ x = va_arg(ap, double);
+ s = s0 = dtoa(x, prec ? 2 : 0, prec, &decpt,
+ &fpb.sign, &se);
+#ifdef GDTOA_H_INCLUDED
+ }
+ else {
+#ifdef GDTOA_both
+ if (fpbits == GDTOA_LD_fpbits)
+ u.ld = va_arg(ap, long double);
+ else
+ u.Qd = va_arg(ap, GDTOA_Qtype);
+#else
+ u.ld = va_arg(ap, long double);
+#endif
+ fpbits(&u, &fpb);
+ RoundCheck
+ s = s0 = fpb.gdtoa(fpb.fpi, fpb.ex, fpb.bits,
+ &fpb.kind, prec ? 2 : 0, prec, &decpt, &se);
+ }
+#endif
+ if (decpt == 9999)
+ goto fmt9999;
+ c = se - s;
+ prec1 = prec;
+ if (!prec) {
+ prec = c;
+ prec1 = c + (s[1] || alt ? 5 : 4);
+ /* %.0g gives 10 rather than 1e1 */
+ }
+ if (decpt > -4 && decpt <= prec1) {
+ if (alt)
+ prec -= decpt;
+ else
+ prec = c - decpt;
+ if (prec < 0)
+ prec = 0;
+ goto f_fmt;
+ }
+ conv -= 2;
+ if (!alt && prec > c)
+ prec = c;
+ --prec;
+ goto e_fmt;
+ case 'e':
+ case 'E':
+ if (!dot)
+ prec = 6;
+ if (prec < 0)
+ prec = 0;
+#ifdef GDTOA_H_INCLUDED
+ if (fpbits == dfpbits) {
+#endif
+ x = va_arg(ap, double);
+ s = s0 = dtoa(x, prec ? 2 : 0, prec+1, &decpt,
+ &fpb.sign, &se);
+#ifdef GDTOA_H_INCLUDED
+ }
+ else {
+#ifdef GDTOA_both
+ if (fpbits == GDTOA_LD_fpbits)
+ u.ld = va_arg(ap, long double);
+ else
+ u.Qd = va_arg(ap, GDTOA_Qtype);
+#else
+ u.ld = va_arg(ap, long double);
+#endif
+ fpbits(&u, &fpb);
+ RoundCheck
+ s = s0 = fpb.gdtoa(fpb.fpi, fpb.ex, fpb.bits,
+ &fpb.kind, prec ? 2 : 0, prec, &decpt, &se);
+ }
+#endif
+ if (decpt == 9999)
+ goto fmt9999;
+ e_fmt:
+ if (fpb.sign && (x||sign))
+ sign = '-';
+ if ((width -= prec + 5) > 0) {
+ if (sign)
+ --width;
+ if (prec || alt)
+ --width;
+ }
+ if ((c = --decpt) < 0)
+ c = -c;
+ while(c >= 100) {
+ --width;
+ c /= 10;
+ }
+ if (width > 0 && !left) {
+ if (lead0) {
+ if (sign)
+ put(sign)
+ sign = 0;
+ do put('0')
+ while(--width > 0);
+ }
+ else do put(' ')
+ while(--width > 0);
+ }
+ if (sign)
+ put(sign)
+ put(*s++)
+ if (prec || alt)
+ put('.')
+ while(--prec >= 0) {
+ if ((c = *s))
+ s++;
+ else
+ c = '0';
+ put(c)
+ }
+ put(conv)
+ if (decpt < 0) {
+ put('-')
+ decpt = -decpt;
+ }
+ else
+ put('+')
+ for(c = 2, k = 10; 10*k <= decpt; c++, k *= 10);
+ for(;;) {
+ i1 = decpt / k;
+ put(i1 + '0')
+ if (--c <= 0)
+ break;
+ decpt -= i1*k;
+ decpt *= 10;
+ }
+ while(--width >= 0)
+ put(' ')
+ freedtoa(s0);
+ continue;
+#ifndef NO_PRINTF_A_FMT
+ case 'a':
+ digits = hex;
+ goto more_a;
+ case 'A':
+ digits = Hex;
+ more_a:
+#ifdef GDTOA_H_INCLUDED /*{{*/
+ if (fpbits == dfpbits)
+ u.d = va_arg(ap, double);
+#ifdef GDTOA_both /*{*/
+ else if (fpbits == GDTOA_LD_fpbits)
+ u.ld = va_arg(ap, long double);
+ else
+ u.Qd = va_arg(ap, GDTOA_Qtype);
+#else
+ else
+ u.ld = va_arg(ap, long double);
+#endif /*}*/
+#else /*}{*/
+ u.d = va_arg(ap, double);
+#endif /*}}*/
+ fpbits(&u, &fpb);
+ if (fpb.kind == STRTOG_Infinite) {
+ s = "Infinity";
+ s0 = 0;
+ goto fmt9999;
+ }
+ if (fpb.kind == STRTOG_NaN) {
+ s = "NaN";
+ s0 = 0;
+ goto fmt9999;
+ }
+ prec1 = fpiprec(&fpb);
+ if (dot && prec < prec1)
+ prec1 = bround(&fpb, prec, prec1);
+ bw = 1;
+ bex = fpb.ex + 4*prec1;
+ if (bex) {
+ if ((i1 = bex) < 0)
+ i1 = -i1;
+ while(i1 >= 10) {
+ ++bw;
+ i1 /= 10;
+ }
+ }
+ if (fpb.sign && (sign || fpb.kind != STRTOG_Zero))
+ sign = '-';
+ if ((width -= bw + 5) > 0) {
+ if (sign)
+ --width;
+ if (prec1 || alt)
+ --width;
+ }
+ if ((width -= prec1) > 0 && !left && !lead0) {
+ do put(' ')
+ while(--width > 0);
+ }
+ if (sign)
+ put(sign)
+ put('0')
+ put(digits[17])
+ if (lead0 && width > 0 && !left) {
+ do put('0')
+ while(--width > 0);
+ }
+ i1 = prec1 & 7;
+ k = prec1 >> 3;
+ put(digits[(fpb.bits[k] >> 4*i1) & 0xf])
+ if (prec1 > 0 || alt)
+ put('.')
+ if (prec1 > 0) {
+ prec -= prec1;
+ while(prec1 > 0) {
+ if (--i1 < 0) {
+ if (--k < 0)
+ break;
+ i1 = 7;
+ }
+ put(digits[(fpb.bits[k] >> 4*i1) & 0xf])
+ --prec1;
+ }
+ if (alt && prec > 0)
+ do put(0)
+ while(--prec > 0);
+ }
+ put(digits[16])
+ if (bex < 0) {
+ put('-')
+ bex = -bex;
+ }
+ else
+ put('+')
+ for(c = 1; 10*c <= bex; c *= 10);
+ for(;;) {
+ i1 = bex / c;
+ put('0' + i1)
+ if (!--bw)
+ break;
+ bex -= i1 * c;
+ bex *= 10;
+ }
+ while(--width >= 0)
+ put(' ')
+ continue;
+#endif /* NO_PRINTF_A_FMT */
+ default:
+ put('%')
+ while(fmt0 < fmt)
+ put(*fmt0++)
+ continue;
+ }
+ }
+ done:
+ *outbuf = 0;
+ return (f->lastlen = outbuf - ob0) + rv;
+ }
+
+#define Bsize 256
+
+ int
+Printf
+#ifdef KR_headers
+ (va_alist)
+ va_dcl
+{
+ char *fmt;
+
+ va_list ap;
+ int rv;
+ Finfo f;
+ char buf[Bsize];
+
+ va_start(ap);
+ fmt = va_arg(ap, char*);
+ /*}*/
+#else
+ (const char *fmt, ...)
+{
+ va_list ap;
+ int rv;
+ Finfo f;
+ char buf[Bsize];
+
+ va_start(ap, fmt);
+#endif
+ f.u.cf = stdout;
+ f.ob0 = buf;
+ f.obe1 = buf + Bsize - 1;
+#ifdef _windows_
+ if (fileno(stdout) == stdout_fileno_ASL) {
+ rv = x_sprintf(f.obe1, Wput, &f, fmt, ap);
+ mwrite(buf, f.lastlen);
+ }
+ else
+#endif
+#ifdef PF_BUF
+ if (stdout == stderr_ASL) {
+ rv = x_sprintf(f.obe1, pfput, &f, fmt, ap);
+ pf_put(buf, f.lastlen);
+ }
+ else
+#endif
+ {
+ rv = x_sprintf(f.obe1, Fput, &f, fmt, ap);
+ fputs(buf, stdout);
+ }
+ va_end(ap);
+ return rv;
+ }
+
+ static char *
+Sput
+#ifdef KR_headers
+ (f, rvp) Finfo *f; int *rvp;
+#else
+ (Finfo *f, int *rvp)
+#endif
+{
+ if (Printf("\nBUG! Sput called!\n", f, rvp))
+ /* pass vp, rvp and return 0 to shut diagnostics off */
+ exit(250);
+ return 0;
+ }
+
+ int
+Sprintf
+#ifdef KR_headers
+ (va_alist)
+ va_dcl
+{
+ char *s, *fmt;
+ va_list ap;
+ int rv;
+ Finfo f;
+
+ va_start(ap);
+ s = va_arg(ap, char*);
+ fmt = va_arg(ap, char*);
+ /*}*/
+#else
+ (char *s, const char *fmt, ...)
+{
+ va_list ap;
+ int rv;
+ Finfo f;
+
+ va_start(ap, fmt);
+#endif
+ f.ob0 = s;
+ rv = x_sprintf(s, Sput, &f, fmt, ap);
+ va_end(ap);
+ return rv;
+ }
+
+ int
+Fprintf
+#ifdef KR_headers
+ (va_alist)
+ va_dcl
+{
+ FILE *F;
+ char *s, *fmt;
+ va_list ap;
+ int rv;
+ Finfo f;
+ char buf[Bsize];
+
+ va_start(ap);
+ F = va_arg(ap, FILE*);
+ fmt = va_arg(ap, char*);
+ /*}*/
+#else
+ (FILE *F, const char *fmt, ...)
+{
+ va_list ap;
+ int rv;
+ Finfo f;
+ char buf[Bsize];
+
+ va_start(ap, fmt);
+#endif
+ f.u.cf = F;
+ f.ob0 = buf;
+ f.obe1 = buf + Bsize - 1;
+#ifdef MESS
+ if (stdout_or_err(F)) {
+#ifdef _windows_
+ if (fileno(stdout) == stdout_fileno_ASL) {
+ rv = x_sprintf(f.obe1, Wput, &f, fmt, ap);
+ mwrite(buf, f.lastlen);
+ }
+ else
+#endif
+#ifdef PF_BUF
+ if (F == stderr_ASL) {
+ rv = x_sprintf(f.obe1, pfput, &f, fmt, ap);
+ pf_put(buf, f.lastlen);
+ }
+ else
+#endif
+ {
+ rv = x_sprintf(f.obe1, Fput, &f, fmt, ap);
+ fputs(buf, F);
+ }
+ }
+ else
+#endif /*MESS*/
+ {
+#ifdef PF_BUF
+ if (F == stderr_ASL) {
+ rv = x_sprintf(f.obe1, pfput, &f, fmt, ap);
+ pf_put(buf, f.lastlen);
+ }
+ else
+#endif
+ {
+ rv = x_sprintf(f.obe1, Fput, &f, fmt, ap);
+ fputs(buf, F);
+ }
+ }
+ va_end(ap);
+ return rv;
+ }
+
+ int
+Vsprintf
+#ifdef KR_headers
+ (s, fmt, ap) char *s, *fmt; va_list ap;
+#else
+ (char *s, const char *fmt, va_list ap)
+#endif
+{
+ Finfo f;
+ return x_sprintf(f.ob0 = s, Sput, &f, fmt, ap);
+ }
+
+ int
+Vfprintf
+#ifdef KR_headers
+ (F, fmt, ap) FILE *F; char *fmt; va_list ap;
+#else
+ (FILE *F, const char *fmt, va_list ap)
+#endif
+{
+ char buf[Bsize];
+ int rv;
+ Finfo f;
+
+ f.u.cf = F;
+ f.ob0 = buf;
+ f.obe1 = buf + Bsize - 1;
+#ifdef MESS
+ if (stdout_or_err(F)) {
+#ifdef _windows_
+ if (fileno(stdout) == stdout_fileno_ASL) {
+ rv = x_sprintf(f.obe1, Wput, &f, fmt, ap);
+ mwrite(buf, f.lastlen);
+ }
+ else
+#endif
+#ifdef PF_BUF
+ if (F == stderr_ASL) {
+ rv = x_sprintf(f.obe1, pfput, &f, fmt, ap);
+ pf_put(buf, f.lastlen);
+ }
+ else
+#endif
+ {
+ rv = x_sprintf(f.obe1, Fput, &f, fmt, ap);
+ fputs(buf, F);
+ }
+ }
+ else
+#endif /*MESS*/
+ {
+#ifdef PF_BUF
+ if (F == stderr_ASL) {
+ rv = x_sprintf(f.obe1, pfput, &f, fmt, ap);
+ pf_put(buf, f.lastlen);
+ }
+ else
+#endif
+ {
+ rv = x_sprintf(f.obe1, Fput, &f, fmt, ap);
+ fputs(buf, F);
+ }
+ }
+ va_end(ap);
+ return rv;
+ }
+
+ void
+Perror
+#ifdef KR_headers
+ (s) char *s;
+#else
+ (const char *s)
+#endif
+{
+ if (s && *s)
+ Fprintf(Stderr, "%s: ", s);
+ Fprintf(Stderr, "%s\n", strerror(errno));
+ }
+
+ static char *
+Snput
+#ifdef KR_headers
+ (f, rvp) Finfo *f; int *rvp;
+#else
+ (Finfo *f, int *rvp)
+#endif
+{
+ char *s, *s0;
+ size_t L;
+
+ *rvp += Bsize;
+ s0 = f->ob0;
+ s = f->u.sf;
+ if ((L = f->obe1 - s) > Bsize) {
+ L = Bsize;
+ goto copy;
+ }
+ if (L > 0) {
+ copy:
+ memcpy(s, s0, L);
+ f->u.sf = s + L;
+ }
+ return s0;
+ }
+
+ int
+Vsnprintf
+#ifdef KR_headers
+ (s, n, fmt, ap) char *s; size_t n; char *fmt; va_list ap;
+#else
+ (char *s, size_t n, const char *fmt, va_list ap)
+#endif
+{
+ Finfo f;
+ char buf[Bsize];
+ int L, rv;
+
+ if (n <= 0 || !s) {
+ n = 1;
+ s = buf;
+ }
+ f.u.sf = s;
+ f.ob0 = buf;
+ f.obe1 = s + n - 1;
+ rv = x_sprintf(buf + Bsize, Snput, &f, fmt, ap);
+ if (f.lastlen > (L = f.obe1 - f.u.sf))
+ f.lastlen = L;
+ if (f.lastlen > 0) {
+ memcpy(f.u.sf, buf, f.lastlen);
+ f.u.sf += f.lastlen;
+ }
+ *f.u.sf = 0;
+ return rv;
+ }
+ int
+Snprintf
+#ifdef KR_headers
+ (va_alist)
+ va_dcl
+{
+ char *s, *fmt;
+ int rv;
+ size_t n;
+ va_list ap;
+
+ va_start(ap);
+ s = va_arg(ap, char*);
+ n = va_arg(ap, size_t);
+ fmt = va_arg(ap, char*);
+ /*}*/
+#else
+ (char *s, size_t n, const char *fmt, ...)
+{
+ int rv;
+ va_list ap;
+
+ va_start(ap, fmt);
+#endif
+ rv = Vsnprintf(s, n, fmt, ap);
+ va_end(ap);
+ return rv;
+ }
+
+
+#ifdef __cplusplus
+}
+#endif
diff --git a/smisc.c b/smisc.c
index 50431fce16e1..f4dbafb21c5f 100644
--- a/smisc.c
+++ b/smisc.c
@@ -77,33 +77,33 @@ ratio
(Bigint *a, Bigint *b)
#endif
{
- double da, db;
+ U da, db;
int k, ka, kb;
- dval(da) = b2d(a, &ka);
- dval(db) = b2d(b, &kb);
+ dval(&da) = b2d(a, &ka);
+ dval(&db) = b2d(b, &kb);
k = ka - kb + ULbits*(a->wds - b->wds);
#ifdef IBM
if (k > 0) {
- word0(da) += (k >> 2)*Exp_msk1;
+ word0(&da) += (k >> 2)*Exp_msk1;
if (k &= 3)
- dval(da) *= 1 << k;
+ dval(&da) *= 1 << k;
}
else {
k = -k;
- word0(db) += (k >> 2)*Exp_msk1;
+ word0(&db) += (k >> 2)*Exp_msk1;
if (k &= 3)
- dval(db) *= 1 << k;
+ dval(&db) *= 1 << k;
}
#else
if (k > 0)
- word0(da) += k*Exp_msk1;
+ word0(&da) += k*Exp_msk1;
else {
k = -k;
- word0(db) += k*Exp_msk1;
+ word0(&db) += k*Exp_msk1;
}
#endif
- return dval(da) / dval(db);
+ return dval(&da) / dval(&db);
}
#ifdef INFNAN_CHECK
diff --git a/stdio1.h b/stdio1.h
new file mode 100644
index 000000000000..ef2bb634424e
--- /dev/null
+++ b/stdio1.h
@@ -0,0 +1,103 @@
+/****************************************************************
+Copyright (C) 1997-1999 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.
+****************************************************************/
+
+/* stdio1.h -- for using Printf, Fprintf, Sprintf while
+ * retaining the system-supplied printf, fprintf, sprintf.
+ */
+
+#ifndef STDIO1_H_included
+#define STDIO1_H_included
+#ifndef STDIO_H_included /* allow suppressing stdio.h */
+#include <stdio.h> /* in case it's already included, */
+#endif /* e.g., by cplex.h */
+
+#ifdef KR_headers
+#ifndef _SIZE_T
+#define _SIZE_T
+typedef unsigned int size_t;
+#endif
+#define ANSI(x) ()
+#include "varargs.h"
+#ifndef Char
+#define Char char
+#endif
+#else
+#define ANSI(x) x
+#include "stdarg.h"
+#ifndef Char
+#define Char void
+#endif
+#endif
+
+#ifndef NO_STDIO1
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+extern int Fprintf ANSI((FILE*, const char*, ...));
+extern int Printf ANSI((const char*, ...));
+extern int Sprintf ANSI((char*, const char*, ...));
+extern int Snprintf ANSI((char*, size_t, const char*, ...));
+extern void Perror ANSI((const char*));
+extern int Vfprintf ANSI((FILE*, const char*, va_list));
+extern int Vsprintf ANSI((char*, const char*, va_list));
+extern int Vsnprintf ANSI((char*, size_t, const char*, va_list));
+
+#ifdef PF_BUF
+extern FILE *stderr_ASL;
+extern void (*pfbuf_print_ASL) ANSI((char*));
+extern char *pfbuf_ASL;
+extern void fflush_ASL ANSI((FILE*));
+#ifdef fflush
+#define old_fflush_ASL fflush
+#undef fflush
+#endif
+#define fflush fflush_ASL
+#endif
+
+#ifdef __cplusplus
+ }
+#endif
+
+#undef printf
+#undef fprintf
+#undef sprintf
+#undef perror
+#undef vfprintf
+#undef vsprintf
+#define printf Printf
+#define fprintf Fprintf
+#undef snprintf /* for MacOSX */
+#undef vsnprintf /* for MacOSX */
+#define snprintf Snprintf
+#define sprintf Sprintf
+#define perror Perror
+#define vfprintf Vfprintf
+#define vsnprintf Vsnprintf
+#define vsprintf Vsprintf
+
+#endif /* NO_STDIO1 */
+
+#endif /* STDIO1_H_included */
diff --git a/strtoIg.c b/strtoIg.c
index 90c88db3283d..6a17760cf5ce 100644
--- a/strtoIg.c
+++ b/strtoIg.c
@@ -74,7 +74,7 @@ strtoIg(CONST char *s00, char **se, FPI *fpi, Long *exp, Bigint **B, int *rvp)
goto swapcheck;
}
if (b1->wds > nw
- || nb1 && b1->x[nw1] & 1L << nb1) {
+ || (nb1 && b1->x[nw1] & 1L << nb1)) {
if (++e1 > fpi->emax)
rv1 = STRTOG_Infinite | STRTOG_Inexhi;
rshift(b1, 1);
diff --git a/strtod.c b/strtod.c
index b8287eb164be..6adef8b4bbb4 100644
--- a/strtod.c
+++ b/strtod.c
@@ -57,6 +57,28 @@ static CONST double tinytens[] = { 1e-16, 1e-32, 1e-64, 1e-128,
#define Rounding Flt_Rounds
#endif
+#ifdef Avoid_Underflow /*{*/
+ static double
+sulp
+#ifdef KR_headers
+ (x, scale) U *x; int scale;
+#else
+ (U *x, int scale)
+#endif
+{
+ U u;
+ double rv;
+ int i;
+
+ rv = ulp(x);
+ if (!scale || (i = 2*P + 1 - ((word0(x) & Exp_mask) >> Exp_shift)) <= 0)
+ return rv; /* Is there an example where i <= 0 ? */
+ word0(&u) = Exp_1 + (i << Exp_shift);
+ word1(&u) = 0;
+ return rv * u.d;
+ }
+#endif /*}*/
+
double
strtod
#ifdef KR_headers
@@ -71,10 +93,14 @@ strtod
int bb2, bb5, bbe, bd2, bd5, bbbits, bs2, c, decpt, dsign,
e, e1, esign, i, j, k, nd, nd0, nf, nz, nz0, sign;
CONST char *s, *s0, *s1;
- double aadj, aadj1, adj, rv, rv0;
+ double aadj;
Long L;
+ U adj, aadj1, rv, rv0;
ULong y, z;
Bigint *bb, *bb1, *bd, *bd0, *bs, *delta;
+#ifdef Avoid_Underflow
+ ULong Lsb, Lsb1;
+#endif
#ifdef SET_INEXACT
int inexact, oldinexact;
#endif
@@ -88,7 +114,7 @@ strtod
static int dplen;
if (!(s0 = decimalpoint_cache)) {
s0 = localeconv()->decimal_point;
- if ((decimalpoint_cache = (char*)malloc(strlen(s0) + 1))) {
+ if ((decimalpoint_cache = (char*)MALLOC(strlen(s0) + 1))) {
strcpy(decimalpoint_cache, s0);
s0 = decimalpoint_cache;
}
@@ -115,7 +141,7 @@ strtod
#endif /*}*/
sign = nz0 = nz = decpt = 0;
- dval(rv) = 0.;
+ dval(&rv) = 0.;
for(s = s00;;s++) switch(*s) {
case '-':
sign = 1;
@@ -147,20 +173,12 @@ strtod
case 'x':
case 'X':
{
-#if defined(FE_DOWNWARD) && defined(FE_TONEAREST) && defined(FE_TOWARDZERO) && defined(FE_UPWARD) /*{{*/
+#ifdef Honor_FLT_ROUNDS
FPI fpi1 = fpi;
-#ifdef Honor_FLT_ROUNDS /*{{*/
fpi1.rounding = Rounding;
-#else /*}{*/
- switch(fegetround()) {
- case FE_TOWARDZERO: fpi1.rounding = 0; break;
- case FE_UPWARD: fpi1.rounding = 2; break;
- case FE_DOWNWARD: fpi1.rounding = 3;
- }
-#endif /*}}*/
-#else /*}{*/
+#else
#define fpi1 fpi
-#endif /*}}*/
+#endif
switch((i = gethex(&s, &fpi1, &exp, &bb, sign)) & STRTOG_Retmask) {
case STRTOG_NoNumber:
s = s00;
@@ -285,8 +303,8 @@ strtod
--s;
if (!match(&s,"inity"))
++s;
- word0(rv) = 0x7ff00000;
- word1(rv) = 0;
+ word0(&rv) = 0x7ff00000;
+ word1(&rv) = 0;
goto ret;
}
break;
@@ -297,13 +315,13 @@ strtod
if (*s == '(' /*)*/
&& hexnan(&s, &fpinan, bits)
== STRTOG_NaNbits) {
- word0(rv) = 0x7ff00000 | bits[1];
- word1(rv) = bits[0];
+ word0(&rv) = 0x7ff00000 | bits[1];
+ word1(&rv) = bits[0];
}
else {
#endif
- word0(rv) = NAN_WORD0;
- word1(rv) = NAN_WORD1;
+ word0(&rv) = NAN_WORD0;
+ word1(&rv) = NAN_WORD1;
#ifndef No_Hex_NaN
}
#endif
@@ -327,13 +345,13 @@ strtod
if (!nd0)
nd0 = nd;
k = nd < DBL_DIG + 1 ? nd : DBL_DIG + 1;
- dval(rv) = y;
+ dval(&rv) = y;
if (k > 9) {
#ifdef SET_INEXACT
if (k > DBL_DIG)
oldinexact = get_inexact();
#endif
- dval(rv) = tens[k - 9] * dval(rv) + z;
+ dval(&rv) = tens[k - 9] * dval(&rv) + z;
}
bd0 = 0;
if (nd <= DBL_DIG
@@ -345,6 +363,7 @@ strtod
) {
if (!e)
goto ret;
+#ifndef ROUND_BIASED_without_Round_Up
if (e > 0) {
if (e <= Ten_pmax) {
#ifdef VAX
@@ -353,11 +372,11 @@ strtod
#ifdef Honor_FLT_ROUNDS
/* round correctly FLT_ROUNDS = 2 or 3 */
if (sign) {
- rv = -rv;
+ rv.d = -rv.d;
sign = 0;
}
#endif
- /* rv = */ rounded_product(dval(rv), tens[e]);
+ /* rv = */ rounded_product(dval(&rv), tens[e]);
goto ret;
#endif
}
@@ -369,25 +388,25 @@ strtod
#ifdef Honor_FLT_ROUNDS
/* round correctly FLT_ROUNDS = 2 or 3 */
if (sign) {
- rv = -rv;
+ rv.d = -rv.d;
sign = 0;
}
#endif
e -= i;
- dval(rv) *= tens[i];
+ dval(&rv) *= tens[i];
#ifdef VAX
/* VAX exponent range is so narrow we must
* worry about overflow here...
*/
vax_ovfl_check:
- word0(rv) -= P*Exp_msk1;
- /* rv = */ rounded_product(dval(rv), tens[e]);
- if ((word0(rv) & Exp_mask)
+ word0(&rv) -= P*Exp_msk1;
+ /* rv = */ rounded_product(dval(&rv), tens[e]);
+ if ((word0(&rv) & Exp_mask)
> Exp_msk1*(DBL_MAX_EXP+Bias-1-P))
goto ovfl;
- word0(rv) += P*Exp_msk1;
+ word0(&rv) += P*Exp_msk1;
#else
- /* rv = */ rounded_product(dval(rv), tens[e]);
+ /* rv = */ rounded_product(dval(&rv), tens[e]);
#endif
goto ret;
}
@@ -397,14 +416,15 @@ strtod
#ifdef Honor_FLT_ROUNDS
/* round correctly FLT_ROUNDS = 2 or 3 */
if (sign) {
- rv = -rv;
+ rv.d = -rv.d;
sign = 0;
}
#endif
- /* rv = */ rounded_quotient(dval(rv), tens[-e]);
+ /* rv = */ rounded_quotient(dval(&rv), tens[-e]);
goto ret;
}
#endif
+#endif /* ROUND_BIASED_without_Round_Up */
}
e1 += nd - k;
@@ -432,67 +452,73 @@ strtod
if (e1 > 0) {
if ( (i = e1 & 15) !=0)
- dval(rv) *= tens[i];
+ dval(&rv) *= tens[i];
if (e1 &= ~15) {
if (e1 > DBL_MAX_10_EXP) {
ovfl:
-#ifndef NO_ERRNO
- errno = ERANGE;
-#endif
/* Can't trust HUGE_VAL */
#ifdef IEEE_Arith
#ifdef Honor_FLT_ROUNDS
switch(Rounding) {
case 0: /* toward 0 */
case 3: /* toward -infinity */
- word0(rv) = Big0;
- word1(rv) = Big1;
+ word0(&rv) = Big0;
+ word1(&rv) = Big1;
break;
default:
- word0(rv) = Exp_mask;
- word1(rv) = 0;
+ word0(&rv) = Exp_mask;
+ word1(&rv) = 0;
}
#else /*Honor_FLT_ROUNDS*/
- word0(rv) = Exp_mask;
- word1(rv) = 0;
+ word0(&rv) = Exp_mask;
+ word1(&rv) = 0;
#endif /*Honor_FLT_ROUNDS*/
#ifdef SET_INEXACT
/* set overflow bit */
- dval(rv0) = 1e300;
- dval(rv0) *= dval(rv0);
+ dval(&rv0) = 1e300;
+ dval(&rv0) *= dval(&rv0);
#endif
#else /*IEEE_Arith*/
- word0(rv) = Big0;
- word1(rv) = Big1;
+ word0(&rv) = Big0;
+ word1(&rv) = Big1;
#endif /*IEEE_Arith*/
- if (bd0)
- goto retfree;
+ range_err:
+ if (bd0) {
+ Bfree(bb);
+ Bfree(bd);
+ Bfree(bs);
+ Bfree(bd0);
+ Bfree(delta);
+ }
+#ifndef NO_ERRNO
+ errno = ERANGE;
+#endif
goto ret;
}
e1 >>= 4;
for(j = 0; e1 > 1; j++, e1 >>= 1)
if (e1 & 1)
- dval(rv) *= bigtens[j];
+ dval(&rv) *= bigtens[j];
/* The last multiplication could overflow. */
- word0(rv) -= P*Exp_msk1;
- dval(rv) *= bigtens[j];
- if ((z = word0(rv) & Exp_mask)
+ word0(&rv) -= P*Exp_msk1;
+ dval(&rv) *= bigtens[j];
+ if ((z = word0(&rv) & Exp_mask)
> Exp_msk1*(DBL_MAX_EXP+Bias-P))
goto ovfl;
if (z > Exp_msk1*(DBL_MAX_EXP+Bias-1-P)) {
/* set to largest number */
/* (Can't trust DBL_MAX) */
- word0(rv) = Big0;
- word1(rv) = Big1;
+ word0(&rv) = Big0;
+ word1(&rv) = Big1;
}
else
- word0(rv) += P*Exp_msk1;
+ word0(&rv) += P*Exp_msk1;
}
}
else if (e1 < 0) {
e1 = -e1;
if ( (i = e1 & 15) !=0)
- dval(rv) /= tens[i];
+ dval(&rv) /= tens[i];
if (e1 >>= 4) {
if (e1 >= 1 << n_bigtens)
goto undfl;
@@ -501,44 +527,39 @@ strtod
scale = 2*P;
for(j = 0; e1 > 0; j++, e1 >>= 1)
if (e1 & 1)
- dval(rv) *= tinytens[j];
- if (scale && (j = 2*P + 1 - ((word0(rv) & Exp_mask)
+ dval(&rv) *= tinytens[j];
+ if (scale && (j = 2*P + 1 - ((word0(&rv) & Exp_mask)
>> Exp_shift)) > 0) {
/* scaled rv is denormal; zap j low bits */
if (j >= 32) {
- word1(rv) = 0;
+ word1(&rv) = 0;
if (j >= 53)
- word0(rv) = (P+2)*Exp_msk1;
+ word0(&rv) = (P+2)*Exp_msk1;
else
- word0(rv) &= 0xffffffff << j-32;
+ word0(&rv) &= 0xffffffff << (j-32);
}
else
- word1(rv) &= 0xffffffff << j;
+ word1(&rv) &= 0xffffffff << j;
}
#else
for(j = 0; e1 > 1; j++, e1 >>= 1)
if (e1 & 1)
- dval(rv) *= tinytens[j];
+ dval(&rv) *= tinytens[j];
/* The last multiplication could underflow. */
- dval(rv0) = dval(rv);
- dval(rv) *= tinytens[j];
- if (!dval(rv)) {
- dval(rv) = 2.*dval(rv0);
- dval(rv) *= tinytens[j];
+ dval(&rv0) = dval(&rv);
+ dval(&rv) *= tinytens[j];
+ if (!dval(&rv)) {
+ dval(&rv) = 2.*dval(&rv0);
+ dval(&rv) *= tinytens[j];
#endif
- if (!dval(rv)) {
+ if (!dval(&rv)) {
undfl:
- dval(rv) = 0.;
-#ifndef NO_ERRNO
- errno = ERANGE;
-#endif
- if (bd0)
- goto retfree;
- goto ret;
+ dval(&rv) = 0.;
+ goto range_err;
}
#ifndef Avoid_Underflow
- word0(rv) = Tiny0;
- word1(rv) = Tiny1;
+ word0(&rv) = Tiny0;
+ word1(&rv) = Tiny1;
/* The refinement below will clean
* this approximation up.
*/
@@ -556,7 +577,7 @@ strtod
for(;;) {
bd = Balloc(bd0->k);
Bcopy(bd, bd0);
- bb = d2b(dval(rv), &bbe, &bbbits); /* rv = bb * 2^bbe */
+ bb = d2b(dval(&rv), &bbe, &bbbits); /* rv = bb * 2^bbe */
bs = i2b(1);
if (e >= 0) {
@@ -577,12 +598,19 @@ strtod
bs2++;
#endif
#ifdef Avoid_Underflow
+ Lsb = LSB;
+ Lsb1 = 0;
j = bbe - scale;
i = j + bbbits - 1; /* logb(rv) */
- if (i < Emin) /* denormal */
- j += P - Emin;
- else
- j = P + 1 - bbbits;
+ j = P + 1 - bbbits;
+ if (i < Emin) { /* denormal */
+ i = Emin - i;
+ j -= i;
+ if (i < 32)
+ Lsb <<= i;
+ else
+ Lsb1 = Lsb << (i-32);
+ }
#else /*Avoid_Underflow*/
#ifdef Sudden_Underflow
#ifdef IBM
@@ -592,7 +620,7 @@ strtod
#endif
#else /*Sudden_Underflow*/
j = bbe;
- i = j + bbbits - 1; /* logb(rv) */
+ i = j + bbbits - 1; /* logb(&rv) */
if (i < Emin) /* denormal */
j += P - Emin;
else
@@ -643,15 +671,15 @@ strtod
}
if (Rounding) {
if (dsign) {
- adj = 1.;
+ dval(&adj) = 1.;
goto apply_adj;
}
}
else if (!dsign) {
- adj = -1.;
- if (!word1(rv)
- && !(word0(rv) & Frac_mask)) {
- y = word0(rv) & Exp_mask;
+ dval(&adj) = -1.;
+ if (!word1(&rv)
+ && !(word0(&rv) & Frac_mask)) {
+ y = word0(&rv) & Exp_mask;
#ifdef Avoid_Underflow
if (!scale || y > 2*P*Exp_msk1)
#else
@@ -660,66 +688,66 @@ strtod
{
delta = lshift(delta,Log2P);
if (cmp(delta, bs) <= 0)
- adj = -0.5;
+ dval(&adj) = -0.5;
}
}
apply_adj:
#ifdef Avoid_Underflow
- if (scale && (y = word0(rv) & Exp_mask)
+ if (scale && (y = word0(&rv) & Exp_mask)
<= 2*P*Exp_msk1)
- word0(adj) += (2*P+1)*Exp_msk1 - y;
+ word0(&adj) += (2*P+1)*Exp_msk1 - y;
#else
#ifdef Sudden_Underflow
- if ((word0(rv) & Exp_mask) <=
+ if ((word0(&rv) & Exp_mask) <=
P*Exp_msk1) {
- word0(rv) += P*Exp_msk1;
- dval(rv) += adj*ulp(dval(rv));
- word0(rv) -= P*Exp_msk1;
+ word0(&rv) += P*Exp_msk1;
+ dval(&rv) += adj*ulp(&rv);
+ word0(&rv) -= P*Exp_msk1;
}
else
#endif /*Sudden_Underflow*/
#endif /*Avoid_Underflow*/
- dval(rv) += adj*ulp(dval(rv));
+ dval(&rv) += adj.d*ulp(&rv);
}
break;
}
- adj = ratio(delta, bs);
- if (adj < 1.)
- adj = 1.;
- if (adj <= 0x7ffffffe) {
- /* adj = Rounding ? ceil(adj) : floor(adj); */
- y = adj;
- if (y != adj) {
+ dval(&adj) = ratio(delta, bs);
+ if (adj.d < 1.)
+ dval(&adj) = 1.;
+ if (adj.d <= 0x7ffffffe) {
+ /* dval(&adj) = Rounding ? ceil(&adj) : floor(&adj); */
+ y = adj.d;
+ if (y != adj.d) {
if (!((Rounding>>1) ^ dsign))
y++;
- adj = y;
+ dval(&adj) = y;
}
}
#ifdef Avoid_Underflow
- if (scale && (y = word0(rv) & Exp_mask) <= 2*P*Exp_msk1)
- word0(adj) += (2*P+1)*Exp_msk1 - y;
+ if (scale && (y = word0(&rv) & Exp_mask) <= 2*P*Exp_msk1)
+ word0(&adj) += (2*P+1)*Exp_msk1 - y;
#else
#ifdef Sudden_Underflow
- if ((word0(rv) & Exp_mask) <= P*Exp_msk1) {
- word0(rv) += P*Exp_msk1;
- adj *= ulp(dval(rv));
+ if ((word0(&rv) & Exp_mask) <= P*Exp_msk1) {
+ word0(&rv) += P*Exp_msk1;
+ dval(&adj) *= ulp(&rv);
if (dsign)
- dval(rv) += adj;
+ dval(&rv) += adj;
else
- dval(rv) -= adj;
- word0(rv) -= P*Exp_msk1;
+ dval(&rv) -= adj;
+ word0(&rv) -= P*Exp_msk1;
goto cont;
}
#endif /*Sudden_Underflow*/
#endif /*Avoid_Underflow*/
- adj *= ulp(dval(rv));
+ dval(&adj) *= ulp(&rv);
if (dsign) {
- if (word0(rv) == Big0 && word1(rv) == Big1)
+ if (word0(&rv) == Big0 && word1(&rv) == Big1)
goto ovfl;
- dval(rv) += adj;
+ dval(&rv) += adj.d;
}
else
- dval(rv) -= adj;
+ dval(&rv) -= adj.d;
goto cont;
}
#endif /*Honor_FLT_ROUNDS*/
@@ -728,12 +756,12 @@ strtod
/* Error is less than half an ulp -- check for
* special case of mantissa a power of two.
*/
- if (dsign || word1(rv) || word0(rv) & Bndry_mask
+ if (dsign || word1(&rv) || word0(&rv) & Bndry_mask
#ifdef IEEE_Arith
#ifdef Avoid_Underflow
- || (word0(rv) & Exp_mask) <= (2*P+1)*Exp_msk1
+ || (word0(&rv) & Exp_mask) <= (2*P+1)*Exp_msk1
#else
- || (word0(rv) & Exp_mask) <= Exp_msk1
+ || (word0(&rv) & Exp_mask) <= Exp_msk1
#endif
#endif
) {
@@ -758,32 +786,34 @@ strtod
if (i == 0) {
/* exactly half-way between */
if (dsign) {
- if ((word0(rv) & Bndry_mask1) == Bndry_mask1
- && word1(rv) == (
+ if ((word0(&rv) & Bndry_mask1) == Bndry_mask1
+ && word1(&rv) == (
#ifdef Avoid_Underflow
- (scale && (y = word0(rv) & Exp_mask) <= 2*P*Exp_msk1)
+ (scale && (y = word0(&rv) & Exp_mask) <= 2*P*Exp_msk1)
? (0xffffffff & (0xffffffff << (2*P+1-(y>>Exp_shift)))) :
#endif
0xffffffff)) {
/*boundary case -- increment exponent*/
- word0(rv) = (word0(rv) & Exp_mask)
+ if (word0(&rv) == Big0 && word1(&rv) == Big1)
+ goto ovfl;
+ word0(&rv) = (word0(&rv) & Exp_mask)
+ Exp_msk1
#ifdef IBM
| Exp_msk1 >> 4
#endif
;
- word1(rv) = 0;
+ word1(&rv) = 0;
#ifdef Avoid_Underflow
dsign = 0;
#endif
break;
}
}
- else if (!(word0(rv) & Bndry_mask) && !word1(rv)) {
+ else if (!(word0(&rv) & Bndry_mask) && !word1(&rv)) {
drop_down:
/* boundary case -- decrement exponent */
#ifdef Sudden_Underflow /*{{*/
- L = word0(rv) & Exp_mask;
+ L = word0(&rv) & Exp_mask;
#ifdef IBM
if (L < Exp_msk1)
#else
@@ -798,7 +828,7 @@ strtod
#else /*Sudden_Underflow}{*/
#ifdef Avoid_Underflow
if (scale) {
- L = word0(rv) & Exp_mask;
+ L = word0(&rv) & Exp_mask;
if (L <= (2*P+1)*Exp_msk1) {
if (L > (P+2)*Exp_msk1)
/* round even ==> */
@@ -809,10 +839,10 @@ strtod
}
}
#endif /*Avoid_Underflow*/
- L = (word0(rv) & Exp_mask) - Exp_msk1;
+ L = (word0(&rv) & Exp_mask) - Exp_msk1;
#endif /*Sudden_Underflow}}*/
- word0(rv) = L | Bndry_mask1;
- word1(rv) = 0xffffffff;
+ word0(&rv) = L | Bndry_mask1;
+ word1(&rv) = 0xffffffff;
#ifdef IBM
goto cont;
#else
@@ -820,16 +850,33 @@ strtod
#endif
}
#ifndef ROUND_BIASED
- if (!(word1(rv) & LSB))
+#ifdef Avoid_Underflow
+ if (Lsb1) {
+ if (!(word0(&rv) & Lsb1))
+ break;
+ }
+ else if (!(word1(&rv) & Lsb))
+ break;
+#else
+ if (!(word1(&rv) & LSB))
break;
#endif
+#endif
if (dsign)
- dval(rv) += ulp(dval(rv));
+#ifdef Avoid_Underflow
+ dval(&rv) += sulp(&rv, scale);
+#else
+ dval(&rv) += ulp(&rv);
+#endif
#ifndef ROUND_BIASED
else {
- dval(rv) -= ulp(dval(rv));
+#ifdef Avoid_Underflow
+ dval(&rv) -= sulp(&rv, scale);
+#else
+ dval(&rv) -= ulp(&rv);
+#endif
#ifndef Sudden_Underflow
- if (!dval(rv))
+ if (!dval(&rv))
goto undfl;
#endif
}
@@ -841,14 +888,14 @@ strtod
}
if ((aadj = ratio(delta, bs)) <= 2.) {
if (dsign)
- aadj = aadj1 = 1.;
- else if (word1(rv) || word0(rv) & Bndry_mask) {
+ aadj = dval(&aadj1) = 1.;
+ else if (word1(&rv) || word0(&rv) & Bndry_mask) {
#ifndef Sudden_Underflow
- if (word1(rv) == Tiny1 && !word0(rv))
+ if (word1(&rv) == Tiny1 && !word0(&rv))
goto undfl;
#endif
aadj = 1.;
- aadj1 = -1.;
+ dval(&aadj1) = -1.;
}
else {
/* special case -- power of FLT_RADIX to be */
@@ -858,45 +905,45 @@ strtod
aadj = 1./FLT_RADIX;
else
aadj *= 0.5;
- aadj1 = -aadj;
+ dval(&aadj1) = -aadj;
}
}
else {
aadj *= 0.5;
- aadj1 = dsign ? aadj : -aadj;
+ dval(&aadj1) = dsign ? aadj : -aadj;
#ifdef Check_FLT_ROUNDS
switch(Rounding) {
case 2: /* towards +infinity */
- aadj1 -= 0.5;
+ dval(&aadj1) -= 0.5;
break;
case 0: /* towards 0 */
case 3: /* towards -infinity */
- aadj1 += 0.5;
+ dval(&aadj1) += 0.5;
}
#else
if (Flt_Rounds == 0)
- aadj1 += 0.5;
+ dval(&aadj1) += 0.5;
#endif /*Check_FLT_ROUNDS*/
}
- y = word0(rv) & Exp_mask;
+ y = word0(&rv) & Exp_mask;
/* Check for overflow */
if (y == Exp_msk1*(DBL_MAX_EXP+Bias-1)) {
- dval(rv0) = dval(rv);
- word0(rv) -= P*Exp_msk1;
- adj = aadj1 * ulp(dval(rv));
- dval(rv) += adj;
- if ((word0(rv) & Exp_mask) >=
+ dval(&rv0) = dval(&rv);
+ word0(&rv) -= P*Exp_msk1;
+ dval(&adj) = dval(&aadj1) * ulp(&rv);
+ dval(&rv) += dval(&adj);
+ if ((word0(&rv) & Exp_mask) >=
Exp_msk1*(DBL_MAX_EXP+Bias-P)) {
- if (word0(rv0) == Big0 && word1(rv0) == Big1)
+ if (word0(&rv0) == Big0 && word1(&rv0) == Big1)
goto ovfl;
- word0(rv) = Big0;
- word1(rv) = Big1;
+ word0(&rv) = Big0;
+ word1(&rv) = Big1;
goto cont;
}
else
- word0(rv) += P*Exp_msk1;
+ word0(&rv) += P*Exp_msk1;
}
else {
#ifdef Avoid_Underflow
@@ -905,58 +952,58 @@ strtod
if ((z = aadj) <= 0)
z = 1;
aadj = z;
- aadj1 = dsign ? aadj : -aadj;
+ dval(&aadj1) = dsign ? aadj : -aadj;
}
- word0(aadj1) += (2*P+1)*Exp_msk1 - y;
+ word0(&aadj1) += (2*P+1)*Exp_msk1 - y;
}
- adj = aadj1 * ulp(dval(rv));
- dval(rv) += adj;
+ dval(&adj) = dval(&aadj1) * ulp(&rv);
+ dval(&rv) += dval(&adj);
#else
#ifdef Sudden_Underflow
- if ((word0(rv) & Exp_mask) <= P*Exp_msk1) {
- dval(rv0) = dval(rv);
- word0(rv) += P*Exp_msk1;
- adj = aadj1 * ulp(dval(rv));
- dval(rv) += adj;
+ if ((word0(&rv) & Exp_mask) <= P*Exp_msk1) {
+ dval(&rv0) = dval(&rv);
+ word0(&rv) += P*Exp_msk1;
+ dval(&adj) = dval(&aadj1) * ulp(&rv);
+ dval(&rv) += adj;
#ifdef IBM
- if ((word0(rv) & Exp_mask) < P*Exp_msk1)
+ if ((word0(&rv) & Exp_mask) < P*Exp_msk1)
#else
- if ((word0(rv) & Exp_mask) <= P*Exp_msk1)
+ if ((word0(&rv) & Exp_mask) <= P*Exp_msk1)
#endif
{
- if (word0(rv0) == Tiny0
- && word1(rv0) == Tiny1)
+ if (word0(&rv0) == Tiny0
+ && word1(&rv0) == Tiny1)
goto undfl;
- word0(rv) = Tiny0;
- word1(rv) = Tiny1;
+ word0(&rv) = Tiny0;
+ word1(&rv) = Tiny1;
goto cont;
}
else
- word0(rv) -= P*Exp_msk1;
+ word0(&rv) -= P*Exp_msk1;
}
else {
- adj = aadj1 * ulp(dval(rv));
- dval(rv) += adj;
+ dval(&adj) = dval(&aadj1) * ulp(&rv);
+ dval(&rv) += adj;
}
#else /*Sudden_Underflow*/
- /* Compute adj so that the IEEE rounding rules will
- * correctly round rv + adj in some half-way cases.
- * If rv * ulp(rv) is denormalized (i.e.,
+ /* Compute dval(&adj) so that the IEEE rounding rules will
+ * correctly round rv + dval(&adj) in some half-way cases.
+ * If rv * ulp(&rv) is denormalized (i.e.,
* y <= (P-1)*Exp_msk1), we must adjust aadj to avoid
* trouble from bits lost to denormalization;
* example: 1.2e-307 .
*/
if (y <= (P-1)*Exp_msk1 && aadj > 1.) {
- aadj1 = (double)(int)(aadj + 0.5);
+ dval(&aadj1) = (double)(int)(aadj + 0.5);
if (!dsign)
- aadj1 = -aadj1;
+ dval(&aadj1) = -dval(&aadj1);
}
- adj = aadj1 * ulp(dval(rv));
- dval(rv) += adj;
+ dval(&adj) = dval(&aadj1) * ulp(&rv);
+ dval(&rv) += adj;
#endif /*Sudden_Underflow*/
#endif /*Avoid_Underflow*/
}
- z = word0(rv) & Exp_mask;
+ z = word0(&rv) & Exp_mask;
#ifndef SET_INEXACT
#ifdef Avoid_Underflow
if (!scale)
@@ -966,7 +1013,7 @@ strtod
L = (Long)aadj;
aadj -= L;
/* The tolerances below are conservative. */
- if (dsign || word1(rv) || word0(rv) & Bndry_mask) {
+ if (dsign || word1(&rv) || word0(&rv) & Bndry_mask) {
if (aadj < .4999999 || aadj > .5000001)
break;
}
@@ -980,12 +1027,17 @@ strtod
Bfree(bs);
Bfree(delta);
}
+ Bfree(bb);
+ Bfree(bd);
+ Bfree(bs);
+ Bfree(bd0);
+ Bfree(delta);
#ifdef SET_INEXACT
if (inexact) {
if (!oldinexact) {
- word0(rv0) = Exp_1 + (70 << Exp_shift);
- word1(rv0) = 0;
- dval(rv0) += 1.;
+ word0(&rv0) = Exp_1 + (70 << Exp_shift);
+ word1(&rv0) = 0;
+ dval(&rv0) += 1.;
}
}
else if (!oldinexact)
@@ -993,36 +1045,30 @@ strtod
#endif
#ifdef Avoid_Underflow
if (scale) {
- word0(rv0) = Exp_1 - 2*P*Exp_msk1;
- word1(rv0) = 0;
- dval(rv) *= dval(rv0);
+ word0(&rv0) = Exp_1 - 2*P*Exp_msk1;
+ word1(&rv0) = 0;
+ dval(&rv) *= dval(&rv0);
#ifndef NO_ERRNO
/* try to avoid the bug of testing an 8087 register value */
#ifdef IEEE_Arith
- if (!(word0(rv) & Exp_mask))
+ if (!(word0(&rv) & Exp_mask))
#else
- if (word0(rv) == 0 && word1(rv) == 0)
+ if (word0(&rv) == 0 && word1(&rv) == 0)
#endif
errno = ERANGE;
#endif
}
#endif /* Avoid_Underflow */
#ifdef SET_INEXACT
- if (inexact && !(word0(rv) & Exp_mask)) {
+ if (inexact && !(word0(&rv) & Exp_mask)) {
/* set underflow bit */
- dval(rv0) = 1e-300;
- dval(rv0) *= dval(rv0);
+ dval(&rv0) = 1e-300;
+ dval(&rv0) *= dval(&rv0);
}
#endif
- retfree:
- Bfree(bb);
- Bfree(bd);
- Bfree(bs);
- Bfree(bd0);
- Bfree(delta);
ret:
if (se)
*se = (char *)s;
- return sign ? -dval(rv) : dval(rv);
+ return sign ? -dval(&rv) : dval(&rv);
}
diff --git a/strtodI.c b/strtodI.c
index 98f889110e0e..0b7b8a45c09b 100644
--- a/strtodI.c
+++ b/strtodI.c
@@ -33,16 +33,16 @@ THIS SOFTWARE.
static double
#ifdef KR_headers
-ulpdown(d) double *d;
+ulpdown(d) U *d;
#else
-ulpdown(double *d)
+ulpdown(U *d)
#endif
{
double u;
- ULong *L = (ULong*)d;
+ ULong *L = d->L;
- u = ulp(*d);
- if (!(L[_1] | L[_0] & 0xfffff)
+ u = ulp(d);
+ if (!(L[_1] | (L[_0] & 0xfffff))
&& (L[_0] & 0x7ff00000) > 0x00100000)
u *= 0.5;
return u;
@@ -59,10 +59,6 @@ strtodI(CONST char *s, char **sp, double *dd)
ULong bits[2], sign;
Long exp;
int j, k;
- typedef union {
- double d[2];
- ULong L[4];
- } U;
U *u;
k = strtodg(s, sp, &fpi, &exp, bits);
@@ -70,17 +66,17 @@ strtodI(CONST char *s, char **sp, double *dd)
sign = k & STRTOG_Neg ? 0x80000000L : 0;
switch(k & STRTOG_Retmask) {
case STRTOG_NoNumber:
- u->d[0] = u->d[1] = 0.;
+ dval(&u[0]) = dval(&u[1]) = 0.;
break;
case STRTOG_Zero:
- u->d[0] = u->d[1] = 0.;
+ dval(&u[0]) = dval(&u[1]) = 0.;
#ifdef Sudden_Underflow
if (k & STRTOG_Inexact) {
if (sign)
- u->L[_0] = 0x80100000L;
+ word0(&u[0]) = 0x80100000L;
else
- u->L[2+_0] = 0x100000L;
+ word0(&u[1]) = 0x100000L;
}
break;
#else
@@ -88,80 +84,80 @@ strtodI(CONST char *s, char **sp, double *dd)
#endif
case STRTOG_Denormal:
- u->L[_1] = bits[0];
- u->L[_0] = bits[1];
+ word1(&u[0]) = bits[0];
+ word0(&u[0]) = bits[1];
goto contain;
case STRTOG_Normal:
- u->L[_1] = bits[0];
- u->L[_0] = (bits[1] & ~0x100000) | ((exp + 0x3ff + 52) << 20);
+ word1(&u[0]) = bits[0];
+ word0(&u[0]) = (bits[1] & ~0x100000) | ((exp + 0x3ff + 52) << 20);
contain:
j = k & STRTOG_Inexact;
if (sign) {
- u->L[_0] |= sign;
+ word0(&u[0]) |= sign;
j = STRTOG_Inexact - j;
}
switch(j) {
case STRTOG_Inexlo:
#ifdef Sudden_Underflow
if ((u->L[_0] & 0x7ff00000) < 0x3500000) {
- u->L[2+_0] = u->L[_0] + 0x3500000;
- u->L[2+_1] = u->L[_1];
- u->d[1] += ulp(u->d[1]);
- u->L[2+_0] -= 0x3500000;
- if (!(u->L[2+_0] & 0x7ff00000)) {
- u->L[2+_0] = sign;
- u->L[2+_1] = 0;
+ word0(&u[1]) = word0(&u[0]) + 0x3500000;
+ word1(&u[1]) = word1(&u[0]);
+ dval(&u[1]) += ulp(&u[1]);
+ word0(&u[1]) -= 0x3500000;
+ if (!(word0(&u[1]) & 0x7ff00000)) {
+ word0(&u[1]) = sign;
+ word1(&u[1]) = 0;
}
}
else
#endif
- u->d[1] = u->d[0] + ulp(u->d[0]);
+ dval(&u[1]) = dval(&u[0]) + ulp(&u[0]);
break;
case STRTOG_Inexhi:
- u->d[1] = u->d[0];
+ dval(&u[1]) = dval(&u[0]);
#ifdef Sudden_Underflow
- if ((u->L[_0] & 0x7ff00000) < 0x3500000) {
- u->L[_0] += 0x3500000;
- u->d[0] -= ulpdown(u->d);
- u->L[_0] -= 0x3500000;
- if (!(u->L[_0] & 0x7ff00000)) {
- u->L[_0] = sign;
- u->L[_1] = 0;
+ if ((word0(&u[0]) & 0x7ff00000) < 0x3500000) {
+ word0(&u[0]) += 0x3500000;
+ dval(&u[0]) -= ulpdown(u);
+ word0(&u[0]) -= 0x3500000;
+ if (!(word0(&u[0]) & 0x7ff00000)) {
+ word0(&u[0]) = sign;
+ word1(&u[0]) = 0;
}
}
else
#endif
- u->d[0] -= ulpdown(u->d);
+ dval(&u[0]) -= ulpdown(u);
break;
default:
- u->d[1] = u->d[0];
+ dval(&u[1]) = dval(&u[0]);
}
break;
case STRTOG_Infinite:
- u->L[_0] = u->L[2+_0] = sign | 0x7ff00000;
- u->L[_1] = u->L[2+_1] = 0;
+ word0(&u[0]) = word0(&u[1]) = sign | 0x7ff00000;
+ word1(&u[0]) = word1(&u[1]) = 0;
if (k & STRTOG_Inexact) {
if (sign) {
- u->L[2+_0] = 0xffefffffL;
- u->L[2+_1] = 0xffffffffL;
+ word0(&u[1]) = 0xffefffffL;
+ word1(&u[1]) = 0xffffffffL;
}
else {
- u->L[_0] = 0x7fefffffL;
- u->L[_1] = 0xffffffffL;
+ word0(&u[0]) = 0x7fefffffL;
+ word1(&u[0]) = 0xffffffffL;
}
}
break;
case STRTOG_NaN:
- u->L[0] = u->L[2] = d_QNAN0;
- u->L[1] = u->L[3] = d_QNAN1;
+ u->L[0] = (u+1)->L[0] = d_QNAN0;
+ u->L[1] = (u+1)->L[1] = d_QNAN1;
break;
case STRTOG_NaNbits:
- u->L[_0] = u->L[2+_0] = 0x7ff00000 | sign | bits[1];
- u->L[_1] = u->L[2+_1] = bits[0];
+ word0(&u[0]) = word0(&u[1]) = 0x7ff00000 | sign | bits[1];
+ word1(&u[0]) = word1(&u[1]) = bits[0];
}
return k;
}
diff --git a/strtodg.c b/strtodg.c
index a69ce3028256..5059869ecf5f 100644
--- a/strtodg.c
+++ b/strtodg.c
@@ -172,9 +172,9 @@ set_ones(Bigint *b, int n)
rvOK
#ifdef KR_headers
(d, fpi, exp, bits, exact, rd, irv)
- double d; FPI *fpi; Long *exp; ULong *bits; int exact, rd, *irv;
+ U *d; FPI *fpi; Long *exp; ULong *bits; int exact, rd, *irv;
#else
- (double d, FPI *fpi, Long *exp, ULong *bits, int exact, int rd, int *irv)
+ (U *d, FPI *fpi, Long *exp, ULong *bits, int exact, int rd, int *irv)
#endif
{
Bigint *b;
@@ -182,7 +182,7 @@ rvOK
int bdif, e, j, k, k1, nb, rv;
carry = rv = 0;
- b = d2b(d, &e, &bdif);
+ b = d2b(dval(d), &e, &bdif);
bdif -= nb = fpi->nbits;
e += bdif;
if (bdif <= 0) {
@@ -291,9 +291,9 @@ rvOK
static int
#ifdef KR_headers
-mantbits(d) double d;
+mantbits(d) U *d;
#else
-mantbits(double d)
+mantbits(U *d)
#endif
{
ULong L;
@@ -327,8 +327,9 @@ strtodg
int j, k, nbits, nd, nd0, nf, nz, nz0, rd, rvbits, rve, rve1, sign;
int sudden_underflow;
CONST char *s, *s0, *s1;
- double adj, adj0, rv, tol;
+ double adj0, tol;
Long L;
+ U adj, rv;
ULong *b, *be, y, z;
Bigint *ab, *bb, *bb1, *bd, *bd0, *bs, *delta, *rvb, *rvb0;
#ifdef USE_LOCALE /*{{*/
@@ -341,7 +342,7 @@ strtodg
static int dplen;
if (!(s0 = decimalpoint_cache)) {
s0 = localeconv()->decimal_point;
- if ((decimalpoint_cache = (char*)malloc(strlen(s0) + 1))) {
+ if ((decimalpoint_cache = (char*)MALLOC(strlen(s0) + 1))) {
strcpy(decimalpoint_cache, s0);
s0 = decimalpoint_cache;
}
@@ -355,7 +356,7 @@ strtodg
irv = STRTOG_Zero;
denorm = sign = nz0 = nz = 0;
- dval(rv) = 0.;
+ dval(&rv) = 0.;
rvb = 0;
nbits = fpi->nbits;
for(s = s00;;s++) switch(*s) {
@@ -547,13 +548,13 @@ strtodg
if (!nd0)
nd0 = nd;
k = nd < DBL_DIG + 1 ? nd : DBL_DIG + 1;
- dval(rv) = y;
+ dval(&rv) = y;
if (k > 9)
- dval(rv) = tens[k - 9] * dval(rv) + z;
+ dval(&rv) = tens[k - 9] * dval(&rv) + z;
bd0 = 0;
if (nbits <= P && nd <= DBL_DIG) {
if (!e) {
- if (rvOK(dval(rv), fpi, exp, bits, 1, rd, &irv))
+ if (rvOK(&rv, fpi, exp, bits, 1, rd, &irv))
goto ret;
}
else if (e > 0) {
@@ -561,9 +562,9 @@ strtodg
#ifdef VAX
goto vax_ovfl_check;
#else
- i = fivesbits[e] + mantbits(dval(rv)) <= P;
- /* rv = */ rounded_product(dval(rv), tens[e]);
- if (rvOK(dval(rv), fpi, exp, bits, i, rd, &irv))
+ i = fivesbits[e] + mantbits(&rv) <= P;
+ /* rv = */ rounded_product(dval(&rv), tens[e]);
+ if (rvOK(&rv, fpi, exp, bits, i, rd, &irv))
goto ret;
e1 -= e;
goto rv_notOK;
@@ -576,32 +577,32 @@ strtodg
*/
e2 = e - i;
e1 -= i;
- dval(rv) *= tens[i];
+ dval(&rv) *= tens[i];
#ifdef VAX
/* VAX exponent range is so narrow we must
* worry about overflow here...
*/
vax_ovfl_check:
- dval(adj) = dval(rv);
- word0(adj) -= P*Exp_msk1;
- /* adj = */ rounded_product(dval(adj), tens[e2]);
- if ((word0(adj) & Exp_mask)
+ dval(&adj) = dval(&rv);
+ word0(&adj) -= P*Exp_msk1;
+ /* adj = */ rounded_product(dval(&adj), tens[e2]);
+ if ((word0(&adj) & Exp_mask)
> Exp_msk1*(DBL_MAX_EXP+Bias-1-P))
goto rv_notOK;
- word0(adj) += P*Exp_msk1;
- dval(rv) = dval(adj);
+ word0(&adj) += P*Exp_msk1;
+ dval(&rv) = dval(&adj);
#else
- /* rv = */ rounded_product(dval(rv), tens[e2]);
+ /* rv = */ rounded_product(dval(&rv), tens[e2]);
#endif
- if (rvOK(dval(rv), fpi, exp, bits, 0, rd, &irv))
+ if (rvOK(&rv, fpi, exp, bits, 0, rd, &irv))
goto ret;
e1 -= e2;
}
}
#ifndef Inaccurate_Divide
else if (e >= -Ten_pmax) {
- /* rv = */ rounded_quotient(dval(rv), tens[-e]);
- if (rvOK(dval(rv), fpi, exp, bits, 0, rd, &irv))
+ /* rv = */ rounded_quotient(dval(&rv), tens[-e]);
+ if (rvOK(&rv, fpi, exp, bits, 0, rd, &irv))
goto ret;
e1 -= e;
}
@@ -615,45 +616,45 @@ strtodg
e2 = 0;
if (e1 > 0) {
if ( (i = e1 & 15) !=0)
- dval(rv) *= tens[i];
+ dval(&rv) *= tens[i];
if (e1 &= ~15) {
e1 >>= 4;
- while(e1 >= (1 << n_bigtens-1)) {
- e2 += ((word0(rv) & Exp_mask)
+ while(e1 >= (1 << (n_bigtens-1))) {
+ e2 += ((word0(&rv) & Exp_mask)
>> Exp_shift1) - Bias;
- word0(rv) &= ~Exp_mask;
- word0(rv) |= Bias << Exp_shift1;
- dval(rv) *= bigtens[n_bigtens-1];
- e1 -= 1 << n_bigtens-1;
+ word0(&rv) &= ~Exp_mask;
+ word0(&rv) |= Bias << Exp_shift1;
+ dval(&rv) *= bigtens[n_bigtens-1];
+ e1 -= 1 << (n_bigtens-1);
}
- e2 += ((word0(rv) & Exp_mask) >> Exp_shift1) - Bias;
- word0(rv) &= ~Exp_mask;
- word0(rv) |= Bias << Exp_shift1;
+ e2 += ((word0(&rv) & Exp_mask) >> Exp_shift1) - Bias;
+ word0(&rv) &= ~Exp_mask;
+ word0(&rv) |= Bias << Exp_shift1;
for(j = 0; e1 > 0; j++, e1 >>= 1)
if (e1 & 1)
- dval(rv) *= bigtens[j];
+ dval(&rv) *= bigtens[j];
}
}
else if (e1 < 0) {
e1 = -e1;
if ( (i = e1 & 15) !=0)
- dval(rv) /= tens[i];
+ dval(&rv) /= tens[i];
if (e1 &= ~15) {
e1 >>= 4;
- while(e1 >= (1 << n_bigtens-1)) {
- e2 += ((word0(rv) & Exp_mask)
+ while(e1 >= (1 << (n_bigtens-1))) {
+ e2 += ((word0(&rv) & Exp_mask)
>> Exp_shift1) - Bias;
- word0(rv) &= ~Exp_mask;
- word0(rv) |= Bias << Exp_shift1;
- dval(rv) *= tinytens[n_bigtens-1];
- e1 -= 1 << n_bigtens-1;
+ word0(&rv) &= ~Exp_mask;
+ word0(&rv) |= Bias << Exp_shift1;
+ dval(&rv) *= tinytens[n_bigtens-1];
+ e1 -= 1 << (n_bigtens-1);
}
- e2 += ((word0(rv) & Exp_mask) >> Exp_shift1) - Bias;
- word0(rv) &= ~Exp_mask;
- word0(rv) |= Bias << Exp_shift1;
+ e2 += ((word0(&rv) & Exp_mask) >> Exp_shift1) - Bias;
+ word0(&rv) &= ~Exp_mask;
+ word0(&rv) |= Bias << Exp_shift1;
for(j = 0; e1 > 0; j++, e1 >>= 1)
if (e1 & 1)
- dval(rv) *= tinytens[j];
+ dval(&rv) *= tinytens[j];
}
}
#ifdef IBM
@@ -664,7 +665,7 @@ strtodg
*/
e2 <<= 2;
#endif
- rvb = d2b(dval(rv), &rve, &rvbits); /* rv = rvb * 2^rve */
+ rvb = d2b(dval(&rv), &rve, &rvbits); /* rv = rvb * 2^rve */
rve += e2;
if ((j = rvbits - nbits) > 0) {
rshift(rvb, j);
@@ -842,7 +843,7 @@ strtodg
}
else
irv = STRTOG_Normal | STRTOG_Inexhi;
- if (bbbits < nbits && !denorm || !(rvb->x[0] & 1))
+ if ((bbbits < nbits && !denorm) || !(rvb->x[0] & 1))
break;
if (dsign) {
rvb = increment(rvb);
@@ -859,7 +860,7 @@ strtodg
}
break;
}
- if ((dval(adj) = ratio(delta, bs)) <= 2.) {
+ if ((dval(&adj) = ratio(delta, bs)) <= 2.) {
adj1:
inex = STRTOG_Inexlo;
if (dsign) {
@@ -873,15 +874,15 @@ strtodg
irv = STRTOG_Underflow | STRTOG_Inexlo;
break;
}
- adj0 = dval(adj) = 1.;
+ adj0 = dval(&adj) = 1.;
}
else {
- adj0 = dval(adj) *= 0.5;
+ adj0 = dval(&adj) *= 0.5;
if (dsign) {
asub = 0;
inex = STRTOG_Inexlo;
}
- if (dval(adj) < 2147483647.) {
+ if (dval(&adj) < 2147483647.) {
L = adj0;
adj0 -= L;
switch(rd) {
@@ -900,12 +901,12 @@ strtodg
inex = STRTOG_Inexact - inex;
}
}
- dval(adj) = L;
+ dval(&adj) = L;
}
}
y = rve + rvbits;
- /* adj *= ulp(dval(rv)); */
+ /* adj *= ulp(dval(&rv)); */
/* if (asub) rv -= adj; else rv += adj; */
if (!denorm && rvbits < nbits) {
@@ -913,7 +914,7 @@ strtodg
rve -= j;
rvbits = nbits;
}
- ab = d2b(dval(adj), &abe, &abits);
+ ab = d2b(dval(&adj), &abe, &abits);
if (abe < 0)
rshift(ab, -abe);
else if (abe > 0)
@@ -967,15 +968,15 @@ strtodg
z = rve + rvbits;
if (y == z && L) {
/* Can we stop now? */
- tol = dval(adj) * 5e-16; /* > max rel error */
- dval(adj) = adj0 - .5;
- if (dval(adj) < -tol) {
+ tol = dval(&adj) * 5e-16; /* > max rel error */
+ dval(&adj) = adj0 - .5;
+ if (dval(&adj) < -tol) {
if (adj0 > tol) {
irv |= inex;
break;
}
}
- else if (dval(adj) > tol && adj0 < 1. - tol) {
+ else if (dval(&adj) > tol && adj0 < 1. - tol) {
irv |= inex;
break;
}
diff --git a/strtof.c b/strtof.c
index f8111b716c21..a8beb3520a01 100644
--- a/strtof.c
+++ b/strtof.c
@@ -58,7 +58,7 @@ strtof(CONST char *s, char **sp)
case STRTOG_Normal:
case STRTOG_NaNbits:
- u.L[0] = bits[0] & 0x7fffff | exp + 0x7f + 23 << 23;
+ u.L[0] = (bits[0] & 0x7fffff) | ((exp + 0x7f + 23) << 23);
break;
case STRTOG_Denormal:
diff --git a/strtopdd.c b/strtopdd.c
index c6659761abb1..738372d8829f 100644
--- a/strtopdd.c
+++ b/strtopdd.c
@@ -67,8 +67,8 @@ strtopdd(CONST char *s, char **sp, double *dd)
case STRTOG_Normal:
u->L[_1] = (bits[1] >> 21 | bits[2] << 11) & 0xffffffffL;
- u->L[_0] = bits[2] >> 21 | bits[3] << 11 & 0xfffff
- | exp + 0x3ff + 105 << 20;
+ u->L[_0] = (bits[2] >> 21) | ((bits[3] << 11) & 0xfffff)
+ | ((exp + 0x3ff + 105) << 20);
exp += 0x3ff + 52;
if (bits[1] &= 0x1fffff) {
i = hi0bits(bits[1]) - 11;
@@ -79,7 +79,7 @@ strtopdd(CONST char *s, char **sp, double *dd)
else
exp -= i;
if (i > 0) {
- bits[1] = bits[1] << i | bits[0] >> 32-i;
+ bits[1] = bits[1] << i | bits[0] >> (32-i);
bits[0] = bits[0] << i & 0xffffffffL;
}
}
@@ -92,11 +92,11 @@ strtopdd(CONST char *s, char **sp, double *dd)
else
exp -= i;
if (i < 32) {
- bits[1] = bits[0] >> 32 - i;
+ bits[1] = bits[0] >> (32 - i);
bits[0] = bits[0] << i & 0xffffffffL;
}
else {
- bits[1] = bits[0] << i - 32;
+ bits[1] = bits[0] << (i - 32);
bits[0] = 0;
}
}
@@ -105,7 +105,7 @@ strtopdd(CONST char *s, char **sp, double *dd)
break;
}
u->L[2+_1] = bits[0];
- u->L[2+_0] = bits[1] & 0xfffff | exp << 20;
+ u->L[2+_0] = (bits[1] & 0xfffff) | (exp << 20);
break;
case STRTOG_Denormal:
@@ -124,10 +124,10 @@ strtopdd(CONST char *s, char **sp, double *dd)
nearly_normal:
i = hi0bits(bits[3]) - 11; /* i >= 12 */
j = 32 - i;
- u->L[_0] = (bits[3] << i | bits[2] >> j) & 0xfffff
- | 65 - i << 20;
+ u->L[_0] = ((bits[3] << i | bits[2] >> j) & 0xfffff)
+ | ((65 - i) << 20);
u->L[_1] = (bits[2] << i | bits[1] >> j) & 0xffffffffL;
- u->L[2+_0] = bits[1] & (1L << j) - 1;
+ u->L[2+_0] = bits[1] & ((1L << j) - 1);
u->L[2+_1] = bits[0];
break;
@@ -136,34 +136,34 @@ strtopdd(CONST char *s, char **sp, double *dd)
if (i < 0) {
j = -i;
i += 32;
- u->L[_0] = bits[2] >> j & 0xfffff | (33 + j) << 20;
- u->L[_1] = (bits[2] << i | bits[1] >> j) & 0xffffffffL;
- u->L[2+_0] = bits[1] & (1L << j) - 1;
+ u->L[_0] = (bits[2] >> j & 0xfffff) | (33 + j) << 20;
+ u->L[_1] = ((bits[2] << i) | (bits[1] >> j)) & 0xffffffffL;
+ u->L[2+_0] = bits[1] & ((1L << j) - 1);
u->L[2+_1] = bits[0];
break;
}
if (i == 0) {
- u->L[_0] = bits[2] & 0xfffff | 33 << 20;
+ u->L[_0] = (bits[2] & 0xfffff) | (33 << 20);
u->L[_1] = bits[1];
u->L[2+_0] = 0;
u->L[2+_1] = bits[0];
break;
}
j = 32 - i;
- u->L[_0] = (bits[2] << i | bits[1] >> j) & 0xfffff
- | j + 1 << 20;
+ u->L[_0] = (((bits[2] << i) | (bits[1] >> j)) & 0xfffff)
+ | ((j + 1) << 20);
u->L[_1] = (bits[1] << i | bits[0] >> j) & 0xffffffffL;
u->L[2+_0] = 0;
- u->L[2+_1] = bits[0] & (1L << j) - 1;
+ u->L[2+_1] = bits[0] & ((1L << j) - 1);
break;
hardly_normal:
j = 11 - hi0bits(bits[1]);
i = 32 - j;
- u->L[_0] = bits[1] >> j & 0xfffff | j + 1 << 20;
+ u->L[_0] = (bits[1] >> j & 0xfffff) | ((j + 1) << 20);
u->L[_1] = (bits[1] << i | bits[0] >> j) & 0xffffffffL;
u->L[2+_0] = 0;
- u->L[2+_1] = bits[0] & (1L << j) - 1;
+ u->L[2+_1] = bits[0] & ((1L << j) - 1);
break;
case STRTOG_Infinite:
diff --git a/strtopf.c b/strtopf.c
index 74694a07ef51..23ca5cbe582a 100644
--- a/strtopf.c
+++ b/strtopf.c
@@ -58,7 +58,7 @@ strtopf(CONST char *s, char **sp, float *f)
case STRTOG_Normal:
case STRTOG_NaNbits:
- L[0] = bits[0] & 0x7fffff | exp + 0x7f + 23 << 23;
+ L[0] = (bits[0] & 0x7fffff) | ((exp + 0x7f + 23) << 23);
break;
case STRTOG_Denormal:
diff --git a/strtopx.c b/strtopx.c
index 07d04587b000..f7a25ff1ac9d 100644
--- a/strtopx.c
+++ b/strtopx.c
@@ -92,7 +92,8 @@ strtopx(CONST char *s, char **sp, void *V)
case STRTOG_Infinite:
L[_0] = 0x7fff;
- L[_1] = L[_2] = L[_3] = L[_4] = 0;
+ L[_1] = 0x8000;
+ L[_2] = L[_3] = L[_4] = 0;
break;
case STRTOG_NaN:
diff --git a/strtopxL.c b/strtopxL.c
index b0f5cdd0d813..6519a4144286 100644
--- a/strtopxL.c
+++ b/strtopxL.c
@@ -82,7 +82,8 @@ strtopxL(CONST char *s, char **sp, void *V)
case STRTOG_Infinite:
L[_0] = 0x7fff << 16;
- L[_1] = L[_2] = 0;
+ L[_1] = 0x80000000;
+ L[_2] = 0;
break;
case STRTOG_NaN:
diff --git a/strtordd.c b/strtordd.c
index 9c2b46e65e3e..e0b8e6a23fda 100644
--- a/strtordd.c
+++ b/strtordd.c
@@ -48,8 +48,8 @@ ULtodd(ULong *L, ULong *bits, Long exp, int k)
case STRTOG_Normal:
L[_1] = (bits[1] >> 21 | bits[2] << 11) & (ULong)0xffffffffL;
- L[_0] = bits[2] >> 21 | bits[3] << 11 & 0xfffff
- | exp + 0x3ff + 105 << 20;
+ L[_0] = (bits[2] >> 21) | (bits[3] << 11 & 0xfffff)
+ | ((exp + 0x3ff + 105) << 20);
exp += 0x3ff + 52;
if (bits[1] &= 0x1fffff) {
i = hi0bits(bits[1]) - 11;
@@ -60,7 +60,7 @@ ULtodd(ULong *L, ULong *bits, Long exp, int k)
else
exp -= i;
if (i > 0) {
- bits[1] = bits[1] << i | bits[0] >> 32-i;
+ bits[1] = bits[1] << i | bits[0] >> (32-i);
bits[0] = bits[0] << i & (ULong)0xffffffffL;
}
}
@@ -73,11 +73,11 @@ ULtodd(ULong *L, ULong *bits, Long exp, int k)
else
exp -= i;
if (i < 32) {
- bits[1] = bits[0] >> 32 - i;
+ bits[1] = bits[0] >> (32 - i);
bits[0] = bits[0] << i & (ULong)0xffffffffL;
}
else {
- bits[1] = bits[0] << i - 32;
+ bits[1] = bits[0] << (i - 32);
bits[0] = 0;
}
}
@@ -86,7 +86,7 @@ ULtodd(ULong *L, ULong *bits, Long exp, int k)
break;
}
L[2+_1] = bits[0];
- L[2+_0] = bits[1] & 0xfffff | exp << 20;
+ L[2+_0] = (bits[1] & 0xfffff) | (exp << 20);
break;
case STRTOG_Denormal:
@@ -105,10 +105,10 @@ ULtodd(ULong *L, ULong *bits, Long exp, int k)
nearly_normal:
i = hi0bits(bits[3]) - 11; /* i >= 12 */
j = 32 - i;
- L[_0] = (bits[3] << i | bits[2] >> j) & 0xfffff
- | 65 - i << 20;
+ L[_0] = ((bits[3] << i | bits[2] >> j) & 0xfffff)
+ | ((65 - i) << 20);
L[_1] = (bits[2] << i | bits[1] >> j) & 0xffffffffL;
- L[2+_0] = bits[1] & ((ULong)1L << j) - 1;
+ L[2+_0] = bits[1] & (((ULong)1L << j) - 1);
L[2+_1] = bits[0];
break;
@@ -117,34 +117,34 @@ ULtodd(ULong *L, ULong *bits, Long exp, int k)
if (i < 0) {
j = -i;
i += 32;
- L[_0] = bits[2] >> j & 0xfffff | (33 + j) << 20;
+ L[_0] = (bits[2] >> j & 0xfffff) | ((33 + j) << 20);
L[_1] = (bits[2] << i | bits[1] >> j) & 0xffffffffL;
- L[2+_0] = bits[1] & ((ULong)1L << j) - 1;
+ L[2+_0] = bits[1] & (((ULong)1L << j) - 1);
L[2+_1] = bits[0];
break;
}
if (i == 0) {
- L[_0] = bits[2] & 0xfffff | 33 << 20;
+ L[_0] = (bits[2] & 0xfffff) | (33 << 20);
L[_1] = bits[1];
L[2+_0] = 0;
L[2+_1] = bits[0];
break;
}
j = 32 - i;
- L[_0] = (bits[2] << i | bits[1] >> j) & 0xfffff
- | j + 1 << 20;
+ L[_0] = (((bits[2] << i) | (bits[1] >> j)) & 0xfffff)
+ | ((j + 1) << 20);
L[_1] = (bits[1] << i | bits[0] >> j) & 0xffffffffL;
L[2+_0] = 0;
- L[2+_1] = bits[0] & (1L << j) - 1;
+ L[2+_1] = bits[0] & ((1L << j) - 1);
break;
hardly_normal:
j = 11 - hi0bits(bits[1]);
i = 32 - j;
- L[_0] = bits[1] >> j & 0xfffff | j + 1 << 20;
+ L[_0] = (bits[1] >> j & 0xfffff) | ((j + 1) << 20);
L[_1] = (bits[1] << i | bits[0] >> j) & 0xffffffffL;
L[2+_0] = 0;
- L[2+_1] = bits[0] & ((ULong)1L << j) - 1;
+ L[2+_1] = bits[0] & (((ULong)1L << j) - 1);
break;
case STRTOG_Infinite:
diff --git a/strtorf.c b/strtorf.c
index 46b0ba2e4246..21c6d28b88b9 100644
--- a/strtorf.c
+++ b/strtorf.c
@@ -46,7 +46,7 @@ ULtof(ULong *L, ULong *bits, Long exp, int k)
case STRTOG_Normal:
case STRTOG_NaNbits:
- L[0] = bits[0] & 0x7fffff | exp + 0x7f + 23 << 23;
+ L[0] = (bits[0] & 0x7fffff) | ((exp + 0x7f + 23) << 23);
break;
case STRTOG_Denormal:
diff --git a/strtorx.c b/strtorx.c
index 23f721aa2931..d2f947220e65 100644
--- a/strtorx.c
+++ b/strtorx.c
@@ -80,7 +80,8 @@ ULtox(UShort *L, ULong *bits, Long exp, int k)
case STRTOG_Infinite:
L[_0] = 0x7fff;
- L[_1] = L[_2] = L[_3] = L[_4] = 0;
+ L[_1] = 0x8000;
+ L[_2] = L[_3] = L[_4] = 0;
break;
case STRTOG_NaN:
diff --git a/strtorxL.c b/strtorxL.c
index ff62a61302a5..58acc8085561 100644
--- a/strtorxL.c
+++ b/strtorxL.c
@@ -70,7 +70,8 @@ ULtoxL(ULong *L, ULong *bits, Long exp, int k)
case STRTOG_Infinite:
L[_0] = 0x7fff << 16;
- L[_1] = L[_2] = 0;
+ L[_1] = 0x80000000;
+ L[_2] = 0;
break;
case STRTOG_NaN:
diff --git a/test/Qtest.c b/test/Qtest.c
index f694afb603e1..a94466a09f53 100644
--- a/test/Qtest.c
+++ b/test/Qtest.c
@@ -81,9 +81,14 @@ THIS SOFTWARE.
main(Void)
{
char *s, *s1, *se, *se1;
- int i, dItry, ndig = 0, r = 1;
- union { long double d; ULong bits[4]; } u, v[2];
+ int Ltest, i, dItry, ndig = 0, r = 1;
+ union { long double d; ULong bits[4]; } u, v[2], w;
+ w.bits[0] = w.bits[3] = 0;
+ w.d = 1.;
+ u.d = 3.;
+ w.d = w.d / u.d;
+ Ltest = sizeof(long double) == 16 && w.bits[0] && w.bits[3];
while( (s = fgets(ibuf, sizeof(ibuf), stdin)) !=0) {
while(*s <= ' ')
if (!*s++)
@@ -95,7 +100,7 @@ main(Void)
continue;
case 'n':
i = s[1];
- if (i <= ' ' || i >= '0' && i <= '9') {
+ if (i <= ' ' || (i >= '0' && i <= '9')) {
ndig = atoi(s+1);
continue;
}
@@ -113,8 +118,8 @@ main(Void)
}
}
printf("\nInput: %s", ibuf);
- printf(" --> f = #%lx %lx %lx %lx\n", u.bits[_0],
- u.bits[_1], u.bits[_2], u.bits[_3]);
+ printf(" --> f = #%lx %lx %lx %lx\n", U u.bits[_0],
+ U u.bits[_1], U u.bits[_2], U u.bits[_3]);
goto fmt_test;
}
dItry = 1;
@@ -128,7 +133,7 @@ main(Void)
printf("with bits = #%lx %lx %lx %lx\n",
U u.bits[_0], U u.bits[_1], U u.bits[_2], U u.bits[_3]);
fmt_test:
- if (sizeof(long double) == 16)
+ if (Ltest)
printf("printf(\"%%.35Lg\") gives %.35Lg\n", u.d);
se = g_Qfmt(obuf, u.bits, ndig, sizeof(obuf));
printf("g_Qfmt(%d) gives %d bytes: \"%s\"\n\n", ndig,
@@ -145,7 +150,7 @@ main(Void)
printf("fI[0] == fI[1] = #%lx %lx %lx %lx\n",
U v[0].bits[_0], U v[0].bits[_1],
U v[0].bits[_2], U v[0].bits[_3]);
- if (sizeof(long double) == 16)
+ if (Ltest)
printf("= %.35Lg\n", v[0].d);
}
}
@@ -153,12 +158,12 @@ main(Void)
printf("fI[0] = #%lx %lx %lx %lx\n",
U v[0].bits[_0], U v[0].bits[_1],
U v[0].bits[_2], U v[0].bits[_3]);
- if (sizeof(long double) == 16)
+ if (Ltest)
printf("= %.35Lg\n", v[0].d);
printf("fI[1] = #%lx %lx %lx %lx\n",
U v[1].bits[_0], U v[1].bits[_1],
U v[1].bits[_2], U v[1].bits[_3]);
- if (sizeof(long double) == 16)
+ if (Ltest)
printf("= %.35Lg\n", v[1].d);
if (!memcmp(v[0].bits, u.bits, 16))
printf("fI[0] == strtod\n");
diff --git a/test/README b/test/README
index 107620539389..042ecfea0aac 100644
--- a/test/README
+++ b/test/README
@@ -69,6 +69,12 @@ You can also or alternatively compile getround.c with
-DUSE_MY_LOCALE (when ../gdtoa.a is compiled with -DUSE_LOCALE)
to test multi-byte decimal points.
+If in the parent directory, you have sucessfully invoked "make Printf"
+to add a "printf" (called Printf and accessed via ../stdio1.h), then
+here you can use "make pf_test" and (if you have both a 64-bit long
+double and a 113-bit "quad" double type) "make pf_testLq" for a brief
+test of %g and %a variants in Printf.
+
These are simple test programs, not meant for exhaustive testing,
but for manually testing "interesting" cases. Paxson's testbase
is good for more exhaustive testing, in part with random inputs.
diff --git a/test/ddtest.c b/test/ddtest.c
index 6fc32511be05..2cf31524a905 100644
--- a/test/ddtest.c
+++ b/test/ddtest.c
@@ -94,7 +94,7 @@ main(Void)
continue;
case 'n':
i = s[1];
- if (i <= ' ' || i >= '0' && i <= '9') {
+ if (i <= ' ' || (i >= '0' && i <= '9')) {
ndig = atoi(s+1);
continue;
}
diff --git a/test/dt.c b/test/dt.c
index ed0daeb37e43..355476ff2797 100644
--- a/test/dt.c
+++ b/test/dt.c
@@ -44,6 +44,7 @@ THIS SOFTWARE.
#include <stdio.h>
#include "gdtoa.h"
+int STRTOD_DIGLIM = 24;
#ifdef KR_headers
#define Void /*void*/
#else
@@ -59,13 +60,18 @@ extern "C" double atof(const char*);
extern double atof ANSI((char*));
#endif
#endif
+
+typedef union { double d; ULong L[2]; } U;
+
#ifdef IEEE_8087
-#define word0(x) ((ULong *)&x)[1]
-#define word1(x) ((ULong *)&x)[0]
+#define word0(x) (x)->L[1]
+#define word1(x) (x)->L[0]
#else
-#define word0(x) ((ULong *)&x)[0]
-#define word1(x) ((ULong *)&x)[1]
+#define word0(x) (x)->L[0]
+#define word1(x) (x)->L[1]
#endif
+#define dval(x) (x)->d
+
#include "errno.h"
#ifdef __cplusplus
@@ -93,14 +99,14 @@ g_fmt(char *b, double x)
if (sign)
*b++ = '-';
if (decpt == 9999) /* Infinity or Nan */ {
- while(*b++ = *s++);
+ while((*b++ = *s++));
return;
}
if (decpt <= -4 || decpt > se - s + 5) {
*b++ = *s++;
if (*s) {
*b++ = '.';
- while(*b = *s++)
+ while((*b = *s++))
b++;
}
*b++ = 'e';
@@ -126,10 +132,10 @@ g_fmt(char *b, double x)
*b++ = '.';
for(; decpt < 0; decpt++)
*b++ = '0';
- while(*b++ = *s++);
+ while((*b++ = *s++));
}
else {
- while(*b = *s++) {
+ while((*b = *s++)) {
b++;
if (--decpt == 0 && *s)
*b++ = '.';
@@ -148,40 +154,41 @@ baderrno(Void)
fflush(stderr);
}
-#define U (unsigned long)
+#define UL (unsigned long)
static void
#ifdef KR_headers
-check(d) double d;
+check(d) U *d;
#else
-check(double d)
+check(U *d)
#endif
{
char buf[64];
int decpt, sign;
char *s, *se;
- double d1;
+ U d1;
- s = dtoa(d, 0, 0, &decpt, &sign, &se);
+ s = dtoa(dval(d), 0, 0, &decpt, &sign, &se);
sprintf(buf, "%s%s%se%d", sign ? "-" : "",
decpt == 9999 ? "" : ".", s, decpt);
errno = 0;
- d1 = strtod(buf, (char **)0);
+ dval(&d1) = strtod(buf, (char **)0);
if (errno)
baderrno();
- if (d != d1) {
+ if (dval(d) != dval(&d1)) {
printf("sent d = %.17g = 0x%lx %lx, buf = %s\n",
- d, U word0(d), U word1(d), buf);
+ dval(d), UL word0(d), UL word1(d), buf);
printf("got d1 = %.17g = 0x%lx %lx\n",
- d1, U word0(d1), U word1(d1));
+ dval(&d1), UL word0(&d1), UL word1(&d1));
}
}
int
-main(Void){
+main(Void)
+{
+ U d, d1;
char buf[2048], buf1[32];
char *fmt, *s, *s1, *se;
- double d, d1;
int decpt, sign;
int mode = 0, ndigits = 17;
ULong x, y;
@@ -196,8 +203,8 @@ main(Void){
}
printf("Input: %s", buf);
if (*buf == '#') {
- x = word0(d);
- y = word1(d);
+ x = word0(&d);
+ y = word1(&d);
/* sscanf(buf+1, "%lx %lx:%d %d", &x, &y, &mode, &ndigits); */
x = (ULong)strtoul(s1 = buf+1, &se, 16);
if (se > s1) {
@@ -205,72 +212,79 @@ main(Void){
if (se > s1)
sscanf(se, ":%d %d", &mode, &ndigits);
}
- word0(d) = x;
- word1(d) = y;
+ word0(&d) = x;
+ word1(&d) = y;
fmt = "Output: d =\n%.17g = 0x%lx %lx\n";
}
+ else if (*buf == '*') {
+ x = strtoul(buf,&s,10);
+ if (!*s && x > 18)
+ STRTOD_DIGLIM = (int)x;
+ printf("STRTOD_DIGLIM = %lu\n", UL x);
+ continue;
+ }
else {
errno = 0;
- d = strtod(buf,&se);
+ dval(&d) = strtod(buf,&se);
if (*se == ':')
sscanf(se+1,"%d %d", &mode, &ndigits);
- d1 = atof(buf);
+ dval(&d1) = atof(buf);
fmt = "Output: d =\n%.17g = 0x%lx %lx, se = %s";
if (errno)
baderrno();
}
- printf(fmt, d, U word0(d), U word1(d), se);
- g_fmt(buf1, d);
+ printf(fmt, dval(&d), UL word0(&d), UL word1(&d), se);
+ g_fmt(buf1, dval(&d));
printf("\tg_fmt gives \"%s\"\n", buf1);
- if (*buf != '#' && d != d1)
+ if (*buf != '#' && dval(&d) != dval(&d1))
printf("atof gives\n\
d1 = %.17g = 0x%lx %lx\nversus\n\
- d = %.17g = 0x%lx %lx\n", d1, U word0(d1), U word1(d1),
- d, U word0(d), U word1(d));
- check(d);
- s = dtoa(d, mode, ndigits, &decpt, &sign, &se);
+ d = %.17g = 0x%lx %lx\n", dval(&d1), UL word0(&d1), UL word1(&d1),
+ dval(&d), UL word0(&d), UL word1(&d));
+ check(&d);
+ s = dtoa(dval(&d), mode, ndigits, &decpt, &sign, &se);
printf("\tdtoa(mode = %d, ndigits = %d):\n", mode, ndigits);
printf("\tdtoa returns sign = %d, decpt = %d, %d digits:\n%s\n",
- sign, decpt, se-s, s);
- x = word1(d);
+ sign, decpt, (int)(se-s), s);
+ x = word1(&d);
if (x != 0xffffffff
- && (word0(d) & 0x7ff00000) != 0x7ff00000) {
+ && (word0(&d) & 0x7ff00000) != 0x7ff00000) {
#ifdef VAX
z = x << 16 | x >> 16;
z++;
z = z << 16 | z >> 16;
- word1(d) = z;
+ word1(&d) = z;
#else
- word1(d) = x + 1;
+ word1(&d) = x + 1;
#endif
printf("\tnextafter(d,+Inf) = %.17g = 0x%lx %lx:\n",
- d, U word0(d), U word1(d));
- g_fmt(buf1, d);
+ dval(&d), UL word0(&d), UL word1(&d));
+ g_fmt(buf1, dval(&d));
printf("\tg_fmt gives \"%s\"\n", buf1);
- s = dtoa(d, mode, ndigits, &decpt, &sign, &se);
+ s = dtoa(dval(&d), mode, ndigits, &decpt, &sign, &se);
printf(
"\tdtoa returns sign = %d, decpt = %d, %d digits:\n%s\n",
- sign, decpt, se-s, s);
- check(d);
+ sign, decpt, (int)(se-s), s);
+ check(&d);
}
if (x) {
#ifdef VAX
z = x << 16 | x >> 16;
z--;
z = z << 16 | z >> 16;
- word1(d) = z;
+ word1(&d) = z;
#else
- word1(d) = x - 1;
+ word1(&d) = x - 1;
#endif
printf("\tnextafter(d,-Inf) = %.17g = 0x%lx %lx:\n",
- d, U word0(d), U word1(d));
- g_fmt(buf1, d);
+ dval(&d), UL word0(&d), UL word1(&d));
+ g_fmt(buf1, dval(&d));
printf("\tg_fmt gives \"%s\"\n", buf1);
- s = dtoa(d, mode, ndigits, &decpt, &sign, &se);
+ s = dtoa(dval(&d), mode, ndigits, &decpt, &sign, &se);
printf(
"\tdtoa returns sign = %d, decpt = %d, %d digits:\n%s\n",
- sign, decpt, se-s, s);
- check(d);
+ sign, decpt, (int)(se-s), s);
+ check(&d);
}
}
return 0;
diff --git a/test/dtest.c b/test/dtest.c
index adcbfd11a228..0140f2ed3260 100644
--- a/test/dtest.c
+++ b/test/dtest.c
@@ -78,7 +78,7 @@ main(Void)
continue;
case 'n':
i = s[1];
- if (i <= ' ' || i >= '0' && i <= '9') {
+ if (i <= ' ' || (i >= '0' && i <= '9')) {
ndig = atoi(s+1);
continue;
}
diff --git a/test/ftest.c b/test/ftest.c
index 9f6e144ae7b6..2006fdcdd428 100644
--- a/test/ftest.c
+++ b/test/ftest.c
@@ -77,7 +77,7 @@ main(Void)
continue;
case 'n':
i = s[1];
- if (i <= ' ' || i >= '0' && i <= '9') {
+ if (i <= ' ' || (i >= '0' && i <= '9')) {
ndig = atoi(s+1);
continue;
}
diff --git a/test/getround.c b/test/getround.c
index e67e14fd4bd0..05eb199e7737 100644
--- a/test/getround.c
+++ b/test/getround.c
@@ -55,7 +55,7 @@ getround(int r, char *s)
r, dir[r]);
return r;
}
- }
+ }
i = atoi(s);
if (i >= 0 && i < 4) {
printf("Rounding mode for strtor... ");
diff --git a/test/makefile b/test/makefile
index 243b5a62a76f..a409fa166a0d 100644
--- a/test/makefile
+++ b/test/makefile
@@ -91,6 +91,10 @@ strtodt = strtodt.o $A
strtodt: $(strtodt)
$(CC) -o strtodt $(strtodt) $L
+pftest = pftest.o $A
+pftest: ../Printf $(pftest)
+ $(CC) -o pftest $(pftest) $L
+
## On Intel (and Intel-like) systems using extended-precision registers
## for double-precision (C type double) computations that sometimes suffer
## double rounding errors, the test below involving strtodt generally shows
@@ -138,16 +142,31 @@ tests: Q.out x.out xL.out dt dItest ddtest dtest ftest Qtest xLtest xtest ddtest
(cd bad; for i in *; do cmp -s $$i ../obad/$$i && rm $$i;done; cd ..; rmdir bad)
touch tests
-xs0 = README Qtest.c dItest.c ddtest.c dtest.c dt.c ftest.c getround.c \
- strtoIdSI.c strtoIddSI.c strtodISI.c strtodt.c strtopddSI.c \
- strtorddSI.c xLtest.c xQtest.c xtest.c rtestnos testnos testnos1 \
- testnos3 dI.out dIsi.out ddsi.out dd.out dtst.out d.out f.out \
- x.ou0 xL.ou0 x.ou1 xL.ou1 Q.ou0 Q.ou1 makefile
+# To test Printf in ../gdtoa.a, "make pf_test" and perhaps "make pf_testLq"
+# (if both long double and quad are desired and available).
+
+pf_test: pftest
+ ./pftest <pftestnos >zap
+ cmp pftest.out zap && rm zap
+
+pf_testLq: pftest
+ ./pftest <pfLqtestnos >zap
+ cmp pftestLq.out zap && rm zap
+
+xs0 = README Q.ou0 Q.ou1 Qtest.c d.out dI.out dIsi.out dItest.c dd.out\
+ ddsi.out ddtest.c dt.c dtest.c dtst.out f.out ftest.c\
+ getround.c makefile pfLqtestnos pftest.c pftestQ.out\
+ pftestx.out pftestLq.out pftestnos rtestnos strtoIdSI.c\
+ strtoIddSI.c strtodISI.c strtodt.c strtopddSI.c strtorddSI.c\
+ testnos testnos1 testnos3 x.ou0 x.ou1 xL.ou0 xL.ou1 xLtest.c\
+ xQtest.c xtest.c
+# invoke "make -r xsum.out"
xsum.out: xsum0.out $(xs0)
xsum $(xs0) >xsum1.out
cmp xsum0.out xsum1.out && mv xsum1.out xsum.out || diff xsum[01].out
clean:
- rm -f *.[ao] dt *test *testsi strtodt strtodtnrp xsum.out xsum1.out tests zap x.out xL.out Q.out
+ rm -f *.[ao] dt *test *testsi pftest.out strtodt strtodtnrp xsum.out\
+ xsum1.out tests zap x.out xL.out Q.out
rm -rf bad
diff --git a/test/pfLqtestnos b/test/pfLqtestnos
new file mode 100644
index 000000000000..0680923378b8
--- /dev/null
+++ b/test/pfLqtestnos
@@ -0,0 +1,13 @@
+%.8a 1.23
+%.7a
+%.2a
+%.La 1.23
+%.20Lqa 1.23
+%La 3e27
+%La 1.7e27
+%Lqa 3e48
+%Lqa 1e49
+1.5
+2.5
+4.5
+8.5
diff --git a/test/pftest.c b/test/pftest.c
new file mode 100644
index 000000000000..99d78ee451c1
--- /dev/null
+++ b/test/pftest.c
@@ -0,0 +1,158 @@
+/****************************************************************
+
+The author of this software is David M. Gay.
+
+Copyright (C) 2009 by David M. Gay
+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
+source-code copies and that both that the copyright notice and this
+permission notice and warranty disclaimer appear in supporting
+documentation.
+
+THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
+INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS.
+IN NO EVENT SHALL THE AUTHOR 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.
+
+****************************************************************/
+#include "stdio1.h"
+#include "gdtoa.h"
+#include <string.h>
+
+#undef allow_Quad
+#undef want_Quad
+#undef want_Ux
+#define want_LD
+typedef union Ud {double x; unsigned int u[2]; } Ud;
+#ifdef __x86_64 /*{{*/
+#define want_Ux
+#ifndef NO_GDTOA_i386_Quad /*{*/
+typedef union UQ {__float128 x; unsigned int u[4]; } UQ;
+#define allow_Quad(x) x
+#define want_Quad
+#endif /*}*/
+#else /*}{*/
+#ifdef __i386 /*{{*/
+#define want_Ux
+#else /*}{*/
+#ifdef __sparc /*{{*/
+typedef union UQ {long double x; unsigned int u[4]; } Ux;
+#else /*}{*/
+#ifdef __INTEL_COMPILER /*{*/
+#undef want_Quad
+#undef want_Ux
+#undef want_LD
+#endif /*}*/
+#endif /*}}*/
+#endif /*}}*/
+#endif /*}}*/
+
+#ifndef allow_Quad
+#define allow_Quad(x) /*nothing*/
+#endif
+
+#ifdef want_Ux /*{{*/
+typedef union Ux {long double x; unsigned short u[5]; } Ux;
+#else /*}{*/
+#ifdef __sparc
+#define want_Ux
+#endif
+#endif /*}}*/
+
+ int
+main(void)
+{
+ Ud d;
+ allow_Quad(UQ q;)
+ char *b, buf[256], fmt[32], *s;
+#ifdef want_Ux
+ Ux x;
+ x.x = 0.;
+#endif
+ int k;
+
+ k = 0;
+ strcpy(fmt, "%.g");
+ d.x = 0.;
+ allow_Quad(q.x = 0.;)
+ while(fgets(buf, sizeof(buf), stdin)) {
+ for(b = buf; *b && *b != '\n'; ++b);
+ *b = 0;
+ if (b == buf)
+ continue;
+ b = buf;
+ if (*b == '%') {
+ for(k = 0; *b > ' '; ++b)
+#ifdef want_LD /*{{*/
+ switch(*b) {
+ case 'L':
+ k = 1;
+#ifdef want_Quad
+ break;
+ case 'q':
+ if (k >= 1)
+ k = 2;
+#endif
+ }
+#else /*}{*/
+ ;
+#endif /*}}*/
+ if (*b)
+ *b++ = 0;
+ if (b - buf < sizeof(fmt)) {
+ strcpy(fmt, buf);
+ }
+ }
+ if (*b) {
+ switch(k) {
+ case 0:
+ d.x = strtod(b,&s);
+ break;
+ case 1:
+#ifdef want_Ux
+#ifdef __sparc
+ strtopQ(b,&s,&x.x);
+#else
+ strtopx(b,&s,&x.x);
+#endif
+#else
+ strtopQ(b,&s,&q.x);
+#endif
+ break;
+ allow_Quad(case 2: strtopQ(b,&s,&q.x);)
+ }
+ if (*s)
+ printf("Ignoring \"%s\"\n", s);
+ }
+ switch(k) {
+ case 0:
+ printf("d.x = %.g = #%x %x; %s ==> ", d.x, d.u[1], d.u[0], fmt);
+ printf(fmt, d.x);
+ break;
+ case 1:
+#ifdef __sparc
+ printf("x.x = %.Lg = #%x %x %x %x; %s ==> ", x.x,
+ x.u[0], x.u[1], x.u[2], x.u[3], fmt);
+#else
+ printf("x.x = %.Lg = #%x %x %x %x %x; %s ==> ", x.x,
+ x.u[4], x.u[3], x.u[2], x.u[1], x.u[0], fmt);
+#endif
+ printf(fmt, x.x);
+#ifdef want_Quad
+ break;
+ case 2:
+ printf("q.x = %.Lqg = #%x %x %x %x; %s ==> ", q.x,
+ q.u[3], q.u[2], q.u[1], q.u[0], fmt);
+ printf(fmt, q.x);
+#endif
+ }
+ putchar('\n');
+ }
+ return 0;
+ }
diff --git a/test/pftestLq.out b/test/pftestLq.out
new file mode 100644
index 000000000000..0bcec7461a1d
--- /dev/null
+++ b/test/pftestLq.out
@@ -0,0 +1,13 @@
+d.x = 1.23 = #3ff3ae14 7ae147ae; %.8a ==> 0x1.3ae147aep+0
+d.x = 1.23 = #3ff3ae14 7ae147ae; %.7a ==> 0x1.3ae147bp+0
+d.x = 1.23 = #3ff3ae14 7ae147ae; %.2a ==> 0x1.3bp+0
+x.x = 1.23 = #3fff 9d70 a3d7 a3d 70a4; %.La ==> 0xap-3
+q.x = 1.23 = #3fff3ae1 47ae147a e147ae14 7ae147ae; %.20Lqa ==> 0x1.3ae147ae147ae147ae14p+0
+x.x = 3e+27 = #405a 9b18 ab5d f718 b6c; %La ==> 0x9.b18ab5df7180b6cp+88
+x.x = 1.7e+27 = #4059 afc6 a015 291b 4024; %La ==> 0xa.fc6a015291b4024p+87
+q.x = 3e+48 = #40a006be 53879565 60c1e1a9 9c13ee2; %Lqa ==> 0x1.06be5387956560c1e1a909c13ee2p+161
+q.x = 1e+49 = #40a1b5e7 e08ca3a8 f6987819 baecbe22; %Lqa ==> 0x1.b5e7e08ca3a8f6987819baecbe22p+162
+q.x = 1.5 = #3fff8000 0 0 0; %Lqa ==> 0x1.8p+0
+q.x = 2.5 = #40004000 0 0 0; %Lqa ==> 0x1.4p+1
+q.x = 4.5 = #40012000 0 0 0; %Lqa ==> 0x1.2p+2
+q.x = 8.5 = #40021000 0 0 0; %Lqa ==> 0x1.1p+3
diff --git a/test/pftestQ.out b/test/pftestQ.out
new file mode 100644
index 000000000000..8c42afe69487
--- /dev/null
+++ b/test/pftestQ.out
@@ -0,0 +1,15 @@
+d.x = 1.23 = #7ae147ae 3ff3ae14; %.8a ==> 0x1.3ae147aep+0
+d.x = 1.23 = #7ae147ae 3ff3ae14; %.7a ==> 0x1.3ae147bp+0
+d.x = 1.23 = #7ae147ae 3ff3ae14; %.2a ==> 0x1.3bp+0
+x.x = 1.23 = #3fff3ae1 47ae147a e147ae14 7ae147ae; %.La ==> 0x1p+0
+x.x = 1.23 = #3fff3ae1 47ae147a e147ae14 7ae147ae; %.20La ==> 0x1.3ae147ae147ae147ae14p+0
+x.x = 3e+27 = #405a3631 56bbee30 16d70000 0; %La ==> 0x1.363156bbee3016d7p+91
+x.x = 1.7e+27 = #40595f8d 402a5236 80490000 0; %La ==> 0x1.5f8d402a52368049p+90
+d.x = 1.5 = #0 3ff80000; %a ==> 0x1.8p+0
+d.x = 2.5 = #0 40040000; %a ==> 0x1.4p+1
+d.x = 4.5 = #0 40120000; %a ==> 0x1.2p+2
+d.x = 8.5 = #0 40210000; %a ==> 0x1.1p+3
+x.x = 1.5 = #3fff8000 0 0 0; %La ==> 0x1.8p+0
+x.x = 2.5 = #40004000 0 0 0; %La ==> 0x1.4p+1
+x.x = 4.5 = #40012000 0 0 0; %La ==> 0x1.2p+2
+x.x = 8.5 = #40021000 0 0 0; %La ==> 0x1.1p+3
diff --git a/test/pftestnos b/test/pftestnos
new file mode 100644
index 000000000000..7b3010a8b4f2
--- /dev/null
+++ b/test/pftestnos
@@ -0,0 +1,15 @@
+%.8a 1.23
+%.7a
+%.2a
+%.La 1.23
+%.20La 1.23
+%La 3e27
+%La 1.7e27
+%a 1.5
+2.5
+4.5
+8.5
+%La 1.5
+2.5
+4.5
+8.5
diff --git a/test/pftestx.out b/test/pftestx.out
new file mode 100644
index 000000000000..15a08d3629c8
--- /dev/null
+++ b/test/pftestx.out
@@ -0,0 +1,15 @@
+d.x = 1.23 = #3ff3ae14 7ae147ae; %.8a ==> 0x1.3ae147aep+0
+d.x = 1.23 = #3ff3ae14 7ae147ae; %.7a ==> 0x1.3ae147bp+0
+d.x = 1.23 = #3ff3ae14 7ae147ae; %.2a ==> 0x1.3bp+0
+x.x = 1.23 = #3fff 9d70 a3d7 a3d 70a4; %.La ==> 0xap-3
+x.x = 1.23 = #3fff 9d70 a3d7 a3d 70a4; %.20La ==> 0x9.d70a3d70a3d70a4p-3
+x.x = 3e+27 = #405a 9b18 ab5d f718 b6c; %La ==> 0x9.b18ab5df7180b6cp+88
+x.x = 1.7e+27 = #4059 afc6 a015 291b 4024; %La ==> 0xa.fc6a015291b4024p+87
+d.x = 1.5 = #3ff80000 0; %a ==> 0x1.8p+0
+d.x = 2.5 = #40040000 0; %a ==> 0x1.4p+1
+d.x = 4.5 = #40120000 0; %a ==> 0x1.2p+2
+d.x = 8.5 = #40210000 0; %a ==> 0x1.1p+3
+x.x = 1.5 = #3fff c000 0 0 0; %La ==> 0xcp-3
+x.x = 2.5 = #4000 a000 0 0 0; %La ==> 0xap-2
+x.x = 4.5 = #4001 9000 0 0 0; %La ==> 0x9p-1
+x.x = 8.5 = #4002 8800 0 0 0; %La ==> 0x8.8p+0
diff --git a/test/strtodt.c b/test/strtodt.c
index 94c70213c211..2983615c0408 100644
--- a/test/strtodt.c
+++ b/test/strtodt.c
@@ -49,6 +49,8 @@ THIS SOFTWARE.
ULong L[2];
} U;
+#define UL (unsigned long)
+
static int
process(char *fname, FILE *f)
{
@@ -81,7 +83,7 @@ process(char *fname, FILE *f)
if (b.L[W0] != a.L[0] || b.L[W1] != a.L[1]) {
n++;
printf("Line %d of %s: got %lx %lx; expected %lx %lx\n",
- line, fname, b.L[W0], b.L[W1], a.L[0], a.L[1]);
+ line, fname, UL b.L[W0], UL b.L[W1], UL a.L[0], UL a.L[1]);
}
}
return n;
@@ -120,8 +122,8 @@ main(int argc, char **argv)
if (argc <= 1)
n = process("<stdin>", stdin);
else
- while(s = *++argv)
- if (f = fopen(s,"r")) {
+ while((s = *++argv))
+ if ((f = fopen(s,"r"))) {
n += process(s, f);
fclose(f);
}
diff --git a/test/testnos3 b/test/testnos3
index be489027edd7..2a7cf79444ee 100644
--- a/test/testnos3
+++ b/test/testnos3
@@ -326,3 +326,27 @@
# first is 2^-1075 (half the smallest denormal)
2.4703282292062327208828439643411068618252990130716238221279284125033775363510437593264991818081799618989828234772285886546332835517796989819938739800539093906315035659515570226392290858392449105184435931802849936536152500319370457678249219365623669863658480757001585769269903706311928279558551332927834338409351978015531246597263579574622766465272827220056374006485499977096599470454020828166226237857393450736339007967761930577506740176324673600968951340535537458516661134223766678604162159680461914467291840300530057530849048765391711386591646239524912623653881879636239373280423891018672348497668235089863388587925628302755995657524455507255189313690836254779186948667994968324049705821028513185451396213837722826145437693412532098591327667236328125e-324 0 0
2.47032822920623272e-324 0 0
+
+# examples reported by Mark Dickinson of bugs in the bigcomp() logic introduced
+# 20090316 in dtoa.c to speed handling of absurdly long input:
+12579816049008305546974391768996369464963024663104e-357 90bbd 7412d19f
+17489628565202117263145367596028389348922981857013e-357 c938e 9000492f
+18487398785991994634182916638542680759613590482273e-357 d4b3a ee198863
+32002864200581033134358724675198044527469366773928e-358 24d1e ed8448e3
+99999999999999994487665465554760717039532578546e-47 3ff00000 0
+1.0000000000000000100000000000000000000001e44 4911efc6 59cf7d4c
+1000000000000000000000000000000000000000e-16 44b52d02 c7e14af6
+10000000000000000000000000000000000000000e-17 44b52d02 c7e14af6
+10.900000000000000012345678912345678912345 4025cccc cccccccd
+104308485241983990666713401708072175773165034278685682646111762292409330928739751702404658197872319129036519947435319418387839758990478549477777586673075945844895981012024387992135617064532141489278815239849108105951619997829153633535314849999674266169258928940692239684771590065027025835804863585454872499320500023126142553932654370362024104462255244034053203998964360882487378334860197725139151265590832887433736189468858614521708567646743455601905935595381852723723645799866672558576993978025033590728687206296379801363024094048327273913079612469982585674824156000783167963081616214710691759864332339239688734656548790656486646106983450809073750535624894296242072010195710276073042036425579852459556183541199012652571123898996574563824424330960027873516082763671875e-1075 78026 65fd9600
+99037485700245683102805043437346965248029601286431e-373 0 2
+99617639833743863161109961162881027406769510558457e-373 0 2
+98852915025769345295749278351563179840130565591462e-372 0 14
+99059944827693569659153042769690930905148015876788e-373 0 2
+98914979205069368270421829889078356254059760327101e-372 0 14
+0.999999999999999999999999999999999999999999999e23 44b52d02 c7e14af6
+991633793189150720000000000000000000000000000000000000000e-33 44ea3f92 6bad90c6
+37652435753827922121470370984740152789920e234 78f1667a c9e75d61
+999999999999999996790597280027956716285163e-42 3ff00000 0
+9483973038658180570348795755328802873667739881500874740826641664593613312413122937394311083577538394191754403820631172036846773125424639263833553383990195662207006139342261292777056851379062046720e0 68a03d69 82f2f936
+20209005503919489280000000000000000000000000000000000000000e-40 43bc0bae 57e880e6
diff --git a/test/xLtest.c b/test/xLtest.c
index aba0cf538041..403ad83b62bc 100644
--- a/test/xLtest.c
+++ b/test/xLtest.c
@@ -83,7 +83,7 @@ main(Void)
int dItry, i, ndig = 0, r = 1;
union { long double d; ULong bits[3]; } u, v[2];
- while(s = fgets(ibuf, sizeof(ibuf), stdin)) {
+ while((s = fgets(ibuf, sizeof(ibuf), stdin))) {
while(*s <= ' ')
if (!*s++)
continue;
@@ -94,7 +94,7 @@ main(Void)
continue;
case 'n':
i = s[1];
- if (i <= ' ' || i >= '0' && i <= '9') {
+ if (i <= ' ' || (i >= '0' && i <= '9')) {
ndig = atoi(s+1);
continue;
}
@@ -109,8 +109,8 @@ main(Void)
u.bits[_2] = (ULong)strtoul(s1=se, &se, 16);
}
printf("\nInput: %s", ibuf);
- printf(" --> f = #%lx %lx %lx\n", u.bits[_0],
- u.bits[_1], u.bits[_2]);
+ printf(" --> f = #%lx %lx %lx\n", U u.bits[_0],
+ U u.bits[_1], U u.bits[_2]);
goto fmt_test;
}
dItry = 1;
diff --git a/test/xQtest.c b/test/xQtest.c
index 8dfe3652c42f..93bc4142ff2f 100644
--- a/test/xQtest.c
+++ b/test/xQtest.c
@@ -31,16 +31,28 @@ THIS SOFTWARE.
int
main(void)
{
+ union { long double d; unsigned int bits[4]; } u, w;
switch(sizeof(long double)) {
+ case 16:
+ w.bits[0] = w.bits[3] = 0;
+ w.d = 1.;
+ u.d = 3.;
+ w.d = w.d / u.d;
+ if (w.bits[0] && w.bits[3])
+ printf("cp x.ou0 x.out; cp xL.ou0 xL.out;"
+ " cp Q.ou1 Q.out; cp pftestQ.out pftest.out\n");
+ else
+ printf("cp x.ou0 x.out; cp xL.ou0 xL.out;"
+ " cp Q.ou0 Q.out; cp pftestx.out pftest.out\n");
+ break;
case 10:
case 12:
- printf("cp x.ou1 x.out; cp xL.ou1 xL.out; cp Q.ou0 Q.out\n");
- break;
- case 16:
- printf("cp x.ou0 x.out; cp xL.ou0 xL.out; cp Q.ou1 Q.out\n");
+ printf("cp x.ou1 x.out; cp xL.ou1 xL.out; cp Q.ou0 Q.out;"
+ " cp pftestx.out pftest.out\n");
break;
default:
- printf("cp x.ou0 x.out; cp xL.ou0 xL.out; cp Q.ou0 Q.out\n");
+ printf("cp x.ou0 x.out; cp xL.ou0 xL.out; cp Q.ou0 Q.out;"
+ " cp pftestx.out pftest.out\n");
}
return 0;
}
diff --git a/test/xsum0.out b/test/xsum0.out
index 3081e0a8722d..52b8a3e6040a 100644
--- a/test/xsum0.out
+++ b/test/xsum0.out
@@ -1,35 +1,41 @@
-README e3adb571 3095
-Qtest.c e8353ffc 5046
+README efba0d5d 3412
+Q.ou0 e4592b85 28742
+Q.ou1 ea0b344d 39572
+Qtest.c efe2b3f4 5116
+d.out f271efc9 28131
+dI.out d522eef 4369
+dIsi.out 1dd6d02f 4350
dItest.c e33800ce 2371
-ddtest.c f9d06e7b 4984
-dtest.c ee533ac3 4078
-dt.c 7eeda57 6384
-ftest.c ec8a6654 3999
-getround.c fe659fe7 2503
+dd.out e262456e 40923
+ddsi.out 1f94bbe2 10251
+ddtest.c ef71cbf3 4986
+dt.c e562c302 6808
+dtest.c 9a5d01 4080
+dtst.out e284ac98 23711
+f.out 9013e91 21537
+ftest.c 1c824a88 4001
+getround.c ee95ed1 2502
+makefile f714a641 5634
+pfLqtestnos ffb9723 99
+pftest.c ea314d7f 3452
+pftestQ.out 198434fd 830
+pftestx.out 1ccea5dd 788
+pftestLq.out 1691dbfc 845
+pftestnos ecbc9be6 101
+rtestnos f94bcdf6 336
strtoIdSI.c 7bfb88b 49
strtoIddSI.c 72e8852 50
strtodISI.c ed08b740 49
-strtodt.c aaf94bc 3330
+strtodt.c f1aa53af 3374
strtopddSI.c 13e7138d 50
strtorddSI.c f7e4b1d5 50
-xLtest.c f3f96ad1 4833
-xQtest.c efdea3a2 1549
-xtest.c ee81e661 4830
-rtestnos f94bcdf6 336
testnos e89999d6 485
testnos1 7e16229 294
-testnos3 fa5c8aca 11998
-dI.out d522eef 4369
-dIsi.out 1dd6d02f 4350
-ddsi.out 1f94bbe2 10251
-dd.out e262456e 40923
-dtst.out e284ac98 23711
-d.out f271efc9 28131
-f.out 9013e91 21537
+testnos3 f5ae7ef3 14403
x.ou0 1402f834 25372
-xL.ou0 faa3a741 26363
x.ou1 f1af5a00 34581
+xL.ou0 faa3a741 26363
xL.ou1 e349e5c 37165
-Q.ou0 e4592b85 28742
-Q.ou1 ea0b344d 39572
-makefile 13d36c85 5148
+xLtest.c ee11f673 4843
+xQtest.c efbe29be 1912
+xtest.c ec9f5deb 4834
diff --git a/test/xtest.c b/test/xtest.c
index 86d7fba01ce7..f5275f0b42ec 100644
--- a/test/xtest.c
+++ b/test/xtest.c
@@ -85,7 +85,7 @@ main(Void)
int i, dItry, ndig = 0, r = 1;
union { long double d; UShort bits[5]; } u, v[2];
- while(s = fgets(ibuf, sizeof(ibuf), stdin)) {
+ while((s = fgets(ibuf, sizeof(ibuf), stdin))) {
while(*s <= ' ')
if (!*s++)
continue;
@@ -96,7 +96,7 @@ main(Void)
continue;
case 'n':
i = s[1];
- if (i <= ' ' || i >= '0' && i <= '9') {
+ if (i <= ' ' || (i >= '0' && i <= '9')) {
ndig = atoi(s+1);
continue;
}
diff --git a/ulp.c b/ulp.c
index 7810a5c8e642..17e9f862c443 100644
--- a/ulp.c
+++ b/ulp.c
@@ -34,13 +34,13 @@ THIS SOFTWARE.
double
ulp
#ifdef KR_headers
- (x) double x;
+ (x) U *x;
#else
- (double x)
+ (U *x)
#endif
{
Long L;
- double a;
+ U a;
L = (word0(x) & Exp_mask) - (P-1)*Exp_msk1;
#ifndef Sudden_Underflow
@@ -49,22 +49,22 @@ ulp
#ifdef IBM
L |= Exp_msk1 >> 4;
#endif
- word0(a) = L;
- word1(a) = 0;
+ word0(&a) = L;
+ word1(&a) = 0;
#ifndef Sudden_Underflow
}
else {
L = -L >> Exp_shift;
if (L < Exp_shift) {
- word0(a) = 0x80000 >> L;
- word1(a) = 0;
+ word0(&a) = 0x80000 >> L;
+ word1(&a) = 0;
}
else {
- word0(a) = 0;
+ word0(&a) = 0;
L -= Exp_shift;
- word1(a) = L >= 31 ? 1 : 1 << 31 - L;
+ word1(&a) = L >= 31 ? 1 : 1 << (31 - L);
}
}
#endif
- return a;
+ return dval(&a);
}
diff --git a/xsum0.out b/xsum0.out
index 2034c711a352..e9c29bc23988 100644
--- a/xsum0.out
+++ b/xsum0.out
@@ -1,49 +1,52 @@
-README ee32ce1c 15386
+README 664d441 15750
arithchk.c ebbe5bc7 4075
dmisc.c c8daa18 4682
-dtoa.c 14f5b9e1 17138
+dtoa.c f6ed7306 17542
g_Qfmt.c f6aad16c 2926
-g__fmt.c 1b8e8cd8 3401
-g_ddfmt.c eb4d0889 4090
-g_dfmt.c 10d694eb 2584
+g__fmt.c e961947e 3401
+g_ddfmt.c 1f75ef12 4161
+g_dfmt.c 24be3a8 2629
g_ffmt.c 197652f1 2516
g_xLfmt.c 3fd29c5 2773
g_xfmt.c f6a580a 2862
-gdtoa.c eabc1bc5 17024
-gdtoa.h f3c171cc 4945
+gdtoa.c e4651ba8 17355
+gdtoa.h f966845d 4944
gdtoa_fltrnds.h 1aaf5112 421
-gdtoaimp.h 490a372 19893
-gethex.c e7327648 7106
+gdtoaimp.h 395c83e 20044
+gethex.c 144ecbb4 7107
gmisc.c 1859d016 2084
hd_init.c efdbe921 1797
-hexnan.c 13f362b7 3462
-makefile 3cd7ae 2933
-misc.c 1757f7fc 14252
+hexnan.c 891b04e 3468
+makefile ffae86d0 3148
+misc.c 1d84f517 14416
+printf.c 15c97ab 158
+printf.c0 efece124 29696
qnan.c efd33d64 3417
-smisc.c 1064c213 3694
+smisc.c feb7290 3699
+stdio1.h e6e5dc11 2909
strtoIQ.c 1809dfcf 1939
strtoId.c f41ddac2 1931
strtoIdd.c f13e3bc3 2105
strtoIf.c f12c6af4 1875
-strtoIg.c fd8c1bcf 3589
+strtoIg.c fe47bc72 3591
strtoIx.c e50f716d 1960
strtoIxL.c ea0b821b 1931
-strtod.c e7e4addc 21731
-strtodI.c 1c2440ce 3915
-strtodg.c f74828cc 21164
+strtod.c 1dabf6 22744
+strtodI.c f1dbb0af 4004
+strtodg.c eacc7424 21188
strtodnrp.c af895e9 2538
-strtof.c 1db524d 2155
+strtof.c e1cb24dd 2161
strtopQ.c f244b012 2645
strtopd.c 1c3c9ce 1751
-strtopdd.c 125d6c19 4580
-strtopf.c 1939f590 2149
-strtopx.c f78a816e 2700
-strtopxL.c b77b701 2455
+strtopdd.c 177251c9 4640
+strtopf.c f305c6ea 2155
+strtopx.c 1529e1f5 2710
+strtopxL.c 69418e3 2469
strtorQ.c 9360a0b 2885
strtord.c af5c50e 2491
-strtordd.c 1b266865 4936
-strtorf.c f0d86e2b 2396
-strtorx.c f19a56af 2947
-strtorxL.c 167fe87c 2704
+strtordd.c e3d20ab 4992
+strtorf.c fbe2ea18 2402
+strtorx.c 168faee5 2957
+strtorxL.c 42c6cec 2718
sum.c f525bad9 2494
-ulp.c 1e2e148f 1864
+ulp.c edb56c0b 1866