{-# LINE 1 "src/Data/Number/Flint/Padic/Poly/FFI.hsc" #-}
{-|
module      :  Data.Number.Flint.Padic.Poly.FFI
copyright   :  (c) 2022 Hartmut Monien
license     :  GNU GPL, version 2 or above (see LICENSE)
maintainer  :  hmonien@uni-bonn.de
-}
module Data.Number.Flint.Padic.Poly.FFI (
  -- * Polynomials over p-adic numbers
    PadicPoly (..)
  , CPadicPoly (..)
  , newPadicPoly
  , withPadicPoly
  , withNewPadicPoly
  -- * Memory management
  , padic_poly_init
  , padic_poly_init2
  , padic_poly_realloc
  , padic_poly_fit_length
  , _padic_poly_set_length
  , padic_poly_clear
  , _padic_poly_normalise
  , _padic_poly_canonicalise
  , padic_poly_reduce
  , padic_poly_truncate
  -- * Polynomial parameters
  , padic_poly_degree
  , padic_poly_length
  , padic_poly_val
  -- , padic_poly_prec
  -- * Randomisation
  , padic_poly_randtest
  , padic_poly_randtest_not_zero
  , padic_poly_randtest_val
  -- * Assignment and basic manipulation
  , padic_poly_set_padic
  , padic_poly_set
  , padic_poly_set_si
  , padic_poly_set_ui
  , padic_poly_set_fmpz
  , padic_poly_set_fmpq
  , padic_poly_set_fmpz_poly
  , padic_poly_set_fmpq_poly
  , padic_poly_get_fmpz_poly
  , padic_poly_get_fmpq_poly
  , padic_poly_zero
  , padic_poly_one
  , padic_poly_swap
  -- * Getting and setting coefficients
  , padic_poly_get_coeff_padic
  , padic_poly_set_coeff_padic
  -- * Comparison
  , padic_poly_equal
  , padic_poly_is_zero
  , padic_poly_is_one
  -- * Addition and subtraction
  , _padic_poly_add
  , padic_poly_add
  , _padic_poly_sub
  , padic_poly_sub
  , padic_poly_neg
  -- * Scalar multiplication
  , _padic_poly_scalar_mul_padic
  , padic_poly_scalar_mul_padic
  -- * Multiplication
  , _padic_poly_mul
  , padic_poly_mul
  -- * Powering
  , _padic_poly_pow
  , padic_poly_pow
  -- * Series inversion
  , padic_poly_inv_series
  -- * Derivative
  , _padic_poly_derivative
  , padic_poly_derivative
  -- * Shifting
  , padic_poly_shift_left
  , padic_poly_shift_right
  -- * Evaluation
  , _padic_poly_evaluate_padic
  , padic_poly_evaluate_padic
  -- * Composition
  , _padic_poly_compose
  , padic_poly_compose
  , _padic_poly_compose_pow
  , padic_poly_compose_pow
  -- * Input and output
  , padic_poly_debug
  , _padic_poly_fprint
  , padic_poly_fprint
  , _padic_poly_print
  , padic_poly_print
  , _padic_poly_fprint_pretty
  , padic_poly_fprint_pretty
  , _padic_poly_print_pretty
  , padic_poly_print_pretty
  , padic_poly_get_str_pretty
  , padic_poly_get_str
  -- * Testing
  , _padic_poly_is_canonical
) where

-- polynomials over p-adic numbers ---------------------------------------------

import Control.Monad

import Foreign.C.String
import Foreign.C.Types
import Foreign.ForeignPtr
import Foreign.Ptr ( Ptr, FunPtr, nullPtr, plusPtr, castPtr )
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.Fmpq
import Data.Number.Flint.Fmpq.Poly
import Data.Number.Flint.Padic





-- padic_poly_t ----------------------------------------------------------------

data PadicPoly = PadicPoly {-# UNPACK #-} !(ForeignPtr CPadicPoly)
data CPadicPoly = CPadicPoly (Ptr CFmpz) CLong CLong CLong CLong

instance Storable CPadicPoly where
  {-# INLINE sizeOf #-}
  sizeOf :: CPadicPoly -> Int
sizeOf CPadicPoly
_ = (Int
40)
{-# LINE 132 "src/Data/Number/Flint/Padic/Poly/FFI.hsc" #-}
  {-# INLINE alignment #-}
  alignment :: CPadicPoly -> Int
alignment CPadicPoly
_ = Int
8
{-# LINE 134 "src/Data/Number/Flint/Padic/Poly/FFI.hsc" #-}
  peek ptr = return CPadicPoly
    `ap` (return $ castPtr ptr)
    `ap` (\hsc_ptr -> peekByteOff hsc_ptr 8) ptr
{-# LINE 137 "src/Data/Number/Flint/Padic/Poly/FFI.hsc" #-}
    `ap` (\hsc_ptr -> peekByteOff hsc_ptr 16) ptr
{-# LINE 138 "src/Data/Number/Flint/Padic/Poly/FFI.hsc" #-}
    `ap` (\hsc_ptr -> peekByteOff hsc_ptr 24) ptr
{-# LINE 139 "src/Data/Number/Flint/Padic/Poly/FFI.hsc" #-}
    `ap` (\hsc_ptr -> peekByteOff hsc_ptr 32) ptr
{-# LINE 140 "src/Data/Number/Flint/Padic/Poly/FFI.hsc" #-}
  poke ptr (CPadicPoly coeffs alloc length val n) = do
    ((\hsc_ptr -> pokeByteOff hsc_ptr 0)) ptr coeffs
{-# LINE 142 "src/Data/Number/Flint/Padic/Poly/FFI.hsc" #-}
    ((\hsc_ptr -> pokeByteOff hsc_ptr 8)) ptr alloc
{-# LINE 143 "src/Data/Number/Flint/Padic/Poly/FFI.hsc" #-}
    ((\hsc_ptr -> pokeByteOff hsc_ptr 16)) ptr length
{-# LINE 144 "src/Data/Number/Flint/Padic/Poly/FFI.hsc" #-}
    ((\hsc_ptr -> pokeByteOff hsc_ptr 24)) ptr val
{-# LINE 145 "src/Data/Number/Flint/Padic/Poly/FFI.hsc" #-}
    ((\hsc_ptr -> pokeByteOff hsc_ptr 32)) ptr n
{-# LINE 146 "src/Data/Number/Flint/Padic/Poly/FFI.hsc" #-}

newPadicPoly :: IO PadicPoly
newPadicPoly = do
  ForeignPtr CPadicPoly
x <- IO (ForeignPtr CPadicPoly)
forall a. Storable a => IO (ForeignPtr a)
mallocForeignPtr
  ForeignPtr CPadicPoly -> (Ptr CPadicPoly -> IO ()) -> IO ()
forall a b. ForeignPtr a -> (Ptr a -> IO b) -> IO b
withForeignPtr ForeignPtr CPadicPoly
x Ptr CPadicPoly -> IO ()
padic_poly_init
  FinalizerPtr CPadicPoly -> ForeignPtr CPadicPoly -> IO ()
forall a. FinalizerPtr a -> ForeignPtr a -> IO ()
addForeignPtrFinalizer FinalizerPtr CPadicPoly
p_padic_poly_clear ForeignPtr CPadicPoly
x
  PadicPoly -> IO PadicPoly
forall a. a -> IO a
forall (m :: * -> *) a. Monad m => a -> m a
return (PadicPoly -> IO PadicPoly) -> PadicPoly -> IO PadicPoly
forall a b. (a -> b) -> a -> b
$ ForeignPtr CPadicPoly -> PadicPoly
PadicPoly ForeignPtr CPadicPoly
x

{-# INLINE withPadicPoly #-}
withPadicPoly :: PadicPoly -> (Ptr CPadicPoly -> IO a) -> IO (PadicPoly, a)
withPadicPoly (PadicPoly ForeignPtr CPadicPoly
x) Ptr CPadicPoly -> IO a
f = do
  ForeignPtr CPadicPoly
-> (Ptr CPadicPoly -> IO (PadicPoly, a)) -> IO (PadicPoly, a)
forall a b. ForeignPtr a -> (Ptr a -> IO b) -> IO b
withForeignPtr ForeignPtr CPadicPoly
x ((Ptr CPadicPoly -> IO (PadicPoly, a)) -> IO (PadicPoly, a))
-> (Ptr CPadicPoly -> IO (PadicPoly, a)) -> IO (PadicPoly, a)
forall a b. (a -> b) -> a -> b
$ \Ptr CPadicPoly
px -> Ptr CPadicPoly -> IO a
f Ptr CPadicPoly
px IO a -> (a -> IO (PadicPoly, a)) -> IO (PadicPoly, a)
forall a b. IO a -> (a -> IO b) -> IO b
forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
>>= (PadicPoly, a) -> IO (PadicPoly, a)
forall a. a -> IO a
forall (m :: * -> *) a. Monad m => a -> m a
return ((PadicPoly, a) -> IO (PadicPoly, a))
-> (a -> (PadicPoly, a)) -> a -> IO (PadicPoly, a)
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (ForeignPtr CPadicPoly -> PadicPoly
PadicPoly ForeignPtr CPadicPoly
x,)

{-# INLINE withNewPadicPoly #-}
withNewPadicPoly :: (Ptr CPadicPoly -> IO a) -> IO (PadicPoly, a)
withNewPadicPoly Ptr CPadicPoly -> IO a
f = do
  PadicPoly
x <- IO PadicPoly
newPadicPoly
  PadicPoly -> (Ptr CPadicPoly -> IO a) -> IO (PadicPoly, a)
forall {a}.
PadicPoly -> (Ptr CPadicPoly -> IO a) -> IO (PadicPoly, a)
withPadicPoly PadicPoly
x Ptr CPadicPoly -> IO a
f
  
-- Memory management -----------------------------------------------------------

-- | /padic_poly_init/ /poly/ 
-- 
-- Initialises @poly@ for use, setting its length to zero. The precision of
-- the polynomial is set to @PADIC_DEFAULT_PREC@. A corresponding call to
-- @padic_poly_clear@ must be made after finishing with the @padic_poly_t@
-- to free the memory used by the polynomial.
foreign import ccall "padic_poly.h padic_poly_init"
  padic_poly_init :: Ptr CPadicPoly -> IO ()

-- | /padic_poly_init2/ /poly/ /alloc/ /prec/ 
-- 
-- Initialises @poly@ with space for at least @alloc@ coefficients and sets
-- the length to zero. The allocated coefficients are all set to zero. The
-- precision is set to @prec@.
foreign import ccall "padic_poly.h padic_poly_init2"
  padic_poly_init2 :: Ptr CPadicPoly -> CLong -> CLong -> IO ()

-- | /padic_poly_realloc/ /poly/ /alloc/ /p/ 
-- 
-- Reallocates the given polynomial to have space for @alloc@ coefficients.
-- If @alloc@ is zero the polynomial is cleared and then reinitialised. If
-- the current length is greater than @alloc@ the polynomial is first
-- truncated to length @alloc@.
foreign import ccall "padic_poly.h padic_poly_realloc"
  padic_poly_realloc :: Ptr CPadicPoly -> CLong -> Ptr CFmpz -> IO ()

-- | /padic_poly_fit_length/ /poly/ /len/ 
-- 
-- If @len@ is greater than the number of coefficients currently allocated,
-- then the polynomial is reallocated to have space for at least @len@
-- coefficients. No data is lost when calling this function.
-- 
-- The function efficiently deals with the case where @fit_length@ is
-- called many times in small increments by at least doubling the number of
-- allocated coefficients when length is larger than the number of
-- coefficients currently allocated.
foreign import ccall "padic_poly.h padic_poly_fit_length"
  padic_poly_fit_length :: Ptr CPadicPoly -> CLong -> IO ()

-- | /_padic_poly_set_length/ /poly/ /len/ 
-- 
-- Demotes the coefficients of @poly@ beyond @len@ and sets the length of
-- @poly@ to @len@.
-- 
-- Note that if the current length is greater than @len@ the polynomial may
-- no slonger be in canonical form.
foreign import ccall "padic_poly.h _padic_poly_set_length"
  _padic_poly_set_length :: Ptr CPadicPoly -> CLong -> IO ()

-- | /padic_poly_clear/ /poly/ 
-- 
-- Clears the given polynomial, releasing any memory used. It must be
-- reinitialised in order to be used again.
foreign import ccall "padic_poly.h padic_poly_clear"
  padic_poly_clear :: Ptr CPadicPoly -> IO ()

foreign import ccall "padic_poly.h &padic_poly_clear"
  p_padic_poly_clear :: FunPtr (Ptr CPadicPoly -> IO ())

-- | /_padic_poly_normalise/ /poly/ 
-- 
-- Sets the length of @poly@ so that the top coefficient is non-zero. If
-- all coefficients are zero, the length is set to zero. This function is
-- mainly used internally, as all functions guarantee normalisation.
foreign import ccall "padic_poly.h _padic_poly_normalise"
  _padic_poly_normalise :: Ptr CPadicPoly -> IO ()

-- | /_padic_poly_canonicalise/ /poly/ /v/ /len/ /p/ 
-- 
-- Brings the polynomial @poly@ into canonical form, assuming that it is
-- normalised already. Does /not/ carry out any reduction.
foreign import ccall "padic_poly.h _padic_poly_canonicalise"
  _padic_poly_canonicalise :: Ptr CFmpz -> Ptr CLong -> CLong -> Ptr CFmpz -> IO ()

-- | /padic_poly_reduce/ /poly/ /ctx/ 
-- 
-- Reduces the polynomial @poly@ modulo \(p^N\), assuming that it is in
-- canonical form already.
foreign import ccall "padic_poly.h padic_poly_reduce"
  padic_poly_reduce :: Ptr CPadicPoly -> Ptr CPadicCtx -> IO ()

-- | /padic_poly_truncate/ /poly/ /n/ /p/ 
-- 
-- Truncates the polynomial to length at most~\`n\`.
foreign import ccall "padic_poly.h padic_poly_truncate"
  padic_poly_truncate :: Ptr CPadicPoly -> CLong -> Ptr CFmpz -> IO ()

-- Polynomial parameters -------------------------------------------------------

-- | /padic_poly_degree/ /poly/ 
-- 
-- Returns the degree of the polynomial @poly@.
foreign import ccall "padic_poly.h padic_poly_degree"
  padic_poly_degree :: Ptr CPadicPoly -> IO CLong

-- | /padic_poly_length/ /poly/ 
-- 
-- Returns the length of the polynomial @poly@.
foreign import ccall "padic_poly.h padic_poly_length"
  padic_poly_length :: Ptr CPadicPoly -> IO CLong

-- | /padic_poly_val/ /poly/ 
-- 
-- Returns the valuation of the polynomial @poly@, which is defined to be
-- the minimum valuation of all its coefficients.
-- 
-- The valuation of the zero polynomial is~\`0\`.
-- 
-- Note that this is implemented as a macro and can be used as either a
-- @lvalue@ or a @rvalue@.
foreign import ccall "padic_poly.h padic_poly_val"
  padic_poly_val :: Ptr CPadicPoly -> IO CLong

-- | /padic_poly_prec/ /poly/ 
-- 
-- Returns the precision of the polynomial @poly@.
-- 
-- Note that this is implemented as a macro and can be used as either a
-- @lvalue@ or a @rvalue@.
-- 
-- Note that increasing the precision might require a call to
-- @padic_poly_reduce@.
-- foreign import ccall "padic_poly.h padic_poly_prec"
--   padic_poly_prec :: Ptr CPadicPoly -> IO CLong

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

-- | /padic_poly_randtest/ /f/ /state/ /len/ /ctx/ 
-- 
-- Sets \(f\) to a random polynomial of length at most @len@ with entries
-- reduced modulo \(p^N\).
foreign import ccall "padic_poly.h padic_poly_randtest"
  padic_poly_randtest :: Ptr CPadicPoly -> Ptr CFRandState -> CLong -> Ptr CPadicCtx -> IO ()

-- | /padic_poly_randtest_not_zero/ /f/ /state/ /len/ /ctx/ 
-- 
-- Sets \(f\) to a non-zero random polynomial of length at most @len@ with
-- entries reduced modulo \(p^N\).
foreign import ccall "padic_poly.h padic_poly_randtest_not_zero"
  padic_poly_randtest_not_zero :: Ptr CPadicPoly -> Ptr CFRandState -> CLong -> Ptr CPadicCtx -> IO ()

-- | /padic_poly_randtest_val/ /f/ /state/ /val/ /len/ /ctx/ 
-- 
-- Sets \(f\) to a random polynomial of length at most @len@ with at most
-- the prescribed valuation @val@ and entries reduced modulo \(p^N\).
-- 
-- Specifically, we aim to set the valuation to be exactly equal to @val@,
-- but do not check for additional cancellation when creating the
-- coefficients.
foreign import ccall "padic_poly.h padic_poly_randtest_val"
  padic_poly_randtest_val :: Ptr CPadicPoly -> Ptr CFRandState -> CLong -> CLong -> Ptr CPadicCtx -> IO ()

-- Assignment and basic manipulation -------------------------------------------

-- | /padic_poly_set_padic/ /poly/ /x/ /ctx/ 
-- 
-- Sets the polynomial @poly@ to the \(p\)-adic number \(x\), reduced to
-- the precision of the polynomial.
foreign import ccall "padic_poly.h padic_poly_set_padic"
  padic_poly_set_padic :: Ptr CPadicPoly -> Ptr CPadic -> Ptr CPadicCtx -> IO ()

-- | /padic_poly_set/ /poly1/ /poly2/ /ctx/ 
-- 
-- Sets the polynomial @poly1@ to the polynomial @poly2@, reduced to the
-- precision of @poly1@.
foreign import ccall "padic_poly.h padic_poly_set"
  padic_poly_set :: Ptr CPadicPoly -> Ptr CPadicPoly -> Ptr CPadicCtx -> IO ()

-- | /padic_poly_set_si/ /poly/ /x/ /ctx/ 
-- 
-- Sets the polynomial @poly@ to the @signed slong@ integer \(x\) reduced
-- to the precision of the polynomial.
foreign import ccall "padic_poly.h padic_poly_set_si"
  padic_poly_set_si :: Ptr CPadicPoly -> CLong -> Ptr CPadicCtx -> IO ()

-- | /padic_poly_set_ui/ /poly/ /x/ /ctx/ 
-- 
-- Sets the polynomial @poly@ to the @unsigned slong@ integer \(x\) reduced
-- to the precision of the polynomial.
foreign import ccall "padic_poly.h padic_poly_set_ui"
  padic_poly_set_ui :: Ptr CPadicPoly -> CULong -> Ptr CPadicCtx -> IO ()

-- | /padic_poly_set_fmpz/ /poly/ /x/ /ctx/ 
-- 
-- Sets the polynomial @poly@ to the integer \(x\) reduced to the precision
-- of the polynomial.
foreign import ccall "padic_poly.h padic_poly_set_fmpz"
  padic_poly_set_fmpz :: Ptr CPadicPoly -> Ptr CFmpz -> Ptr CPadicCtx -> IO ()

-- | /padic_poly_set_fmpq/ /poly/ /x/ /ctx/ 
-- 
-- Sets the polynomial @poly@ to the value of the rational \(x\), reduced
-- to the precision of the polynomial.
foreign import ccall "padic_poly.h padic_poly_set_fmpq"
  padic_poly_set_fmpq :: Ptr CPadicPoly -> Ptr CFmpq -> Ptr CPadicCtx -> IO ()

-- | /padic_poly_set_fmpz_poly/ /rop/ /op/ /ctx/ 
-- 
-- Sets the polynomial @rop@ to the integer polynomial @op@ reduced to the
-- precision of the polynomial.
foreign import ccall "padic_poly.h padic_poly_set_fmpz_poly"
  padic_poly_set_fmpz_poly :: Ptr CPadicPoly -> Ptr CFmpzPoly -> Ptr CPadicCtx -> IO ()

-- | /padic_poly_set_fmpq_poly/ /rop/ /op/ /ctx/ 
-- 
-- Sets the polynomial @rop@ to the value of the rational polynomial @op@,
-- reduced to the precision of the polynomial.
foreign import ccall "padic_poly.h padic_poly_set_fmpq_poly"
  padic_poly_set_fmpq_poly :: Ptr CPadicPoly -> Ptr CFmpqPoly -> Ptr CPadicCtx -> IO ()

-- | /padic_poly_get_fmpz_poly/ /rop/ /op/ /ctx/ 
-- 
-- Sets the integer polynomial @rop@ to the value of the \(p\)-adic
-- polynomial @op@ and returns \(1\) if the polynomial is \(p\)-adically
-- integral. Otherwise, returns \(0\).
foreign import ccall "padic_poly.h padic_poly_get_fmpz_poly"
  padic_poly_get_fmpz_poly :: Ptr CFmpzPoly -> Ptr CPadicPoly -> Ptr CPadicCtx -> IO CInt

-- | /padic_poly_get_fmpq_poly/ /rop/ /op/ /ctx/ 
-- 
-- Sets @rop@ to the rational polynomial corresponding to the \(p\)-adic
-- polynomial @op@.
foreign import ccall "padic_poly.h padic_poly_get_fmpq_poly"
  padic_poly_get_fmpq_poly :: Ptr CFmpqPoly -> Ptr CPadicPoly -> Ptr CPadicCtx -> IO ()

-- | /padic_poly_zero/ /poly/ 
-- 
-- Sets @poly@ to the zero polynomial.
foreign import ccall "padic_poly.h padic_poly_zero"
  padic_poly_zero :: Ptr CPadicPoly -> IO ()

-- | /padic_poly_one/ /poly/ 
-- 
-- Sets @poly@ to the constant polynomial \(1\), reduced to the precision
-- of the polynomial.
foreign import ccall "padic_poly.h padic_poly_one"
  padic_poly_one :: Ptr CPadicPoly -> IO ()

-- | /padic_poly_swap/ /poly1/ /poly2/ 
-- 
-- Swaps the two polynomials @poly1@ and @poly2@, including their
-- precisions.
-- 
-- This is done efficiently by swapping pointers.
foreign import ccall "padic_poly.h padic_poly_swap"
  padic_poly_swap :: Ptr CPadicPoly -> Ptr CPadicPoly -> IO ()

-- Getting and setting coefficients --------------------------------------------

-- | /padic_poly_get_coeff_padic/ /c/ /poly/ /n/ /ctx/ 
-- 
-- Sets \(c\) to the coefficient of \(x^n\) in the polynomial, reduced
-- modulo the precision of \(c\).
foreign import ccall "padic_poly.h padic_poly_get_coeff_padic"
  padic_poly_get_coeff_padic :: Ptr CPadic -> Ptr CPadicPoly -> CLong -> Ptr CPadicCtx -> IO ()

-- | /padic_poly_set_coeff_padic/ /f/ /n/ /c/ /ctx/ 
-- 
-- Sets the coefficient of \(x^n\) in the polynomial \(f\) to \(c\),
-- reduced to the precision of the polynomial \(f\).
-- 
-- Note that this operation can take linear time in the length of the
-- polynomial.
foreign import ccall "padic_poly.h padic_poly_set_coeff_padic"
  padic_poly_set_coeff_padic :: Ptr CPadicPoly -> CLong -> Ptr CPadic -> Ptr CPadicCtx -> IO ()

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

-- | /padic_poly_equal/ /poly1/ /poly2/ 
-- 
-- Returns whether the two polynomials @poly1@ and @poly2@ are equal.
foreign import ccall "padic_poly.h padic_poly_equal"
  padic_poly_equal :: Ptr CPadicPoly -> Ptr CPadicPoly -> IO CInt

-- | /padic_poly_is_zero/ /poly/ 
-- 
-- Returns whether the polynomial @poly@ is the zero polynomial.
foreign import ccall "padic_poly.h padic_poly_is_zero"
  padic_poly_is_zero :: Ptr CPadicPoly -> IO CInt

-- | /padic_poly_is_one/ /poly/ /ctx/ 
-- 
-- Returns whether the polynomial @poly@ is equal to the constant
-- polynomial~\`1\`, taking the precision of the polynomial into account.
foreign import ccall "padic_poly.h padic_poly_is_one"
  padic_poly_is_one :: Ptr CPadicPoly -> Ptr CPadicCtx -> IO CInt

-- Addition and subtraction ----------------------------------------------------

-- | /_padic_poly_add/ /rop/ /rval/ /N/ /op1/ /val1/ /len1/ /N1/ /op2/ /val2/ /len2/ /N2/ /ctx/ 
-- 
-- Sets @(rop, *val, FLINT_MAX(len1, len2)@ to the sum of
-- @(op1, val1, len1)@ and @(op2, val2, len2)@.
-- 
-- Assumes that the input is reduced and guarantees that this is also the
-- case for the output.
-- 
-- Assumes that \(\min\{v_1, v_2\} < N\).
-- 
-- Supports aliasing between the output and input arguments.
foreign import ccall "padic_poly.h _padic_poly_add"
  _padic_poly_add :: Ptr CFmpz -> Ptr CLong -> CLong -> Ptr CFmpz -> CLong -> CLong -> CLong -> Ptr CFmpz -> CLong -> CLong -> CLong -> Ptr CPadicCtx -> IO ()

-- | /padic_poly_add/ /f/ /g/ /h/ /ctx/ 
-- 
-- Sets \(f\) to the sum \(g + h\).
foreign import ccall "padic_poly.h padic_poly_add"
  padic_poly_add :: Ptr CPadicPoly -> Ptr CPadicPoly -> Ptr CPadicPoly -> Ptr CPadicCtx -> IO ()

-- | /_padic_poly_sub/ /rop/ /rval/ /op1/ /val1/ /len1/ /op2/ /val2/ /len2/ /ctx/ 
-- 
-- Sets @(rop, *val, FLINT_MAX(len1, len2)@ to the difference of
-- @(op1, val1, len1)@ and @(op2, val2, len2)@.
-- 
-- Assumes that the input is reduced and guarantees that this is also the
-- case for the output.
-- 
-- Assumes that \(\min\{v_1, v_2\} < N\).
-- 
-- Support aliasing between the output and input arguments.
foreign import ccall "padic_poly.h _padic_poly_sub"
  _padic_poly_sub :: Ptr CFmpz -> Ptr CLong -> Ptr CFmpz -> CLong -> CLong -> Ptr CFmpz -> CLong -> CLong -> Ptr CPadicCtx -> IO ()

-- | /padic_poly_sub/ /f/ /g/ /h/ /ctx/ 
-- 
-- Sets \(f\) to the difference \(g - h\).
foreign import ccall "padic_poly.h padic_poly_sub"
  padic_poly_sub :: Ptr CPadicPoly -> Ptr CPadicPoly -> Ptr CPadicPoly -> Ptr CPadicCtx -> IO ()

-- | /padic_poly_neg/ /f/ /g/ /ctx/ 
-- 
-- Sets \(f\) to \(-g\).
foreign import ccall "padic_poly.h padic_poly_neg"
  padic_poly_neg :: Ptr CPadicPoly -> Ptr CPadicPoly -> Ptr CPadicCtx -> IO ()

-- Scalar multiplication -------------------------------------------------------

-- | /_padic_poly_scalar_mul_padic/ /rop/ /rval/ /op/ /val/ /len/ /c/ /ctx/ 
-- 
-- Sets @(rop, *rval, len)@ to @(op, val, len)@ multiplied by the scalar
-- \(c\).
-- 
-- The result will only be correctly reduced if the polynomial is non-zero.
-- Otherwise, the array @(rop, len)@ will be set to zero but the valuation
-- @*rval@ might be wrong.
foreign import ccall "padic_poly.h _padic_poly_scalar_mul_padic"
  _padic_poly_scalar_mul_padic :: Ptr CFmpz -> Ptr CLong -> Ptr CFmpz -> CLong -> CLong -> Ptr CPadic -> Ptr CPadicCtx -> IO ()

-- | /padic_poly_scalar_mul_padic/ /rop/ /op/ /c/ /ctx/ 
-- 
-- Sets the polynomial @rop@ to the product of the polynomial @op@ and the
-- \(p\)-adic number \(c\), reducing the result modulo \(p^N\).
foreign import ccall "padic_poly.h padic_poly_scalar_mul_padic"
  padic_poly_scalar_mul_padic :: Ptr CPadicPoly -> Ptr CPadicPoly -> Ptr CPadic -> Ptr CPadicCtx -> IO ()

-- Multiplication --------------------------------------------------------------

-- | /_padic_poly_mul/ /rop/ /rval/ /N/ /op1/ /val1/ /len1/ /op2/ /val2/ /len2/ /ctx/ 
-- 
-- Sets @(rop, *rval, len1 + len2 - 1)@ to the product of
-- @(op1, val1, len1)@ and @(op2, val2, len2)@.
-- 
-- Assumes that the resulting valuation @*rval@, which is the sum of the
-- valuations @val1@ and @val2@, is less than the precision~\`N\` of the
-- context.
-- 
-- Assumes that @len1 >= len2 > 0@.
foreign import ccall "padic_poly.h _padic_poly_mul"
  _padic_poly_mul :: Ptr CFmpz -> Ptr CLong -> CLong -> Ptr CFmpz -> CLong -> CLong -> Ptr CFmpz -> CLong -> CLong -> Ptr CPadicCtx -> IO ()

-- | /padic_poly_mul/ /res/ /poly1/ /poly2/ /ctx/ 
-- 
-- Sets the polynomial @res@ to the product of the two polynomials @poly1@
-- and @poly2@, reduced modulo \(p^N\).
foreign import ccall "padic_poly.h padic_poly_mul"
  padic_poly_mul :: Ptr CPadicPoly -> Ptr CPadicPoly -> Ptr CPadicPoly -> Ptr CPadicCtx -> IO ()

-- Powering --------------------------------------------------------------------

-- | /_padic_poly_pow/ /rop/ /rval/ /N/ /op/ /val/ /len/ /e/ /ctx/ 
-- 
-- Sets the polynomial @(rop, *rval, e (len - 1) + 1)@ to the polynomial
-- @(op, val, len)@ raised to the power~\`e\`.
-- 
-- Assumes that \(e > 1\) and @len > 0@.
-- 
-- Does not support aliasing between the input and output arguments.
foreign import ccall "padic_poly.h _padic_poly_pow"
  _padic_poly_pow :: Ptr CFmpz -> Ptr CLong -> CLong -> Ptr CFmpz -> CLong -> CLong -> CULong -> Ptr CPadicCtx -> IO ()

-- | /padic_poly_pow/ /rop/ /op/ /e/ /ctx/ 
-- 
-- Sets the polynomial @rop@ to the polynomial @op@ raised to the
-- power~\`e\`, reduced to the precision in @rop@.
-- 
-- In the special case \(e = 0\), sets @rop@ to the constant polynomial one
-- reduced to the precision of @rop@. Also note that when \(e = 1\), this
-- operation sets @rop@ to @op@ and then reduces @rop@.
-- 
-- When the valuation of the input polynomial is negative, this results in
-- a loss of \(p\)-adic precision. Suppose that the input polynomial is
-- given to precision~\`N\` and has valuation~\`v \< 0\`. The result then
-- has valuation \(e v < 0\) but is only correct to precision
-- \(N + (e - 1) v\).
foreign import ccall "padic_poly.h padic_poly_pow"
  padic_poly_pow :: Ptr CPadicPoly -> Ptr CPadicPoly -> CULong -> Ptr CPadicCtx -> IO ()

-- Series inversion ------------------------------------------------------------

-- | /padic_poly_inv_series/ /g/ /f/ /n/ /ctx/ 
-- 
-- Computes the power series inverse \(g\) of \(f\) modulo \(X^n\), where
-- \(n \geq 1\).
-- 
-- Given the polynomial \(f \in \mathbf{Q}[X] \subset \mathbf{Q}_p[X]\),
-- there exists a unique polynomial \(f^{-1} \in \mathbf{Q}[X]\) such that
-- \(f f^{-1} = 1\) modulo \(X^n\). This function sets \(g\) to \(f^{-1}\)
-- reduced modulo \(p^N\).
-- 
-- Assumes that the constant coefficient of \(f\) is non-zero.
-- 
-- Moreover, assumes that the valuation of the constant coefficient of
-- \(f\) is minimal among the coefficients of \(f\).
-- 
-- Note that the result \(g\) is zero if and only if
-- \(- \operatorname{ord}_p(f) \geq N\).
foreign import ccall "padic_poly.h padic_poly_inv_series"
  padic_poly_inv_series :: Ptr CPadicPoly -> Ptr CPadicPoly -> CLong -> Ptr CPadicCtx -> IO ()

-- Derivative ------------------------------------------------------------------

-- | /_padic_poly_derivative/ /rop/ /rval/ /N/ /op/ /val/ /len/ /ctx/ 
-- 
-- Sets @(rop, rval)@ to the derivative of @(op, val)@ reduced modulo
-- \(p^N\).
-- 
-- Supports aliasing of the input and the output parameters.
foreign import ccall "padic_poly.h _padic_poly_derivative"
  _padic_poly_derivative :: Ptr CFmpz -> Ptr CLong -> CLong -> Ptr CFmpz -> CLong -> CLong -> Ptr CPadicCtx -> IO ()

-- | /padic_poly_derivative/ /rop/ /op/ /ctx/ 
-- 
-- Sets @rop@ to the derivative of @op@, reducing the result modulo the
-- precision of @rop@.
foreign import ccall "padic_poly.h padic_poly_derivative"
  padic_poly_derivative :: Ptr CPadicPoly -> Ptr CPadicPoly -> Ptr CPadicCtx -> IO ()

-- Shifting --------------------------------------------------------------------

-- | /padic_poly_shift_left/ /rop/ /op/ /n/ /ctx/ 
-- 
-- Notationally, sets the polynomial @rop@ to the polynomial @op@
-- multiplied by \(x^n\), where \(n \geq 0\), and reduces the result.
foreign import ccall "padic_poly.h padic_poly_shift_left"
  padic_poly_shift_left :: Ptr CPadicPoly -> Ptr CPadicPoly -> CLong -> Ptr CPadicCtx -> IO ()

-- | /padic_poly_shift_right/ /rop/ /op/ /n/ 
-- 
-- Notationally, sets the polynomial @rop@ to the polynomial @op@ after
-- floor division by \(x^n\), where \(n \geq 0\), ensuring the result is
-- reduced.
foreign import ccall "padic_poly.h padic_poly_shift_right"
  padic_poly_shift_right :: Ptr CPadicPoly -> Ptr CPadicPoly -> CLong -> IO ()

-- Evaluation ------------------------------------------------------------------

foreign import ccall "padic_poly.h _padic_poly_evaluate_padic"
  _padic_poly_evaluate_padic :: Ptr CFmpz -> Ptr CLong -> CLong -> Ptr CFmpz -> CLong -> CLong -> Ptr CFmpz -> CLong -> Ptr CPadicCtx -> IO ()

-- | /_padic_poly_evaluate_padic/ /u/ /v/ /N/ /poly/ /val/ /len/ /a/ /b/ /ctx/ 
-- 
-- Sets the \(p\)-adic number @y@ to @poly@ evaluated at \(a\), reduced in
-- the given context.
-- 
-- Suppose that the polynomial can be written as \(F(X) = p^w f(X)\) with
-- \(\operatorname{ord}_p(f) = 1\), that \(\operatorname{ord}_p(a) = b\)
-- and that both are defined to precision~\`N\`. Then \(f\) is defined to
-- precision \(N-w\) and so \(f(a)\) is defined to precision \(N-w\) when
-- \(a\) is integral and \(N-w+(n-1)b\) when \(b < 0\), where
-- \(n = \deg(f)\). Thus, \(y = F(a)\) is defined to precision \(N\) when
-- \(a\) is integral and \(N+(n-1)b\) when \(b < 0\).

foreign import ccall "flint/padic_poly.h padic_poly_evaluate_padic"
  padic_poly_evaluate_padic :: Ptr CPadic -> Ptr CPadicPoly -> Ptr CPadic -> Ptr CPadicCtx -> IO ()

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

-- | /_padic_poly_compose/ /rop/ /rval/ /N/ /op1/ /val1/ /len1/ /op2/ /val2/ /len2/ /ctx/ 
-- 
-- Sets @(rop, *rval, (len1-1)*(len2-1)+1)@ to the composition of the two
-- input polynomials, reducing the result modulo \(p^N\).
-- 
-- Assumes that @len1@ is non-zero.
-- 
-- Does not support aliasing.
foreign import ccall "padic_poly.h _padic_poly_compose"
  _padic_poly_compose :: Ptr CFmpz -> Ptr CLong -> CLong -> Ptr CFmpz -> CLong -> CLong -> Ptr CFmpz -> CLong -> CLong -> Ptr CPadicCtx -> IO ()

-- | /padic_poly_compose/ /rop/ /op1/ /op2/ /ctx/ 
-- 
-- Sets @rop@ to the composition of @op1@ and @op2@, reducing the result in
-- the given context.
-- 
-- To be clear about the order of composition, let \(f(X)\) and \(g(X)\)
-- denote the polynomials @op1@ and @op2@, respectively. Then @rop@ is set
-- to \(f(g(X))\).
foreign import ccall "padic_poly.h padic_poly_compose"
  padic_poly_compose :: Ptr CPadicPoly -> Ptr CPadicPoly -> Ptr CPadicPoly -> Ptr CPadicCtx -> IO ()

-- | /_padic_poly_compose_pow/ /rop/ /rval/ /N/ /op/ /val/ /len/ /k/ /ctx/ 
-- 
-- Sets @(rop, *rval, (len - 1)*k + 1)@ to the composition of
-- @(op, val, len)@ and the monomial \(x^k\), where \(k \geq 1\).
-- 
-- Assumes that @len@ is positive.
-- 
-- Supports aliasing between the input and output polynomials.
foreign import ccall "padic_poly.h _padic_poly_compose_pow"
  _padic_poly_compose_pow :: Ptr CFmpz -> Ptr CLong -> CLong -> Ptr CFmpz -> CLong -> CLong -> CLong -> Ptr CPadicCtx -> IO ()

-- | /padic_poly_compose_pow/ /rop/ /op/ /k/ /ctx/ 
-- 
-- Sets @rop@ to the composition of @op@ and the monomial \(x^k\), where
-- \(k \geq 1\).
-- 
-- Note that no reduction takes place.
foreign import ccall "padic_poly.h padic_poly_compose_pow"
  padic_poly_compose_pow :: Ptr CPadicPoly -> Ptr CPadicPoly -> CLong -> Ptr CPadicCtx -> IO ()

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

-- | /padic_poly_debug/ /poly/ 
-- 
-- Prints the data defining the \(p\)-adic polynomial @poly@ in a simple
-- format useful for debugging purposes.
-- 
-- In the current implementation, always returns \(1\).
foreign import ccall "padic_poly.h padic_poly_debug"
  padic_poly_debug :: Ptr CPadicPoly -> IO CInt

-- | /_padic_poly_fprint/ /file/ /poly/ /val/ /len/ /ctx/ 
-- 
-- Prints a simple representation of the polynomial @poly@ to the stream
-- @file@.
-- 
-- A non-zero polynomial is represented by the number of coefficients, two
-- spaces, followed by a list of the coefficients, which are printed in a
-- way depending on the print mode,
-- 
-- In the @PADIC_TERSE@ mode, the coefficients are printed as rational
-- numbers.
-- 
-- The @PADIC_SERIES@ mode is currently not supported and will raise an
-- abort signal.
-- 
-- In the @PADIC_VAL_UNIT@ mode, the coefficients are printed in the form
-- \(p^v u\).
-- 
-- The zero polynomial is represented by @\"0\"@.
-- 
-- In the current implementation, always returns \(1\).
foreign import ccall "padic_poly.h _padic_poly_fprint"
  _padic_poly_fprint :: Ptr CFile -> Ptr CFmpz -> CLong -> CLong -> Ptr CPadicCtx -> IO CInt

foreign import ccall "flint/padic_poly.h padic_poly_fprint"
  padic_poly_fprint :: Ptr CFile -> Ptr CPadicPoly -> Ptr CPadicCtx -> IO CInt

-- | /_padic_poly_print/ /poly/ /val/ /len/ /ctx/ 
-- 
-- Prints a simple representation of the polynomial @poly@ to @stdout@.
-- 
-- In the current implementation, always returns \(1\).
foreign import ccall "padic_poly.h _padic_poly_print"
  _padic_poly_print :: Ptr CFmpz -> CLong -> CLong -> Ptr CPadicCtx -> IO CInt

padic_poly_print :: Ptr CPadicPoly -> Ptr CPadicCtx -> IO CInt
padic_poly_print :: Ptr CPadicPoly -> Ptr CPadicCtx -> IO CInt
padic_poly_print Ptr CPadicPoly
poly Ptr CPadicCtx
ctx = do
  CString
cs <- CString -> Ptr CPadicPoly -> Ptr CPadicCtx -> IO CString
padic_poly_get_str CString
forall a. Ptr a
nullPtr Ptr CPadicPoly
poly Ptr CPadicCtx
ctx
  String
s <- CString -> IO String
peekCString CString
cs
  CString -> IO ()
forall a. Ptr a -> IO ()
free CString
cs
  String -> IO ()
putStr String
s
  CInt -> IO CInt
forall a. a -> IO a
forall (m :: * -> *) a. Monad m => a -> m a
return (CInt
1 :: CInt)

foreign import ccall "padic_poly.h _padic_poly_fprint_pretty"
  _padic_poly_fprint_pretty :: Ptr CFile -> Ptr CFmpz -> CLong -> CLong -> CString -> Ptr CPadicCtx -> IO CInt

foreign import ccall "flint/padic_poly.h _padic_poly_print_pretty"
  _padic_poly_print_pretty :: Ptr CFmpz -> CLong -> CLong -> CString -> Ptr CPadicCtx -> IO CInt

foreign import ccall "flint/padic_poly.h padic_poly_fprint_pretty"
  padic_poly_fprint_pretty :: Ptr CFile -> Ptr CPadicPoly -> CString -> Ptr CPadicCtx -> IO CInt

padic_poly_print_pretty :: Ptr CPadicPoly -> CString -> Ptr CPadicCtx -> IO CInt
padic_poly_print_pretty :: Ptr CPadicPoly -> CString -> Ptr CPadicCtx -> IO CInt
padic_poly_print_pretty  Ptr CPadicPoly
poly CString
var Ptr CPadicCtx
ctx = do
  CString
cs <- Ptr CPadicPoly -> CString -> Ptr CPadicCtx -> IO CString
padic_poly_get_str_pretty Ptr CPadicPoly
poly CString
var Ptr CPadicCtx
ctx
  String
s <- CString -> IO String
peekCString CString
cs
  CString -> IO ()
forall a. Ptr a -> IO ()
free CString
cs
  String -> IO ()
putStr String
s
  CInt -> IO CInt
forall a. a -> IO a
forall (m :: * -> *) a. Monad m => a -> m a
return (CInt
1 :: CInt)


foreign import ccall "padic_poly_get_str"
  padic_poly_get_str :: CString -> Ptr CPadicPoly -> Ptr CPadicCtx -> IO CString
  
foreign import ccall "padic_poly_get_str_pretty"
  padic_poly_get_str_pretty :: Ptr CPadicPoly -> CString -> Ptr CPadicCtx -> IO CString

-- Testing ---------------------------------------------------------------------

foreign import ccall "padic_poly.h _padic_poly_is_canonical"
  _padic_poly_is_canonical :: Ptr CFmpz -> CLong -> CLong -> Ptr CPadicCtx -> IO CInt

foreign import ccall "flint/padic_poly.h padic_poly_is_canonical"
 padic_poly_is_canonical :: Ptr CPadicPoly -> Ptr CPadicCtx -> IO CInt 

foreign import ccall "flint/padic_poly.h _padic_poly_is_reduced"
  _padic_poly_is_reduced :: Ptr CFmpz -> CLong -> CLong -> Ptr CPadicCtx -> IO CInt

foreign import ccall "flint/padic_poly.h padic_poly_is_reduced"
 padic_poly_is_reduced :: Ptr CPadicPoly -> Ptr CPadicCtx -> IO CInt