{-# LINE 1 "src/Data/Number/Flint/Groups/Dirichlet/FFI.hsc" #-}
{-|
module      :  Data.Number.Flint.Groups.Dirichlet.FFI
copyright   :  (c) 2022 Hartmut Monien
license     :  GNU GPL, version 2 or above (see LICENSE)
maintainer  :  hmonien@uni-bonn.de
-}
module Data.Number.Flint.Groups.Dirichlet.FFI (
  -- * Dirichlet characters
  -- * Multiplicative group modulo /q/
    DirichletGroup (..)
  , CDirichletGroup (..)
  , newDirichletGroup
  , withDirichletGroup
  , withNewDirichletGroup
  , dirichlet_group_init
  , dirichlet_subgroup_init
  , dirichlet_group_clear
  , dirichlet_group_size
  , dirichlet_group_num_primitive
  , dirichlet_group_dlog_precompute
  , dirichlet_group_dlog_clear
  -- * Character type
  , DirichletChar (..)
  , CDirichletChar (..)
  , newDirichletChar 
  , withDirichletChar
  , withNewDirichletChar
  , dirichlet_char_init
  , dirichlet_char_clear
  , dirichlet_char_print
  , dirichlet_char_log
  , dirichlet_char_exp
  , _dirichlet_char_exp
  , dirichlet_char_one
  , dirichlet_char_first_primitive
  , dirichlet_char_set
  , dirichlet_char_next
  , dirichlet_char_next_primitive
  , dirichlet_index_char
  , dirichlet_char_index
  , dirichlet_char_eq
  , dirichlet_char_eq_deep
  -- * Character properties
  , dirichlet_char_is_principal
  , dirichlet_conductor_ui
  , dirichlet_conductor_char
  , dirichlet_parity_ui
  , dirichlet_parity_char
  , dirichlet_order_ui
  , dirichlet_order_char
  , dirichlet_char_is_real
  , dirichlet_char_is_primitive
  -- * Character evaluation
  , dirichlet_pairing
  , dirichlet_pairing_char
  , dirichlet_chi
  , dirichlet_chi_vec
  , dirichlet_chi_vec_order
  -- * Character operations
  , dirichlet_char_mul
  , dirichlet_char_pow
  , dirichlet_char_lift
  , dirichlet_char_lower
) where

-- Dirichlet characters --------------------------------------------------------

import Foreign.C.Types
import Foreign.C.String
import Foreign.Ptr
import Foreign.ForeignPtr
import Foreign.Storable

import Data.Number.Flint.Flint



-- dirichlet_group_t -----------------------------------------------------------

data DirichletGroup =
  DirichletGroup {-# UNPACK #-} !(ForeignPtr CDirichletGroup)
data CDirichletGroup = CFlint DirichletGroup

newDirichletGroup :: a -> IO DirichletGroup
newDirichletGroup a
n = do
  ForeignPtr CDirichletGroup
x <- IO (ForeignPtr CDirichletGroup)
forall a. Storable a => IO (ForeignPtr a)
mallocForeignPtr
  ForeignPtr CDirichletGroup
-> (Ptr CDirichletGroup -> IO CInt) -> IO CInt
forall a b. ForeignPtr a -> (Ptr a -> IO b) -> IO b
withForeignPtr ForeignPtr CDirichletGroup
x ((Ptr CDirichletGroup -> IO CInt) -> IO CInt)
-> (Ptr CDirichletGroup -> IO CInt) -> IO CInt
forall a b. (a -> b) -> a -> b
$ \Ptr CDirichletGroup
x -> do
    Ptr CDirichletGroup -> CULong -> IO CInt
dirichlet_group_init Ptr CDirichletGroup
x (a -> CULong
forall a b. (Integral a, Num b) => a -> b
fromIntegral a
n)
  FinalizerPtr CDirichletGroup -> ForeignPtr CDirichletGroup -> IO ()
forall a. FinalizerPtr a -> ForeignPtr a -> IO ()
addForeignPtrFinalizer FinalizerPtr CDirichletGroup
p_dirichlet_group_clear ForeignPtr CDirichletGroup
x
  DirichletGroup -> IO DirichletGroup
forall a. a -> IO a
forall (m :: * -> *) a. Monad m => a -> m a
return (DirichletGroup -> IO DirichletGroup)
-> DirichletGroup -> IO DirichletGroup
forall a b. (a -> b) -> a -> b
$ ForeignPtr CDirichletGroup -> DirichletGroup
DirichletGroup ForeignPtr CDirichletGroup
x

-- | Use DirichletGroup in `f`.
{-# INLINE withDirichletGroup #-}
withDirichletGroup :: DirichletGroup
-> (Ptr CDirichletGroup -> IO a) -> IO (DirichletGroup, a)
withDirichletGroup (DirichletGroup ForeignPtr CDirichletGroup
p) Ptr CDirichletGroup -> IO a
f = do
  ForeignPtr CDirichletGroup
-> (Ptr CDirichletGroup -> IO (DirichletGroup, a))
-> IO (DirichletGroup, a)
forall a b. ForeignPtr a -> (Ptr a -> IO b) -> IO b
withForeignPtr ForeignPtr CDirichletGroup
p ((Ptr CDirichletGroup -> IO (DirichletGroup, a))
 -> IO (DirichletGroup, a))
-> (Ptr CDirichletGroup -> IO (DirichletGroup, a))
-> IO (DirichletGroup, a)
forall a b. (a -> b) -> a -> b
$ \Ptr CDirichletGroup
fp -> (ForeignPtr CDirichletGroup -> DirichletGroup
DirichletGroup ForeignPtr CDirichletGroup
p,) (a -> (DirichletGroup, a)) -> IO a -> IO (DirichletGroup, a)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Ptr CDirichletGroup -> IO a
f Ptr CDirichletGroup
fp

-- | Apply `f` to new DirichletGroup.
{-# INLINE withNewDirichletGroup #-}
withNewDirichletGroup :: a -> (Ptr CDirichletGroup -> IO a) -> IO (DirichletGroup, a)
withNewDirichletGroup a
n Ptr CDirichletGroup -> IO a
f = do
  DirichletGroup
x <- a -> IO DirichletGroup
forall {a}. Integral a => a -> IO DirichletGroup
newDirichletGroup a
n
  DirichletGroup
-> (Ptr CDirichletGroup -> IO a) -> IO (DirichletGroup, a)
forall {a}.
DirichletGroup
-> (Ptr CDirichletGroup -> IO a) -> IO (DirichletGroup, a)
withDirichletGroup DirichletGroup
x Ptr CDirichletGroup -> IO a
f

instance Storable CDirichletGroup where
  {-# INLINE sizeOf #-}
  sizeOf :: CDirichletGroup -> Int
sizeOf    CDirichletGroup
_ = (Int
104)
{-# LINE 105 "src/Data/Number/Flint/Groups/Dirichlet/FFI.hsc" #-}
  {-# INLINE alignment #-}
  alignment :: CDirichletGroup -> Int
alignment CDirichletGroup
_ = Int
8
{-# LINE 107 "src/Data/Number/Flint/Groups/Dirichlet/FFI.hsc" #-}
  peek = undefined
  poke :: Ptr CDirichletGroup -> CDirichletGroup -> IO ()
poke = Ptr CDirichletGroup -> CDirichletGroup -> IO ()
forall a. HasCallStack => a
undefined

-- Multiplicative group modulo /q/ ---------------------------------------------

-- | /dirichlet_group_init/ /G/ /q/ 
-- 
-- Initializes /G/ to the group of Dirichlet characters mod /q/.
-- 
-- This method computes a canonical decomposition of /G/ in terms of cyclic
-- groups, which are the mod \(p^e\) subgroups for \(p^e\|q\), plus the
-- specific generator described by Conrey for each subgroup.
-- 
-- In particular /G/ contains:
-- 
-- -   the number /num/ of components
-- -   the generators
-- -   the exponent /expo/ of the group
-- 
-- It does /not/ automatically precompute lookup tables of discrete
-- logarithms or numerical roots of unity, and can therefore safely be
-- called even with large /q/.
-- 
-- For implementation reasons, the largest prime factor of /q/ must not
-- exceed \(10^{16}\). This restriction could be removed in the future. The
-- function returns 1 on success and 0 if a factor is too large.
foreign import ccall "dirichlet.h dirichlet_group_init"
  dirichlet_group_init :: Ptr CDirichletGroup -> CULong -> IO CInt

-- | /dirichlet_subgroup_init/ /H/ /G/ /h/ 
-- 
-- Given an already computed group /G/ mod \(q\), initialize its subgroup
-- /H/ defined mod \(h\mid q\). Precomputed discrete log tables are
-- inherited.
foreign import ccall "dirichlet.h dirichlet_subgroup_init"
  dirichlet_subgroup_init :: Ptr CDirichletGroup -> Ptr CDirichletGroup -> CULong -> IO ()

-- | /dirichlet_group_clear/ /G/ 
-- 
-- Clears /G/. Remark this function does /not/ clear the discrete logarithm
-- tables stored in /G/ (which may be shared with another group).
foreign import ccall "dirichlet.h dirichlet_group_clear"
  dirichlet_group_clear :: Ptr CDirichletGroup -> IO ()

foreign import ccall "dirichlet.h &dirichlet_group_clear"
  p_dirichlet_group_clear :: FunPtr (Ptr CDirichletGroup -> IO ())

-- | /dirichlet_group_size/ /G/ 
-- 
-- Returns the number of elements in /G/, i.e. \(\varphi(q)\).
foreign import ccall "dirichlet.h dirichlet_group_size"
  dirichlet_group_size :: Ptr CDirichletGroup -> IO CULong

-- | /dirichlet_group_num_primitive/ /G/ 
-- 
-- Returns the number of primitive elements in /G/.
foreign import ccall "dirichlet.h dirichlet_group_num_primitive"
  dirichlet_group_num_primitive :: Ptr CDirichletGroup -> IO CULong

-- | /dirichlet_group_dlog_precompute/ /G/ /num/ 
-- 
-- Precompute decomposition and tables for discrete log computations in
-- /G/, so as to minimize the complexity of /num/ calls to discrete
-- logarithms.
-- 
-- If /num/ gets very large, the entire group may be indexed.
foreign import ccall "dirichlet.h dirichlet_group_dlog_precompute"
  dirichlet_group_dlog_precompute :: Ptr CDirichletGroup -> CULong -> IO ()

-- | /dirichlet_group_dlog_clear/ /G/ /num/ 
-- 
-- Clear discrete logarithm tables in /G/. When discrete logarithm tables
-- are shared with subgroups, those subgroups must be cleared before
-- clearing the tables.
foreign import ccall "dirichlet.h dirichlet_group_dlog_clear"
  dirichlet_group_dlog_clear :: Ptr CDirichletGroup -> CULong -> IO ()

-- Character type --------------------------------------------------------------

data DirichletChar = DirichletChar {-# UNPACK #-} !(ForeignPtr CDirichletChar)
data CDirichletChar = CDirichletChar CULong (Ptr CULong)

newDirichletChar :: DirichletGroup -> IO DirichletChar
newDirichletChar DirichletGroup
group = do
  ForeignPtr CDirichletChar
x <- IO (ForeignPtr CDirichletChar)
forall a. Storable a => IO (ForeignPtr a)
mallocForeignPtr
  ForeignPtr CDirichletChar
-> (Ptr CDirichletChar -> IO (DirichletGroup, ()))
-> IO (DirichletGroup, ())
forall a b. ForeignPtr a -> (Ptr a -> IO b) -> IO b
withForeignPtr ForeignPtr CDirichletChar
x ((Ptr CDirichletChar -> IO (DirichletGroup, ()))
 -> IO (DirichletGroup, ()))
-> (Ptr CDirichletChar -> IO (DirichletGroup, ()))
-> IO (DirichletGroup, ())
forall a b. (a -> b) -> a -> b
$ \Ptr CDirichletChar
x -> do
    DirichletGroup
-> (Ptr CDirichletGroup -> IO ()) -> IO (DirichletGroup, ())
forall {a}.
DirichletGroup
-> (Ptr CDirichletGroup -> IO a) -> IO (DirichletGroup, a)
withDirichletGroup DirichletGroup
group ((Ptr CDirichletGroup -> IO ()) -> IO (DirichletGroup, ()))
-> (Ptr CDirichletGroup -> IO ()) -> IO (DirichletGroup, ())
forall a b. (a -> b) -> a -> b
$ \Ptr CDirichletGroup
group -> do
      Ptr CDirichletChar -> Ptr CDirichletGroup -> IO ()
dirichlet_char_init Ptr CDirichletChar
x Ptr CDirichletGroup
group
  FinalizerPtr CDirichletChar -> ForeignPtr CDirichletChar -> IO ()
forall a. FinalizerPtr a -> ForeignPtr a -> IO ()
addForeignPtrFinalizer FinalizerPtr CDirichletChar
p_dirichlet_char_clear ForeignPtr CDirichletChar
x
  DirichletChar -> IO DirichletChar
forall a. a -> IO a
forall (m :: * -> *) a. Monad m => a -> m a
return (DirichletChar -> IO DirichletChar)
-> DirichletChar -> IO DirichletChar
forall a b. (a -> b) -> a -> b
$ ForeignPtr CDirichletChar -> DirichletChar
DirichletChar ForeignPtr CDirichletChar
x

-- | Use DirichletChar in `f`.
{-# INLINE withDirichletChar #-}
withDirichletChar :: DirichletChar
-> (Ptr CDirichletChar -> IO a) -> IO (DirichletChar, a)
withDirichletChar (DirichletChar ForeignPtr CDirichletChar
p) Ptr CDirichletChar -> IO a
f = do
  ForeignPtr CDirichletChar
-> (Ptr CDirichletChar -> IO (DirichletChar, a))
-> IO (DirichletChar, a)
forall a b. ForeignPtr a -> (Ptr a -> IO b) -> IO b
withForeignPtr ForeignPtr CDirichletChar
p ((Ptr CDirichletChar -> IO (DirichletChar, a))
 -> IO (DirichletChar, a))
-> (Ptr CDirichletChar -> IO (DirichletChar, a))
-> IO (DirichletChar, a)
forall a b. (a -> b) -> a -> b
$ \Ptr CDirichletChar
fp -> (ForeignPtr CDirichletChar -> DirichletChar
DirichletChar ForeignPtr CDirichletChar
p,) (a -> (DirichletChar, a)) -> IO a -> IO (DirichletChar, a)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Ptr CDirichletChar -> IO a
f Ptr CDirichletChar
fp

-- | Apply `f` to new DirichletChar.
{-# INLINE withNewDirichletChar #-}
withNewDirichletChar :: DirichletGroup
-> (Ptr CDirichletChar -> IO a) -> IO (DirichletChar, a)
withNewDirichletChar DirichletGroup
group Ptr CDirichletChar -> IO a
f = do
  DirichletChar
x <- DirichletGroup -> IO DirichletChar
newDirichletChar DirichletGroup
group
  DirichletChar
-> (Ptr CDirichletChar -> IO a) -> IO (DirichletChar, a)
forall {a}.
DirichletChar
-> (Ptr CDirichletChar -> IO a) -> IO (DirichletChar, a)
withDirichletChar DirichletChar
x Ptr CDirichletChar -> IO a
f

instance Storable CDirichletChar where
  {-# INLINE sizeOf #-}
  sizeOf :: CDirichletChar -> Int
sizeOf    CDirichletChar
_ = (Int
16)
{-# LINE 211 "src/Data/Number/Flint/Groups/Dirichlet/FFI.hsc" #-}
  {-# INLINE alignment #-}
  alignment :: CDirichletChar -> Int
alignment CDirichletChar
_ = Int
8
{-# LINE 213 "src/Data/Number/Flint/Groups/Dirichlet/FFI.hsc" #-}
  peek ptr = CDirichletChar
    <$> (\hsc_ptr -> peekByteOff hsc_ptr 0) ptr
{-# LINE 215 "src/Data/Number/Flint/Groups/Dirichlet/FFI.hsc" #-}
    <*> (\hsc_ptr -> peekByteOff hsc_ptr 8) ptr
{-# LINE 216 "src/Data/Number/Flint/Groups/Dirichlet/FFI.hsc" #-}
  poke ptr (CDirichletChar n log) = do
    (\hsc_ptr -> pokeByteOff hsc_ptr 0) ptr n
{-# LINE 218 "src/Data/Number/Flint/Groups/Dirichlet/FFI.hsc" #-}
    (\hsc_ptr -> pokeByteOff hsc_ptr 8) ptr log
{-# LINE 219 "src/Data/Number/Flint/Groups/Dirichlet/FFI.hsc" #-}

--------------------------------------------------------------------------------

-- | /dirichlet_char_init/ /chi/ /G/ 
-- 
-- Initializes /chi/ to an element of the group /G/ and sets its value to
-- the principal character.
foreign import ccall "dirichlet.h dirichlet_char_init"
  dirichlet_char_init :: Ptr CDirichletChar -> Ptr CDirichletGroup -> IO ()

-- | /dirichlet_char_clear/ /chi/ 
-- 
-- Clears /chi/.
foreign import ccall "dirichlet.h dirichlet_char_clear"
  dirichlet_char_clear :: Ptr CDirichletChar -> IO ()

foreign import ccall "dirichlet.h &dirichlet_char_clear"
  p_dirichlet_char_clear :: FunPtr (Ptr CDirichletChar -> IO ())

-- | /dirichlet_char_print/ /G/ /chi/ 
-- 
-- Prints the array of exponents representing this character.
dirichlet_char_print :: Ptr CDirichletGroup -> Ptr CDirichletChar -> IO ()
dirichlet_char_print :: Ptr CDirichletGroup -> Ptr CDirichletChar -> IO ()
dirichlet_char_print Ptr CDirichletGroup
g Ptr CDirichletChar
c = do
  (Ptr CDirichletChar -> IO CString) -> Ptr CDirichletChar -> IO CInt
forall a. (Ptr a -> IO CString) -> Ptr a -> IO CInt
printCStr (Ptr CDirichletGroup -> Ptr CDirichletChar -> IO CString
dirichlet_char_get_str Ptr CDirichletGroup
g) Ptr CDirichletChar
c
  () -> IO ()
forall a. a -> IO a
forall (m :: * -> *) a. Monad m => a -> m a
return ()
  

foreign import ccall "dirichlet.h dirichlet_char_get_str"
  dirichlet_char_get_str :: Ptr CDirichletGroup
                         -> Ptr CDirichletChar -> IO CString

-- | /dirichlet_char_log/ /x/ /G/ /m/ 
-- 
-- Sets /x/ to the character of number /m/, computing its log using
-- discrete logarithm in /G/.
foreign import ccall "dirichlet.h dirichlet_char_log"
  dirichlet_char_log :: Ptr CDirichletChar -> Ptr CDirichletGroup -> CULong -> IO ()

-- | /dirichlet_char_exp/ /G/ /x/ 
-- 
-- Returns the number /m/ corresponding to exponents in /x/.
foreign import ccall "dirichlet.h dirichlet_char_exp"
  dirichlet_char_exp :: Ptr CDirichletGroup -> Ptr CDirichletChar -> IO CULong

-- | /_dirichlet_char_exp/ /x/ /G/ 
-- 
-- Computes and returns the number /m/ corresponding to exponents in /x/.
-- This function is for internal use.
foreign import ccall "dirichlet.h _dirichlet_char_exp"
  _dirichlet_char_exp :: Ptr CDirichletChar -> Ptr CDirichletGroup -> IO CULong

-- | /dirichlet_char_one/ /x/ /G/ 
-- 
-- Sets /x/ to the principal character in /G/, having /log/
-- \([0,\dots 0]\).
foreign import ccall "dirichlet.h dirichlet_char_one"
  dirichlet_char_one :: Ptr CDirichletChar -> Ptr CDirichletGroup -> IO ()

-- | /dirichlet_char_first_primitive/ /x/ /G/ 
-- 
-- Sets /x/ to the first primitive character of /G/, having /log/
-- \([1,\dots 1]\), or \([0, 1, \dots 1]\) if \(8\mid q\).
foreign import ccall "dirichlet.h dirichlet_char_first_primitive"
  dirichlet_char_first_primitive :: Ptr CDirichletChar -> Ptr CDirichletGroup -> IO ()

-- | /dirichlet_char_set/ /x/ /G/ /y/ 
-- 
-- Sets /x/ to the element /y/.
foreign import ccall "dirichlet.h dirichlet_char_set"
  dirichlet_char_set :: Ptr CDirichletChar -> Ptr CDirichletGroup -> Ptr CDirichletChar -> IO ()

-- | /dirichlet_char_next/ /x/ /G/ 
-- 
-- Sets /x/ to the next character in /G/ according to lexicographic
-- ordering of /log/.
-- 
-- The return value is the index of the last updated exponent of /x/, or
-- /-1/ if the last element has been reached.
-- 
-- This function allows to iterate on all elements of /G/ looping on their
-- /log/. Note that it produces elements in seemingly random /number/
-- order.
-- 
-- The following template can be used for such a loop:
-- 
-- > dirichlet_char_one(chi, G);
-- > do {
-- >     /* use character chi */
-- > } while (dirichlet_char_next(chi, G) >= 0);
foreign import ccall "dirichlet.h dirichlet_char_next"
  dirichlet_char_next :: Ptr CDirichletChar -> Ptr CDirichletGroup -> IO CInt

-- | /dirichlet_char_next_primitive/ /x/ /G/ 
-- 
-- Same as @dirichlet_char_next@, but jumps to the next primitive character
-- of /G/.
foreign import ccall "dirichlet.h dirichlet_char_next_primitive"
  dirichlet_char_next_primitive :: Ptr CDirichletChar -> Ptr CDirichletGroup -> IO CInt

-- | /dirichlet_index_char/ /G/ /x/ 
-- 
-- Returns the lexicographic index of the /log/ of /x/ as an integer in
-- \(0\dots \varphi(q)\).
foreign import ccall "dirichlet.h dirichlet_index_char"
  dirichlet_index_char :: Ptr CDirichletGroup -> Ptr CDirichletChar -> IO CULong

-- | /dirichlet_char_index/ /x/ /G/ /j/ 
-- 
-- Sets /x/ to the character whose /log/ has lexicographic index /j/.
foreign import ccall "dirichlet.h dirichlet_char_index"
  dirichlet_char_index :: Ptr CDirichletChar -> Ptr CDirichletGroup -> CULong -> IO ()

foreign import ccall "dirichlet.h dirichlet_char_eq"
  dirichlet_char_eq :: Ptr CDirichletChar -> Ptr CDirichletChar -> IO CInt

-- | /dirichlet_char_eq_deep/ /G/ /x/ /y/ 
-- 
-- Return 1 if /x/ equals /y/.
-- 
-- The second version checks every byte of the representation and is
-- intended for testing only.
foreign import ccall "dirichlet.h dirichlet_char_eq_deep"
  dirichlet_char_eq_deep :: Ptr CDirichletGroup -> Ptr CDirichletChar -> Ptr CDirichletChar -> IO CInt

-- Character properties --------------------------------------------------------

-- As a consequence of the Conrey numbering, all these numbers are
-- available at the level of /number/ and /char/ object. Both case require
-- no discrete log computation.
--
-- | /dirichlet_char_is_principal/ /G/ /chi/ 
-- 
-- Returns 1 if /chi/ is the principal character mod /q/.
foreign import ccall "dirichlet.h dirichlet_char_is_principal"
  dirichlet_char_is_principal :: Ptr CDirichletGroup -> Ptr CDirichletChar -> IO CInt

foreign import ccall "dirichlet.h dirichlet_conductor_ui"
  dirichlet_conductor_ui :: Ptr CDirichletGroup -> CULong -> IO CULong

-- | /dirichlet_conductor_char/ /G/ /x/ 
-- 
-- Returns the /conductor/ of \(\chi_q(a,\cdot)\), that is the smallest
-- \(r\) dividing \(q\) such \(\chi_q(a,\cdot)\) can be obtained as a
-- character mod \(r\).
foreign import ccall "dirichlet.h dirichlet_conductor_char"
  dirichlet_conductor_char :: Ptr CDirichletGroup -> Ptr CDirichletChar -> IO CULong

foreign import ccall "dirichlet.h dirichlet_parity_ui"
  dirichlet_parity_ui :: Ptr CDirichletGroup -> CULong -> IO CInt

-- | /dirichlet_parity_char/ /G/ /x/ 
-- 
-- Returns the /parity/ \(\lambda\) in \(\{0,1\}\) of \(\chi_q(a,\cdot)\),
-- such that \(\chi_q(a,-1)=(-1)^\lambda\).
foreign import ccall "dirichlet.h dirichlet_parity_char"
  dirichlet_parity_char :: Ptr CDirichletGroup -> Ptr CDirichletChar -> IO CInt

foreign import ccall "dirichlet.h dirichlet_order_ui"
  dirichlet_order_ui :: Ptr CDirichletGroup -> CULong -> IO CULong

-- | /dirichlet_order_char/ /G/ /x/ 
-- 
-- Returns the order of \(\chi_q(a,\cdot)\) which is the order of
-- \(a\bmod q\).
foreign import ccall "dirichlet.h dirichlet_order_char"
  dirichlet_order_char :: Ptr CDirichletGroup -> Ptr CDirichletChar -> IO CULong

-- | /dirichlet_char_is_real/ /G/ /chi/ 
-- 
-- Returns 1 if /chi/ is a real character (iff it has order \(\leq 2\)).
foreign import ccall "dirichlet.h dirichlet_char_is_real"
  dirichlet_char_is_real :: Ptr CDirichletGroup -> Ptr CDirichletChar -> IO CInt

-- | /dirichlet_char_is_primitive/ /G/ /chi/ 
-- 
-- Returns 1 if /chi/ is primitive (iff its conductor is exactly /q/).
foreign import ccall "dirichlet.h dirichlet_char_is_primitive"
  dirichlet_char_is_primitive :: Ptr CDirichletGroup -> Ptr CDirichletChar -> IO CInt

-- Character evaluation --------------------------------------------------------

-- Dirichlet characters take value in a finite cyclic group of roots of
-- unity plus zero.
--
-- Evaluation functions return a /ulong/, this number corresponds to the
-- power of a primitive root of unity, the special value
-- /DIRICHLET_CHI_NULL/ encoding the zero value.
--
foreign import ccall "dirichlet.h dirichlet_pairing"
  dirichlet_pairing :: Ptr CDirichletGroup -> CULong -> CULong -> IO CULong

-- | /dirichlet_pairing_char/ /G/ /chi/ /psi/ 
-- 
-- Compute the value of the Dirichlet pairing on numbers /m/ and /n/, as
-- exponent modulo /G->expo/.
-- 
-- The /char/ variant takes as input two characters, so that no discrete
-- logarithm is computed.
-- 
-- The returned value is the numerator of the actual value exponent mod the
-- group exponent /G->expo/.
foreign import ccall "dirichlet.h dirichlet_pairing_char"
  dirichlet_pairing_char :: Ptr CDirichletGroup -> Ptr CDirichletChar -> Ptr CDirichletChar -> IO CULong

-- | /dirichlet_chi/ /G/ /chi/ /n/ 
-- 
-- Compute the value \(\chi(n)\) as the exponent modulo /G->expo/.
foreign import ccall "dirichlet.h dirichlet_chi"
  dirichlet_chi :: Ptr CDirichletGroup -> Ptr CDirichletChar -> CULong -> IO CULong

-- | /dirichlet_chi_vec/ /v/ /G/ /chi/ /nv/ 
-- 
-- Compute the list of exponent values /v[k]/ for \(0\leq k < nv\), as
-- exponents modulo /G->expo/.
foreign import ccall "dirichlet.h dirichlet_chi_vec"
  dirichlet_chi_vec :: Ptr CULong -> Ptr CDirichletGroup -> Ptr CDirichletChar -> CLong -> IO ()

-- | /dirichlet_chi_vec_order/ /v/ /G/ /chi/ /order/ /nv/ 
-- 
-- Compute the list of exponent values /v[k]/ for \(0\leq k < nv\), as
-- exponents modulo /order/, which is assumed to be a multiple of the order
-- of /chi/.
foreign import ccall "dirichlet.h dirichlet_chi_vec_order"
  dirichlet_chi_vec_order :: Ptr CULong -> Ptr CDirichletGroup -> Ptr CDirichletChar -> CULong -> CLong -> IO ()

-- Character operations --------------------------------------------------------

-- | /dirichlet_char_mul/ /chi12/ /G/ /chi1/ /chi2/ 
-- 
-- Multiply two characters of the same group /G/.
foreign import ccall "dirichlet.h dirichlet_char_mul"
  dirichlet_char_mul :: Ptr CDirichletChar -> Ptr CDirichletGroup -> Ptr CDirichletChar -> Ptr CDirichletChar -> IO ()

-- | /dirichlet_char_pow/ /c/ /G/ /a/ /n/ 
-- 
-- Take the power of a character.
foreign import ccall "dirichlet.h dirichlet_char_pow"
  dirichlet_char_pow :: Ptr CDirichletChar -> Ptr CDirichletGroup -> Ptr CDirichletChar -> CULong -> IO ()

-- | /dirichlet_char_lift/ /chi_G/ /G/ /chi_H/ /H/ 
-- 
-- If /H/ is a subgroup of /G/, computes the character in /G/ corresponding
-- to /chi_H/ in /H/.
foreign import ccall "dirichlet.h dirichlet_char_lift"
  dirichlet_char_lift :: Ptr CDirichletChar -> Ptr CDirichletGroup -> Ptr CDirichletChar -> Ptr CDirichletGroup -> IO ()

-- | /dirichlet_char_lower/ /chi_H/ /H/ /chi_G/ /G/ 
-- 
-- If /chi_G/ is a character of /G/ which factors through /H/, sets /chi_H/
-- to the corresponding restriction in /H/.
-- 
-- This requires \(c(\chi_G)\mid q_H\mid q_G\), where \(c(\chi_G)\) is the
-- conductor of \(\chi_G\) and \(q_G, q_H\) are the moduli of G and H.
foreign import ccall "dirichlet.h dirichlet_char_lower"
  dirichlet_char_lower :: Ptr CDirichletChar -> Ptr CDirichletGroup -> Ptr CDirichletChar -> Ptr CDirichletGroup -> IO ()