commit 055c7bf6207e738c6b0ebf0743effb1a46fa96ec
parent 69a62ed7f735b369138719ce13687448655b7a8d
Author: Jared Tobin <jared@jtobin.io>
Date: Sat, 15 Nov 2025 15:03:01 +0400
lib: montgomery addition, subtraction
Diffstat:
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