{-# LINE 1 "src/Data/Number/Flint/Fq/FFI.hsc" #-}
{-|
module      :  Data.Number.Flint.Fq.FFI
copyright   :  (c) 2022 Hartmut Monien
license     :  GNU GPL, version 2 or above (see LICENSE)
maintainer  :  hmonien@uni-bonn.de
-}
module Data.Number.Flint.Fq.FFI (
  -- * Finite fields
  -- ** Finite field element
  --
  -- | The type `Fq` represents an element of the finite field \(\mathbb F_q\).
    Fq (..)
  , CFq (..)
  , newFq
  , withFq
  , withNewFq
  -- * Finite field context
  , FqCtx (..)
  , CFqCtx (..)
  , newFqCtx
  , withFqCtx
  , withNewFqCtx
  , newFqCtxConway
  , withNewFqCtxConway
  , newFqCtxModulus
  , withNewFqCtxModulus
  -- * Context Management
  , fq_ctx_init
  , _fq_ctx_init_conway
  , fq_ctx_init_conway
  , fq_ctx_init_modulus
  , fq_ctx_clear
  , fq_ctx_modulus
  , fq_ctx_degree
  , fq_ctx_prime
  , fq_ctx_order
  , fq_ctx_get_str
  , fq_ctx_fprint
  , fq_ctx_print
  , fq_ctx_randtest
  , fq_ctx_randtest_reducible
  -- * Memory management
  , fq_init
  , fq_init2
  , fq_clear
  , _fq_sparse_reduce
  , _fq_dense_reduce
  , _fq_reduce
  , fq_reduce
  -- * Basic arithmetic
  , fq_add
  , fq_sub
  , fq_sub_one
  , fq_neg
  , fq_mul
  , fq_mul_fmpz
  , fq_mul_si
  , fq_mul_ui
  , fq_sqr
  , fq_div
  , _fq_inv
  , fq_inv
  , fq_gcdinv
  , _fq_pow
  , fq_pow
  , fq_pow_ui
  -- * Roots
  , fq_sqrt
  , fq_pth_root
  , fq_is_square
  -- * Output
  , fq_fprint_pretty
  , fq_print_pretty
  , fq_fprint
  , fq_print
  , fq_get_str
  , fq_get_str_pretty
  -- * Randomisation
  , fq_randtest
  , fq_randtest_not_zero
  , fq_randtest_dense
  , fq_rand
  , fq_rand_not_zero
  -- * Assignments and conversions
  , fq_set
  , fq_set_si
  , fq_set_ui
  , fq_set_fmpz
  , fq_swap
  , fq_zero
  , fq_one
  , fq_gen
  , fq_get_fmpz
  , fq_get_fmpz_poly
  , fq_get_fmpz_mod_poly
  , fq_set_fmpz_poly
  , fq_set_fmpz_mod_poly
  , fq_get_fmpz_mod_mat
  , fq_set_fmpz_mod_mat
  -- * Comparison
  , fq_is_zero
  , fq_is_one
  , fq_equal
  , fq_is_invertible
  , fq_is_invertible_f
  -- * Special functions
  , _fq_trace
  , fq_trace
  , _fq_norm
  , fq_norm
  , _fq_frobenius
  , fq_frobenius
  , fq_multiplicative_order
  , fq_is_primitive
  -- * Bit packing
  , fq_bit_pack
  , fq_bit_unpack
) where 

-- finite fields ---------------------------------------------------------------

import Foreign.C.String
import Foreign.C.Types
import qualified Foreign.Concurrent
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.Poly
import Data.Number.Flint.Fmpz.Mod
import Data.Number.Flint.Fmpz.Mod.Poly
import Data.Number.Flint.Fmpz.Mod.Mat
import Data.Number.Flint.Fmpq
import Data.Number.Flint.Fq.Types




-- fq_t ------------------------------------------------------------------------

-- | Create a new `Fq` with context `ctx`.
newFq :: FqCtx -> IO Fq
newFq :: FqCtx -> IO Fq
newFq ctx :: FqCtx
ctx@(FqCtx ForeignPtr CFqCtx
pctx) = do
  ForeignPtr CFq
x <- IO (ForeignPtr CFq)
forall a. Storable a => IO (ForeignPtr a)
mallocForeignPtr
  ForeignPtr CFq -> (Ptr CFq -> IO (FqCtx, ())) -> IO (FqCtx, ())
forall a b. ForeignPtr a -> (Ptr a -> IO b) -> IO b
withForeignPtr ForeignPtr CFq
x ((Ptr CFq -> IO (FqCtx, ())) -> IO (FqCtx, ()))
-> (Ptr CFq -> IO (FqCtx, ())) -> IO (FqCtx, ())
forall a b. (a -> b) -> a -> b
$ \Ptr CFq
x -> do
    FqCtx -> (Ptr CFqCtx -> IO ()) -> IO (FqCtx, ())
forall {a}. FqCtx -> (Ptr CFqCtx -> IO a) -> IO (FqCtx, a)
withFqCtx FqCtx
ctx ((Ptr CFqCtx -> IO ()) -> IO (FqCtx, ()))
-> (Ptr CFqCtx -> IO ()) -> IO (FqCtx, ())
forall a b. (a -> b) -> a -> b
$ \Ptr CFqCtx
ctx -> do
      Ptr CFq -> Ptr CFqCtx -> IO ()
fq_init Ptr CFq
x Ptr CFqCtx
ctx
      FinalizerEnvPtr CFq CFqCtx -> Ptr CFq -> ForeignPtr CFqCtx -> IO ()
forall env a.
FinalizerEnvPtr env a -> Ptr env -> ForeignPtr a -> IO ()
addForeignPtrFinalizerEnv FinalizerEnvPtr CFq CFqCtx
p_fq_clear Ptr CFq
x ForeignPtr CFqCtx
pctx
  Fq -> IO Fq
forall a. a -> IO a
forall (m :: * -> *) a. Monad m => a -> m a
return (Fq -> IO Fq) -> Fq -> IO Fq
forall a b. (a -> b) -> a -> b
$ ForeignPtr CFq -> Fq
Fq ForeignPtr CFq
x

-- | Use `Fq`.
{-# INLINE withFq #-}
withFq :: Fq -> (Ptr CFq -> IO a) -> IO (Fq, a)
withFq (Fq ForeignPtr CFq
p) Ptr CFq -> IO a
f = do
  ForeignPtr CFq -> (Ptr CFq -> IO (Fq, a)) -> IO (Fq, a)
forall a b. ForeignPtr a -> (Ptr a -> IO b) -> IO b
withForeignPtr ForeignPtr CFq
p ((Ptr CFq -> IO (Fq, a)) -> IO (Fq, a))
-> (Ptr CFq -> IO (Fq, a)) -> IO (Fq, a)
forall a b. (a -> b) -> a -> b
$ \Ptr CFq
fp -> Ptr CFq -> IO a
f Ptr CFq
fp IO a -> (a -> IO (Fq, a)) -> IO (Fq, a)
forall a b. IO a -> (a -> IO b) -> IO b
forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
>>= (Fq, a) -> IO (Fq, a)
forall a. a -> IO a
forall (m :: * -> *) a. Monad m => a -> m a
return ((Fq, a) -> IO (Fq, a)) -> (a -> (Fq, a)) -> a -> IO (Fq, a)
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (ForeignPtr CFq -> Fq
Fq ForeignPtr CFq
p,)

-- | Use a new `Fq`.
{-# INLINE withNewFq #-}
withNewFq :: FqCtx -> (Ptr CFq -> IO a) -> IO (Fq, a)
withNewFq FqCtx
ctx Ptr CFq -> IO a
f = do
  Fq
x <- FqCtx -> IO Fq
newFq FqCtx
ctx
  Fq -> (Ptr CFq -> IO a) -> IO (Fq, a)
forall {a}. Fq -> (Ptr CFq -> IO a) -> IO (Fq, a)
withFq Fq
x Ptr CFq -> IO a
f

-- fq_ctx_t --------------------------------------------------------------------

-- | Context of the finite field (opaque pointer)
data FqCtx = FqCtx {-# UNPACK #-} !(ForeignPtr CFqCtx)
type CFqCtx = CFlint FqCtx

instance Storable CFqCtx where
  {-# INLINE sizeOf #-}
  sizeOf :: CFqCtx -> Int
sizeOf CFqCtx
_ = (Int
200)
{-# LINE 174 "src/Data/Number/Flint/Fq/FFI.hsc" #-}
  {-# INLINE alignment #-}
  alignment :: CFqCtx -> Int
alignment CFqCtx
_ = Int
8
{-# LINE 176 "src/Data/Number/Flint/Fq/FFI.hsc" #-}
  peek = undefined
  poke :: Ptr CFqCtx -> CFqCtx -> IO ()
poke = Ptr CFqCtx -> CFqCtx -> IO ()
forall a. HasCallStack => a
undefined

-- | Create a new `Fq` context using `fq_ctx_init`.
newFqCtx :: Fmpz -> CLong -> String -> IO FqCtx
newFqCtx Fmpz
p CLong
d String
var = do
  ForeignPtr CFqCtx
x <- IO (ForeignPtr CFqCtx)
forall a. Storable a => IO (ForeignPtr a)
mallocForeignPtr
  ForeignPtr CFqCtx -> (Ptr CFqCtx -> IO (Fmpz, ())) -> IO (Fmpz, ())
forall a b. ForeignPtr a -> (Ptr a -> IO b) -> IO b
withForeignPtr ForeignPtr CFqCtx
x ((Ptr CFqCtx -> IO (Fmpz, ())) -> IO (Fmpz, ()))
-> (Ptr CFqCtx -> IO (Fmpz, ())) -> IO (Fmpz, ())
forall a b. (a -> b) -> a -> b
$ \Ptr CFqCtx
x ->
    Fmpz -> (Ptr CFmpz -> IO ()) -> IO (Fmpz, ())
forall {a}. Fmpz -> (Ptr CFmpz -> IO a) -> IO (Fmpz, a)
withFmpz Fmpz
p ((Ptr CFmpz -> IO ()) -> IO (Fmpz, ()))
-> (Ptr CFmpz -> IO ()) -> IO (Fmpz, ())
forall a b. (a -> b) -> a -> b
$ \Ptr CFmpz
p ->
      String -> (CString -> IO ()) -> IO ()
forall a. String -> (CString -> IO a) -> IO a
withCString String
var ((CString -> IO ()) -> IO ()) -> (CString -> IO ()) -> IO ()
forall a b. (a -> b) -> a -> b
$ \CString
var ->
        Ptr CFqCtx -> Ptr CFmpz -> CLong -> CString -> IO ()
fq_ctx_init Ptr CFqCtx
x Ptr CFmpz
p CLong
d CString
var
  FinalizerPtr CFqCtx -> ForeignPtr CFqCtx -> IO ()
forall a. FinalizerPtr a -> ForeignPtr a -> IO ()
addForeignPtrFinalizer FinalizerPtr CFqCtx
p_fq_ctx_clear ForeignPtr CFqCtx
x
  FqCtx -> IO FqCtx
forall a. a -> IO a
forall (m :: * -> *) a. Monad m => a -> m a
return (FqCtx -> IO FqCtx) -> FqCtx -> IO FqCtx
forall a b. (a -> b) -> a -> b
$ ForeignPtr CFqCtx -> FqCtx
FqCtx ForeignPtr CFqCtx
x

-- | Use the `FqCtx`.
{-# INLINE withFqCtx #-}
withFqCtx :: FqCtx -> (Ptr CFqCtx -> IO a) -> IO (FqCtx, a)
withFqCtx (FqCtx ForeignPtr CFqCtx
p) Ptr CFqCtx -> IO a
f = do
  ForeignPtr CFqCtx -> (Ptr CFqCtx -> IO (FqCtx, a)) -> IO (FqCtx, a)
forall a b. ForeignPtr a -> (Ptr a -> IO b) -> IO b
withForeignPtr ForeignPtr CFqCtx
p ((Ptr CFqCtx -> IO (FqCtx, a)) -> IO (FqCtx, a))
-> (Ptr CFqCtx -> IO (FqCtx, a)) -> IO (FqCtx, a)
forall a b. (a -> b) -> a -> b
$ \Ptr CFqCtx
fp -> Ptr CFqCtx -> IO a
f Ptr CFqCtx
fp IO a -> (a -> IO (FqCtx, a)) -> IO (FqCtx, a)
forall a b. IO a -> (a -> IO b) -> IO b
forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
>>= (FqCtx, a) -> IO (FqCtx, a)
forall a. a -> IO a
forall (m :: * -> *) a. Monad m => a -> m a
return ((FqCtx, a) -> IO (FqCtx, a))
-> (a -> (FqCtx, a)) -> a -> IO (FqCtx, a)
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (ForeignPtr CFqCtx -> FqCtx
FqCtx ForeignPtr CFqCtx
p,)

-- | Apply function to new `FqCtx`.
-- parameters as in `newFqCtx`.
withNewFqCtx :: Fmpz -> CLong -> String -> (Ptr CFqCtx -> IO a) -> IO (FqCtx, a)
withNewFqCtx Fmpz
p CLong
d String
var Ptr CFqCtx -> IO a
f = do
  FqCtx
ctx <- Fmpz -> CLong -> String -> IO FqCtx
newFqCtx Fmpz
p CLong
d String
var
  FqCtx -> (Ptr CFqCtx -> IO a) -> IO (FqCtx, a)
forall {a}. FqCtx -> (Ptr CFqCtx -> IO a) -> IO (FqCtx, a)
withFqCtx FqCtx
ctx Ptr CFqCtx -> IO a
f
  
-- | Create a new `Fq` context using `fq_ctx_init_conway`.
newFqCtxConway :: Fmpz -> CLong -> String -> IO FqCtx
newFqCtxConway Fmpz
p CLong
d String
var = do
  ForeignPtr CFqCtx
x <- IO (ForeignPtr CFqCtx)
forall a. Storable a => IO (ForeignPtr a)
mallocForeignPtr
  ForeignPtr CFqCtx -> (Ptr CFqCtx -> IO (Fmpz, ())) -> IO (Fmpz, ())
forall a b. ForeignPtr a -> (Ptr a -> IO b) -> IO b
withForeignPtr ForeignPtr CFqCtx
x ((Ptr CFqCtx -> IO (Fmpz, ())) -> IO (Fmpz, ()))
-> (Ptr CFqCtx -> IO (Fmpz, ())) -> IO (Fmpz, ())
forall a b. (a -> b) -> a -> b
$ \Ptr CFqCtx
x ->
    Fmpz -> (Ptr CFmpz -> IO ()) -> IO (Fmpz, ())
forall {a}. Fmpz -> (Ptr CFmpz -> IO a) -> IO (Fmpz, a)
withFmpz Fmpz
p ((Ptr CFmpz -> IO ()) -> IO (Fmpz, ()))
-> (Ptr CFmpz -> IO ()) -> IO (Fmpz, ())
forall a b. (a -> b) -> a -> b
$ \Ptr CFmpz
p ->
      String -> (CString -> IO ()) -> IO ()
forall a. String -> (CString -> IO a) -> IO a
withCString String
var ((CString -> IO ()) -> IO ()) -> (CString -> IO ()) -> IO ()
forall a b. (a -> b) -> a -> b
$ \CString
var ->
        Ptr CFqCtx -> Ptr CFmpz -> CLong -> CString -> IO ()
fq_ctx_init_conway Ptr CFqCtx
x Ptr CFmpz
p CLong
d CString
var
  FinalizerPtr CFqCtx -> ForeignPtr CFqCtx -> IO ()
forall a. FinalizerPtr a -> ForeignPtr a -> IO ()
addForeignPtrFinalizer FinalizerPtr CFqCtx
p_fq_ctx_clear ForeignPtr CFqCtx
x
  FqCtx -> IO FqCtx
forall a. a -> IO a
forall (m :: * -> *) a. Monad m => a -> m a
return (FqCtx -> IO FqCtx) -> FqCtx -> IO FqCtx
forall a b. (a -> b) -> a -> b
$ ForeignPtr CFqCtx -> FqCtx
FqCtx ForeignPtr CFqCtx
x

-- | Apply function to new `Fq` initialized with `fq_ctx_init_conway`.
withNewFqCtxConway :: Fmpz -> CLong -> String -> (Ptr CFqCtx -> IO a) -> IO (FqCtx, a)
withNewFqCtxConway Fmpz
p CLong
d String
var Ptr CFqCtx -> IO a
f = do
  FqCtx
ctx <- Fmpz -> CLong -> String -> IO FqCtx
newFqCtxConway Fmpz
p CLong
d String
var
  FqCtx -> (Ptr CFqCtx -> IO a) -> IO (FqCtx, a)
forall {a}. FqCtx -> (Ptr CFqCtx -> IO a) -> IO (FqCtx, a)
withFqCtx FqCtx
ctx Ptr CFqCtx -> IO a
f
 
-- | Create a new `Fq` context using `fq_ctx_init_modulus`.
newFqCtxModulus :: FmpzModPoly -> FmpzModCtx -> String -> IO FqCtx
newFqCtxModulus FmpzModPoly
modulus FmpzModCtx
mod_ctx String
var = do
  ForeignPtr CFqCtx
x <- IO (ForeignPtr CFqCtx)
forall a. Storable a => IO (ForeignPtr a)
mallocForeignPtr
  ForeignPtr CFqCtx
-> (Ptr CFqCtx -> IO (FmpzModPoly, (FmpzModCtx, ())))
-> IO (FmpzModPoly, (FmpzModCtx, ()))
forall a b. ForeignPtr a -> (Ptr a -> IO b) -> IO b
withForeignPtr ForeignPtr CFqCtx
x ((Ptr CFqCtx -> IO (FmpzModPoly, (FmpzModCtx, ())))
 -> IO (FmpzModPoly, (FmpzModCtx, ())))
-> (Ptr CFqCtx -> IO (FmpzModPoly, (FmpzModCtx, ())))
-> IO (FmpzModPoly, (FmpzModCtx, ()))
forall a b. (a -> b) -> a -> b
$ \Ptr CFqCtx
x ->
    FmpzModPoly
-> (Ptr CFmpzModPoly -> IO (FmpzModCtx, ()))
-> IO (FmpzModPoly, (FmpzModCtx, ()))
forall {a}.
FmpzModPoly -> (Ptr CFmpzModPoly -> IO a) -> IO (FmpzModPoly, a)
withFmpzModPoly FmpzModPoly
modulus ((Ptr CFmpzModPoly -> IO (FmpzModCtx, ()))
 -> IO (FmpzModPoly, (FmpzModCtx, ())))
-> (Ptr CFmpzModPoly -> IO (FmpzModCtx, ()))
-> IO (FmpzModPoly, (FmpzModCtx, ()))
forall a b. (a -> b) -> a -> b
$ \Ptr CFmpzModPoly
modulus ->
      FmpzModCtx -> (Ptr CFmpzModCtx -> IO ()) -> IO (FmpzModCtx, ())
forall {a}.
FmpzModCtx -> (Ptr CFmpzModCtx -> IO a) -> IO (FmpzModCtx, a)
withFmpzModCtx FmpzModCtx
mod_ctx ((Ptr CFmpzModCtx -> IO ()) -> IO (FmpzModCtx, ()))
-> (Ptr CFmpzModCtx -> IO ()) -> IO (FmpzModCtx, ())
forall a b. (a -> b) -> a -> b
$ \Ptr CFmpzModCtx
mod_ctx ->  
        String -> (CString -> IO ()) -> IO ()
forall a. String -> (CString -> IO a) -> IO a
withCString String
var ((CString -> IO ()) -> IO ()) -> (CString -> IO ()) -> IO ()
forall a b. (a -> b) -> a -> b
$ \CString
var ->
          Ptr CFqCtx
-> Ptr CFmpzModPoly -> Ptr CFmpzModCtx -> CString -> IO ()
fq_ctx_init_modulus Ptr CFqCtx
x Ptr CFmpzModPoly
modulus Ptr CFmpzModCtx
mod_ctx CString
var
  FinalizerPtr CFqCtx -> ForeignPtr CFqCtx -> IO ()
forall a. FinalizerPtr a -> ForeignPtr a -> IO ()
addForeignPtrFinalizer FinalizerPtr CFqCtx
p_fq_ctx_clear ForeignPtr CFqCtx
x
  FqCtx -> IO FqCtx
forall a. a -> IO a
forall (m :: * -> *) a. Monad m => a -> m a
return (FqCtx -> IO FqCtx) -> FqCtx -> IO FqCtx
forall a b. (a -> b) -> a -> b
$ ForeignPtr CFqCtx -> FqCtx
FqCtx ForeignPtr CFqCtx
x

-- | Create a new `Fq` initialized using `fq_ctx_init_modulus`.
withNewFqCtxModulus :: FmpzModPoly
-> FmpzModCtx -> String -> (Ptr CFqCtx -> IO a) -> IO (FqCtx, a)
withNewFqCtxModulus FmpzModPoly
modulus FmpzModCtx
mod_ctx String
var Ptr CFqCtx -> IO a
f = do
  FqCtx
ctx <- FmpzModPoly -> FmpzModCtx -> String -> IO FqCtx
newFqCtxModulus FmpzModPoly
modulus FmpzModCtx
mod_ctx String
var
  FqCtx -> (Ptr CFqCtx -> IO a) -> IO (FqCtx, a)
forall {a}. FqCtx -> (Ptr CFqCtx -> IO a) -> IO (FqCtx, a)
withFqCtx FqCtx
ctx Ptr CFqCtx -> IO a
f
 
-- Context Management ----------------------------------------------------------

-- | /fq_ctx_init/ /ctx/ /p/ /d/ /var/ 
-- 
-- Initialises the context for prime \(p\) and extension degree \(d\), with
-- name @var@ for the generator. By default, it will try use a Conway
-- polynomial; if one is not available, a random irreducible polynomial
-- will be used.
-- 
-- Assumes that \(p\) is a prime.
-- 
-- Assumes that the string @var@ is a null-terminated string of length at
-- least one.
foreign import ccall "fq.h fq_ctx_init"
  fq_ctx_init :: Ptr CFqCtx -> Ptr CFmpz -> CLong -> CString -> IO ()

-- | /_fq_ctx_init_conway/ /ctx/ /p/ /d/ /var/ 
-- 
-- Attempts to initialise the context for prime \(p\) and extension degree
-- \(d\), with name @var@ for the generator using a Conway polynomial for
-- the modulus.
-- 
-- Returns \(1\) if the Conway polynomial is in the database for the given
-- size and the initialization is successful; otherwise, returns \(0\).
-- 
-- Assumes that \(p\) is a prime.
-- 
-- Assumes that the string @var@ is a null-terminated string of length at
-- least one.
foreign import ccall "fq.h _fq_ctx_init_conway"
  _fq_ctx_init_conway :: Ptr CFqCtx -> Ptr CFmpz -> CLong -> CString -> IO CInt

-- | /fq_ctx_init_conway/ /ctx/ /p/ /d/ /var/ 
-- 
-- Initialises the context for prime \(p\) and extension degree \(d\), with
-- name @var@ for the generator using a Conway polynomial for the modulus.
-- 
-- Assumes that \(p\) is a prime.
-- 
-- Assumes that the string @var@ is a null-terminated string of length at
-- least one.
foreign import ccall "fq.h fq_ctx_init_conway"
  fq_ctx_init_conway :: Ptr CFqCtx -> Ptr CFmpz -> CLong -> CString -> IO ()

-- | /fq_ctx_init_modulus/ /ctx/ /modulus/ /ctxp/ /var/ 
-- 
-- Initialises the context for given @modulus@ with name @var@ for the
-- generator.
-- 
-- Assumes that @modulus@ is an irreducible polynomial over the finite
-- field \(\mathbf{F}_{p}\) in @ctxp@.
-- 
-- Assumes that the string @var@ is a null-terminated string of length at
-- least one.
foreign import ccall "fq.h fq_ctx_init_modulus"
  fq_ctx_init_modulus :: Ptr CFqCtx -> Ptr CFmpzModPoly -> Ptr CFmpzModCtx -> CString -> IO ()

-- | /fq_ctx_clear/ /ctx/ 
-- 
-- Clears all memory that has been allocated as part of the context.
foreign import ccall "fq.h fq_ctx_clear"
  fq_ctx_clear :: Ptr CFqCtx -> IO ()

foreign import ccall "fq.h &fq_ctx_clear"
  p_fq_ctx_clear :: FunPtr (Ptr CFqCtx -> IO ())

-- | /fq_ctx_modulus/ /ctx/ 
-- 
-- Returns a pointer to the modulus in the context.
foreign import ccall "fq.h fq_ctx_modulus"
  fq_ctx_modulus :: Ptr CFqCtx -> IO (Ptr CFmpzModPoly)

-- | /fq_ctx_degree/ /ctx/ 
-- 
-- Returns the degree of the field extension
-- \([\mathbf{F}_{q} : \mathbf{F}_{p}]\), which is equal to \(\log_{p} q\).
foreign import ccall "fq.h fq_ctx_degree"
  fq_ctx_degree :: Ptr CFqCtx -> IO CLong

-- | /fq_ctx_prime/ /ctx/ 
-- 
-- Returns a pointer to the prime \(p\) in the context.
foreign import ccall "fq.h fq_ctx_prime"
  fq_ctx_prime :: Ptr CFqCtx -> IO (Ptr CFmpz)

-- | /fq_ctx_order/ /f/ /ctx/ 
-- 
-- Sets \(f\) to be the size of the finite field.
foreign import ccall "fq.h fq_ctx_order"
  fq_ctx_order :: Ptr CFmpz -> Ptr CFqCtx -> IO ()

foreign import ccall "fq.h fq_ctx_get_str"
  fq_ctx_get_str :: Ptr CFqCtx -> IO CString

-- | /fq_ctx_fprint/ /file/ /ctx/ 
-- 
-- Prints the context information to @file@. Returns 1 for a success and a
-- negative number for an error.
foreign import ccall "fq.h fq_ctx_fprint"
  fq_ctx_fprint :: Ptr CFile -> Ptr CFqCtx -> IO CInt

-- | /fq_ctx_print/ /ctx/ 
-- 
-- Prints the context information to @stdout@.
fq_ctx_print :: Ptr CFqCtx -> IO ()
fq_ctx_print :: Ptr CFqCtx -> IO ()
fq_ctx_print Ptr CFqCtx
ctx = do
  (Ptr CFqCtx -> IO CString) -> Ptr CFqCtx -> IO CInt
forall a. (Ptr a -> IO CString) -> Ptr a -> IO CInt
printCStr Ptr CFqCtx -> IO CString
fq_ctx_get_str Ptr CFqCtx
ctx
  () -> IO ()
forall a. a -> IO a
forall (m :: * -> *) a. Monad m => a -> m a
return ()
  
-- | /fq_ctx_randtest/ /ctx/ 
-- 
-- Initializes @ctx@ to a random finite field. Assumes that @fq_ctx_init@
-- has not been called on @ctx@ already.
foreign import ccall "fq.h fq_ctx_randtest"
  fq_ctx_randtest :: Ptr CFqCtx -> IO ()

-- | /fq_ctx_randtest_reducible/ /ctx/ 
-- 
-- Initializes @ctx@ to a random extension of a prime field. The modulus
-- may or may not be irreducible. Assumes that @fq_ctx_init@ has not been
-- called on @ctx@ already.
foreign import ccall "fq.h fq_ctx_randtest_reducible"
  fq_ctx_randtest_reducible :: Ptr CFqCtx -> IO ()

-- Memory management -----------------------------------------------------------

-- | /fq_init/ /rop/ /ctx/ 
-- 
-- Initialises the element @rop@, setting its value to \(0\).
foreign import ccall "fq.h fq_init"
  fq_init :: Ptr CFq -> Ptr CFqCtx -> IO ()

-- | /fq_init2/ /rop/ /ctx/ 
-- 
-- Initialises @poly@ with at least enough space for it to be an element of
-- @ctx@ and sets it to \(0\).
foreign import ccall "fq.h fq_init2"
  fq_init2 :: Ptr CFq -> Ptr CFqCtx -> IO ()

-- | /fq_clear/ /rop/ /ctx/ 
-- 
-- Clears the element @rop@.
foreign import ccall "fq.h fq_clear"
  fq_clear :: Ptr CFq -> Ptr CFqCtx -> IO ()

foreign import ccall "fq.h &fq_clear"
  p_fq_clear :: FunPtr (Ptr CFq -> Ptr CFqCtx -> IO ())

-- | /_fq_sparse_reduce/ /R/ /lenR/ /ctx/ 
-- 
-- Reduces @(R, lenR)@ modulo the polynomial \(f\) given by the modulus of
-- @ctx@.
foreign import ccall "fq.h _fq_sparse_reduce"
  _fq_sparse_reduce :: Ptr CFmpz -> CLong -> Ptr CFqCtx -> IO ()

-- | /_fq_dense_reduce/ /R/ /lenR/ /ctx/ 
-- 
-- Reduces @(R, lenR)@ modulo the polynomial \(f\) given by the modulus of
-- @ctx@ using Newton division.
foreign import ccall "fq.h _fq_dense_reduce"
  _fq_dense_reduce :: Ptr CFmpz -> CLong -> Ptr CFqCtx -> IO ()

-- | /_fq_reduce/ /r/ /lenR/ /ctx/ 
-- 
-- Reduces @(R, lenR)@ modulo the polynomial \(f\) given by the modulus of
-- @ctx@. Does either sparse or dense reduction based on
-- @ctx->sparse_modulus@.
foreign import ccall "fq.h _fq_reduce"
  _fq_reduce :: Ptr CFmpz -> CLong -> Ptr CFqCtx -> IO ()

-- | /fq_reduce/ /rop/ /ctx/ 
-- 
-- Reduces the polynomial @rop@ as an element of
-- \(\mathbf{F}_p[X] / (f(X))\).
foreign import ccall "fq.h fq_reduce"
  fq_reduce :: Ptr CFq -> Ptr CFqCtx -> IO ()

-- Basic arithmetic ------------------------------------------------------------

-- | /fq_add/ /rop/ /op1/ /op2/ /ctx/ 
-- 
-- Sets @rop@ to the sum of @op1@ and @op2@.
foreign import ccall "fq.h fq_add"
  fq_add :: Ptr CFq -> Ptr CFq -> Ptr CFq -> Ptr CFqCtx -> IO ()

-- | /fq_sub/ /rop/ /op1/ /op2/ /ctx/ 
-- 
-- Sets @rop@ to the difference of @op1@ and @op2@.
foreign import ccall "fq.h fq_sub"
  fq_sub :: Ptr CFq -> Ptr CFq -> Ptr CFq -> Ptr CFqCtx -> IO ()

-- | /fq_sub_one/ /rop/ /op1/ /ctx/ 
-- 
-- Sets @rop@ to the difference of @op1@ and \(1\).
foreign import ccall "fq.h fq_sub_one"
  fq_sub_one :: Ptr CFq -> Ptr CFq -> Ptr CFqCtx -> IO ()

-- | /fq_neg/ /rop/ /op/ /ctx/ 
-- 
-- Sets @rop@ to the negative of @op@.
foreign import ccall "fq.h fq_neg"
  fq_neg :: Ptr CFq -> Ptr CFq -> Ptr CFqCtx -> IO ()

-- | /fq_mul/ /rop/ /op1/ /op2/ /ctx/ 
-- 
-- Sets @rop@ to the product of @op1@ and @op2@, reducing the output in the
-- given context.
foreign import ccall "fq.h fq_mul"
  fq_mul :: Ptr CFq -> Ptr CFq -> Ptr CFq -> Ptr CFqCtx -> IO ()

-- | /fq_mul_fmpz/ /rop/ /op/ /x/ /ctx/ 
-- 
-- Sets @rop@ to the product of @op@ and \(x\), reducing the output in the
-- given context.
foreign import ccall "fq.h fq_mul_fmpz"
  fq_mul_fmpz :: Ptr CFq -> Ptr CFq -> Ptr CFmpz -> Ptr CFqCtx -> IO ()

-- | /fq_mul_si/ /rop/ /op/ /x/ /ctx/ 
-- 
-- Sets @rop@ to the product of @op@ and \(x\), reducing the output in the
-- given context.
foreign import ccall "fq.h fq_mul_si"
  fq_mul_si :: Ptr CFq -> Ptr CFq -> CLong -> Ptr CFqCtx -> IO ()

-- | /fq_mul_ui/ /rop/ /op/ /x/ /ctx/ 
-- 
-- Sets @rop@ to the product of @op@ and \(x\), reducing the output in the
-- given context.
foreign import ccall "fq.h fq_mul_ui"
  fq_mul_ui :: Ptr CFq -> Ptr CFq -> CULong -> Ptr CFqCtx -> IO ()

-- | /fq_sqr/ /rop/ /op/ /ctx/ 
-- 
-- Sets @rop@ to the square of @op@, reducing the output in the given
-- context.
foreign import ccall "fq.h fq_sqr"
  fq_sqr :: Ptr CFq -> Ptr CFq -> Ptr CFqCtx -> IO ()

-- | /fq_div/ /rop/ /op1/ /op2/ /ctx/ 
-- 
-- Sets @rop@ to the quotient of @op1@ and @op2@, reducing the output in
-- the given context.
foreign import ccall "fq.h fq_div"
  fq_div :: Ptr CFq -> Ptr CFq -> Ptr CFq -> Ptr CFqCtx -> IO ()

-- | /_fq_inv/ /rop/ /op/ /len/ /ctx/ 
-- 
-- Sets @(rop, d)@ to the inverse of the non-zero element @(op, len)@.
foreign import ccall "fq.h _fq_inv"
  _fq_inv :: Ptr CFmpz -> Ptr CFmpz -> CLong -> Ptr CFqCtx -> IO ()

-- | /fq_inv/ /rop/ /op/ /ctx/ 
-- 
-- Sets @rop@ to the inverse of the non-zero element @op@.
foreign import ccall "fq.h fq_inv"
  fq_inv :: Ptr CFq -> Ptr CFq -> Ptr CFqCtx -> IO ()

-- | /fq_gcdinv/ /f/ /inv/ /op/ /ctx/ 
-- 
-- Sets @inv@ to be the inverse of @op@ modulo the modulus of @ctx@. If
-- @op@ is not invertible, then @f@ is set to a factor of the modulus;
-- otherwise, it is set to one.
foreign import ccall "fq.h fq_gcdinv"
  fq_gcdinv :: Ptr CFq -> Ptr CFq -> Ptr CFq -> Ptr CFqCtx -> IO ()

-- | /_fq_pow/ /rop/ /op/ /len/ /e/ /ctx/ 
-- 
-- Sets @(rop, 2*d-1)@ to @(op,len)@ raised to the power \(e\), reduced
-- modulo \(f(X)\), the modulus of @ctx@.
-- 
-- Assumes that \(e \geq 0\) and that @len@ is positive and at most \(d\).
-- 
-- Although we require that @rop@ provides space for \(2d - 1\)
-- coefficients, the output will be reduced modulo \(f(X)\), which is a
-- polynomial of degree \(d\).
-- 
-- Does not support aliasing.
foreign import ccall "fq.h _fq_pow"
  _fq_pow :: Ptr CFmpz -> Ptr CFmpz -> CLong -> Ptr CFmpz -> Ptr CFqCtx -> IO ()

-- | /fq_pow/ /rop/ /op/ /e/ /ctx/ 
-- 
-- Sets @rop@ the @op@ raised to the power \(e\).
-- 
-- Currently assumes that \(e \geq 0\).
-- 
-- Note that for any input @op@, @rop@ is set to \(1\) whenever \(e = 0\).
foreign import ccall "fq.h fq_pow"
  fq_pow :: Ptr CFq -> Ptr CFq -> Ptr CFmpz -> Ptr CFqCtx -> IO ()

-- | /fq_pow_ui/ /rop/ /op/ /e/ /ctx/ 
-- 
-- Sets @rop@ the @op@ raised to the power \(e\).
-- 
-- Currently assumes that \(e \geq 0\).
-- 
-- Note that for any input @op@, @rop@ is set to \(1\) whenever \(e = 0\).
foreign import ccall "fq.h fq_pow_ui"
  fq_pow_ui :: Ptr CFq -> Ptr CFq -> CULong -> Ptr CFqCtx -> IO ()

-- Roots -----------------------------------------------------------------------

-- | /fq_sqrt/ /rop/ /op1/ /ctx/ 
-- 
-- Sets @rop@ to the square root of @op1@ if it is a square, and return
-- \(1\), otherwise return \(0\).
foreign import ccall "fq.h fq_sqrt"
  fq_sqrt :: Ptr CFq -> Ptr CFq -> Ptr CFqCtx -> IO CInt

-- | /fq_pth_root/ /rop/ /op1/ /ctx/ 
-- 
-- Sets @rop@ to a \(p^{th}\) root root of @op1@. Currently, this computes
-- the root by raising @op1@ to \(p^{d-1}\) where \(d\) is the degree of
-- the extension.
foreign import ccall "fq.h fq_pth_root"
  fq_pth_root :: Ptr CFq -> Ptr CFq -> Ptr CFqCtx -> IO ()

-- | /fq_is_square/ /op/ /ctx/ 
-- 
-- Return @1@ if @op@ is a square.
foreign import ccall "fq.h fq_is_square"
  fq_is_square :: Ptr CFq -> Ptr CFqCtx -> IO CInt

-- Output ----------------------------------------------------------------------

-- | /fq_fprint_pretty/ /file/ /op/ /ctx/ 
-- 
-- Prints a pretty representation of @op@ to @file@.
-- 
-- In the current implementation, always returns \(1\). The return code is
-- part of the function\'s signature to allow for a later implementation to
-- return the number of characters printed or a non-positive error code.
foreign import ccall "fq.h fq_fprint_pretty"
  fq_fprint_pretty :: Ptr CFile -> Ptr CFq -> Ptr CFqCtx -> IO CInt

-- | /fq_print_pretty/ /op/ /ctx/ 
-- 
-- Prints a pretty representation of @op@ to @stdout@.
-- 
-- In the current implementation, always returns \(1\). The return code is
-- part of the function\'s signature to allow for a later implementation to
-- return the number of characters printed or a non-positive error code.
fq_print_pretty :: Ptr CFq -> Ptr CFqCtx -> IO CInt
fq_print_pretty :: Ptr CFq -> Ptr CFqCtx -> IO CInt
fq_print_pretty Ptr CFq
x Ptr CFqCtx
ctx = (Ptr CFq -> IO CString) -> Ptr CFq -> IO CInt
forall a. (Ptr a -> IO CString) -> Ptr a -> IO CInt
printCStr ((Ptr CFq -> Ptr CFqCtx -> IO CString)
-> Ptr CFqCtx -> Ptr CFq -> IO CString
forall a b c. (a -> b -> c) -> b -> a -> c
flip Ptr CFq -> Ptr CFqCtx -> IO CString
fq_get_str_pretty Ptr CFqCtx
ctx) Ptr CFq
x
 
-- | /fq_fprint/ /file/ /op/ /ctx/ 
-- 
-- Prints a representation of @op@ to @file@.
-- 
-- For further details on the representation used, see
-- @fmpz_mod_poly_fprint@.
foreign import ccall "fq.h fq_fprint"
  fq_fprint :: Ptr CFile -> Ptr CFq -> Ptr CFqCtx -> IO ()

-- | /fq_print/ /op/ /ctx/ 
-- 
-- Prints a representation of @op@ to @stdout@.
-- 
-- For further details on the representation used, see
-- @fmpz_mod_poly_print@.
fq_print :: Ptr CFq -> Ptr CFqCtx -> IO CInt
fq_print :: Ptr CFq -> Ptr CFqCtx -> IO CInt
fq_print Ptr CFq
x Ptr CFqCtx
ctx = (Ptr CFq -> IO CString) -> Ptr CFq -> IO CInt
forall a. (Ptr a -> IO CString) -> Ptr a -> IO CInt
printCStr ((Ptr CFq -> Ptr CFqCtx -> IO CString)
-> Ptr CFqCtx -> Ptr CFq -> IO CString
forall a b c. (a -> b -> c) -> b -> a -> c
flip Ptr CFq -> Ptr CFqCtx -> IO CString
fq_get_str Ptr CFqCtx
ctx) Ptr CFq
x
  
-- | /fq_get_str/ /op/ /ctx/ 
-- 
-- Returns the plain FLINT string representation of the element @op@.
foreign import ccall "fq.h fq_get_str"
  fq_get_str :: Ptr CFq -> Ptr CFqCtx -> IO CString

-- | /fq_get_str_pretty/ /op/ /ctx/ 
-- 
-- Returns a pretty representation of the element @op@ using the
-- null-terminated string @x@ as the variable name.
foreign import ccall "fq.h fq_get_str_pretty"
  fq_get_str_pretty :: Ptr CFq -> Ptr CFqCtx -> IO CString

-- Randomisation ---------------------------------------------------------------

-- | /fq_randtest/ /rop/ /state/ /ctx/ 
-- 
-- Generates a random element of \(\mathbf{F}_q\).
foreign import ccall "fq.h fq_randtest"
  fq_randtest :: Ptr CFq -> Ptr CFRandState -> Ptr CFqCtx -> IO ()

-- | /fq_randtest_not_zero/ /rop/ /state/ /ctx/ 
-- 
-- Generates a random non-zero element of \(\mathbf{F}_q\).
foreign import ccall "fq.h fq_randtest_not_zero"
  fq_randtest_not_zero :: Ptr CFq -> Ptr CFRandState -> Ptr CFqCtx -> IO ()

-- | /fq_randtest_dense/ /rop/ /state/ /ctx/ 
-- 
-- Generates a random element of \(\mathbf{F}_q\) which has an underlying
-- polynomial with dense coefficients.
foreign import ccall "fq.h fq_randtest_dense"
  fq_randtest_dense :: Ptr CFq -> Ptr CFRandState -> Ptr CFqCtx -> IO ()

-- | /fq_rand/ /rop/ /state/ /ctx/ 
-- 
-- Generates a high quality random element of \(\mathbf{F}_q\).
foreign import ccall "fq.h fq_rand"
  fq_rand :: Ptr CFq -> Ptr CFRandState -> Ptr CFqCtx -> IO ()

-- | /fq_rand_not_zero/ /rop/ /state/ /ctx/ 
-- 
-- Generates a high quality non-zero random element of \(\mathbf{F}_q\).
foreign import ccall "fq.h fq_rand_not_zero"
  fq_rand_not_zero :: Ptr CFq -> Ptr CFRandState -> Ptr CFqCtx -> IO ()

-- Assignments and conversions -------------------------------------------------

-- | /fq_set/ /rop/ /op/ /ctx/ 
-- 
-- Sets @rop@ to @op@.
foreign import ccall "fq.h fq_set"
  fq_set :: Ptr CFq -> Ptr CFq -> Ptr CFqCtx -> IO ()

-- | /fq_set_si/ /rop/ /x/ /ctx/ 
-- 
-- Sets @rop@ to @x@, considered as an element of \(\mathbf{F}_p\).
foreign import ccall "fq.h fq_set_si"
  fq_set_si :: Ptr CFq -> CLong -> Ptr CFqCtx -> IO ()

-- | /fq_set_ui/ /rop/ /x/ /ctx/ 
-- 
-- Sets @rop@ to @x@, considered as an element of \(\mathbf{F}_p\).
foreign import ccall "fq.h fq_set_ui"
  fq_set_ui :: Ptr CFq -> CULong -> Ptr CFqCtx -> IO ()

-- | /fq_set_fmpz/ /rop/ /x/ /ctx/ 
-- 
-- Sets @rop@ to @x@, considered as an element of \(\mathbf{F}_p\).
foreign import ccall "fq.h fq_set_fmpz"
  fq_set_fmpz :: Ptr CFq -> Ptr CFmpz -> Ptr CFqCtx -> IO ()

-- | /fq_swap/ /op1/ /op2/ /ctx/ 
-- 
-- Swaps the two elements @op1@ and @op2@.
foreign import ccall "fq.h fq_swap"
  fq_swap :: Ptr CFq -> Ptr CFq -> Ptr CFqCtx -> IO ()

-- | /fq_zero/ /rop/ /ctx/ 
-- 
-- Sets @rop@ to zero.
foreign import ccall "fq.h fq_zero"
  fq_zero :: Ptr CFq -> Ptr CFqCtx -> IO ()

-- | /fq_one/ /rop/ /ctx/ 
-- 
-- Sets @rop@ to one, reduced in the given context.
foreign import ccall "fq.h fq_one"
  fq_one :: Ptr CFq -> Ptr CFqCtx -> IO ()

-- | /fq_gen/ /rop/ /ctx/ 
-- 
-- Sets @rop@ to a generator for the finite field. There is no guarantee
-- this is a multiplicative generator of the finite field.
foreign import ccall "fq.h fq_gen"
  fq_gen :: Ptr CFq -> Ptr CFqCtx -> IO ()

-- | /fq_get_fmpz/ /rop/ /op/ /ctx/ 
-- 
-- If @op@ has a lift to the integers, return \(1\) and set @rop@ to the
-- lift in \([0,p)\). Otherwise, return \(0\) and leave \(rop\) undefined.
foreign import ccall "fq.h fq_get_fmpz"
  fq_get_fmpz :: Ptr CFmpz -> Ptr CFq -> Ptr CFqCtx -> IO CInt

foreign import ccall "fq.h fq_get_fmpz_poly"
  fq_get_fmpz_poly :: Ptr CFmpzPoly -> Ptr CFq -> Ptr CFqCtx -> IO ()

-- | /fq_get_fmpz_mod_poly/ /a/ /b/ /ctx/ 
-- 
-- Set @a@ to a representative of @b@ in @ctx@. The representatives are
-- taken in \((\mathbb{Z}/p\mathbb{Z})[x]/h(x)\) where \(h(x)\) is the
-- defining polynomial in @ctx@.
foreign import ccall "fq.h fq_get_fmpz_mod_poly"
  fq_get_fmpz_mod_poly :: Ptr CFmpzModPoly -> Ptr CFq -> Ptr CFqCtx -> IO ()

foreign import ccall "fq.h fq_set_fmpz_poly"
  fq_set_fmpz_poly :: Ptr CFq -> Ptr CFmpzPoly -> Ptr CFqCtx -> IO ()

-- | /fq_set_fmpz_mod_poly/ /a/ /b/ /ctx/ 
-- 
-- Set @a@ to the element in @ctx@ with representative @b@. The
-- representatives are taken in \((\mathbb{Z}/p\mathbb{Z})[x]/h(x)\) where
-- \(h(x)\) is the defining polynomial in @ctx@.
foreign import ccall "fq.h fq_set_fmpz_mod_poly"
  fq_set_fmpz_mod_poly :: Ptr CFq -> Ptr CFmpzModPoly -> Ptr CFqCtx -> IO ()

-- | /fq_get_fmpz_mod_mat/ /col/ /a/ /ctx/ 
-- 
-- Convert @a@ to a column vector of length @degree(ctx)@.
foreign import ccall "fq.h fq_get_fmpz_mod_mat"
  fq_get_fmpz_mod_mat :: Ptr CFmpzModMat -> Ptr CFq -> Ptr CFqCtx -> IO ()

-- | /fq_set_fmpz_mod_mat/ /a/ /col/ /ctx/ 
-- 
-- Convert a column vector @col@ of length @degree(ctx)@ to an element of
-- @ctx@.
foreign import ccall "fq.h fq_set_fmpz_mod_mat"
  fq_set_fmpz_mod_mat :: Ptr CFq -> Ptr CFmpzModMat -> Ptr CFqCtx -> IO ()

-- Comparison ------------------------------------------------------------------

-- | /fq_is_zero/ /op/ /ctx/ 
-- 
-- Returns whether @op@ is equal to zero.
foreign import ccall "fq.h fq_is_zero"
  fq_is_zero :: Ptr CFq -> Ptr CFqCtx -> IO CInt

-- | /fq_is_one/ /op/ /ctx/ 
-- 
-- Returns whether @op@ is equal to one.
foreign import ccall "fq.h fq_is_one"
  fq_is_one :: Ptr CFq -> Ptr CFqCtx -> IO CInt

-- | /fq_equal/ /op1/ /op2/ /ctx/ 
-- 
-- Returns whether @op1@ and @op2@ are equal.
foreign import ccall "fq.h fq_equal"
  fq_equal :: Ptr CFq -> Ptr CFq -> Ptr CFqCtx -> IO CInt

-- | /fq_is_invertible/ /op/ /ctx/ 
-- 
-- Returns whether @op@ is an invertible element.
foreign import ccall "fq.h fq_is_invertible"
  fq_is_invertible :: Ptr CFq -> Ptr CFqCtx -> IO CInt

-- | /fq_is_invertible_f/ /f/ /op/ /ctx/ 
-- 
-- Returns whether @op@ is an invertible element. If it is not, then @f@ is
-- set of a factor of the modulus.
foreign import ccall "fq.h fq_is_invertible_f"
  fq_is_invertible_f :: Ptr CFq -> Ptr CFq -> Ptr CFqCtx -> IO CInt

-- Special functions -----------------------------------------------------------

-- | /_fq_trace/ /rop/ /op/ /len/ /ctx/ 
-- 
-- Sets @rop@ to the trace of the non-zero element @(op, len)@ in
-- \(\mathbf{F}_{q}\).
foreign import ccall "fq.h _fq_trace"
  _fq_trace :: Ptr CFmpz -> Ptr CFmpz -> CLong -> Ptr CFqCtx -> IO ()

-- | /fq_trace/ /rop/ /op/ /ctx/ 
-- 
-- Sets @rop@ to the trace of @op@.
-- 
-- For an element \(a \in \mathbf{F}_q\), multiplication by \(a\) defines a
-- \(\mathbf{F}_p\)-linear map on \(\mathbf{F}_q\). We define the trace of
-- \(a\) as the trace of this map. Equivalently, if \(\Sigma\) generates
-- \(\operatorname{Gal}(\mathbf{F}_q / \mathbf{F}_p)\) then the trace of
-- \(a\) is equal to \(\sum_{i=0}^{d-1} \Sigma^i (a)\), where \(d =
-- \log_{p} q\).
foreign import ccall "fq.h fq_trace"
  fq_trace :: Ptr CFmpz -> Ptr CFq -> Ptr CFqCtx -> IO ()

-- | /_fq_norm/ /rop/ /op/ /len/ /ctx/ 
-- 
-- Sets @rop@ to the norm of the non-zero element @(op, len)@ in
-- \(\mathbf{F}_{q}\).
foreign import ccall "fq.h _fq_norm"
  _fq_norm :: Ptr CFmpz -> Ptr CFmpz -> CLong -> Ptr CFqCtx -> IO ()

-- | /fq_norm/ /rop/ /op/ /ctx/ 
-- 
-- Computes the norm of @op@.
-- 
-- For an element \(a \in \mathbf{F}_q\), multiplication by \(a\) defines a
-- \(\mathbf{F}_p\)-linear map on \(\mathbf{F}_q\). We define the norm of
-- \(a\) as the determinant of this map. Equivalently, if \(\Sigma\)
-- generates \(\operatorname{Gal}(\mathbf{F}_q / \mathbf{F}_p)\) then the
-- trace of \(a\) is equal to \(\prod_{i=0}^{d-1} \Sigma^i (a)\), where
-- \(d = \text{dim}_{\mathbf{F}_p}(\mathbf{F}_q)\).
-- 
-- Algorithm selection is automatic depending on the input.
foreign import ccall "fq.h fq_norm"
  fq_norm :: Ptr CFmpz -> Ptr CFq -> Ptr CFqCtx -> IO ()

-- | /_fq_frobenius/ /rop/ /op/ /len/ /e/ /ctx/ 
-- 
-- Sets @(rop, 2d-1)@ to the image of @(op, len)@ under the Frobenius
-- operator raised to the e-th power, assuming that neither @op@ nor @e@
-- are zero.
foreign import ccall "fq.h _fq_frobenius"
  _fq_frobenius :: Ptr CFmpz -> Ptr CFmpz -> CLong -> CLong -> Ptr CFqCtx -> IO ()

-- | /fq_frobenius/ /rop/ /op/ /e/ /ctx/ 
-- 
-- Evaluates the homomorphism \(\Sigma^e\) at @op@.
-- 
-- Recall that \(\mathbf{F}_q / \mathbf{F}_p\) is Galois with Galois group
-- \(\langle \sigma \rangle\), which is also isomorphic to
-- \(\mathbf{Z}/d\mathbf{Z}\), where
-- \(\sigma \in \operatorname{Gal}(\mathbf{F}_q/\mathbf{F}_p)\) is the
-- Frobenius element \(\sigma \colon x \mapsto x^p\).
foreign import ccall "fq.h fq_frobenius"
  fq_frobenius :: Ptr CFq -> Ptr CFq -> CLong -> Ptr CFqCtx -> IO ()

-- | /fq_multiplicative_order/ /ord/ /op/ /ctx/ 
-- 
-- Computes the order of @op@ as an element of the multiplicative group of
-- @ctx@.
-- 
-- Returns 0 if @op@ is 0, otherwise it returns 1 if @op@ is a generator of
-- the multiplicative group, and -1 if it is not.
-- 
-- This function can also be used to check primitivity of a generator of a
-- finite field whose defining polynomial is not primitive.
foreign import ccall "fq.h fq_multiplicative_order"
  fq_multiplicative_order :: Ptr CFmpz -> Ptr CFq -> Ptr CFqCtx -> IO CInt

-- | /fq_is_primitive/ /op/ /ctx/ 
-- 
-- Returns whether @op@ is primitive, i.e., whether it is a generator of
-- the multiplicative group of @ctx@.
foreign import ccall "fq.h fq_is_primitive"
  fq_is_primitive :: Ptr CFq -> Ptr CFqCtx -> IO CInt

-- Bit packing -----------------------------------------------------------------

-- | /fq_bit_pack/ /f/ /op/ /bit_size/ /ctx/ 
-- 
-- Packs @op@ into bitfields of size @bit_size@, writing the result to @f@.
foreign import ccall "fq.h fq_bit_pack"
  fq_bit_pack :: Ptr CFmpz -> Ptr CFq -> CFBitCnt -> Ptr CFqCtx -> IO ()

-- | /fq_bit_unpack/ /rop/ /f/ /bit_size/ /ctx/ 
-- 
-- Unpacks into @rop@ the element with coefficients packed into fields of
-- size @bit_size@ as represented by the integer @f@.
foreign import ccall "fq.h fq_bit_unpack"
  fq_bit_unpack :: Ptr CFq -> Ptr CFmpz -> CFBitCnt -> Ptr CFqCtx -> IO ()