{-# LANGUAGE ScopedTypeVariables, MultiParamTypeClasses, DeriveDataTypeable, TemplateHaskell, BangPatterns #-}
{-# LANGUAGE CPP, KindSignatures, DataKinds, ConstraintKinds #-}
{-# OPTIONS_GHC -Wall #-}
module Data.FiniteField.PrimeField
( PrimeField
, toInteger
, primeField
) where
import Prelude hiding (toInteger)
import Control.DeepSeq
import Data.Hashable
import Data.Ratio (denominator, numerator)
import Data.Typeable
import qualified Language.Haskell.TH as TH
#if !defined(UseGHCTypeLits)
import qualified TypeLevel.Number.Nat as TL
#else
import GHC.TypeLits
#endif
import Data.FiniteField.Base
#if !defined(UseGHCTypeLits)
newtype PrimeField p = PrimeField Integer deriving (Eq, Typeable)
#else
newtype PrimeField (p::Nat) = PrimeField Integer deriving (PrimeField p -> PrimeField p -> Bool
(PrimeField p -> PrimeField p -> Bool)
-> (PrimeField p -> PrimeField p -> Bool) -> Eq (PrimeField p)
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
forall (p :: Nat). PrimeField p -> PrimeField p -> Bool
/= :: PrimeField p -> PrimeField p -> Bool
$c/= :: forall (p :: Nat). PrimeField p -> PrimeField p -> Bool
== :: PrimeField p -> PrimeField p -> Bool
$c== :: forall (p :: Nat). PrimeField p -> PrimeField p -> Bool
Eq, Typeable)
#endif
#if !defined(UseGHCTypeLits)
type KnownNat p = TL.Nat p
#endif
toInteger :: PrimeField p -> Integer
toInteger :: PrimeField p -> Integer
toInteger (PrimeField a :: Integer
a) = Integer
a
toInt :: Integral a => PrimeField p -> a
toInt :: PrimeField p -> a
toInt = Integer -> a
forall a. Num a => Integer -> a
fromInteger (Integer -> a) -> (PrimeField p -> Integer) -> PrimeField p -> a
forall b c a. (b -> c) -> (a -> b) -> a -> c
. PrimeField p -> Integer
forall (p :: Nat). PrimeField p -> Integer
toInteger
instance Show (PrimeField p) where
showsPrec :: Int -> PrimeField p -> ShowS
showsPrec n :: Int
n (PrimeField x :: Integer
x) = Int -> Integer -> ShowS
forall a. Show a => Int -> a -> ShowS
showsPrec Int
n Integer
x
instance KnownNat p => Read (PrimeField p) where
readsPrec :: Int -> ReadS (PrimeField p)
readsPrec n :: Int
n s :: String
s = [(Integer -> PrimeField p
forall a. Num a => Integer -> a
fromInteger Integer
a, String
s') | (a :: Integer
a,s' :: String
s') <- Int -> ReadS Integer
forall a. Read a => Int -> ReadS a
readsPrec Int
n String
s]
instance NFData (PrimeField p) where
rnf :: PrimeField p -> ()
rnf (PrimeField a :: Integer
a) = Integer -> ()
forall a. NFData a => a -> ()
rnf Integer
a
instance KnownNat p => Num (PrimeField p) where
PrimeField a :: Integer
a + :: PrimeField p -> PrimeField p -> PrimeField p
+ PrimeField b :: Integer
b = Integer -> PrimeField p
forall a. Num a => Integer -> a
fromInteger (Integer -> PrimeField p) -> Integer -> PrimeField p
forall a b. (a -> b) -> a -> b
$ Integer
aInteger -> Integer -> Integer
forall a. Num a => a -> a -> a
+Integer
b
PrimeField a :: Integer
a * :: PrimeField p -> PrimeField p -> PrimeField p
* PrimeField b :: Integer
b = Integer -> PrimeField p
forall a. Num a => Integer -> a
fromInteger (Integer -> PrimeField p) -> Integer -> PrimeField p
forall a b. (a -> b) -> a -> b
$ Integer
aInteger -> Integer -> Integer
forall a. Num a => a -> a -> a
*Integer
b
PrimeField a :: Integer
a - :: PrimeField p -> PrimeField p -> PrimeField p
- PrimeField b :: Integer
b = Integer -> PrimeField p
forall a. Num a => Integer -> a
fromInteger (Integer -> PrimeField p) -> Integer -> PrimeField p
forall a b. (a -> b) -> a -> b
$ Integer
aInteger -> Integer -> Integer
forall a. Num a => a -> a -> a
-Integer
b
negate :: PrimeField p -> PrimeField p
negate (PrimeField a :: Integer
a) = Integer -> PrimeField p
forall a. Num a => Integer -> a
fromInteger (Integer -> PrimeField p) -> Integer -> PrimeField p
forall a b. (a -> b) -> a -> b
$ Integer -> Integer
forall a. Num a => a -> a
negate Integer
a
abs :: PrimeField p -> PrimeField p
abs a :: PrimeField p
a = PrimeField p
a
signum :: PrimeField p -> PrimeField p
signum _ = 1
fromInteger :: Integer -> PrimeField p
fromInteger a :: Integer
a = PrimeField p
ret
where
ret :: PrimeField p
ret = Integer -> PrimeField p
forall (p :: Nat). Integer -> PrimeField p
PrimeField (Integer -> PrimeField p) -> Integer -> PrimeField p
forall a b. (a -> b) -> a -> b
$ Integer
a Integer -> Integer -> Integer
forall a. Integral a => a -> a -> a
`mod` PrimeField p -> Integer
forall k. FiniteField k => k -> Integer
char PrimeField p
ret
instance KnownNat p => Fractional (PrimeField p) where
fromRational :: Rational -> PrimeField p
fromRational r :: Rational
r = Integer -> PrimeField p
forall a. Num a => Integer -> a
fromInteger (Rational -> Integer
forall a. Ratio a -> a
numerator Rational
r) PrimeField p -> PrimeField p -> PrimeField p
forall a. Fractional a => a -> a -> a
/ Integer -> PrimeField p
forall a. Num a => Integer -> a
fromInteger (Rational -> Integer
forall a. Ratio a -> a
denominator Rational
r)
recip :: PrimeField p -> PrimeField p
recip x :: PrimeField p
x@(PrimeField a :: Integer
a) =
case Integer -> Integer -> (Integer, Integer, Integer)
forall a. Integral a => a -> a -> (a, a, a)
exgcd Integer
a Integer
p of
(_, r :: Integer
r, _) -> Integer -> PrimeField p
forall a. Num a => Integer -> a
fromInteger Integer
r
where
p :: Integer
p :: Integer
p = PrimeField p -> Integer
forall k. FiniteField k => k -> Integer
char PrimeField p
x
instance KnownNat p => Bounded (PrimeField p) where
minBound :: PrimeField p
minBound = Integer -> PrimeField p
forall (p :: Nat). Integer -> PrimeField p
PrimeField 0
maxBound :: PrimeField p
maxBound = PrimeField p
ret
where
ret :: PrimeField p
ret = Integer -> PrimeField p
forall (p :: Nat). Integer -> PrimeField p
PrimeField (PrimeField p -> Integer
forall k. FiniteField k => k -> Integer
char PrimeField p
ret Integer -> Integer -> Integer
forall a. Num a => a -> a -> a
- 1)
instance KnownNat p => Enum (PrimeField p) where
toEnum :: Int -> PrimeField p
toEnum x :: Int
x
| PrimeField p -> Int
forall a (p :: Nat). Integral a => PrimeField p -> a
toInt (PrimeField p
forall a. Bounded a => a
minBound :: PrimeField p) Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
<= Int
x Bool -> Bool -> Bool
&& Int
x Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
<= PrimeField p -> Int
forall a (p :: Nat). Integral a => PrimeField p -> a
toInt (PrimeField p
forall a. Bounded a => a
maxBound :: PrimeField p) = Int -> PrimeField p
forall a b. (Integral a, Num b) => a -> b
fromIntegral Int
x
| Bool
otherwise = String -> PrimeField p
forall a. HasCallStack => String -> a
error "PrimeField.toEnum: bad argument"
fromEnum :: PrimeField p -> Int
fromEnum = PrimeField p -> Int
forall a (p :: Nat). Integral a => PrimeField p -> a
toInt
instance Ord (PrimeField p) where
PrimeField a :: Integer
a compare :: PrimeField p -> PrimeField p -> Ordering
`compare` PrimeField b :: Integer
b = Integer
a Integer -> Integer -> Ordering
forall a. Ord a => a -> a -> Ordering
`compare` Integer
b
instance KnownNat p => FiniteField (PrimeField p) where
order :: PrimeField p -> Integer
order x :: PrimeField p
x = PrimeField p -> Integer
forall k. FiniteField k => k -> Integer
char PrimeField p
x
#if !defined(UseGHCTypeLits)
char _ = TL.toInt (undefined :: p)
#else
char :: PrimeField p -> Integer
char _ = Proxy p -> Integer
forall (n :: Nat) (proxy :: Nat -> *).
KnownNat n =>
proxy n -> Integer
natVal (Proxy p
forall k (t :: k). Proxy t
Proxy :: Proxy p)
#endif
pthRoot :: PrimeField p -> PrimeField p
pthRoot a :: PrimeField p
a = PrimeField p
a
allValues :: [PrimeField p]
allValues = [PrimeField p
forall a. Bounded a => a
minBound .. PrimeField p
forall a. Bounded a => a
maxBound]
instance KnownNat p => Hashable (PrimeField p) where
hashWithSalt :: Int -> PrimeField p -> Int
hashWithSalt s :: Int
s x :: PrimeField p
x@(PrimeField a :: Integer
a) =
Int
s Int -> Integer -> Int
forall a. Hashable a => Int -> a -> Int
`hashWithSalt` PrimeField p -> Integer
forall k. FiniteField k => k -> Integer
char PrimeField p
x Int -> Integer -> Int
forall a. Hashable a => Int -> a -> Int
`hashWithSalt` Integer
a
exgcd :: Integral a => a -> a -> (a, a, a)
exgcd :: a -> a -> (a, a, a)
exgcd f1 :: a
f1 f2 :: a
f2 = (a, a, a) -> (a, a, a)
forall a b c.
(Ord a, Num a, Num b, Num c) =>
(a, b, c) -> (a, b, c)
f ((a, a, a) -> (a, a, a)) -> (a, a, a) -> (a, a, a)
forall a b. (a -> b) -> a -> b
$ a -> a -> a -> a -> a -> a -> (a, a, a)
forall t. Integral t => t -> t -> t -> t -> t -> t -> (t, t, t)
go a
f1 a
f2 1 0 0 1
where
go :: t -> t -> t -> t -> t -> t -> (t, t, t)
go !t
r0 !t
r1 !t
s0 !t
s1 !t
t0 !t
t1
| t
r1 t -> t -> Bool
forall a. Eq a => a -> a -> Bool
== 0 = (t
r0, t
s0, t
t0)
| Bool
otherwise = t -> t -> t -> t -> t -> t -> (t, t, t)
go t
r1 t
r2 t
s1 t
s2 t
t1 t
t2
where
(q :: t
q, r2 :: t
r2) = t
r0 t -> t -> (t, t)
forall a. Integral a => a -> a -> (a, a)
`divMod` t
r1
s2 :: t
s2 = t
s0 t -> t -> t
forall a. Num a => a -> a -> a
- t
qt -> t -> t
forall a. Num a => a -> a -> a
*t
s1
t2 :: t
t2 = t
t0 t -> t -> t
forall a. Num a => a -> a -> a
- t
qt -> t -> t
forall a. Num a => a -> a -> a
*t
t1
f :: (a, b, c) -> (a, b, c)
f (g :: a
g,u :: b
u,v :: c
v)
| a
g a -> a -> Bool
forall a. Ord a => a -> a -> Bool
< 0 = (-a
g, -b
u, -c
v)
| Bool
otherwise = (a
g,b
u,c
v)
primeField :: Integer -> TH.TypeQ
primeField :: Integer -> TypeQ
primeField n :: Integer
n
| Integer
n Integer -> Integer -> Bool
forall a. Ord a => a -> a -> Bool
<= 0 = String -> TypeQ
forall a. HasCallStack => String -> a
error "primeField: negative value"
#if !defined(UseGHCTypeLits)
| otherwise = [t| PrimeField $(TL.natT n) |]
#else
| Bool
otherwise = [t| PrimeField $(TH.litT (TH.numTyLit n)) |]
#endif