in reply to Re^5: unintentional conversion of signaling NaN to quiet NaN
in thread unintentional conversion of signaling NaN to quiet NaN
The problem is this definition of SvNVX from sv.h:
/* Need -0.0 for SvNVX to preserve IEEE FP "negative zero" because +0.0 + -0.0 => +0.0 but -0.0 + -0.0 => -0.0 */ # define SvIVX(sv) (0 + ((XPVIV*) SvANY(sv))->xiv_iv) # define SvUVX(sv) (0 + ((XPVUV*) SvANY(sv))->xuv_uv) # define SvNVX(sv) (-0.0 + ((XPVNV*) SvANY(sv))->xnv_u.xnv_nv)
Their attempts to "preserve IEEE FP "negative zero"", performs + -0.0, which will *always* force SNaN to QNaN.
That said, there is conditional code for the 'F' and 'D' templates in pp_pack.c that bypasses SvNV (which uses SvNVX() if SvNOK is set) in favour of sv_2nv(), which ought to kick in on mingw builds:
#ifdef __GNUC__ /* to work round a gcc/x86 bug; don't use SvNV */ anv.nv = sv_2nv(fromstr); #else anv.nv = SvNV(fromstr); #endif
But that conditional is not present in 'd' template.
And in any case, sv_2nv() goes right ahead and uses SvNVX() if SvNOKp is set anyway:
Perl_sv_2nv_flags(pTHX_ SV *const sv, const I32 flags) { dVAR; if (!sv) return 0.0; if (SvGMAGICAL(sv) || SvVALID(sv) || isREGEXP(sv)) { /* FBMs use the space for SvIVX and SvNVX for other purposes, and +use the same flag bit as SVf_IVisUV, so must not let them cache NVs +. Regexps have no SvIVX and SvNVX fields. */ const char *ptr; if (flags & SV_GMAGIC) mg_get(sv); if (SvNOKp(sv)) return SvNVX(sv);
so I don't quite see what purpose the conditional code above achieves ?
Bottom line: There is a bug -- or a combination of bugs -- that is preventing you getting your hands on an SNAN; but I don't think that it will be a quick fix.
Your best bet if you want to 'cure' the problem yourself is to bypass the Perl macros completely. The following won't work pre-5.10, and may not work on some later builds. (The latest version of 32-bit perl I have with inline installed is 5.8.9 and it doesn't work there.) And remember, if you touch the returned value with pack it will probably screw with it again. :
#! perl -slw use strict; use Config; use Inline C => Config => BUILD_NOISY => 1, CCFLAGS => $Config{ccflags +}." -DDEBUG=1"; use Inline C => <<'END_C', NAME => 'ICexample', CLEAN_AFTER_BUILD =>0 +; static const unsigned __int64 i = 0x7ff0000000000001; SV*get_snan() { SV *nv = newSVnv(0.0); *(unsigned __int64*)&( ((XPVNV*) SvANY(nv))->xnv_u.xnv_nv ) = i; return nv; } END_C sub doubleToHex { scalar reverse unpack 'h16', pack 'd', $_[0] } my $snan = get_snan(); printf "%f\n", $snan; print doubleToHex( $snan );
|
---|
Replies are listed 'Best First'. | |
---|---|
Re^7: unintentional conversion of signaling NaN to quiet NaN
by syphilis (Archbishop) on Jun 26, 2016 at 03:24 UTC | |
by BrowserUk (Patriarch) on Jun 26, 2016 at 08:15 UTC | |
by syphilis (Archbishop) on Jun 26, 2016 at 13:35 UTC | |
by BrowserUk (Patriarch) on Jun 26, 2016 at 14:00 UTC | |
by syphilis (Archbishop) on Jun 27, 2016 at 01:27 UTC | |
|