Import gdtoa sources dated 2011-03-04. This version includes a number
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/.
This commit is contained in:
parent
9ea4d2a874
commit
21a2b1c905
Notes:
svn2git
2020-12-20 02:59:44 +00:00
svn path=/vendor/gdtoa/dist/; revision=219422 svn path=/vendor/gdtoa/20110304/; revision=219423; tag=vendor/gdtoa/20110304
7
README
7
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 ".").
|
||||
|
672
changes
Normal file
672
changes
Normal file
@ -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.
|
168
dtoa.c
168
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)
|
||||
|
2
g__fmt.c
2
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;
|
||||
}
|
||||
|
23
g_ddfmt.c
23
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);
|
||||
|
2
g_dfmt.c
2
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);
|
||||
}
|
||||
|
172
gdtoa.c
172
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')
|
||||
|
2
gdtoa.h
2
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;
|
||||
|
49
gdtoaimp.h
49
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
|
||||
}
|
||||
|
10
gethex.c
10
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;
|
||||
|
6
hexnan.c
6
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;
|
||||
|
41
makefile
41
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
|
||||
|
82
misc.c
82
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;
|
||||
|
8
printf.c
Normal file
8
printf.c
Normal file
@ -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"
|
20
smisc.c
20
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
|
||||
|
103
stdio1.h
Normal file
103
stdio1.h
Normal file
@ -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 */
|
@ -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);
|
||||
|
446
strtod.c
446
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);
|
||||
}
|
||||
|
||||
|
88
strtodI.c
88
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;
|
||||
}
|
||||
|
121
strtodg.c
121
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;
|
||||
}
|
||||
|
2
strtof.c
2
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:
|
||||
|
36
strtopdd.c
36
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:
|
||||
|
@ -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:
|
||||
|
@ -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:
|
||||
|
@ -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:
|
||||
|
34
strtordd.c
34
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:
|
||||
|
@ -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:
|
||||
|
@ -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:
|
||||
|
@ -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:
|
||||
|
23
test/Qtest.c
23
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");
|
||||
|
@ -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.
|
||||
|
@ -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;
|
||||
}
|
||||
|
112
test/dt.c
112
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;
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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... ");
|
||||
|
@ -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
|
||||
|
13
test/pfLqtestnos
Normal file
13
test/pfLqtestnos
Normal file
@ -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
|
158
test/pftest.c
Normal file
158
test/pftest.c
Normal file
@ -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;
|
||||
}
|
13
test/pftestLq.out
Normal file
13
test/pftestLq.out
Normal file
@ -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
|
15
test/pftestQ.out
Normal file
15
test/pftestQ.out
Normal file
@ -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
|
15
test/pftestnos
Normal file
15
test/pftestnos
Normal file
@ -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
|
15
test/pftestx.out
Normal file
15
test/pftestx.out
Normal file
@ -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
|
@ -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);
|
||||
}
|
||||
|
@ -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
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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
|
||||
|
@ -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;
|
||||
}
|
||||
|
20
ulp.c
20
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);
|
||||
}
|
||||
|
57
xsum0.out
57
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
|
||||
|
Loading…
Reference in New Issue
Block a user