From: Bruno Haible Date: Tue, 23 Jul 2024 10:40:37 +0000 (+0200) Subject: strtod: Revisit underflow behaviour. X-Git-Url: https://gitweb.git.savannah.gnu.org/gitweb/?a=commitdiff_plain;h=bd61e8c8ca7a41ce6e265c2cd8d9de5f4c3c4bd5;p=gnulib.git strtod: Revisit underflow behaviour. * doc/posix-functions/strtod.texi: Mention the macOS bug. Mention that gradual underflow does not count as an error on Cygwin 2.9 and MSVC. * m4/strtod.m4 (gl_FUNC_STRTOD): Update comment. * tests/test-strtod.h (test_function): Add a gradual underflow test. Check the sign in case of flush-to-zero underflow. --- diff --git a/ChangeLog b/ChangeLog index 3da7b01049..3f086d2a9f 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,5 +1,12 @@ 2024-07-23 Bruno Haible + strtod: Revisit underflow behaviour. + * doc/posix-functions/strtod.texi: Mention the macOS bug. Mention that + gradual underflow does not count as an error on Cygwin 2.9 and MSVC. + * m4/strtod.m4 (gl_FUNC_STRTOD): Update comment. + * tests/test-strtod.h (test_function): Add a gradual underflow test. + Check the sign in case of flush-to-zero underflow. + strtof: Revisit underflow behaviour. * doc/posix-functions/strtof.texi: Mention the macOS bug. Mention the mingw overflow bug. Mention the underflow bugs on Cygwin 2.9 and mingw. diff --git a/doc/posix-functions/strtod.texi b/doc/posix-functions/strtod.texi index 9b470eb465..a7d0143a13 100644 --- a/doc/posix-functions/strtod.texi +++ b/doc/posix-functions/strtod.texi @@ -31,7 +31,7 @@ OpenBSD 4.0, HP-UX 11.11, Solaris 9, mingw, MSVC 14. @item This function fails to parse @samp{NaN()} on some platforms: -glibc-2.3.6, Mac OS X 10.5, FreeBSD 6.2, OpenBSD 4.0, AIX 7.1, HP-UX 11.11, Cygwin < 1.5.25-11, mingw, MSVC 14. +glibc 2.3.6, Mac OS X 10.5, FreeBSD 6.2, OpenBSD 4.0, AIX 7.1, HP-UX 11.11, Cygwin < 1.5.25-11, mingw, MSVC 14. @item This function fails to parse @samp{NaN(@var{n-char-sequence})} on some @@ -41,7 +41,11 @@ OpenBSD 4.0, HP-UX 11.11, mingw, MSVC 14. @item This function parses @samp{NaN(@var{n-char-sequence})}, but returns the wrong end pointer on some platforms: -glibc-2.4, AIX 7.1. +glibc 2.4, AIX 7.1. + +@item +This function misparses @samp{nan(} on some platforms: +macOS 10.6.6. @item This function fails to parse C99 hexadecimal floating point on some @@ -57,6 +61,14 @@ HP-UX 11.31/ia64. This function returns the wrong end pointer for @samp{0x1p} on some platforms: AIX 7.1. + +@item +@c The term "underflow", as defined by ISO C23 § 7.12.1.(6), includes both +@c "gradual underflow" (result is a denormalized number) and "flush-to-zero +@c underflow" (result is zero). +This function fails to set @code{errno} upon gradual underflow (resulting +in a denormalized number) on some platforms: +Cygwin 2.9. @end itemize Portability problems fixed by Gnulib module @code{strtod-obsolete}: @@ -82,6 +94,11 @@ This function fails to correctly parse very long strings on some platforms: Mac OS X 10.5, FreeBSD 6.2, NetBSD 5.0, OpenBSD 4.0, Cygwin, mingw, MSVC 14. +@item +This function fails to set @code{errno} upon gradual underflow (resulting +in a denormalized number) on some platforms: +MSVC 14. + @item The replacement function does not always return correctly rounded results. @end itemize diff --git a/m4/strtod.m4 b/m4/strtod.m4 index 2ccbf3139a..e974478845 100644 --- a/m4/strtod.m4 +++ b/m4/strtod.m4 @@ -1,5 +1,5 @@ # strtod.m4 -# serial 30 +# serial 31 dnl Copyright (C) 2002-2003, 2006-2024 Free Software Foundation, Inc. dnl This file is free software; the Free Software Foundation dnl gives unlimited permission to copy and/or distribute it, @@ -92,7 +92,7 @@ numeric_equal (double x, double y) result |= 16; } { - /* darwin 10.6.1 misparses "nan(". */ + /* Darwin 10.6.1 (macOS 10.6.6) misparses "nan(". */ const char *string = "nan("; char *term; double value = strtod (string, &term); diff --git a/tests/test-strtod.h b/tests/test-strtod.h index 48d784f368..c806953e84 100644 --- a/tests/test-strtod.h +++ b/tests/test-strtod.h @@ -481,7 +481,7 @@ test_function (double (*my_strtod) (const char *, char **)) ASSERT (errno == 0); } - /* Overflow/underflow. */ + /* Overflow. */ { const char input[] = "1E1000000"; char *ptr; @@ -502,6 +502,34 @@ test_function (double (*my_strtod) (const char *, char **)) ASSERT (ptr == input + 10); ASSERT (errno == ERANGE); } + + /* Gradual underflow, resulting in a denormalized number. */ + { + const char input[] = "1e-320"; + char *ptr; + double result; + errno = 0; + result = my_strtod (input, &ptr); + ASSERT (0.0 < result && result <= DBL_MIN); + ASSERT (ptr == input + 6); +#if !defined _MSC_VER + ASSERT (errno == ERANGE); +#endif + } + { + const char input[] = "-1e-320"; + char *ptr; + double result; + errno = 0; + result = my_strtod (input, &ptr); + ASSERT (-DBL_MIN <= result && result < 0.0); + ASSERT (ptr == input + 7); +#if !defined _MSC_VER + ASSERT (errno == ERANGE); +#endif + } + + /* Flush-to-zero underflow. */ { const char input[] = "1E-100000"; char *ptr; @@ -520,16 +548,14 @@ test_function (double (*my_strtod) (const char *, char **)) errno = 0; result = my_strtod (input, &ptr); ASSERT (-DBL_MIN <= result && result <= 0.0); -#if 0 - /* FIXME - this is glibc bug 5995; POSIX allows returning positive - 0 on negative underflow, even though quality of implementation - demands preserving the sign. Disable this test until fixed - glibc is more prevalent. */ + /* Negative underflow. Expect a negative sign, although POSIX allows +0.0. + See also . */ ASSERT (!!signbit (result) == !!signbit (minus_zerod)); /* glibc-2.3.6, mingw */ -#endif ASSERT (ptr == input + 10); ASSERT (errno == ERANGE); } + + /* Space before the exponent. */ { const char input[] = "1E 1000000"; char *ptr;