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" 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: 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(), so match + /* The subject sequence didn't match NAN(), 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(), so match + /* The subject sequence didn't match NAN(), 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(), so match + /* The subject sequence didn't match NAN(), 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 +#include +#include +#include +#include -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() 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 + +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 + +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 +#include +#include +#include + +float +nanf(const char *tagp) +{ + float ret = NAN; + char buf[256]; + int s; + + if (tagp) + { + /* + * If we can't fit NAN() 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 + +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 +#include +#include +#include + +long double +nanl(const char *tagp) +{ + float ret = NAN; + char buf[256]; + int s; + + if (tagp) + { + /* + * If we can't fit NAN() 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 + +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 + */ + +#include +#include +#include +#include + +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*("") == 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*("") == strto*("NAN()") + */ + { + 1, + "1", + 0, + { 0x1U, 0x80000U, 0x7ffU, 0 }, + { 0x400001, 0xffU, 0 }, + { 1, 0xc0000000, 0x7fffU, 0 } + }, + + /* + * Testcase 6: + * nan*("") == strto*("NAN()") + */ + { + 1, + "1234", + 0, + { 0x4d2, 0x80000U, 0x7ffU, 0 }, + { 0x4004d2, 0xffU, 0 }, + { 0x4d2, 0xc0000000, 0x7fffU, 0 } + }, + + /* + * Testcase 7: + * nan*("") == strto*("NAN()") + */ + { + 1, + "0x1", + 0, + { 0x1U, 0x80000U, 0x7ffU, 0 }, + { 0x400001, 0xffU, 0 }, + { 1, 0xc0000000, 0x7fffU, 0 } + }, + + /* + * Testcase 8: + * nan*("") == strto*("NAN()") + */ + { + 1, + "0x1234", + 0, + { 0x1234, 0x80000U, 0x7ffU, 0 }, + { 0x401234, 0xffU, 0 }, + { 0x1234, 0xc0000000, 0x7fffU, 0 } + }, + + /* + * Testcase 9: + * nan*("") + * == strto*("NAN(") + */ + /* + * 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*("") + * == strto*("NAN(") + */ + /* + * 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; +}