__builtin_isnanl() and invalid x87 80-bit floating point numbers
Liu Hao
lh_mouse@126.com
Sat May 13 03:06:00 GMT 2017
On 2017/5/13 10:25, Vincent Lefevre wrote:
> On 2017-05-12 23:46:09 +0800, Liu Hao wrote:
> But if you do this, you're out of scope of the standards.
>
> Moreover, I suppose that you will also get a floating-point exception
> on a signaling NaN, in which case, on this example, this isn't
> distinguishable from a signaling NaN.
A QNaN doesn't generate an exception regardless of the x87 control word.
To make a QNaN, replace the last three bytes of `data` with `0xc0, 0xff,
0x7f`. The last example would then exit normally with the output 'nan'.
I will show an example later.
> But the goal of Intel's x87 80-bit format and the IEEE 754-1985 spec
> was to regard this format as a conforming double-extended format.
> And AFAIK, the intent of IEEE 754-2008 was not to break this.
>
>> I don't think ISO C forbids existence of `trap representation` of
>> `long double`.
>
> Anyway, this is not a trap representation as shown above.
It does generate an exception so why do you think it is not a trap
representation?
> FXAM is neither an IEEE 754 operation, nor an ISO C operation.
>
> Let's try ==, which corresponds to the IEEE 754 equality operator:
>
> #include <stdio.h>
>
> int main (void)
> {
> long double ld = 0;
> unsigned char data[10] = {
> 0x5b, 0x01, 0x04, 0x5e, 0x85, 0x00, 0x00, 0x00, 0xd8, 0x59
> };
> __builtin_memcpy(&ld, data, 10);
> printf ("NaN? %s\n", ld == ld ? "no" : "yes");
> return 0;
> }
>
> This gives:
>
> NaN? yes
>
> So, it is regarded as a NaN.
>
Let's try `=` which corresponds to the IEEE 754 equality operator too:
-------------------------------------------------------
lh_mouse@lhmouse-dev:~$ cat test.c
#include <stdio.h>
#include <math.h>
int main (void)
{
unsigned short fcw;
__asm__ volatile (
"fstcw %0; "
"andw $-2, %0; "
"fldcw %0; "
: "=m"(fcw)
);
long double ld = 0;
unsigned char data[10] = {
0x5b, 0x01, 0x04, 0x5e, 0x85, 0x00, 0x00, 0x00, 0xd8, 0x59
};
__builtin_memcpy(&ld, data, 10);
long double y = 1;
y = ld;
printf ("%Lg\n", y);
return 0;
}
lh_mouse@lhmouse-dev:~$ gcc test.c -Wall -Wextra -pedantic -std=c99
lh_mouse@lhmouse-dev:~$ ./a.out
5.11212e+1984
-------------------------------------------------------
Then replace it with a QNaN:
-------------------------------------------------------
lh_mouse@lhmouse-dev:~$ sed -i 's/0x00, 0xd8, 0x59/0xc0, 0xff, 0x7f/' test.c
lh_mouse@lhmouse-dev:~$ gcc test.c -Wall -Wextra -pedantic -std=c99
lh_mouse@lhmouse-dev:~$ ./a.out
nan
-------------------------------------------------------
Then replace it with a SNaN:
-------------------------------------------------------
lh_mouse@lhmouse-dev:~$ gcc test.c -Wall -Wextra -pedantic -std=c99
lh_mouse@lhmouse-dev:~$ ./a.out
nan
-------------------------------------------------------
So, it is not regarded as a NaN.
--
Best regards,
LH_Mouse
More information about the Gcc-help
mailing list