module Data.Field.Galois.Frobenius
( frobenius
) where
import Protolude
import Data.Vector (Vector)
import Data.Field.Galois.Base (GaloisField(..))
frobenius :: GaloisField k => Vector k -> Vector k -> Maybe (Vector k)
frobenius [ ] _ = Just []
frobenius [a] _ = Just [frob a]
frobenius [a, b] [x, 0, 1]
| deg x == 2 = Just [a, negate b]
| char x == 2 = Just [frob a - frob b * x]
| otherwise = Just [frob a, frob b * nxq]
where
nxq = negate x ^ shiftR (char x) 1
frobenius [a, b] [x, 0, 0, 1]
| char x == 3 = Just [frob a - frob b * x]
| r == 1 = Just [frob a, frob b * nxq]
| otherwise = Just [frob a, 0, frob b * nxq]
where
(q, r) = quotRem (char x) 3
nxq = negate x ^ q
frobenius [a, b, c] [x, 0, 0, 1]
| char x == 3 = Just [frob a - (frob b - frob c * x) * x]
| r == 1 = Just [frob a, frob b * nxq, frob c * nxq * nxq]
| otherwise = Just [frob a, frob c * nx * nxq * nxq, frob b * nxq]
where
(q, r) = quotRem (char x) 3
nx = negate x
nxq = nx ^ q
frobenius _ _ = Nothing
{-# INLINABLE frobenius #-}