This is the mail archive of the newlib@sourceware.org mailing list for the newlib project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

Re: strtod ("nan") returns negative NaN


On 08/14/2018 11:05 AM, Masamichi Hosoda wrote:
Hi

I've found that strtod ("nan") returns negative NaN on Cygwin 64 bit.
https://cygwin.com/ml/cygwin/2018-08/msg00168.html

On Linux with glibc, both strtod ("nan")
and strtod ("-nan") return positive NaN.

So I've created the patch that behaves like glibc.
Both strtod ("nan") and strtod ("-nan") return positive NaN.

Sample code:
```
#include <stdio.h>
#include <stdlib.h>

int main (void)
{
   printf ("strtof (\"nan\", NULL) = %f\n", strtof ("nan", NULL));
   printf ("strtof (\"-nan\", NULL) = %f\n", strtof ("-nan", NULL));
   printf ("strtod (\"nan\", NULL) = %f\n", strtod ("nan", NULL));
   printf ("strtod (\"-nan\", NULL) = %f\n", strtod ("-nan", NULL));
   printf ("strtold (\"nan\", NULL) = %Lf\n", strtold ("nan", NULL));
   printf ("strtold (\"-nan\", NULL) = %Lf\n", strtold ("-nan", NULL));
}
```

The result of Cygwin (newlib) without my patch:
```
strtof ("nan", NULL) = nan
strtof ("-nan", NULL) = nan
strtod ("nan", NULL) = -nan
strtod ("-nan", NULL) = nan
strtold ("nan", NULL) = -nan
strtold ("-nan", NULL) = -nan
```
...

Thanks.
The Newlib math functions generally do support signed NANs.  The C standard says (in section 5.2.4.2.2 Characteristics of floating types <float.h>) NANs can be treated as having a sign or not.  But since the math library does support signed NANs, the proper behavior for the strtox() functions would be to listen to the sign rather than ignoring it.  So while the current Cygwin 64 behavior is clearly incorrect, the given patch needs to be adjusted to listen to sign.

(It can be seen that the math functions support signed NANs by looking, for example, at s_copysign.c.  it blindly copies the sign without checking the type of the arguments.  The standard requires requests to set sign to be ignored when NANs are not treated as having signs.)

I cannot generate git diffs at this time (corporate firewall), but here is how I think strtof() would need to be fixed after strtod() is:

$ diff -pu strtod.c.20180420 strtod.c
--- strtod.c.20180420    2018-04-20 10:32:36.974479745 -0400
+++ strtod.c    2018-08-14 13:27:57.958177691 -0400
@@ -1285,7 +1285,7 @@ strtof_l (const char *__restrict s00, ch
 {
   double val = _strtod_l (_REENT, s00, se, loc);
   if (isnan (val))
-    return nanf (NULL);
+    return copysign( nanf (NULL), signbit(val) ? -1.0f : 1.0f);
   float retval = (float) val;
 #ifndef NO_ERRNO
   if (isinf (retval) && !isinf (val))
@@ -1300,7 +1300,7 @@ strtof (const char *__restrict s00,
 {
   double val = _strtod_l (_REENT, s00, se, __get_current_locale ());
   if (isnan (val))
-    return nanf (NULL);
+    return copysign( nanf (NULL), signbit(val) ? -1.0f : 1.0f);
   float retval = (float) val;
 #ifndef NO_ERRNO
   if (isinf (retval) && !isinf (val))


By the way, here are the results of the test prints from an embedded 64-bit ARM:

strtof ("nan", NULL) = 0.000000
strtof ("-nan", NULL) = 0.000000
strtod ("nan", NULL) = nan
strtod ("-nan", NULL) = nan
strtold ("nan", NULL) = inf
strtold ("-nan", NULL) = 2315841784746322880031071374419981810209660594968745666
57923565917084799991808.000000

Craig


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]