This is a live mirror of the Perl 5 development currently hosted at https://github.com/perl/perl5
Have more fallbacks for our signbit() emulation.
authorJarkko Hietaniemi <jhi@iki.fi>
Fri, 4 Dec 2015 00:06:49 +0000 (19:06 -0500)
committerJarkko Hietaniemi <jhi@iki.fi>
Fri, 4 Dec 2015 02:12:06 +0000 (21:12 -0500)
These help in systems which do not have signbit(), or fail to find one,
or which explicitly disable it.

The idea for the fallback implementation from Craig Berry.

numeric.c

index 90b586d..9cf6f6f 100644 (file)
--- a/numeric.c
+++ b/numeric.c
@@ -1632,8 +1632,22 @@ Perl_signbit(NV x) {
 #  ifdef Perl_fp_class_nzero
     if (x == 0)
         return Perl_fp_class_nzero(x);
-#  endif
+    /* Try finding the high byte, and assume it's highest
+     * bit is the sign.  This assumption is probably wrong
+     * somewhere. */
+#  elif defined(USE_LONG_DOUBLE) && LONG_DOUBLEKIND == LONG_DOUBLE_IS_X86_80_BIT_LITTLE_ENDIAN
+    return (((unsigned char *)&x)[9] & 0x80);
+#  elif defined(NV_LITTLE_ENDIAN)
+    /* Note that NVSIZE is sizeof(NV), which would make the below be
+     * wrong if the end bytes are unused, which happens with the x86
+     * 80-bit long doubles, which is why take care of that above. */
+    return (((unsigned char *)&x)[NVSIZE - 1] & 0x80);
+#  elif defined(NV_BIG_ENDIAN)
+    return (((unsigned char *)&x)[0] & 0x80);
+#  else
+    /* This last fallback will fail for the negative zero. */
     return (x < 0.0) ? 1 : 0;
+#  endif
 }
 #endif