fixed

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

commit 6f67dddf52e9bae312d876d9f0becddd22d034fa
parent fa3b1c1cbe8d22ef9a87c02472d67b1b65c7c6ab
Author: Jared Tobin <jared@jtobin.io>
Date:   Wed, 22 Jan 2025 21:57:35 +0400

lib: s/W64Pair/Word128

Diffstat:
Mbench/Main.hs | 3++-
Mlib/Data/Word/Extended.hs | 26+++++++++++++-------------
2 files changed, 15 insertions(+), 14 deletions(-)

diff --git a/bench/Main.hs b/bench/Main.hs @@ -42,8 +42,9 @@ mul_baseline = bench "mul (baseline)" $ nf ((*) w0) w1 where !w0 = 0x7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffed !w1 = 0x7fffffffffffffffffffffffffffffffffffffffffffffbfffffffffffffffed +-- XX overflows; unsure if valid comparison mul :: Benchmark -mul = bench "mul" $ nf (W.mul_512 w0) w1 where +mul = bench "mul" $ nf (W.mul w0) w1 where !w0 = W.to_word256 0x7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffed !w1 = W.to_word256 diff --git a/lib/Data/Word/Extended.hs b/lib/Data/Word/Extended.hs @@ -36,6 +36,12 @@ data Word512 = Word512 {-# UNPACK #-} !Word64 deriving (Eq, Show, Generic) +-- just for holding a couple of word64's +data Word128 = P + {-# UNPACK #-} !Word64 + {-# UNPACK #-} !Word64 + deriving (Eq, Show) + -- conversion ----------------------------------------------------------------- to_integer :: Word256 -> Integer @@ -80,12 +86,6 @@ to_word512 n = -- addition, subtraction ------------------------------------------------------ --- strict, unboxed pair of Word64 -data W64Pair = P - {-# UNPACK #-} !Word64 - {-# UNPACK #-} !Word64 - deriving (Eq, Show) - -- add-with-carry -- -- x86-64 ADDQ rX, rY @@ -93,7 +93,7 @@ data W64Pair = P -- -- ARM ADDS -- ADC -add_c :: Word64 -> Word64 -> Word64 -> W64Pair +add_c :: Word64 -> Word64 -> Word64 -> Word128 add_c w64_0 w64_1 c = let !s = w64_0 + w64_1 + c !n | s < w64_0 || s < w64_1 = 1 @@ -127,7 +127,7 @@ add w0 w1 = s where -- -- ARM SUBS -- SBC -sub_b :: Word64 -> Word64 -> Word64 -> W64Pair +sub_b :: Word64 -> Word64 -> Word64 -> Word128 sub_b w64_0 w64_1 b = let !d = w64_0 - w64_1 - b !n | w64_0 < w64_1 + b = 1 @@ -155,7 +155,7 @@ sub w0 w1 = d where -- ARM UMULH -- -- translated from Mul64 in go's math/bits package -mul_c :: Word64 -> Word64 -> W64Pair +mul_c :: Word64 -> Word64 -> Word128 mul_c x y = let !mask32 = 0xffffffff !x0 = x .&. mask32 @@ -174,7 +174,7 @@ mul_c x y = in P hi lo -- (hi * 2 ^ 64 + lo) = z + (x * y) -umul_hop :: Word64 -> Word64 -> Word64 -> W64Pair +umul_hop :: Word64 -> Word64 -> Word64 -> Word128 umul_hop z x y = let !(P hi_0 lo_0) = mul_c x y !(P lo c) = add_c lo_0 z 0 @@ -182,7 +182,7 @@ umul_hop z x y = in P hi lo -- (hi * 2 ^ 64 + lo) = z + (x * y) + c -umul_step :: Word64 -> Word64 -> Word64 -> Word64 -> W64Pair +umul_step :: Word64 -> Word64 -> Word64 -> Word64 -> Word128 umul_step z x y c = let !(P hi_0 lo_0) = mul_c x y !(P lo_1 c_0) = add_c lo_0 c 0 @@ -260,7 +260,7 @@ sub_mul (Word256 x0 x1 x2 x3) (Word256 y0 y1 y2 y3) m = -- translated from Div64 in go's math/bits package -- -- x86-64 (RDX:RAX) DIVQ -quotrem_r :: Word64 -> Word64 -> Word64 -> W64Pair +quotrem_r :: Word64 -> Word64 -> Word64 -> Word128 quotrem_r hi lo y_0 | y_0 == 0 = error "ppad-fixed: division by zero" | y_0 <= hi = error "ppad-fixed: overflow" @@ -307,7 +307,7 @@ recip_2by1 :: Word64 -> Word64 recip_2by1 d = r where !(P r _) = quotrem_r (B.complement d) 0xffffffffffffffff d -quotrem_2by1 :: Word64 -> Word64 -> Word64 -> Word64 -> W64Pair +quotrem_2by1 :: Word64 -> Word64 -> Word64 -> Word64 -> Word128 quotrem_2by1 uh ul d rec = let !(P qh_0 ql) = mul_c rec uh !(P ql_0 c) = add_c ql ul 0