{-# LANGUAGE BangPatterns, DataKinds, KindSignatures, TypeFamilies #-}
{-# LANGUAGE ExistentialQuantification, StandaloneDeriving #-}
module Math.FiniteField.PrimeField.Small
(
WitnessFp(..)
, SomeWitnessFp(..)
, mkSmallPrimeField
, unsafeSmallPrimeField
, Fp
, primRoot
)
where
import Data.Bits
import Data.Int
import Data.Word
import GHC.TypeNats (Nat)
import System.Random ( RandomGen , randomR )
import Math.FiniteField.Primes
import Math.FiniteField.TypeLevel
import Math.FiniteField.Class
import Math.FiniteField.Conway.Internal ( lookupConwayPrimRoot_ )
import qualified Math.FiniteField.PrimeField.Small.Raw as Raw
newtype WitnessFp (p :: Nat)
= WitnessFp { WitnessFp p -> IsSmallPrime p
fromWitnessFp :: IsSmallPrime p }
deriving Int -> WitnessFp p -> ShowS
[WitnessFp p] -> ShowS
WitnessFp p -> String
(Int -> WitnessFp p -> ShowS)
-> (WitnessFp p -> String)
-> ([WitnessFp p] -> ShowS)
-> Show (WitnessFp p)
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
forall (p :: Nat). Int -> WitnessFp p -> ShowS
forall (p :: Nat). [WitnessFp p] -> ShowS
forall (p :: Nat). WitnessFp p -> String
showList :: [WitnessFp p] -> ShowS
$cshowList :: forall (p :: Nat). [WitnessFp p] -> ShowS
show :: WitnessFp p -> String
$cshow :: forall (p :: Nat). WitnessFp p -> String
showsPrec :: Int -> WitnessFp p -> ShowS
$cshowsPrec :: forall (p :: Nat). Int -> WitnessFp p -> ShowS
Show
data SomeWitnessFp
= forall p. SomeWitnessFp (WitnessFp p)
deriving instance Show SomeWitnessFp
mkSmallPrimeField :: Int -> Maybe SomeWitnessFp
mkSmallPrimeField :: Int -> Maybe SomeWitnessFp
mkSmallPrimeField Int
p = case Int64 -> SomeSNat64
someSNat64 (Int -> Int64
forall a b. (Integral a, Num b) => a -> b
fromIntegral Int
p) of
SomeSNat64 SNat64 n
sp -> (WitnessFp n -> SomeWitnessFp
forall (p :: Nat). WitnessFp p -> SomeWitnessFp
SomeWitnessFp (WitnessFp n -> SomeWitnessFp)
-> (IsSmallPrime n -> WitnessFp n)
-> IsSmallPrime n
-> SomeWitnessFp
forall b c a. (b -> c) -> (a -> b) -> a -> c
. IsSmallPrime n -> WitnessFp n
forall (p :: Nat). IsSmallPrime p -> WitnessFp p
WitnessFp) (IsSmallPrime n -> SomeWitnessFp)
-> Maybe (IsSmallPrime n) -> Maybe SomeWitnessFp
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> SNat64 n -> Maybe (IsSmallPrime n)
forall (n :: Nat). SNat64 n -> Maybe (IsSmallPrime n)
isSmallPrime SNat64 n
sp
unsafeSmallPrimeField :: Int -> SomeWitnessFp
unsafeSmallPrimeField :: Int -> SomeWitnessFp
unsafeSmallPrimeField Int
p = case Int64 -> SomeSNat64
someSNat64 (Int -> Int64
forall a b. (Integral a, Num b) => a -> b
fromIntegral Int
p) of
SomeSNat64 SNat64 n
sp -> WitnessFp n -> SomeWitnessFp
forall (p :: Nat). WitnessFp p -> SomeWitnessFp
SomeWitnessFp (IsSmallPrime n -> WitnessFp n
forall (p :: Nat). IsSmallPrime p -> WitnessFp p
WitnessFp (SNat64 n -> IsSmallPrime n
forall (n :: Nat). SNat64 n -> IsSmallPrime n
believeMeItsASmallPrime SNat64 n
sp))
data Fp (p :: Nat)
= Fp {-# UNPACK #-} !(IsSmallPrime p) {-# UNPACK #-} !Word64
fpWitness :: Fp p -> WitnessFp p
fpWitness :: Fp p -> WitnessFp p
fpWitness (Fp IsSmallPrime p
p Word64
_) = IsSmallPrime p -> WitnessFp p
forall (p :: Nat). IsSmallPrime p -> WitnessFp p
WitnessFp IsSmallPrime p
p
fp :: IsSmallPrime p -> Word64 -> Fp p
fp :: IsSmallPrime p -> Word64 -> Fp p
fp !IsSmallPrime p
p !Word64
n
| Word64
n Word64 -> Word64 -> Bool
forall a. Ord a => a -> a -> Bool
>= Word64
0 Bool -> Bool -> Bool
&& Word64
n Word64 -> Word64 -> Bool
forall a. Ord a => a -> a -> Bool
< Word64
q = IsSmallPrime p -> Word64 -> Fp p
forall (p :: Nat). IsSmallPrime p -> Word64 -> Fp p
Fp IsSmallPrime p
p Word64
n
| Bool
otherwise = IsSmallPrime p -> Word64 -> Fp p
forall (p :: Nat). IsSmallPrime p -> Word64 -> Fp p
Fp IsSmallPrime p
p (Word64 -> Word64 -> Word64
forall a. Integral a => a -> a -> a
mod Word64
n Word64
q)
where
!q :: Word64
q = IsSmallPrime p -> Word64
forall (n :: Nat). IsSmallPrime n -> Word64
fromSmallPrime IsSmallPrime p
p
randomFp :: RandomGen gen => IsSmallPrime p -> gen -> (Fp p, gen)
randomFp :: IsSmallPrime p -> gen -> (Fp p, gen)
randomFp !IsSmallPrime p
p !gen
gen = case (Word64, Word64) -> gen -> (Word64, gen)
forall a g. (Random a, RandomGen g) => (a, a) -> g -> (a, g)
randomR (Word64
0,Word64
qWord64 -> Word64 -> Word64
forall a. Num a => a -> a -> a
-Word64
1) gen
gen of { (Word64
x, gen
gen') -> (IsSmallPrime p -> Word64 -> Fp p
forall (p :: Nat). IsSmallPrime p -> Word64 -> Fp p
Fp IsSmallPrime p
p Word64
x, gen
gen') } where !q :: Word64
q = IsSmallPrime p -> Word64
forall (n :: Nat). IsSmallPrime n -> Word64
fromSmallPrime IsSmallPrime p
p
randomInvFp :: RandomGen gen => IsSmallPrime p -> gen -> (Fp p, gen)
randomInvFp :: IsSmallPrime p -> gen -> (Fp p, gen)
randomInvFp !IsSmallPrime p
p !gen
gen = case (Word64, Word64) -> gen -> (Word64, gen)
forall a g. (Random a, RandomGen g) => (a, a) -> g -> (a, g)
randomR (Word64
1,Word64
qWord64 -> Word64 -> Word64
forall a. Num a => a -> a -> a
-Word64
1) gen
gen of { (Word64
x, gen
gen') -> (IsSmallPrime p -> Word64 -> Fp p
forall (p :: Nat). IsSmallPrime p -> Word64 -> Fp p
Fp IsSmallPrime p
p Word64
x, gen
gen') } where !q :: Word64
q = IsSmallPrime p -> Word64
forall (n :: Nat). IsSmallPrime n -> Word64
fromSmallPrime IsSmallPrime p
p
fpOrder :: Fp p -> Word64
fpOrder :: Fp p -> Word64
fpOrder (Fp IsSmallPrime p
p Word64
_) = Word64 -> Word64
forall a b. (Integral a, Num b) => a -> b
fromIntegral (IsSmallPrime p -> Word64
forall (n :: Nat). IsSmallPrime n -> Word64
fromSmallPrime IsSmallPrime p
p)
modp :: Word64 -> IsSmallPrime p -> Word64
modp :: Word64 -> IsSmallPrime p -> Word64
modp !Word64
x !IsSmallPrime p
p = Word64 -> Word64 -> Word64
forall a. Integral a => a -> a -> a
mod Word64
x (IsSmallPrime p -> Word64
forall (n :: Nat). IsSmallPrime n -> Word64
fromSmallPrime IsSmallPrime p
p)
modpInteger :: Integer -> IsSmallPrime p -> Word64
modpInteger :: Integer -> IsSmallPrime p -> Word64
modpInteger Integer
x IsSmallPrime p
p = Integer -> Word64
forall a b. (Integral a, Num b) => a -> b
fromIntegral (Integer -> Integer -> Integer
forall a. Integral a => a -> a -> a
mod Integer
x (Word64 -> Integer
forall a b. (Integral a, Num b) => a -> b
fromIntegral (IsSmallPrime p -> Word64
forall (n :: Nat). IsSmallPrime n -> Word64
fromSmallPrime IsSmallPrime p
p)))
modpSigned :: Int64 -> IsSmallPrime p -> Int64
modpSigned :: Int64 -> IsSmallPrime p -> Int64
modpSigned Int64
x IsSmallPrime p
p = Int64 -> Int64 -> Int64
forall a. Integral a => a -> a -> a
mod Int64
x (IsSmallPrime p -> Int64
forall (n :: Nat). IsSmallPrime n -> Int64
fromSmallPrimeSigned IsSmallPrime p
p)
primRoot :: IsSmallPrime p -> Fp p
primRoot :: IsSmallPrime p -> Fp p
primRoot IsSmallPrime p
p = case Int -> Maybe Word64
lookupConwayPrimRoot_ (Word64 -> Int
forall a b. (Integral a, Num b) => a -> b
fromIntegral (IsSmallPrime p -> Word64
forall (n :: Nat). IsSmallPrime n -> Word64
fromSmallPrime IsSmallPrime p
p)) of
Just Word64
g -> IsSmallPrime p -> Word64 -> Fp p
forall (p :: Nat). IsSmallPrime p -> Word64 -> Fp p
fp IsSmallPrime p
p (Word64 -> Word64
forall a b. (Integral a, Num b) => a -> b
fromIntegral Word64
g)
Maybe Word64
Nothing -> String -> Fp p
forall a. HasCallStack => String -> a
error String
"PrimeField/Small/Fp/primRoot: primitive generator not found in the Conway table"
enumerateFp :: IsSmallPrime p -> [Fp p]
enumerateFp :: IsSmallPrime p -> [Fp p]
enumerateFp IsSmallPrime p
p = [ IsSmallPrime p -> Word64 -> Fp p
forall (p :: Nat). IsSmallPrime p -> Word64 -> Fp p
Fp IsSmallPrime p
p Word64
k | Word64
k <- [Word64
0..IsSmallPrime p -> Word64
forall (n :: Nat). IsSmallPrime n -> Word64
fromSmallPrime IsSmallPrime p
pWord64 -> Word64 -> Word64
forall a. Num a => a -> a -> a
-Word64
1] ]
instance Eq (Fp p) where
== :: Fp p -> Fp p -> Bool
(==) (Fp IsSmallPrime p
_ Word64
x) (Fp IsSmallPrime p
_ Word64
y) = Word64
x Word64 -> Word64 -> Bool
forall a. Eq a => a -> a -> Bool
== Word64
y
instance Ord (Fp p) where
compare :: Fp p -> Fp p -> Ordering
compare (Fp IsSmallPrime p
_ Word64
x) (Fp IsSmallPrime p
_ Word64
y) = Word64 -> Word64 -> Ordering
forall a. Ord a => a -> a -> Ordering
compare Word64
x Word64
y
instance Show (Fp p) where
show :: Fp p -> String
show (Fp IsSmallPrime p
p Word64
k) = String
"(" String -> ShowS
forall a. [a] -> [a] -> [a]
++ Word64 -> String
forall a. Show a => a -> String
show Word64
k String -> ShowS
forall a. [a] -> [a] -> [a]
++ String
" mod " String -> ShowS
forall a. [a] -> [a] -> [a]
++ Word64 -> String
forall a. Show a => a -> String
show (IsSmallPrime p -> Word64
forall (n :: Nat). IsSmallPrime n -> Word64
fromSmallPrime IsSmallPrime p
p) String -> ShowS
forall a. [a] -> [a] -> [a]
++ String
")"
instance Num (Fp p) where
fromInteger :: Integer -> Fp p
fromInteger = String -> Integer -> Fp p
forall a. HasCallStack => String -> a
error String
"PrimeField/Small/Fp/fromInteger: cannot be defined; use `embed` instead"
negate :: Fp p -> Fp p
negate (Fp IsSmallPrime p
p Word64
x) = IsSmallPrime p -> Word64 -> Fp p
forall (p :: Nat). IsSmallPrime p -> Word64 -> Fp p
Fp IsSmallPrime p
p (Word64 -> Word64 -> Word64
Raw.neg (IsSmallPrime p -> Word64
forall (n :: Nat). IsSmallPrime n -> Word64
fromSmallPrime IsSmallPrime p
p) Word64
x)
+ :: Fp p -> Fp p -> Fp p
(+) (Fp IsSmallPrime p
p Word64
x) (Fp IsSmallPrime p
_ Word64
y) = IsSmallPrime p -> Word64 -> Fp p
forall (p :: Nat). IsSmallPrime p -> Word64 -> Fp p
Fp IsSmallPrime p
p (Word64 -> Word64 -> Word64 -> Word64
Raw.add (IsSmallPrime p -> Word64
forall (n :: Nat). IsSmallPrime n -> Word64
fromSmallPrime IsSmallPrime p
p) Word64
x Word64
y)
(-) (Fp IsSmallPrime p
p Word64
x) (Fp IsSmallPrime p
_ Word64
y) = IsSmallPrime p -> Word64 -> Fp p
forall (p :: Nat). IsSmallPrime p -> Word64 -> Fp p
Fp IsSmallPrime p
p (Word64 -> Word64 -> Word64 -> Word64
Raw.sub (IsSmallPrime p -> Word64
forall (n :: Nat). IsSmallPrime n -> Word64
fromSmallPrime IsSmallPrime p
p) Word64
x Word64
y)
* :: Fp p -> Fp p -> Fp p
(*) (Fp IsSmallPrime p
p Word64
x) (Fp IsSmallPrime p
_ Word64
y) = IsSmallPrime p -> Word64 -> Fp p
forall (p :: Nat). IsSmallPrime p -> Word64 -> Fp p
Fp IsSmallPrime p
p (Word64 -> Word64 -> Word64 -> Word64
Raw.mul (IsSmallPrime p -> Word64
forall (n :: Nat). IsSmallPrime n -> Word64
fromSmallPrime IsSmallPrime p
p) Word64
x Word64
y)
abs :: Fp p -> Fp p
abs = Fp p -> Fp p
forall a. a -> a
id
signum :: Fp p -> Fp p
signum (Fp IsSmallPrime p
p Word64
_) = IsSmallPrime p -> Word64 -> Fp p
forall (p :: Nat). IsSmallPrime p -> Word64 -> Fp p
Fp IsSmallPrime p
p Word64
1
instance Fractional (Fp p) where
fromRational :: Rational -> Fp p
fromRational = String -> Rational -> Fp p
forall a. HasCallStack => String -> a
error String
"PrimeField/Small/Fp/fromRational: cannot be defined; use `embed` instead"
recip :: Fp p -> Fp p
recip (Fp IsSmallPrime p
p Word64
x) = IsSmallPrime p -> Word64 -> Fp p
forall (p :: Nat). IsSmallPrime p -> Word64 -> Fp p
Fp IsSmallPrime p
p (Word64 -> Word64 -> Word64
Raw.inv (IsSmallPrime p -> Word64
forall (n :: Nat). IsSmallPrime n -> Word64
fromSmallPrime IsSmallPrime p
p) Word64
x)
/ :: Fp p -> Fp p -> Fp p
(/) (Fp IsSmallPrime p
p Word64
x) (Fp IsSmallPrime p
_ Word64
y) = IsSmallPrime p -> Word64 -> Fp p
forall (p :: Nat). IsSmallPrime p -> Word64 -> Fp p
Fp IsSmallPrime p
p (Word64 -> Word64 -> Word64 -> Word64
Raw.div (IsSmallPrime p -> Word64
forall (n :: Nat). IsSmallPrime n -> Word64
fromSmallPrime IsSmallPrime p
p) Word64
x Word64
y)
instance Field (Fp p) where
type Witness (Fp p) = WitnessFp p
type Prime (Fp p) = p
type Dim (Fp p) = 1
characteristic :: Witness (Fp p) -> Integer
characteristic Witness (Fp p)
w = case Witness (Fp p)
w of { WitnessFp p -> IsSmallPrime p -> Integer
forall (n :: Nat). IsSmallPrime n -> Integer
fromSmallPrimeInteger IsSmallPrime p
p }
dimension :: Witness (Fp p) -> Integer
dimension Witness (Fp p)
_ = Integer
1
fieldSize :: Witness (Fp p) -> Integer
fieldSize Witness (Fp p)
w = case Witness (Fp p)
w of { WitnessFp p -> IsSmallPrime p -> Integer
forall (n :: Nat). IsSmallPrime n -> Integer
fromSmallPrimeInteger IsSmallPrime p
p }
enumerate :: Witness (Fp p) -> [Fp p]
enumerate Witness (Fp p)
w = case Witness (Fp p)
w of { WitnessFp p -> let q :: Word64
q = IsSmallPrime p -> Word64
forall (n :: Nat). IsSmallPrime n -> Word64
fromSmallPrime IsSmallPrime p
p in [ IsSmallPrime p -> Word64 -> Fp p
forall (p :: Nat). IsSmallPrime p -> Word64 -> Fp p
fp IsSmallPrime p
p Word64
k | Word64
k<-[Word64
0..Word64
qWord64 -> Word64 -> Word64
forall a. Num a => a -> a -> a
-Word64
1] ] }
embed :: Witness (Fp p) -> Integer -> Fp p
embed Witness (Fp p)
w Integer
x = IsSmallPrime p -> Word64 -> Fp p
forall (p :: Nat). IsSmallPrime p -> Word64 -> Fp p
fp (WitnessFp p -> IsSmallPrime p
forall (p :: Nat). WitnessFp p -> IsSmallPrime p
fromWitnessFp Witness (Fp p)
WitnessFp p
w) (Integer -> Word64
forall a. Num a => Integer -> a
fromInteger Integer
x)
embedSmall :: Witness (Fp p) -> Int -> Fp p
embedSmall Witness (Fp p)
w Int
x = IsSmallPrime p -> Word64 -> Fp p
forall (p :: Nat). IsSmallPrime p -> Word64 -> Fp p
fp (WitnessFp p -> IsSmallPrime p
forall (p :: Nat). WitnessFp p -> IsSmallPrime p
fromWitnessFp Witness (Fp p)
WitnessFp p
w) (Int -> Word64
forall a b. (Integral a, Num b) => a -> b
fromIntegral Int
x)
primGen :: Witness (Fp p) -> Fp p
primGen Witness (Fp p)
w = IsSmallPrime p -> Fp p
forall (p :: Nat). IsSmallPrime p -> Fp p
primRoot (WitnessFp p -> IsSmallPrime p
forall (p :: Nat). WitnessFp p -> IsSmallPrime p
fromWitnessFp Witness (Fp p)
WitnessFp p
w)
witnessOf :: Fp p -> Witness (Fp p)
witnessOf = Fp p -> Witness (Fp p)
forall (p :: Nat). Fp p -> WitnessFp p
fpWitness
power :: Fp p -> Integer -> Fp p
power = Fp p -> Integer -> Fp p
forall (p :: Nat). Fp p -> Integer -> Fp p
fpPow
powerSmall :: Fp p -> Int -> Fp p
powerSmall Fp p
x Int
e = Fp p -> Int64 -> Fp p
forall (p :: Nat). Fp p -> Int64 -> Fp p
fpPow_ Fp p
x (Int -> Int64
forall a b. (Integral a, Num b) => a -> b
fromIntegral Int
e)
frobenius :: Fp p -> Fp p
frobenius = Fp p -> Fp p
forall a. a -> a
id
randomFieldElem :: Witness (Fp p) -> gen -> (Fp p, gen)
randomFieldElem Witness (Fp p)
w = case Witness (Fp p)
w of { WitnessFp p -> IsSmallPrime p -> gen -> (Fp p, gen)
forall gen (p :: Nat).
RandomGen gen =>
IsSmallPrime p -> gen -> (Fp p, gen)
randomFp IsSmallPrime p
p }
randomInvertible :: Witness (Fp p) -> gen -> (Fp p, gen)
randomInvertible Witness (Fp p)
w = case Witness (Fp p)
w of { WitnessFp p -> IsSmallPrime p -> gen -> (Fp p, gen)
forall gen (p :: Nat).
RandomGen gen =>
IsSmallPrime p -> gen -> (Fp p, gen)
randomInvFp IsSmallPrime p
p }
zero :: Witness (Fp p) -> Fp p
zero Witness (Fp p)
w = IsSmallPrime p -> Word64 -> Fp p
forall (p :: Nat). IsSmallPrime p -> Word64 -> Fp p
Fp (WitnessFp p -> IsSmallPrime p
forall (p :: Nat). WitnessFp p -> IsSmallPrime p
fromWitnessFp Witness (Fp p)
WitnessFp p
w) Word64
0
one :: Witness (Fp p) -> Fp p
one Witness (Fp p)
w = IsSmallPrime p -> Word64 -> Fp p
forall (p :: Nat). IsSmallPrime p -> Word64 -> Fp p
Fp (WitnessFp p -> IsSmallPrime p
forall (p :: Nat). WitnessFp p -> IsSmallPrime p
fromWitnessFp Witness (Fp p)
WitnessFp p
w) Word64
1
isZero :: Fp p -> Bool
isZero (Fp IsSmallPrime p
_ Word64
x) = (Word64
x Word64 -> Word64 -> Bool
forall a. Eq a => a -> a -> Bool
== Word64
0)
isOne :: Fp p -> Bool
isOne (Fp IsSmallPrime p
_ Word64
x) = (Word64
x Word64 -> Word64 -> Bool
forall a. Eq a => a -> a -> Bool
== Word64
1)
fpPow_ :: Fp p -> Int64 -> Fp p
fpPow_ :: Fp p -> Int64 -> Fp p
fpPow_ (Fp IsSmallPrime p
p Word64
x) Int64
e = IsSmallPrime p -> Word64 -> Fp p
forall (p :: Nat). IsSmallPrime p -> Word64 -> Fp p
Fp IsSmallPrime p
p (Word64 -> Word64 -> Int64 -> Word64
Raw.pow (IsSmallPrime p -> Word64
forall (n :: Nat). IsSmallPrime n -> Word64
fromSmallPrime IsSmallPrime p
p) Word64
x Int64
e)
fpPow :: Fp p -> Integer -> Fp p
fpPow :: Fp p -> Integer -> Fp p
fpPow (Fp IsSmallPrime p
p Word64
x) Integer
e = IsSmallPrime p -> Word64 -> Fp p
forall (p :: Nat). IsSmallPrime p -> Word64 -> Fp p
Fp IsSmallPrime p
p (Word64 -> Word64 -> Integer -> Word64
Raw.pow' (IsSmallPrime p -> Word64
forall (n :: Nat). IsSmallPrime n -> Word64
fromSmallPrime IsSmallPrime p
p) Word64
x Integer
e)
fpInv :: Fp p -> Fp p
fpInv :: Fp p -> Fp p
fpInv (Fp IsSmallPrime p
p Word64
a) = IsSmallPrime p -> Word64 -> Fp p
forall (p :: Nat). IsSmallPrime p -> Word64 -> Fp p
Fp IsSmallPrime p
p (Word64 -> Word64 -> Word64
Raw.inv (IsSmallPrime p -> Word64
forall (n :: Nat). IsSmallPrime n -> Word64
fromSmallPrime IsSmallPrime p
p) Word64
a)
fpDiv :: Fp p -> Fp p -> Fp p
fpDiv :: Fp p -> Fp p -> Fp p
fpDiv (Fp IsSmallPrime p
p Word64
a) (Fp IsSmallPrime p
_ Word64
b) = IsSmallPrime p -> Word64 -> Fp p
forall (p :: Nat). IsSmallPrime p -> Word64 -> Fp p
Fp IsSmallPrime p
p (Word64 -> Word64 -> Word64 -> Word64
Raw.div (IsSmallPrime p -> Word64
forall (n :: Nat). IsSmallPrime n -> Word64
fromSmallPrime IsSmallPrime p
p) Word64
a Word64
b)
fpDiv2 :: Fp p -> Fp p -> Fp p
fpDiv2 :: Fp p -> Fp p -> Fp p
fpDiv2 (Fp IsSmallPrime p
p Word64
a) (Fp IsSmallPrime p
_ Word64
b) = IsSmallPrime p -> Word64 -> Fp p
forall (p :: Nat). IsSmallPrime p -> Word64 -> Fp p
Fp IsSmallPrime p
p (Word64 -> Word64 -> Word64 -> Word64
Raw.div2 (IsSmallPrime p -> Word64
forall (n :: Nat). IsSmallPrime n -> Word64
fromSmallPrime IsSmallPrime p
p) Word64
a Word64
b)