module Crypto.Lol.Types.FiniteField
( PrimeField, CharOf, GF
, trace
, size
) where
import Crypto.Lol.CRTrans
import Crypto.Lol.Factored
import Crypto.Lol.LatticePrelude
import Crypto.Lol.Reflects
import Crypto.Lol.Types.PrimeField hiding ((^))
import qualified Crypto.Lol.Types.PrimeField as PF
import Algebra.Additive as Additive (C)
import Algebra.Field as Field (C)
import Algebra.Ring as Ring (C)
import Algebra.ZeroTestable as ZeroTestable (C)
import MathObj.Polynomial
import Math.NumberTheory.Primes.Factorisation
import Control.Applicative
import Control.DeepSeq
import Control.Monad
import qualified Data.Vector as V
newtype GF fp deg = GF (Polynomial fp)
deriving (Eq, Show, Additive.C, ZeroTestable.C, NFData)
type role GF representational representational
type GFCtx fp deg = (PrimeField fp, Reflects deg Int)
instance (GFCtx fp deg) => Enumerable (GF fp deg) where
values = GF <$> fromCoeffs <$>
replicateM (proxy value (Proxy::Proxy deg)) values
instance (GFCtx fp deg) => Ring.C (GF fp deg) where
one = GF one
(*) = let poly = proxy irreduciblePoly (Proxy :: Proxy deg)
in \(GF f) (GF g) -> GF $ (f*g) `mod` poly
fromInteger = GF . fromInteger
instance (GFCtx fp deg) => Field.C (GF fp deg) where
recip = let g = proxy irreduciblePoly (Proxy :: Proxy deg)
in \(GF f) -> let (_,(a,_)) = extendedGCD f g
in GF a
instance (GFCtx fp deg) => CRTrans (GF fp deg) where
crtInfo m = (,) <$> omegaPow <*> scalarInv
where
omegaPow =
let size' = proxy size (Proxy :: Proxy (GF fp deg))
(q,r) = (size'1) `quotRem` m
gen = head $ filter isPrimitive values
omega = gen^q
omegaPows = V.iterateN m (*omega) one
in if r == 0
then Just $ (omegaPows V.!) . (`mod` m)
else Nothing
scalarInv = Just $ recip $ fromIntegral $ valueHat m
sizePP :: forall fp deg . (GFCtx fp deg) => Tagged (GF fp deg) PP
sizePP = tag (proxy value (Proxy::Proxy (CharOf fp)),
proxy value (Proxy::Proxy deg))
size :: (GFCtx fp deg) => Tagged (GF fp deg) Int
size = uncurry (^) <$> sizePP
isPrimitive :: forall fp deg . (GFCtx fp deg) => GF fp deg -> Bool
isPrimitive = let q = proxy size (Proxy :: Proxy (GF fp deg))
ps = map (fromIntegral . fst) $ factorise $
fromIntegral $ q1
exps = map ((q1) `div`) ps
in \g -> not (isZero g) && all (\e -> g^e /= 1) exps
dotp :: (Ring a) => [a] -> [a] -> a
dotp a b = sum $ zipWith (*) a b
trace :: forall fp deg . (GFCtx fp deg) => GF fp deg -> fp
trace = let ts = proxy powTraces (Proxy::Proxy (GF fp deg))
in \(GF f) -> dotp ts (coeffs f)
powTraces :: forall fp deg . (GFCtx fp deg) => Tagged (GF fp deg) [fp]
powTraces =
let d = proxy value (Proxy :: Proxy deg)
in tag $ map trace' $ take d $
iterate (* (GF (X PF.^ 1))) (one :: GF fp deg)
trace' :: (GFCtx fp deg) => GF fp deg -> fp
trace' e = let (p,d) = witness sizePP e
(GF t) = sum $ take d $ iterate (^p) e
in head $ coeffs t