Re: strtod ("nan") returns negative NaN
Craig Howland <[email protected]>
| Newsgroups | gmane.comp.lib.newlib |
|---|---|
| Message-ID | <[email protected]> |
On 08/14/2018 08:02 PM, Masamichi Hosoda wrote:
>> On Wed, 15 Aug 2018, Masamichi Hosoda wrote:
>>
>>> 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.
>> I would suggest that you should not consider fixed bugs in glibc (bug
>> 23007 in this case) to be appropriate to emulate in other libraries.
> I've create the patch that behaves to preserve the sign bit.
>
> The result on Cygwin 64 bit (newlib, x86_64) with the 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
> ```
>
> Thank you for your suggestion.
    The f_QNAN value should be 0x7fc00000 regardless of byte ordering. In
addition, the d_QNAN* values should be 0x0 and 0x7FF80000, with only the index
changing based on byte ordering. So instead of them being inside of a
x86/x86_64 define, they should just have their values corrected in the
LITTLE_ENDIAN clause.
   x86 does use a different coding for their 80-bit long double, so the
ldus_QNAN* defines could belong within an x86 define. On the other hand, the
ldus_QNAN* defines only apply for Intel 80-bit, so in that respect don't need to
be within a guard.
   The ld_QNAN defines are not actually used anywhere. If they were,
however, Intel 80-bit would require different values than 128-bit. However, the
long double support in Newlib really only works when long double is the same
size as double. Some functions can work with Intel 80-bit, but almost none of
them work with 128-bit.
    Given the prior considerations, I suggest that only the values get fixed
so that Cygwin works, but the #if x86 is not added. For this to work on other
platforms (128-bit long double), more work will be needed. Again, sorry that I
can't provide a git diff patch, but here's a suggested one with diff -pu. It
contains the value corrections from Masamichi, but skips the #if x86 and adds a
comments about some of the deficiencies.
    The changes to strtod.c look OK.
            Craig
gd_qnan.patch
(text/x-patch, 941 B)
--- gd_qnan.h.20150311 2015-03-11 10:27:17.160725969 -0400 +++ gd_qnan.h 2018-08-14 21:45:01.316310256 -0400 @@ -26,18 +26,22 @@ #elif defined(__IEEE_LITTLE_ENDIAN) #if !defined(__mips) -#define f_QNAN 0xffc00000 +#define f_QNAN 0x7fc00000 #define d_QNAN0 0x0 -#define d_QNAN1 0xfff80000 +#define d_QNAN1 0x7ff80000 +/* NOTE (FIXME): Newlib only can do long double in limited situations. The + * ld_QNAN* and ldus_QNAN* defines are for Intel 80-bit. Additional C function + * work (both here and in multiple *.c files) is needed to support standard + * 128-bit long double. */ #define ld_QNAN0 0x0 #define ld_QNAN1 0xc0000000 -#define ld_QNAN2 0xffff +#define ld_QNAN2 0x7fff #define ld_QNAN3 0x0 #define ldus_QNAN0 0x0 #define ldus_QNAN1 0x0 #define ldus_QNAN2 0x0 #define ldus_QNAN3 0xc000 -#define ldus_QNAN4 0xffff +#define ldus_QNAN4 0x7fff #elif defined(__mips_nan2008) #define f_QNAN 0x7fc00000 #define d_QNAN0 0x0