delorie.com/archives/browse.cgi   search  
Mail Archives: djgpp-workers/2003/03/14/15:03:29

From: <ams AT ludd DOT luth DOT se>
Message-Id: <200303142003.h2EK3NH09554@speedy.ludd.luth.se>
Subject: strto{d,f,ld}, inf and nan patch
To: DJGPP-WORKERS <djgpp-workers AT delorie DOT com>
Date: Fri, 14 Mar 2003 21:03:23 +0100 (CET)
X-Mailer: ELM [version 2.4ME+ PL78 (25)]
MIME-Version: 1.0
X-MailScanner: Found to be clean
Reply-To: djgpp-workers AT delorie DOT com

Hello.

Ok, this is what I have for inf and nan support for strto{d,f,ld}.
Now all three of them are done. Many added test cases for
strtof(). Somebody else might want to add some in the endptr category.

No test cases at all for strtold(). Sorry. There weren't any before
either.

I'm unsure if my markup in wc204.txi is good.

Comments?


Right,

						MartinS

Index: djgpp/include/math.h
===================================================================
RCS file: /cvs/djgpp/djgpp/include/math.h,v
retrieving revision 1.7
diff -p -u -r1.7 math.h
--- djgpp/include/math.h        20 Feb 2003 19:04:02 -0000      1.7
+++ djgpp/include/math.h        14 Mar 2003 19:53:52 -0000
@@ -51,6 +51,11 @@ extern long double __dj_huge_vall;
 #define HUGE_VALF __dj_huge_valf
 #define HUGE_VALL __dj_huge_vall
 
+#define INFINITY  HUGE_VALF
+
+extern float       __dj_nan;
+#define NAN        __dj_nan
+
 #endif /* (__STDC_VERSION__ >= 199901L) || !__STRICT_ANSI__ */
   
 #ifndef __STRICT_ANSI__
Index: djgpp/src/docs/kb/wc204.txi
===================================================================
RCS file: /cvs/djgpp/djgpp/src/docs/kb/wc204.txi,v
retrieving revision 1.149
diff -p -u -r1.149 wc204.txi
--- djgpp/src/docs/kb/wc204.txi 14 Mar 2003 19:11:31 -0000      1.149
+++ djgpp/src/docs/kb/wc204.txi 14 Mar 2003 19:54:00 -0000
@@ -917,3 +917,10 @@ The functions @code{readv} and @code{wri
 
 @findex pwrite
 The function @code{pwrite} was added.
+
+@findex strtod AT r{, inf and nan in input}
+@findex strtof AT r{, inf and nan in input}
+@findex strtold AT r{, inf and nan in input}
+The functions @code{strtod}, @code{strtof} and @code{strtold} now
+understand ``inf'', ``infinity'', ``nan'' and ``nan(<anything>)'' in the
+input string.
Index: djgpp/src/libc/ansi/stdlib/strtod.c
===================================================================
RCS file: /cvs/djgpp/djgpp/src/libc/ansi/stdlib/strtod.c,v
retrieving revision 1.5
diff -p -u -r1.5 strtod.c
--- djgpp/src/libc/ansi/stdlib/strtod.c 17 Oct 2002 23:00:24 -0000      1.5
+++ djgpp/src/libc/ansi/stdlib/strtod.c 14 Mar 2003 19:54:01 -0000
@@ -1,13 +1,16 @@
+/* Copyright (C) 2003 DJ Delorie, see COPYING.DJ for details */
 /* Copyright (C) 2001 DJ Delorie, see COPYING.DJ for details */
 /* Copyright (C) 1998 DJ Delorie, see COPYING.DJ for details */
 /* Copyright (C) 1997 DJ Delorie, see COPYING.DJ for details */
 /* Copyright (C) 1996 DJ Delorie, see COPYING.DJ for details */
 /* Copyright (C) 1994 DJ Delorie, see COPYING.DJ for details */
+#include <libc/stubs.h>
 #include <math.h>
 #include <stdlib.h>
 #include <float.h>
 #include <errno.h>
 #include <ctype.h>
+#include <string.h>
 #include <libc/unconst.h>
 
 double
@@ -32,6 +35,7 @@ strtod(const char *s, char **sret)
   while (isspace((unsigned char) *s))
     s++;
 
+  /* Handle leading sign. */
   if (*s == '+')
     s++;
   else if (*s == '-')
@@ -40,6 +44,66 @@ strtod(const char *s, char **sret)
     s++;
   }
 
