fixed

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

commit ed25904267663fd6b484b23d1b9499d26ff6af1d
parent 59f9d6b4bd5c18f91c30a959749592e2347e5949
Author: Jared Tobin <jared@jtobin.io>
Date:   Fri, 24 Jan 2025 13:49:07 +0400

lib: test and bench cases

Diffstat:
M.gitignore | 1+
Mbench/Main.hs | 18+++++++++++++-----
Mbench/Weight.hs | 1+
Mlib/Data/Word/Extended.hs | 19+++++++++++++++++++
Msrc/Main.hs | 35++++++++++++++++-------------------
Mtest/Main.hs | 16++++++++++++++++
6 files changed, 66 insertions(+), 24 deletions(-)

diff --git a/.gitignore b/.gitignore @@ -1,2 +1,3 @@ dist-newstyle/ *.prof +*.hp diff --git a/bench/Main.hs b/bench/Main.hs @@ -121,6 +121,13 @@ div = bench "div" $ nf (W.div w0) w1 where !w1 = W.to_word256 0x066bd4c3c10e30260cb6e7832af25f15527b089b258a1fef13b6eec3ce73bf06 +div_pure :: Benchmark +div_pure = bench "div_pure" $ nf (W.div_pure w0) w1 where + !w0 = W.to_word256 + 0x41cf50c7d0d65afabcf5ba37750dba71c7db29ec9f20a216d3ef013a59b9188a + !w1 = W.to_word256 + 0x066bd4c3c10e30260cb6e7832af25f15527b089b258a1fef13b6eec3ce73bf06 + div_baseline_small :: Benchmark div_baseline_small = bench "div, small (baseline)" $ nf (Prelude.div w0) w1 @@ -169,12 +176,13 @@ quotrem_by1_gen = main :: IO () main = defaultMain [ - quotrem_by1 - , quotrem_by1_gen - , mul_baseline - , mul - , div_baseline + -- quotrem_by1 + -- , quotrem_by1_gen + div_baseline + , div_pure , div + --, mul_baseline + --, mul --, mod_baseline --, mod --, div_baseline_small diff --git a/bench/Weight.hs b/bench/Weight.hs @@ -55,6 +55,7 @@ main = do 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) diff --git a/lib/Data/Word/Extended.hs b/lib/Data/Word/Extended.hs @@ -799,6 +799,16 @@ div a@(Word256 a0 a1 a2 a3) b@(Word256 b0 b1 b2 b3) 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 -- ? + | a == b = one + | is_word64 a = Word256 (a0 `quot` b0) 0 0 0 + | otherwise = + let !u = Word576 a0 a1 a2 a3 0 0 0 0 0 + !(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) @@ -822,3 +832,12 @@ mod a@(Word256 a0 a1 a2 a3) b@(Word256 b0 b1 b2 b3) 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 -- ? + | a `lt` b = a + | is_word64 a = Word256 (a0 `Prelude.rem` b0) 0 0 0 + | otherwise = + let !u = Word576 a0 a1 a2 a3 0 0 0 0 0 + !(Word832 _ r) = quotrem_gen u b + in r diff --git a/src/Main.hs b/src/Main.hs @@ -7,28 +7,25 @@ import Data.Word.Extended main :: IO () main = do - let !u = PA.primArrayFromList [ - 5152276743337338587 - , 6823823105342984773 - , 12649096328525870222 - , 8811572179372364942 - ] - !d = PA.primArrayFromList [ + let !u = Word576 + 5152276743337338587 + 6823823105342984773 + 12649096328525870222 + 8811572179372364942 + 0 0 0 0 0 + + !d = Word256 8849385646123010679 - , 653197174784954101 - , 1286679968202709238 - , 3741537094902495500 - ] + 653197174784954101 + 1286679968202709238 + 3741537094902495500 - quo <- PA.newPrimArray 5 let go !j !acc - | j == 10000 = pure () - | otherwise = do - PA.setPrimArray quo 0 5 0 - w <- quotrem quo u d - go (succ j) w - r <- go 0 zero - q <- PA.unsafeFreezePrimArray quo + | j == 10000 = acc + | otherwise = + let !(Word832 q r) = quotrem_gen u d + in go (succ j) (q, r) + (q, r) = go 0 (zero576, zero) print r print q diff --git a/test/Main.hs b/test/Main.hs @@ -148,12 +148,24 @@ div_matches (DivMonotonic (a, 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 + !rite = to_word256 (a `rem` b) + in left == rite + -- assertions ------------------------------------------------------------------ quotrem_r_case0 :: H.Assertion @@ -422,8 +434,12 @@ arithmetic = testGroup "arithmetic" [ 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 ] utils :: TestTree