content: module Data.Field.Galois.Base
    ( module Data.Field.Galois.Base
    ) where
  
  import Protolude hiding ((-), one, quot)
  
  import Control.Monad.Random (Random)
  import Data.Field (Field)
  import qualified Data.Group as G (Group(..))
  import GHC.Natural (Natural)
  import Test.QuickCheck (Arbitrary)
  import Text.PrettyPrint.Leijen.Text (Pretty)
  
  -------------------------------------------------------------------------------
  -- Classes
  -------------------------------------------------------------------------------
  
  -- | Galois fields @GF(p^q)@ for @p@ prime and @q@ non-negative.
  class (Arbitrary k, Field k, Fractional k, Generic k, G.Group k,
         NFData k, Ord k, Pretty k, Random k, Show k) => GaloisField k where
    {-# MINIMAL char, deg, frob #-}
  
    -- | Characteristic @p@ of field and order of prime subfield.
    char :: k -> Natural
  
    -- | Degree @q@ of field as extension field over prime subfield.
    deg :: k -> Word
  
    -- | Frobenius endomorphism @x -> x^p@ of prime subfield.
    frob :: k -> k
  
    -- | Order @p^q@ of field.
    order :: k -> Natural
    order = (^) <$> char <*> deg
    {-# INLINABLE order #-}
  
  -- | Exponentiation of field element to integer.
  pow :: (GaloisField k, Integral n) => k -> n -> k
  pow = G.pow
  {-# INLINABLE pow #-}
  
  {-# SPECIALISE pow ::
    GaloisField k => k -> Int -> k,
    GaloisField k => k -> Integer -> k,
    GaloisField k => k -> Natural -> k,
    GaloisField k => k -> Word -> k
    #-}
  