diff options
author | Jarkko Hietaniemi <jhi@iki.fi> | 2015-11-07 14:38:21 -0500 |
---|---|---|
committer | Steve Hay <steve.m.hay@googlemail.com> | 2015-11-15 12:02:21 +0000 |
commit | 9a24a3ef8624123e57d0ae8b40fcd211a9e5f6dc (patch) | |
tree | 83d2d4786bdc3438d6fb19f7536b0d6886111194 | |
parent | fff4a2c9645dffe498ae699ff5d35c1a74670f94 (diff) | |
download | perl-9a24a3ef8624123e57d0ae8b40fcd211a9e5f6dc.tar.gz |
perl #126586 hexfp may lose 1-3 low order bits (most often, 1)
(cherry picked from commit 96524c28e76cdc1099eebc2832aef5b789ebbc11)
-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; } } @@ -10245,6 +10245,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 } } } |