Date: Wed, 18 Dec 2002 14:37:49 +0000 From: "Richard Dawe" 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: strtof, revision 2 (C99) [PATCH] Message-Id: Reply-To: djgpp-workers AT delorie DOT com Hello. Below is revision 2 of the strtof patch. This updates the test to test NaNs too - they're not understood by strto*. Here's what the test displays for me now: float tests: Test 1: 2 -> 2 Test 2: 20 -> 20 Test 3: 200 -> 200 Test 4: 2e+38 -> 2e+38 Test 5: 1e+38 -> 1e+38 Test 6: Inf -> 0 Test 7: 0.2 -> 0.2 Test 8: 0.02 -> 0.02 Test 9: 0.002 -> 0.002 Test 10: 2e-37 -> 2e-37 Test 11: 2e-38 -> 2e-38 Test 12: 2e-39 -> 2e-39 Test 13: 9.80909e-45 -> 9.80909e-45 Test 14: 1.4013e-45 -> 1.4013e-45 float_t tests: Test 1: Inf -> 0 Test 2: NaN -> 0 OK to commit? Thanks, bye, Rich =] Index: include/stdlib.h =================================================================== RCS file: /cvs/djgpp/djgpp/include/stdlib.h,v retrieving revision 1.15 diff -p -c -3 -r1.15 stdlib.h *** include/stdlib.h 6 Dec 2002 09:32:41 -0000 1.15 --- include/stdlib.h 18 Dec 2002 14:32:29 -0000 *************** int rand(void); *** 72,77 **** --- 72,78 ---- void * realloc(void *_ptr, size_t _size); void srand(unsigned _seed); double strtod(const char *_s, char **_endptr); + float strtof(const char *_s, char **_endptr); long strtol(const char *_s, char **_endptr, int _base); long double strtold(const char *_s, char **_endptr); unsigned long strtoul(const char *_s, char **_endptr, int _base); Index: src/libc/c99/stdlib/makefile =================================================================== RCS file: /cvs/djgpp/djgpp/src/libc/c99/stdlib/makefile,v retrieving revision 1.1 diff -p -c -3 -r1.1 makefile *** src/libc/c99/stdlib/makefile 30 Nov 2002 09:27:03 -0000 1.1 --- src/libc/c99/stdlib/makefile 18 Dec 2002 14:32:29 -0000 *************** *** 2,6 **** --- 2,7 ---- TOP=../.. SRC += _exit.S + SRC += strtof.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.130 diff -p -c -3 -r1.130 wc204.txi *** src/docs/kb/wc204.txi 18 Dec 2002 07:29:44 -0000 1.130 --- src/docs/kb/wc204.txi 18 Dec 2002 14:32:38 -0000 *************** to avoid conflicts. *** 833,835 **** --- 833,838 ---- @findex ctime AT r{, and calls to @code{getenv}} Fix caching when environment variable TZ is not set. Prevents many calls to getenv() which are not needed. + + @findex strtof + The function @code{strtof} was added. Index: tests/libc/c99/stdlib/makefile =================================================================== RCS file: /cvs/djgpp/djgpp/tests/libc/c99/stdlib/makefile,v retrieving revision 1.1 diff -p -c -3 -r1.1 makefile *** tests/libc/c99/stdlib/makefile 30 Nov 2002 09:28:09 -0000 1.1 --- tests/libc/c99/stdlib/makefile 18 Dec 2002 14:32:38 -0000 *************** *** 1,5 **** --- 1,6 ---- TOP=../.. SRC += t-_exit.c + SRC += t-strtof.c include $(TOP)/../makefile.inc *** /dev/null Wed Dec 18 14:33:45 2002 --- src/libc/c99/stdlib/strtof.c Tue Dec 17 13:05:26 2002 *************** *** 0 **** --- 1,126 ---- + /* Copyright (C) 2002 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 + #include + #include + #include + #include + #include + + float + strtof(const char *s, char **sret) + { + long double r; /* result */ + int e; /* exponent */ + long double d; /* scale */ + int sign; /* +- 1.0 */ + int esign; + int i; + int flags=0; + + r = 0.0; + sign = 1; + e = 0; + esign = 1; + + if (sret) + *sret = unconst(s, char *); + + while (isspace((unsigned char) *s)) + s++; + + if (*s == '+') + s++; + else if (*s == '-') + { + sign = -1; + s++; + } + + while ((*s >= '0') && (*s <= '9')) + { + flags |= 1; + r *= 10.0; + r += *s - '0'; + s++; + } + + if (*s == '.') + { + d = 0.1L; + s++; + while ((*s >= '0') && (*s <= '9')) + { + flags |= 2; + r += d * (*s - '0'); + s++; + d *= 0.1L; + } + } + + if (flags == 0) + return 0; + + if (sret) + *sret = unconst(s, char *); + + if ((*s == 'e') || (*s == 'E')) + { + s++; + if (*s == '+') + s++; + else if (*s == '-') + { + s++; + esign = -1; + } + if ((*s < '0') || (*s > '9')) + return r * sign; + + while ((*s >= '0') && (*s <= '9')) + { + e *= 10; + e += *s - '0'; + s++; + } + } + + /* Detect overflow. */ + if (e < 0) + { + errno = ERANGE; + r = HUGE_VAL; + } + else if (esign < 0) + for (i = 1; i <= e; i++) + { + r *= 0.1L; + /* Detect underflow below 2^-150, which is half + the smallest representable float. */ + if (r < 7.00649232162408535461e-46L) + { + errno = ERANGE; + r = 0.0; + break; + } + } + else + for (i = 1; i <= e; i++) + { + r *= 10.0; + if (r > FLT_MAX) /* detect overflow */ + { + errno = ERANGE; + r = HUGE_VAL; + break; + } + } + + if (sret) + *sret = unconst(s, char *); + return r * sign; + } *** /dev/null Wed Dec 18 14:33:45 2002 --- src/libc/c99/stdlib/strtof.txh Sat Dec 14 22:30:10 2002 *************** *** 0 **** --- 1,36 ---- + @node strtof, string + @subheading Syntax + + @example + #include + + float strtof(const char *s, char **endp); + @end example + + @subheading Description + + This function converts as many characters of @var{s} as look like a + floating point number into that number. If @var{endp} is not a null + pointer, @code{*endp} is set to point to the first unconverted + character. + + @subheading Return Value + + The value the represented by @var{s}. + + If a number represented by @var{s} doesn't fit into the range of values + representable by the type @code{double}, the function returns either + @code{-HUGE_VAL} (if @var{s} begins with the character @code{-}) or + @code{+HUGE_VAL}, and sets @code{errno} to @code{ERANGE}. + + @subheading Portability + + @portability !ansi-c89, ansi-c99, !posix-1003.2-1992, posix-1003.1-2001 + + @subheading Example + + @example + char *buf = "123ret"; + char *bp; + float x = strtof(buf, &bp); + @end example *** /dev/null Wed Dec 18 14:33:45 2002 --- tests/libc/c99/stdlib/t-strtof.c Wed Dec 18 14:27:42 2002 *************** *** 0 **** --- 1,56 ---- + #include + #include + #include + #include + + /* float tests */ + static const float tests[] = { + 2.0, 20.0, 200.0, 2e38, 1e38, + 2.0e39, /* Larger than maximum float => "infinite" */ + 2.0e-01, 2.0e-02, 2.0e-03, 2e-37, + 2e-38, 2e-39, + 1e-44, 1e-45 + }; + + static const size_t n_tests = sizeof(tests) / sizeof(tests[0]); + + /* float_t tests - so we can specify *exactly* what we want. */ + static const float_t tests2[] = { + /* Infinity */ + { 0U, 0xffU, 0x0 }, + + /* NaN */ + { 1U, 0xffU, 0x0 } + }; + + static const size_t n_tests2 = sizeof(tests2) / sizeof(tests2[0]); + + static void inline + result (const size_t n, const float f_in, const float f_out) + { + printf("Test %lu: %g -> %g\n", n, f_in, f_out); + } + + int + main (void) + { + char buf[128]; + float f_res; + size_t i; + + puts("float tests:"); + for (i = 0; i < n_tests; i++) { + sprintf(buf, "%g", tests[i]); + f_res = strtof(buf, NULL); + result(i + 1, tests[i], f_res); + } + + puts("float_t tests:"); + for (i = 0; i < n_tests2; i++) { + sprintf(buf, "%g", *(const float *) &tests2[i]); + f_res = strtof(buf, NULL); + result(i + 1, *(const float *) &tests2[i], f_res); + } + + return(EXIT_SUCCESS); + }