{-# LANGUAGE BangPatterns, DataKinds, KindSignatures, TypeFamilies #-}
{-# LANGUAGE ExistentialQuantification, StandaloneDeriving #-}
module Math.FiniteField.PrimeField.Generic
(
WitnessFp(..)
, SomeWitnessFp(..)
, mkPrimeField
, unsafePrimeField
, Fp
)
where
import Data.Bits
import GHC.TypeNats (Nat)
import System.Random ( RandomGen , randomR )
import Math.FiniteField.Primes
import Math.FiniteField.TypeLevel
import Math.FiniteField.Class
import qualified Math.FiniteField.PrimeField.Generic.Raw as Raw
newtype WitnessFp (p :: Nat)
= WitnessFp { forall (p :: Nat). WitnessFp p -> IsPrime p
fromWitnessFp :: IsPrime p }
deriving Int -> WitnessFp p -> ShowS
forall (p :: Nat). Int -> WitnessFp p -> ShowS
forall (p :: Nat). [WitnessFp p] -> ShowS
forall (p :: Nat). WitnessFp p -> String
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
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
mkPrimeField :: Integer -> Maybe SomeWitnessFp
mkPrimeField :: Integer -> Maybe SomeWitnessFp
mkPrimeField Integer
p = case Integer -> SomeSNat
someSNat Integer
p of
SomeSNat SNat n
sp -> (forall (p :: Nat). WitnessFp p -> SomeWitnessFp
SomeWitnessFp forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall (p :: Nat). IsPrime p -> WitnessFp p
WitnessFp) forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> forall (n :: Nat). SNat n -> Maybe (IsPrime n)
isPrime SNat n
sp
unsafePrimeField :: Integer -> SomeWitnessFp
unsafePrimeField :: Integer -> SomeWitnessFp
unsafePrimeField Integer
p = case Integer -> SomeSNat
someSNat Integer
p of
SomeSNat SNat n
sp -> forall (p :: Nat). WitnessFp p -> SomeWitnessFp
SomeWitnessFp (forall (p :: Nat). IsPrime p -> WitnessFp p
WitnessFp (forall (n :: Nat). SNat n -> IsPrime n
believeMeItsPrime SNat n
sp))
data Fp (p :: Nat)
= Fp !(IsPrime p) !Integer
fpWitness :: Fp p -> WitnessFp p
fpWitness :: forall (p :: Nat). Fp p -> WitnessFp p
fpWitness (Fp IsPrime p
p Integer
_) = forall (p :: Nat). IsPrime p -> WitnessFp p
WitnessFp IsPrime p
p
fp :: IsPrime p -> Integer -> Fp p
fp :: forall (p :: Nat). IsPrime p -> Integer -> Fp p
fp !IsPrime p
p !Integer
n
| Integer
n forall a. Ord a => a -> a -> Bool
>= Integer
0 Bool -> Bool -> Bool
&& Integer
n forall a. Ord a => a -> a -> Bool
< Integer
q = forall (p :: Nat). IsPrime p -> Integer -> Fp p
Fp IsPrime p
p Integer
n
| Bool
otherwise = forall (p :: Nat). IsPrime p -> Integer -> Fp p
Fp IsPrime p
p (forall a. Integral a => a -> a -> a
mod Integer
n Integer
q)
where
!q :: Integer
q = forall (n :: Nat). IsPrime n -> Integer
fromPrime IsPrime p
p
randomFp :: RandomGen gen => IsPrime p -> gen -> (Fp p, gen)
randomFp :: forall gen (p :: Nat).
RandomGen gen =>
IsPrime p -> gen -> (Fp p, gen)
randomFp !IsPrime p
p !gen
gen = case forall a g. (Random a, RandomGen g) => (a, a) -> g -> (a, g)
randomR (Integer
0,Integer
qforall a. Num a => a -> a -> a
-Integer
1) gen
gen of { (Integer
x, gen
gen') -> (forall (p :: Nat). IsPrime p -> Integer -> Fp p
Fp IsPrime p
p Integer
x, gen
gen') } where !q :: Integer
q = forall (n :: Nat). IsPrime n -> Integer
fromPrime IsPrime p
p
randomInvFp :: RandomGen gen => IsPrime p -> gen -> (Fp p, gen)
randomInvFp :: forall gen (p :: Nat).
RandomGen gen =>
IsPrime p -> gen -> (Fp p, gen)
randomInvFp !IsPrime p
p !gen
gen = case forall a g. (Random a, RandomGen g) => (a, a) -> g -> (a, g)
randomR (Integer
1,Integer
qforall a. Num a => a -> a -> a
-Integer
1) gen
gen of { (Integer
x, gen
gen') -> (forall (p :: Nat). IsPrime p -> Integer -> Fp p
Fp IsPrime p
p Integer
x, gen
gen') } where !q :: Integer
q = forall (n :: Nat). IsPrime n -> Integer
fromPrime IsPrime p
p
fpOrder :: Fp p -> Integer
fpOrder :: forall (p :: Nat). Fp p -> Integer
fpOrder (Fp IsPrime p
p Integer
_) = forall (n :: Nat). IsPrime n -> Integer
fromPrime IsPrime p
p
modp :: Integer -> IsPrime p -> Integer
modp :: forall (p :: Nat). Integer -> IsPrime p -> Integer
modp !Integer
x !IsPrime p
p = forall a. Integral a => a -> a -> a
mod Integer
x (forall (n :: Nat). IsPrime n -> Integer
fromPrime IsPrime p
p)
instance Eq (Fp p) where
== :: Fp p -> Fp p -> Bool
(==) (Fp IsPrime p
_ Integer
x) (Fp IsPrime p
_ Integer
y) = Integer
x forall a. Eq a => a -> a -> Bool
== Integer
y
instance Ord (Fp p) where
compare :: Fp p -> Fp p -> Ordering
compare (Fp IsPrime p
_ Integer
x) (Fp IsPrime p
_ Integer
y) = forall a. Ord a => a -> a -> Ordering
compare Integer
x Integer
y
instance Show (Fp p) where
show :: Fp p -> String
show (Fp IsPrime p
p Integer
k) = String
"(" forall a. [a] -> [a] -> [a]
++ forall a. Show a => a -> String
show Integer
k forall a. [a] -> [a] -> [a]
++ String
" mod " forall a. [a] -> [a] -> [a]
++ forall a. Show a => a -> String
show (forall (n :: Nat). IsPrime n -> Integer
fromPrime IsPrime p
p) forall a. [a] -> [a] -> [a]
++ String
")"
instance Num (Fp p) where
fromInteger :: Integer -> Fp p
fromInteger = forall a. HasCallStack => String -> a
error String
"PrimeField/Generic/Fp/fromInteger: not defined; use `fp` instead"
negate :: Fp p -> Fp p
negate (Fp IsPrime p
p Integer
x) = forall (p :: Nat). IsPrime p -> Integer -> Fp p
Fp IsPrime p
p (Integer -> Integer -> Integer
Raw.neg (forall (n :: Nat). IsPrime n -> Integer
fromPrime IsPrime p
p) Integer
x)
+ :: Fp p -> Fp p -> Fp p
(+) (Fp IsPrime p
p Integer
x) (Fp IsPrime p
_ Integer
y) = forall (p :: Nat). IsPrime p -> Integer -> Fp p
Fp IsPrime p
p (Integer -> Integer -> Integer -> Integer
Raw.add (forall (n :: Nat). IsPrime n -> Integer
fromPrime IsPrime p
p) Integer
x Integer
y)
(-) (Fp IsPrime p
p Integer
x) (Fp IsPrime p
_ Integer
y) = forall (p :: Nat). IsPrime p -> Integer -> Fp p
Fp IsPrime p
p (Integer -> Integer -> Integer -> Integer
Raw.sub (forall (n :: Nat). IsPrime n -> Integer
fromPrime IsPrime p
p) Integer
x Integer
y)
* :: Fp p -> Fp p -> Fp p
(*) (Fp IsPrime p
p Integer
x) (Fp IsPrime p
_ Integer
y) = forall (p :: Nat). IsPrime p -> Integer -> Fp p
Fp IsPrime p
p (Integer -> Integer -> Integer -> Integer
Raw.mul (forall (n :: Nat). IsPrime n -> Integer
fromPrime IsPrime p
p) Integer
x Integer
y)
abs :: Fp p -> Fp p
abs = forall a. a -> a
id
signum :: Fp p -> Fp p
signum (Fp IsPrime p
p Integer
_) = forall (p :: Nat). IsPrime p -> Integer -> Fp p
Fp IsPrime p
p Integer
1
instance Fractional (Fp p) where
fromRational :: Rational -> Fp p
fromRational = forall a. HasCallStack => String -> a
error String
"PrimeField/Generic/Fp/fromRational: not defined; use `fp` instead"
recip :: Fp p -> Fp p
recip (Fp IsPrime p
p Integer
x) = forall (p :: Nat). IsPrime p -> Integer -> Fp p
Fp IsPrime p
p (Integer -> Integer -> Integer
Raw.inv (forall (n :: Nat). IsPrime n -> Integer
fromPrime IsPrime p
p) Integer
x)
/ :: Fp p -> Fp p -> Fp p
(/) (Fp IsPrime p
p Integer
x) (Fp IsPrime p
_ Integer
y) = forall (p :: Nat). IsPrime p -> Integer -> Fp p
Fp IsPrime p
p (Integer -> Integer -> Integer -> Integer
Raw.div (forall (n :: Nat). IsPrime n -> Integer
fromPrime IsPrime p
p) Integer
x Integer
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 IsPrime p
p -> forall (n :: Nat). IsPrime n -> Integer
fromPrime IsPrime 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 IsPrime p
p -> forall (n :: Nat). IsPrime n -> Integer
fromPrime IsPrime p
p }
enumerate :: Witness (Fp p) -> [Fp p]
enumerate Witness (Fp p)
w = case Witness (Fp p)
w of { WitnessFp IsPrime p
p -> let q :: Integer
q = forall (n :: Nat). IsPrime n -> Integer
fromPrime IsPrime p
p in [ forall (p :: Nat). IsPrime p -> Integer -> Fp p
fp IsPrime p
p Integer
k | Integer
k<-[Integer
0..Integer
qforall a. Num a => a -> a -> a
-Integer
1] ] }
embed :: Witness (Fp p) -> Integer -> Fp p
embed Witness (Fp p)
w Integer
x = forall (p :: Nat). IsPrime p -> Integer -> Fp p
fp (forall (p :: Nat). WitnessFp p -> IsPrime p
fromWitnessFp Witness (Fp p)
w) Integer
x
primGen :: Witness (Fp p) -> Fp p
primGen = forall a. HasCallStack => String -> a
error String
"PrimeField/Generic/Fp: primGen: not implemented"
witnessOf :: Fp p -> Witness (Fp p)
witnessOf = forall (p :: Nat). Fp p -> WitnessFp p
fpWitness
power :: Fp p -> Integer -> Fp p
power = forall (p :: Nat). Fp p -> Integer -> Fp p
fpPow
frobenius :: Fp p -> Fp p
frobenius = forall a. a -> a
id
randomFieldElem :: forall gen. RandomGen gen => Witness (Fp p) -> gen -> (Fp p, gen)
randomFieldElem Witness (Fp p)
w = case Witness (Fp p)
w of { WitnessFp IsPrime p
p -> forall gen (p :: Nat).
RandomGen gen =>
IsPrime p -> gen -> (Fp p, gen)
randomFp IsPrime p
p }
randomInvertible :: forall gen. RandomGen gen => Witness (Fp p) -> gen -> (Fp p, gen)
randomInvertible Witness (Fp p)
w = case Witness (Fp p)
w of { WitnessFp IsPrime p
p -> forall gen (p :: Nat).
RandomGen gen =>
IsPrime p -> gen -> (Fp p, gen)
randomInvFp IsPrime p
p }
zero :: Witness (Fp p) -> Fp p
zero Witness (Fp p)
w = forall (p :: Nat). IsPrime p -> Integer -> Fp p
Fp (forall (p :: Nat). WitnessFp p -> IsPrime p
fromWitnessFp Witness (Fp p)
w) Integer
0
one :: Witness (Fp p) -> Fp p
one Witness (Fp p)
w = forall (p :: Nat). IsPrime p -> Integer -> Fp p
Fp (forall (p :: Nat). WitnessFp p -> IsPrime p
fromWitnessFp Witness (Fp p)
w) Integer
1
isZero :: Fp p -> Bool
isZero (Fp IsPrime p
_ Integer
x) = (Integer
x forall a. Eq a => a -> a -> Bool
== Integer
0)
isOne :: Fp p -> Bool
isOne (Fp IsPrime p
_ Integer
x) = (Integer
x forall a. Eq a => a -> a -> Bool
== Integer
1)
fpPow :: Fp p -> Integer -> Fp p
fpPow :: forall (p :: Nat). Fp p -> Integer -> Fp p
fpPow (Fp IsPrime p
p Integer
x) Integer
e = forall (p :: Nat). IsPrime p -> Integer -> Fp p
Fp IsPrime p
p (Integer -> Integer -> Integer -> Integer
Raw.pow (forall (n :: Nat). IsPrime n -> Integer
fromPrime IsPrime p
p) Integer
x Integer
e)
fpInv :: Fp p -> Fp p
fpInv :: forall (p :: Nat). Fp p -> Fp p
fpInv (Fp IsPrime p
p Integer
a) = forall (p :: Nat). IsPrime p -> Integer -> Fp p
Fp IsPrime p
p (Integer -> Integer -> Integer
Raw.inv (forall (n :: Nat). IsPrime n -> Integer
fromPrime IsPrime p
p) Integer
a)
fpDiv :: Fp p -> Fp p -> Fp p
fpDiv :: forall (p :: Nat). Fp p -> Fp p -> Fp p
fpDiv (Fp IsPrime p
p Integer
a) (Fp IsPrime p
_ Integer
b) = forall (p :: Nat). IsPrime p -> Integer -> Fp p
Fp IsPrime p
p (Integer -> Integer -> Integer -> Integer
Raw.div (forall (n :: Nat). IsPrime n -> Integer
fromPrime IsPrime p
p) Integer
a Integer
b)
fpDiv2 :: Fp p -> Fp p -> Fp p
fpDiv2 :: forall (p :: Nat). Fp p -> Fp p -> Fp p
fpDiv2 (Fp IsPrime p
p Integer
a) (Fp IsPrime p
_ Integer
b) = forall (p :: Nat). IsPrime p -> Integer -> Fp p
Fp IsPrime p
p (Integer -> Integer -> Integer -> Integer
Raw.div2 (forall (n :: Nat). IsPrime n -> Integer
fromPrime IsPrime p
p) Integer
a Integer
b)