packages feed

mcl-1.0.0: src/MCL/Curves/Fp254BNb/GT.hs

{-# LANGUAGE GeneralizedNewtypeDeriving #-}
{-# LANGUAGE MagicHash #-}
{-# LANGUAGE UnliftedFFITypes #-}
module MCL.Curves.Fp254BNb.GT
  ( GT
  , mkGT
  , gt_powFr
  ) where

import Control.DeepSeq
import Data.Binary
import Data.Group
import Foreign.C.Types
import GHC.Exts

import MCL.Curves.Fp254BNb.Fp12
import MCL.Curves.Fp254BNb.Fr
import qualified MCL.Internal.Prim as I

-- | Subgroup of Fp12* of @r@-th roots of unity.
newtype GT = GT_ { unGT :: Fp12 }
  deriving (Binary, Eq, NFData)

instance Show GT where
  showsPrec p (GT_ a) = showsPrec p a

instance Monoid GT where
  mempty                  = GT_ 1
  mappend (GT_ a) (GT_ b) = GT_ (a * b)

instance Group GT where
  invert (GT_ a) = GT_ (recip a)
  pow a p  = a `gt_powFr` mkFr (toInteger p)

instance Abelian GT

-- | Construct an element of GT from @a ∈ Fp12@. If @a@ is not an @r@-th root of
-- unity, no result is returned.
{-# INLINABLE mkGT #-}
mkGT :: Fp12 -> Maybe GT
mkGT a = case a ^ fr_modulus of
  1 -> Just (GT_ a)
  _ -> Nothing

-- | Raise the element of GT to the power @x ∈ Fr@. Note: it uses const-time
-- method, i.e. the time it takes to calculate the result depends only on the
-- bitlength of @x@.
{-# INLINABLE gt_powFr #-}
gt_powFr :: GT -> Fr -> GT
gt_powFr (GT_ a) = GT_ . I.safeOp2_ (c_mcl_fp254bnb_gt_pow_native 1) a

----------------------------------------

-- | Internal
instance I.Prim GT where
  prim_size _ = I.prim_size (proxy# :: Proxy# Fp12)
  prim_wrap   = \ba -> GT_ (I.prim_wrap ba)
  prim_unwrap = \gt -> I.prim_unwrap (unGT gt)

foreign import ccall safe "hs_mcl_fp254bnb_gt_pow_native"
  c_mcl_fp254bnb_gt_pow_native :: CInt -> I.CC Fp12 -> I.CC Fr -> I.MC Fp12 -> IO ()