Flint2-0.1.0.0: src/Data/Number/Flint/Fmpz/Mod/FFI.hsc
{-|
module : Data.Number.Flint.Fmpz.Mod.FFI
copyright : (c) 2022 Hartmut Monien
license : GNU GPL, version 2 or above (see LICENSE)
maintainer : hmonien@uni-bonn.de
-}
module Data.Number.Flint.Fmpz.Mod.FFI (
-- * Arithmetic modulo integers
-- * Context object
FmpzModCtx (..)
, CFmpzModCtx (..)
, newFmpzModCtx
, withFmpzModCtx
, withNewFmpzModCtx
, fmpz_mod_ctx_init
, fmpz_mod_ctx_clear
, fmpz_mod_ctx_set_modulus
-- * Conversions
, fmpz_mod_set_fmpz
-- * Arithmetic
, fmpz_mod_is_canonical
, fmpz_mod_is_one
, fmpz_mod_add
, fmpz_mod_add_fmpz
, fmpz_mod_sub
, fmpz_mod_sub_fmpz
, fmpz_mod_fmpz_sub
, fmpz_mod_neg
, fmpz_mod_mul
, fmpz_mod_inv
, fmpz_mod_divides
, fmpz_mod_pow_ui
, fmpz_mod_pow_fmpz
-- * Discrete Logarithms via Pohlig-Hellman
, fmpz_mod_discrete_log_pohlig_hellman_init
, fmpz_mod_discrete_log_pohlig_hellman_clear
, fmpz_mod_discrete_log_pohlig_hellman_precompute_prime
, fmpz_mod_discrete_log_pohlig_hellman_primitive_root
, fmpz_mod_discrete_log_pohlig_hellman_run
, fmpz_next_smooth_prime
) where
-- arithmetic modulo integers --------------------------------------------------
import Control.Monad
import Foreign.C.String
import Foreign.C.Types
import Foreign.ForeignPtr
import Foreign.Ptr ( Ptr, FunPtr, plusPtr )
import Foreign.Storable
import Foreign.Marshal ( free )
import Data.Number.Flint.Flint
import Data.Number.Flint.Fmpz
#include <flint/flint.h>
#include <flint/fmpz.h>
#include <flint/fmpz_mod.h>
-- fmpz_mod_ctx_t --------------------------------------------------------------
data FmpzModCtx = FmpzModCtx {-# UNPACK #-} !(ForeignPtr CFmpzModCtx)
type CFmpzModCtx = CFlint FmpzModCtx
instance Storable CFmpzModCtx where
{-# INLINE sizeOf #-}
sizeOf _ = #{size fmpz_mod_ctx_t}
{-# INLINE alignment #-}
alignment _ = #{alignment fmpz_mod_ctx_t}
peek = error "CFmpzModCtx.peek: Not defined"
poke = error "CFmpzModCtx.poke: Not defined"
newFmpzModCtx n = do
p <- mallocForeignPtr
withFmpz n $ \n ->
withForeignPtr p $ \p ->
fmpz_mod_ctx_init p n
addForeignPtrFinalizer p_fmpz_mod_ctx_clear p
return $ FmpzModCtx p
{-# INLINE withFmpzModCtx #-}
withFmpzModCtx (FmpzModCtx p) f = do
withForeignPtr p $ \fp -> f fp >>= return . (FmpzModCtx p,)
{-# INLINE withNewFmpzModCtx #-}
withNewFmpzModCtx n f = newFmpzModCtx n >>= flip withFmpzModCtx f
-- Context object --------------------------------------------------------------
-- | /fmpz_mod_ctx_init/ /ctx/ /n/
--
-- Initialise @ctx@ for arithmetic modulo @n@, which is expected to be
-- positive.
foreign import ccall "fmpz_mod.h fmpz_mod_ctx_init"
fmpz_mod_ctx_init :: Ptr CFmpzModCtx -> Ptr CFmpz -> IO ()
-- | /fmpz_mod_ctx_clear/ /ctx/
--
-- Free any memory used by @ctx@.
foreign import ccall "fmpz_mod.h fmpz_mod_ctx_clear"
fmpz_mod_ctx_clear :: Ptr CFmpzModCtx -> IO ()
foreign import ccall "fmpz_mod.h &fmpz_mod_ctx_clear"
p_fmpz_mod_ctx_clear :: FunPtr (Ptr CFmpzModCtx -> IO ())
-- | /fmpz_mod_ctx_set_modulus/ /ctx/ /n/
--
-- Reconfigure @ctx@ for arithmetic modulo @n@.
foreign import ccall "fmpz_mod.h fmpz_mod_ctx_set_modulus"
fmpz_mod_ctx_set_modulus :: Ptr CFmpzModCtx -> Ptr CFmpz -> IO ()
-- Conversions -----------------------------------------------------------------
-- | /fmpz_mod_set_fmpz/ /a/ /b/ /ctx/
--
-- Set @a@ to @b@ after reduction modulo the modulus.
foreign import ccall "fmpz_mod.h fmpz_mod_set_fmpz"
fmpz_mod_set_fmpz :: Ptr CFmpz -> Ptr CFmpz -> Ptr CFmpzModCtx -> IO ()
-- Arithmetic ------------------------------------------------------------------
-- Unless specified otherwise all functions here expect their relevant
-- arguments to be in the canonical range \([0,n)\). Comparison of elements
-- against each other or against zero can be accomplished with
-- func::fmpz_equal or func::fmpz_is_zero without a context.
--
-- | /fmpz_mod_is_canonical/ /a/ /ctx/
--
-- Return @1@ if \(a\) is in the canonical range \([0,n)\) and @0@
-- otherwise.
foreign import ccall "fmpz_mod.h fmpz_mod_is_canonical"
fmpz_mod_is_canonical :: Ptr CFmpz -> Ptr CFmpzModCtx -> IO CInt
-- | /fmpz_mod_is_one/ /a/ /ctx/
--
-- Return @1@ if \(a\) is \(1\) modulo \(n\) and return @0@ otherwise.
foreign import ccall "fmpz_mod.h fmpz_mod_is_one"
fmpz_mod_is_one :: Ptr CFmpz -> Ptr CFmpzModCtx -> IO CInt
-- | /fmpz_mod_add/ /a/ /b/ /c/ /ctx/
--
-- Set \(a\) to \(b+c\) modulo \(n\).
foreign import ccall "fmpz_mod.h fmpz_mod_add"
fmpz_mod_add :: Ptr CFmpz -> Ptr CFmpz -> Ptr CFmpz -> Ptr CFmpzModCtx -> IO ()
-- | /fmpz_mod_add_fmpz/ /a/ /b/ /c/ /ctx/
--
-- Set \(a\) to \(b+c\) modulo \(n\) where only \(b\) is assumed to be
-- canonical.
foreign import ccall "fmpz_mod.h fmpz_mod_add_fmpz"
fmpz_mod_add_fmpz :: Ptr CFmpz -> Ptr CFmpz -> Ptr CFmpz -> Ptr CFmpzModCtx -> IO ()
-- | /fmpz_mod_sub/ /a/ /b/ /c/ /ctx/
--
-- Set \(a\) to \(b-c\) modulo \(n\).
foreign import ccall "fmpz_mod.h fmpz_mod_sub"
fmpz_mod_sub :: Ptr CFmpz -> Ptr CFmpz -> Ptr CFmpz -> Ptr CFmpzModCtx -> IO ()
-- | /fmpz_mod_sub_fmpz/ /a/ /b/ /c/ /ctx/
--
-- Set \(a\) to \(b-c\) modulo \(n\) where only \(b\) is assumed to be
-- canonical.
foreign import ccall "fmpz_mod.h fmpz_mod_sub_fmpz"
fmpz_mod_sub_fmpz :: Ptr CFmpz -> Ptr CFmpz -> Ptr CFmpz -> Ptr CFmpzModCtx -> IO ()
-- | /fmpz_mod_fmpz_sub/ /a/ /b/ /c/ /ctx/
--
-- Set \(a\) to \(b-c\) modulo \(n\) where only \(c\) is assumed to be
-- canonical.
foreign import ccall "fmpz_mod.h fmpz_mod_fmpz_sub"
fmpz_mod_fmpz_sub :: Ptr CFmpz -> Ptr CFmpz -> Ptr CFmpz -> Ptr CFmpzModCtx -> IO ()
-- | /fmpz_mod_neg/ /a/ /b/ /ctx/
--
-- Set \(a\) to \(-b\) modulo \(n\).
foreign import ccall "fmpz_mod.h fmpz_mod_neg"
fmpz_mod_neg :: Ptr CFmpz -> Ptr CFmpz -> Ptr CFmpzModCtx -> IO ()
-- | /fmpz_mod_mul/ /a/ /b/ /c/ /ctx/
--
-- Set \(a\) to \(b*c\) modulo \(n\).
foreign import ccall "fmpz_mod.h fmpz_mod_mul"
fmpz_mod_mul :: Ptr CFmpz -> Ptr CFmpz -> Ptr CFmpz -> Ptr CFmpzModCtx -> IO ()
-- | /fmpz_mod_inv/ /a/ /b/ /ctx/
--
-- Set \(a\) to \(b^{-1}\) modulo \(n\). This function expects that \(b\)
-- is invertible modulo \(n\) and throws if this not the case.
-- Invertibility maybe tested with func:fmpz_mod_pow_fmpz or
-- func:fmpz_mod_divides.
foreign import ccall "fmpz_mod.h fmpz_mod_inv"
fmpz_mod_inv :: Ptr CFmpz -> Ptr CFmpz -> Ptr CFmpzModCtx -> IO ()
-- | /fmpz_mod_divides/ /a/ /b/ /c/ /ctx/
--
-- If \(a*c = b \mod n\) has a solution for \(a\) return \(1\) and set
-- \(a\) to such a solution. Otherwise return \(0\) and leave \(a\)
-- undefined.
foreign import ccall "fmpz_mod.h fmpz_mod_divides"
fmpz_mod_divides :: Ptr CFmpz -> Ptr CFmpz -> Ptr CFmpz -> Ptr CFmpzModCtx -> IO CInt
-- | /fmpz_mod_pow_ui/ /a/ /b/ /e/ /ctx/
--
-- Set \(a\) to \(b^e\) modulo \(n\).
foreign import ccall "fmpz_mod.h fmpz_mod_pow_ui"
fmpz_mod_pow_ui :: Ptr CFmpz -> Ptr CFmpz -> CULong -> Ptr CFmpzModCtx -> IO ()
-- | /fmpz_mod_pow_fmpz/ /a/ /b/ /e/ /ctx/
--
-- Try to set \(a\) to \(b^e\) modulo \(n\). If \(e < 0\) and \(b\) is not
-- invertible modulo \(n\), the return is \(0\). Otherwise, the return is
-- \(1\).
foreign import ccall "fmpz_mod.h fmpz_mod_pow_fmpz"
fmpz_mod_pow_fmpz :: Ptr CFmpz -> Ptr CFmpz -> Ptr CFmpz -> Ptr CFmpzModCtx -> IO CInt
-- Discrete Logarithms via Pohlig-Hellman --------------------------------------
-- fmpz_mod_discrete_log_pohlig_hellman_t --------------------------------------
data FmpzModDiscreteLogPohligHellmann = FmpzModDiscreteLogPohligHellmann {-# UNPACK #-} !(ForeignPtr CFmpzModDiscreteLogPohligHellmann)
type CFmpzModDiscreteLogPohligHellmann = CFlint FmpzModDiscreteLogPohligHellmann
instance Storable CFmpzModDiscreteLogPohligHellmann where
{-# INLINE sizeOf #-}
sizeOf _ = #{size fmpz_mod_discrete_log_pohlig_hellman_t}
{-# INLINE alignment #-}
alignment _ = #{alignment fmpz_mod_discrete_log_pohlig_hellman_t}
peek = error "CCFmpzModDiscreteLogPohligHellmann.peek: Not defined"
poke = error "CCFmpzModDiscreteLogPohligHellmann.poke: Not defined"
newCFmpzModDiscreteLogPohligHellmann = do
p <- mallocForeignPtr
withForeignPtr p fmpz_mod_discrete_log_pohlig_hellman_init
addForeignPtrFinalizer p_fmpz_mod_discrete_log_pohlig_hellman_clear p
return $ FmpzModDiscreteLogPohligHellmann p
-- | /fmpz_mod_discrete_log_pohlig_hellman_init/ /L/
--
-- Initialize @L@. Upon initialization @L@ is not ready for computation.
foreign import ccall "fmpz_mod.h fmpz_mod_discrete_log_pohlig_hellman_init"
fmpz_mod_discrete_log_pohlig_hellman_init :: Ptr CFmpzModDiscreteLogPohligHellmann -> IO ()
-- | /fmpz_mod_discrete_log_pohlig_hellman_clear/ /L/
--
-- Free any space used by @L@.
foreign import ccall "fmpz_mod.h fmpz_mod_discrete_log_pohlig_hellman_clear"
fmpz_mod_discrete_log_pohlig_hellman_clear :: Ptr CFmpzModDiscreteLogPohligHellmann -> IO ()
foreign import ccall "fmpz_mod.h &fmpz_mod_discrete_log_pohlig_hellman_clear"
p_fmpz_mod_discrete_log_pohlig_hellman_clear :: FunPtr (Ptr CFmpzModDiscreteLogPohligHellmann -> IO ())
-- | /fmpz_mod_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 "fmpz_mod.h fmpz_mod_discrete_log_pohlig_hellman_precompute_prime"
fmpz_mod_discrete_log_pohlig_hellman_precompute_prime :: Ptr CFmpzModDiscreteLogPohligHellmann -> Ptr CFmpz -> IO CDouble
-- | /fmpz_mod_discrete_log_pohlig_hellman_primitive_root/ /L/
--
-- Return the internally stored base.
foreign import ccall "fmpz_mod.h fmpz_mod_discrete_log_pohlig_hellman_primitive_root"
fmpz_mod_discrete_log_pohlig_hellman_primitive_root :: Ptr CFmpzModDiscreteLogPohligHellmann -> IO (Ptr CFmpz)
-- | /fmpz_mod_discrete_log_pohlig_hellman_run/ /x/ /L/ /y/
--
-- Set @x@ to 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 "fmpz_mod.h fmpz_mod_discrete_log_pohlig_hellman_run"
fmpz_mod_discrete_log_pohlig_hellman_run :: Ptr CFmpz -> Ptr CFmpzModDiscreteLogPohligHellmann -> Ptr CFmpz -> IO ()
-- | /fmpz_next_smooth_prime/ /a/ /b/
--
-- Either return \(1\) and set \(a\) to a smooth prime strictly greater
-- than \(b\), or return \(0\) and set \(a\) to \(0\). The smooth primes
-- returned by this function currently have no prime factor of \(a-1\)
-- greater than \(23\), but this should not be relied upon.
foreign import ccall "fmpz_mod.h fmpz_next_smooth_prime"
fmpz_next_smooth_prime :: Ptr CFmpz -> Ptr CFmpz -> IO CInt