+  /* Handle INF and INFINITY. */
+  if ( ! strnicmp( "INF", s, 3 ) )
+  {
+    if( sret )
+    {
+      if ( ! strnicmp( "INITY", &s[3], 5 ) )
+      {
+       *sret = unconst((&s[8]), char *);
+      }
+      else
+      {
+       *sret = unconst((&s[3]), char *);
+      }
+    }
+
+    if( 0 <= sign )
+    {
+      return INFINITY;
+    }
+    else
+    {
+      return -INFINITY;
+    }
+  }
+
+  /* Handle NAN and NAN(<whatever>). */
+  if ( ! strnicmp( "NAN", s, 3 ) )
+  {
+    if( s[3] == '(' )
+    {
+      int end_of_n_char_sequence = 4;
+
+      while( s[end_of_n_char_sequence] != 0 && 
+            s[end_of_n_char_sequence] != ')' )
+      {
+       end_of_n_char_sequence++;
+      }
+      if( s[end_of_n_char_sequence] == ')' )
+      {
+       /* If we are going to support "nan(0x1234) for setting specific bits, 
+        * that code goes here. Something like "bits = strtoul( &s[4], &end_p,
+        * 0);".
+        */
+       if( sret )
+       {
+         *sret = unconst((&s[end_of_n_char_sequence+1]), char *);
+       }
+       return NAN;
+      }
+      /* The subject sequence didn't match NAN(), so match only NAN. */
+    }
+
+    if( sret )
+    {
+      *sret = unconst((&s[3]), char *);
+    }
+    return NAN;
+  }
+
+  /* Handle ordinary numbers. */
   while ((*s >= '0') && (*s <= '9'))
   {
     flags |= 1;
Index: djgpp/src/libc/ansi/stdlib/strtold.c
===================================================================
RCS file: /cvs/djgpp/djgpp/src/libc/ansi/stdlib/strtold.c,v
retrieving revision 1.4
diff -p -u -r1.4 strtold.c
--- djgpp/src/libc/ansi/stdlib/strtold.c        6 Dec 2002 09:32:23 -0000       1.4
+++ djgpp/src/libc/ansi/stdlib/strtold.c        14 Mar 2003 19:54:01 -0000
@@ -1,9 +1,12 @@
+/* Copyright (C) 2003 DJ Delorie, see COPYING.DJ for details */
 /* Copyright (C) 2002 DJ Delorie, see COPYING.DJ for details */
 /* Copyright (C) 1999 DJ Delorie, see COPYING.DJ for details */
 /* Copyright (C) 1994 DJ Delorie, see COPYING.DJ for details */
 #include <libc/stubs.h>
 #include <stdlib.h>
 #include <ctype.h>
+#include <math.h>
+#include <string.h>
 #include <libc/unconst.h>
 
 static long double powten[] =
@@ -38,6 +41,66 @@ strtold(const char *s, char **sret)
     s++;
   }
 
+  /* Handle INF and INFINITY. */
+  if ( ! strnicmp( "INF", s, 3 ) )
+  {
+    if( sret )
+    {
+      if ( ! strnicmp( "INITY", &s[3], 5 ) )
+      {
+       *sret = unconst((&s[8]), char *);
+      }
+      else
+      {
+       *sret = unconst((&s[3]), char *);
+      }
+    }
+
+    if( 0 <= sign )
+    {
+      return INFINITY;
+    }
+    else
+    {
+      return -INFINITY;
+    }
+  }
+
+  /* Handle NAN and NAN(<whatever>). */
+  if ( ! strnicmp( "NAN", s, 3 ) )
+  {
+    if( s[3] == '(' )
+    {
+      int end_of_n_char_sequence = 4;
+
+      while( s[end_of_n_char_sequence] != 0 && 
+            s[end_of_n_char_sequence] != ')' )
+      {
+       end_of_n_char_sequence++;
+      }
+      if( s[end_of_n_char_sequence] == ')' )
+      {
+       /* If we are going to support "nan(0x1234) for setting specific bits, 
+        * that code goes here. Something like "bits = strtoul( &s[4], &end_p,
+        * 0);".
+        */
+       if( sret )
+       {
+         *sret = unconst((&s[end_of_n_char_sequence+1]), char *);
+       }
+       return NAN;
+      }
+      /* The subject sequence didn't match NAN(), so match only NAN. */
+    }
+
+    if( sret )
+    {
+      *sret = unconst((&s[3]), char *);
+    }
+    return NAN;
+  }
+
+  /* Handle ordinary numbers. */
   while ((*s >= '0') && (*s <= '9'))
   {
     flags |= 1;
Index: djgpp/src/libc/c99/math/makefile
===================================================================
RCS file: /cvs/djgpp/djgpp/src/libc/c99/math/makefile,v
retrieving revision 1.1
diff -p -u -r1.1 makefile
--- djgpp/src/libc/c99/math/makefile    23 Jan 2003 19:50:51 -0000      1.1
+++ djgpp/src/libc/c99/math/makefile    14 Mar 2003 19:54:01 -0000
@@ -3,5 +3,6 @@ TOP=../..
 
 SRC += hugevalf.c
 SRC += hugevall.c
+SRC += nan.c
 
 include $(TOP)/../makefile.inc
Index: djgpp/src/libc/c99/stdlib/strtof.c
===================================================================
RCS file: /cvs/djgpp/djgpp/src/libc/c99/stdlib/strtof.c,v
retrieving revision 1.2
diff -p -u -r1.2 strtof.c
--- djgpp/src/libc/c99/stdlib/strtof.c  23 Jan 2003 19:53:02 -0000      1.2
+++ djgpp/src/libc/c99/stdlib/strtof.c  14 Mar 2003 19:54:01 -0000
@@ -5,11 +5,13 @@
 /* Copyright (C) 1997 DJ Delorie, see COPYING.DJ for details */
 /* Copyright (C) 1996 DJ Delorie, see COPYING.DJ for details */
 /* Copyright (C) 1994 DJ Delorie, see COPYING.DJ for details */
+#include <libc/stubs.h>
 #include <math.h>
 #include <stdlib.h>
 #include <float.h>
 #include <errno.h>
 #include <ctype.h>
+#include <string.h>
 #include <libc/unconst.h>
 
 float
@@ -43,6 +45,66 @@ strtof(const char *s, char **sret)
     s++;
   }
 
