Date: Wed, 14 Jul 1999 10:11:20 +0000 From: Matthew Seaman <m.seaman@inpharmatica.co.uk> To: Doug Rabson <dfr@nlsystems.com> Cc: John Polstra <jdp@polstra.com>, simokawa@sat.t.u-tokyo.ac.jp, alpha@FreeBSD.ORG Subject: Re: alpha/12623: strtod(3) FPE on alphaev56 Message-ID: <378C6248.31904C2@inpharmatica.co.uk> References: <Pine.BSF.4.10.9907140754120.58023-100000@salmon.nlsystems.com>
next in thread | previous in thread | raw e-mail | index | archive | help
This is a multi-part message in MIME format. --------------99239EED8BCDF62A6E75BB4D Content-Type: text/plain; charset=us-ascii Content-Transfer-Encoding: 7bit Doug Rabson wrote: > > On Tue, 13 Jul 1999, John Polstra wrote: > > > In article <14219.25613.478914.44162J@ett.sat.t.u-tokyo.ac.jp>, > > Hidetoshi Shimokawa <simokawa@sat.t.u-tokyo.ac.jp> wrote: > > > > > > /usr/src/lib/libc/stdlib/strtod.c seems broken on alpha in three ways. > > > > > > 1) IEEE_8087 should be defined instead of IEEE_MC68k. > > > > > > 2) It assumes long is 32bit, but long is 64bit on alpha. > > > s/unsigned long/u_int32_t/, s/long/int32_t/. > > > > > > 3) It generates denormal numbers which can not be treaded by the hardware > > > on alpha. It should be compiled with the option > > > `-mtrap-precision=i -mfp-trap-mode=su' to enable software completion. > > > > Yes, or the equivalent "-mieee". In my opinion, all of the libraries > > (if not the whole world) should be compiled that way. In fact, this > > option should be the default. Users who wanted a little extra speed > > and who knew what they are doing could turn it off. > > I agree (at least as far as the libraries go). Setting it as default would > be easy but there are performance implications. On the other hand, the > only applications whose performance is affected are ones using floating > point.. Great. Although /usr/src/lib/libc/stdlib/netbsd_strtod.c is temporarily being substituted for strtod.c on alpha --- applying the patches attached to this message should make strtod.c usable on both i386 and alpha. There are a bunch of other changes from the current {Net,Open}BSD sources that would probably be a good idea to merge in but I don't have time to do that right now. After installing egcs from ports I could compile a small test case using the -mieee flag and everything seems to be working fine: b0:/tmp:% cat foo.c #include <stdio.h> #include <stdlib.h> int main(int argc, char *argv[]) { char str[128] = "2.49521e-297"; double num; if (argc > 1) { strncpy(str, argv[1], 127); } num = strtod(str, NULL); printf("%s -> %.20lg\n", str, num); exit(0); } b0:/tmp:% egcc -g -c foo.c b0:/tmp:% egcc -g -c strtod.c b0:/tmp:% egcc foo.o strtod.o -o foo b0:/tmp:% ./foo Floating exception (core dumped) b0:/tmp:% egcc -mieee -g -c foo.c b0:/tmp:% egcc -mieee -g -c strtod.c b0:/tmp:% egcc -mieee foo.o strtod.o -o foo b0:/tmp:% ./foo 2.49521e-297 -> 2.4952099999999999545e-297 I guess it's time to make world using egcc -mieee and run some more extensive tests. Cheers, Matthew -- Certe, Toto, sentio nos in Kansate non iam adesse. Dr. Matthew Seaman, Inpharmatica Ltd, 60 Charlotte St, London, W1P 2AX Tel: +44 171 631 4644 x229 Fax: +44 171 631 4844 --------------99239EED8BCDF62A6E75BB4D Content-Type: text/plain; charset=us-ascii; name="Makefile.inc.diff" Content-Transfer-Encoding: 7bit Content-Disposition: inline; filename="Makefile.inc.diff" --- Makefile.inc.orig Wed Sep 16 04:16:06 1998 +++ Makefile.inc Wed Jul 14 09:44:56 1999 @@ -7,17 +7,8 @@ MISRCS+=abort.c abs.c atexit.c atof.c atoi.c atol.c bsearch.c calloc.c div.c \ exit.c getenv.c getopt.c getsubopt.c heapsort.c labs.c ldiv.c \ malloc.c merge.c putenv.c qsort.c radixsort.c rand.c random.c \ - reallocf.c realpath.c setenv.c strhash.c strtol.c strtoq.c strtoul.c \ - strtouq.c system.c - -.if ${MACHINE_ARCH} == "alpha" -# XXX Temporary until the assumption that a long is 32-bits is resolved -# XXX FreeBSD's code. NetBSD kludged this with Long = int32_t and -# XXX ULong = u_int32_t -SRCS+= netbsd_strtod.c -.else -SRCS+= strtod.c -.endif + reallocf.c realpath.c setenv.c strhash.c strtod.c strtol.c strtoq.c \ + strtoul.c strtouq.c system.c # machine-dependent stdlib sources .include "${.CURDIR}/../libc/${MACHINE_ARCH}/stdlib/Makefile.inc" --------------99239EED8BCDF62A6E75BB4D Content-Type: text/plain; charset=us-ascii; name="strtod.c.diff" Content-Transfer-Encoding: 7bit Content-Disposition: inline; filename="strtod.c.diff" --- strtod.c.orig Fri Jul 12 19:55:22 1996 +++ strtod.c Wed Jul 14 10:29:20 1999 @@ -94,9 +94,9 @@ */ /* - * #define IEEE_8087 for IEEE-arithmetic machines where the least + * #define IEEE_LITTLE_ENDIAN for IEEE-arithmetic machines where the least * significant byte has the lowest address. - * #define IEEE_MC68k for IEEE-arithmetic machines where the most + * #define IEEE_BIG_ENDIAN for IEEE-arithmetic machines where the most * significant byte has the lowest address. * #define Sudden_Underflow for IEEE-format machines without gradual * underflow (i.e., that flush to zero on underflow). @@ -112,19 +112,27 @@ * #define ROUND_BIASED for IEEE-format with biased rounding. * #define Inaccurate_Divide for IEEE-format with correctly rounded * products but inaccurate quotients, e.g., for Intel i860. - * #define Just_16 to store 16 bits per 32-bit long when doing high-precision - * integer arithmetic. Whether this speeds things up or slows things - * down depends on the machine and the number being converted. + * #define Just_16 to store 16 bits per 32-bit integer when doing + * high-precision integer arithmetic. Whether this speeds things up + * or slows things down depends on the machine and the number being + * converted. * #define KR_headers for old-style C function headers. * #define Bad_float_h if your system lacks a float.h or if it does not * define some or all of DBL_DIG, DBL_MAX_10_EXP, DBL_MAX_EXP, * FLT_RADIX, FLT_ROUNDS, and DBL_MAX. */ -#if defined(i386) || defined(mips) && defined(MIPSEL) -#define IEEE_8087 +#include <sys/cdefs.h> + +#if defined(__m68k__) || defined(__sparc__) || defined(__i386__) || \ + defined(__mips__) || defined(__ns32k__) || defined(__alpha__) || \ + defined(__powerpc__) +#include <sys/types.h> +#if BYTE_ORDER == BIG_ENDIAN +#define IEEE_BIG_ENDIAN #else -#define IEEE_MC68k +#define IEEE_LITTLE_ENDIAN +#endif #endif #ifdef DEBUG @@ -149,10 +157,10 @@ #include <ctype.h> #ifdef Bad_float_h #undef __STDC__ -#ifdef IEEE_MC68k +#ifdef IEEE_BIG_ENDIAN #define IEEE_ARITHMETIC #endif -#ifdef IEEE_8087 +#ifdef IEEE_LITTLE_ENDIAN #define IEEE_ARITHMETIC #endif #ifdef IEEE_ARITHMETIC @@ -210,23 +218,25 @@ #define Sign_Extend(a,b) /*no-op*/ #endif -#if defined(IEEE_8087) + defined(IEEE_MC68k) + defined(VAX) + defined(IBM) != 1 -Exactly one of IEEE_8087, IEEE_MC68k, VAX, or IBM should be defined. +#if defined(IEEE_LITTLE_ENDIAN) + defined(IEEE_BIG_ENDIAN) + defined(VAX) + \ + defined(IBM) != 1 +#error Exactly one of IEEE_LITTLE_ENDIAN, IEEE_BIG_ENDIAN, VAX, or IBM \ + should be defined. #endif -#ifdef IEEE_8087 -#define word0(x) ((unsigned long *)&x)[1] -#define word1(x) ((unsigned long *)&x)[0] +#ifdef IEEE_LITTLE_ENDIAN +#define word0(x) ((u_int32_t *)&x)[1] +#define word1(x) ((u_int32_t *)&x)[0] #else -#define word0(x) ((unsigned long *)&x)[0] -#define word1(x) ((unsigned long *)&x)[1] +#define word0(x) ((u_int32_t *)&x)[0] +#define word1(x) ((u_int32_t *)&x)[1] #endif /* The following definition of Storeinc is appropriate for MIPS processors. * An alternative that might be better on some machines is * #define Storeinc(a,b,c) (*a++ = b << 16 | c & 0xffff) */ -#if defined(IEEE_8087) + defined(VAX) +#if defined(IEEE_LITTLE_ENDIAN) + defined(VAX) #define Storeinc(a,b,c) (((unsigned short *)a)[1] = (unsigned short)b, \ ((unsigned short *)a)[0] = (unsigned short)c, a++) #else @@ -240,7 +250,7 @@ /* Quick_max = floor((P-1)*log(FLT_RADIX)/log(10) - 1) */ /* Int_max = floor(P*log(FLT_RADIX)/log(10) - 1) */ -#if defined(IEEE_8087) + defined(IEEE_MC68k) +#if defined(IEEE_LITTLE_ENDIAN) + defined(IEEE_BIG_ENDIAN) #define Exp_shift 20 #define Exp_shift1 20 #define Exp_msk1 0x100000 @@ -342,10 +352,10 @@ #define Big1 0xffffffff #ifndef Just_16 -/* When Pack_32 is not defined, we store 16 bits per 32-bit long. +/* When Pack_32 is not defined, we store 16 bits per 32-bit integer. * This makes some inner loops simpler and sometimes saves work * during multiplications, but it often seems to make things slightly - * slower. Hence the default is now to store 32 bits per long. + * slower. Hence the default is now to store 32 bits per integer. */ #ifndef Pack_32 #define Pack_32 @@ -364,7 +374,7 @@ Bigint { struct Bigint *next; int k, maxwds, sign, wds; - unsigned long x[1]; + u_int32_t x[1]; }; typedef struct Bigint Bigint; @@ -386,7 +396,7 @@ freelist[k] = rv->next; } else { x = 1 << k; - rv = (Bigint *)malloc(sizeof(Bigint) + (x-1)*sizeof(long)); + rv = (Bigint *)malloc(sizeof(Bigint) + (x-1)*sizeof(int32_t)); rv->k = k; rv->maxwds = x; } @@ -409,7 +419,7 @@ } #define Bcopy(x,y) memcpy((char *)&x->sign, (char *)&y->sign, \ -y->wds*sizeof(long) + 2*sizeof(int)) +y->wds*sizeof(int32_t) + 2*sizeof(int)) static Bigint * multadd @@ -420,9 +430,9 @@ #endif { int i, wds; - unsigned long *x, y; + u_int32_t *x, y; #ifdef Pack_32 - unsigned long xi, z; + u_int32_t xi, z; #endif Bigint *b1; @@ -458,14 +468,14 @@ static Bigint * s2b #ifdef KR_headers - (s, nd0, nd, y9) CONST char *s; int nd0, nd; unsigned long y9; + (s, nd0, nd, y9) CONST char *s; int nd0, nd; u_int32_t y9; #else - (CONST char *s, int nd0, int nd, unsigned long y9) + (CONST char *s, int nd0, int nd, u_int32_t y9) #endif { Bigint *b; int i, k; - long x, y; + int32_t x, y; x = (nd + 8) / 9; for (k = 0, y = 1; x > y; y <<= 1, k++) ; @@ -496,9 +506,9 @@ static int hi0bits #ifdef KR_headers - (x) register unsigned long x; + (x) register u_int32_t x; #else - (register unsigned long x) + (register u_int32_t x) #endif { register int k = 0; @@ -530,13 +540,13 @@ static int lo0bits #ifdef KR_headers - (y) unsigned long *y; + (y) u_int32_t *y; #else - (unsigned long *y) + (u_int32_t *y) #endif { register int k; - register unsigned long x = *y; + register u_int32_t x = *y; if (x & 7) { if (x & 1) @@ -601,10 +611,10 @@ { Bigint *c; int k, wa, wb, wc; - unsigned long carry, y, z; - unsigned long *x, *xa, *xae, *xb, *xbe, *xc, *xc0; + u_int32_t carry, y, z; + u_int32_t *x, *xa, *xae, *xb, *xbe, *xc, *xc0; #ifdef Pack_32 - unsigned long z2; + u_int32_t z2; #endif if (a->wds < b->wds) { @@ -727,7 +737,7 @@ { int i, k1, n, n1; Bigint *b1; - unsigned long *x, *x1, *xe, z; + u_int32_t *x, *x1, *xe, z; #ifdef Pack_32 n = k >> 5; @@ -784,7 +794,7 @@ (Bigint *a, Bigint *b) #endif { - unsigned long *xa, *xa0, *xb, *xb0; + u_int32_t *xa, *xa0, *xb, *xb0; int i, j; i = a->wds; @@ -820,10 +830,10 @@ { Bigint *c; int i, wa, wb; - long borrow, y; /* We need signed shifts here. */ - unsigned long *xa, *xae, *xb, *xbe, *xc; + int32_t borrow, y; /* We need signed shifts here. */ + u_int32_t *xa, *xae, *xb, *xbe, *xc; #ifdef Pack_32 - long z; + int32_t z; #endif i = cmp(a,b); @@ -897,7 +907,7 @@ (double x) #endif { - register long L; + register int32_t L; double a; L = (word0(x) & Exp_mask) - (P-1)*Exp_msk1; @@ -933,11 +943,11 @@ (Bigint *a, int *e) #endif { - unsigned long *xa, *xa0, w, y, z; + u_int32_t *xa, *xa0, w, y, z; int k; double d; #ifdef VAX - unsigned long d0, d1; + u_int32_t d0, d1; #else #define d0 word0(d) #define d1 word1(d) @@ -1004,9 +1014,9 @@ { Bigint *b; int de, i, k; - unsigned long *x, y, z; + u_int32_t *x, y, z; #ifdef VAX - unsigned long d0, d1; + u_int32_t d0, d1; d0 = word0(d) >> 16 | word0(d) << 16; d1 = word1(d) >> 16 | word1(d) << 16; #else @@ -1197,8 +1207,8 @@ e, e1, esign, i, j, k, nd, nd0, nf, nz, nz0, sign; CONST char *s, *s0, *s1; double aadj, aadj1, adj, rv, rv0; - long L; - unsigned long y, z; + int32_t L; + u_int32_t y, z; Bigint *bb, *bb1, *bd, *bd0, *bs, *delta; sign = nz0 = nz = 0; rv = 0.; @@ -1707,12 +1717,12 @@ #endif { int n; - long borrow, y; - unsigned long carry, q, ys; - unsigned long *bx, *bxe, *sx, *sxe; + int32_t borrow, y; + u_int32_t carry, q, ys; + u_int32_t *bx, *bxe, *sx, *sxe; #ifdef Pack_32 - long z; - unsigned long si, zs; + int32_t z; + u_int32_t si, zs; #endif n = S->wds; @@ -1882,10 +1892,10 @@ int bbits, b2, b5, be, dig, i, ieps, ilim, ilim0, ilim1, j, j1, k, k0, k_check, leftright, m2, m5, s2, s5, spec_case, try_quick; - long L; + int32_t L; #ifndef Sudden_Underflow int denorm; - unsigned long x; + u_int32_t x; #endif Bigint *b, *b1, *delta, *mlo, *mhi, *S; double d2, ds, eps; @@ -2057,8 +2067,8 @@ if (i <= 0) i = 1; } - j = sizeof(unsigned long); - for (result_k = 0; sizeof(Bigint) - sizeof(unsigned long) + j < i; + j = sizeof(u_int32_t); + for (result_k = 0; sizeof(Bigint) - sizeof(u_int32_t) + j < i; j <<= 1) result_k++; result = Balloc(result_k); s = s0 = (char *)result; --------------99239EED8BCDF62A6E75BB4D-- To Unsubscribe: send mail to majordomo@FreeBSD.org with "unsubscribe freebsd-alpha" in the body of the message
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?378C6248.31904C2>