fixed

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

commit 23973120631b32df3ce446f79550adb9c9d39dba
parent 96940abb678c1b3cfa9d6bae3bde43ac0fb584f9
Author: Jared Tobin <jared@jtobin.io>
Date:   Mon,  3 Feb 2025 11:19:26 +0400

test: mul_512#

Diffstat:
Mtest/Main.hs | 48++++++++++++++++++++++++++++++++++++++++++++++--
1 file changed, 46 insertions(+), 2 deletions(-)

diff --git a/test/Main.hs b/test/Main.hs @@ -6,7 +6,7 @@ module Main where -import Data.Bits ((.|.), (.&.), (.>>.), (.^.)) +import Data.Bits ((.|.), (.&.), (.>>.), (.<<.), (.^.)) import qualified Data.Bits as B import qualified Data.Primitive.PrimArray as PA import Data.Word.Extended @@ -22,6 +22,34 @@ fi :: (Integral a, Num b) => a -> b fi = fromIntegral {-# INLINE fi #-} +to_word512 + :: Integer + -> (# Word64#, Word64#, Word64#, Word64#, Word64#, Word64#, Word64#, Word64# #) +to_word512 n = + let !mask64 = 2 ^ (64 :: Int) - 1 + !(W64# w0) = fi (n .&. mask64) + !(W64# w1) = fi ((n .>>. 64) .&. mask64) + !(W64# w2) = fi ((n .>>. 128) .&. mask64) + !(W64# w3) = fi ((n .>>. 192) .&. mask64) + !(W64# w4) = fi ((n .>>. 256) .&. mask64) + !(W64# w5) = fi ((n .>>. 320) .&. mask64) + !(W64# w6) = fi ((n .>>. 384) .&. mask64) + !(W64# w7) = fi ((n .>>. 448) .&. mask64) + in (# w0, w1, w2, w3, w4, w5, w6, w7 #) + +word512_to_integer + :: (# Word64#, Word64#, Word64#, Word64#, Word64#, Word64#, Word64#, Word64# #) + -> Integer +word512_to_integer (# w0, w1, w2, w3, w4, w5, w6, w7 #) = + fi (W64# w7) .<<. 448 + .|. fi (W64# w6) .<<. 384 + .|. fi (W64# w5) .<<. 320 + .|. fi (W64# w4) .<<. 256 + .|. fi (W64# w3) .<<. 192 + .|. fi (W64# w2) .<<. 128 + .|. fi (W64# w1) .<<. 64 + .|. fi (W64# w0) + instance Q.Arbitrary Word256 where arbitrary = do w0 <- Q.arbitrary @@ -95,6 +123,15 @@ mul_lo_matches (Q.NonNegative a) (Q.NonNegative b) = in to_word256 a_lo `mul` to_word256 b_lo == to_word256 (a_lo * b_lo) +mul_512_matches :: Q.NonNegative Integer -> Q.NonNegative Integer -> Bool +mul_512_matches (Q.NonNegative a) (Q.NonNegative b) = + let !(Word256 (W64# a0) (W64# a1) (W64# a2) (W64# a3)) = to_word256 a + !(Word256 (W64# b0) (W64# b1) (W64# b2) (W64# b3)) = to_word256 b + !left = word512_to_integer $ + (# a0, a1, a2, a3 #) `mul_512#` (# b0, b1, b2, b3 #) + !rite = a * b + in left == rite + -- division ------------------------------ div_matches :: DivMonotonic -> Bool @@ -171,7 +208,13 @@ multiplication = testGroup "arithmetic" [ Q.withMaxSuccess 1000 umul_step_predicate_holds , Q.testProperty "mul matches (nonneg, low bits)" $ Q.withMaxSuccess 1000 mul_lo_matches - , Q.testProperty "division matches" $ + , Q.testProperty "mul_512# matches" $ + Q.withMaxSuccess 1000 mul_512_matches + ] + +division :: TestTree +division = testGroup "division" [ + Q.testProperty "division matches" $ Q.withMaxSuccess 1000 div_matches , Q.testProperty "mod matches" $ Q.withMaxSuccess 1000 mod_matches @@ -182,6 +225,7 @@ main = defaultMain $ testGroup "ppad-fixed" [ testGroup "property tests" [ add_sub , multiplication + , division ] , testGroup "unit tests" [ H.testCase "quotrem_r matches case0" quotrem_r_case0