module Data.FiniteField.PrimeField
( PrimeField
, toInteger
, primeField
) where
import Prelude hiding (toInteger)
import Control.DeepSeq
import Data.Ratio (denominator, numerator)
import Data.Typeable
import qualified Language.Haskell.TH as TH
import qualified Numeric.Algebra as Alg
import qualified TypeLevel.Number.Nat as TL
import Data.FiniteField.Base
newtype PrimeField p = PrimeField Integer deriving (Eq, Typeable)
toInteger :: PrimeField p -> Integer
toInteger (PrimeField a) = a
toInt :: Integral a => PrimeField p -> a
toInt = fromInteger . toInteger
instance Show (PrimeField p) where
showsPrec n (PrimeField x) = showsPrec n x
instance TL.Nat p => Read (PrimeField p) where
readsPrec n s = [(fromInteger a, s') | (a,s') <- readsPrec n s]
instance NFData (PrimeField p) where
rnf (PrimeField a) = rnf a
instance TL.Nat p => Num (PrimeField p) where
PrimeField a + PrimeField b = fromInteger $ a+b
PrimeField a * PrimeField b = fromInteger $ a*b
PrimeField a PrimeField b = fromInteger $ ab
negate (PrimeField a) = fromInteger $ negate a
abs a = a
signum _ = 1
fromInteger a = PrimeField $ a `mod` TL.toInt (undefined :: p)
instance TL.Nat p => Fractional (PrimeField p) where
fromRational r = fromInteger (numerator r) / fromInteger (denominator r)
recip a = a ^ (TL.toInt (undefined :: p) 2 :: Integer)
instance TL.Nat p => Bounded (PrimeField p) where
minBound = PrimeField 0
maxBound = PrimeField (TL.toInt (undefined :: p) 1)
instance TL.Nat p => Enum (PrimeField p) where
toEnum x
| toInt (minBound :: PrimeField p) <= x && x <= toInt (maxBound :: PrimeField p) = fromIntegral x
| otherwise = error "PrimeField.toEnum: bad argument"
fromEnum = toInt
instance Ord (PrimeField p) where
PrimeField a `compare` PrimeField b = a `compare` b
PrimeField a `max` PrimeField b = PrimeField (a `max` b)
PrimeField a `min` PrimeField b = PrimeField (a `min` b)
instance TL.Nat p => FiniteField (PrimeField p) where
order _ = TL.toInt (undefined :: p)
char _ = TL.toInt (undefined :: p)
pthRoot a = a
allValues = [minBound .. maxBound]
instance TL.Nat p => Alg.Multiplicative (PrimeField p) where
(*) = (*)
instance TL.Nat p => Alg.Commutative (PrimeField p)
instance TL.Nat p => Alg.Unital (PrimeField p) where
one = 1
instance TL.Nat p => Alg.Division (PrimeField p) where
recip = recip
instance TL.Nat p => Alg.Additive (PrimeField p) where
(+) = (+)
instance TL.Nat p => Alg.Abelian (PrimeField p)
instance TL.Nat p => Alg.Semiring (PrimeField p)
instance TL.Nat p => Alg.LeftModule Alg.Natural (PrimeField p) where
n .* a = fromIntegral n * a
instance TL.Nat p => Alg.RightModule Alg.Natural (PrimeField p) where
a *. n = a * fromIntegral n
instance TL.Nat p => Alg.Monoidal (PrimeField p) where
zero = 0
instance TL.Nat p => Alg.LeftModule Integer (PrimeField p) where
n .* a = fromIntegral n * a
instance TL.Nat p => Alg.RightModule Integer (PrimeField p) where
a *. n = a * fromIntegral n
instance TL.Nat p => Alg.Group (PrimeField p) where
negate = negate
instance TL.Nat p => Alg.Rig (PrimeField p)
instance TL.Nat p => Alg.Ring (PrimeField p)
instance TL.Nat p => Alg.Characteristic (PrimeField p) where
char _ = TL.toInt (undefined :: p)
instance TL.Nat p => Alg.Field (PrimeField p)
primeField :: Integer -> TH.TypeQ
primeField n
| n <= 0 = error "primeField: negative value"
| otherwise = [t| PrimeField $(TL.natT n) |]