Flint2-0.1.0.0: src/Data/Number/Flint/NMod/FFI.hsc
{-|
module : Data.Number.Flint.NMod.FFI
copyright : (c) 2022 Hartmut Monien
license : GNU GPL, version 2 or above (see LICENSE)
maintainer : hmonien@uni-bonn.de
-}
module Data.Number.Flint.NMod.FFI (
-- * Integers mod n (word-size n)
NMod (..)
, CNMod (..)
-- * Memory management
, newNMod
, withNMod
, withNewNMod
, nmod_init
-- * Modular reduction and arithmetic
, _nmod_add
, nmod_add
, _nmod_sub
, nmod_sub
, nmod_neg
, nmod_mul
, _nmod_mul_fullword
, nmod_inv
, nmod_div
, nmod_pow_ui
-- * Discrete Logarithms via Pohlig-Hellman
, NModDiscreteLogPohligHellman (..)
, CNModDiscreteLogPohligHellman (..)
, nmod_discrete_log_pohlig_hellman_init
, nmod_discrete_log_pohlig_hellman_clear
, nmod_discrete_log_pohlig_hellman_precompute_prime
, nmod_discrete_log_pohlig_hellman_primitive_root
, nmod_discrete_log_pohlig_hellman_run
) where
-- integers mod n (word-size n) ------------------------------------------------
import Foreign.C.Types
import Foreign.ForeignPtr
import Foreign.Ptr ( Ptr, FunPtr, plusPtr, nullPtr )
import Foreign.Storable
import Data.Number.Flint.Flint
#include <flint/nmod.h>
-- NMod ------------------------------------------------------------------------
data NMod = NMod {-# UNPACK #-} !(ForeignPtr CNMod)
data CNMod = CNMod CMpLimb CMpLimb CFBitCnt
instance Storable CNMod where
{-# INLINE sizeOf #-}
sizeOf _ = #{size nmod_t}
{-# INLINE alignment #-}
alignment _ = #{alignment nmod_t}
peek ptr = return CNMod
<*> #{peek nmod_t, n } ptr
<*> #{peek nmod_t, ninv} ptr
<*> #{peek nmod_t, norm} ptr
poke = error "CNMod.poke: Not defined"
instance Show CNMod where
show (CNMod n ninv norm) = show n
-- NModDiscreteLogPohligHellman ------------------------------------------------
data NModDiscreteLogPohligHellman =
NModDiscreteLogPohligHellman !(ForeignPtr CNModDiscreteLogPohligHellman)
type CNModDiscreteLogPohligHellman = CFlint NModDiscreteLogPohligHellman
instance Storable CNModDiscreteLogPohligHellman where
{-# INLINE sizeOf #-}
sizeOf _ = #{size nmod_discrete_log_pohlig_hellman_t}
{-# INLINE alignment #-}
alignment _ = #{alignment nmod_discrete_log_pohlig_hellman_t}
peek ptr = error "CNModDiscreteLogPohligHellman poke: Not defined"
poke = error "CNMod.poke: Not defined"
-- Modular reduction and arithmetic --------------------------------------------
-- | Create a new `NMod` structure
newNMod n = do
x <- mallocForeignPtr
withForeignPtr x $ \x -> nmod_init x n
return $ NMod x
-- | Use `NMod` structure
{-# INLINE withNMod #-}
withNMod (NMod x) f = do
withForeignPtr x $ \xp -> f xp >>= return . (NMod x,)
withNewNMod n f = do
x <- newNMod n
withNMod x $ \x -> f x
--------------------------------------------------------------------------------
-- | /nmod_init/ /mod/ /n/
--
-- Initialises the given @nmod_t@ structure for reduction modulo \(n\) with
-- a precomputed inverse.
foreign import ccall "nmod.h nmod_init"
nmod_init :: Ptr CNMod -> CMpLimb -> IO ()
-- | /_nmod_add/ /a/ /b/ /mod/
--
-- Returns \(a + b\) modulo @mod.n@. It is assumed that @mod@ is no more
-- than @FLINT_BITS - 1@ bits. It is assumed that \(a\) and \(b\) are
-- already reduced modulo @mod.n@.
foreign import ccall "nmod.h _nmod_add"
_nmod_add :: CMpLimb -> CMpLimb -> Ptr CNMod -> IO CMpLimb
-- | /nmod_add/ /a/ /b/ /mod/
--
-- Returns \(a + b\) modulo @mod.n@. No assumptions are made about @mod.n@.
-- It is assumed that \(a\) and \(b\) are already reduced modulo @mod.n@.
foreign import ccall "nmod.h nmod_add"
nmod_add :: CMpLimb -> CMpLimb -> Ptr CNMod -> IO CMpLimb
-- | /_nmod_sub/ /a/ /b/ /mod/
--
-- Returns \(a - b\) modulo @mod.n@. It is assumed that @mod@ is no more
-- than @FLINT_BITS - 1@ bits. It is assumed that \(a\) and \(b\) are
-- already reduced modulo @mod.n@.
foreign import ccall "nmod.h _nmod_sub"
_nmod_sub :: CMpLimb -> CMpLimb -> Ptr CNMod -> IO CMpLimb
-- | /nmod_sub/ /a/ /b/ /mod/
--
-- Returns \(a - b\) modulo @mod.n@. No assumptions are made about @mod.n@.
-- It is assumed that \(a\) and \(b\) are already reduced modulo @mod.n@.
foreign import ccall "nmod.h nmod_sub"
nmod_sub :: CMpLimb -> CMpLimb -> Ptr CNMod -> IO CMpLimb
-- | /nmod_neg/ /a/ /mod/
--
-- Returns \(-a\) modulo @mod.n@. It is assumed that \(a\) is already
-- reduced modulo @mod.n@, but no assumptions are made about the latter.
foreign import ccall "nmod.h nmod_neg"
nmod_neg :: CMpLimb -> Ptr CNMod -> IO CMpLimb
-- | /nmod_mul/ /a/ /b/ /mod/
--
-- Returns \(ab\) modulo @mod.n@. No assumptions are made about @mod.n@. It
-- is assumed that \(a\) and \(b\) are already reduced modulo @mod.n@.
foreign import ccall "nmod.h nmod_mul"
nmod_mul :: CMpLimb -> CMpLimb -> Ptr CNMod -> IO CMpLimb
-- | /_nmod_mul_fullword/ /a/ /b/ /mod/
--
-- Returns \(ab\) modulo @mod.n@. Requires that @mod.n@ is exactly
-- @FLINT_BITS@ large. It is assumed that \(a\) and \(b\) are already
-- reduced modulo @mod.n@.
foreign import ccall "nmod.h _nmod_mul_fullword"
_nmod_mul_fullword :: CMpLimb -> CMpLimb -> Ptr CNMod -> IO CMpLimb
-- | /nmod_inv/ /a/ /mod/
--
-- Returns \(a^{-1}\) modulo @mod.n@. The inverse is assumed to exist.
foreign import ccall "nmod.h nmod_inv"
nmod_inv :: CMpLimb -> Ptr CNMod -> IO CMpLimb
-- | /nmod_div/ /a/ /b/ /mod/
--
-- Returns \(ab^{-1}\) modulo @mod.n@. The inverse of \(b\) is assumed to
-- exist. It is assumed that \(a\) is already reduced modulo @mod.n@.
foreign import ccall "nmod.h nmod_div"
nmod_div :: CMpLimb -> CMpLimb -> Ptr CNMod -> IO CMpLimb
-- | /nmod_pow_ui/ /a/ /e/ /mod/
--
-- Returns \(a^e\) modulo @mod.n@. No assumptions are made about @mod.n@.
-- It is assumed that \(a\) is already reduced modulo @mod.n@.
foreign import ccall "nmod.h nmod_pow_ui"
nmod_pow_ui :: CMpLimb -> CULong -> Ptr CNMod -> IO CMpLimb
-- Discrete Logarithms via Pohlig-Hellman --------------------------------------
-- | /nmod_discrete_log_pohlig_hellman_init/ /L/
--
-- Initialize @L@. Upon initialization @L@ is not ready for computation.
foreign import ccall "nmod.h nmod_discrete_log_pohlig_hellman_init"
nmod_discrete_log_pohlig_hellman_init :: Ptr CNModDiscreteLogPohligHellman -> IO ()
-- | /nmod_discrete_log_pohlig_hellman_clear/ /L/
--
-- Free any space used by @L@.
foreign import ccall "nmod.h nmod_discrete_log_pohlig_hellman_clear"
nmod_discrete_log_pohlig_hellman_clear :: Ptr CNModDiscreteLogPohligHellman -> IO ()
-- | /nmod_discrete_log_pohlig_hellman_precompute_prime/ /L/ /p/
--
-- Configure @L@ for discrete logarithms modulo @p@ to an internally chosen
-- base. It is assumed that @p@ is prime. The return is an estimate on the
-- number of multiplications needed for one run.
foreign import ccall "nmod.h nmod_discrete_log_pohlig_hellman_precompute_prime"
nmod_discrete_log_pohlig_hellman_precompute_prime :: Ptr CNModDiscreteLogPohligHellman -> CMpLimb -> IO CDouble
-- | /nmod_discrete_log_pohlig_hellman_primitive_root/ /L/
--
-- Return the internally stored base.
foreign import ccall "nmod.h nmod_discrete_log_pohlig_hellman_primitive_root"
nmod_discrete_log_pohlig_hellman_primitive_root :: Ptr CNModDiscreteLogPohligHellman -> IO CMpLimb
-- | /nmod_discrete_log_pohlig_hellman_run/ /L/ /y/
--
-- Return the logarithm of @y@ with respect to the internally stored base.
-- @y@ is expected to be reduced modulo the @p@. The function is undefined
-- if the logarithm does not exist.
foreign import ccall "nmod.h nmod_discrete_log_pohlig_hellman_run"
nmod_discrete_log_pohlig_hellman_run :: Ptr CNModDiscreteLogPohligHellman -> CMpLimb -> IO CULong