commit 4c3581bcf22336a805f85f6f5a72f224fad738d9
parent c0bf48d835b31ee2d8ab17d0e1756462664c1782
Author: Jared Tobin <jared@jtobin.io>
Date: Fri, 24 Jan 2025 22:23:00 +0400
lib: gut primitive stuff
Diffstat:
| M | bench/Main.hs | | | 66 | ++++-------------------------------------------------------------- |
| M | bench/Weight.hs | | | 14 | -------------- |
| M | lib/Data/Word/Extended.hs | | | 263 | ++++--------------------------------------------------------------------------- |
| M | test/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
]