{-# LANGUAGE Strict #-}
module Pairing.Fq12 (
Fq12(..),
new,
deconstruct,
fq12inv,
fq12one,
fq12zero,
fq12conj,
fq12frobenius,
random
) where
import Protolude
import Crypto.Random (MonadRandom)
import Pairing.Fq (Fq)
import Pairing.Fq6 (Fq6(..))
import qualified Pairing.Fq2 as Fq2
import qualified Pairing.Fq6 as Fq6
import Pairing.Params
data Fq12 = Fq12 { fq12x :: Fq6, fq12y :: Fq6 }
deriving (Eq, Show)
instance Num Fq12 where
(+) = fq12add
(*) = fq12mul
negate = fq12neg
fromInteger = fq12int
abs = panic "abs not defined for fq12"
signum = panic "signum not defined for fq12"
instance Fractional Fq12 where
(/) = fq12div
fromRational (a :% b) = fq12int a / fq12int b
new :: [Fq] -> Fq12
new [a,b,c,d,e,f,g,h,i,j,k,l] = Fq12
(Fq6.new (Fq2.new a b) (Fq2.new c d) (Fq2.new e f))
(Fq6.new (Fq2.new g h) (Fq2.new i j) (Fq2.new k l))
new _ = panic "Invalid arguments to fq12"
deconstruct :: Fq12 -> [Fq]
deconstruct (Fq12
(Fq6.Fq6 (Fq2.Fq2 a b) (Fq2.Fq2 c d) (Fq2.Fq2 e f))
(Fq6.Fq6 (Fq2.Fq2 g h) (Fq2.Fq2 i j) (Fq2.Fq2 k l)))
= [a,b,c,d,e,f,g,h,i,j,k,l]
fq12int :: Integer -> Fq12
fq12int n = new (fromIntegral n : replicate 11 0)
fq12one :: Fq12
fq12one = fq12int 1
fq12zero :: Fq12
fq12zero = fq12int 0
fq12add :: Fq12 -> Fq12 -> Fq12
fq12add (Fq12 x y) (Fq12 a b) = Fq12 (x+a) (y+b)
fq12neg :: Fq12 -> Fq12
fq12neg (Fq12 x y) = Fq12 (negate x) (negate y)
fq12div :: Fq12 -> Fq12 -> Fq12
fq12div a b = a * fq12inv b
fq12mul :: Fq12 -> Fq12 -> Fq12
fq12mul (Fq12 x y) (Fq12 a b) = Fq12 (Fq6.mulXi bb + aa) ((x+y) * (a+b) - aa - bb)
where
aa = x*a
bb = y*b
{-# INLINEABLE fq12inv #-}
fq12inv :: Fq12 -> Fq12
fq12inv (Fq12 a b) = Fq12 (a*t) (-(b*t))
where
t = Fq6.fq6inv (a^2 - Fq6.mulXi (b^2))
fq12conj :: Fq12 -> Fq12
fq12conj (Fq12 x y) = Fq12 x (negate y)
fq12frobenius :: Int -> Fq12 -> Fq12
fq12frobenius i a
| i == 0 = a
| i == 1 = fastFrobenius1 a
| i > 1 = let prev = fq12frobenius (i - 1) a
in fastFrobenius1 prev
| otherwise = panic "fq12frobenius not defined for negative values of i"
fastFrobenius1 :: Fq12 -> Fq12
fastFrobenius1 (Fq12 (Fq6.Fq6 x0 x1 x2) (Fq6.Fq6 y0 y1 y2)) =
let
t1 = Fq2.fq2conj x0
t2 = Fq2.fq2conj y0
t3 = Fq2.fq2conj x1
t4 = Fq2.fq2conj y1
t5 = Fq2.fq2conj x2
t6 = Fq2.fq2conj y2
gamma1 :: Integer -> Fq2.Fq2
gamma1 i = Fq2.xi ^ ((i * (_q - 1)) `div` 6)
t11 = t1
t21 = t2 * gamma1 1
t31 = t3 * gamma1 2
t41 = t4 * gamma1 3
t51 = t5 * gamma1 4
t61 = t6 * gamma1 5
c0 = Fq6 t11 t31 t51
c1 = Fq6 t21 t41 t61
in Fq12 c0 c1
random :: MonadRandom m => m Fq12
random = do
x <- Fq6.random
y <- Fq6.random
pure (Fq12 x y)