fixed

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

commit 055c7bf6207e738c6b0ebf0743effb1a46fa96ec
parent 69a62ed7f735b369138719ce13687448655b7a8d
Author: Jared Tobin <jared@jtobin.io>
Date:   Sat, 15 Nov 2025 15:03:01 +0400

lib: montgomery addition, subtraction

Diffstat:
Mlib/Data/Word/Montgomery.hs | 22++++++++++++++++++++++
Mlib/Data/Word/Wider.hs | 24++++++++++++++++++++++++
2 files changed, 46 insertions(+), 0 deletions(-)

diff --git a/lib/Data/Word/Montgomery.hs b/lib/Data/Word/Montgomery.hs @@ -308,3 +308,25 @@ to (Wider x) (Wider r2) (Wider m) (W# n) = Wider (to# x r2 m n) from :: Wider -> Wider -> Word -> Wider from = retr +add# + :: (# Word#, Word#, Word#, Word# #) -- ^ augend + -> (# Word#, Word#, Word#, Word# #) -- ^ addend + -> (# Word#, Word#, Word#, Word# #) -- ^ modulus + -> (# Word#, Word#, Word#, Word# #) -- ^ sum +add# a b m = WW.add_mod# a b m +{-# INLINE add# #-} + +add :: Wider -> Wider -> Wider -> Wider +add (Wider a) (Wider b) (Wider m) = Wider (add# a b m) + +sub# + :: (# Word#, Word#, Word#, Word# #) -- ^ minuend + -> (# Word#, Word#, Word#, Word# #) -- ^ subtrahend + -> (# Word#, Word#, Word#, Word# #) -- ^ modulus + -> (# Word#, Word#, Word#, Word# #) -- ^ difference +sub# a b m = WW.sub_mod# a b m +{-# INLINE sub# #-} + +sub :: Wider -> Wider -> Wider -> Wider +sub (Wider a) (Wider b) (Wider m) = Wider (sub# a b m) + diff --git a/lib/Data/Word/Wider.hs b/lib/Data/Word/Wider.hs @@ -99,6 +99,17 @@ add_w# a b = in c {-# INLINE add_w# #-} +-- | Modular addition. +add_mod# + :: (# Word#, Word#, Word#, Word# #) -- ^ augend + -> (# Word#, Word#, Word#, Word# #) -- ^ addend + -> (# Word#, Word#, Word#, Word# #) -- ^ modulus + -> (# Word#, Word#, Word#, Word# #) -- ^ sum +add_mod# a b m = + let !(# w, c #) = add_c# a b + in sub_mod_c# w c m m +{-# INLINE add_mod# #-} + -- | Borrowing subtraction, computing 'a - b' and returning the -- difference with a borrow bit. sub_b# @@ -113,6 +124,19 @@ sub_b# (# a0, a1, a2, a3 #) (# b0, b1, b2, b3 #) = in (# (# s0, s1, s2, s3 #), c3 #) {-# INLINE sub_b# #-} +-- | Modular subtraction. Computes a - b mod m. +sub_mod# + :: (# Word#, Word#, Word#, Word# #) -- ^ minuend + -> (# Word#, Word#, Word#, Word# #) -- ^ subtrahend + -> (# Word#, Word#, Word#, Word# #) -- ^ modulus + -> (# Word#, Word#, Word#, Word# #) -- ^ difference +sub_mod# a b (# p0, p1, p2, p3 #) = + let !(# (# o0, o1, o2, o3 #), bb #) = sub_b# a b + !mask = wrapping_neg# bb + !band = (# and# p0 mask, and# p1 mask, and# p2 mask, and# p3 mask #) + in add_w# (# o0, o1, o2, o3 #) band +{-# INLINE sub_mod# #-} + -- | Modular subtraction with carry. Computes (# a, c #) - b mod m. sub_mod_c# :: (# Word#, Word#, Word#, Word# #) -- ^ minuend