2024-07-23 Bruno Haible <bruno@clisp.org>
+ strtold: Revisit underflow behaviour.
+ * doc/posix-functions/strtold.texi: Mention broken mingw 5.0. Mention
+ that gradual underflow does not count as an error on MSVC.
+ * tests/test-strtold.h (test_function): Add a gradual underflow test.
+ Check the sign in case of flush-to-zero underflow.
+
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.
This function returns a struct, not a @code{long double}, on some platforms:
HP-UX 11.31/hppa.
+@item
+This function always returns a wrong value on some platforms:
+mingw 5.0.
+
@item
This function allows whitespace between @samp{e} and the exponent on
some platforms:
HP-UX 11.31/ia64.
@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 underflow on some platforms:
@c https://cygwin.com/ml/cygwin/2019-12/msg00072.html
Cygwin 2.9.
Portability problems not fixed by Gnulib:
@itemize
+@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
ASSERT (errno == 0);
}
- /* Overflow/underflow. */
+ /* Overflow. */
{
const char input[] = "1E1000000";
char *ptr;
ASSERT (ptr == input + 10);
ASSERT (errno == ERANGE);
}
+
+ /* Gradual underflow, resulting in a denormalized number. */
+ {
+#if LDBL_MAX_EXP > 10000
+ const char input[] = "1e-4950";
+#else
+ const char input[] = "1e-320";
+#endif
+ char *ptr;
+ long double result;
+ errno = 0;
+ result = my_strtold (input, &ptr);
+ ASSERT (0.0L < result && result <= LDBL_MIN);
+ ASSERT (ptr == input + strlen (input));
+#if !defined _MSC_VER
+ ASSERT (errno == ERANGE);
+#endif
+ }
+ {
+#if LDBL_MAX_EXP > 10000
+ const char input[] = "-1e-4950";
+#else
+ const char input[] = "-1e-320";
+#endif
+ char *ptr;
+ long double result;
+ errno = 0;
+ result = my_strtold (input, &ptr);
+ ASSERT (-LDBL_MIN <= result && result < 0.0L);
+ ASSERT (ptr == input + strlen (input));
+#if !defined _MSC_VER
+ ASSERT (errno == ERANGE);
+#endif
+ }
+
+ /* Flush-to-zero underflow. */
{
const char input[] = "1E-100000";
char *ptr;
errno = 0;
result = my_strtold (input, &ptr);
ASSERT (-LDBL_MIN <= result && result <= 0.0L);
-#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.0L.
+ See also <https://sourceware.org/bugzilla/show_bug.cgi?id=5995>. */
ASSERT (!!signbit (result) == !!signbit (minus_zerol)); /* glibc-2.3.2, Haiku */
-#endif
ASSERT (ptr == input + 10);
ASSERT (errno == ERANGE);
}
+
+ /* Space before the exponent. */
{
const char input[] = "1E 1000000";
char *ptr;