+  /* Handle INF and INFINITY. */
+  if ( ! strnicmp( "INF", s, 3 ) )
+  {
+    if( sret )
+    {
+      if ( ! strnicmp( "INITY", &s[3], 5 ) )
+      {
+       *sret = unconst((&s[8]), char *);
+      }
+      else
+      {
+       *sret = unconst((&s[3]), char *);
+      }
+    }
+
+    if( 0 <= sign )
+    {
+      return INFINITY;
+    }
+    else
+    {
+      return -INFINITY;
+    }
+  }
+
+  /* Handle NAN and NAN(<whatever>). */
+  if ( ! strnicmp( "NAN", s, 3 ) )
+  {
+    if( s[3] == '(' )
+    {
+      int end_of_n_char_sequence = 4;
+
+      while( s[end_of_n_char_sequence] != 0 && 
+            s[end_of_n_char_sequence] != ')' )
+      {
+       end_of_n_char_sequence++;
+      }
+      if( s[end_of_n_char_sequence] == ')' )
+      {
+       /* If we are going to support "nan(0x1234) for setting specific bits, 
+        * that code goes here. Something like "bits = strtoul( &s[4], &end_p,
+        * 0);".
+        */
+       if( sret )
+       {
+         *sret = unconst((&s[end_of_n_char_sequence+1]), char *);
+       }
+       return NAN;
+      }
+      /* The subject sequence didn't match NAN(), so match only NAN. */
+    }
+
+    if( sret )
+    {
+      *sret = unconst((&s[3]), char *);
+    }
+    return NAN;
+  }
+
+  /* Handle ordinary numbers. */
   while ((*s >= '0') && (*s <= '9'))
   {
     flags |= 1;
Index: djgpp/tests/libc/ansi/stdlib/strtod.c
===================================================================
RCS file: /cvs/djgpp/djgpp/tests/libc/ansi/stdlib/strtod.c,v
retrieving revision 1.1
diff -p -u -r1.1 strtod.c
--- djgpp/tests/libc/ansi/stdlib/strtod.c       1 Jan 1998 21:45:46 -0000       1.1
+++ djgpp/tests/libc/ansi/stdlib/strtod.c       14 Mar 2003 19:54:05 -0000
@@ -9,6 +9,10 @@ static const char *testnum[] = {
   "1e6000000000",      /* overflow */
   "1e400",             /* ditto */
   "1e-400",            /* underflow */
+  "InF",               /* infinity */
+  "-inFinitY",         /* infinity */
+  "nAn",               /* nan */
+  "-Nan()",            /* nan */
   0
 };
 
Index: djgpp/tests/libc/c99/stdlib/t-strtof.c
===================================================================
RCS file: /cvs/djgpp/djgpp/tests/libc/c99/stdlib/t-strtof.c,v
retrieving revision 1.2
diff -p -u -r1.2 t-strtof.c
--- djgpp/tests/libc/c99/stdlib/t-strtof.c      23 Jan 2003 19:53:57 -0000      1.2
+++ djgpp/tests/libc/c99/stdlib/t-strtof.c      14 Mar 2003 19:54:05 -0000
@@ -51,6 +51,50 @@ static const test3_t tests3[] = {
 
 static const size_t n_tests3 = sizeof(tests3) / sizeof(tests3[0]);
 
+typedef struct {
+  const char * const str; /* String to run strtof() on. */
+  const int diff; /* For endptr tests. How many characters from string start
+                    endptr should be offset. */
+  const int inf; /* 0 -> not inf, 1 -> +inf, -1 -> -inf. */
+  const int nan; /* 0 -> not nan, 1 -> nan. */
+} test4_t;
+
+static const test4_t tests4[] = {
+  { "nAn",                 3,  0, 1 },
+  { "-nAn",                4,  0, 1 },
+  { "nanny",               3,  0, 1 },
+  { "-nanny",              4,  0, 1 },
+  { "NAN()",               5,  0, 1 },
+  { "-NAN()",              6,  0, 1 },
+  { "nan(whatever)",      13,  0, 1 },
+  { "-nan(someMOREever)", 18,  0, 1 },
+  { "nan(!#%&/=?`)",      13,  0, 1 },
+  { "-nan(((()",           9,  0, 1 },
+  { "nan(-0x12)",         10,  0, 1 },
+  { "-nan(-nan)",         10,  0, 1 },
+  { "nan(-42)",            8,  0, 1 },
+  { "-nan(0xaa7d7aa74)",  17,  0, 1 },
+  { "nan()()",             5,  0, 1 },
+  { "-nan(smurf)()",      11,  0, 1 },
+  { "NAN()nan",            5,  0, 1 },
+  { "-nan(NAN)nanNAN",     9,  0, 1 },
+  { "inF",                 3,  1, 0 },
+  { "-INf",                4, -1, 0 },
+  { "infi",                3,  1, 0 },
+  { "-infi",               4, -1, 0 },
+  { "infinit",             3,  1, 0 },
+  { "-infinit",            4, -1, 0 },
+  { "INfINITY",            8,  1, 0 },
+  { "-InfInIty",           9, -1, 0 },
+  { "infinity0",           8,  1, 0 },
+  { "-infinity5",          9, -1, 0 },
+  { "infinity-1",          8,  1, 0 },
+  { "-infinity-6",         9, -1, 0 },
+};
+
+static const size_t n_tests4 = sizeof(tests4) / sizeof(tests4[0]);
+
+
 static void inline
 result (const size_t n, const float f_in, const float f_out)
 {
@@ -104,6 +148,62 @@ main (void)
        puts("Yes - FAIL");
       else
        puts("No - OK");
+    }
+  }
+  
+  puts("Infinity tests:");
+  for (i = 0; i < n_tests4; i++) {
+    float_t float_bits;
+
+    if (tests4[i].inf) {
+      f_res = strtof(tests4[i].str, NULL);
+      
+      printf("strtof(\"%s\", NULL) -> %f - ", tests4[i].str, f_res);
+
+      /* Need to to the inf detection ourselves. */
+      float_bits = *(float_t *)(&f_res);
+      if (float_bits.exponent == 0xff && float_bits.mantissa == 0 &&
+         ( (float_bits.sign && f_res < 0) || 
+          (!float_bits.sign && 0 < f_res) )) {
+       puts("OK");
+      } else {
+       puts("FAIL");
+      }
+    }
+  }
+  
+  puts("Nan tests:");
+  for (i = 0; i < n_tests4; i++) {
+    float_t float_bits;
+
+    if (tests4[i].nan) {
+      f_res = strtof(tests4[i].str, NULL);
+
+      printf("strtof(\"%s\", NULL) -> %f - ", tests4[i].str, f_res);
+
+      /* Need to to the nandetection ourselves. */
+      float_bits = *(float_t *)(&f_res);
+      if (float_bits.exponent == 0xff && float_bits.mantissa != 0) {
+       puts("OK");
+      } else {
+        puts("FAIL");
+      }
+    }
+  }
+
+  puts("endptr tests:");
+  for (i = 0; i < n_tests4; i++) {
+    char *endptr;
+
+    f_res = strtof(tests4[i].str, &endptr);
+
+    printf("strtof(\"%s\", endptr) -> endptr - (start_of_string) == %ld - ", 
+          tests4[i].str, endptr - tests4[i].str);
+
+    if (endptr-tests4[i].str == tests4[i].diff) {
+      puts("OK");
+    } else {
+      puts("FAIL");
     }
   }
 

- Raw text -


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