summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSylvain Henry <sylvain@haskus.fr>2020-07-28 11:30:44 +0200
committerMarge Bot <ben+marge-bot@smart-cactus.org>2020-07-29 15:09:02 -0400
commit96c31ea1f0303ebabc59edccff2e88444fe02722 (patch)
treeb3da29f2cfdd29b1f1e479be215e6478cedb3e82
parente3db4b4c5b7f5d2a62ebd88e174fca07d04c4e18 (diff)
downloadhaskell-96c31ea1f0303ebabc59edccff2e88444fe02722.tar.gz
Fix bug in Natural multiplication (fix #18509)
A bug was lingering in Natural multiplication (inverting two limbs) despite QuickCheck tests used during the development leading to wrong results (independently of the selected backend).
-rw-r--r--libraries/ghc-bignum/src/GHC/Num/BigNat.hs4
-rw-r--r--libraries/ghc-bignum/src/GHC/Num/Natural.hs4
-rw-r--r--libraries/ghc-bignum/src/GHC/Num/WordArray.hs10
-rw-r--r--testsuite/tests/numeric/should_run/T18509.hs6
-rw-r--r--testsuite/tests/numeric/should_run/T18509.stdout2
-rw-r--r--testsuite/tests/numeric/should_run/all.T1
6 files changed, 19 insertions, 8 deletions
diff --git a/libraries/ghc-bignum/src/GHC/Num/BigNat.hs b/libraries/ghc-bignum/src/GHC/Num/BigNat.hs
index 20a227f099..4aeedafc9d 100644
--- a/libraries/ghc-bignum/src/GHC/Num/BigNat.hs
+++ b/libraries/ghc-bignum/src/GHC/Num/BigNat.hs
@@ -228,8 +228,8 @@ bigNatToWordList bn = go (bigNatSize# bn)
-- | Convert two Word# (most-significant first) into a BigNat
bigNatFromWord2# :: Word# -> Word# -> BigNat#
bigNatFromWord2# 0## 0## = bigNatZero# (# #)
-bigNatFromWord2# 0## n = bigNatFromWord# n
-bigNatFromWord2# w1 w2 = wordArrayFromWord2# w1 w2
+bigNatFromWord2# 0## l = bigNatFromWord# l
+bigNatFromWord2# h l = wordArrayFromWord2# h l
-- | Convert a BigNat into a Word#
bigNatToWord# :: BigNat# -> Word#
diff --git a/libraries/ghc-bignum/src/GHC/Num/Natural.hs b/libraries/ghc-bignum/src/GHC/Num/Natural.hs
index ac35b65522..62e9f33e1c 100644
--- a/libraries/ghc-bignum/src/GHC/Num/Natural.hs
+++ b/libraries/ghc-bignum/src/GHC/Num/Natural.hs
@@ -86,8 +86,8 @@ naturalFromWord# x = NS x
-- | Convert two Word# (most-significant first) into a Natural
naturalFromWord2# :: Word# -> Word# -> Natural
naturalFromWord2# 0## 0## = naturalZero
-naturalFromWord2# 0## n = NS n
-naturalFromWord2# w1 w2 = NB (bigNatFromWord2# w2 w1)
+naturalFromWord2# 0## l = NS l
+naturalFromWord2# h l = NB (bigNatFromWord2# h l)
-- | Create a Natural from a Word
naturalFromWord :: Word -> Natural
diff --git a/libraries/ghc-bignum/src/GHC/Num/WordArray.hs b/libraries/ghc-bignum/src/GHC/Num/WordArray.hs
index 78c450b55e..9b98f74293 100644
--- a/libraries/ghc-bignum/src/GHC/Num/WordArray.hs
+++ b/libraries/ghc-bignum/src/GHC/Num/WordArray.hs
@@ -121,12 +121,14 @@ withNewWordArrayTrimedMaybe# sz act = case runRW# io of (# _, a #) -> a
-- | Create a WordArray# from two Word#
--
--- `byteArrayFromWord2# msw lsw = lsw:msw`
+-- `wordArrayFromWord2# h l
+-- where h is the most significant word
+-- l is the least significant word
wordArrayFromWord2# :: Word# -> Word# -> WordArray#
-wordArrayFromWord2# msw lsw =
+wordArrayFromWord2# h l =
withNewWordArray# 2# \mwa s ->
- case mwaWrite# mwa 0# lsw s of
- s -> mwaWrite# mwa 1# msw s
+ case mwaWrite# mwa 0# l s of
+ s -> mwaWrite# mwa 1# h s
-- | Create a WordArray# from one Word#
wordArrayFromWord# :: Word# -> WordArray#
diff --git a/testsuite/tests/numeric/should_run/T18509.hs b/testsuite/tests/numeric/should_run/T18509.hs
new file mode 100644
index 0000000000..fe4df42b14
--- /dev/null
+++ b/testsuite/tests/numeric/should_run/T18509.hs
@@ -0,0 +1,6 @@
+import Numeric.Natural
+
+main :: IO ()
+main = do
+ print $ (0xFFFFFFFF0 * 0xFFFFFFFF0 :: Natural)
+ print $ (2 :: Natural) ^ (190 :: Int)
diff --git a/testsuite/tests/numeric/should_run/T18509.stdout b/testsuite/tests/numeric/should_run/T18509.stdout
new file mode 100644
index 0000000000..4f0e5fd092
--- /dev/null
+++ b/testsuite/tests/numeric/should_run/T18509.stdout
@@ -0,0 +1,2 @@
+4722366480670621958400
+1569275433846670190958947355801916604025588861116008628224
diff --git a/testsuite/tests/numeric/should_run/all.T b/testsuite/tests/numeric/should_run/all.T
index faa4d7c992..f8d6ea3d4d 100644
--- a/testsuite/tests/numeric/should_run/all.T
+++ b/testsuite/tests/numeric/should_run/all.T
@@ -71,3 +71,4 @@ test('T497', normal, compile_and_run, ['-O'])
test('T17303', normal, compile_and_run, [''])
test('T18359', normal, compile_and_run, [''])
test('T18499', normal, compile_and_run, [''])
+test('T18509', normal, compile_and_run, [''])