Closed t-a-k closed 2 weeks ago
LGTM.
For 64 bit builds, the problem you've found applies to all of my 32-bit and 64-bit builds of perl-5.39.9 on Windows, irrespective of nvtype and ivsize, in that the (appropriate) one-liner you've provided always returns a positive value for the middle calculation.
AIUI, X % -Y
should be zero if X % Y
is zero.
Otherwise it should be ( X % Y) - Y
With your patches in place, your one liner outputs as follows. For 64-bit perl whose nvtype is double:
4611686018427387902 % -1.38350580552822e+19 = -9.22337203685478e+18
4611686018427387903 % -1.38350580552822e+19 = -9.22337203685478e+18
4611686018427387904 % -1.38350580552822e+19 = -9223372036854775808
The first 2 results are, in fact, identical. But given that both -9223372036854775809 and -9223372036854775810 cannot be accurately represented on this configuration of perl (either as IV or NV), I think that's fair enough.
For 64-bit perl whose nvtype is 80-bit extended precision long double:
4611686018427387902 % -1.38350580552821637e+19 = -9.22337203685477581e+18
4611686018427387903 % -1.38350580552821637e+19 = -9.22337203685477581e+18
4611686018427387904 % -1.38350580552821637e+19 = -9223372036854775808
Despite appearances, these are the expected values of -9223372036854775810, -9223372036854775809 and -9223372036854775808. We have sane results, but an unfortunate presentation that has rounded the first 2 of them to 18 significant digits .
For 64-bit perl whose nvtype is __float128:
4611686018427387902 % -13835058055282163712 = -9223372036854775810
4611686018427387903 % -13835058055282163712 = -9223372036854775809
4611686018427387904 % -13835058055282163712 = -9223372036854775808
At last !! ... sane results && presented sanely.
I expected the long double build to present identical output, and I don't know why it didn't. (Maybe that requires that the integer be expressible in no more than 18 digits - but it's a separate issue, anyway)
Note also the sane presentation of the value -0xc000000000000000
. (The long double build could be made capable of doing the same.)
For 32-bit builds with IVSIZE of 4, the 32-bit one liner is also fixed by the patches, producing:
1073741822 % -3221225472 = -2147483650
1073741823 % -3221225472 = -2147483649
1073741824 % -3221225472 = -2147483648
irrespective of nvtype.
After patching the 32-bit builds that have IVSIZE of 8, I find that the 64-bit one liner matches the outputs of the 64-bit builds for each of the 3 nvtypes. (It would have been surprising if that wasn't the case.)
All good, AFAICS.
I found a corner case where
%
(modulo) operator returns wrong result when the result should be (IV_MIN - 1):For 32-bit (i686-linux) perl:
For
-Duse64bitint
perl:I think the second result of both example above should be contiguous to the first and third results (or at least should be negative, as perlop says that
$m % $n
will be less than or equal to zero if$n
is negative).I hope this pull request will fix this.