Flint2-0.1.0.0: src/Data/Number/Flint/APRCL/FFI.hsc
{-|
module : Data.Number.Flint.APRCL.FFI
copyright : (c) 2022 Hartmut Monien
license : GNU GPL, version 2 or above (see LICENSE)
maintainer : hmonien@uni-bonn.de
-}
module Data.Number.Flint.APRCL.FFI (
-- * APRCL primality testing
APRCLConfig (..)
, CAPRCLConfig (..)
, newAPRCLConfigGauss
, newAPRCLConfigJacobi
, withAPRCLConfig
-- * Primality test functions
, aprcl_is_prime
, aprcl_is_prime_jacobi
, aprcl_is_prime_gauss
, _aprcl_is_prime_jacobi
, _aprcl_is_prime_gauss
, aprcl_is_prime_gauss_min_R
, aprcl_is_prime_final_division
-- * Configuration functions
, aprcl_config_gauss_init
, aprcl_config_gauss_init_min_R
, aprcl_config_gauss_clear
, aprcl_R_value
, aprcl_config_jacobi_init
, aprcl_config_jacobi_clear
-- * Cyclotomic arithmetic
, UnityZp (..)
, CUnityZp (..)
, newUnityZp
, withUnityZp
, UnityZpq (..)
, CUnityZpq (..)
, newUnityZpq
, withUnityZpq
-- * Memory management
, unity_zp_init
, unity_zp_clear
, unity_zp_copy
, unity_zp_swap
, unity_zp_set_zero
-- * Comparison
, unity_zp_is_unity
, unity_zp_equal
-- * Output
, unity_zp_print
-- * Coefficient management
, unity_zp_coeff_set_fmpz
, unity_zp_coeff_set_ui
, unity_zp_coeff_add_fmpz
, unity_zp_coeff_add_ui
, unity_zp_coeff_inc
, unity_zp_coeff_dec
-- * Scalar multiplication
, unity_zp_mul_scalar_fmpz
, unity_zp_mul_scalar_ui
-- * Addition and multiplication
, unity_zp_add
, unity_zp_mul
, unity_zp_sqr
, unity_zp_mul_inplace
, unity_zp_sqr_inplace
-- * Powering functions
, unity_zp_pow_fmpz
, unity_zp_pow_ui
, _unity_zp_pow_select_k
, unity_zp_pow_2k_fmpz
, unity_zp_pow_2k_ui
, unity_zp_pow_sliding_fmpz
-- * Cyclotomic reduction
, _unity_zp_reduce_cyclotomic_divmod
, _unity_zp_reduce_cyclotomic
, unity_zp_reduce_cyclotomic
-- * Automorphism and inverse
, unity_zp_aut
, unity_zp_aut_inv
-- * Jacobi sum
, unity_zp_jacobi_sum_pq
, unity_zp_jacobi_sum_2q_one
, unity_zp_jacobi_sum_2q_two
-- * Extended rings
, unity_zpq_init
, unity_zpq_clear
, unity_zpq_copy
, unity_zpq_swap
, unity_zpq_equal
, unity_zpq_p_unity
, unity_zpq_is_p_unity
, unity_zpq_is_p_unity_generator
, unity_zpq_coeff_set_fmpz
, unity_zpq_coeff_set_ui
, unity_zpq_coeff_add
, unity_zpq_add
, unity_zpq_mul
, _unity_zpq_mul_unity_p
, unity_zpq_mul_unity_p_pow
, unity_zpq_pow
, unity_zpq_pow_ui
, unity_zpq_gauss_sum
, unity_zpq_gauss_sum_sigma_pow
) where
-- APRCL primality testing -----------------------------------------------------
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
import Data.Number.Flint.Fmpz.Mod
import Data.Number.Flint.Fmpz.Mod.Poly
import Data.Number.Flint.Support.ULong.Extras
#include <flint/flint.h>
#include <flint/fmpz.h>
#include <flint/aprcl.h>
-- aprcl_config ----------------------------------------------------------------
data APRCLConfig =
Gauss {-# UNPACK #-} !(ForeignPtr CAPRCLConfig)
| Jacobi {-# UNPACK #-} !(ForeignPtr CAPRCLConfig)
data CAPRCLConfig =
CAPRCLConfig CULong
(Ptr CFmpz)
(Ptr CNFactor)
(Ptr CFmpz)
(Ptr CInt)
instance Storable CAPRCLConfig where
{-# INLINE sizeOf #-}
sizeOf _ = #{size aprcl_config}
{-# INLINE alignment #-}
alignment _ = #{alignment aprcl_config}
peek = error "CAPRCLConfig.peek: not implemented."
poke = error "CAPRCLConfig.poke: not implemented."
newAPRCLConfigGauss n = do
x <- mallocForeignPtr
withForeignPtr x $ \x ->
withFmpz n $ \n ->
aprcl_config_gauss_init x n
addForeignPtrFinalizer p_aprcl_config_gauss_clear x
return $ Gauss x
newAPRCLConfigJacobi n = do
x <- mallocForeignPtr
withForeignPtr x $ \x ->
withFmpz n $ \n ->
aprcl_config_jacobi_init x n
addForeignPtrFinalizer p_aprcl_config_jacobi_clear x
return $ Jacobi x
withAPRCLConfig (Gauss x) f = do
withForeignPtr x $ \px -> f px >>= return . (Gauss x,)
withAPRCLConfig (Jacobi x) f = do
withForeignPtr x $ \px -> f px >>= return . (Jacobi x,)
-- primality_test_status -------------------------------------------------------
newtype PrimalityTestStatus =
PrimalityTestStatus { _PrimalityTestStatus :: CInt } deriving Eq
instance Show PrimalityTestStatus where
show status
| status == unknown = "UNKNOWN"
| status == prime = "PRIME"
| status == composite = "COMPOSITE"
| status == probaprime = "PROBABPRIME"
| otherwise = "unknown PrimalityTestStatus."
unknown = PrimalityTestStatus #const UNKNOWN
prime = PrimalityTestStatus #const PRIME
composite = PrimalityTestStatus #const COMPOSITE
probaprime = PrimalityTestStatus #const PROBABPRIME
-- Primality test functions ----------------------------------------------------
-- | /aprcl_is_prime/ /n/
--
-- Tests \(n\) for primality using the APRCL test. This is the same as
-- @aprcl_is_prime_jacobi@.
foreign import ccall "aprcl.h aprcl_is_prime"
aprcl_is_prime :: Ptr CFmpz -> IO CInt
-- | /aprcl_is_prime_jacobi/ /n/
--
-- If \(n\) is prime returns 1; otherwise returns 0. The algorithm is well
-- described in \"Implementation of a New Primality Test\" by H. Cohen and
-- A.K. Lenstra and \"A Course in Computational Algebraic Number Theory\"
-- by H. Cohen.
--
-- It is theoretically possible that this function fails to prove that
-- \(n\) is prime. In this event, @flint_abort@ is called. To handle this
-- condition, the @_aprcl_is_prime_jacobi@ function can be used.
foreign import ccall "aprcl.h aprcl_is_prime_jacobi"
aprcl_is_prime_jacobi :: Ptr CFmpz -> IO CInt
-- | /aprcl_is_prime_gauss/ /n/
--
-- If \(n\) is prime returns 1; otherwise returns 0. Uses the cyclotomic
-- primality testing algorithm described in \"Four primality testing
-- algorithms\" by Rene Schoof. The minimum required numbers \(s\) and
-- \(R\) are computed automatically.
--
-- By default \(R \ge 180\). In some cases this function fails to prove
-- that \(n\) is prime. This means that we select a too small \(R\) value.
-- In this event, @flint_abort@ is called. To handle this condition, the
-- @_aprcl_is_prime_jacobi@ function can be used.
foreign import ccall "aprcl.h aprcl_is_prime_gauss"
aprcl_is_prime_gauss :: Ptr CFmpz -> IO CInt
-- | /_aprcl_is_prime_jacobi/ /n/ /config/
--
-- Jacobi sum test for \(n\). Possible return values: @PRIME@, @COMPOSITE@
-- and @UNKNOWN@ (if we cannot prove primality).
foreign import ccall "aprcl.h _aprcl_is_prime_jacobi"
_aprcl_is_prime_jacobi :: Ptr CFmpz -> Ptr CAPRCLConfig -> IO PrimalityTestStatus
-- | /_aprcl_is_prime_gauss/ /n/ /config/
--
-- Tests \(n\) for primality with fixed @config@. Possible return values:
-- @PRIME@, @COMPOSITE@ and @PROBABPRIME@ (if we cannot prove primality).
foreign import ccall "aprcl.h _aprcl_is_prime_gauss"
_aprcl_is_prime_gauss :: Ptr CFmpz -> Ptr CAPRCLConfig -> IO PrimalityTestStatus
-- | /aprcl_is_prime_gauss_min_R/ /n/ /R/
--
-- Same as @aprcl_is_prime_gauss@ with fixed minimum value of \(R\).
foreign import ccall "aprcl.h aprcl_is_prime_gauss_min_R"
aprcl_is_prime_gauss_min_R :: Ptr CFmpz -> CULong -> IO ()
-- | /aprcl_is_prime_final_division/ /n/ /s/ /r/
--
-- Returns 0 if for some \(a = n^k \bmod s\), where \(k \in [1, r - 1]\),
-- we have that \(a \mid n\); otherwise returns 1.
foreign import ccall "aprcl.h aprcl_is_prime_final_division"
aprcl_is_prime_final_division :: Ptr CFmpz -> Ptr CFmpz -> CULong -> IO CInt
-- Configuration functions -----------------------------------------------------
-- | /aprcl_config_gauss_init/ /conf/ /n/
--
-- Computes the \(s\) and \(R\) values used in the cyclotomic primality
-- test, \(s^2 > n\) and
-- \(s=\prod\limits_{\substack{q-1\mid R \\ q \text{ prime}}}q\). Also
-- stores factors of \(R\) and \(s\).
foreign import ccall "aprcl.h aprcl_config_gauss_init"
aprcl_config_gauss_init :: Ptr CAPRCLConfig -> Ptr CFmpz -> IO ()
-- | /aprcl_config_gauss_init_min_R/ /conf/ /n/ /R/
--
-- Computes the \(s\) with fixed minimum \(R\) such that
-- \(a^R \equiv 1 \mod{s}\) for all integers \(a\) coprime to \(s\).
foreign import ccall "aprcl.h aprcl_config_gauss_init_min_R"
aprcl_config_gauss_init_min_R :: Ptr CAPRCLConfig -> Ptr CFmpz -> CULong -> IO ()
-- | /aprcl_config_gauss_clear/ /conf/
--
-- Clears the given @aprcl_config@ element. It must be reinitialised in
-- order to be used again.
foreign import ccall "aprcl.h aprcl_config_gauss_clear"
aprcl_config_gauss_clear :: Ptr CAPRCLConfig -> IO ()
foreign import ccall "aprcl.h &aprcl_config_gauss_clear"
p_aprcl_config_gauss_clear :: FunPtr (Ptr CAPRCLConfig -> IO ())
-- | /aprcl_R_value/ /n/
--
-- Returns a precomputed \(R\) value for APRCL, such that the corresponding
-- \(s\) value is greater than \(\sqrt{n}\). The maximum stored value
-- \(6983776800\) allows to test numbers up to \(6000\) digits.
foreign import ccall "aprcl.h aprcl_R_value"
aprcl_R_value :: Ptr CFmpz -> IO CULong
-- | /aprcl_config_jacobi_init/ /conf/ /n/
--
-- Computes the \(s\) and \(R\) values used in the cyclotomic primality
-- test, \(s^2 > n\) and \(a^R \equiv 1 \mod{s}\) for all \(a\) coprime to
-- \(s\). Also stores factors of \(R\) and \(s\).
foreign import ccall "aprcl.h aprcl_config_jacobi_init"
aprcl_config_jacobi_init :: Ptr CAPRCLConfig -> Ptr CFmpz -> IO ()
-- | /aprcl_config_jacobi_clear/ /conf/
--
-- Clears the given @aprcl_config@ element. It must be reinitialised in
-- order to be used again.
foreign import ccall "aprcl.h aprcl_config_jacobi_clear"
aprcl_config_jacobi_clear :: Ptr CAPRCLConfig -> IO ()
foreign import ccall "aprcl.h &aprcl_config_jacobi_clear"
p_aprcl_config_jacobi_clear :: FunPtr (Ptr CAPRCLConfig -> IO ())
-- Cyclotomic arithmetic -------------------------------------------------------
-- unity_zpq -------------------------------------------------------------------
data UnityZpq = UnityZpq {-# UNPACK #-} !(ForeignPtr CUnityZpq)
type CUnityZpq = CFlint UnityZpq
instance Storable CUnityZpq where
{-# INLINE sizeOf #-}
sizeOf _ = #{size unity_zpq}
{-# INLINE alignment #-}
alignment _ = #{alignment unity_zpq}
peek = error "CUnityZpq.peek: not implemented."
poke = error "CUnityZpq.poke: not implemented."
newUnityZpq q p n = do
x <- mallocForeignPtr
withForeignPtr x $ \x ->
withFmpz n $ \n ->
unity_zpq_init x q p n
addForeignPtrFinalizer p_unity_zpq_clear x
return $ UnityZpq x
{-# INLINE withUnityZpq #-}
withUnityZpq (UnityZpq x) f = do
withForeignPtr x $ \px -> f px >>= return . (UnityZpq x,)
-- unity_zp --------------------------------------------------------------------
data UnityZp = UnityZp {-# UNPACK #-} !(ForeignPtr CUnityZp )
data CUnityZp = CUnityZp (Ptr CFmpzModPoly) CULong CULong (Ptr CFmpzModCtx)
instance Storable CUnityZp where
{-# INLINE sizeOf #-}
sizeOf _ = #{size unity_zp}
{-# INLINE alignment #-}
alignment _ = #{alignment unity_zp}
peek ptr = CUnityZp
<$> #{peek _unity_zp, poly} ptr
<*> #{peek _unity_zp, p } ptr
<*> #{peek _unity_zp, exp } ptr
<*> #{peek _unity_zp, ctx } ptr
poke = error "CUnityZp.poke: not implemented."
newUnityZp p exp n = do
x <- mallocForeignPtr
withForeignPtr x $ \x ->
withFmpz n $ \n ->
unity_zp_init x p exp n
addForeignPtrFinalizer p_unity_zp_clear x
return $ UnityZp x
{-# INLINE withUnityZp #-}
withUnityZp (UnityZp x) f = do
withForeignPtr x $ \px -> f px >>= return . (UnityZp x,)
-- Memory management -----------------------------------------------------------
-- | /unity_zp_init/ /f/ /p/ /exp/ /n/
--
-- Initializes \(f\) as an element of \(\mathbb{Z}[\zeta_{p^{exp}}]/(n)\).
foreign import ccall "aprcl.h unity_zp_init"
unity_zp_init :: Ptr CUnityZp -> CULong -> CULong -> Ptr CFmpz -> IO ()
-- | /unity_zp_clear/ /f/
--
-- Clears the given element. It must be reinitialised in order to be used
-- again.
foreign import ccall "aprcl.h unity_zp_clear"
unity_zp_clear :: Ptr CUnityZp -> IO ()
foreign import ccall "aprcl.h &unity_zp_clear"
p_unity_zp_clear :: FunPtr (Ptr CUnityZp -> IO ())
-- | /unity_zp_copy/ /f/ /g/
--
-- Sets \(f\) to \(g\). \(f\) and \(g\) must be initialized with same \(p\)
-- and \(n\).
foreign import ccall "aprcl.h unity_zp_copy"
unity_zp_copy :: Ptr CUnityZp -> Ptr CUnityZp -> IO ()
-- | /unity_zp_swap/ /f/ /q/
--
-- Swaps \(f\) and \(g\). \(f\) and \(g\) must be initialized with same
-- \(p\) and \(n\).
foreign import ccall "aprcl.h unity_zp_swap"
unity_zp_swap :: Ptr CUnityZp -> Ptr CUnityZp -> IO ()
-- | /unity_zp_set_zero/ /f/
--
-- Sets \(f\) to zero.
foreign import ccall "aprcl.h unity_zp_set_zero"
unity_zp_set_zero :: Ptr CUnityZp -> IO ()
-- Comparison ------------------------------------------------------------------
-- | /unity_zp_is_unity/ /f/
--
-- If \(f = \zeta^h\) returns h; otherwise returns -1.
foreign import ccall "aprcl.h unity_zp_is_unity"
unity_zp_is_unity :: Ptr CUnityZp -> IO CLong
-- | /unity_zp_equal/ /f/ /g/
--
-- Returns nonzero if \(f = g\) reduced by the \(p^{exp}\)-th cyclotomic
-- polynomial.
foreign import ccall "aprcl.h unity_zp_equal"
unity_zp_equal :: Ptr CUnityZp -> Ptr CUnityZp -> IO CInt
-- Output ----------------------------------------------------------------------
foreign import ccall "aprcl.h unity_zp_get_str"
unity_zp_get_str :: Ptr CUnityZp -> IO CString
-- | /unity_zp_print/ /f/
--
-- Prints the contents of the \(f\).
unity_zp_print :: Ptr CUnityZp -> IO ()
unity_zp_print z = do
printCStr unity_zp_get_str z
return ()
-- Coefficient management ------------------------------------------------------
-- | /unity_zp_coeff_set_fmpz/ /f/ /ind/ /x/
foreign import ccall "aprcl.h unity_zp_coeff_set_fmpz"
unity_zp_coeff_set_fmpz :: Ptr CUnityZp -> CULong -> Ptr CFmpz -> IO ()
-- | /unity_zp_coeff_set_ui/ /f/ /ind/ /x/
--
-- Sets the coefficient of \(\zeta^{ind}\) to \(x\). \(ind\) must be less
-- than \(p^{exp}\).
foreign import ccall "aprcl.h unity_zp_coeff_set_ui"
unity_zp_coeff_set_ui :: Ptr CUnityZp -> CULong -> CULong -> IO ()
-- | /unity_zp_coeff_add_fmpz/ /f/ /ind/ /x/
foreign import ccall "aprcl.h unity_zp_coeff_add_fmpz"
unity_zp_coeff_add_fmpz :: Ptr CUnityZp -> CULong -> Ptr CFmpz -> IO ()
-- | /unity_zp_coeff_add_ui/ /f/ /ind/ /x/
--
-- Adds \(x\) to the coefficient of \(\zeta^{ind}\). \(x\) must be less
-- than \(n\). \(ind\) must be less than \(p^{exp}\).
foreign import ccall "aprcl.h unity_zp_coeff_add_ui"
unity_zp_coeff_add_ui :: Ptr CUnityZp -> CULong -> CULong -> IO ()
-- | /unity_zp_coeff_inc/ /f/ /ind/
--
-- Increments the coefficient of \(\zeta^{ind}\). \(ind\) must be less than
-- \(p^{exp}\).
foreign import ccall "aprcl.h unity_zp_coeff_inc"
unity_zp_coeff_inc :: Ptr CUnityZp -> CULong -> IO ()
-- | /unity_zp_coeff_dec/ /f/ /ind/
--
-- Decrements the coefficient of \(\zeta^{ind}\). \(ind\) must be less than
-- \(p^{exp}\).
foreign import ccall "aprcl.h unity_zp_coeff_dec"
unity_zp_coeff_dec :: Ptr CUnityZp -> CULong -> IO ()
-- Scalar multiplication -------------------------------------------------------
-- | /unity_zp_mul_scalar_fmpz/ /f/ /g/ /s/
--
-- Sets \(f\) to \(s \cdot g\). \(f\) and \(g\) must be initialized with
-- same \(p\), \(exp\) and \(n\).
foreign import ccall "aprcl.h unity_zp_mul_scalar_fmpz"
unity_zp_mul_scalar_fmpz :: Ptr CUnityZp -> Ptr CUnityZp -> Ptr CFmpz -> IO ()
-- | /unity_zp_mul_scalar_ui/ /f/ /g/ /s/
--
-- Sets \(f\) to \(s \cdot g\). \(f\) and \(g\) must be initialized with
-- same \(p\), \(exp\) and \(n\).
foreign import ccall "aprcl.h unity_zp_mul_scalar_ui"
unity_zp_mul_scalar_ui :: Ptr CUnityZp -> Ptr CUnityZp -> CULong -> IO ()
-- Addition and multiplication -------------------------------------------------
-- | /unity_zp_add/ /f/ /g/ /h/
--
-- Sets \(f\) to \(g + h\). \(f\), \(g\) and \(h\) must be initialized with
-- same \(p\), \(exp\) and \(n\).
foreign import ccall "aprcl.h unity_zp_add"
unity_zp_add :: Ptr CUnityZp -> Ptr CUnityZp -> Ptr CUnityZp -> IO ()
-- | /unity_zp_mul/ /f/ /g/ /h/
--
-- Sets \(f\) to \(g \cdot h\). \(f\), \(g\) and \(h\) must be initialized
-- with same \(p\), \(exp\) and \(n\).
foreign import ccall "aprcl.h unity_zp_mul"
unity_zp_mul :: Ptr CUnityZp -> Ptr CUnityZp -> Ptr CUnityZp -> IO ()
-- | /unity_zp_sqr/ /f/ /g/
--
-- Sets \(f\) to \(g \cdot g\). \(f\), \(g\) and \(h\) must be initialized
-- with same \(p\), \(exp\) and \(n\).
foreign import ccall "aprcl.h unity_zp_sqr"
unity_zp_sqr :: Ptr CUnityZp -> Ptr CUnityZp -> IO ()
-- | /unity_zp_mul_inplace/ /f/ /g/ /h/ /t/
--
-- Sets \(f\) to \(g \cdot h\). If \(p^{exp} = 3, 4, 5, 7, 8, 9, 11, 16\)
-- special multiplication functions are used. The preallocated array \(t\)
-- of @fmpz_t@ is used for all computations in this case. \(f\), \(g\) and
-- \(h\) must be initialized with same \(p\), \(exp\) and \(n\).
foreign import ccall "aprcl.h unity_zp_mul_inplace"
unity_zp_mul_inplace :: Ptr CUnityZp -> Ptr CUnityZp -> Ptr CUnityZp -> Ptr (Ptr CFmpz) -> IO ()
-- | /unity_zp_sqr_inplace/ /f/ /g/ /t/
--
-- Sets \(f\) to \(g \cdot g\). If \(p^{exp} = 3, 4, 5, 7, 8, 9, 11, 16\)
-- special multiplication functions are used. The preallocated array \(t\)
-- of @fmpz_t@ is used for all computations in this case. \(f\) and \(g\)
-- must be initialized with same \(p\), \(exp\) and \(n\).
foreign import ccall "aprcl.h unity_zp_sqr_inplace"
unity_zp_sqr_inplace :: Ptr CUnityZp -> Ptr CUnityZp -> Ptr (Ptr CFmpz) -> IO ()
-- Powering functions ----------------------------------------------------------
-- | /unity_zp_pow_fmpz/ /f/ /g/ /pow/
--
-- Sets \(f\) to \(g^{pow}\). \(f\) and \(g\) must be initialized with same
-- \(p\), \(exp\) and \(n\).
foreign import ccall "aprcl.h unity_zp_pow_fmpz"
unity_zp_pow_fmpz :: Ptr CUnityZp -> Ptr CUnityZp -> Ptr CFmpz -> IO ()
-- | /unity_zp_pow_ui/ /f/ /g/ /pow/
--
-- Sets \(f\) to \(g^{pow}\). \(f\) and \(g\) must be initialized with same
-- \(p\), \(exp\) and \(n\).
foreign import ccall "aprcl.h unity_zp_pow_ui"
unity_zp_pow_ui :: Ptr CUnityZp -> Ptr CUnityZp -> CULong -> IO ()
-- | /_unity_zp_pow_select_k/ /n/
--
-- Returns the smallest integer \(k\) satisfying
-- \(\log (n) < (k(k + 1)2^{2k}) / (2^{k + 1} - k - 2) + 1\)
foreign import ccall "aprcl.h _unity_zp_pow_select_k"
_unity_zp_pow_select_k :: Ptr CFmpz -> IO CULong
-- | /unity_zp_pow_2k_fmpz/ /f/ /g/ /pow/
--
-- Sets \(f\) to \(g^{pow}\) using the \(2^k\)-ary exponentiation method.
-- \(f\) and \(g\) must be initialized with same \(p\), \(exp\) and \(n\).
foreign import ccall "aprcl.h unity_zp_pow_2k_fmpz"
unity_zp_pow_2k_fmpz :: Ptr CUnityZp -> Ptr CUnityZp -> Ptr CFmpz -> IO ()
-- | /unity_zp_pow_2k_ui/ /f/ /g/ /pow/
--
-- Sets \(f\) to \(g^{pow}\) using the \(2^k\)-ary exponentiation method.
-- \(f\) and \(g\) must be initialized with same \(p\), \(exp\) and \(n\).
foreign import ccall "aprcl.h unity_zp_pow_2k_ui"
unity_zp_pow_2k_ui :: Ptr CUnityZp -> Ptr CUnityZp -> CULong -> IO ()
-- | /unity_zp_pow_sliding_fmpz/ /f/ /g/ /pow/
--
-- Sets \(f\) to \(g^{pow}\) using the sliding window exponentiation
-- method. \(f\) and \(g\) must be initialized with same \(p\), \(exp\) and
-- \(n\).
foreign import ccall "aprcl.h unity_zp_pow_sliding_fmpz"
unity_zp_pow_sliding_fmpz :: Ptr CUnityZp -> Ptr CUnityZp -> Ptr CFmpz -> IO ()
-- Cyclotomic reduction --------------------------------------------------------
-- | /_unity_zp_reduce_cyclotomic_divmod/ /f/
foreign import ccall "aprcl.h _unity_zp_reduce_cyclotomic_divmod"
_unity_zp_reduce_cyclotomic_divmod :: Ptr CUnityZp -> IO ()
-- | /_unity_zp_reduce_cyclotomic/ /f/
--
-- Sets \(f = f \bmod \Phi_{p^{exp}}\). \(\Phi_{p^{exp}}\) is the
-- \(p^{exp}\)-th cyclotomic polynomial. \(g\) must be reduced by
-- \(x^{p^{exp}}-1\) poly. \(f\) and \(g\) must be initialized with same
-- \(p\), \(exp\) and \(n\).
foreign import ccall "aprcl.h _unity_zp_reduce_cyclotomic"
_unity_zp_reduce_cyclotomic :: Ptr CUnityZp -> IO ()
-- | /unity_zp_reduce_cyclotomic/ /f/ /g/
--
-- Sets \(f = g \bmod \Phi_{p^{exp}}\). \(\Phi_{p^{exp}}\) is the
-- \(p^{exp}\)-th cyclotomic polynomial.
foreign import ccall "aprcl.h unity_zp_reduce_cyclotomic"
unity_zp_reduce_cyclotomic :: Ptr CUnityZp -> Ptr CUnityZp -> IO ()
-- Automorphism and inverse ----------------------------------------------------
-- | /unity_zp_aut/ /f/ /g/ /x/
--
-- Sets \(f = \sigma_x(g)\), the automorphism \(\sigma_x(\zeta)=\zeta^x\).
-- \(f\) and \(g\) must be initialized with the same \(p\), \(exp\) and
-- \(n\).
foreign import ccall "aprcl.h unity_zp_aut"
unity_zp_aut :: Ptr CUnityZp -> Ptr CUnityZp -> CULong -> IO ()
-- | /unity_zp_aut_inv/ /f/ /g/ /x/
--
-- Sets \(f = \sigma_x^{-1}(g)\), so \(\sigma_x(f) = g\). \(g\) must be
-- reduced by \(\Phi_{p^{exp}}\). \(f\) and \(g\) must be initialized with
-- the same \(p\), \(exp\) and \(n\).
foreign import ccall "aprcl.h unity_zp_aut_inv"
unity_zp_aut_inv :: Ptr CUnityZp -> Ptr CUnityZp -> CULong -> IO ()
-- Jacobi sum ------------------------------------------------------------------
-- Here \(\chi_{p, q}\) is the character defined by chi_{p, q}(g^x) =
-- zeta_{p^k}^x, where \(g\) is a primitive root modulo \(q\).
--
-- | /unity_zp_jacobi_sum_pq/ /f/ /q/ /p/
--
-- Sets \(f\) to the Jacobi sum \(J(p, q) = j(\chi_{p, q}, \chi_{p, q})\).
foreign import ccall "aprcl.h unity_zp_jacobi_sum_pq"
unity_zp_jacobi_sum_pq :: Ptr CUnityZp -> CULong -> CULong -> IO ()
-- | /unity_zp_jacobi_sum_2q_one/ /f/ /q/
--
-- Sets \(f\) to the Jacobi sum
-- \(J_2(q) = j(\chi_{2, q}^{2^{k - 3}}, \chi_{2, q}^{3 \cdot 2^{k - 3}}))^2\).
foreign import ccall "aprcl.h unity_zp_jacobi_sum_2q_one"
unity_zp_jacobi_sum_2q_one :: Ptr CUnityZp -> CULong -> IO ()
-- | /unity_zp_jacobi_sum_2q_two/ /f/ /q/
--
-- Sets \(f\) to the Jacobi sum
-- \(J_3(1) = j(\chi_{2, q}, \chi_{2, q}, \chi_{2, q}) =
-- J(2, q) \cdot j(\chi_{2, q}^2, \chi_{2, q})\).
foreign import ccall "aprcl.h unity_zp_jacobi_sum_2q_two"
unity_zp_jacobi_sum_2q_two :: Ptr CUnityZp -> CULong -> IO ()
-- Extended rings --------------------------------------------------------------
-- | /unity_zpq_init/ /f/ /q/ /p/ /n/
--
-- Initializes \(f\) as an element of \(\mathbb{Z}[\zeta_q, \zeta_p]/(n)\).
foreign import ccall "aprcl.h unity_zpq_init"
unity_zpq_init :: Ptr CUnityZpq -> CULong -> CULong -> Ptr CFmpz -> IO ()
-- | /unity_zpq_clear/ /f/
--
-- Clears the given element. It must be reinitialized in order to be used
-- again.
foreign import ccall "aprcl.h unity_zpq_clear"
unity_zpq_clear :: Ptr CUnityZpq -> IO ()
foreign import ccall "aprcl.h &unity_zpq_clear"
p_unity_zpq_clear :: FunPtr (Ptr CUnityZpq -> IO ())
-- | /unity_zpq_copy/ /f/ /g/
--
-- Sets \(f\) to \(g\). \(f\) and \(g\) must be initialized with same
-- \(p\), \(q\) and \(n\).
foreign import ccall "aprcl.h unity_zpq_copy"
unity_zpq_copy :: Ptr CUnityZpq ->Ptr CUnityZpq -> IO ()
-- | /unity_zpq_swap/ /f/ /q/
--
-- Swaps \(f\) and \(g\). \(f\) and \(g\) must be initialized with same
-- \(p\), \(q\) and \(n\).
foreign import ccall "aprcl.h unity_zpq_swap"
unity_zpq_swap :: Ptr CUnityZpq ->Ptr CUnityZpq -> IO ()
-- | /unity_zpq_equal/ /f/ /g/
--
-- Returns nonzero if \(f = g\).
foreign import ccall "aprcl.h unity_zpq_equal"
unity_zpq_equal :: Ptr CUnityZpq ->Ptr CUnityZpq -> IO CInt
-- | /unity_zpq_p_unity/ /f/
--
-- If \(f = \zeta_p^x\) returns \(x \in [0, p - 1]\); otherwise returns
-- \(p\).
foreign import ccall "aprcl.h unity_zpq_p_unity"
unity_zpq_p_unity :: Ptr CUnityZpq -> IO CULong
-- | /unity_zpq_is_p_unity/ /f/
--
-- Returns nonzero if \(f = \zeta_p^x\).
foreign import ccall "aprcl.h unity_zpq_is_p_unity"
unity_zpq_is_p_unity :: Ptr CUnityZpq -> IO CInt
-- | /unity_zpq_is_p_unity_generator/ /f/
--
-- Returns nonzero if \(f\) is a generator of the cyclic group
-- \(\langle\zeta_p\rangle\).
foreign import ccall "aprcl.h unity_zpq_is_p_unity_generator"
unity_zpq_is_p_unity_generator :: Ptr CUnityZpq -> IO CInt
-- | /unity_zpq_coeff_set_fmpz/ /f/ /i/ /j/ /x/
--
-- Sets the coefficient of \(\zeta_q^i \zeta_p^j\) to \(x\). \(i\) must be
-- less than \(q\) and \(j\) must be less than \(p\).
foreign import ccall "aprcl.h unity_zpq_coeff_set_fmpz"
unity_zpq_coeff_set_fmpz :: Ptr CUnityZpq -> CULong -> CULong -> Ptr CFmpz -> IO ()
-- | /unity_zpq_coeff_set_ui/ /f/ /i/ /j/ /x/
--
-- Sets the coefficient of \(\zeta_q^i \zeta_p^j\) to \(x\). \(i\) must be
-- less than \(q\) and \(j\) must be less then \(p\).
foreign import ccall "aprcl.h unity_zpq_coeff_set_ui"
unity_zpq_coeff_set_ui :: Ptr CUnityZpq -> CULong -> CULong -> CULong -> IO ()
-- | /unity_zpq_coeff_add/ /f/ /i/ /j/ /x/
--
-- Adds \(x\) to the coefficient of \(\zeta_p^i \zeta_q^j\). \(x\) must be
-- less than \(n\).
foreign import ccall "aprcl.h unity_zpq_coeff_add"
unity_zpq_coeff_add :: Ptr CUnityZpq -> CULong -> CULong -> Ptr CFmpz -> IO ()
-- | /unity_zpq_add/ /f/ /g/ /h/
--
-- Sets \(f\) to \(g + h\). \(f\), \(g\) and \(h\) must be initialized with
-- same \(q\), \(p\) and \(n\).
foreign import ccall "aprcl.h unity_zpq_add"
unity_zpq_add :: Ptr CUnityZpq ->Ptr CUnityZpq ->Ptr CUnityZpq -> IO ()
-- | /unity_zpq_mul/ /f/ /g/ /h/
--
-- Sets the \(f\) to \(g \cdot h\). \(f\), \(g\) and \(h\) must be
-- initialized with same \(q\), \(p\) and \(n\).
foreign import ccall "aprcl.h unity_zpq_mul"
unity_zpq_mul :: Ptr CUnityZpq ->Ptr CUnityZpq ->Ptr CUnityZpq -> IO ()
-- | /_unity_zpq_mul_unity_p/ /f/
--
-- Sets \(f = f \cdot \zeta_p\).
foreign import ccall "aprcl.h _unity_zpq_mul_unity_p"
_unity_zpq_mul_unity_p :: Ptr CUnityZpq -> IO ()
-- | /unity_zpq_mul_unity_p_pow/ /f/ /g/ /k/
--
-- Sets \(f\) to \(g \cdot \zeta_p^k\).
foreign import ccall "aprcl.h unity_zpq_mul_unity_p_pow"
unity_zpq_mul_unity_p_pow :: Ptr CUnityZpq ->Ptr CUnityZpq -> CULong -> IO ()
-- | /unity_zpq_pow/ /f/ /g/ /p/
--
-- Sets \(f\) to \(g^p\). \(f\) and \(g\) must be initialized with same
-- \(p\), \(q\) and \(n\).
foreign import ccall "aprcl.h unity_zpq_pow"
unity_zpq_pow :: Ptr CUnityZpq ->Ptr CUnityZpq -> Ptr CFmpz -> IO ()
-- | /unity_zpq_pow_ui/ /f/ /g/ /p/
--
-- Sets \(f\) to \(g^p\). \(f\) and \(g\) must be initialized with same
-- \(p\), \(q\) and \(n\).
foreign import ccall "aprcl.h unity_zpq_pow_ui"
unity_zpq_pow_ui :: Ptr CUnityZpq ->Ptr CUnityZpq -> CULong -> IO ()
-- | /unity_zpq_gauss_sum/ /f/ /q/ /p/
--
-- Sets \(f = \tau(\chi_{p, q})\).
foreign import ccall "aprcl.h unity_zpq_gauss_sum"
unity_zpq_gauss_sum :: Ptr CUnityZpq -> CULong -> CULong -> IO ()
-- | /unity_zpq_gauss_sum_sigma_pow/ /f/ /q/ /p/
--
-- Sets \(f = \tau^{\sigma_n}(\chi_{p, q})\).
foreign import ccall "aprcl.h unity_zpq_gauss_sum_sigma_pow"
unity_zpq_gauss_sum_sigma_pow :: Ptr CUnityZpq -> CULong -> CULong -> IO ()