summaryrefslogtreecommitdiff
path: root/numeric.c
diff options
context:
space:
mode:
authorJarkko Hietaniemi <jhi@iki.fi>2015-02-07 09:29:31 -0500
committerJarkko Hietaniemi <jhi@iki.fi>2015-02-08 21:54:49 -0500
commit6640aa2c3b93d7ac78e4e86983fe5948b3ca55f2 (patch)
treebc46de381b4ae809589d78615f81664e63a90d81 /numeric.c
parentb74dc0b3c96390d8bf83d8c3ffc0c2c2d1f0a5d3 (diff)
downloadperl-6640aa2c3b93d7ac78e4e86983fe5948b3ca55f2.tar.gz
infnan: add nan_signaling_set
Diffstat (limited to 'numeric.c')
-rw-r--r--numeric.c46
1 files changed, 46 insertions, 0 deletions
diff --git a/numeric.c b/numeric.c
index 16717aa412..c20c85e58d 100644
--- a/numeric.c
+++ b/numeric.c
@@ -583,6 +583,52 @@ Perl_nan_hibyte(NV *nvp, U8* mask)
}
/*
+=for apidoc nan_signaling_set
+
+Set or unset the NaN signaling-ness.
+
+Of those platforms that differentiate between quiet and signaling
+platforms the majority has the semantics of the most significant bit
+being on meaning quiet NaN, so for signaling we need to clear the bit.
+
+Some platforms (older MIPS, and HPPA) have the opposite
+semantics, and we set the bit for a signaling NaN.
+
+=cut
+*/
+void
+Perl_nan_signaling_set(NV *nvp, bool signaling)
+{
+ U8 mask;
+ U8* hibyte;
+
+ PERL_ARGS_ASSERT_NAN_SIGNALING_SET;
+
+ hibyte = nan_hibyte(nvp, &mask);
+ if (hibyte) {
+ const NV nan = NV_NAN;
+ /* Decent optimizers should make the irrelevant branch to disappear. */
+ if ((((U8*)&nan)[hibyte - (U8*)nvp] & mask)) {
+ /* x86 style: the most significant bit of the NaN is off
+ * for a signaling NaN, and on for a quiet NaN. */
+ if (signaling) {
+ *hibyte &= ~mask;
+ } else {
+ *hibyte |= mask;
+ }
+ } else {
+ /* MIPS/HPPA style: the most significant bit of the NaN is on
+ * for a signaling NaN, and off for a quiet NaN. */
+ if (signaling) {
+ *hibyte |= mask;
+ } else {
+ *hibyte &= ~mask;
+ }
+ }
+ }
+}
+
+/*
=for apidoc grok_infnan
Helper for grok_number(), accepts various ways of spelling "infinity"