summaryrefslogtreecommitdiff
path: root/numeric.c
diff options
context:
space:
mode:
authorJarkko Hietaniemi <jhi@iki.fi>2015-02-07 15:47:59 -0500
committerJarkko Hietaniemi <jhi@iki.fi>2015-02-08 21:54:51 -0500
commit29b62199cd4c359dfc6b9d690341de40d105ca5f (patch)
tree5b77ffb142d6ed7178770150055ebd9327e93471 /numeric.c
parentbe181dc9d91c84a2fe03912c993c8259fed92641 (diff)
downloadperl-29b62199cd4c359dfc6b9d690341de40d105ca5f.tar.gz
infnan: the x86 80-bit extended precision is special
Diffstat (limited to 'numeric.c')
-rw-r--r--numeric.c33
1 files changed, 30 insertions, 3 deletions
diff --git a/numeric.c b/numeric.c
index 88770b7a0a..18ee1b93bd 100644
--- a/numeric.c
+++ b/numeric.c
@@ -547,6 +547,26 @@ Perl_grok_numeric_radix(pTHX_ const char **sp, const char *send)
return FALSE;
}
+/* x86 80-bit extended precision mantissa bits:
+ *
+ * 63 62 61 30387+ pre-387
+ * -------- ---- --------
+ * 0 0 0 invalid infinity
+ * 0 0 n invalid snan
+ * 0 1 * invalid snan
+ * 1 0 0 infinity snan
+ * 1 0 n snan
+ * 1 1 0 qnan (1.#IND)
+ * 1 1 n qnan
+ *
+ * This means that there are 61 bits for nan payload.
+ */
+#if defined(USE_LONG_DOUBLE) && (LONG_DOUBLEKIND == LONG_DOUBLE_IS_X86_80_BIT_LITTLE_ENDIAN)
+# define NV_NAN_BITS 61
+#else
+# define NV_NAN_BITS (NV_MANT_REAL_DIG - 1)
+#endif
+
/*
=for apidoc nan_hibyte
@@ -569,11 +589,18 @@ U8*
Perl_nan_hibyte(NV *nvp, U8* mask)
{
STRLEN i = (NV_MANT_REAL_DIG - 1) / 8;
- STRLEN j = (NV_MANT_REAL_DIG - 1) % 8;
PERL_ARGS_ASSERT_NAN_HIBYTE;
- *mask = 1 << j;
+#if defined(USE_LONG_DOUBLE) && (LONG_DOUBLEKIND == LONG_DOUBLE_IS_X86_80_BIT_LITTLE_ENDIAN)
+ /* See the definition of NV_NAN_BITS. */
+ *mask = 1 << 6;
+#else
+ {
+ STRLEN j = (NV_MANT_REAL_DIG - 1) % 8;
+ *mask = 1 << j;
+ }
+#endif
#ifdef NV_BIG_ENDIAN
return (U8*) nvp + NVSIZE - 1 - i;
#endif
@@ -699,7 +726,7 @@ Perl_nan_payload_set(pTHX_ NV *nvp, const void *bytes, STRLEN byten, bool signal
* signaling NaNs.
*
* C99 nan() is supposed to generate quiet NaNs. */
- int bits = NV_MANT_REAL_DIG - 1;
+ int bits = NV_NAN_BITS;
STRLEN i, nvi;
bool error = FALSE;