delorie.com/archives/browse.cgi   search  
Mail Archives: djgpp-workers/2003/09/27/17:34:20

X-Authentication-Warning: delorie.com: mail set sender to djgpp-workers-bounces using -f
Date: Sat, 27 Sep 2003 22:43:37 +0100
From: "Richard Dawe" <rich AT phekda DOT freeserve DOT co DOT uk>
Sender: rich AT phekda DOT freeserve DOT co DOT uk
To: djgpp-workers AT delorie DOT com
X-Mailer: Emacs 21.3.50 (via feedmail 8.3.emacs20_6 I) and Blat ver 1.8.6
Subject: nan, nanf, nanl, revision 2 [PATCH]
Message-Id: <E1A3Mh6-0000oK-00@phekda.freeserve.co.uk>
Reply-To: djgpp-workers AT delorie DOT com

Hello.

Below is revision 2 of the patch to add the C99 functions
nan, nanf and nanl to DJGPP. Changes:

* Add some tests for nan*.

* Fix the compilation t-strtof. Some of the formats needed fixing.
  I used the new 't' width specifier for ptrdiff_t, since we're
  subtracting pointers. I also added a PASS/FAIL information line
  at the end, to make it more obvious when the test has failed.

* Make strto* support decimal numbers, when doing strto*("NAN(1234)", ...).
  Currently it interprets everything inside NAN() as hexidecimal.
  I think that is a bug, from reading the C99 specification.
  Perhaps we should make sure that the number is decimal or hexidecimal,
  before doing the conversion, to stop, for example, octal numbers
  being used.

Note that several of the nanl test cases fail for me at the moment,
due to the way that strto* are implemented. Here's what I see:

bash-2.04$ ./t-nan2.exe
Testcase 1: nan(): OK
Testcase 1: nanf(): OK
Testcase 1: nanl(): OK
Testcase 2: nan(): OK
Testcase 2: nanf(): OK
Testcase 2: nanl(): OK
Testcase 3: nan(): OK
Testcase 3: nanf(): OK
Testcase 3: nanl(): OK
Testcase 4: nan(): OK
Testcase 4: nanf(): OK
Testcase 4: nanl(): OK
Testcase 5: nan(): OK
Testcase 5: nanf(): OK
Testcase 5: nanl(): FAIL
Expected: (0x1, 0xc0000000, 0x7fff, 0x0)
Got: (0x0, 0xc0000000, 0x7fff, 0x0)
Testcase 6: nan(): OK
Testcase 6: nanf(): OK
Testcase 6: nanl(): FAIL
Expected: (0x4d2, 0xc0000000, 0x7fff, 0x0)
Got: (0x0, 0xc0000000, 0x7fff, 0x0)
Testcase 7: nan(): OK
Testcase 7: nanf(): OK
Testcase 7: nanl(): FAIL
Expected: (0x1, 0xc0000000, 0x7fff, 0x0)
Got: (0x0, 0xc0000000, 0x7fff, 0x0)
Testcase 8: nan(): OK
Testcase 8: nanf(): OK
Testcase 8: nanl(): FAIL
Expected: (0x1234, 0xc0000000, 0x7fff, 0x0)
Got: (0x0, 0xc0000000, 0x7fff, 0x0)
Testcase 9: nan(): OK
Testcase 9: nanf(): OK
Testcase 9: nanl(): OK
Testcase 10: nan(): OK
Testcase 10: nanf(): OK
Testcase 10: nanl(): OK
FAIL

I don't think we need to worry about that. They're not bugs in nanl.

OK to commit?

Bye, Rich =]

Index: include/math.h
===================================================================
RCS file: /cvs/djgpp/djgpp/include/math.h,v
retrieving revision 1.9
diff -p -u -3 -r1.9 math.h
--- include/math.h	3 Sep 2003 17:05:22 -0000	1.9
+++ include/math.h	27 Sep 2003 21:27:37 -0000
@@ -75,9 +75,12 @@ extern float       __dj_nan;
 #define isnan(x)	(fpclassify(x)==FP_NAN)
 #define isnormal(x)	(fpclassify(x)==FP_NORMAL)
 
-int __fpclassifyf(float) __attribute__((const));
-int __fpclassifyd(double) __attribute__((const));
-int __fpclassifyld(long double) __attribute__((const));
+int		__fpclassifyf(float) __attribute__((const));
+int		__fpclassifyd(double) __attribute__((const));
+int		__fpclassifyld(long double) __attribute__((const));
+double		nan(const char *);
+float		nanf(const char *);
+long double	nanl(const char *);
 
 #endif /* (__STDC_VERSION__ >= 199901L) || !__STRICT_ANSI__ */
   
@@ -139,7 +142,6 @@ extern double j0(double);
 extern double j1(double);
 extern double jn(int, double);
 extern double lgamma(double);
-extern double nan(void);
 extern double y0(double);
 extern double y1(double);
 extern double yn(int, double);
@@ -191,7 +193,6 @@ extern float j0f(float);
 extern float j1f(float);
 extern float jnf(int, float);
 extern float lgammaf(float);
-extern float nanf(void);
 extern float y0f(float);
 extern float y1f(float);
 extern float ynf(int, float);
