packages feed

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

{-# LANGUAGE MagicHash #-}
{-# LANGUAGE UnliftedFFITypes #-}
module MCL.Curves.Fp254BNb.Fp
  ( Fp
  , mkFp
  , hashToFp
  , fromFp
  , fp_modulus
  , fp_isZero
  , fp_squareRoot
  ) where

import Control.DeepSeq
import Data.Binary
import Foreign.C.Types
import GHC.Exts
import GHC.Integer.GMP.Internals
import qualified Data.ByteString as BS

import MCL.Internal.Utils
import qualified MCL.Internal.Field as I
import qualified MCL.Internal.Prim as I

-- | Prime finite field of characteristic @p@.
data Fp = Fp { unFp :: I.CC Fp }

instance Binary Fp where
  put = putBytesFx 32 . fromFp
  get = mkFp <$> getBytesFx 32

instance NFData Fp where
  rnf = (`seq` ())

instance Num Fp where
  (+)         = I.addFp
  (-)         = I.subtractFp
  (*)         = I.multiplyFp
  negate      = I.negateFp
  abs         = I.absFp
  signum      = I.signumFp
  fromInteger = I.mkFp

instance Fractional Fp where
  recip        = I.recipFp
  fromRational = I.fromRationalFp

instance Eq Fp where
  (==) = I.eqFp

instance Show Fp where
  showsPrec = I.showsPrecFp

-- | Construct an element of Fp from Integer.
{-# INLINE mkFp #-}
mkFp :: Integer -> Fp
mkFp = I.mkFp

-- | Hash arbitrary message to Fp by computing its SHA256 hash and treating its
-- first 253 bits as the value of Fp.
{-# INLINE hashToFp #-}
hashToFp :: BS.ByteString -> Fp
hashToFp = I.hashToFp

-- | Convert the element of Fp back to non-negative Integer.
{-# INLINE fromFp #-}
fromFp :: Fp -> Integer
fromFp = I.fromFp

-- | Modulus of Fp.
{-# NOINLINE fp_modulus #-}
fp_modulus :: Integer
fp_modulus = I.modulus (proxy# :: Proxy# Fp)

-- | Check if the element of Fp is zero.
{-# INLINE fp_isZero #-}
fp_isZero :: Fp -> Bool
fp_isZero = I.isZero

-- | Compute square root of the element @a ∈ Fp@. If polynomial @x² - a@ has no
-- roots in Fp, no result is returned.
{-# INLINE fp_squareRoot #-}
fp_squareRoot :: Fp -> Maybe Fp
fp_squareRoot = I.squareRoot

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

-- | Internal
instance I.Prim Fp where
  prim_size _ = fromIntegral c_mcl_fp254bnb_fp_size
  prim_wrap   = Fp
  prim_unwrap = unFp

-- | Internal
instance I.BaseField Fp where
  c_limbs        _ = fromIntegral c_mcl_fp254bnb_fp_limbs
  c_modulus      _ = c_mcl_fp254bnb_fp_modulus
  c_hash_to      _ = c_mcl_fp254bnb_fp_hash_to
  c_from_integer _ = c_mcl_fp254bnb_fp_from_integer
  c_from_hsint   _ = c_mcl_fp254bnb_fp_from_hsint
  c_to_integer   _ = c_mcl_fp254bnb_fp_to_gmp_integer

-- | Internal
instance I.HasArith Fp where
  c_add      _ = c_mcl_fp254bnb_fp_add
  c_subtract _ = c_mcl_fp254bnb_fp_subtract
  c_multiply _ = c_mcl_fp254bnb_fp_multiply
  c_negate   _ = c_mcl_fp254bnb_fp_negate
  c_invert   _ = c_mcl_fp254bnb_fp_invert
  c_eq       _ = c_mcl_fp254bnb_fp_eq
  c_is_zero  _ = c_mcl_fp254bnb_fp_is_zero

-- | Internal
instance I.HasSqrt Fp where
  c_sqrt _ = c_mcl_fp254bnb_fp_sqrt

foreign import ccall unsafe "hs_mcl_fp254bnb_fp_size"
  c_mcl_fp254bnb_fp_size :: CInt

foreign import ccall unsafe "hs_mcl_fp254bnb_fp_limbs"
  c_mcl_fp254bnb_fp_limbs :: CInt

foreign import ccall unsafe "hs_mcl_fp254bnb_fp_modulus"
  c_mcl_fp254bnb_fp_modulus :: I.MC Integer -> CSize -> IO ()

foreign import ccall unsafe "hs_mcl_fp254bnb_fp_hash_to"
  c_mcl_fp254bnb_fp_hash_to :: Ptr CChar -> CSize -> I.MC Fp -> IO ()

foreign import ccall unsafe "hs_mcl_fp254bnb_fp_add"
  c_mcl_fp254bnb_fp_add :: I.CC Fp -> I.CC Fp -> I.MC Fp -> IO ()

foreign import ccall unsafe "hs_mcl_fp254bnb_fp_subtract"
  c_mcl_fp254bnb_fp_subtract :: I.CC Fp -> I.CC Fp -> I.MC Fp -> IO ()

foreign import ccall unsafe "hs_mcl_fp254bnb_fp_multiply"
  c_mcl_fp254bnb_fp_multiply :: I.CC Fp -> I.CC Fp -> I.MC Fp -> IO ()

foreign import ccall unsafe "hs_mcl_fp254bnb_fp_negate"
  c_mcl_fp254bnb_fp_negate :: I.CC Fp -> I.MC Fp -> IO ()

foreign import ccall unsafe "hs_mcl_fp254bnb_fp_from_integer"
  c_mcl_fp254bnb_fp_from_integer :: I.CC Integer -> GmpSize# -> I.MC Fp -> IO ()

foreign import ccall unsafe "hs_mcl_fp254bnb_fp_from_hsint"
  c_mcl_fp254bnb_fp_from_hsint :: Int# -> I.MC Fp -> IO ()

foreign import ccall unsafe "hs_mcl_fp254bnb_fp_invert"
  c_mcl_fp254bnb_fp_invert :: I.CC Fp -> I.MC Fp -> IO ()

foreign import ccall unsafe "hs_mcl_fp254bnb_fp_eq"
  c_mcl_fp254bnb_fp_eq :: I.CC Fp -> I.CC Fp -> IO CInt

foreign import ccall unsafe "hs_mcl_fp254bnb_fp_to_gmp_integer"
  c_mcl_fp254bnb_fp_to_gmp_integer :: I.CC Fp -> I.MC Integer -> CSize -> IO ()

foreign import ccall unsafe "hs_mcl_fp254bnb_fp_is_zero"
  c_mcl_fp254bnb_fp_is_zero :: I.CC Fp -> IO CInt

foreign import ccall unsafe "hs_mcl_fp254bnb_fp_sqrt"
  c_mcl_fp254bnb_fp_sqrt :: I.CC Fp -> I.MC Fp -> IO CInt