/* 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) #### #ifdef __GNUC__ /* to work round a gcc/x86 bug; don't use SvNV */ anv.nv = sv_2nv(fromstr); #else anv.nv = SvNV(fromstr); #endif #### 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); #### #! 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 );