/* 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 );