In perl.git, the branch blead has been updated <http://perl5.git.perl.org/perl.git/commitdiff/2bb3725dfe9edb3ec056dbc691826cda14d85a48?hp=db8b8c75c9ae410a0e47828e501550fa4f47e811>
- Log ----------------------------------------------------------------- commit 2bb3725dfe9edb3ec056dbc691826cda14d85a48 Author: Jarkko Hietaniemi <j...@iki.fi> Date: Tue Aug 19 18:44:30 2014 -0400 Add todo comment about special hexfp values. M sv.c commit 6094cb95350921efd1cc9550c3c5dfedefa580cb Author: Jarkko Hietaniemi <j...@iki.fi> Date: Tue Aug 19 22:16:54 2014 -0400 Quadruple float BE test triggering had a typo. M t/op/sprintf2.t commit 0096dfabfd24cd5a57ff81d61186b2ffc50dbb6d Author: Jarkko Hietaniemi <j...@iki.fi> Date: Mon Aug 18 12:56:51 2014 -0400 Reduce double-double %a to single-double for now. How to exactly handle the second double is unknown, so for now extract the mantissa bits only from the first double. (Known platforms aix-ppc and linux-ppc.) M sv.c M t/op/sprintf2.t commit 288741806892d643315f5aac944e9ca60aad2171 Author: Jarkko Hietaniemi <j...@iki.fi> Date: Mon Aug 18 17:04:06 2014 -0400 double-double needs the first mantissa bits of doubles. M sv.c commit e85ae363ea55e756d30efca06216f575419e9b9c Author: Jarkko Hietaniemi <j...@iki.fi> Date: Mon Aug 18 15:27:58 2014 -0400 Modify the hexfp exponent explicitly in each long double case. M sv.c commit 08780b356b3dfd25eb8df7d19c3f4af4a3511cb6 Author: Jarkko Hietaniemi <j...@iki.fi> Date: Mon Aug 18 08:13:18 2014 -0400 Comment: scan_num also handles hexadecimal floats now. M toke.c ----------------------------------------------------------------------- Summary of changes: sv.c | 119 ++++++++++++++++++++++++++++++++++++-------------------- t/op/sprintf2.t | 52 ++++++++++++------------- toke.c | 7 ++-- 3 files changed, 106 insertions(+), 72 deletions(-) diff --git a/sv.c b/sv.c index 44f816b..92c34a8 100644 --- a/sv.c +++ b/sv.c @@ -10610,14 +10610,16 @@ S_hextract(pTHX_ const NV nv, int* exponent, U8* vhex, U8* vend) * repetitions below, but usually only one (or sometimes two) * of them is really being used. */ /* HEXTRACT_OUTPUT() extracts the high nybble first. */ -#define HEXTRACT_OUTPUT() \ +#define HEXTRACT_OUTPUT_HI(ix) (*v++ = nvp[ix] >> 4) +#define HEXTRACT_OUTPUT_LO(ix) (*v++ = nvp[ix] & 0xF) +#define HEXTRACT_OUTPUT(ix) \ STMT_START { \ - *v++ = nvp[ix] >> 4; \ - *v++ = nvp[ix] & 0xF; \ + HEXTRACT_OUTPUT_HI(ix); \ + HEXTRACT_OUTPUT_LO(ix); \ } STMT_END -#define HEXTRACT_COUNT() \ +#define HEXTRACT_COUNT(ix, c) \ STMT_START { \ - v += 2; \ + v += c; \ if (ix < ixmin) \ ixmin = ix; \ else if (ix > ixmax) \ @@ -10644,10 +10646,11 @@ S_hextract(pTHX_ const NV nv, int* exponent, U8* vhex, U8* vend) HEXTRACT_IMPLICIT_BIT(); for (ix = 13; ix >= 0; ix--) { if (vend) - HEXTRACT_OUTPUT(); + HEXTRACT_OUTPUT(ix); else - HEXTRACT_COUNT(); + HEXTRACT_COUNT(ix, 2); } + *exponent -= 4; # elif LONG_DOUBLEKIND == LONG_DOUBLE_IS_IEEE_754_128_BIT_BIG_ENDIAN /* Used in e.g. Solaris Sparc and HP-UX PA-RISC, e.g. -0.1L: * bf fb 99 99 99 99 99 99 99 99 99 99 99 99 99 9a */ @@ -10656,10 +10659,11 @@ S_hextract(pTHX_ const NV nv, int* exponent, U8* vhex, U8* vend) HEXTRACT_IMPLICIT_BIT(); for (ix = 2; ix <= 15; ix++) { if (vend) - HEXTRACT_OUTPUT(); + HEXTRACT_OUTPUT(ix); else - HEXTRACT_COUNT(); + HEXTRACT_COUNT(ix, 2); } + *exponent -= 4; # elif LONG_DOUBLEKIND == LONG_DOUBLE_IS_X86_80_BIT_LITTLE_ENDIAN /* x86 80-bit "extended precision", 64 bits of mantissa / fraction / * significand, 15 bits of exponent, 1 bit of sign. NVSIZE can @@ -10669,64 +10673,86 @@ S_hextract(pTHX_ const NV nv, int* exponent, U8* vhex, U8* vend) /* There explicitly is *no* implicit bit in this case. */ for (ix = 7; ix >= 0; ix--) { if (vend) - HEXTRACT_OUTPUT(); + HEXTRACT_OUTPUT(ix); else - HEXTRACT_COUNT(); + HEXTRACT_COUNT(ix, 2); } + *exponent -= 4; # elif LONG_DOUBLEKIND == LONG_DOUBLE_IS_X86_80_BIT_BIG_ENDIAN /* The last 8 bytes are the mantissa/fraction. * (does this format ever happen?) */ /* There explicitly is *no* implicit bit in this case. */ for (ix = LONGDBLSIZE - 8; ix < LONGDBLSIZE; ix++) { if (vend) - HEXTRACT_OUTPUT(); + HEXTRACT_OUTPUT(ix); else - HEXTRACT_COUNT(); + HEXTRACT_COUNT(ix, 2); } + *exponent -= 4; # elif LONG_DOUBLEKIND == LONG_DOUBLE_IS_DOUBLEDOUBLE_128_BIT_LITTLE_ENDIAN /* Where is this used? - * - * Guessing that the format would be the reverse - * of big endian, i.e. for -0.1L: - * 9a 99 99 99 99 99 59 3c 9a 99 99 99 99 99 b9 bf */ + * 9a 99 99 99 99 99 59 bc 9a 99 99 99 99 99 b9 3f */ HEXTRACT_IMPLICIT_BIT(); + if (vend) + HEXTRACT_OUTPUT_LO(14); + else + HEXTRACT_COUNT(14, 1); for (ix = 13; ix >= 8; ix--) { if (vend) - HEXTRACT_OUTPUT(); + HEXTRACT_OUTPUT(ix); else - HEXTRACT_COUNT(); + HEXTRACT_COUNT(ix, 2); } + /* XXX not extracting from the second double -- see the discussion + * below for the big endian double double. */ +# if 0 + if (vend) + HEXTRACT_OUTPUT_LO(6); + else + HEXTRACT_COUNT(6, 1); for (ix = 5; ix >= 0; ix--) { if (vend) - HEXTRACT_OUTPUT(); + HEXTRACT_OUTPUT(ix); else - HEXTRACT_COUNT(); + HEXTRACT_COUNT(ix, 2); } +# endif + (*exponent)--; # elif LONG_DOUBLEKIND == LONG_DOUBLE_IS_DOUBLEDOUBLE_128_BIT_BIG_ENDIAN /* Used in e.g. PPC/Power (AIX) and MIPS. * - * The mantissa bits are in two separate stretches, - * e.g. for -0.1L: - * bf b9 99 99 99 99 99 9a 3c 59 99 99 99 99 99 9a - * - * Note that this blind copying might be considered not to be - * the right thing, since the first double already does - * rounding (0x9A as opposed to 0x99). But then again, we - * probably should just copy the bits as they are? + * The mantissa bits are in two separate stretches, e.g. for -0.1L: + * 3f b9 99 99 99 99 99 9a bc 59 99 99 99 99 99 9a */ HEXTRACT_IMPLICIT_BIT(); + if (vend) + HEXTRACT_OUTPUT_LO(1); + else + HEXTRACT_COUNT(1, 1); for (ix = 2; ix < 8; ix++) { if (vend) - HEXTRACT_OUTPUT(); + HEXTRACT_OUTPUT(ix); else - HEXTRACT_COUNT(); - } + HEXTRACT_COUNT(ix, 2); + } + /* XXX not extracting the second double mantissa bits- this is not + * right nor ideal (we effectively reduce the output format to + * that of a "single double", only 53 bits), but we do not know + * exactly how to do the extraction correctly so that it matches + * the semantics of, say, the IEEE quadruple float. */ +# if 0 + if (vend) + HEXTRACT_OUTPUT_LO(9); + else + HEXTRACT_COUNT(9, 1); for (ix = 10; ix < 16; ix++) { if (vend) - HEXTRACT_OUTPUT(); + HEXTRACT_OUTPUT(ix); else - HEXTRACT_COUNT(); + HEXTRACT_COUNT(ix, 2); } +# endif + (*exponent)--; # else Perl_croak(aTHX_ "Hexadecimal float: unsupported long double format"); @@ -10777,17 +10803,17 @@ S_hextract(pTHX_ const NV nv, int* exponent, U8* vhex, U8* vend) /* Little endian. */ for (ix = limit_byte; ix >= 0; ix--) { if (vend) - HEXTRACT_OUTPUT(); + HEXTRACT_OUTPUT(ix); else - HEXTRACT_COUNT(); + HEXTRACT_COUNT(ix, 2); } # else /* Big endian. */ for (ix = MANTISSASIZE - 1 - limit_byte; ix < MANTISSASIZE; ix++) { if (vend) - HEXTRACT_OUTPUT(); + HEXTRACT_OUTPUT(ix); else - HEXTRACT_COUNT(); + HEXTRACT_COUNT(ix, 2); } # endif /* If there are not enough bits in MANTISSATYPE, we couldn't get @@ -11825,7 +11851,15 @@ Perl_sv_vcatpvfn_flags(pTHX_ SV *const sv, const char *const pat, const STRLEN p * human-readable xdigits. */ const char* xdig = PL_hexdigit; int zerotail = 0; /* how many extra zeros to append */ - int exponent; /* exponent of the floating point input */ + int exponent = 0; /* exponent of the floating point input */ + + /* XXX: denormals, NaN, Inf. + * + * For example with denormals, (assuming the vanilla + * 64-bit double): the exponent is zero. 1xp-1074 is + * the smallest denormal and the smallest double, it + * should be output as 0x0.0000000000001p-1022 to + * match its internal structure. */ vend = S_hextract(aTHX_ nv, &exponent, vhex, NULL); S_hextract(aTHX_ nv, &exponent, vhex, vend); @@ -11862,9 +11896,10 @@ Perl_sv_vcatpvfn_flags(pTHX_ SV *const sv, const char *const pat, const STRLEN p } } - /* Adjust the exponent so that the first output - * xdigit aligns with the 4-bit nybbles. */ - exponent -= NV_MANT_DIG % 4 ? NV_MANT_DIG % 4 : 4; +#if NVSIZE == DOUBLESIZE + /* For long doubles S_hextract() took care of this. */ + exponent--; +#endif if (precis > 0) { v = vhex + precis + 1; diff --git a/t/op/sprintf2.t b/t/op/sprintf2.t index 0969d58..4969abf 100644 --- a/t/op/sprintf2.t +++ b/t/op/sprintf2.t @@ -132,9 +132,8 @@ if ($Config{nvsize} == 8 && # IEEE 754 128-bit ("quadruple precision"), e.g. IA-64 (Itanium) in VMS $Config{nvsize} == 16 && # 9a 99 99 99 99 99 99 99 99 99 99 99 99 99 fb 3f (LE), pack F is the NV - # (compare this with "double-double") (pack("F", 0.1) =~ /^\x9A\x99{6}/ || # LE - pack("F", 0.1) =~ /\x99{6}x9A$/) # BE + pack("F", 0.1) =~ /\x99{6}\x9A$/) # BE ) { @hexfloat = ( [ '%a', '0', '0x1p-1' ], @@ -186,14 +185,13 @@ if ($Config{nvsize} == 8 && } elsif ( # "double-double", two 64-bit doubles end to end $Config{nvsize} == 16 && - # bf b9 99 99 99 99 99 9a 3c 59 99 99 99 99 99 9a (BE), pack F is the NV - # (compare this with "quadruple precision") - (pack("F", 0.1) =~ /^\x9A\x99{5}\x59\x3C/ || # LE - pack("F", 0.1) =~ /\x3C\x59\x99{5}\x9A$/) # BE + # bf b9 99 99 99 99 99 9a bc 59 99 99 99 99 99 9a (BE), pack F is the NV + (pack("F", 0.1) =~ /^\x9A\x99{5}\x59\xBC/ || # LE + pack("F", 0.1) =~ /\xBC\x59\x99{5}\x9A$/) # BE ) { - # XXX these values are probably slightly wrong, even if - # the double-double extraction code gets fixed, the exact - # truncation/rounding effects are unknown. + # XXX these values are actually only "single-double" since + # we currently do not know how to exactly handle the second + # double. See the discussion in sv.c:S_hextract(). @hexfloat = ( [ '%a', '0', '0x1p-1' ], [ '%a', '1', '0x1p+0' ], @@ -201,16 +199,16 @@ if ($Config{nvsize} == 8 && [ '%a', '0.5', '0x1p-1' ], [ '%a', '0.25', '0x1p-2' ], [ '%a', '0.75', '0x1.8p-1' ], - [ '%a', '3.14', '0x1.91eb851eb851eb851eb851eb852p+1' ], + [ '%a', '3.14', '0x1.91eb851eb851fp+1' ], [ '%a', '-1', '-0x1p+0' ], - [ '%a', '-3.14', '-0x1.91eb851eb851eb851eb851eb852p+1' ], - [ '%a', '0.1', '0x1.99999999999999999999999999ap-4' ], - [ '%a', '1/7', '0x1.249249249249249249249249249p-3' ], - [ '%a', 'sqrt(2)', '0x1.6a09e667f3bcc908b2fb1366ea9p+0' ], - [ '%a', 'exp(1)', '0x1.5bf0a8b1457695355fb8ac404e8p+1' ], + [ '%a', '-3.14', '-0x1.91eb851eb851fp+1' ], + [ '%a', '0.1', '0x1.999999999999ap-4' ], + [ '%a', '1/7', '0x1.2492492492492p-3' ], + [ '%a', 'sqrt(2)', '0x1.6a09e661366ebp+0' ], + [ '%a', 'exp(1)', '0x1.5bf0a8b145769p+1' ], [ '%a', '2**-10', '0x1p-10' ], [ '%a', '2**10', '0x1p+10' ], - [ '%a', '1e-09', '0x1.12e0be826d694b2e62d01511f13p-30' ], + [ '%a', '1e-09', '0x1.12e0be826d695p-30' ], [ '%a', '1e9', '0x1.dcd65p+29' ], [ '%#a', '1', '0x1.p+0' ], @@ -219,27 +217,27 @@ if ($Config{nvsize} == 8 && [ '% a', '1', ' 0x1p+0' ], [ '% a', '-1', '-0x1p+0' ], - [ '%8a', '3.14', '0x1.91eb851eb851eb851eb851eb852p+1' ], - [ '%13a', '3.14', '0x1.91eb851eb851eb851eb851eb852p+1' ], - [ '%20a', '3.14', '0x1.91eb851eb851eb851eb851eb852p+1' ], + [ '%8a', '3.14', '0x1.91eb851eb851fp+1' ], + [ '%13a', '3.14', '0x1.91eb851eb851fp+1' ], + [ '%20a', '3.14', '0x1.91eb851eb851fp+1' ], [ '%.4a', '3.14', '0x1.91ecp+1' ], [ '%.5a', '3.14', '0x1.91eb8p+1' ], [ '%.6a', '3.14', '0x1.91eb85p+1' ], - [ '%.20a', '3.14', '0x1.91eb851eb851eb851eb8p+1' ], + [ '%.20a', '3.14', '0x1.91eb851eb851f0000000p+1' ], [ '%20.10a', '3.14', ' 0x1.91eb851eb8p+1' ], - [ '%20.15a', '3.14', '0x1.91eb851eb851eb8p+1' ], + [ '%20.15a', '3.14', '0x1.91eb851eb851f00p+1' ], [ '% 20.10a', '3.14', ' 0x1.91eb851eb8p+1' ], [ '%020.10a', '3.14', '0x0001.91eb851eb8p+1' ], - [ '%30a', '3.14', '0x1.91eb851eb851eb851eb851eb852p+1' ], - [ '%-30a', '3.14', '0x1.91eb851eb851eb851eb851eb852p+1' ], - [ '%030a', '3.14', '0x1.91eb851eb851eb851eb851eb852p+1' ], - [ '%-030a', '3.14', '0x1.91eb851eb851eb851eb851eb852p+1' ], + [ '%30a', '3.14', ' 0x1.91eb851eb851fp+1' ], + [ '%-30a', '3.14', '0x1.91eb851eb851fp+1 ' ], + [ '%030a', '3.14', '0x00000000001.91eb851eb851fp+1' ], + [ '%-030a', '3.14', '0x1.91eb851eb851fp+1 ' ], [ '%.40a', '3.14', - '0x1.91eb851eb851eb851eb851eb8520000000000000p+1' ], + '0x1.91eb851eb851f000000000000000000000000000p+1' ], - [ '%A', '3.14', '0X1.91EB851EB851EB851EB851EB852P+1' ], + [ '%A', '3.14', '0X1.91EB851EB851FP+1' ], ); } else { print "# no hexfloat tests\n"; diff --git a/toke.c b/toke.c index 0f0641f..be4c8a5 100644 --- a/toke.c +++ b/toke.c @@ -9781,9 +9781,10 @@ S_scan_str(pTHX_ char *start, int keep_bracketed_quoted, int keep_delims, int re \d(_?\d)*(\.(\d(_?\d)*)?)?[Ee][\+\-]?(\d(_?\d)*) 12 12.34 12. \.\d(_?\d)*[Ee][\+\-]?(\d(_?\d)*) .34 - 0b[01](_?[01])* - 0[0-7](_?[0-7])* - 0x[0-9A-Fa-f](_?[0-9A-Fa-f])* + 0b[01](_?[01])* binary integers + 0[0-7](_?[0-7])* octal integers + 0x[0-9A-Fa-f](_?[0-9A-Fa-f])* hexadecimal integers + 0x[0-9A-Fa-f](_?[0-9A-Fa-f])*(?:\.\d*)?p[+-]?[0-9]+ hexadecimal floats Like most scan_ routines, it uses the PL_tokenbuf buffer to hold the thing it reads. -- Perl5 Master Repository