Bruno Haible <bruno <at> clisp.org> writes: > Ack. It's a bug in the isnanl module. > > > I'm not sure how to fix this, but it seems like rpl_isnanl needs to check for > > invalid x86 long double bit patterns before falling back to ==. > > Either this, or ensure that the "checking where to find the exponent" tests > return the bit positions instead of "unknown". > > But I don't see how to implement either of these two possible fixes for a > cross-compiler, in a way that works also for other platforms than mingw. > Any ideas?
Here's one idea. Since it fixes the mingw cross-compilation failure of test- isnanl-nolibm, I'm installing it; if we come up with something better or more efficient in the future, we can alter the test then. The idea behind this patch is that = doesn't alter the bit pattern of an invalid representation that sneaks past the == check, but +0 will result in a normalized bit pattern, so that the memcmp can then filter out pseudo- denormals. For all valid bit patterns, the == already filtered out NaN, so adding +0.0 is a no-op to the bit pattern. Here's a snippet of my gdb session on mingw that shows this point (where sizeof(long double) is 12): 142 if (x == x) (gdb) n 149 m1.value = x; (gdb) n 150 m2.value = x + 0; (gdb) x/3w &x 0x22ff50: 0x00000000 0x83333333 0x00000000 (gdb) x/3w &m1 0x22ff30: 0x00000000 0x83333333 0x00000000 (gdb) x/3w &m2 0x22ff20: 0x00000000 0x83333333 0x00000001 From: Eric Blake <[EMAIL PROTECTED]> Date: Tue, 11 Dec 2007 11:35:55 -0700 Subject: [PATCH] Detect pseudo-denormals on x86 even when cross-compiling. * lib/isnan.c (rpl_isnanl) [!KNOWN_EXPBIT0_LOCATION && USE_LONG_DOUBLE && x86]: Add one more check to filter out invalid bit patterns that happen to satisfy ==. Signed-off-by: Eric Blake <[EMAIL PROTECTED]> --- ChangeLog | 5 +++++ lib/isnan.c | 14 +++++++++++++- 2 files changed, 18 insertions(+), 1 deletions(-) diff --git a/ChangeLog b/ChangeLog index ed8799b..127f9a5 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,5 +1,10 @@ 2007-12-11 Eric Blake <[EMAIL PROTECTED]> + Detect pseudo-denormals on x86 even when cross-compiling. + * lib/isnan.c (rpl_isnanl) [!KNOWN_EXPBIT0_LOCATION + && USE_LONG_DOUBLE && x86]: Add one more check to filter out + invalid bit patterns that happen to satisfy ==. + Avoid link failures with separate libtests.a. * gnulib-tool (func_emit_tests_Makefile_am): Also list local_ldadd last, to satisfy circular dependencies. diff --git a/lib/isnan.c b/lib/isnan.c index 4add6a2..182a7bd 100644 --- a/lib/isnan.c +++ b/lib/isnan.c @@ -140,7 +140,19 @@ FUNC (DOUBLE x) /* The configuration did not find sufficient information. Give up about the signaling NaNs, handle only the quiet NaNs. */ if (x == x) - return 0; + { +# if defined USE_LONG_DOUBLE && ((defined __ia64 && LDBL_MANT_DIG == 64) || (defined __x86_64__ || defined __amd64__) || (defined __i386 || defined __i386__ || defined _I386 || defined _M_IX86 || defined _X86_)) + /* Detect any special bit patterns that pass ==; see comment above. */ + memory_double m1; + memory_double m2; + + m1.value = x; + m2.value = x + 0; + if (memcmp (&m1.value, &m2.value, SIZE) != 0) + return 1; +# endif + return 0; + } else return 1; #endif -- 1.5.3.5