diff options
author | Jarkko Hietaniemi <jhi@iki.fi> | 2015-02-07 09:29:31 -0500 |
---|---|---|
committer | Jarkko Hietaniemi <jhi@iki.fi> | 2015-02-08 21:54:49 -0500 |
commit | 6640aa2c3b93d7ac78e4e86983fe5948b3ca55f2 (patch) | |
tree | bc46de381b4ae809589d78615f81664e63a90d81 /numeric.c | |
parent | b74dc0b3c96390d8bf83d8c3ffc0c2c2d1f0a5d3 (diff) | |
download | perl-6640aa2c3b93d7ac78e4e86983fe5948b3ca55f2.tar.gz |
infnan: add nan_signaling_set
Diffstat (limited to 'numeric.c')
-rw-r--r-- | numeric.c | 46 |
1 files changed, 46 insertions, 0 deletions
@@ -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" |