mcl-1.0.0: src/MCL/Curves/Fp254BNb/G2.hs
{-# LANGUAGE MagicHash #-}
{-# LANGUAGE MultiParamTypeClasses #-}
{-# LANGUAGE UnliftedFFITypes #-}
module MCL.Curves.Fp254BNb.G2
( G2
, mkG2
, mapToG2
, g2_zero
, g2_isZero
, g2_affineCoords
, g2_getYfromX
, g2_powFr
) where
import Control.DeepSeq
import Data.Binary
import Data.Bits
import Data.Group
import Data.Primitive.ByteArray
import Foreign.C.Types
import GHC.Exts
import GHC.Integer.GMP.Internals
import MCL.Curves.Fp254BNb.Fp
import MCL.Curves.Fp254BNb.Fp2
import MCL.Curves.Fp254BNb.Fr
import MCL.Internal.Utils
import qualified MCL.Internal.Group as I
import qualified MCL.Internal.Prim as I
-- | Subgroup of @E'(Fp2)@ (i.e. curve points with coordinates in Fp2) of order
-- @r@.
data G2 = G2 { unG2 :: I.CC G2 }
instance Binary G2 where
put = putCurvePoint g2_affineCoords putY
where
putY y = put . cintToBool . fromIntegral $ fromFp (fp2_c0 y) .&. 1
get = getCurvePoint g2_zero $ \x y_lsb ->
mkG2 x =<< g2_getYfromX y_lsb x
instance NFData G2 where
rnf = (`seq` ())
instance Eq G2 where
(==) = I.eqG
instance Show G2 where
showsPrec = I.showsPrecG
-- | Point addition.
instance Monoid G2 where
mempty = I.zero
mappend = I.plusG
-- | Note: 'pow' uses const-time method, just as 'g2_powFr'.
instance Group G2 where
invert = I.invertG
pow = flip I.scalarMul
instance Abelian G2
-- | Construct non-zero element of G2 from two coordinates in Fp2. If @(X,Y)@
-- does not lie on G2, no result is returned.
{-# INLINABLE mkG2 #-}
mkG2
:: Fp2 -- ^ X coordinate
-> Fp2 -- ^ Y coordinate
-> Maybe G2
mkG2 = I.mkG
-- | Map an element of Fp2 to a curve point.
{-# INLINABLE mapToG2 #-}
mapToG2 :: Fp2 -> G2
mapToG2 = I.mapToG
-- | Neutral element of G2 (point at infinity).
{-# NOINLINE g2_zero #-}
g2_zero :: G2
g2_zero = I.zero
-- | Check if the element of G2 is point at infinity.
{-# INLINABLE g2_isZero #-}
g2_isZero :: G2 -> Bool
g2_isZero = I.isZero
-- | Return affine coordinates of the element @a ∈ G2@. No result is returned if
-- @a@ is the point at inifinity.
{-# INLINABLE g2_affineCoords #-}
g2_affineCoords :: G2 -> Maybe (Fp2, Fp2)
g2_affineCoords = I.affineCoords
-- | Attempt to recover Y coordinate from its least significant bit and X
-- coordinate.
{-# INLINABLE g2_getYfromX #-}
g2_getYfromX
:: Bool -- ^ Least significant bit of Y coordinate
-> Fp2 -- ^ X coordinate
-> Maybe Fp2
g2_getYfromX = I.getYfromX (proxy# :: Proxy# G2)
-- | Multiply the element of G2 by a scalar @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 g2_powFr #-}
g2_powFr :: G2 -> Fr -> G2
g2_powFr = I.powFr
----------------------------------------
-- | Internal
instance I.Prim G2 where
prim_size _ = fromIntegral c_mcl_fp254bnb_g2_size
prim_wrap = G2
prim_unwrap = unG2
-- | Internal
instance I.CurveGroup Fp2 G2 where
c_zero _ = c_mcl_fp254bnb_g2_zero
c_construct _ = c_mcl_fp254bnb_g2_construct
c_map_to _ = c_mcl_fp254bnb_g2_map_to
c_add _ = c_mcl_fp254bnb_g2_add
c_invert _ = c_mcl_fp254bnb_g2_invert
c_scalar_mul_native _ = c_mcl_fp254bnb_g2_scalar_mul_native
c_scalar_mul_bignat _ = c_mcl_fp254bnb_g2_scalar_mul
c_scalar_mul_hsint _ = c_mcl_fp254bnb_g2_scalar_mul_small
c_eq _ = c_mcl_fp254bnb_g2_eq
c_is_zero _ = c_mcl_fp254bnb_g2_is_zero
c_affine_coords _ = c_mcl_fp254bnb_g2_affine_coords
c_y_from_x _ = c_mcl_fp254bnb_g2_y_from_x
foreign import ccall unsafe "hs_mcl_fp254bnb_g2_size"
c_mcl_fp254bnb_g2_size :: CInt
foreign import ccall unsafe "hs_mcl_fp254bnb_g2_zero"
c_mcl_fp254bnb_g2_zero :: I.MC G2 -> IO ()
foreign import ccall safe "hs_mcl_fp254bnb_g2_construct"
c_mcl_fp254bnb_g2_construct :: I.CC Fp2 -> I.CC Fp2 -> I.MC G2 -> IO CInt
foreign import ccall safe "hs_mcl_fp254bnb_g2_map_to"
c_mcl_fp254bnb_g2_map_to :: I.CC Fp2 -> I.MC G2 -> IO ()
foreign import ccall unsafe "hs_mcl_fp254bnb_g2_add"
c_mcl_fp254bnb_g2_add :: I.CC G2 -> I.CC G2 -> I.MC G2 -> IO ()
foreign import ccall unsafe "hs_mcl_fp254bnb_g2_invert"
c_mcl_fp254bnb_g2_invert :: I.CC G2 -> I.MC G2 -> IO ()
foreign import ccall safe "hs_mcl_fp254bnb_g2_scalar_mul_native"
c_mcl_fp254bnb_g2_scalar_mul_native :: CInt -> I.CC Fr -> I.CC G2 -> I.MC G2 -> IO ()
foreign import ccall safe "hs_mcl_fp254bnb_g2_scalar_mul"
c_mcl_fp254bnb_g2_scalar_mul :: CInt -> ByteArray# -> GmpSize# -> CInt
-> I.CC G2 -> I.MC G2 -> IO ()
foreign import ccall safe "hs_mcl_fp254bnb_g2_scalar_mul_small"
c_mcl_fp254bnb_g2_scalar_mul_small :: CInt -> Int# -> I.CC G2 -> I.MC G2 -> IO ()
foreign import ccall unsafe "hs_mcl_fp254bnb_g2_eq"
c_mcl_fp254bnb_g2_eq :: I.CC G2 -> I.CC G2 -> IO CInt
foreign import ccall unsafe "hs_mcl_fp254bnb_g2_is_zero"
c_mcl_fp254bnb_g2_is_zero :: I.CC G2 -> IO CInt
foreign import ccall unsafe "hs_mcl_fp254bnb_g2_affine_coords"
c_mcl_fp254bnb_g2_affine_coords :: I.CC G2 -> I.MC Fp2 -> I.MC Fp2 -> IO ()
foreign import ccall unsafe "hs_mcl_fp254bnb_g2_y_from_x"
c_mcl_fp254bnb_g2_y_from_x :: CInt -> I.CC Fp2 -> I.MC Fp2 -> IO CInt