{-# LINE 1 "src/Data/Number/Flint/Calcium/Fexpr/FFI.hsc" #-}
{-|
module      :  Data.Number.Flint.Hypgeom.FFI
copyright   :  (c) 2022 Hartmut Monien
license     :  GNU GPL, version 2 or above (see LICENSE)
maintainer  :  hmonien@uni-bonn.de
-}
module Data.Number.Flint.Calcium.Fexpr.FFI (
  -- * Flat-packed symbolic expressions
  -- * Introduction
  -- * Computing and embedding data
  -- * Flat-packed representation
  -- * Memory management
    Fexpr (..)
  , CFexpr ()
  , newFexpr
  , withFexpr
  , withNewFexpr
  , fexpr_init
  , fexpr_clear
  , _fexpr_vec_init
  , _fexpr_vec_clear
  , fexpr_fit_size
  , fexpr_set
  , fexpr_swap
  -- * Types
  , fexpr_type_small_int
  , fexpr_type_small_symbol
  , fexpr_type_small_string
  , fexpr_type_big_int_pos
  , fexpr_type_big_int_neg
  , fexpr_type_big_symbol
  , fexpr_type_big_string
  , fexpr_type_call0
  , fexpr_type_call1
  , fexpr_type_call2
  , fexpr_type_call3
  , fexpr_type_call4
  , fexpr_type_calln
  -- * Size information
  , fexpr_depth
  , fexpr_num_leaves
  , fexpr_size
  , fexpr_size_bytes
  , fexpr_allocated_bytes
  -- * Comparisons
  , fexpr_equal
  , fexpr_equal_si
  , fexpr_equal_ui
  , fexpr_hash
  , fexpr_cmp_fast
  -- * Atoms
  , fexpr_is_integer
  , fexpr_is_symbol
  , fexpr_is_string
  , fexpr_is_atom
  , fexpr_zero
  , fexpr_is_zero
  , fexpr_is_neg_integer
  , fexpr_set_si
  , fexpr_set_ui
  , fexpr_set_fmpz
  , fexpr_get_fmpz
  , fexpr_set_symbol_builtin
  , fexpr_is_builtin_symbol
  , fexpr_is_any_builtin_symbol
  , fexpr_set_symbol_str
  , fexpr_get_symbol_str
  , fexpr_set_string
  , fexpr_get_string
  -- * Input and output
  , fexpr_write
  , fexpr_print
  , fexpr_get_str
  -- * LaTeX output
  , fexpr_write_latex
  , fexpr_print_latex
  , fexpr_get_str_latex
  -- | The /flags/ parameter allows specifying options for LaTeX
  -- output. The following flags are supported:
  , fexpr_latex_small
  , fexpr_latex_logic 
  -- * Function call structure
  , fexpr_nargs
  , fexpr_func
  , fexpr_view_func
  , fexpr_arg
  , fexpr_view_arg
  , fexpr_view_next
  , fexpr_is_builtin_call
  , fexpr_is_any_builtin_call
  -- * Composition
  , fexpr_call0
  , fexpr_call1
  , fexpr_call2
  , fexpr_call3
  , fexpr_call4
  , fexpr_call_vec
  , fexpr_call_builtin1
  , fexpr_call_builtin2
  -- * Subexpressions and replacement
  , fexpr_contains
  , fexpr_replace
  , fexpr_replace2
  , fexpr_replace_vec
  -- * Arithmetic expressions
  , fexpr_set_fmpq
  , fexpr_set_arf
  , fexpr_set_d
  , fexpr_set_re_im_d
  , fexpr_neg
  , fexpr_add
  , fexpr_sub
  , fexpr_mul
  , fexpr_div
  , fexpr_pow
  , fexpr_is_arithmetic_operation
  , fexpr_arithmetic_nodes
  , fexpr_get_fmpz_mpoly_q
  , fexpr_set_fmpz_mpoly
  , fexpr_set_fmpz_mpoly_q
  , fexpr_expanded_normal_form
  -- * Vectors
  , newFexprVec
  , withFexprVec
  , withNewFexprVec
  , fexpr_vec_init
  , fexpr_vec_clear
  , fexpr_vec_print
  , fexpr_vec_swap
  , fexpr_vec_fit_length
  , fexpr_vec_set
  , fexpr_vec_append
  , fexpr_vec_insert_unique
  , fexpr_vec_set_length
  , _fexpr_vec_sort_fast
) where 

-- Flat-packed symbolic expressions --------------------------------------------

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

import Data.Word
import Data.Number.Flint.Flint
import Data.Number.Flint.Fmpz
import Data.Number.Flint.Fmpz.MPoly
import Data.Number.Flint.Fmpz.MPoly.Q
import Data.Number.Flint.Fmpq
import Data.Number.Flint.Arb.Types
import Data.Number.Flint.Calcium



-- fexpr_t ---------------------------------------------------------------------

data Fexpr = Fexpr {-# UNPACK #-} !(ForeignPtr CFexpr)
data CFexpr = CFexpr (Ptr CULong) CLong

instance Storable CFexpr where
  {-# INLINE sizeOf #-}
  sizeOf :: CFexpr -> Int
sizeOf CFexpr
_ = (Int
16)
{-# LINE 165 "src/Data/Number/Flint/Calcium/Fexpr/FFI.hsc" #-}
  {-# INLINE alignment #-}
  alignment :: CFexpr -> Int
alignment CFexpr
_ = Int
8
{-# LINE 167 "src/Data/Number/Flint/Calcium/Fexpr/FFI.hsc" #-}
  peek ptr = CFexpr
    <$> (\hsc_ptr -> peekByteOff hsc_ptr 0) ptr
{-# LINE 169 "src/Data/Number/Flint/Calcium/Fexpr/FFI.hsc" #-}
    <*> (\hsc_ptr -> peekByteOff hsc_ptr 8) ptr
{-# LINE 170 "src/Data/Number/Flint/Calcium/Fexpr/FFI.hsc" #-}
  poke ptr (CFexpr d a) = do
    (\hsc_ptr -> pokeByteOff hsc_ptr 0) ptr d
{-# LINE 172 "src/Data/Number/Flint/Calcium/Fexpr/FFI.hsc" #-}
    (\hsc_ptr -> pokeByteOff hsc_ptr 8) ptr a
{-# LINE 173 "src/Data/Number/Flint/Calcium/Fexpr/FFI.hsc" #-}

newFexpr :: IO Fexpr
newFexpr = do
  ForeignPtr CFexpr
p <- IO (ForeignPtr CFexpr)
forall a. Storable a => IO (ForeignPtr a)
mallocForeignPtr
  ForeignPtr CFexpr -> (Ptr CFexpr -> IO ()) -> IO ()
forall a b. ForeignPtr a -> (Ptr a -> IO b) -> IO b
withForeignPtr ForeignPtr CFexpr
p Ptr CFexpr -> IO ()
fexpr_init
  FinalizerPtr CFexpr -> ForeignPtr CFexpr -> IO ()
forall a. FinalizerPtr a -> ForeignPtr a -> IO ()
addForeignPtrFinalizer FinalizerPtr CFexpr
p_fexpr_clear ForeignPtr CFexpr
p
  Fexpr -> IO Fexpr
forall a. a -> IO a
forall (m :: * -> *) a. Monad m => a -> m a
return (Fexpr -> IO Fexpr) -> Fexpr -> IO Fexpr
forall a b. (a -> b) -> a -> b
$ ForeignPtr CFexpr -> Fexpr
Fexpr ForeignPtr CFexpr
p

withFexpr :: Fexpr -> (Ptr CFexpr -> IO a) -> IO (Fexpr, a)
withFexpr (Fexpr ForeignPtr CFexpr
p) Ptr CFexpr -> IO a
f = do
  ForeignPtr CFexpr -> (Ptr CFexpr -> IO (Fexpr, a)) -> IO (Fexpr, a)
forall a b. ForeignPtr a -> (Ptr a -> IO b) -> IO b
withForeignPtr ForeignPtr CFexpr
p ((Ptr CFexpr -> IO (Fexpr, a)) -> IO (Fexpr, a))
-> (Ptr CFexpr -> IO (Fexpr, a)) -> IO (Fexpr, a)
forall a b. (a -> b) -> a -> b
$ \Ptr CFexpr
fp -> (ForeignPtr CFexpr -> Fexpr
Fexpr ForeignPtr CFexpr
p,) (a -> (Fexpr, a)) -> IO a -> IO (Fexpr, a)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Ptr CFexpr -> IO a
f Ptr CFexpr
fp

withNewFexpr :: (Ptr CFexpr -> IO a) -> IO (Fexpr, a)
withNewFexpr Ptr CFexpr -> IO a
f = do
  Fexpr
x <- IO Fexpr
newFexpr
  Fexpr -> (Ptr CFexpr -> IO a) -> IO (Fexpr, a)
forall {a}. Fexpr -> (Ptr CFexpr -> IO a) -> IO (Fexpr, a)
withFexpr Fexpr
x Ptr CFexpr -> IO a
f

type FexprType = CULong

fexpr_type_small_int :: FexprLatexFlag
fexpr_type_small_int    =  (FexprLatexFlag
0) :: FexprType
{-# LINE 190 "src/Data/Number/Flint/Calcium/Fexpr/FFI.hsc" #-}
fexpr_type_small_symbol =  (1) :: FexprType
{-# LINE 191 "src/Data/Number/Flint/Calcium/Fexpr/FFI.hsc" #-}
fexpr_type_small_string =  (2) :: FexprType
{-# LINE 192 "src/Data/Number/Flint/Calcium/Fexpr/FFI.hsc" #-}
fexpr_type_big_int_pos  =  (3) :: FexprType
{-# LINE 193 "src/Data/Number/Flint/Calcium/Fexpr/FFI.hsc" #-}
fexpr_type_big_int_neg  =  (4) :: FexprType
{-# LINE 194 "src/Data/Number/Flint/Calcium/Fexpr/FFI.hsc" #-}
fexpr_type_big_symbol   =  (5) :: FexprType
{-# LINE 195 "src/Data/Number/Flint/Calcium/Fexpr/FFI.hsc" #-}
fexpr_type_big_string   =  (6) :: FexprType
{-# LINE 196 "src/Data/Number/Flint/Calcium/Fexpr/FFI.hsc" #-}
fexpr_type_call0        =  (7) :: FexprType
{-# LINE 197 "src/Data/Number/Flint/Calcium/Fexpr/FFI.hsc" #-}
fexpr_type_call1        =  (8) :: FexprType
{-# LINE 198 "src/Data/Number/Flint/Calcium/Fexpr/FFI.hsc" #-}
fexpr_type_call2        =  (9) :: FexprType
{-# LINE 199 "src/Data/Number/Flint/Calcium/Fexpr/FFI.hsc" #-}
fexpr_type_call3        =  (10) :: FexprType
{-# LINE 200 "src/Data/Number/Flint/Calcium/Fexpr/FFI.hsc" #-}
fexpr_type_call4        =  (11) :: FexprType
{-# LINE 201 "src/Data/Number/Flint/Calcium/Fexpr/FFI.hsc" #-}
fexpr_type_calln        =  (12) :: FexprType
{-# LINE 202 "src/Data/Number/Flint/Calcium/Fexpr/FFI.hsc" #-}
     
-- Memory management -----------------------------------------------------------

-- | /fexpr_init/ /expr/ 
--
-- Initializes /expr/ for use. Its value is set to the atomic integer 0.
foreign import ccall "fexpr.h fexpr_init"
  fexpr_init :: Ptr CFexpr -> IO ()

-- | /fexpr_clear/ /expr/ 
--
-- Clears /expr/, freeing its allocated memory.
foreign import ccall "fexpr.h fexpr_clear"
  fexpr_clear :: Ptr CFexpr -> IO ()

foreign import ccall "fexpr.h &fexpr_clear"
  p_fexpr_clear :: FunPtr (Ptr CFexpr -> IO ())

-- | /_fexpr_vec_init/ /len/ 
--
-- Returns a heap-allocated vector of /len/ initialized expressions.
foreign import ccall "fexpr.h _fexpr_vec_init"
  _fexpr_vec_init :: CLong -> IO (Ptr Fexpr)

-- | /_fexpr_vec_clear/ /vec/ /len/ 
--
-- Clears the /len/ expressions in /vec/ and frees /vec/ itself.
foreign import ccall "fexpr.h _fexpr_vec_clear"
  _fexpr_vec_clear :: Ptr Fexpr -> CLong -> IO ()

-- | /fexpr_fit_size/ /expr/ /size/ 
--
-- Ensures that /expr/ has room for /size/ words.
foreign import ccall "fexpr.h fexpr_fit_size"
  fexpr_fit_size :: Ptr CFexpr -> CLong -> IO ()

-- | /fexpr_set/ /res/ /expr/ 
--
-- Sets /res/ to the a copy of /expr/.
foreign import ccall "fexpr.h fexpr_set"
  fexpr_set :: Ptr CFexpr -> Ptr CFexpr -> IO ()

-- | /fexpr_swap/ /a/ /b/ 
--
-- Swaps /a/ and /b/ efficiently.
foreign import ccall "fexpr.h fexpr_swap"
  fexpr_swap :: Ptr CFexpr -> Ptr CFexpr -> IO ()

-- Size information ------------------------------------------------------------

-- | /fexpr_depth/ /expr/ 
--
-- Returns the depth of /expr/ as a symbolic expression tree.
foreign import ccall "fexpr.h fexpr_depth"
  fexpr_depth :: Ptr CFexpr -> IO CLong

-- | /fexpr_num_leaves/ /expr/ 
--
-- Returns the number of leaves (atoms, counted with repetition) in the
-- expression /expr/.
foreign import ccall "fexpr.h fexpr_num_leaves"
  fexpr_num_leaves :: Ptr CFexpr -> IO CLong

-- | /fexpr_size/ /expr/ 
--
-- Returns the number of words in the internal representation of /expr/.
foreign import ccall "fexpr.h fexpr_size"
  fexpr_size :: Ptr CFexpr -> IO CLong

-- | /fexpr_size_bytes/ /expr/ 
--
-- Returns the number of bytes in the internal representation of /expr/.
-- The count excludes the size of the structure itself. Add
-- @sizeof(fexpr_struct)@ to get the size of the object as a whole.
foreign import ccall "fexpr.h fexpr_size_bytes"
  fexpr_size_bytes :: Ptr CFexpr -> IO CLong

-- | /fexpr_allocated_bytes/ /expr/ 
--
-- Returns the number of allocated bytes in the internal representation of
-- /expr/. The count excludes the size of the structure itself. Add
-- @sizeof(fexpr_struct)@ to get the size of the object as a whole.
foreign import ccall "fexpr.h fexpr_allocated_bytes"
  fexpr_allocated_bytes :: Ptr CFexpr -> IO CLong

-- Comparisons -----------------------------------------------------------------

-- | /fexpr_equal/ /a/ /b/ 
--
-- Checks if /a/ and /b/ are exactly equal as expressions.
foreign import ccall "fexpr.h fexpr_equal"
  fexpr_equal :: Ptr CFexpr -> Ptr CFexpr -> IO CInt

-- | /fexpr_equal_si/ /expr/ /c/ 
--
foreign import ccall "fexpr.h fexpr_equal_si"
  fexpr_equal_si :: Ptr CFexpr -> CLong -> IO CInt

-- | /fexpr_equal_ui/ /expr/ /c/ 
--
-- Checks if /expr/ is an atomic integer exactly equal to /c/.
foreign import ccall "fexpr.h fexpr_equal_ui"
  fexpr_equal_ui :: Ptr CFexpr -> CULong -> IO CInt

-- | /fexpr_hash/ /expr/ 
--
-- Returns a hash of the expression /expr/.
foreign import ccall "fexpr.h fexpr_hash"
  fexpr_hash :: Ptr CFexpr -> IO CULong

-- | /fexpr_cmp_fast/ /a/ /b/ 
--
-- Compares /a/ and /b/ using an ordering based on the internal
-- representation, returning -1, 0 or 1. This can be used, for instance, to
-- maintain sorted arrays of expressions for binary search; the sort order
-- has no mathematical significance.
foreign import ccall "fexpr.h fexpr_cmp_fast"
  fexpr_cmp_fast :: Ptr CFexpr -> Ptr CFexpr -> IO CInt

-- Atoms -----------------------------------------------------------------------

-- | /fexpr_is_integer/ /expr/ 
--
-- Returns whether /expr/ is an atomic integer
foreign import ccall "fexpr.h fexpr_is_integer"
  fexpr_is_integer :: Ptr CFexpr -> IO CInt

-- | /fexpr_is_symbol/ /expr/ 
--
-- Returns whether /expr/ is an atomic symbol.
foreign import ccall "fexpr.h fexpr_is_symbol"
  fexpr_is_symbol :: Ptr CFexpr -> IO CInt

-- | /fexpr_is_string/ /expr/ 
--
-- Returns whether /expr/ is an atomic string.
foreign import ccall "fexpr.h fexpr_is_string"
  fexpr_is_string :: Ptr CFexpr -> IO CInt

-- | /fexpr_is_atom/ /expr/ 
--
-- Returns whether /expr/ is any atom.
foreign import ccall "fexpr.h fexpr_is_atom"
  fexpr_is_atom :: Ptr CFexpr -> IO CInt

-- | /fexpr_zero/ /res/ 
--
-- Sets /res/ to the atomic integer 0.
foreign import ccall "fexpr.h fexpr_zero"
  fexpr_zero :: Ptr CFexpr -> IO ()

-- | /fexpr_is_zero/ /expr/ 
--
-- Returns whether /expr/ is the atomic integer 0.
foreign import ccall "fexpr.h fexpr_is_zero"
  fexpr_is_zero :: Ptr CFexpr -> IO CInt

-- | /fexpr_is_neg_integer/ /expr/ 
--
-- Returns whether /expr/ is any negative atomic integer.
foreign import ccall "fexpr.h fexpr_is_neg_integer"
  fexpr_is_neg_integer :: Ptr CFexpr -> IO CInt

-- | /fexpr_set_si/ /res/ /c/ 
foreign import ccall "fexpr.h fexpr_set_si"
  fexpr_set_si :: Ptr CFexpr -> CLong -> IO ()
-- | /fexpr_set_ui/ /res/ /c/ 
foreign import ccall "fexpr.h fexpr_set_ui"
  fexpr_set_ui :: Ptr CFexpr -> CULong -> IO ()
-- | /fexpr_set_fmpz/ /res/ /c/ 
--
-- Sets /res/ to the atomic integer /c/.
foreign import ccall "fexpr.h fexpr_set_fmpz"
  fexpr_set_fmpz :: Ptr CFexpr -> Ptr CFmpz -> IO ()

-- | /fexpr_get_fmpz/ /res/ /expr/ 
--
-- Sets /res/ to the atomic integer in /expr/. This aborts if /expr/ is not
-- an atomic integer.
foreign import ccall "fexpr.h fexpr_get_fmpz"
  fexpr_get_fmpz :: Ptr CFmpz -> Ptr CFexpr -> IO CInt

-- | /fexpr_set_symbol_builtin/ /res/ /id/ 
--
-- Sets /res/ to the builtin symbol with internal index /id/ (see
-- @fexpr-builtin@).
foreign import ccall "fexpr.h fexpr_set_symbol_builtin"
  fexpr_set_symbol_builtin :: Ptr CFexpr -> CLong -> IO ()

-- | /fexpr_is_builtin_symbol/ /expr/ /id/ 
--
-- Returns whether /expr/ is the builtin symbol with index /id/ (see
-- @fexpr-builtin@).
foreign import ccall "fexpr.h fexpr_is_builtin_symbol"
  fexpr_is_builtin_symbol :: Ptr CFexpr -> CLong -> IO CInt

-- | /fexpr_is_any_builtin_symbol/ /expr/ 
--
-- Returns whether /expr/ is any builtin symbol (see @fexpr-builtin@).
foreign import ccall "fexpr.h fexpr_is_any_builtin_symbol"
  fexpr_is_any_builtin_symbol :: Ptr CFexpr -> IO CInt

-- | /fexpr_set_symbol_str/ /res/ /s/ 
--
-- Sets /res/ to the symbol given by /s/.
foreign import ccall "fexpr.h fexpr_set_symbol_str"
  fexpr_set_symbol_str :: Ptr CFexpr -> CString -> IO ()

-- | /fexpr_get_symbol_str/ /expr/ 
--
-- Returns the symbol in /expr/ as a string. The string must be freed with
-- @flint_free@. This aborts if /expr/ is not an atomic symbol.
foreign import ccall "fexpr.h fexpr_get_symbol_str"
  fexpr_get_symbol_str :: Ptr CFexpr -> IO CString

-- | /fexpr_set_string/ /res/ /s/ 
--
-- Sets /res/ to the atomic string /s/.
foreign import ccall "fexpr.h fexpr_set_string"
  fexpr_set_string :: Ptr CFexpr -> CString -> IO ()

-- | /fexpr_get_string/ /expr/ 
--
-- Assuming that /expr/ is an atomic string, returns a copy of this string.
-- The string must be freed with @flint_free@.
foreign import ccall "fexpr.h fexpr_get_string"
  fexpr_get_string :: Ptr CFexpr -> IO CString

-- Input and output ------------------------------------------------------------

-- | /fexpr_write/ /stream/ /expr/ 
--
-- Writes /expr/ to /stream/.
foreign import ccall "fexpr.h fexpr_write"
  fexpr_write :: Ptr CCalciumStream -> Ptr CFexpr -> IO ()

-- | /fexpr_print/ /expr/ 
--
-- Prints /expr/ to standard output.
fexpr_print :: Ptr CFexpr -> IO ()
fexpr_print :: Ptr CFexpr -> IO ()
fexpr_print Ptr CFexpr
expr = do
  (Ptr CFexpr -> IO CString) -> Ptr CFexpr -> IO CInt
forall a. (Ptr a -> IO CString) -> Ptr a -> IO CInt
printCStr Ptr CFexpr -> IO CString
fexpr_get_str Ptr CFexpr
expr
  () -> IO ()
forall a. a -> IO a
forall (m :: * -> *) a. Monad m => a -> m a
return ()
  
-- | /fexpr_get_str/ /expr/ 
--
-- Returns a string representation of /expr/. The string must be freed with
-- @flint_free@.
-- 
-- Warning: string literals appearing in expressions are currently not
-- escaped.
foreign import ccall "fexpr.h fexpr_get_str"
  fexpr_get_str :: Ptr CFexpr -> IO CString

-- LaTeX output ----------------------------------------------------------------

-- | /fexpr_write_latex/ /stream/ /expr/ /flags/ 
--
-- Writes the LaTeX representation of /expr/ to /stream/.
foreign import ccall "fexpr.h fexpr_write_latex"
  fexpr_write_latex :: Ptr CCalciumStream -> Ptr CFexpr -> CULong -> IO ()

-- | /fexpr_print_latex/ /expr/ /flags/ 
--
-- Prints the LaTeX representation of /expr/ to standard output.
fexpr_print_latex :: Ptr CFexpr -> CULong -> IO ()
fexpr_print_latex :: Ptr CFexpr -> FexprLatexFlag -> IO ()
fexpr_print_latex Ptr CFexpr
expr FexprLatexFlag
flags = do
  (Ptr CFexpr -> IO CString) -> Ptr CFexpr -> IO CInt
forall a. (Ptr a -> IO CString) -> Ptr a -> IO CInt
printCStr ((Ptr CFexpr -> FexprLatexFlag -> IO CString)
-> FexprLatexFlag -> Ptr CFexpr -> IO CString
forall a b c. (a -> b -> c) -> b -> a -> c
flip Ptr CFexpr -> FexprLatexFlag -> IO CString
fexpr_get_str_latex FexprLatexFlag
flags) Ptr CFexpr
expr
  () -> IO ()
forall a. a -> IO a
forall (m :: * -> *) a. Monad m => a -> m a
return ()
  
-- | /fexpr_get_str_latex/ /expr/ /flags/ 
--
-- Returns a string of the LaTeX representation of /expr/. The string must
-- be freed with @flint_free@.
-- 
-- Warning: string literals appearing in expressions are currently not
-- escaped.
foreign import ccall "fexpr.h fexpr_get_str_latex"
  fexpr_get_str_latex :: Ptr CFexpr -> CULong -> IO CString

type FexprLatexFlag = CULong

fexpr_latex_small, fexpr_latex_logic :: FexprLatexFlag

-- | /fexpr_latex_small/
--
-- Generate more compact formulas, most importantly by printing
-- fractions inline as \(p/q\) instead of as \(\frac{p}{q}\).  This
-- flag is automatically activated within subscripts and superscripts
-- and in certain other parts of formulas.
fexpr_latex_small :: FexprLatexFlag
fexpr_latex_small = FexprLatexFlag
1
{-# LINE 493 "src/Data/Number/Flint/Calcium/Fexpr/FFI.hsc" #-}

-- | /fexpr_latex_logic/
--
-- Use symbols for logical operators such as Not, And, Or, which by
-- default are rendered as words for legibility.
fexpr_latex_logic :: FexprLatexFlag
fexpr_latex_logic = FexprLatexFlag
2
{-# LINE 499 "src/Data/Number/Flint/Calcium/Fexpr/FFI.hsc" #-}

-- Function call structure -----------------------------------------------------

-- | /fexpr_nargs/ /expr/ 
--
-- Returns the number of arguments /n/ in the function call
-- \(f(e_1,\ldots,e_n)\) represented by /expr/. If /expr/ is an atom,
-- returns -1.
foreign import ccall "fexpr.h fexpr_nargs"
  fexpr_nargs :: Ptr CFexpr -> IO CLong

-- | /fexpr_func/ /res/ /expr/ 
--
-- Assuming that /expr/ represents a function call \(f(e_1,\ldots,e_n)\),
-- sets /res/ to the function expression /f/.
foreign import ccall "fexpr.h fexpr_func"
  fexpr_func :: Ptr CFexpr -> Ptr CFexpr -> IO ()

-- | /fexpr_view_func/ /view/ /expr/ 
--
-- As @fexpr_func@, but sets /view/ to a shallow view instead of copying
-- the expression. The variable /view/ must not be initialized before use
-- or cleared after use, and /expr/ must not be modified or cleared as long
-- as /view/ is in use.
foreign import ccall "fexpr.h fexpr_view_func"
  fexpr_view_func :: Ptr CFexpr -> Ptr CFexpr -> IO ()

-- | /fexpr_arg/ /res/ /expr/ /i/ 
--
-- Assuming that /expr/ represents a function call \(f(e_1,\ldots,e_n)\),
-- sets /res/ to the argument \(e_{i+1}\). Note that indexing starts from
-- 0. The index must be in bounds, with \(0 \le i < n\).
foreign import ccall "fexpr.h fexpr_arg"
  fexpr_arg :: Ptr CFexpr -> Ptr CFexpr -> CLong -> IO ()

-- | /fexpr_view_arg/ /view/ /expr/ /i/ 
--
-- As @fexpr_arg@, but sets /view/ to a shallow view instead of copying the
-- expression. The variable /view/ must not be initialized before use or
-- cleared after use, and /expr/ must not be modified or cleared as long as
-- /view/ is in use.
foreign import ccall "fexpr.h fexpr_view_arg"
  fexpr_view_arg :: Ptr CFexpr -> Ptr CFexpr -> CLong -> IO ()

-- | /fexpr_view_next/ /view/ 
--
-- Assuming that /view/ is a shallow view of a function argument \(e_i\) in
-- a function call \(f(e_1,\ldots,e_n)\), sets /view/ to a view of the next
-- argument \(e_{i+1}\). This function can be called when /view/ refers to
-- the last argument \(e_n\), provided that /view/ is not used afterwards.
-- This function can also be called when /view/ refers to the function /f/,
-- in which case it will make /view/ point to \(e_1\).
foreign import ccall "fexpr.h fexpr_view_next"
  fexpr_view_next :: Ptr CFexpr -> IO ()

-- | /fexpr_is_builtin_call/ /expr/ /id/ 
--
-- Returns whether /expr/ has the form \(f(\ldots)\) where /f/ is a builtin
-- function defined by /id/ (see @fexpr-builtin@).
foreign import ccall "fexpr.h fexpr_is_builtin_call"
  fexpr_is_builtin_call :: Ptr CFexpr -> CLong -> IO CInt

-- | /fexpr_is_any_builtin_call/ /expr/ 
--
-- Returns whether /expr/ has the form \(f(\ldots)\) where /f/ is any
-- builtin function (see @fexpr-builtin@).
foreign import ccall "fexpr.h fexpr_is_any_builtin_call"
  fexpr_is_any_builtin_call :: Ptr CFexpr -> IO CInt

-- Composition -----------------------------------------------------------------

-- | /fexpr_call0/ /res/ /f/ 
foreign import ccall "fexpr.h fexpr_call0"
  fexpr_call0 :: Ptr CFexpr -> Ptr CFexpr -> IO ()
-- | /fexpr_call1/ /res/ /f/ /x1/ 
foreign import ccall "fexpr.h fexpr_call1"
  fexpr_call1 :: Ptr CFexpr -> Ptr CFexpr -> Ptr CFexpr -> IO ()
-- | /fexpr_call2/ /res/ /f/ /x1/ /x2/ 
foreign import ccall "fexpr.h fexpr_call2"
  fexpr_call2 :: Ptr CFexpr -> Ptr CFexpr -> Ptr CFexpr -> Ptr CFexpr -> IO ()
-- | /fexpr_call3/ /res/ /f/ /x1/ /x2/ /x3/ 
foreign import ccall "fexpr.h fexpr_call3"
  fexpr_call3 :: Ptr CFexpr -> Ptr CFexpr -> Ptr CFexpr -> Ptr CFexpr -> Ptr CFexpr -> IO ()
-- | /fexpr_call4/ /res/ /f/ /x1/ /x2/ /x3/ /x4/ 
foreign import ccall "fexpr.h fexpr_call4"
  fexpr_call4 :: Ptr CFexpr -> Ptr CFexpr -> Ptr CFexpr -> Ptr CFexpr -> Ptr CFexpr -> Ptr CFexpr -> IO ()
-- | /fexpr_call_vec/ /res/ /f/ /args/ /len/ 
--
-- Creates the function call \(f(x_1,\ldots,x_n)\). The /vec/ version takes
-- the arguments as an array /args/ and /n/ is given by /len/. Warning:
-- aliasing between inputs and outputs is not implemented.
foreign import ccall "fexpr.h fexpr_call_vec"
  fexpr_call_vec :: Ptr CFexpr -> Ptr CFexpr -> Ptr Fexpr -> CLong -> IO ()

-- | /fexpr_call_builtin1/ /res/ /f/ /x1/ 
foreign import ccall "fexpr.h fexpr_call_builtin1"
  fexpr_call_builtin1 :: Ptr CFexpr -> CLong -> Ptr CFexpr -> IO ()
-- | /fexpr_call_builtin2/ /res/ /f/ /x1/ /x2/ 
--
-- Creates the function call \(f(x_1,\ldots,x_n)\), where /f/ defines a
-- builtin symbol.
foreign import ccall "fexpr.h fexpr_call_builtin2"
  fexpr_call_builtin2 :: Ptr CFexpr -> CLong -> Ptr CFexpr -> Ptr CFexpr -> IO ()

-- Subexpressions and replacement ----------------------------------------------

-- | /fexpr_contains/ /expr/ /x/ 
--
-- Returns whether /expr/ contains the expression /x/ as a subexpression
-- (this includes the case where /expr/ and /x/ are equal).
foreign import ccall "fexpr.h fexpr_contains"
  fexpr_contains :: Ptr CFexpr -> Ptr CFexpr -> IO CInt

-- | /fexpr_replace/ /res/ /expr/ /x/ /y/ 
--
-- Sets /res/ to the expression /expr/ with all occurrences of the
-- subexpression /x/ replaced by the expression /y/. Returns a boolean
-- value indicating whether any replacements have been performed. Aliasing
-- is allowed between /res/ and /expr/ but not between /res/ and /x/ or
-- /y/.
foreign import ccall "fexpr.h fexpr_replace"
  fexpr_replace :: Ptr CFexpr -> Ptr CFexpr -> Ptr CFexpr -> Ptr CFexpr -> IO CInt

-- | /fexpr_replace2/ /res/ /expr/ /x1/ /y1/ /x2/ /y2/ 
--
-- Like @fexpr_replace@, but simultaneously replaces /x1/ by /y1/ and /x2/
-- by /y2/.
foreign import ccall "fexpr.h fexpr_replace2"
  fexpr_replace2 :: Ptr CFexpr -> Ptr CFexpr -> Ptr CFexpr -> Ptr CFexpr -> Ptr CFexpr -> Ptr CFexpr -> IO CInt

-- | /fexpr_replace_vec/ /res/ /expr/ /xs/ /ys/ 
--
-- Sets /res/ to the expression /expr/ with all occurrences of the
-- subexpressions given by entries in /xs/ replaced by the corresponding
-- expressions in /ys/. It is required that /xs/ and /ys/ have the same
-- length. Returns a boolean value indicating whether any replacements have
-- been performed. Aliasing is allowed between /res/ and /expr/ but not
-- between /res/ and the entries of /xs/ or /ys/.
foreign import ccall "fexpr.h fexpr_replace_vec"
  fexpr_replace_vec :: Ptr CFexpr -> Ptr CFexpr -> Ptr CFexprVec -> Ptr CFexprVec -> IO CInt

-- Arithmetic expressions ------------------------------------------------------

-- | /fexpr_set_fmpq/ /res/ /x/ 
--
-- Sets /res/ to the rational number /x/. This creates an atomic integer if
-- the denominator of /x/ is one, and otherwise creates a division
-- expression.
foreign import ccall "fexpr.h fexpr_set_fmpq"
  fexpr_set_fmpq :: Ptr CFexpr -> Ptr CFmpq -> IO ()

-- | /fexpr_set_arf/ /res/ /x/ 
foreign import ccall "fexpr.h fexpr_set_arf"
  fexpr_set_arf :: Ptr CFexpr -> Ptr CArf -> IO ()
-- | /fexpr_set_d/ /res/ /x/ 
--
-- Sets /res/ to an expression for the value of the floating-point number
-- /x/. NaN is represented as @Undefined@. For a regular value, this
-- creates an atomic integer or a rational fraction if the exponent is
-- small, and otherwise creates an expression of the form
-- @Mul(m, Pow(2, e))@.
foreign import ccall "fexpr.h fexpr_set_d"
  fexpr_set_d :: Ptr CFexpr -> CDouble -> IO ()

-- | /fexpr_set_re_im_d/ /res/ /x/ /y/ 
--
-- Sets /res/ to an expression for the complex number with real part /x/
-- and imaginary part /y/.
foreign import ccall "fexpr.h fexpr_set_re_im_d"
  fexpr_set_re_im_d :: Ptr CFexpr -> CDouble -> CDouble -> IO ()

-- | /fexpr_neg/ /res/ /a/ 
foreign import ccall "fexpr.h fexpr_neg"
  fexpr_neg :: Ptr CFexpr -> Ptr CFexpr -> IO ()
-- | /fexpr_add/ /res/ /a/ /b/ 
foreign import ccall "fexpr.h fexpr_add"
  fexpr_add :: Ptr CFexpr -> Ptr CFexpr -> Ptr CFexpr -> IO ()
-- | /fexpr_sub/ /res/ /a/ /b/ 
foreign import ccall "fexpr.h fexpr_sub"
  fexpr_sub :: Ptr CFexpr -> Ptr CFexpr -> Ptr CFexpr -> IO ()
-- | /fexpr_mul/ /res/ /a/ /b/ 
foreign import ccall "fexpr.h fexpr_mul"
  fexpr_mul :: Ptr CFexpr -> Ptr CFexpr -> Ptr CFexpr -> IO ()
-- | /fexpr_div/ /res/ /a/ /b/ 
foreign import ccall "fexpr.h fexpr_div"
  fexpr_div :: Ptr CFexpr -> Ptr CFexpr -> Ptr CFexpr -> IO ()
-- | /fexpr_pow/ /res/ /a/ /b/ 
--
-- Constructs an arithmetic expression with given arguments. No
-- simplifications whatsoever are performed.
foreign import ccall "fexpr.h fexpr_pow"
  fexpr_pow :: Ptr CFexpr -> Ptr CFexpr -> Ptr CFexpr -> IO ()

-- | /fexpr_is_arithmetic_operation/ /expr/ 
--
-- Returns whether /expr/ is of the form \(f(e_1,\ldots,e_n)\) where /f/ is
-- one of the arithmetic operators @Pos@, @Neg@, @Add@, @Sub@, @Mul@,
-- @Div@.
foreign import ccall "fexpr.h fexpr_is_arithmetic_operation"
  fexpr_is_arithmetic_operation :: Ptr CFexpr -> IO CInt

-- | /fexpr_arithmetic_nodes/ /nodes/ /expr/ 
--
-- Sets /nodes/ to a vector of subexpressions of /expr/ such that /expr/ is
-- an arithmetic expression with /nodes/ as leaves. More precisely, /expr/
-- will be constructed out of nested application the arithmetic operators
-- @Pos@, @Neg@, @Add@, @Sub@, @Mul@, @Div@ with integers and expressions
-- in /nodes/ as leaves. Powers @Pow@ with an atomic integer exponent are
-- also allowed. The nodes are output without repetition but are not
-- automatically sorted in a canonical order.
foreign import ccall "fexpr.h fexpr_arithmetic_nodes"
  fexpr_arithmetic_nodes :: Ptr CFexprVec -> Ptr CFexpr -> IO ()

-- | /fexpr_get_fmpz_mpoly_q/ /res/ /expr/ /vars/ /ctx/ 
--
-- Sets /res/ to the expression /expr/ as a formal rational function of the
-- subexpressions in /vars/. The vector /vars/ must have the same length as
-- the number of variables specified in /ctx/. To build /vars/
-- automatically for a given expression, @fexpr_arithmetic_nodes@ may be
-- used.
-- 
-- Returns 1 on success and 0 on failure. Failure can occur for the
-- following reasons:
-- 
-- -   A subexpression is encountered that cannot be interpreted as an
--     arithmetic operation and does not appear (exactly) in /vars/.
-- -   Overflow (too many terms or too large exponent).
-- -   Division by zero (a zero denominator is encountered).
-- 
-- It is important to note that this function views /expr/ as a formal
-- rational function with /vars/ as formal indeterminates. It does thus not
-- check for algebraic relations between /vars/ and can implicitly divide
-- by zero if /vars/ are not algebraically independent.
foreign import ccall "fexpr.h fexpr_get_fmpz_mpoly_q"
  fexpr_get_fmpz_mpoly_q :: Ptr CFmpzMPolyQ -> Ptr CFexpr -> Ptr CFexprVec -> Ptr CFmpzMPolyCtx -> IO CInt

-- | /fexpr_set_fmpz_mpoly/ /res/ /poly/ /vars/ /ctx/ 
foreign import ccall "fexpr.h fexpr_set_fmpz_mpoly"
  fexpr_set_fmpz_mpoly :: Ptr CFexpr -> Ptr CFmpzMPoly -> Ptr CFexprVec -> Ptr CFmpzMPolyCtx -> IO ()
-- | /fexpr_set_fmpz_mpoly_q/ /res/ /frac/ /vars/ /ctx/ 
--
-- Sets /res/ to an expression for the multivariate polynomial /poly/ (or
-- rational function /frac/), using the expressions in /vars/ as the
-- variables. The length of /vars/ must agree with the number of variables
-- in /ctx/. If /NULL/ is passed for /vars/, a default choice of symbols is
-- used.
foreign import ccall "fexpr.h fexpr_set_fmpz_mpoly_q"
  fexpr_set_fmpz_mpoly_q :: Ptr CFexpr -> Ptr CFmpzMPolyQ -> Ptr CFexprVec -> Ptr CFmpzMPolyCtx -> IO ()

-- | /fexpr_expanded_normal_form/ /res/ /expr/ /flags/ 
--
-- Sets /res/ to /expr/ converted to expanded normal form viewed as a
-- formal rational function with its non-arithmetic subexpressions as
-- terminal nodes. This function first computes nodes with
-- @fexpr_arithmetic_nodes@, sorts the nodes, evaluates to a rational
-- function with @fexpr_get_fmpz_mpoly_q@, and then converts back to an
-- expression with @fexpr_set_fmpz_mpoly_q@. Optional /flags/ are reserved
-- for future use.
foreign import ccall "fexpr.h fexpr_expanded_normal_form"
  fexpr_expanded_normal_form :: Ptr CFexpr -> Ptr CFexpr -> CULong -> IO CInt

-- Vectors ---------------------------------------------------------------------

data FexprVec = FexprVec {-# UNPACK #-} !(ForeignPtr CFexprVec)
data CFexprVec = CFexprVec (Ptr Fexpr) CLong CLong

instance Storable CFexprVec where
  {-# INLINE sizeOf #-}
  sizeOf :: CFexprVec -> Int
sizeOf CFexprVec
_ = (Int
24)
{-# LINE 768 "src/Data/Number/Flint/Calcium/Fexpr/FFI.hsc" #-}
  {-# INLINE alignment #-}
  alignment :: CFexprVec -> Int
alignment CFexprVec
_ = Int
8
{-# LINE 770 "src/Data/Number/Flint/Calcium/Fexpr/FFI.hsc" #-}
  peek ptr = CFexprVec
    <$> (\hsc_ptr -> peekByteOff hsc_ptr 0) ptr
{-# LINE 772 "src/Data/Number/Flint/Calcium/Fexpr/FFI.hsc" #-}
    <*> (\hsc_ptr -> peekByteOff hsc_ptr 8) ptr
{-# LINE 773 "src/Data/Number/Flint/Calcium/Fexpr/FFI.hsc" #-}
    <*> (\hsc_ptr -> peekByteOff hsc_ptr 16) ptr
{-# LINE 774 "src/Data/Number/Flint/Calcium/Fexpr/FFI.hsc" #-}
  poke ptr (CFexprVec entries alloc length) = do
    (\hsc_ptr -> pokeByteOff hsc_ptr 0) ptr entries
{-# LINE 776 "src/Data/Number/Flint/Calcium/Fexpr/FFI.hsc" #-}
    (\hsc_ptr -> pokeByteOff hsc_ptr 8) ptr alloc
{-# LINE 777 "src/Data/Number/Flint/Calcium/Fexpr/FFI.hsc" #-}
    (\hsc_ptr -> pokeByteOff hsc_ptr 16) ptr length
{-# LINE 778 "src/Data/Number/Flint/Calcium/Fexpr/FFI.hsc" #-}

newFexprVec :: CLong -> IO FexprVec
newFexprVec CLong
n = do
  ForeignPtr CFexprVec
p <- IO (ForeignPtr CFexprVec)
forall a. Storable a => IO (ForeignPtr a)
mallocForeignPtr
  ForeignPtr CFexprVec -> (Ptr CFexprVec -> IO ()) -> IO ()
forall a b. ForeignPtr a -> (Ptr a -> IO b) -> IO b
withForeignPtr ForeignPtr CFexprVec
p ((Ptr CFexprVec -> IO ()) -> IO ())
-> (Ptr CFexprVec -> IO ()) -> IO ()
forall a b. (a -> b) -> a -> b
$ \Ptr CFexprVec
p -> do
    Ptr CFexprVec -> CLong -> IO ()
fexpr_vec_init Ptr CFexprVec
p CLong
n
  FinalizerPtr CFexprVec -> ForeignPtr CFexprVec -> IO ()
forall a. FinalizerPtr a -> ForeignPtr a -> IO ()
addForeignPtrFinalizer FinalizerPtr CFexprVec
p_fexpr_vec_clear ForeignPtr CFexprVec
p
  FexprVec -> IO FexprVec
forall a. a -> IO a
forall (m :: * -> *) a. Monad m => a -> m a
return (FexprVec -> IO FexprVec) -> FexprVec -> IO FexprVec
forall a b. (a -> b) -> a -> b
$ ForeignPtr CFexprVec -> FexprVec
FexprVec ForeignPtr CFexprVec
p

withFexprVec :: FexprVec -> (Ptr CFexprVec -> IO a) -> IO (FexprVec, a)
withFexprVec (FexprVec ForeignPtr CFexprVec
p) Ptr CFexprVec -> IO a
f = do
  ForeignPtr CFexprVec
-> (Ptr CFexprVec -> IO (FexprVec, a)) -> IO (FexprVec, a)
forall a b. ForeignPtr a -> (Ptr a -> IO b) -> IO b
withForeignPtr ForeignPtr CFexprVec
p ((Ptr CFexprVec -> IO (FexprVec, a)) -> IO (FexprVec, a))
-> (Ptr CFexprVec -> IO (FexprVec, a)) -> IO (FexprVec, a)
forall a b. (a -> b) -> a -> b
$ \Ptr CFexprVec
fp -> (ForeignPtr CFexprVec -> FexprVec
FexprVec ForeignPtr CFexprVec
p,) (a -> (FexprVec, a)) -> IO a -> IO (FexprVec, a)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Ptr CFexprVec -> IO a
f Ptr CFexprVec
fp

withNewFexprVec :: CLong -> (Ptr CFexprVec -> IO a) -> IO (FexprVec, a)
withNewFexprVec CLong
n Ptr CFexprVec -> IO a
f = do
  FexprVec
x <- CLong -> IO FexprVec
newFexprVec CLong
n
  FexprVec -> (Ptr CFexprVec -> IO a) -> IO (FexprVec, a)
forall {a}. FexprVec -> (Ptr CFexprVec -> IO a) -> IO (FexprVec, a)
withFexprVec FexprVec
x Ptr CFexprVec -> IO a
f

-- | /fexpr_vec_init/ /vec/ /len/ 
--
-- Initializes /vec/ to a vector of length /len/. All entries are set to
-- the atomic integer 0.
foreign import ccall "fexpr.h fexpr_vec_init"
  fexpr_vec_init :: Ptr CFexprVec -> CLong -> IO ()

-- | /fexpr_vec_clear/ /vec/ 
--
-- Clears the vector /vec/.
foreign import ccall "fexpr.h fexpr_vec_clear"
  fexpr_vec_clear :: Ptr CFexprVec -> IO ()

foreign import ccall "fexpr.h &fexpr_vec_clear"
  p_fexpr_vec_clear :: FunPtr (Ptr CFexprVec -> IO ())

-- | /fexpr_vec_print/ /vec/ 
--
-- Prints /vec/ to standard output.
foreign import ccall "fexpr.h fexpr_vec_print"
  fexpr_vec_print :: Ptr CFexprVec -> IO ()

-- | /fexpr_vec_swap/ /x/ /y/ 
--
-- Swaps /x/ and /y/ efficiently.
foreign import ccall "fexpr.h fexpr_vec_swap"
  fexpr_vec_swap :: Ptr CFexprVec -> Ptr CFexprVec -> IO ()

-- | /fexpr_vec_fit_length/ /vec/ /len/ 
--
-- Ensures that /vec/ has space for /len/ entries.
foreign import ccall "fexpr.h fexpr_vec_fit_length"
  fexpr_vec_fit_length :: Ptr CFexprVec -> CLong -> IO ()

-- | /fexpr_vec_set/ /dest/ /src/ 
--
-- Sets /dest/ to a copy of /src/.
foreign import ccall "fexpr.h fexpr_vec_set"
  fexpr_vec_set :: Ptr CFexprVec -> Ptr CFexprVec -> IO ()

-- | /fexpr_vec_append/ /vec/ /expr/ 
--
-- Appends /expr/ to the end of the vector /vec/.
foreign import ccall "fexpr.h fexpr_vec_append"
  fexpr_vec_append :: Ptr CFexprVec -> Ptr CFexpr -> IO ()

-- | /fexpr_vec_insert_unique/ /vec/ /expr/ 
--
-- Inserts /expr/ without duplication into vec, returning its position. If
-- this expression already exists, /vec/ is unchanged. If this expression
-- does not exist in /vec/, it is appended.
foreign import ccall "fexpr.h fexpr_vec_insert_unique"
  fexpr_vec_insert_unique :: Ptr CFexprVec -> Ptr CFexpr -> IO CLong

-- | /fexpr_vec_set_length/ /vec/ /len/ 
--
-- Sets the length of /vec/ to /len/, truncating or zero-extending as
-- needed.
foreign import ccall "fexpr.h fexpr_vec_set_length"
  fexpr_vec_set_length :: Ptr CFexprVec -> CLong -> IO ()

-- | /_fexpr_vec_sort_fast/ /vec/ /len/ 
--
-- Sorts the /len/ entries in /vec/ using the comparison function
-- @fexpr_cmp_fast@.
foreign import ccall "fexpr.h _fexpr_vec_sort_fast"
  _fexpr_vec_sort_fast :: Ptr Fexpr -> CLong -> IO ()