diff options
author | Jarkko Hietaniemi <jhi@iki.fi> | 2015-11-07 14:38:21 -0500 |
---|---|---|
committer | Jarkko Hietaniemi <jhi@iki.fi> | 2015-11-07 17:49:49 -0500 |
commit | 96524c28e76cdc1099eebc2832aef5b789ebbc11 (patch) | |
tree | 0259ac2f369cfa41e8e5f55ce63ac14c4fa7c00a | |
parent | 0c8adad77d308bd7d386922521a57b894a2bf959 (diff) | |
download | perl-96524c28e76cdc1099eebc2832aef5b789ebbc11.tar.gz |
perl #126586 hexfp may lose 1-3 low order bits (most often, 1)
-rw-r--r-- | t/op/hexfp.t | 34 | ||||
-rw-r--r-- | toke.c | 25 |
2 files changed, 57 insertions, 2 deletions
diff --git a/t/op/hexfp.t b/t/op/hexfp.t index e83050e348..c9f9e39cbd 100644 --- a/t/op/hexfp.t +++ b/t/op/hexfp.t @@ -10,7 +10,7 @@ use strict; use Config; -plan(tests => 85); +plan(tests => 97); # Test hexfloat literals. @@ -187,9 +187,39 @@ SKIP: eval '$a = 0x111.00000000000000p+0'; # 14 zeros. like(get_warn(), qr/^Hexadecimal float: mantissa overflow/); is($a, 273); + + undef $a; + eval '$a = 0xfffffffffffffp0'; # 52 bits. + is(get_warn(), undef); + is($a, 4.5035996273705e+15); + + undef $a; + eval '$a = 0xfffffffffffff.8p0'; # 53 bits. + is(get_warn(), undef); + is($a, 4.5035996273705e+15); + + undef $a; + eval '$a = 0xfffffffffffff.cp0'; # 54 bits. + like(get_warn(), qr/^Hexadecimal float: mantissa overflow/); + is($a, 4.5035996273705e+15); + + undef $a; + eval '$a = 0xf.ffffffffffffp0'; # 52 bits. + is(get_warn(), undef); + is($a, 16); + + undef $a; + eval '$a = 0xf.ffffffffffff8p0'; # 53 bits. + is(get_warn(), undef); + is($a, 16); + + undef $a; + eval '$a = 0xf.ffffffffffffcp0'; # 54 bits. + like(get_warn(), qr/^Hexadecimal float: mantissa overflow/); + is($a, 16); } else { print "# skipping warning tests\n"; - skip "nv_preserves_uv_bits is $Config{nv_preserves_uv_bits} not 53", 14; + skip "nv_preserves_uv_bits is $Config{nv_preserves_uv_bits} not 53", 26; } } @@ -10483,6 +10483,31 @@ Perl_scan_num(pTHX_ const char *start, YYSTYPE* lvalp) hexfp_nv += b * mult; mult /= 16.0; #endif + } else if (total_bits - shift < NV_MANT_DIG) { + /* A hexdigit straddling the edge of + * mantissa. We can try grabbing as + * many as possible bits. */ + int shift2 = 0; + if (b & 1) { + shift2 = 4; + } else if (b & 2) { + shift2 = 3; + total_bits--; + } else if (b & 4) { + shift2 = 2; + total_bits -= 2; + } else if (b & 8) { + shift2 = 1; + total_bits -= 3; + } +#ifdef HEXFP_UQUAD + hexfp_uquad <<= shift2; + hexfp_uquad |= b; + hexfp_frac_bits += shift2; +#else /* HEXFP_NV */ + hexfp_nv += b * mult; + mult /= 16.0; +#endif } } } |