fixed

Pure Haskell large fixed-width integers.
git clone git://git.ppad.tech/fixed.git
Log | Files | Refs | README | LICENSE

commit 4c3581bcf22336a805f85f6f5a72f224fad738d9
parent c0bf48d835b31ee2d8ab17d0e1756462664c1782
Author: Jared Tobin <jared@jtobin.io>
Date:   Fri, 24 Jan 2025 22:23:00 +0400

lib: gut primitive stuff

Diffstat:
Mbench/Main.hs | 66++++--------------------------------------------------------------
Mbench/Weight.hs | 14--------------
Mlib/Data/Word/Extended.hs | 263++++---------------------------------------------------------------------------
Mtest/Main.hs | 137-------------------------------------------------------------------------------
4 files changed, 16 insertions(+), 464 deletions(-)

diff --git a/bench/Main.hs b/bench/Main.hs @@ -8,7 +8,6 @@ import Criterion.Main import Data.Bits ((.|.), (.&.), (.^.)) import qualified Data.Bits as B import qualified Data.Word.Extended as W -import qualified Data.Primitive.PrimArray as PA import Prelude hiding (or, and, div, mod) import qualified Prelude (div) @@ -115,13 +114,6 @@ div_baseline = bench "div (baseline)" $ nf (Prelude.div w0) w1 where !w0 = 0x41cf50c7d0d65afabcf5ba37750dba71c7db29ec9f20a216d3ef013a59b9188a !w1 = 0x066bd4c3c10e30260cb6e7832af25f15527b089b258a1fef13b6eec3ce73bf06 -div :: Benchmark -div = bench "div" $ nf (W.div w0) w1 where - !w0 = W.to_word256 - 0x41cf50c7d0d65afabcf5ba37750dba71c7db29ec9f20a216d3ef013a59b9188a - !w1 = W.to_word256 - 0x066bd4c3c10e30260cb6e7832af25f15527b089b258a1fef13b6eec3ce73bf06 - div_pure :: Benchmark div_pure = bench "div_pure" $ nf (W.div_pure w0) w1 where !w0 = W.to_word256 @@ -137,24 +129,12 @@ div_baseline_small = !w0 = 0x7fffffed !w1 = 0x7ffbffed -div_small :: Benchmark -div_small = bench "div, small" $ nf (W.div w0) w1 where - !w0 = W.to_word256 0x7fffffed - !w1 = W.to_word256 0x7ffbffed - mod_baseline :: Benchmark mod_baseline = bench "mod (baseline)" $ nf (Prelude.rem w0) w1 where w0, w1 :: Integer !w0 = 0x41cf50c7d0d65afabcf5ba37750dba71c7db29ec9f20a216d3ef013a59b9188a !w1 = 0x066bd4c3c10e30260cb6e7832af25f15527b089b258a1fef13b6eec3ce73bf06 -mod :: Benchmark -mod = bench "mod" $ nf (W.mod w0) w1 where - !w0 = W.to_word256 - 0x41cf50c7d0d65afabcf5ba37750dba71c7db29ec9f20a216d3ef013a59b9188a - !w1 = W.to_word256 - 0x066bd4c3c10e30260cb6e7832af25f15527b089b258a1fef13b6eec3ce73bf06 - mod_pure :: Benchmark mod_pure = bench "mod (pure)" $ nf (W.mod_pure w0) w1 where !w0 = W.to_word256 @@ -162,49 +142,12 @@ mod_pure = bench "mod (pure)" $ nf (W.mod_pure w0) w1 where !w1 = W.to_word256 0x066bd4c3c10e30260cb6e7832af25f15527b089b258a1fef13b6eec3ce73bf06 -quotrem_by1 :: Benchmark -quotrem_by1 = env setup $ \ ~(quo, u, d) -> - bench "quotrem_by1" $ nfAppIO (W.quotrem_by1 quo u) d - where - setup = do - quo <- PA.newPrimArray 5 - PA.setPrimArray quo 0 5 0 - let u = PA.primArrayFromList [ - 300 - , 200 - , 100 - ] - d = B.complement 50 - pure (quo, u, d) - quotrem_by1_gen :: Benchmark quotrem_by1_gen = bench "quotrem_by1_gen" $ nf (W.quotrem_by1_gen (W.Word576 300 200 100 0 0 0 0 0 0) 3) (B.complement 50) -quotrem_knuth :: Benchmark -quotrem_knuth = env setup $ \ ~(quo, u, d) -> - bench "quotrem_knuth" $ nfAppIO (W.quotrem_knuth quo u) d - where - setup = do - quo <- PA.newPrimArray 5 - PA.setPrimArray quo 0 5 0 - u <- PA.newPrimArray 9 - PA.setPrimArray u 0 9 0 - PA.writePrimArray u 0 2162362899639802732 - PA.writePrimArray u 0 8848548347662387477 - PA.writePrimArray u 0 13702897166684377657 - PA.writePrimArray u 0 16799544643779908154 - PA.writePrimArray u 0 1 - let !d = PA.primArrayFromList [ - 16950798510782491100 - , 2612788699139816405 - , 5146719872810836952 - , 14966148379609982000 - ] - pure (quo, u, d) - quotrem_knuth_gen :: Benchmark quotrem_knuth_gen = bench "quotrem_knuth_gen" $ @@ -220,11 +163,10 @@ quotrem_knuth_gen = main :: IO () main = defaultMain [ -- quotrem_knuth_gen - --, quotrem_knuth - quotrem_by1 - , quotrem_by1_gen - --, div_baseline - --, div_pure + -- quotrem_by1 + --, quotrem_by1_gen + div_baseline + , div_pure --, div --, mul_baseline --, mul diff --git a/bench/Weight.hs b/bench/Weight.hs @@ -7,7 +7,6 @@ module Main where import Control.DeepSeq import qualified Data.Bits as B -import qualified Data.Primitive.PrimArray as PA import qualified Data.Word.Extended as E import qualified Weigh as W @@ -37,17 +36,6 @@ w3 = E.to_word256 i3 main :: IO () main = do - !(!q, !u, !d) <- do - quo <- PA.newPrimArray 5 - PA.setPrimArray quo 0 5 0 - let uf = PA.primArrayFromList [ - 300 - , 200 - , 100 - ] - df = B.complement 50 - pure (quo, uf, df) - W.mainWith $ do W.func "add (baseline)" ((+) i0) i1 W.func "add" (E.add w0) w1 @@ -56,9 +44,7 @@ main = do W.func "mul (baseline)" ((*) i0) i1 W.func "mul" (E.mul w0) w1 W.func "div (baseline)" (Prelude.div i2) i3 - W.func "div" (E.div w2) w3 W.func "div_pure" (E.div_pure w2) w3 - W.io "quotrem_by1" (E.quotrem_by1 q u) d W.func "quotrem_by1_gen" (E.quotrem_by1_gen (E.Word576 300 200 100 0 0 0 0 0 0) 3) (B.complement 50) W.func "quotrem_gen" diff --git a/lib/Data/Word/Extended.hs b/lib/Data/Word/Extended.hs @@ -338,43 +338,17 @@ mul_512 (Word256 x0 x1 x2 x3) (Word256 y0 y1 y2 y3) = -- division ------------------------------------------------------------------- --- x =- y * m --- requires (len x - x_offset) >= len y > 0 -sub_mul_to - :: PrimMonad m - => PA.MutablePrimArray (PrimState m) Word64 - -> Int - -> PA.PrimArray Word64 - -> Word64 - -> m Word64 -sub_mul_to x x_offset y m = do - let l = PA.sizeofPrimArray y - loop !j !borrow - | j == l = pure borrow - | otherwise = do - !x_j <- PA.readPrimArray x (j + x_offset) - let !y_j = PA.indexPrimArray y j - !(P s carry1) = sub_b x_j borrow 0 - !(P ph pl) = mul_c y_j m - !(P t carry2) = sub_b s pl 0 - PA.writePrimArray x (j + x_offset) t - loop (succ j) (ph + carry1 + carry2) - loop 0 0 - sub_mul :: Word576 -> Int -> Word256 -> Int -> Word64 -> Word640 sub_mul u u_start (Word256 d0 d1 d2 d3) d_len m = case d_len of - 2 -> - let !(Word640 u_0 b_0) = step0 u 0 - in step1 u_0 b_0 - 3 -> - let !(Word640 u_0 b_0) = step0 u 0 - !(Word640 u_1 b_1) = step1 u_0 b_0 - in step2 u_1 b_1 - 4 -> - let !(Word640 u_0 b_0) = step0 u 0 - !(Word640 u_1 b_1) = step1 u_0 b_0 - !(Word640 u_2 b_2) = step2 u_1 b_1 - in step3 u_2 b_2 + 2 -> let !(Word640 u_0 b_0) = step0 u 0 + in step1 u_0 b_0 + 3 -> let !(Word640 u_0 b_0) = step0 u 0 + !(Word640 u_1 b_1) = step1 u_0 b_0 + in step2 u_1 b_1 + 4 -> let !(Word640 u_0 b_0) = step0 u 0 + !(Word640 u_1 b_1) = step1 u_0 b_0 + !(Word640 u_2 b_2) = step2 u_1 b_1 + in step3 u_2 b_2 _ -> error "ppad-fixed (sub_mul): bad index" where @@ -529,39 +503,20 @@ sub_mul u u_start (Word256 d0 d1 d2 d3) d_len m = case d_len of _ -> error "ppad-fixed (step3): bad index" --- requires (len x - x_offset) >= len y > 0 -add_to - :: PrimMonad m - => PA.MutablePrimArray (PrimState m) Word64 - -> Int - -> PA.PrimArray Word64 - -> m Word64 -add_to x x_offset y = do - let l = PA.sizeofPrimArray y - loop !j !cacc - | j == l = pure cacc - | otherwise = do - xj <- PA.readPrimArray x (j + x_offset) - let yj = PA.indexPrimArray y j - !(P nex carry) = add_c xj yj cacc - PA.writePrimArray x (j + x_offset) nex - loop (succ j) carry - loop 0 0 - add_big :: Word576 -> Int -> Word256 -> Int -> Word640 add_big u u_start (Word256 d0 d1 d2 d3) d_len = case d_len of 2 -> let !(Word640 u_0 c_0) = step0 u 0 - in step1 u_0 c_0 + in step1 u_0 c_0 3 -> let !(Word640 u_0 c_0) = step0 u 0 !(Word640 u_1 c_1) = step1 u_0 c_0 - in step2 u_1 c_1 + in step2 u_1 c_1 4 -> let !(Word640 u_0 c_0) = step0 u 0 !(Word640 u_1 c_1) = step1 u_0 c_0 !(Word640 u_2 c_2) = step2 u_1 c_1 - in step3 u_2 c_2 + in step3 u_2 c_2 _ -> error "ppad-fixed (add_big): bad index" where @@ -728,25 +683,6 @@ quotrem_2by1 uh ul d rec = then P (qh_y + 1) (r_y - d) else P qh_y r_y -quotrem_by1 - :: PrimMonad m - => PA.MutablePrimArray (PrimState m) Word64 - -> PA.PrimArray Word64 - -> Word64 - -> m Word64 -quotrem_by1 quo u d = do - let !rec = recip_2by1 d - !lu = PA.sizeofPrimArray u - !r0 = PA.indexPrimArray u (lu - 1) - loop !j !racc - | j < 0 = pure racc - | otherwise = do - let uj = PA.indexPrimArray u j - !(P qj rnex) = quotrem_2by1 racc uj d rec - PA.writePrimArray quo j qj - loop (pred j) rnex - loop (lu - 2) r0 - quotrem_by1_gen :: Word576 -- dividend -> Int -- dividend length @@ -881,45 +817,6 @@ quotrem_knuth_gen u ulen d dlen = loop (ulen - dlen - 1) zero576 u where let !q = set576 qacc j qhat in loop (pred j) q u1 -quotrem_knuth - :: PrimMonad m - => PA.MutablePrimArray (PrimState m) Word64 - -> PA.MutablePrimArray (PrimState m) Word64 - -> PA.PrimArray Word64 - -> m () -quotrem_knuth quo u d = do - !lu <- PA.getSizeofMutablePrimArray u - let !ld = PA.sizeofPrimArray d - !dh = PA.indexPrimArray d (ld - 1) - !dl = PA.indexPrimArray d (ld - 2) - !rec = recip_2by1 dh - loop !j - | j < 0 = pure () - | otherwise = do - !u2 <- PA.readPrimArray u (j + ld) - !u1 <- PA.readPrimArray u (j + ld - 1) - !u0 <- PA.readPrimArray u (j + ld - 2) - let !qhat | u2 >= dh = 0xffff_ffff_ffff_ffff - | otherwise = - let !(P qh rh) = quotrem_2by1 u2 u1 dh rec - !(P ph pl) = mul_c qh dl - in if ph > rh || (ph == rh && pl > u0) - then qh - 1 - else qh - - borrow <- sub_mul_to u j d qhat - PA.writePrimArray u (j + ld) (u2 - borrow) - if u2 < borrow - then do - let !qh = qhat - 1 - r <- add_to u j d - PA.writePrimArray u (j + ld) r - PA.writePrimArray quo j qh - else - PA.writePrimArray quo j qhat - loop (pred j) - loop (lu - ld - 1) - quotrem_gen :: Word576 -> Word256 @@ -1016,119 +913,6 @@ quotrem_gen u@(Word576 u0 u1 u2 u3 u4 u5 u6 u7 u8) d@(Word256 d0 d1 d2 d3) = | z0 /= 0 = 1 | otherwise = error "ppad-fixed (quotrem_256): division by zero" -quotrem - :: PrimMonad m - => PA.MutablePrimArray (PrimState m) Word64 - -> PA.PrimArray Word64 - -> PA.PrimArray Word64 - -> m Word256 -quotrem quo u d = do - let !ld = PA.sizeofPrimArray d - !lu = PA.sizeofPrimArray u - !dlen = len_loop d (ld - 1) - !shift = B.countLeadingZeros (PA.indexPrimArray d (dlen - 1)) - dn <- PA.newPrimArray dlen - PA.setPrimArray dn 0 dlen 0 - let go_dn !j - | j == 0 = pure () - | otherwise = do - let !dj = PA.indexPrimArray d j - !dj_1 = PA.indexPrimArray d (j - 1) - !val = (dj .<<. shift) .|. (dj_1 .>>. (64 - shift)) - PA.writePrimArray dn j val - go_dn (pred j) - go_dn (dlen - 1) - PA.writePrimArray dn 0 (PA.indexPrimArray d 0 .<<. shift) - let !ulen = len_loop u (lu - 1) - if ulen < dlen - then do - let !u0 | lu >= 1 = PA.indexPrimArray u 0 - | otherwise = 0 - !u1 | lu >= 2 = PA.indexPrimArray u 1 - | otherwise = 0 - !u2 | lu >= 3 = PA.indexPrimArray u 2 - | otherwise = 0 - !u3 | lu >= 4 = PA.indexPrimArray u 3 - | otherwise = 0 - pure (Word256 u0 u1 u2 u3) - else do - un <- PA.newPrimArray (ulen + 1) - PA.setPrimArray un 0 (ulen + 1) 0 - let u_ulen = PA.indexPrimArray u (ulen - 1) - PA.writePrimArray un ulen (u_ulen .>>. (64 - shift)) - -- duplicated, but easy to handle mutableprimarrays this way - let go_un !j - | j == 0 = pure () - | otherwise = do - let !uj = PA.indexPrimArray u j - !uj_1 = PA.indexPrimArray u (j - 1) - !val = (uj .<<. shift) .|. (uj_1 .>>. (64 - shift)) - PA.writePrimArray un j val - go_un (pred j) - go_un (ulen - 1) - PA.writePrimArray un 0 (PA.indexPrimArray u 0 .<<. shift) - if dlen == 1 - then do - dn_0 <- PA.readPrimArray dn 0 - un_c <- PA.freezePrimArray un 0 (ulen + 1) - r <- quotrem_by1 quo un_c dn_0 - pure (Word256 (r .>>. shift) 0 0 0) - else do - dnf <- PA.unsafeFreezePrimArray dn - quotrem_knuth quo un dnf - let go_r !j !acc - | j == dlen = pure acc - | otherwise = do - un_j <- PA.readPrimArray un j - un_j_1 <- PA.readPrimArray un (j + 1) - let !val = (un_j .>>. shift) - .|. (un_j_1 .<<. (64 - shift)) - !nacc = setr acc j val - go_r (succ j) nacc - !r <- go_r 0 zero - un_dlen_1 <- PA.readPrimArray un (dlen - 1) - pure (setr r (dlen - 1) (un_dlen_1 .>>. shift)) - where - len_loop !arr !j - | j < 0 = 0 - | PA.indexPrimArray arr j /= 0 = j + 1 - | otherwise = len_loop arr (pred j) - - setr w@(Word256 z0 z1 z2 z3) j val - | j == 0 = Word256 val z1 z2 z3 - | j == 1 = Word256 z0 val z2 z3 - | j == 2 = Word256 z0 z1 val z3 - | j == 3 = Word256 z0 z1 z2 val - | otherwise = w - --- primarray -div :: Word256 -> Word256 -> Word256 -div a@(Word256 a0 a1 a2 a3) b@(Word256 b0 b1 b2 b3) - | is_zero b || b `gt` a = zero -- ? - | a == b = one - | is_word64 a = Word256 (a0 `quot` b0) 0 0 0 - | otherwise = runST $ do - quo <- PA.newPrimArray 4 - PA.setPrimArray quo 0 4 0 - mx <- PA.newPrimArray 4 - my <- PA.newPrimArray 4 - PA.writePrimArray mx 0 a0 - PA.writePrimArray mx 1 a1 - PA.writePrimArray mx 2 a2 - PA.writePrimArray mx 3 a3 - PA.writePrimArray my 0 b0 - PA.writePrimArray my 1 b1 - PA.writePrimArray my 2 b2 - PA.writePrimArray my 3 b3 - x <- PA.unsafeFreezePrimArray mx - y <- PA.unsafeFreezePrimArray my - _ <- quotrem quo x y - z0 <- PA.readPrimArray quo 0 - z1 <- PA.readPrimArray quo 1 - z2 <- PA.readPrimArray quo 2 - z3 <- PA.readPrimArray quo 3 - pure (Word256 z0 z1 z2 z3) - div_pure :: Word256 -> Word256 -> Word256 div_pure a@(Word256 a0 a1 a2 a3) b@(Word256 b0 _ _ _) | is_zero b || b `gt` a = zero -- ? @@ -1139,29 +923,6 @@ div_pure a@(Word256 a0 a1 a2 a3) b@(Word256 b0 _ _ _) !(Word832 (Word576 q0 q1 q2 q3 _ _ _ _ _) _) = quotrem_gen u b in Word256 q0 q1 q2 q3 --- primarray -mod :: Word256 -> Word256 -> Word256 -mod a@(Word256 a0 a1 a2 a3) b@(Word256 b0 b1 b2 b3) - | is_zero b || a == b = zero -- ? - | a `lt` b = a - | is_word64 a = Word256 (a0 `Prelude.rem` b0) 0 0 0 - | otherwise = runST $ do - quo <- PA.newPrimArray 4 - PA.setPrimArray quo 0 4 0 - mx <- PA.newPrimArray 4 - my <- PA.newPrimArray 4 - PA.writePrimArray mx 0 a0 - PA.writePrimArray mx 1 a1 - PA.writePrimArray mx 2 a2 - PA.writePrimArray mx 3 a3 - PA.writePrimArray my 0 b0 - PA.writePrimArray my 1 b1 - PA.writePrimArray my 2 b2 - PA.writePrimArray my 3 b3 - x <- PA.unsafeFreezePrimArray mx - y <- PA.unsafeFreezePrimArray my - quotrem quo x y - mod_pure :: Word256 -> Word256 -> Word256 mod_pure a@(Word256 a0 a1 a2 a3) b@(Word256 b0 _ _ _) | is_zero b || a == b = zero -- ? diff --git a/test/Main.hs b/test/Main.hs @@ -3,10 +3,8 @@ module Main where -import Control.Monad.ST import Data.Bits ((.|.), (.&.), (.>>.), (.^.)) import qualified Data.Bits as B -import qualified Data.Primitive.PrimArray as PA import Data.Word (Word64) import Data.Word.Extended import Prelude hiding (and, or, div, mod) @@ -142,24 +140,12 @@ mul_512_matches (Q.NonNegative a) (Q.NonNegative b) = !rite = to_word512 (a * b) in left == rite -div_matches :: DivMonotonic -> Bool -div_matches (DivMonotonic (a, b)) = - let !left = to_word256 a `div` to_word256 b - !rite = to_word256 (a `Prelude.div` b) - in left == rite - div_pure_matches :: DivMonotonic -> Bool div_pure_matches (DivMonotonic (a, b)) = let !left = to_word256 a `div_pure` to_word256 b !rite = to_word256 (a `Prelude.div` b) in left == rite -mod_matches :: DivMonotonic -> Bool -mod_matches (DivMonotonic (a, b)) = - let !left = to_word256 a `mod` to_word256 b - !rite = to_word256 (a `rem` b) - in left == rite - mod_pure_matches :: DivMonotonic -> Bool mod_pure_matches (DivMonotonic (a, b)) = let !left = to_word256 a `mod_pure` to_word256 b @@ -194,21 +180,6 @@ quotrem_2by1_case0 = do !o = quotrem_2by1 8 4 d (recip_2by1 d) H.assertEqual mempty (P 8 2052) o -quotrem_by1_case0 :: H.Assertion -quotrem_by1_case0 = do - let (q, r) = runST $ do - quo <- PA.newPrimArray 4 - PA.setPrimArray quo 0 4 0 - let !u = PA.primArrayFromList [8, 4] - !d = B.complement 0xFF :: Word64 - re <- quotrem_by1 quo u d - qu <- PA.unsafeFreezePrimArray quo - pure (qu, re) - let pec_array = PA.primArrayFromList [4, 0, 0, 0] - pec_rem = 1032 - H.assertEqual "remainder matches" pec_rem r - H.assertEqual "quotient matches" pec_array q - quotrem_by1_gen_case0 :: H.Assertion quotrem_by1_gen_case0 = do let !u = Word576 8 4 0 0 0 0 0 0 0 @@ -219,21 +190,6 @@ quotrem_by1_gen_case0 = do H.assertEqual "remainder matches" pec_rem r H.assertEqual "quotient matches" pec_quo q -quotrem_by1_case1 :: H.Assertion -quotrem_by1_case1 = do - let (q, r) = runST $ do - quo <- PA.newPrimArray 4 - PA.setPrimArray quo 0 4 0 - let !u = PA.primArrayFromList [8, 26] - !d = B.complement 0xFF :: Word64 - re <- quotrem_by1 quo u d - qu <- PA.unsafeFreezePrimArray quo - pure (qu, re) - let pec_array = PA.primArrayFromList [26, 0, 0, 0] - pec_rem = 6664 - H.assertEqual "remainder matches" pec_rem r - H.assertEqual "quotient matches" pec_array q - quotrem_by1_gen_case1 :: H.Assertion quotrem_by1_gen_case1 = do let !u = Word576 8 26 0 0 0 0 0 0 0 @@ -270,90 +226,6 @@ quotrem_knuth_gen_case0 = do H.assertEqual "divisor matches" pec_u nu H.assertEqual "quotient matches" pec_q q -quotrem_knuth_case0 :: H.Assertion -quotrem_knuth_case0 = do - let (q, u) = runST $ do - quo <- PA.newPrimArray 5 - PA.setPrimArray quo 0 5 0 - u_arr <- PA.newPrimArray 5 - PA.writePrimArray u_arr 0 2162362899639802732 - PA.writePrimArray u_arr 1 8848548347662387477 - PA.writePrimArray u_arr 2 13702897166684377657 - PA.writePrimArray u_arr 3 16799544643779908154 - PA.writePrimArray u_arr 4 1 - let !d = PA.primArrayFromList [ - 16950798510782491100 - , 2612788699139816405 - , 5146719872810836952 - , 14966148379609982000 - ] - quotrem_knuth quo u_arr d - qf <- PA.unsafeFreezePrimArray quo - uf <- PA.unsafeFreezePrimArray u_arr - pure (qf, uf) - let pec_q = PA.primArrayFromList [2, 0, 0, 0, 0] - pec_u = PA.primArrayFromList [ - 5154254025493923764 - , 3622970949382754665 - , 3409457421062703753 - , 5313991958269495770 - , 0 - ] - H.assertEqual "divisor matches" pec_u u - H.assertEqual "quotient matches" pec_q q - -quotrem_case0 :: H.Assertion -quotrem_case0 = do - let (q, r) = runST $ do - quo <- PA.newPrimArray 5 - PA.setPrimArray quo 0 5 (0 :: Word64) - let !u = PA.primArrayFromList - [0x1234567890ABCDEF, 0xFEDCBA0987654321, 0x123456789ABCDEF0] - !d = PA.primArrayFromList - [0x0, 0x0, 0x1, 0x100000000] - rf <- quotrem quo u d - qf <- PA.unsafeFreezePrimArray quo - pure (qf, rf) - let pec_q = PA.primArrayFromList [0, 0, 0, 0, 0] - pec_r = Word256 - 1311768467294899695 - 18364757930599072545 - 1311768467463790320 - 0 - H.assertEqual "remainder matches" pec_r r - H.assertEqual "quotient matches" pec_q q - -quotrem_case1 :: H.Assertion -quotrem_case1 = do - let (q, r) = runST $ do - quo <- PA.newPrimArray 5 - PA.setPrimArray quo 0 5 0 - let !u = PA.primArrayFromList [ - 5152276743337338587 - , 6823823105342984773 - , 12649096328525870222 - , 8811572179372364942 - ] - !d = PA.primArrayFromList [ - 8849385646123010679 - , 653197174784954101 - , 1286679968202709238 - , 3741537094902495500 - ] - - rf <- quotrem quo u d - qf <- PA.unsafeFreezePrimArray quo - pure (qf, rf) - let pec_q = PA.primArrayFromList [2, 0, 0, 0, 0] - pec_r = Word256 - 5900249524800868845 - 5517428755773076570 - 10075736392120451746 - 1328497989567373942 - - H.assertEqual "remainder matches" pec_r r - H.assertEqual "quotient matches" pec_q q - quotrem_gen_case0 :: H.Assertion quotrem_gen_case0 = do let !u = Word576 @@ -431,12 +303,8 @@ arithmetic = testGroup "arithmetic" [ Q.withMaxSuccess 1000 sub_matches , Q.testProperty "multiplication matches (nonneg, low bits)" $ Q.withMaxSuccess 1000 mul_512_matches - , Q.testProperty "division matches" $ - Q.withMaxSuccess 1000 div_matches , Q.testProperty "pure division matches" $ Q.withMaxSuccess 1000 div_pure_matches - , Q.testProperty "mod matches" $ - Q.withMaxSuccess 1000 mod_matches , Q.testProperty "pure mod matches" $ Q.withMaxSuccess 1000 mod_pure_matches ] @@ -467,14 +335,9 @@ main = defaultMain $ , H.testCase "recip_2by1 matches case0" recip_2by1_case0 , H.testCase "recip_2by1 matches case1" recip_2by1_case1 , H.testCase "quotrem_2by1 matches case0" quotrem_2by1_case0 - , H.testCase "quotrem_by1 matches case0" quotrem_by1_case0 - , H.testCase "quotrem_by1 matches case1" quotrem_by1_case1 , H.testCase "quotrem_by1_gen matches case0" quotrem_by1_gen_case0 , H.testCase "quotrem_by1_gen matches case1" quotrem_by1_gen_case1 , H.testCase "quotrem_knuth_gen matches case0" quotrem_knuth_gen_case0 - , H.testCase "quotrem_knuth matches case0" quotrem_knuth_case0 - , H.testCase "quotrem matches case0" quotrem_case0 - , H.testCase "quotrem matches case1" quotrem_case1 , H.testCase "quotrem_gen matches case0" quotrem_gen_case0 , H.testCase "quotrem_gen matches case1" quotrem_gen_case1 ]