diff options
author | Jarkko Hietaniemi <jhi@iki.fi> | 2015-12-03 19:06:49 -0500 |
---|---|---|
committer | Steve Hay <steve.m.hay@googlemail.com> | 2015-12-07 00:42:45 +0000 |
commit | 13353b81126c1ad697c0450811a5d5c47eed896e (patch) | |
tree | 0ba3d9a68bf078a50960d6c740fc726aa18c998b | |
parent | 51b08a51ddedbde437e8f79b55ab9f6313b0c58a (diff) | |
download | perl-13353b81126c1ad697c0450811a5d5c47eed896e.tar.gz |
Have more fallbacks for our signbit() emulation.
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.
(cherry picked from commit 572cd85091706ffa2e19db60c41c6bb106297e3a)
-rw-r--r-- | numeric.c | 16 |
1 files changed, 15 insertions, 1 deletions
@@ -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 |