Index: src/libc/ansi/stdlib/strtod.c
===================================================================
RCS file: /cvs/djgpp/djgpp/src/libc/ansi/stdlib/strtod.c,v
retrieving revision 1.8
diff -p -u -3 -r1.8 strtod.c
--- src/libc/ansi/stdlib/strtod.c	29 Jun 2003 14:20:52 -0000	1.8
+++ src/libc/ansi/stdlib/strtod.c	27 Sep 2003 21:27:37 -0000
@@ -87,7 +87,7 @@ strtod(const char *s, char **sret)
       unsigned long long mantissa_bits = 0;
       char *endptr = unconst((&s[4]), char *);
 
-      mantissa_bits = strtoull(&s[4], &endptr, 16);
+      mantissa_bits = strtoull(&s[4], &endptr, 0);
       if ( *endptr == ')' )
       {
 	mantissa_bits = mantissa_bits & 0xfffffffffffffULL;
@@ -103,7 +103,7 @@ strtod(const char *s, char **sret)
 	return (t.d);
       }
 
-      /* The subject sequence didn't match NAN(<hex-number>), so match
+      /* The subject sequence didn't match NAN(<number>), so match
 	 only NAN. */
     }
 
Index: src/libc/ansi/stdlib/strtod.txh
===================================================================
RCS file: /cvs/djgpp/djgpp/src/libc/ansi/stdlib/strtod.txh,v
retrieving revision 1.4
diff -p -u -3 -r1.4 strtod.txh
--- src/libc/ansi/stdlib/strtod.txh	10 May 2003 17:16:29 -0000	1.4
+++ src/libc/ansi/stdlib/strtod.txh	27 Sep 2003 21:27:43 -0000
@@ -12,8 +12,9 @@ double strtod(const char *s, char **endp
 
 This function converts as many characters of @var{s} as look like a
 floating point number into that number.  It also recognises
-(case-insensitively) ``Inf'', ``Infinity'', ``NaN'' and
-``NaN(@var{optional hex-number})''.  If @var{endp} is not a null
+(case-insensitively) ``Inf'', ``Infinity'', ``NaN'',
+``NaN(@var{optional decimal-number})
+and ``NaN(@var{optional hex-number})''.  If @var{endp} is not a null
 pointer, a pointer to the first unconverted character will be stored
 in the location pointed to by @var{endp}.
 
@@ -31,10 +32,12 @@ and optionally prefixed with ``+'' or ``
 @code{(double)NAN}.  If the prefix is ``-'' the sign bit in the NaN
 will be set to 1.
 
-If @var{s} is ``NaN(@var{hex-number})'', with any variations of
+If @var{s} is ``NaN(@var{decimal-number})''
+or ``NaN(@var{hex-number})'', with any variations of
 case and optionally prefixed with ``+'' or ``-'', the return value is
-a NaN with the mantissa bits set to the lower 52 bits of
-@var{hex-number} (the mantissa for doubles consists of 52 bits).  Use
+a NaN with the mantissa bits set to the lower 52 bits
+of @var{decimal-number} or @var{hex-number}
+(the mantissa for doubles consists of 52 bits).  Use
 at most 16 hexadecimal digits in @var{hex-number} or the internal
 conversion will overflow, which results in a mantissa with all bits
 set.  If the bit pattern given is 0 (which won't work as a
@@ -58,8 +61,16 @@ representable by the type @code{double},
 @subheading Example
 
 @example
-char *buf = "123ret";
+char buf[] = "123ret";
+char buf2[] = "0x123ret";
+char buf3[] = "NAN(123)";
+char buf4[] = "NAN(0x123)";
 char *bp;
-double x = strtod(buf, &bp);
+double x, x2, x3, x4;
+
+x = strtod(buf, &bp);
+x2 = strtod(buf2, &bp);
+x3 = strtod(buf3, &bp);
+x4 = strtod(buf4, &bp);
 @end example
 
Index: src/libc/ansi/stdlib/strtold.c
===================================================================
RCS file: /cvs/djgpp/djgpp/src/libc/ansi/stdlib/strtold.c,v
retrieving revision 1.8
diff -p -u -3 -r1.8 strtold.c
--- src/libc/ansi/stdlib/strtold.c	30 Jun 2003 20:38:15 -0000	1.8
+++ src/libc/ansi/stdlib/strtold.c	27 Sep 2003 21:27:43 -0000
@@ -85,7 +85,7 @@ strtold(const char *s, char **sret)
       unsigned long long mantissa_bits = 0;
       char *endptr = unconst((&s[4]), char *);
       
-      mantissa_bits = strtoull(&s[4], &endptr, 16);
+      mantissa_bits = strtoull(&s[4], &endptr, 0);
       if ( *endptr == ')' )
       {
 	mantissa_bits = mantissa_bits & 0x7fffffffffffffffULL; /* Ignore
@@ -103,7 +103,7 @@ strtold(const char *s, char **sret)
         return (t.ld);
       }
       
-      /* The subject sequence didn't match NAN(<hex-number>), so match
+      /* The subject sequence didn't match NAN(<number>), so match
 	 only NAN. */
     }
 
Index: src/libc/ansi/stdlib/strtold.txh
===================================================================
RCS file: /cvs/djgpp/djgpp/src/libc/ansi/stdlib/strtold.txh,v
retrieving revision 1.5
diff -p -u -3 -r1.5 strtold.txh
--- src/libc/ansi/stdlib/strtold.txh	10 May 2003 17:16:29 -0000	1.5
+++ src/libc/ansi/stdlib/strtold.txh	27 Sep 2003 21:27:49 -0000
@@ -12,8 +12,9 @@ long double _strtold(const char *s, char
 
 This function converts as many characters of @var{s} that look like a
 floating point number into that number.  It also recognises
-(case-insensitively) ``Inf'', ``Infinity'', ``NaN'' and
-``NaN(@var{optional hex-number})''.  If @var{endp} is not a null
+(case-insensitively) ``Inf'', ``Infinity'', ``NaN'',
+``NaN(@var{optional decimal-number})
+and ``NaN(@var{optional hex-number})''.  If @var{endp} is not a null
 pointer, a pointer to the first unconverted character will be stored
 in the location pointed to by @var{endp}.  
 
@@ -34,9 +35,11 @@ optionally prefixed with ``+'' or ``-'',
 @code{(long double)NAN}.  If the prefix is ``-'' the sign bit in the
 NaN will be set to 1.  
 
-If @var{s} is ``NaN(@var{hex-number})'', with any variations of case
+If @var{s} is ``NaN(@var{decimal-number})''
+or ``NaN(@var{hex-number})'', with any variations of case
 and optionally prefixed with ``+'' or ``-'', the return value is a NaN
-with the mantissa bits set to the lower 63 bits of @var{hex-number}
+with the mantissa bits set to the lower 63 bits
+of @var{decimal-number} or @var{hex-number}
 and the most significant bit to 1 (the mantissa for long 
 doubles consists of 64 bits where the most significant bit is the
 integer bit which must be set for NaNs).  Use at most 16 hexadecimal
@@ -55,9 +58,17 @@ mantissa).  
 @subheading Example
 
 @example
-char *buf = "123ret";
+char buf[] = "123ret";
+char buf2[] = "0x123ret";
+char buf3[] = "NAN(123)";
+char buf4[] = "NAN(0x123)";
 char *bp;
-long double x = _strtold(buf, &bp);
+long double x, x2, x3, x4;
+
+x = _strtold(buf, &bp);
+x2 = _strtold(buf2, &bp);
+x3 = _strtold(buf3, &bp);
+x4 = _strtold(buf4, &bp);
 @end example
 
 @node strtold, string
@@ -74,8 +85,9 @@ long double strtold(const char *s, char 
 
 This function converts as many characters of @var{s} that look like a
 floating point number into that number.  It also recognises
-(case-insensitively) ``Inf'', ``Infinity'', ``NaN'' and
-``NaN(@var{optional hex-number})''.  If @var{endp} is not a null
+(case-insensitively) ``Inf'', ``Infinity'', ``NaN'',
+``NaN(@var{optional decimal-number})
+and ``NaN(@var{optional hex-number})''.  If @var{endp} is not a null
 pointer, a pointer to the first unconverted character will be stored
 in the location pointed to by @var{endp}.  
 
@@ -93,9 +105,11 @@ optionally prefixed with ``+'' or ``-'',
 @code{(long double)NAN}.  If the prefix is ``-'' the sign bit in the
 NaN will be set to 1.  
 
-If @var{s} is ``NaN(@var{hex-number})'', with any variations of case
+If @var{s} is ``NaN(@var{decimal-number})''
+or ``NaN(@var{hex-number})'', with any variations of case
 and optionally prefixed with ``+'' or ``-'', the return value is a NaN
-with the mantissa bits set to the lower 63 bits of @var{hex-number}
+with the mantissa bits set to the lower 63 bits
+of @var{decimal-number} or @var{hex-number}
 and the most significant bit to 1 (the mantissa for long 
 doubles consists of 64 bits where the most significant bit is the
 integer bit which must be set for NaNs).  Use at most 16 hexadecimal
@@ -117,7 +131,15 @@ mantissa).  
 @subheading Example
 
 @example
-char *buf = "123ret";
+char buf[] = "123ret";
+char buf2[] = "0x123ret";
+char buf3[] = "NAN(123)";
+char buf4[] = "NAN(0x123)";
 char *bp;
-long double x = strtold(buf, &bp);
+long double x, x2, x3, x4;
+
+x = strtold(buf, &bp);
+x2 = strtold(buf2, &bp);
+x3 = strtold(buf3, &bp);
+x4 = strtold(buf4, &bp);
 @end example
Index: src/libc/c99/stdlib/strtof.c
===================================================================
RCS file: /cvs/djgpp/djgpp/src/libc/c99/stdlib/strtof.c,v
retrieving revision 1.4
diff -p -u -3 -r1.4 strtof.c
--- src/libc/c99/stdlib/strtof.c	29 Jun 2003 14:29:15 -0000	1.4
+++ src/libc/c99/stdlib/strtof.c	27 Sep 2003 21:27:49 -0000
@@ -92,7 +92,7 @@ strtof(const char *s, char **sret)
       unsigned long mantissa_bits = 0;
       char *endptr = unconst((&s[4]), char *);
 
-      mantissa_bits = strtoul(&s[4], &endptr, 16);
+      mantissa_bits = strtoul(&s[4], &endptr, 0);
       if( *endptr == ')' )
       {
 	mantissa_bits = mantissa_bits & 0x7fffff;
@@ -107,7 +107,7 @@ strtof(const char *s, char **sret)
 	return (t.f);
       }
 
-      /* The subject sequence didn't match NAN(<hex-number>), so match
+      /* The subject sequence didn't match NAN(<number>), so match
 	 only NAN. */
     }
 
Index: src/libc/c99/stdlib/strtof.txh
===================================================================
RCS file: /cvs/djgpp/djgpp/src/libc/c99/stdlib/strtof.txh,v
retrieving revision 1.5
diff -p -u -3 -r1.5 strtof.txh
--- src/libc/c99/stdlib/strtof.txh	10 May 2003 17:16:29 -0000	1.5
+++ src/libc/c99/stdlib/strtof.txh	27 Sep 2003 21:27:54 -0000
@@ -12,8 +12,9 @@ float strtof(const char *s, char **endp)
 
 This function converts as many characters of @var{s} as look like a
 floating point number into that number.  It also recognises
-(case-insensitively) ``Inf'', ``Infinity'', ``NaN'' and
-``NaN(@var{optional hex-number})''.  If @var{endp} is not a null
+(case-insensitively) ``Inf'', ``Infinity'', ``NaN'',
+``NaN(@var{optional decimal-number})
+and ``NaN(@var{optional hex-number})''.  If @var{endp} is not a null
 pointer, a pointer to the first unconverted character will be stored
 in the location pointed to by @var{endp}.
 
@@ -31,9 +32,11 @@ optionally prefixed with ``+'' or ``-'',
 @code{NAN}.  If the prefix is ``-'' the sign bit in the NaN will be
 set to 1.
 
-If @var{s} is ``NaN(@var{hex-number})'', with any variations of case
+If @var{s} is ``NaN(@var{decimal-number})''
+or ``NaN(@var{hex-number})'', with any variations of case
 and optionally prefixed with ``+'' or ``-'', the return value is a NaN
-with the mantissa bits set to the lower 23 bits of @var{hex-number}
+with the mantissa bits set to the lower 23 bits
+of @var{decimal-number} or @var{hex-number}
 (the mantissa for floats consists of 23 bits).  Use at most 8
 hexadecimal digits in @var{hex-number} or the internal conversion will
 overflow, which results in a mantissa with all bits set.  If the bit
@@ -57,7 +60,15 @@ representable by the type @code{float}, 
 @subheading Example
 
 @example
-char *buf = "123ret";
+char buf[] = "123ret";
+char buf2[] = "0x123ret";
+char buf3[] = "NAN(123)";
+char buf4[] = "NAN(0x123)";
 char *bp;
-float x = strtof(buf, &bp);
+float x, x2, x3, x4;
+
+x = strtof(buf, &bp);
+x2 = strtof(buf2, &bp);
+x3 = strtof(buf3, &bp);
+x4 = strtof(buf4, &bp);
 @end example
Index: src/libc/c99/math/makefile
===================================================================
RCS file: /cvs/djgpp/djgpp/src/libc/c99/math/makefile,v
retrieving revision 1.3
diff -p -u -3 -r1.3 makefile
--- src/libc/c99/math/makefile	3 Sep 2003 17:05:23 -0000	1.3
+++ src/libc/c99/math/makefile	27 Sep 2003 21:27:54 -0000
@@ -1,9 +1,13 @@
+# Copyright (C) 2003 DJ Delorie, see COPYING.DJ for details
 # Copyright (C) 2002 DJ Delorie, see COPYING.DJ for details
 TOP=../..
 
 SRC += hugevalf.c
 SRC += hugevall.c
+SRC += nan_def.c
 SRC += nan.c
+SRC += nanf.c
+SRC += nanl.c
 SRC += fpclassf.S
 SRC += fpclassd.S
 SRC += fpclassl.S
Index: src/libc/c99/math/nan.c
===================================================================
RCS file: /cvs/djgpp/djgpp/src/libc/c99/math/nan.c,v
retrieving revision 1.1
diff -p -u -3 -r1.1 nan.c
--- src/libc/c99/math/nan.c	22 Mar 2003 11:59:57 -0000	1.1
+++ src/libc/c99/math/nan.c	27 Sep 2003 21:27:56 -0000
@@ -1,4 +1,26 @@
 /* Copyright (C) 2003 DJ Delorie, see COPYING.DJ for details */
-#include <libc/ieee.h>
+#include <math.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
 
-float_t __dj_nan = { 0x7fffff, 0xff, 0x0 };
+double
+nan(const char *tagp)
+{
+  double ret = NAN;
+  char buf[256];
+  ssize_t s;
+
+  if (tagp)
+  {
+    /*
+     * If we can't fit NAN(<tagp>) in the buffer, just return NAN.
+     * It seems better to return a plain NAN than some possibly bogus NAN.
+     */
+    s = snprintf(buf, sizeof(buf), "NAN(%s)", tagp);
+    if (s < (ssize_t) sizeof(buf))
+      ret = strtod(buf, NULL);
+  }
+
+  return ret;
+}
Index: tests/libc/c99/stdlib/t-strtof.c
===================================================================
RCS file: /cvs/djgpp/djgpp/tests/libc/c99/stdlib/t-strtof.c,v
retrieving revision 1.3
diff -p -u -3 -r1.3 t-strtof.c
--- tests/libc/c99/stdlib/t-strtof.c	10 May 2003 17:16:29 -0000	1.3
+++ tests/libc/c99/stdlib/t-strtof.c	27 Sep 2003 21:27:57 -0000
@@ -94,10 +94,15 @@ static const test5_t tests5[] = {
   { "-Nan()",                      6,  1, 0 },
   { "nAN(0)",                      6,  0, 0 },
   { "-nan(0)",                     7,  1, 0 },
+  { "-nan(0x0)",                   9,  1, 0 },
+  { "nan(4198964)",               12,  0, 0x401234 }, /* QNaN */
   { "nan(0x401234)",              13,  0, 0x401234 }, /* QNaN */
   { "-nan(0x400088)",             14,  1, 0x400088 }, /* QNaN */
+  { "nan(1234)",                   9,  0, 1234 }, /* SNaN -> QNaN? */
   { "nan(0x1234)",                11,  0, 0x1234 }, /* SNaN -> QNaN? */
+  { "-nan(88)",                    8,  1, 88 }, /* SNaN -> QNaN? */
   { "-nan(0x88)",                 10,  1, 0x88 }, /* SNaN -> QNaN? */
+  { "-nan(12345678901234567890)", 26,  1, 0x7fffff }, /* Overflow. */
   { "-nan(0xaa7d7aa74)",          17,  1, 0x7fffff }, /* Overflow. */
   { "nan(0x12345678123456781)",   24,  0, 0x7fffff }, /* Overflow. */
   { "-nan(0x12345678123456781)",  25,  1, 0x7fffff }, /* Overflow. */
@@ -126,6 +131,7 @@ main (int argc, char *argv[])
   float f_res;
   int eq;
   size_t i;
+  int ok = 1;
 
   if ( 1 < argc ) {
     /* Fault on FPU exception. */
@@ -162,15 +168,19 @@ main (int argc, char *argv[])
     eq = (f_res == (HUGE_VALF * ((tests3[i].sign < 0) ? -1 : 1)));
 
     if (tests3[i].overflow) {
-      if (eq)
-	puts("Yes - OK");
-      else
+      if (eq) {
+	  puts("Yes - OK");
+      } else {
 	puts("No - FAIL");
+	ok = 0;
+      }
     } else {
-      if (eq)
+      if (eq) {
 	puts("Yes - FAIL");
-      else
+	ok = 0;
+      } else {
 	puts("No - OK");
+      }
     }
   }
   
@@ -181,21 +191,25 @@ main (int argc, char *argv[])
 
     f_res = strtof(tests4[i].str, &endptr);
       
-    printf("strtof(\"%s\", &endptr) -> %f, %ld - ", tests4[i].str,
+    printf("strtof(\"%s\", &endptr) -> %f, %td - ", tests4[i].str,
 	   f_res, endptr-tests4[i].str);
 
     /* Need to do the Inf detection ourselves. */
     float_bits = *(float_t *)(&f_res);
     if (float_bits.exponent != 0xff) {
       puts("exponent != 0xff - FAIL");
+      ok = 0;
     } else if (float_bits.mantissa != 0) {
       puts("mantissa != 0 - FAIL");
+      ok = 0;
     } else if ( (float_bits.sign && 0 < f_res ) || 
 		(!float_bits.sign && f_res < 0) ) {
       puts("Wrong sign - FAIL");
+      ok = 0;
     } else if ( endptr-tests4[i].str != tests4[i].diff) {
-      printf("endptr-(start_of_string) == %ld != %d - FAIL\n",
+      printf("endptr-(start_of_string) == %td != %td - FAIL\n",
 	     endptr-tests4[i].str, tests4[i].diff);
+      ok = 0;
     } else {
       puts("OK");
     }
@@ -208,21 +222,25 @@ main (int argc, char *argv[])
 
     f_res = strtof(tests5[i].str, &endptr);
 
-    printf("strtof(\"%s\", &endptr) -> %f, %ld - ", tests5[i].str,
+    printf("strtof(\"%s\", &endptr) -> %f, %td - ", tests5[i].str,
 	   f_res, endptr-tests5[i].str);
 
     /* Need to to the NaN detection ourselves. */
     float_bits = *(float_t *)(&f_res);
     if (float_bits.exponent != 0xff ) {
       puts("exponent != 0xff - FAIL");
+      ok = 0;
     } else if (float_bits.mantissa == 0) {
       puts("mantissa == 0 - FAIL");
+      ok = 0;
     } else if (tests5[i].sign != float_bits.sign) {
       printf("sign == %d != %d - FAIL\n", float_bits.sign,
 	     tests5[i].sign);
+      ok = 0;
     } else if ( endptr-tests5[i].str != tests5[i].diff) {
-      printf("endptr-(start_of_string) == %ld != %d - FAIL\n",
+      printf("endptr-(start_of_string) == %td != %td - FAIL\n",
 	     endptr-tests5[i].str, tests5[i].diff);
+      ok = 0;
     } else if (tests5[i].mantissa && 
 	       tests5[i].mantissa != float_bits.mantissa) { 
       printf("(note: mantissa == 0x%x != 0x%x) - OK\n",
@@ -231,6 +249,7 @@ main (int argc, char *argv[])
       puts("OK");
     }
   }
-  
-  return(EXIT_SUCCESS);
+
+  puts(ok ? "PASS" : "FAIL");
+  return(ok ? EXIT_SUCCESS : EXIT_FAILURE);
 }
Index: tests/libc/c99/math/makefile
===================================================================
RCS file: /cvs/djgpp/djgpp/tests/libc/c99/math/makefile,v
retrieving revision 1.2
diff -p -u -3 -r1.2 makefile
--- tests/libc/c99/math/makefile	3 Sep 2003 17:05:23 -0000	1.2
+++ tests/libc/c99/math/makefile	27 Sep 2003 21:28:02 -0000
@@ -1,6 +1,7 @@
 TOP=../..
 
-SRC += t-nan.c
 SRC += t-fpclas.c
+SRC += t-nan.c
+SRC += t-nan2.c
 
 include $(TOP)/../makefile.inc
Index: src/docs/kb/wc204.txi
===================================================================
RCS file: /cvs/djgpp/djgpp/src/docs/kb/wc204.txi,v
retrieving revision 1.160
diff -p -u -3 -r1.160 wc204.txi
--- src/docs/kb/wc204.txi	3 Sep 2003 17:05:22 -0000	1.160
+++ src/docs/kb/wc204.txi	27 Sep 2003 21:28:07 -0000
@@ -1008,3 +1008,8 @@ into itself, when the current directory 
 The C99 macro @code{fpclassify} and the supporting functions
 @code{__fpclassifyf}, @code{__fpclassifyd} and @code{__fpclassifyld}
 were added.
+
+@findex nan AT r{ added}
+@findex nanf AT r{ added}
+@findex nanl AT r{ added}
+The C99 functions @code{nan}, @code{nanf} and @code{nanl} were added.
--- /dev/null	2003-09-27 22:38:14.000000000 +0000
+++ src/libc/c99/math/nan_def.c	2003-09-07 21:26:28.000000000 +0000
@@ -0,0 +1,4 @@
+/* Copyright (C) 2003 DJ Delorie, see COPYING.DJ for details */
+#include <libc/ieee.h>
+
+float_t __dj_nan = { 0x7fffff, 0xff, 0x0 };
--- /dev/null	2003-09-27 22:38:14.000000000 +0000
+++ src/libc/c99/math/nan.txh	2003-09-07 21:34:48.000000000 +0000
@@ -0,0 +1,30 @@
+@node nan, math
+@findex nan
+@subheading Syntax
+
+@example
+#include <math.h>
+
+double nan(const char *tagp);
+@end example
+
+@subheading Description
+
+@code{nan} returns a quiet NaN with contents indicated by @var{tagp}.
+
+@subheading Return Value
+
+The quiet NaN.
+
+If quiet NaNs are not supported, zero is returned. DJGPP supports
+quiet NaNs.
+
+@subheading Portability
+
+@portability !ansi-c89, ansi-c99
+
+@subheading Example
+
+@example
+double d = nan("0x1234");
+@end example
--- /dev/null	2003-09-27 22:38:14.000000000 +0000
+++ src/libc/c99/math/nanf.c	2003-09-07 21:26:24.000000000 +0000
@@ -0,0 +1,26 @@
+/* Copyright (C) 2003 DJ Delorie, see COPYING.DJ for details */
+#include <math.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+float
+nanf(const char *tagp)
+{
+  float ret = NAN;
+  char buf[256];
+  int s;
+
+  if (tagp)
+  {
+    /*
+     * If we can't fit NAN(<tagp>) in the buffer, just return NAN.
+     * It seems better to return a plain NAN than some possibly bogus NAN.
+     */
+    s = snprintf(buf, sizeof(buf), "NAN(%s)", tagp);
+    if (s < (ssize_t) sizeof(buf))
+      ret = strtof(buf, NULL);
+  }
+
+  return ret;
+}
--- /dev/null	2003-09-27 22:38:14.000000000 +0000
+++ src/libc/c99/math/nanf.txh	2003-09-07 21:34:54.000000000 +0000
@@ -0,0 +1,30 @@
+@node nanf, math
+@findex nanf
+@subheading Syntax
+
+@example
+#include <math.h>
+
+float nanf(const char *tagp);
+@end example
+
+@subheading Description
+
+@code{nanf} returns a quiet NaN with contents indicated by @var{tagp}.
+
+@subheading Return Value
+
+The quiet NaN.
+
+If quiet NaNs are not supported, zero is returned. DJGPP supports
+quiet NaNs.
+
+@subheading Portability
+
+@portability !ansi-c89, ansi-c99
+
+@subheading Example
+
+@example
+float f = nanf("0x1234");
+@end example
--- /dev/null	2003-09-27 22:38:14.000000000 +0000
+++ src/libc/c99/math/nanl.c	2003-09-07 21:24:30.000000000 +0000
@@ -0,0 +1,26 @@
+/* Copyright (C) 2003 DJ Delorie, see COPYING.DJ for details */
+#include <math.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+long double
+nanl(const char *tagp)
+{
+  float ret = NAN;
+  char buf[256];
+  int s;
+
+  if (tagp)
+  {
+    /*
+     * If we can't fit NAN(<tagp>) in the buffer, just return NAN.
+     * It seems better to return a plain NAN than some possibly bogus NAN.
+     */
+    s = snprintf(buf, sizeof(buf), "NAN(%s)", tagp);
+    if (s < (ssize_t) sizeof(buf))
+      ret = strtold(buf, NULL);
+  }
+
+  return ret;
+}
--- /dev/null	2003-09-27 22:38:14.000000000 +0000
+++ src/libc/c99/math/nanl.txh	2003-09-07 21:35:10.000000000 +0000
@@ -0,0 +1,30 @@
+@node nanl, math
+@findex nanl
+@subheading Syntax
+
+@example
+#include <math.h>
+
+long double nanl(const char *tagp);
+@end example
+
+@subheading Description
+
+@code{nanl} returns a quiet NaN with contents indicated by @var{tagp}.
+
+@subheading Return Value
+
+The quiet NaN.
+
+If quiet NaNs are not supported, zero is returned. DJGPP supports
+quiet NaNs.
+
+@subheading Portability
+
+@portability !ansi-c89, ansi-c99
+
+@subheading Example
+
+@example
+long double ld = nanl("0x1234");
+@end example
--- /dev/null	2003-09-27 22:38:14.000000000 +0000
+++ tests/libc/c99/math/t-nan2.c	2003-09-27 22:06:26.000000000 +0000
@@ -0,0 +1,345 @@
+/* Copyright (C) 2003 DJ Delorie, see COPYING.DJ for details */
+
+/*
+ * t-nan2.c
+ * Tests for nan(), nanf(), nanl().
+ * Written by Richard Dawe <rich AT phekda DOT freeserve DOT co DOT uk>
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <math.h>
+#include <libc/ieee.h>
+
+typedef struct {
+  int valid;
+
+  const char *input;
+
+  int           ignore_mantissa;
+  double_t      dt_expected;
+  float_t       ft_expected;
+  long_double_t ldt_expected;
+} testcase_t;
+
+testcase_t testcases[] = {
+  /* Testcase 1: nan*(NULL) == strto*("NAN") */
+  /*
+   * TODO: This test is a little bogus, due to ignoring
+   * the rounding errors.
+   */
+  {
+    1,
+    NULL,
+    1, /* NB: Rounding errors mean we don't get the mantissas we want. */
+    { 0xffffffffU, 0xfffffU, 0x7ffU, 0 },
+    { 0x7fffffU, 0xffU, 0 },
+    { 0xffffffffU, 0xffffffffU, 0x7fffU, 0 }
+  },
+
+  /* Testcase 2: nan*("<not-a-number>") == strto*("NAN") */
+  /*
+   * TODO: This test is a little bogus, due to ignoring
+   * the rounding errors.
+   */
+  {
+    1,
+    "thisisn'tanumber",
+    1, /* NB: Rounding errors mean we don't get the mantissas we want. */
+    { 0xffffffffU, 0xfffffU, 0x7ffU, 0 },
+    { 0x7fffffU, 0xffU, 0 },
+    { 0xffffffffU, 0xffffffffU, 0x7fffU, 0 }
+  },
+
+  /* Testcase 3: nan*("") == strto*("NAN()") */
+  /*
+   * TODO: This test is a little bogus, due to ignoring
+   * the rounding errors.
+   */
+  {
+    1,
+    "",
+    1, /* NB: Rounding errors mean we don't get the mantissas we want. */
+    { 0xffffffffU, 0xfffffU, 0x7ffU, 0 },
+    { 0x7fffffU, 0xffU, 0 },
+    { 0xffffffffU, 0xffffffffU, 0x7fffU, 0 }
+  },
+
+  /* Testcase 4 */
+  /*
+   * TODO: This test is a little bogus, due to ignoring
+   * the rounding errors.
+   */
+  {
+    1,
+    "0",
+    1, /* NB: Rounding errors mean we don't get the mantissas we want. */
+    { 0, 0x80000U, 0x7ffU, 0 },
+    { 0x400000, 0xffU, 0 },
+    { 0, 0xc0000000U, 0x7fffU, 0 },
+  },
+
+  /*
+   * Testcase 5:
+   * nan*("<decimal-number>") == strto*("NAN(<decimal-number>)")
+   */
+  {
+    1,
+    "1",
+    0,
+    { 0x1U, 0x80000U, 0x7ffU, 0 },
+    { 0x400001, 0xffU, 0 },
+    { 1, 0xc0000000, 0x7fffU, 0 }
+  },
+
+  /*
+   * Testcase 6:
+   * nan*("<decimal-number>") == strto*("NAN(<decimal-number>)")
+   */
+  {
+    1,
+    "1234",
+    0,
+    { 0x4d2, 0x80000U, 0x7ffU, 0 },
+    { 0x4004d2, 0xffU, 0 },
+    { 0x4d2, 0xc0000000, 0x7fffU, 0 }
+  },
+
+  /*
+   * Testcase 7:
+   * nan*("<hexidecimal-number>") == strto*("NAN(<hexidecimal-number>)")
+   */
+  {
+    1,
+    "0x1",
+    0,
+    { 0x1U, 0x80000U, 0x7ffU, 0 },
+    { 0x400001, 0xffU, 0 },
+    { 1, 0xc0000000, 0x7fffU, 0 }
+  },
+
+  /*
+   * Testcase 8:
+   * nan*("<decimal-number>") == strto*("NAN(<decimal-number>)")
+   */
+  {
+    1,
+    "0x1234",
+    0,
+    { 0x1234, 0x80000U, 0x7ffU, 0 },
+    { 0x401234, 0xffU, 0 },
+    { 0x1234, 0xc0000000, 0x7fffU, 0 }
+  },
+
+  /*
+   * Testcase 9:
+   *    nan*("<overflowing-decimal-number>")
+   * == strto*("NAN(<overflowing-decimal-number>")
+   */
+  /*
+   * TODO: This test is a little bogus, due to ignoring
+   * the rounding errors.
+   */
+  {
+    1,
+    "12345678901234567890",
+    1, /* NB: Rounding errors mean we don't get the mantissas we want. */
+    { 0xffffffffU, 0xfffffU, 0x7ffU, 0 },
+    { 0x7fffffU, 0xffU, 0 },
+    { 0xffffffffU, 0xffffffffU, 0x7fffU, 0 }
+  },
+
+  /*
+   * Testcase 10:
+   *    nan*("<overflowing-hexidecimal-number>")
+   * == strto*("NAN(<overflowing-hexidecimal-number>")
+   */
+  /*
+   * TODO: This test is a little bogus, due to ignoring
+   * the rounding errors.
+   */
+  {
+    1,
+    "0x12345678901234567890",
+    1, /* NB: Rounding errors mean we don't get the mantissas we want. */
+    { 0xffffffffU, 0xfffffU, 0x7ffU, 0 },
+    { 0x7fffffU, 0xffU, 0 },
+    { 0xffffffffU, 0xffffffffU, 0x7fffU, 0 }
+  },
+
+  /* Terminator */
+  {
+    0,
+    NULL,
+    0,
+    { 0, 0, 0, 0 },
+    { 0, 0, 0 },
+    { 0, 0, 0, 0 },
+  }
+};
+
+static int
+double_t_equal (double_t *dt1, double_t *dt2, const int ignore_mantissa)
+{
+   int res = 1;
+
+   if (!ignore_mantissa)
+     {
+       if (dt1->mantissal != dt2->mantissal)
+	 res = 0;
+       if (dt1->mantissah != dt2->mantissah)
+	 res = 0;
+     }
+   if (dt1->exponent != dt2->exponent)
+     res = 0;
+   if (dt1->sign != dt2->sign)
+     res = 0;
+
+   return res;
+}
+
+static void
+dump_double_t (double_t *dt)
+{
+  printf("(0x%x, 0x%x, 0x%x, 0x%x)",
+	 dt->mantissal, dt->mantissah, dt->exponent, dt->sign);
+}
+
+static int
+float_t_equal (float_t *ft1, float_t *ft2, const int ignore_mantissa)
+{
+   int res = 1;
+
+   if (!ignore_mantissa && (ft1->mantissa != ft2->mantissa))
+     res = 0;
+   if (ft1->exponent != ft2->exponent)
+     res = 0;
+   if (ft1->sign != ft2->sign)
+     res = 0;
+
+   return res;
+}
+
+static void
+dump_float_t (float_t *ft)
+{
+  printf("(0x%x, 0x%x, 0x%x)",
+	 ft->mantissa, ft->exponent, ft->sign);
+}
+
+static int
+long_double_t_equal (long_double_t *ldt1,
+		     long_double_t *ldt2,
+		     const int ignore_mantissa)
+{
+   int res = 1;
+
+   if (!ignore_mantissa)
+     {
+       if (ldt1->mantissal != ldt2->mantissal)
+	 res = 0;
+       if (ldt1->mantissah != ldt2->mantissah)
+	 res = 0;
+     }
+   if (ldt1->exponent != ldt2->exponent)
+     res = 0;
+   if (ldt1->sign != ldt2->sign)
+     res = 0;
+
+   return res;
+}
+
+static void
+dump_long_double_t (long_double_t *ldt)
+{
+  printf("(0x%x, 0x%x, 0x%x, 0x%x)",
+	 ldt->mantissal, ldt->mantissah, ldt->exponent, ldt->sign);
+}
+
+int
+main (void)
+{
+  int           ok = 1;
+  double        d_res;
+  double_t      dt_res;
+  float         f_res;
+  float_t       ft_res;
+  long double   ld_res;
+  long_double_t ldt_res;
+  int           i;
+  int           testcase = 0;
+
+  testcase++;
+
+  for (i = 0; testcases[i].valid; testcase++, i++)
+    {
+      printf("Testcase %d: nan(): ", testcase);
+
+      d_res = nan(testcases[i].input);
+      dt_res = *(double_t *) &d_res;
+
+      if (!double_t_equal(&testcases[i].dt_expected,
+			  &dt_res,
+			  testcases[i].ignore_mantissa))
+	{
+	  puts("FAIL");
+	  printf("Expected: ");
+	  dump_double_t(&testcases[i].dt_expected);
+	  printf("\nGot: ");
+	  dump_double_t(&dt_res);
+	  puts("");
+	  ok = 0;
+	}
+      else
+	{
+	  puts("OK");
+	}
+
+      printf("Testcase %d: nanf(): ", testcase);
+
+      f_res = nanf(testcases[i].input);
+      ft_res = *(float_t *) &f_res;
+
+      if (!float_t_equal(&testcases[i].ft_expected,
+			 &ft_res,
+			 testcases[i].ignore_mantissa))
+	{
+	  puts("FAIL");
+	  printf("Expected: ");
+	  dump_float_t(&testcases[i].ft_expected);
+	  printf("\nGot: ");
+	  dump_float_t(&ft_res);
+	  puts("");
+	  ok = 0;
+	}
+      else
+	{
+	  puts("OK");
+	}
+
+      printf("Testcase %d: nanl(): ", testcase);
+
+      ld_res = nanl(testcases[i].input);
+      ldt_res = *(long_double_t *) &ld_res;
+
+      if (!long_double_t_equal(&testcases[i].ldt_expected,
+			       &ldt_res,
+			       testcases[i].ignore_mantissa))
+	{
+	  puts("FAIL");
+	  printf("Expected: ");
+	  dump_long_double_t(&testcases[i].ldt_expected);
+	  printf("\nGot: ");
+	  dump_long_double_t(&ldt_res);
+	  puts("");
+	  ok = 0;
+	}
+      else
+	{
+	  puts("OK");
+	}
+    }
+
+  puts(ok ? "PASS" : "FAIL");
+  return ok ? EXIT_SUCCESS : EXIT_FAILURE;
+}

- Raw text -


  webmaster     delorie software   privacy  
  Copyright © 2019   by DJ Delorie     Updated Jul 2019