Skip site navigation (1)Skip section navigation (2)
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>