Skip to content

Conversation

@t-a-k
Copy link
Contributor

@t-a-k t-a-k commented Dec 11, 2025

Hexadecimal floats whose significand (mantissa) part is too large to fit in UV range used to be parsed incorrectly:

  • For 32-bit build:
    $ ./perl.blead -le "print 0x123456789.0p0"
    Integer overflow in hexadecimal number at -e line 1.
    305419896
    
    Despite the warning (I think this warning is spurious because this is a floating point number, not an "integer". I'll make another PR to fix this), this should be numerically equal to 0x123456789 == 4886718345.
  • For 64-bit -Dusequadmath build:
    $ ./perl.blead -le 'print 0x12345678901234567890p0'
    Integer overflow in hexadecimal number at -e line 1.
    1311768467284833366
    
    This should be 85968058271978839505040.

This patch will fix these problem.


  • This set of changes requires a perldelta entry, and it is included.

Hexadecimal floats whose significand (mantissa) part is too large to
fit in UV range (e.g. 0x1234567890.12p+1 for 32-bit UVs) used to be
parsed incorrectly.

t/op/hexfp.t: Added tests for hexadecimal floats with large significand
@sisyphus
Copy link
Contributor

This should be 85968058271978839505040.

Yes, and with this PR I'm seeing that on a quadmath build.
But this PR then produces the following anomaly when perl's nvtype is the 53-bit double:

>perl -wle  "print 0x12345678901234567890;"
Integer overflow in hexadecimal number at -e line 1.
Hexadecimal number > 0xffffffff non-portable at -e line 1.
8.59680582719788e+22

D:\>perl -wle  "print 0x12345678901234567890p0;"
Integer overflow in hexadecimal number at -e line 1.
Hexadecimal float: mantissa overflow at -e line 1.
0

It's also not handling a valid hex representation of DENORM_MIN correctly:

>perl -wle "print 0x0.00000000000001p-1018;"
Hexadecimal float: mantissa overflow at -e line 1.
0

There might be other corner case issues - one can go mad just trying to find them.

There's also the question of how overflow is treated.
Currently, in both blead and this PR, it's just ignored - and (for nvtype of double), where I (we ?) would expect that the literal 0x123456789abcdf.fp0 would be rounded to 0x1.23456789abce0p+52, we find that it is simply truncated to 0x1.23456789abcdfp+52

>perl -wle "printf '%a', 0x123456789abcdf.fp0;"
Hexadecimal float: mantissa overflow at -e line 1.
0x1.23456789abcdfp+52

Should this behaviour be changed, or are we stuck with it for the sake of our precious backwards-compatibility ?

@t-a-k
Copy link
Contributor Author

t-a-k commented Dec 12, 2025

D:\>perl -wle  "print 0x12345678901234567890p0;"
Integer overflow in hexadecimal number at -e line 1.
Hexadecimal float: mantissa overflow at -e line 1.
0

I think this zero come from hexfp_uquad = overflowed ? (Uquad_t)n : u;:

  1. x86 (both SSE2 and x87 FPU) doesn't have native "floating-point to unsigned
    integer" conversion, so (Uquad_t)n is compiled as n >= 0x1p63 ? (Uquad_t)((Quad_t)(n - 0x1p63) ^ (1 << 63)) : (Uquad_t)((Quad_t)n).
  2. In this case n is 0x12345678901234567890 (~ 8.59680582719788e+22), so (Uquad_t)((Quad_t)(n - 0x1p63) ^ (1 << 63)) is taken.
  3. n - 0x1p63 still exceed the range of 64-bit signed integer, so x86 conversion instruction returns 0x8000000000000000 to indicate overflow.
  4. ^ (1 << 63) will turn the return value to zero.

Anyway, even before this patch, parsing was incorrect, so I think it hasn't gotten much worse.

$ ./perl.blead -wle 'print 0x12345678901234567890p0'
Integer overflow in hexadecimal number at -e line 1.
Hexadecimal float: mantissa overflow at -e line 1.
1.31176846728483e+18

It's also not handling a valid hex representation of DENORM_MIN correctly:

This seems to because HEXFP_UQUAD implementation (again, even before this patch) will accumulate only 53 bits from the radix point, so the last digit 1 was effectively ignored.

I think these both anomalies come from HEXFP_UQUAD code.
I'll also make submit another PR to fix this.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants