commit b0321ca1234d755fbd5ae66cd8c9c24caffe8ea2
parent 2a39393f94c91e099447e61698a26d6978da54b7
Author: Jared Tobin <jared@jtobin.io>
Date: Fri, 21 Nov 2025 14:44:50 +0400
lib: montgomery type
Diffstat:
2 files changed, 62 insertions(+), 50 deletions(-)
diff --git a/lib/Numeric/Montgomery/Secp256k1/Curve.hs b/lib/Numeric/Montgomery/Secp256k1/Curve.hs
@@ -8,6 +8,7 @@
module Numeric.Montgomery.Secp256k1.Curve where
+import Control.DeepSeq
import qualified Data.Word.Limb as L
import qualified Data.Word.Wide as W
import Data.Word.Wider (Wider(..))
@@ -18,6 +19,11 @@ import Prelude hiding (div, mod, or, and, not, quot, rem, recip)
-- montgomery arithmetic, specialized to the secp256k1 field prime modulus
-- 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFC2F
+data Montgomery = Montgomery (# Word#, Word#, Word#, Word# #)
+
+instance NFData Montgomery where
+ rnf (Montgomery a) = case a of (# _, _, _, _ #) -> ()
+
-- XX define constants here, current approach is fragile
-- utilities ------------------------------------------------------------------
@@ -112,10 +118,10 @@ redc# l u =
in WW.sub_mod_c# nu mc m m
{-# INLINE redc# #-}
-redc :: Wider -> Wider -> Wider
-redc (Wider l) (Wider u) =
+redc :: Montgomery -> Montgomery -> Montgomery
+redc (Montgomery l) (Montgomery u) =
let !res = redc# l u
- in (Wider res)
+ in (Montgomery res)
retr_inner#
:: (# Word#, Word#, Word#, Word# #) -- ^ value in montgomery form
@@ -168,9 +174,9 @@ retr# f = retr_inner# f
{-# INLINE retr# #-}
retr
- :: Wider -- ^ value in montgomery form
- -> Wider -- ^ retrieved value
-retr (Wider f) =
+ :: Montgomery -- ^ value in montgomery form
+ -> Wider -- ^ retrieved value
+retr (Montgomery f) =
let !res = retr# f
in (Wider res)
@@ -291,10 +297,10 @@ mul# a b =
{-# NOINLINE mul# #-} -- cannot be inlined without exploding comp time
mul
- :: Wider -- ^ lhs in montgomery form
- -> Wider -- ^ rhs in montgomery form
- -> Wider -- ^ montgomery product
-mul (Wider a) (Wider b) = Wider (mul# a b)
+ :: Montgomery -- ^ lhs in montgomery form
+ -> Montgomery -- ^ rhs in montgomery form
+ -> Montgomery -- ^ montgomery product
+mul (Montgomery a) (Montgomery b) = Montgomery (mul# a b)
to#
:: (# Word#, Word#, Word#, Word# #) -- ^ integer
@@ -304,10 +310,10 @@ to# x =
in mul# x r2
{-# INLINE to# #-}
-to :: Wider -> Wider
-to (Wider x) = Wider (to# x)
+to :: Wider -> Montgomery
+to (Wider x) = Montgomery (to# x)
-from :: Wider -> Wider
+from :: Montgomery -> Wider
from = retr
-- | Addition in the Montgomery domain.
@@ -321,8 +327,8 @@ add# a b =
in WW.add_mod# a b m
{-# INLINE add# #-}
-add :: Wider -> Wider -> Wider
-add (Wider a) (Wider b) = Wider (add# a b)
+add :: Montgomery -> Montgomery -> Montgomery
+add (Montgomery a) (Montgomery b) = Montgomery (add# a b)
-- | Subtraction in the Montgomery domain.
sub#
@@ -335,8 +341,8 @@ sub# a b =
in WW.sub_mod# a b m
{-# INLINE sub# #-}
-sub :: Wider -> Wider -> Wider
-sub (Wider a) (Wider b) = Wider (sub# a b)
+sub :: Montgomery -> Montgomery -> Montgomery
+sub (Montgomery a) (Montgomery b) = Montgomery (sub# a b)
-- | Modular negation in the Montgomery domain.
neg#
@@ -345,18 +351,18 @@ neg#
neg# a = sub# (# 0##, 0##, 0##, 0## #) a
{-# INLINE neg# #-}
-neg :: Wider -> Wider
-neg (Wider a) = Wider (neg# a)
+neg :: Montgomery -> Montgomery
+neg (Montgomery a) = Montgomery (neg# a)
sqr# :: (# Word#, Word#, Word#, Word# #) -> (# Word#, Word#, Word#, Word# #)
sqr# a = mul# a a
{-# INLINE sqr# #-}
-sqr :: Wider -> Wider
-sqr (Wider a) = Wider (mul# a a)
+sqr :: Montgomery -> Montgomery
+sqr (Montgomery a) = Montgomery (mul# a a)
-one :: Wider
-one = Wider (# 0x1000003D1##, 0##, 0##, 0## #)
+one :: Montgomery
+one = Montgomery (# 0x1000003D1##, 0##, 0##, 0## #)
-- generated by etc/generate_inv.sh
inv#
@@ -873,5 +879,5 @@ inv# a =
in r
{-# INLINE inv# #-}
-inv :: Wider -> Wider
-inv (Wider w) = Wider (inv# w)
+inv :: Montgomery -> Montgomery
+inv (Montgomery w) = Montgomery (inv# w)
diff --git a/lib/Numeric/Montgomery/Secp256k1/Scalar.hs b/lib/Numeric/Montgomery/Secp256k1/Scalar.hs
@@ -8,6 +8,7 @@
module Numeric.Montgomery.Secp256k1.Scalar where
+import Control.DeepSeq
import qualified Data.Word.Limb as L
import qualified Data.Word.Wide as W
import Data.Word.Wider (Wider(..))
@@ -18,6 +19,11 @@ import Prelude hiding (div, mod, or, and, not, quot, rem, recip)
-- montgomery arithmetic, specialized to the secp256k1 scalar group order
-- 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEBAAEDCE6AF48A03BBFD25E8CD0364141
+data Montgomery = Montgomery (# Word#, Word#, Word#, Word# #)
+
+instance NFData Montgomery where
+ rnf (Montgomery a) = case a of (# _, _, _, _ #) -> ()
+
-- XX define constants here, current approach is fragile
-- utilities ------------------------------------------------------------------
@@ -112,10 +118,10 @@ redc# l u =
in WW.sub_mod_c# nu mc m m
{-# INLINE redc# #-}
-redc :: Wider -> Wider -> Wider
-redc (Wider l) (Wider u) =
+redc :: Montgomery -> Montgomery -> Montgomery
+redc (Montgomery l) (Montgomery u) =
let !res = redc# l u
- in (Wider res)
+ in (Montgomery res)
retr_inner#
:: (# Word#, Word#, Word#, Word# #) -- ^ value in montgomery form
@@ -168,9 +174,9 @@ retr# f = retr_inner# f
{-# INLINE retr# #-}
retr
- :: Wider -- ^ value in montgomery form
- -> Wider -- ^ retrieved value
-retr (Wider f) =
+ :: Montgomery -- ^ value in montgomery form
+ -> Wider -- ^ retrieved value
+retr (Montgomery f) =
let !res = retr# f
in (Wider res)
@@ -291,10 +297,10 @@ mul# a b =
{-# NOINLINE mul# #-} -- cannot be inlined without exploding comp time
mul
- :: Wider -- ^ lhs in montgomery form
- -> Wider -- ^ rhs in montgomery form
- -> Wider -- ^ montgomery product
-mul (Wider a) (Wider b) = Wider (mul# a b)
+ :: Montgomery -- ^ lhs in montgomery form
+ -> Montgomery -- ^ rhs in montgomery form
+ -> Montgomery -- ^ montgomery product
+mul (Montgomery a) (Montgomery b) = Montgomery (mul# a b)
to#
:: (# Word#, Word#, Word#, Word# #) -- ^ integer
@@ -305,10 +311,10 @@ to# x =
in mul# x r2
{-# INLINE to# #-}
-to :: Wider -> Wider
-to (Wider x) = Wider (to# x)
+to :: Wider -> Montgomery
+to (Wider x) = Montgomery (to# x)
-from :: Wider -> Wider
+from :: Montgomery -> Wider
from = retr
-- | Addition in the Montgomery domain.
@@ -322,8 +328,8 @@ add# a b =
in WW.add_mod# a b m
{-# INLINE add# #-}
-add :: Wider -> Wider -> Wider
-add (Wider a) (Wider b) = Wider (add# a b)
+add :: Montgomery -> Montgomery -> Montgomery
+add (Montgomery a) (Montgomery b) = Montgomery (add# a b)
-- | Subtraction in the Montgomery domain.
sub#
@@ -336,8 +342,8 @@ sub# a b =
in WW.sub_mod# a b m
{-# INLINE sub# #-}
-sub :: Wider -> Wider -> Wider
-sub (Wider a) (Wider b) = Wider (sub# a b)
+sub :: Montgomery -> Montgomery -> Montgomery
+sub (Montgomery a) (Montgomery b) = Montgomery (sub# a b)
-- | Modular negation in the Montgomery domain.
neg#
@@ -346,18 +352,18 @@ neg#
neg# a = sub# (# 0##, 0##, 0##, 0## #) a
{-# INLINE neg# #-}
-neg :: Wider -> Wider
-neg (Wider a) = Wider (neg# a)
+neg :: Montgomery -> Montgomery
+neg (Montgomery a) = Montgomery (neg# a)
sqr# :: (# Word#, Word#, Word#, Word# #) -> (# Word#, Word#, Word#, Word# #)
sqr# a = mul# a a
{-# INLINE sqr# #-}
-sqr :: Wider -> Wider
-sqr (Wider a) = Wider (mul# a a)
+sqr :: Montgomery -> Montgomery
+sqr (Montgomery a) = Montgomery (mul# a a)
-one :: Wider
-one = Wider (# 0x402DA1732FC9BEBF##, 0x4551231950B75FC4##
+one :: Montgomery
+one = Montgomery (# 0x402DA1732FC9BEBF##, 0x4551231950B75FC4##
, 0x0000000000000001##, 0x0000000000000000## #)
-- generated by etc/generate_inv.sh
@@ -823,6 +829,6 @@ inv# a =
in r
{-# INLINE inv# #-}
-inv :: Wider -> Wider
-inv (Wider w) = Wider (inv# w)
+inv :: Montgomery -> Montgomery
+inv (Montgomery w) = Montgomery (inv# w)