mingw-w64/mingw-w64-crt/gdtoa/arithchk.c
Jameson Nash b190082731 gdtoa: Sync to match the latest version at netlib.org
As of Jan. 06 2023. Changelog from http://netlib.org/fp/changes (filtered):

20121220
  dtoa.c and gdtoa.tgz:  to avoid a possible one-time race when
Infinity or NaN appear in decimal->binary conversions done in parallel
threads, replace hexdig_init() with static initialization.

20131209
  dtoa.c, gdtoa.tgz: when strtod computes its starting approximation,
allow z to involve one more digit for IEEE arithmetic and two more
digits for IBM-mainframe and VAX arithmetics.  Thanks to Walter Qian
(water.qian@gmail.com) for suggesting this change, which makes some
conversions faster.

20151020
  dtoa.c:  add a test for dtoa() to return "1" under mode 4 when
converting some very small powers of 10, such as 1e-322 with
ndigits = 4 and 1e-319 with ndigits = 7 (examples provided by
jay.foad@gmail.com).

20160219
  gdtoa.tgz: Adjust gdtoa(...,mode,...) to assume
"round near" when mode is 0 or 1.  Make various tweaks to banish
(useless) warnings from "gcc -Wall -Wextra".  Thanks to Jarkko
Hietaniemi <jhi@iki.fi> for advocating the latter exercise (and
correcting a typo in README).

20160307
  dtoa.c:  fix glitches with floating-point values in hexadecimal
notation:  some values that should overflow to (appropriately signed)
Infinity, such as 0x1p1025, were mishandled, and values greater than
0x1p-1075 and less than 0x1.0000000000001p-1075 where treated as zero
rather than the smallest denormal number.
  gdtoa.tgz:  fix a bug with hexadecimal input greater than the
smallest denormal and less than the smallest denormal times the
smallest number greater than one.  In round-to-nearest values, such
values should round to the smallest denormal rather than to zero.
Thanks to Albert Chan <albertmcchan@yahoo.com> for bug reports.

20160325
  dtoa.c:  fix a bug whereby dtoa(...,mode,...) with, e.g., mode = 2 or
3 could return a string with trailing zeros, contrary to specification.
An example provided by Albert Chan:  dtoa(81320560005., 2, 10,...).
  gdtoa.tgz: fix the analogous bug in gdtoa/dtoa.c and gdtoa/gdtoa.c
and apply the bug fix of 20151020 to gdtoa/dtoa.c.

20160429
  dtoa.c, gdtoa.tgz (file dtoa.c):  Fix a bug with dtoa mode 0 when
Honor_FLT_ROUNDS is defined:  with some inputs and nondefault rounding
modes (e.g., 1.23 with round toward zero), the returned string was off
by one.  When the new 64-bit integer logic is used, the test in
question is very unlikely to be used.  This is another bug reported by
Albert Chan.

20160505
  dtoa.c:  fix some glitches in strtod() when Honor_FLT_ROUNDS is
defined:  zero was returned for some decimal values that should have
been rounded to +- the smallest denormal, and +-Infinity was returned
for some hexadecimal strings with huge values that should have been
rounded to +- the largest finite value.

20160506
  gdtoa.tgz: analogous bug fixes to those of 20160505.

20180730
  strtodg.c in gdtoa.c:  fix a glitch, introduced 20160506, with some
return values of +-Infinity:  the STRTOG_Overflow bit was not set.
2023-06-12 23:51:11 +03:00

186 lines
4.0 KiB
C

/****************************************************************
Copyright (C) 1997, 1998 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.
****************************************************************/
/* Try to deduce arith.h from arithmetic properties. */
#ifdef MINGW_BUILD_GEN
#include <stdio.h>
static int dalign;
typedef struct
Akind {
char *name;
int kind;
} Akind;
static Akind
IEEE_8087 = { "IEEE_8087", 1 },
IEEE_MC68k = { "IEEE_MC68k", 2 },
IBM = { "IBM", 3 },
VAX = { "VAX", 4 },
CRAY = { "CRAY", 5};
static Akind *
Lcheck(void)
{
union {
double d;
long L[2];
} u;
struct {
double d;
long L;
} x[2];
if (sizeof(x) > 2*(sizeof(double) + sizeof(long)))
dalign = 1;
u.L[0] = u.L[1] = 0;
u.d = 1e13;
if (u.L[0] == 1117925532 && u.L[1] == -448790528)
return &IEEE_MC68k;
if (u.L[1] == 1117925532 && u.L[0] == -448790528)
return &IEEE_8087;
if (u.L[0] == -2065213935 && u.L[1] == 10752)
return &VAX;
if (u.L[0] == 1267827943 && u.L[1] == 704643072)
return &IBM;
return 0;
}
static Akind *
icheck(void)
{
union {
double d;
int L[2];
} u;
struct {
double d;
int L;
} x[2];
if (sizeof(x) > 2*(sizeof(double) + sizeof(int)))
dalign = 1;
u.L[0] = u.L[1] = 0;
u.d = 1e13;
if (u.L[0] == 1117925532 && u.L[1] == -448790528)
return &IEEE_MC68k;
if (u.L[1] == 1117925532 && u.L[0] == -448790528)
return &IEEE_8087;
if (u.L[0] == -2065213935 && u.L[1] == 10752)
return &VAX;
if (u.L[0] == 1267827943 && u.L[1] == 704643072)
return &IBM;
return 0;
}
static Akind *
ccheck(int ac, char **av)
{
union {
double d;
long L;
} u;
long Cray1;
/* Cray1 = 4617762693716115456 -- without overflow on non-Crays */
/* The next three tests should always be true. */
Cray1 = ac >= -2 ? 4617762 : 0;
if (ac >= -1)
Cray1 = 1000000*Cray1 + 693716;
if (av || ac >= 0)
Cray1 = 1000000*Cray1 + 115456;
u.d = 1e13;
if (u.L == Cray1)
return &CRAY;
return 0;
}
static int
fzcheck(void)
{
double a, b;
int i;
a = 1.;
b = .1;
for(i = 155;; b *= b, i >>= 1) {
if (i & 1) {
a *= b;
if (i == 1)
break;
}
}
b = a * a;
return b == 0.;
}
int
main(int argc, char **argv)
{
Akind *a = 0;
int Ldef = 0;
FILE *f;
#ifdef WRITE_ARITH_H /* for Symantec's buggy "make" */
f = fopen("arith.h", "w");
if (!f) {
printf("Cannot open arith.h\n");
return 1;
}
#else
f = stdout;
#endif
if (sizeof(double) == 2*sizeof(long))
a = Lcheck();
else if (sizeof(double) == 2*sizeof(int)) {
Ldef = 1;
a = icheck();
}
else if (sizeof(double) == sizeof(long))
a = ccheck(argc, argv);
if (a) {
fprintf(f, "#define %s\n#define Arith_Kind_ASL %d\n",
a->name, a->kind);
if (Ldef)
fprintf(f, "#define Long int\n#define Intcast (int)(long)\n");
if (dalign)
fprintf(f, "#define Double_Align\n");
if (sizeof(char*) == 8)
fprintf(f, "#define X64_bit_pointers\n");
#ifndef NO_LONG_LONG
if (sizeof(long long) < 8)
#endif
fprintf(f, "#define NO_LONG_LONG\n");
if (a->kind <= 2 && fzcheck())
fprintf(f, "#define Sudden_Underflow\n");
return 0;
}
fprintf(f, "/* Unknown arithmetic */\n");
return 1;
}
#endif /* MINGW_BUILD_GEN */