fixed

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

commit b0321ca1234d755fbd5ae66cd8c9c24caffe8ea2
parent 2a39393f94c91e099447e61698a26d6978da54b7
Author: Jared Tobin <jared@jtobin.io>
Date:   Fri, 21 Nov 2025 14:44:50 +0400

lib: montgomery type

Diffstat:
Mlib/Numeric/Montgomery/Secp256k1/Curve.hs | 56+++++++++++++++++++++++++++++++-------------------------
Mlib/Numeric/Montgomery/Secp256k1/Scalar.hs | 56+++++++++++++++++++++++++++++++-------------------------
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)