{-# LINE 1 "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





-- 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 :: CAPRCLConfig -> Int
sizeOf    CAPRCLConfig
_ = (Int
248)
{-# LINE 142 "src/Data/Number/Flint/APRCL/FFI.hsc" #-}
  {-# INLINE alignment #-}
  alignment :: CAPRCLConfig -> Int
alignment CAPRCLConfig
_ = Int
8
{-# LINE 144 "src/Data/Number/Flint/APRCL/FFI.hsc" #-}
  peek = error "CAPRCLConfig.peek: not implemented."
  poke :: Ptr CAPRCLConfig -> CAPRCLConfig -> IO ()
poke = [Char] -> Ptr CAPRCLConfig -> CAPRCLConfig -> IO ()
forall a. HasCallStack => [Char] -> a
error [Char]
"CAPRCLConfig.poke: not implemented."

newAPRCLConfigGauss :: Fmpz -> IO APRCLConfig
newAPRCLConfigGauss Fmpz
n = do
  ForeignPtr CAPRCLConfig
x <- IO (ForeignPtr CAPRCLConfig)
forall a. Storable a => IO (ForeignPtr a)
mallocForeignPtr
  ForeignPtr CAPRCLConfig
-> (Ptr CAPRCLConfig -> IO (Fmpz, ())) -> IO (Fmpz, ())
forall a b. ForeignPtr a -> (Ptr a -> IO b) -> IO b
withForeignPtr ForeignPtr CAPRCLConfig
x ((Ptr CAPRCLConfig -> IO (Fmpz, ())) -> IO (Fmpz, ()))
-> (Ptr CAPRCLConfig -> IO (Fmpz, ())) -> IO (Fmpz, ())
forall a b. (a -> b) -> a -> b
$ \Ptr CAPRCLConfig
x ->
    Fmpz -> (Ptr CFmpz -> IO ()) -> IO (Fmpz, ())
forall {a}. Fmpz -> (Ptr CFmpz -> IO a) -> IO (Fmpz, a)
withFmpz Fmpz
n ((Ptr CFmpz -> IO ()) -> IO (Fmpz, ()))
-> (Ptr CFmpz -> IO ()) -> IO (Fmpz, ())
forall a b. (a -> b) -> a -> b
$ \Ptr CFmpz
n ->
      Ptr CAPRCLConfig -> Ptr CFmpz -> IO ()
aprcl_config_gauss_init Ptr CAPRCLConfig
x Ptr CFmpz
n
  FinalizerPtr CAPRCLConfig -> ForeignPtr CAPRCLConfig -> IO ()
forall a. FinalizerPtr a -> ForeignPtr a -> IO ()
addForeignPtrFinalizer FinalizerPtr CAPRCLConfig
p_aprcl_config_gauss_clear ForeignPtr CAPRCLConfig
x
  APRCLConfig -> IO APRCLConfig
forall a. a -> IO a
forall (m :: * -> *) a. Monad m => a -> m a
return (APRCLConfig -> IO APRCLConfig) -> APRCLConfig -> IO APRCLConfig
forall a b. (a -> b) -> a -> b
$ ForeignPtr CAPRCLConfig -> APRCLConfig
Gauss ForeignPtr CAPRCLConfig
x

newAPRCLConfigJacobi :: Fmpz -> IO APRCLConfig
newAPRCLConfigJacobi Fmpz
n = do
  ForeignPtr CAPRCLConfig
x <- IO (ForeignPtr CAPRCLConfig)
forall a. Storable a => IO (ForeignPtr a)
mallocForeignPtr
  ForeignPtr CAPRCLConfig
-> (Ptr CAPRCLConfig -> IO (Fmpz, ())) -> IO (Fmpz, ())
forall a b. ForeignPtr a -> (Ptr a -> IO b) -> IO b
withForeignPtr ForeignPtr CAPRCLConfig
x ((Ptr CAPRCLConfig -> IO (Fmpz, ())) -> IO (Fmpz, ()))
-> (Ptr CAPRCLConfig -> IO (Fmpz, ())) -> IO (Fmpz, ())
forall a b. (a -> b) -> a -> b
$ \Ptr CAPRCLConfig
x ->
    Fmpz -> (Ptr CFmpz -> IO ()) -> IO (Fmpz, ())
forall {a}. Fmpz -> (Ptr CFmpz -> IO a) -> IO (Fmpz, a)
withFmpz Fmpz
n ((Ptr CFmpz -> IO ()) -> IO (Fmpz, ()))
-> (Ptr CFmpz -> IO ()) -> IO (Fmpz, ())
forall a b. (a -> b) -> a -> b
$ \Ptr CFmpz
n ->
      Ptr CAPRCLConfig -> Ptr CFmpz -> IO ()
aprcl_config_jacobi_init Ptr CAPRCLConfig
x Ptr CFmpz
n
  FinalizerPtr CAPRCLConfig -> ForeignPtr CAPRCLConfig -> IO ()
forall a. FinalizerPtr a -> ForeignPtr a -> IO ()
addForeignPtrFinalizer FinalizerPtr CAPRCLConfig
p_aprcl_config_jacobi_clear ForeignPtr CAPRCLConfig
x
  APRCLConfig -> IO APRCLConfig
forall a. a -> IO a
forall (m :: * -> *) a. Monad m => a -> m a
return (APRCLConfig -> IO APRCLConfig) -> APRCLConfig -> IO APRCLConfig
forall a b. (a -> b) -> a -> b
$ ForeignPtr CAPRCLConfig -> APRCLConfig
Jacobi ForeignPtr CAPRCLConfig
x

withAPRCLConfig :: APRCLConfig -> (Ptr CAPRCLConfig -> IO a) -> IO (APRCLConfig, a)
withAPRCLConfig (Gauss ForeignPtr CAPRCLConfig
x) Ptr CAPRCLConfig -> IO a
f = do
  ForeignPtr CAPRCLConfig
-> (Ptr CAPRCLConfig -> IO (APRCLConfig, a)) -> IO (APRCLConfig, a)
forall a b. ForeignPtr a -> (Ptr a -> IO b) -> IO b
withForeignPtr ForeignPtr CAPRCLConfig
x ((Ptr CAPRCLConfig -> IO (APRCLConfig, a)) -> IO (APRCLConfig, a))
-> (Ptr CAPRCLConfig -> IO (APRCLConfig, a)) -> IO (APRCLConfig, a)
forall a b. (a -> b) -> a -> b
$ \Ptr CAPRCLConfig
px -> Ptr CAPRCLConfig -> IO a
f Ptr CAPRCLConfig
px IO a -> (a -> IO (APRCLConfig, a)) -> IO (APRCLConfig, a)
forall a b. IO a -> (a -> IO b) -> IO b
forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
>>= (APRCLConfig, a) -> IO (APRCLConfig, a)
forall a. a -> IO a
forall (m :: * -> *) a. Monad m => a -> m a
return ((APRCLConfig, a) -> IO (APRCLConfig, a))
-> (a -> (APRCLConfig, a)) -> a -> IO (APRCLConfig, a)
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (ForeignPtr CAPRCLConfig -> APRCLConfig
Gauss ForeignPtr CAPRCLConfig
x,)

withAPRCLConfig (Jacobi ForeignPtr CAPRCLConfig
x) Ptr CAPRCLConfig -> IO a
f = do
  ForeignPtr CAPRCLConfig
-> (Ptr CAPRCLConfig -> IO (APRCLConfig, a)) -> IO (APRCLConfig, a)
forall a b. ForeignPtr a -> (Ptr a -> IO b) -> IO b
withForeignPtr ForeignPtr CAPRCLConfig
x ((Ptr CAPRCLConfig -> IO (APRCLConfig, a)) -> IO (APRCLConfig, a))
-> (Ptr CAPRCLConfig -> IO (APRCLConfig, a)) -> IO (APRCLConfig, a)
forall a b. (a -> b) -> a -> b
$ \Ptr CAPRCLConfig
px -> Ptr CAPRCLConfig -> IO a
f Ptr CAPRCLConfig
px IO a -> (a -> IO (APRCLConfig, a)) -> IO (APRCLConfig, a)
forall a b. IO a -> (a -> IO b) -> IO b
forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
>>= (APRCLConfig, a) -> IO (APRCLConfig, a)
forall a. a -> IO a
forall (m :: * -> *) a. Monad m => a -> m a
return ((APRCLConfig, a) -> IO (APRCLConfig, a))
-> (a -> (APRCLConfig, a)) -> a -> IO (APRCLConfig, a)
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (ForeignPtr CAPRCLConfig -> APRCLConfig
Jacobi ForeignPtr CAPRCLConfig
x,)

-- primality_test_status -------------------------------------------------------

newtype PrimalityTestStatus =
  PrimalityTestStatus { PrimalityTestStatus -> CInt
_PrimalityTestStatus :: CInt } deriving PrimalityTestStatus -> PrimalityTestStatus -> Bool
(PrimalityTestStatus -> PrimalityTestStatus -> Bool)
-> (PrimalityTestStatus -> PrimalityTestStatus -> Bool)
-> Eq PrimalityTestStatus
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
$c== :: PrimalityTestStatus -> PrimalityTestStatus -> Bool
== :: PrimalityTestStatus -> PrimalityTestStatus -> Bool
$c/= :: PrimalityTestStatus -> PrimalityTestStatus -> Bool
/= :: PrimalityTestStatus -> PrimalityTestStatus -> Bool
Eq

instance Show PrimalityTestStatus where
  show :: PrimalityTestStatus -> [Char]
show PrimalityTestStatus
status
    | PrimalityTestStatus
status PrimalityTestStatus -> PrimalityTestStatus -> Bool
forall a. Eq a => a -> a -> Bool
== PrimalityTestStatus
unknown    = [Char]
"UNKNOWN"
    | PrimalityTestStatus
status PrimalityTestStatus -> PrimalityTestStatus -> Bool
forall a. Eq a => a -> a -> Bool
== PrimalityTestStatus
prime      = [Char]
"PRIME"
    | PrimalityTestStatus
status PrimalityTestStatus -> PrimalityTestStatus -> Bool
forall a. Eq a => a -> a -> Bool
== PrimalityTestStatus
composite  = [Char]
"COMPOSITE"
    | PrimalityTestStatus
status PrimalityTestStatus -> PrimalityTestStatus -> Bool
forall a. Eq a => a -> a -> Bool
== PrimalityTestStatus
probaprime = [Char]
"PROBABPRIME"
    | Bool
otherwise = [Char]
"unknown PrimalityTestStatus."

unknown :: PrimalityTestStatus
unknown    = CInt -> PrimalityTestStatus
PrimalityTestStatus CInt
0
{-# LINE 183 "src/Data/Number/Flint/APRCL/FFI.hsc" #-}
prime      = PrimalityTestStatus 1
{-# LINE 184 "src/Data/Number/Flint/APRCL/FFI.hsc" #-}
composite  = PrimalityTestStatus 2
{-# LINE 185 "src/Data/Number/Flint/APRCL/FFI.hsc" #-}
probaprime = PrimalityTestStatus 3
{-# LINE 186 "src/Data/Number/Flint/APRCL/FFI.hsc" #-}

-- 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 :: CUnityZpq -> Int
sizeOf CUnityZpq
_ = (Int
136)
{-# LINE 314 "src/Data/Number/Flint/APRCL/FFI.hsc" #-}
  {-# INLINE alignment #-}
  alignment :: CUnityZpq -> Int
alignment CUnityZpq
_ = Int
8
{-# LINE 316 "src/Data/Number/Flint/APRCL/FFI.hsc" #-}
  peek = error "CUnityZpq.peek: not implemented."
  poke :: Ptr CUnityZpq -> CUnityZpq -> IO ()
poke = [Char] -> Ptr CUnityZpq -> CUnityZpq -> IO ()
forall a. HasCallStack => [Char] -> a
error [Char]
"CUnityZpq.poke: not implemented."

newUnityZpq :: CULong -> CULong -> Fmpz -> IO UnityZpq
newUnityZpq CULong
q CULong
p Fmpz
n = do
  ForeignPtr CUnityZpq
x <- IO (ForeignPtr CUnityZpq)
forall a. Storable a => IO (ForeignPtr a)
mallocForeignPtr
  ForeignPtr CUnityZpq
-> (Ptr CUnityZpq -> IO (Fmpz, ())) -> IO (Fmpz, ())
forall a b. ForeignPtr a -> (Ptr a -> IO b) -> IO b
withForeignPtr ForeignPtr CUnityZpq
x ((Ptr CUnityZpq -> IO (Fmpz, ())) -> IO (Fmpz, ()))
-> (Ptr CUnityZpq -> IO (Fmpz, ())) -> IO (Fmpz, ())
forall a b. (a -> b) -> a -> b
$ \Ptr CUnityZpq
x -> 
    Fmpz -> (Ptr CFmpz -> IO ()) -> IO (Fmpz, ())
forall {a}. Fmpz -> (Ptr CFmpz -> IO a) -> IO (Fmpz, a)
withFmpz Fmpz
n ((Ptr CFmpz -> IO ()) -> IO (Fmpz, ()))
-> (Ptr CFmpz -> IO ()) -> IO (Fmpz, ())
forall a b. (a -> b) -> a -> b
$ \Ptr CFmpz
n -> 
      Ptr CUnityZpq -> CULong -> CULong -> Ptr CFmpz -> IO ()
unity_zpq_init Ptr CUnityZpq
x CULong
q CULong
p Ptr CFmpz
n
  FinalizerPtr CUnityZpq -> ForeignPtr CUnityZpq -> IO ()
forall a. FinalizerPtr a -> ForeignPtr a -> IO ()
addForeignPtrFinalizer FinalizerPtr CUnityZpq
p_unity_zpq_clear ForeignPtr CUnityZpq
x
  UnityZpq -> IO UnityZpq
forall a. a -> IO a
forall (m :: * -> *) a. Monad m => a -> m a
return (UnityZpq -> IO UnityZpq) -> UnityZpq -> IO UnityZpq
forall a b. (a -> b) -> a -> b
$ ForeignPtr CUnityZpq -> UnityZpq
UnityZpq ForeignPtr CUnityZpq
x

{-# INLINE withUnityZpq #-}
withUnityZpq :: UnityZpq -> (Ptr CUnityZpq -> IO a) -> IO (UnityZpq, a)
withUnityZpq (UnityZpq ForeignPtr CUnityZpq
x) Ptr CUnityZpq -> IO a
f = do
  ForeignPtr CUnityZpq
-> (Ptr CUnityZpq -> IO (UnityZpq, a)) -> IO (UnityZpq, a)
forall a b. ForeignPtr a -> (Ptr a -> IO b) -> IO b
withForeignPtr ForeignPtr CUnityZpq
x ((Ptr CUnityZpq -> IO (UnityZpq, a)) -> IO (UnityZpq, a))
-> (Ptr CUnityZpq -> IO (UnityZpq, a)) -> IO (UnityZpq, a)
forall a b. (a -> b) -> a -> b
$ \Ptr CUnityZpq
px -> Ptr CUnityZpq -> IO a
f Ptr CUnityZpq
px IO a -> (a -> IO (UnityZpq, a)) -> IO (UnityZpq, a)
forall a b. IO a -> (a -> IO b) -> IO b
forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
>>= (UnityZpq, a) -> IO (UnityZpq, a)
forall a. a -> IO a
forall (m :: * -> *) a. Monad m => a -> m a
return ((UnityZpq, a) -> IO (UnityZpq, a))
-> (a -> (UnityZpq, a)) -> a -> IO (UnityZpq, a)
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (ForeignPtr CUnityZpq -> UnityZpq
UnityZpq ForeignPtr CUnityZpq
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 :: CUnityZp -> Int
sizeOf CUnityZp
_ = (Int
152)
{-# LINE 339 "src/Data/Number/Flint/APRCL/FFI.hsc" #-}
  {-# INLINE alignment #-}
  alignment :: CUnityZp -> Int
alignment CUnityZp
_ = Int
8
{-# LINE 341 "src/Data/Number/Flint/APRCL/FFI.hsc" #-}
  peek ptr = CUnityZp
    <$> (\hsc_ptr -> peekByteOff hsc_ptr 0) ptr
{-# LINE 343 "src/Data/Number/Flint/APRCL/FFI.hsc" #-}
    <*> (\hsc_ptr -> peekByteOff hsc_ptr 24) ptr
{-# LINE 344 "src/Data/Number/Flint/APRCL/FFI.hsc" #-}
    <*> (\hsc_ptr -> peekByteOff hsc_ptr 32) ptr
{-# LINE 345 "src/Data/Number/Flint/APRCL/FFI.hsc" #-}
    <*> (\hsc_ptr -> peekByteOff hsc_ptr 40) ptr
{-# LINE 346 "src/Data/Number/Flint/APRCL/FFI.hsc" #-}
  poke = error "CUnityZp.poke: not implemented."

newUnityZp :: CULong -> CULong -> Fmpz -> IO UnityZp
newUnityZp CULong
p CULong
exp Fmpz
n = do
  ForeignPtr CUnityZp
x <- IO (ForeignPtr CUnityZp)
forall a. Storable a => IO (ForeignPtr a)
mallocForeignPtr
  ForeignPtr CUnityZp
-> (Ptr CUnityZp -> IO (Fmpz, ())) -> IO (Fmpz, ())
forall a b. ForeignPtr a -> (Ptr a -> IO b) -> IO b
withForeignPtr ForeignPtr CUnityZp
x ((Ptr CUnityZp -> IO (Fmpz, ())) -> IO (Fmpz, ()))
-> (Ptr CUnityZp -> IO (Fmpz, ())) -> IO (Fmpz, ())
forall a b. (a -> b) -> a -> b
$ \Ptr CUnityZp
x ->
    Fmpz -> (Ptr CFmpz -> IO ()) -> IO (Fmpz, ())
forall {a}. Fmpz -> (Ptr CFmpz -> IO a) -> IO (Fmpz, a)
withFmpz Fmpz
n ((Ptr CFmpz -> IO ()) -> IO (Fmpz, ()))
-> (Ptr CFmpz -> IO ()) -> IO (Fmpz, ())
forall a b. (a -> b) -> a -> b
$ \Ptr CFmpz
n -> 
    Ptr CUnityZp -> CULong -> CULong -> Ptr CFmpz -> IO ()
unity_zp_init Ptr CUnityZp
x CULong
p CULong
exp Ptr CFmpz
n
  FinalizerPtr CUnityZp -> ForeignPtr CUnityZp -> IO ()
forall a. FinalizerPtr a -> ForeignPtr a -> IO ()
addForeignPtrFinalizer FinalizerPtr CUnityZp
p_unity_zp_clear ForeignPtr CUnityZp
x
  UnityZp -> IO UnityZp
forall a. a -> IO a
forall (m :: * -> *) a. Monad m => a -> m a
return (UnityZp -> IO UnityZp) -> UnityZp -> IO UnityZp
forall a b. (a -> b) -> a -> b
$ ForeignPtr CUnityZp -> UnityZp
UnityZp ForeignPtr CUnityZp
x

{-# INLINE withUnityZp #-}
withUnityZp :: UnityZp -> (Ptr CUnityZp -> IO a) -> IO (UnityZp, a)
withUnityZp (UnityZp ForeignPtr CUnityZp
x) Ptr CUnityZp -> IO a
f = do
  ForeignPtr CUnityZp
-> (Ptr CUnityZp -> IO (UnityZp, a)) -> IO (UnityZp, a)
forall a b. ForeignPtr a -> (Ptr a -> IO b) -> IO b
withForeignPtr ForeignPtr CUnityZp
x ((Ptr CUnityZp -> IO (UnityZp, a)) -> IO (UnityZp, a))
-> (Ptr CUnityZp -> IO (UnityZp, a)) -> IO (UnityZp, a)
forall a b. (a -> b) -> a -> b
$ \Ptr CUnityZp
px -> Ptr CUnityZp -> IO a
f Ptr CUnityZp
px IO a -> (a -> IO (UnityZp, a)) -> IO (UnityZp, a)
forall a b. IO a -> (a -> IO b) -> IO b
forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
>>= (UnityZp, a) -> IO (UnityZp, a)
forall a. a -> IO a
forall (m :: * -> *) a. Monad m => a -> m a
return ((UnityZp, a) -> IO (UnityZp, a))
-> (a -> (UnityZp, a)) -> a -> IO (UnityZp, a)
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (ForeignPtr CUnityZp -> UnityZp
UnityZp ForeignPtr CUnityZp
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 :: Ptr CUnityZp -> IO ()
unity_zp_print Ptr CUnityZp
z = do
  (Ptr CUnityZp -> IO CString) -> Ptr CUnityZp -> IO CInt
forall a. (Ptr a -> IO CString) -> Ptr a -> IO CInt
printCStr Ptr CUnityZp -> IO CString
unity_zp_get_str Ptr CUnityZp
z
  () -> IO ()
forall a. a -> IO a
forall (m :: * -> *) a. Monad m => a -> m a
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 ()