`word2Double#` does not match `doubleFromInteger` for large values
Summary
Implementation of word2Double#
doesn't match the one from gmp-integer: doubleFromInteger
for many values larger than 2^63
Steps to reproduce
Start up ghci:
>>> import GHC.Float
>>> word2Double maxBound
1.8446744073709552e19
>>> fromIntegral (maxBound :: Word) :: Double
1.844674407370955e19
>>> import GHC.Integer
>>> :set -XMagicHash
>>> word2Double maxBound == D# (doubleFromInteger (toInteger (maxBound :: Word64)))
False
Here are also three quickcheck properties that depict the problem:
it "word2Double == doubleFromInteger (2^63 <= x < 2^64)" $
property $
forAll (choose (2 ^ 63, maxBound)) $ \(w :: Word) ->
word2Double w === D# (doubleFromInteger (toInteger w))
it "word2Double == doubleFromInteger (2^54 <= x <= 2^63)" $
property $
forAll (choose (2 ^ 54, 2 ^ 63)) $ \(w :: Word) ->
word2Double w === D# (doubleFromInteger (toInteger w))
it "int2Double == doubleFromInteger (2^52 <= x < 2^63)" $
property $
forAll (choose (2 ^ 54, maxBound)) $ \(w :: Int) ->
int2Double w === D# (doubleFromInteger (toInteger w))
First one fails consistently, while the other two I have not seen to fail yet.
Expected behavior
- Expect
word2Double a
to produce exactly the same result as\(a :: Word64) -> D# (doubleFromInteger (toInteger a))
for alla
This bug has some funny consequences. For example compiling with or without optimizations this:
round (fromIntegral (maxBound :: Word64) :: Double) :: Word64
will produce either 0
or 18446744073709549568
respectfully.
Environment
- GHC version used: 8.8.2 (and I suspect current HEAD and all prior versions)
Optional:
- Operating System: Ubuntu LTS 18.04
- System Architecture: x86_64
Edited by Alexey Kuleshevich