[Git][ghc/ghc][ghc-9.0] Bignum: fix BigNat subtraction (#18604)

Ben Gamari gitlab at gitlab.haskell.org
Tue Sep 1 00:18:13 UTC 2020



Ben Gamari pushed to branch ghc-9.0 at Glasgow Haskell Compiler / GHC


Commits:
bf8bb9e7 by Sylvain Henry at 2020-08-31T13:49:08-04:00
Bignum: fix BigNat subtraction (#18604)

There was a confusion between the boolean expected by
withNewWordArrayTrimedMaybe and the boolean returned by subtracting
functions.

- - - - -


7 changed files:

- libraries/ghc-bignum/src/GHC/Num/BigNat.hs
- libraries/ghc-bignum/src/GHC/Num/BigNat/GMP.hs
- libraries/ghc-bignum/src/GHC/Num/BigNat/Native.hs
- libraries/ghc-bignum/src/GHC/Num/WordArray.hs
- + testsuite/tests/numeric/should_run/T18604.hs
- + testsuite/tests/numeric/should_run/T18604.stdout
- testsuite/tests/numeric/should_run/all.T


Changes:

=====================================
libraries/ghc-bignum/src/GHC/Num/BigNat.hs
=====================================
@@ -506,7 +506,7 @@ bigNatSubUnsafe a b
       let szA = wordArraySize# a
       in withNewWordArrayTrimed# szA \mwa s->
             case inline bignat_sub mwa a b s of
-               (# s', 0# #) -> s'
+               (# s', 1# #) -> s'
                (# s', _  #) -> case raiseUnderflow of
                                  !_ -> s'
                                  -- see Note [ghc-bignum exceptions] in


=====================================
libraries/ghc-bignum/src/GHC/Num/BigNat/GMP.hs
=====================================
@@ -92,8 +92,8 @@ bignat_sub
 {-# INLINE bignat_sub #-}
 bignat_sub mwa wa wb s =
    case ioWord# (c_mpn_sub mwa wa (wordArraySize# wa) wb (wordArraySize# wb)) s of
-      (# s', 0## #) -> (# s', 0# #)
-      (# s', _   #) -> (# s', 1# #)
+      (# s', 1## #) -> (# s', 0# #) -- overflow
+      (# s', _   #) -> (# s', 1# #) -- no overflow
 
 bignat_sub_word
    :: MutableWordArray# RealWorld
@@ -104,8 +104,8 @@ bignat_sub_word
 {-# INLINE bignat_sub_word #-}
 bignat_sub_word mwa wa b s =
    case ioWord# (c_mpn_sub_1 mwa wa (wordArraySize# wa) b) s of
-      (# s', 0## #) -> (# s', 0# #)
-      (# s', _   #) -> (# s', 1# #)
+      (# s', 1## #) -> (# s', 0# #) -- overflow
+      (# s', _   #) -> (# s', 1# #) -- no overflow
 
 bignat_mul
    :: MutableWordArray# RealWorld


=====================================
libraries/ghc-bignum/src/GHC/Num/BigNat/Native.hs
=====================================
@@ -127,17 +127,17 @@ bignat_sub_word mwa wa b = go b 0#
       !sz = wordArraySize# wa
       go carry i s
          | isTrue# (i >=# sz)
-         = (# s, carry `neWord#` 0## #)
+         = (# s, carry `eqWord#` 0## #)
 
          | 0## <- carry
          = case mwaArrayCopy# mwa i wa i (sz -# i) s of
-            s' -> (# s', 0# #)
+            s' -> (# s', 1# #) -- no overflow
 
          | True
          = case subWordC# (indexWordArray# wa i) carry of
             (# 0##, 0# #)
                | isTrue# (i ==# sz) -> case mwaShrink# mwa 1# s of
-                                          s' -> (# s', 0# #)
+                                          s' -> (# s', 1# #) -- no overflow
 
             (# l  , c  #) -> case mwaWrite# mwa i l s of
                               s1 -> go (int2Word# c) (i +# 1#) s1


=====================================
libraries/ghc-bignum/src/GHC/Num/WordArray.hs
=====================================
@@ -318,7 +318,7 @@ mwaAddInplaceWord# mwa i y   s = case readWordArray# mwa i s of
 -- | Sub Word# inplace (at the specified offset) in the mwa with carry
 -- propagation.
 --
--- Return True# on overflow
+-- Return False# on overflow
 mwaSubInplaceWord#
    :: MutableWordArray# d
    -> Int#
@@ -328,9 +328,9 @@ mwaSubInplaceWord#
 mwaSubInplaceWord# mwa ii iw s1 = case mwaSize# mwa s1 of
    (# is, sz #) ->
       let
-         go _ 0## s = (# s, 0# #) -- no overflow
+         go _ 0## s = (# s, 1# #) -- no overflow
          go i y   s
-            | isTrue# (i >=# sz) = (# s, 1# #) -- overflow
+            | isTrue# (i >=# sz) = (# s, 0# #) -- overflow
             | True = case readWordArray# mwa i s of
                (# s1, x #) -> let !(# l,h #) = subWordC# x y
                   in case mwaWrite# mwa i l s1 of
@@ -368,16 +368,16 @@ mwaTrimCompare k mwa wb s1
 --
 -- We don't trim the resulting array!
 --
--- Return True# on overflow.
+-- Return False# on overflow.
 mwaSubInplaceArray :: MutableWordArray# d -> Int# -> WordArray# -> State# d -> (# State# d, Bool# #)
 mwaSubInplaceArray mwa off wb = go (wordArraySize# wb -# 1#)
    where
       go i s
-         | isTrue# (i <# 0#) = (# s, 0# #) -- no overflow
+         | isTrue# (i <# 0#) = (# s, 1# #) -- no overflow
          | True
          = case mwaSubInplaceWord# mwa (off +# i) (indexWordArray# wb i) s of
-            (# s2, 0# #) -> go (i -# 1#) s2
-            (# s2, _  #) -> (# s2, 1# #) -- overflow
+            (# s2, 1# #) -> go (i -# 1#) s2
+            (# s2, _  #) -> (# s2, 0# #) -- overflow
 
 -- | Add array inplace (a the specified offset) in the mwa with carry propagation.
 --
@@ -398,19 +398,19 @@ mwaAddInplaceArray mwa off wb = go 0# 0##
 --
 -- We don't trim the resulting array!
 --
--- Return True# on overflow.
+-- Return False# on overflow.
 mwaSubInplaceMutableArray :: MutableWordArray# d -> Int# -> MutableWordArray# d -> State# d -> (# State# d, Bool# #)
 mwaSubInplaceMutableArray mwa off mwb s0 =
    case mwaSize# mwb s0 of
       (# s1, szB #) -> go (szB -# 1#) s1
    where
       go i s
-         | isTrue# (i <# 0#) = (# s, 0# #) -- no overflow
+         | isTrue# (i <# 0#) = (# s, 1# #) -- no overflow
          | True
          = case readWordArray# mwb i s of
             (# s1, bi #) -> case mwaSubInplaceWord# mwa (off +# i) bi s1 of
-               (# s2, 0# #) -> go (i -# 1#) s2
-               (# s2, _  #) -> (# s2, 1# #) -- overflow
+               (# s2, 1# #) -> go (i -# 1#) s2
+               (# s2, _  #) -> (# s2, 0# #) -- overflow
 
 -- | Sub an array inplace and then trim zeroes
 --


=====================================
testsuite/tests/numeric/should_run/T18604.hs
=====================================
@@ -0,0 +1,10 @@
+module Main (main) where
+
+import Numeric.Natural
+
+main :: IO ()
+main = print (n - s)
+  where
+    n, s :: Natural
+    n = 137503105969312982142385040956303729937425409769904987267247644890331944583201
+    s = 370814112419299627365008243601943822482


=====================================
testsuite/tests/numeric/should_run/T18604.stdout
=====================================
@@ -0,0 +1 @@
+137503105969312982142385040956303729937054595657485687639882636646730000760719


=====================================
testsuite/tests/numeric/should_run/all.T
=====================================
@@ -73,3 +73,4 @@ test('T18359', normal, compile_and_run, [''])
 test('T18499', normal, compile_and_run, [''])
 test('T18509', normal, compile_and_run, [''])
 test('T18515', normal, compile_and_run, [''])
+test('T18604', normal, compile_and_run, [''])



View it on GitLab: https://gitlab.haskell.org/ghc/ghc/-/commit/bf8bb9e7855f680d850dd3ba22af0402b6b2f6df

-- 
View it on GitLab: https://gitlab.haskell.org/ghc/ghc/-/commit/bf8bb9e7855f680d850dd3ba22af0402b6b2f6df
You're receiving this email because of your account on gitlab.haskell.org.


-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://mail.haskell.org/pipermail/ghc-commits/attachments/20200831/0d5a5cb5/attachment-0001.html>


More information about the ghc-commits mailing list