fixed

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

commit 52e2d8acc1ef35a582b2f6986406e627530547e9
parent 4169d99ef8050faa7cc079ff3510f0b45c6e6582
Author: Jared Tobin <jared@jtobin.io>
Date:   Wed, 22 Jan 2025 14:32:29 +0400

lib: shorten data constructor name

Diffstat:
Mbench/Main.hs | 44++++++++++++++++++++++----------------------
Mlib/Data/Word/Extended.hs | 98+++++++++++++++++++++++++++++++++++++++----------------------------------------
Mtest/Main.hs | 6+++---
3 files changed, 73 insertions(+), 75 deletions(-)

diff --git a/bench/Main.hs b/bench/Main.hs @@ -13,52 +13,52 @@ instance NFData W.Word512 add_baseline :: Benchmark add_baseline = bench "add (baseline)" $ nf ((+) w0) w1 where w0, w1 :: Integer - w0 = 0x7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffed - w1 = 0x7fffffffffffffffffffffffffffffffffffffffffffffbfffffffffffffffed + !w0 = 0x7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffed + !w1 = 0x7fffffffffffffffffffffffffffffffffffffffffffffbfffffffffffffffed add :: Benchmark add = bench "add" $ nf (W.add w0) w1 where - w0 = W.to_word256 - 0x7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffed - w1 = W.to_word256 - 0x7fffffffffffffffffffffffffffffffffffffffffffffbfffffffffffffffed + !w0 = W.to_word256 + 0x7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffed + !w1 = W.to_word256 + 0x7fffffffffffffffffffffffffffffffffffffffffffffbfffffffffffffffed sub_baseline :: Benchmark sub_baseline = bench "sub (baseline)" $ nf ((-) w0) w1 where w0, w1 :: Integer - w0 = 0x7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffed - w1 = 0x7fffffffffffffffffffffffffffffffffffffffffffffbfffffffffffffffed + !w0 = 0x7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffed + !w1 = 0x7fffffffffffffffffffffffffffffffffffffffffffffbfffffffffffffffed sub :: Benchmark sub = bench "sub" $ nf (W.sub w0) w1 where - w0 = W.to_word256 - 0x7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffed - w1 = W.to_word256 - 0x7fffffffffffffffffffffffffffffffffffffffffffffbfffffffffffffffed + !w0 = W.to_word256 + 0x7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffed + !w1 = W.to_word256 + 0x7fffffffffffffffffffffffffffffffffffffffffffffbfffffffffffffffed mul_baseline :: Benchmark mul_baseline = bench "mul (baseline)" $ nf ((*) w0) w1 where w0, w1 :: Integer - w0 = 0x7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffed - w1 = 0x7fffffffffffffffffffffffffffffffffffffffffffffbfffffffffffffffed + !w0 = 0x7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffed + !w1 = 0x7fffffffffffffffffffffffffffffffffffffffffffffbfffffffffffffffed mul :: Benchmark mul = bench "mul" $ nf (W.mul_512 w0) w1 where - w0 = W.to_word256 - 0x7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffed - w1 = W.to_word256 - 0x7fffffffffffffffffffffffffffffffffffffffffffffbfffffffffffffffed + !w0 = W.to_word256 + 0x7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffed + !w1 = W.to_word256 + 0x7fffffffffffffffffffffffffffffffffffffffffffffbfffffffffffffffed mul128_baseline :: Benchmark mul128_baseline = bench "mul128 (baseline)" $ nf ((*) w0) w1 where w0, w1 :: Integer - w0 = 0x7fffffffffffffffffffffffffffffed - w1 = 0x7ffffffffffffffbffffffffffffffed + !w0 = 0x7fffffffffffffffffffffffffffffed + !w1 = 0x7ffffffffffffffbffffffffffffffed mul128 :: Benchmark mul128 = bench "mul128" $ nf (W.mul w0) w1 where - w0 = W.to_word256 0x7fffffffffffffffffffffffffffffed - w1 = W.to_word256 0x7ffffffffffffffbffffffffffffffed + !w0 = W.to_word256 0x7fffffffffffffffffffffffffffffed + !w1 = W.to_word256 0x7ffffffffffffffbffffffffffffffed main :: IO () main = defaultMain [ diff --git a/lib/Data/Word/Extended.hs b/lib/Data/Word/Extended.hs @@ -52,7 +52,6 @@ to_word256 n = !w3 = fi ((n .>>. 192) .&. mask64) in Word256 w0 w1 w2 w3 --- for testing word512_to_integer :: Word512 -> Integer word512_to_integer (Word512 w0 w1 w2 w3 w4 w5 w6 w7) = fi w7 .<<. 448 @@ -64,7 +63,6 @@ word512_to_integer (Word512 w0 w1 w2 w3 w4 w5 w6 w7) = .|. fi w1 .<<. 64 .|. fi w0 --- for testing to_word512 :: Integer -> Word512 to_word512 n = let !mask64 = 2 ^ (64 :: Int) - 1 @@ -81,7 +79,7 @@ to_word512 n = -- addition, subtraction ------------------------------------------------------ -- strict, unboxed pair of Word64 -data W64Pair = W64P +data W64Pair = P {-# UNPACK #-} !Word64 {-# UNPACK #-} !Word64 deriving (Eq, Show) @@ -92,7 +90,7 @@ add_c w64_0 w64_1 c = let !s = w64_0 + w64_1 + c !n | s < w64_0 || s < w64_1 = 1 | otherwise = 0 - in W64P s n + in P s n data Word256WithOverflow = Word256WithOverflow !Word256 @@ -102,10 +100,10 @@ data Word256WithOverflow = Word256WithOverflow -- addition with overflow indication add_of :: Word256 -> Word256 -> Word256WithOverflow add_of (Word256 a0 a1 a2 a3) (Word256 b0 b1 b2 b3) = - let !(W64P s0 c0) = add_c a0 b0 0 - !(W64P s1 c1) = add_c a1 b1 c0 - !(W64P s2 c2) = add_c a2 b2 c1 - !(W64P s3 c3) = add_c a3 b3 c2 + let !(P s0 c0) = add_c a0 b0 0 + !(P s1 c1) = add_c a1 b1 c0 + !(P s2 c2) = add_c a2 b2 c1 + !(P s3 c3) = add_c a3 b3 c2 in Word256WithOverflow (Word256 s0 s1 s2 s3) (c3 /= 0) @@ -121,14 +119,14 @@ sub_b w64_0 w64_1 b = let !d = w64_0 - w64_1 - b !n | w64_0 < w64_1 + b = 1 | otherwise = 0 - in W64P d n + in P d n sub_of :: Word256 -> Word256 -> Word256WithOverflow sub_of (Word256 a0 a1 a2 a3) (Word256 b0 b1 b2 b3) = - let !(W64P s0 c0) = sub_b a0 b0 0 - !(W64P s1 c1) = sub_b a1 b1 c0 - !(W64P s2 c2) = sub_b a2 b2 c1 - !(W64P s3 c3) = sub_b a3 b3 c2 + let !(P s0 c0) = sub_b a0 b0 0 + !(P s1 c1) = sub_b a1 b1 c0 + !(P s2 c2) = sub_b a2 b2 c1 + !(P s3 c3) = sub_b a3 b3 c2 in Word256WithOverflow (Word256 s0 s1 s2 s3) (c3 /= 0) @@ -148,8 +146,8 @@ mul_c :: Word64 -> Word64 -> W64Pair mul_c x y = let !mask32 = 0xffffffff !x0 = x .&. mask32 - !x1 = x .>>. 32 !y0 = y .&. mask32 + !x1 = x .>>. 32 !y1 = y .>>. 32 !w0 = x0 * y0 @@ -160,37 +158,37 @@ mul_c x y = !hi = x1 * y1 + w2 + w1_1 .>>. 32 !lo = x * y - in W64P hi lo + in P hi lo -- (hi * 2 ^ 64 + lo) = z + (x * y) umul_hop :: Word64 -> Word64 -> Word64 -> W64Pair umul_hop z x y = - let !(W64P hi_0 lo_0) = mul_c x y - !(W64P lo c) = add_c lo_0 z 0 - !(W64P hi _) = add_c hi_0 0 c - in W64P hi lo + let !(P hi_0 lo_0) = mul_c x y + !(P lo c) = add_c lo_0 z 0 + !(P hi _) = add_c hi_0 0 c + in P hi lo -- (hi * 2 ^ 64 + lo) = z + (x * y) + c umul_step :: Word64 -> Word64 -> Word64 -> Word64 -> W64Pair umul_step z x y c = - let !(W64P hi_0 lo_0) = mul_c x y - !(W64P lo_1 c_0) = add_c lo_0 c 0 - !(W64P hi_1 _) = add_c hi_0 0 c_0 - !(W64P lo c_1) = add_c lo_1 z 0 - !(W64P hi _) = add_c hi_1 0 c_1 - in W64P hi lo + let !(P hi_0 lo_0) = mul_c x y + !(P lo_1 c_0) = add_c lo_0 c 0 + !(P hi_1 _) = add_c hi_0 0 c_0 + !(P lo c_1) = add_c lo_1 z 0 + !(P hi _) = add_c hi_1 0 c_1 + in P hi lo -- | Multiplication on 'Word256' values, with overflow. mul :: Word256 -> Word256 -> Word256 mul (Word256 a0 a1 a2 a3) (Word256 b0 b1 b2 b3) = - let !(W64P c0_0 s0) = mul_c a0 b0 - !(W64P c0_1 r0) = umul_hop c0_0 a1 b0 - !(W64P c0_2 r1) = umul_hop c0_1 a2 b0 + let !(P c0_0 s0) = mul_c a0 b0 + !(P c0_1 r0) = umul_hop c0_0 a1 b0 + !(P c0_2 r1) = umul_hop c0_1 a2 b0 - !(W64P c1_0 s1) = umul_hop r0 a0 b1 - !(W64P c1_1 r2) = umul_step r1 a1 b1 c1_0 + !(P c1_0 s1) = umul_hop r0 a0 b1 + !(P c1_1 r2) = umul_step r1 a1 b1 c1_0 - !(W64P c2 s2) = umul_hop r2 a1 b1 + !(P c2 s2) = umul_hop r2 a1 b1 !s3 = a3 * b0 + a2 * b1 + a0 * b3 + a1 * b2 + c0_2 + c1_1 + c2 in Word256 s0 s1 s2 s3 @@ -198,24 +196,24 @@ mul (Word256 a0 a1 a2 a3) (Word256 b0 b1 b2 b3) = -- | Multiplication on 'Word256' values, to 'Word512'. mul_512 :: Word256 -> Word256 -> Word512 mul_512 (Word256 x0 x1 x2 x3) (Word256 y0 y1 y2 y3) = - let !(W64P c4_0 r0) = mul_c x0 y0 - !(W64P c4_1 r0_1) = umul_hop c4_0 x1 y0 - !(W64P c4_2 r0_2) = umul_hop c4_1 x2 y0 - !(W64P c4 r0_3) = umul_hop c4_2 x3 y0 - - !(W64P c5_0 r1) = umul_hop r0_1 x0 y1 - !(W64P c5_1 r1_2) = umul_step r0_2 x1 y1 c5_0 - !(W64P c5_2 r1_3) = umul_step r0_3 x2 y1 c5_1 - !(W64P c5 r1_4) = umul_step c4 x3 y1 c5_2 - - !(W64P c6_0 r2) = umul_hop r1_2 x0 y2 - !(W64P c6_1 r2_3) = umul_step r1_3 x1 y2 c6_0 - !(W64P c6_2 r2_4) = umul_step r1_4 x2 y2 c6_1 - !(W64P c6 r2_5) = umul_step c5 x3 y2 c6_2 - - !(W64P c7_0 r3) = umul_hop r2_3 x0 y3 - !(W64P c7_1 r4) = umul_step r2_4 x1 y3 c7_0 - !(W64P c7_2 r5) = umul_step r2_5 x2 y3 c7_1 - !(W64P r7 r6) = umul_step c6 x3 y3 c7_2 + let !(P c4_0 r0) = mul_c x0 y0 + !(P c4_1 r0_1) = umul_hop c4_0 x1 y0 + !(P c4_2 r0_2) = umul_hop c4_1 x2 y0 + !(P c4 r0_3) = umul_hop c4_2 x3 y0 + + !(P c5_0 r1) = umul_hop r0_1 x0 y1 + !(P c5_1 r1_2) = umul_step r0_2 x1 y1 c5_0 + !(P c5_2 r1_3) = umul_step r0_3 x2 y1 c5_1 + !(P c5 r1_4) = umul_step c4 x3 y1 c5_2 + + !(P c6_0 r2) = umul_hop r1_2 x0 y2 + !(P c6_1 r2_3) = umul_step r1_3 x1 y2 c6_0 + !(P c6_2 r2_4) = umul_step r1_4 x2 y2 c6_1 + !(P c6 r2_5) = umul_step c5 x3 y2 c6_2 + + !(P c7_0 r3) = umul_hop r2_3 x0 y3 + !(P c7_1 r4) = umul_step r2_4 x1 y3 c7_0 + !(P c7_2 r5) = umul_step r2_5 x2 y3 c7_1 + !(P r7 r6) = umul_step c6 x3 y3 c7_2 in Word512 r0 r1 r2 r3 r4 r5 r6 r7 diff --git a/test/Main.hs b/test/Main.hs @@ -35,19 +35,19 @@ mul_c_matches a b = c_hi = fi (c .>>. 64) :: Word64 c_lo = fi (c .&. 0xffffffffffffffff) :: Word64 - W64P hi lo = mul_c a b + P hi lo = mul_c a b in hi == c_hi && lo == c_lo -- (hi * 2 ^ 64 + lo) = z + (x * y) umul_hop_predicate_holds :: Word64 -> Word64 -> Word64 -> Bool umul_hop_predicate_holds z x y = - let !(W64P hi lo) = umul_hop z x y + let !(P hi lo) = umul_hop z x y in fi hi * 2 ^ (64 :: Int) + fi lo == (fi z + (fi x * fi y) :: Integer) -- (hi * 2 ^ 64 + lo) = z + (x * y) + c umul_step_predicate_holds :: Word64 -> Word64 -> Word64 -> Word64 -> Bool umul_step_predicate_holds z x y c = - let !(W64P hi lo) = umul_step z x y c + let !(P hi lo) = umul_step z x y c !left = fi hi * 2 ^ (64 :: Int) + fi lo :: Integer !rite = fi z + (fi x * fi y) + fi c :: Integer in left == rite