{-# LINE 1 "src/Data/Number/Flint/Fq/NMod/Poly/Factor/FFI.hsc" #-}
{-|
module      :  Data.Number.Flint.Fq.NMod.Poly.Factor.FFI
copyright   :  (c) 2022 Hartmut Monien
license     :  GNU GPL, version 2 or above (see LICENSE)
maintainer  :  hmonien@uni-bonn.de
-}
module Data.Number.Flint.Fq.NMod.Poly.Factor.FFI (
  -- * Factorisation of univariate polynomials over finite fields
  -- (word-size characteristic)
    FqNModPolyFactor (..)
  , CFqNModPolyFactor (..)
  , newFqNModPolyFactor
  , withFqNModPolyFactor
  -- * Memory Management
  , fq_nmod_poly_factor_init
  , fq_nmod_poly_factor_clear
  , fq_nmod_poly_factor_realloc
  , fq_nmod_poly_factor_fit_length
  -- * Basic Operations
  , fq_nmod_poly_factor_set
  , fq_nmod_poly_factor_print_pretty
  , fq_nmod_poly_factor_print
  , fq_nmod_poly_factor_insert
  , fq_nmod_poly_factor_concat
  , fq_nmod_poly_factor_pow
  , fq_nmod_poly_remove
  -- * Irreducibility Testing
  , fq_nmod_poly_is_irreducible
  , fq_nmod_poly_is_irreducible_ddf
  , fq_nmod_poly_is_irreducible_ben_or
  , _fq_nmod_poly_is_squarefree
  , fq_nmod_poly_is_squarefree
  -- * Factorisation
  , fq_nmod_poly_factor_equal_deg_prob
  , fq_nmod_poly_factor_equal_deg
  , fq_nmod_poly_factor_split_single
  , fq_nmod_poly_factor_distinct_deg
  , fq_nmod_poly_factor_squarefree
  , fq_nmod_poly_factor
  , fq_nmod_poly_factor_cantor_zassenhaus
  , fq_nmod_poly_factor_kaltofen_shoup
  , fq_nmod_poly_factor_berlekamp
  , fq_nmod_poly_factor_with_berlekamp
  , fq_nmod_poly_factor_with_cantor_zassenhaus
  , fq_nmod_poly_factor_with_kaltofen_shoup
  , fq_nmod_poly_iterated_frobenius_preinv
  -- * Root Finding
  , fq_nmod_poly_roots
) where 

-- Factorisation of univariate polynomials over finite fields
-- (word-size characteristic)

import Control.Monad

import Foreign.C.String
import Foreign.C.Types
import qualified Foreign.Concurrent
import Foreign.ForeignPtr
import Foreign.Ptr ( Ptr, FunPtr, plusPtr )
import Foreign.Marshal.Array ( advancePtr )
import Foreign.Storable
import Foreign.Marshal ( free )

import Data.Number.Flint.Flint

import Data.Number.Flint.Fmpz
import Data.Number.Flint.Fmpz.Mod.Poly

import Data.Number.Flint.NMod.Poly
import Data.Number.Flint.NMod.Mat

import Data.Number.Flint.Fq
import Data.Number.Flint.Fq.Types

import Data.Number.Flint.Fq.NMod
import Data.Number.Flint.Fq.NMod.Mat

import Data.Number.Flint.Fq.NMod
import Data.Number.Flint.Fq.NMod.Poly
import Data.Number.Flint.Fq.NMod.Types




-- fq_nmod_poly_factor_t -------------------------------------------------------

instance Storable CFqNModPolyFactor where
  {-# INLINE sizeOf #-}
  sizeOf :: CFqNModPolyFactor -> Int
sizeOf CFqNModPolyFactor
_ = (Int
32)
{-# LINE 91 "src/Data/Number/Flint/Fq/NMod/Poly/Factor/FFI.hsc" #-}
  {-# INLINE alignment #-}
  alignment :: CFqNModPolyFactor -> Int
alignment CFqNModPolyFactor
_ = Int
8
{-# LINE 93 "src/Data/Number/Flint/Fq/NMod/Poly/Factor/FFI.hsc" #-}
  peek ptr = CFqNModPolyFactor
    <$> (\hsc_ptr -> peekByteOff hsc_ptr 0) ptr
{-# LINE 95 "src/Data/Number/Flint/Fq/NMod/Poly/Factor/FFI.hsc" #-}
    <*> (\hsc_ptr -> peekByteOff hsc_ptr 8) ptr
{-# LINE 96 "src/Data/Number/Flint/Fq/NMod/Poly/Factor/FFI.hsc" #-}
    <*> (\hsc_ptr -> peekByteOff hsc_ptr 16) ptr
{-# LINE 97 "src/Data/Number/Flint/Fq/NMod/Poly/Factor/FFI.hsc" #-}
    <*> (\hsc_ptr -> peekByteOff hsc_ptr 24) ptr
{-# LINE 98 "src/Data/Number/Flint/Fq/NMod/Poly/Factor/FFI.hsc" #-}
  poke = undefined

newFqNModPolyFactor :: FqNModCtx -> IO FqNModPolyFactor
newFqNModPolyFactor ctx :: FqNModCtx
ctx@(FqNModCtx ForeignPtr CFqNModCtx
ftx) = do
  ForeignPtr CFqNModPolyFactor
x <- IO (ForeignPtr CFqNModPolyFactor)
forall a. Storable a => IO (ForeignPtr a)
mallocForeignPtr
  ForeignPtr CFqNModPolyFactor
-> (Ptr CFqNModPolyFactor -> IO ()) -> IO ()
forall a b. ForeignPtr a -> (Ptr a -> IO b) -> IO b
withForeignPtr ForeignPtr CFqNModPolyFactor
x ((Ptr CFqNModPolyFactor -> IO ()) -> IO ())
-> (Ptr CFqNModPolyFactor -> IO ()) -> IO ()
forall a b. (a -> b) -> a -> b
$ \Ptr CFqNModPolyFactor
x -> do
    FqNModCtx -> (Ptr CFqNModCtx -> IO ()) -> IO (FqNModCtx, ())
forall {a}.
FqNModCtx -> (Ptr CFqNModCtx -> IO a) -> IO (FqNModCtx, a)
withFqNModCtx FqNModCtx
ctx ((Ptr CFqNModCtx -> IO ()) -> IO (FqNModCtx, ()))
-> (Ptr CFqNModCtx -> IO ()) -> IO (FqNModCtx, ())
forall a b. (a -> b) -> a -> b
$ \Ptr CFqNModCtx
ctx -> do
      Ptr CFqNModPolyFactor -> Ptr CFqNModCtx -> IO ()
fq_nmod_poly_factor_init Ptr CFqNModPolyFactor
x Ptr CFqNModCtx
ctx
    FinalizerEnvPtr CFqNModPolyFactor CFqNModCtx
-> Ptr CFqNModPolyFactor -> ForeignPtr CFqNModCtx -> IO ()
forall env a.
FinalizerEnvPtr env a -> Ptr env -> ForeignPtr a -> IO ()
addForeignPtrFinalizerEnv FinalizerEnvPtr CFqNModPolyFactor CFqNModCtx
p_fq_nmod_poly_factor_clear Ptr CFqNModPolyFactor
x ForeignPtr CFqNModCtx
ftx
  FqNModPolyFactor -> IO FqNModPolyFactor
forall a. a -> IO a
forall (m :: * -> *) a. Monad m => a -> m a
return (FqNModPolyFactor -> IO FqNModPolyFactor)
-> FqNModPolyFactor -> IO FqNModPolyFactor
forall a b. (a -> b) -> a -> b
$ ForeignPtr CFqNModPolyFactor -> FqNModPolyFactor
FqNModPolyFactor ForeignPtr CFqNModPolyFactor
x

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

-- Memory Management -----------------------------------------------------------

-- | /fq_nmod_poly_factor_init/ /fac/ /ctx/ 
--
-- Initialises @fac@ for use. An @fq_nmod_poly_factor_t@ represents a
-- polynomial in factorised form as a product of polynomials with
-- associated exponents.
foreign import ccall "fq_nmod_poly_factor.h fq_nmod_poly_factor_init"
  fq_nmod_poly_factor_init :: Ptr CFqNModPolyFactor -> Ptr CFqNModCtx -> IO ()

-- | /fq_nmod_poly_factor_clear/ /fac/ /ctx/ 
--
-- Frees all memory associated with @fac@.
foreign import ccall "fq_nmod_poly_factor.h fq_nmod_poly_factor_clear"
  fq_nmod_poly_factor_clear :: Ptr CFqNModPolyFactor -> Ptr CFqNModCtx -> IO ()

foreign import ccall "fq_nmod_poly_factor.h &fq_nmod_poly_factor_clear"
  p_fq_nmod_poly_factor_clear :: FunPtr (Ptr CFqNModPolyFactor -> Ptr CFqNModCtx -> IO ())

-- | /fq_nmod_poly_factor_realloc/ /fac/ /alloc/ /ctx/ 
--
-- Reallocates the factor structure to provide space for precisely @alloc@
-- factors.
foreign import ccall "fq_nmod_poly_factor.h fq_nmod_poly_factor_realloc"
  fq_nmod_poly_factor_realloc :: Ptr CFqNModPolyFactor -> CLong -> Ptr CFqNModCtx -> IO ()

-- | /fq_nmod_poly_factor_fit_length/ /fac/ /len/ /ctx/ 
--
-- Ensures that the factor structure has space for at least @len@ factors.
-- This function takes care of the case of repeated calls by always at
-- least doubling the number of factors the structure can hold.
foreign import ccall "fq_nmod_poly_factor.h fq_nmod_poly_factor_fit_length"
  fq_nmod_poly_factor_fit_length :: Ptr CFqNModPolyFactor -> CLong -> Ptr CFqNModCtx -> IO ()

-- Basic Operations ------------------------------------------------------------

-- | /fq_nmod_poly_factor_set/ /res/ /fac/ /ctx/ 
--
-- Sets @res@ to the same factorisation as @fac@.
foreign import ccall "fq_nmod_poly_factor.h fq_nmod_poly_factor_set"
  fq_nmod_poly_factor_set :: Ptr CFqNModPolyFactor -> Ptr CFqNModPolyFactor -> Ptr CFqNModCtx -> IO ()

-- | /fq_nmod_poly_factor_print_pretty/ /fac/ /ctx/ 
--
-- Pretty-prints the entries of @fac@ to standard output.
fq_nmod_poly_factor_print_pretty :: Ptr CFqNModPolyFactor
                                 -> CString
                                 -> Ptr CFqNModCtx
                                 -> IO ()
fq_nmod_poly_factor_print_pretty :: Ptr CFqNModPolyFactor -> CString -> Ptr CFqNModCtx -> IO ()
fq_nmod_poly_factor_print_pretty Ptr CFqNModPolyFactor
fac CString
var Ptr CFqNModCtx
ctx = do
  CFqNModPolyFactor Ptr CFqNModPoly
poly Ptr CLong
exp CLong
num CLong
alloc <- Ptr CFqNModPolyFactor -> IO CFqNModPolyFactor
forall a. Storable a => Ptr a -> IO a
peek Ptr CFqNModPolyFactor
fac
  [Int] -> (Int -> IO ()) -> IO ()
forall (t :: * -> *) (m :: * -> *) a b.
(Foldable t, Monad m) =>
t a -> (a -> m b) -> m ()
forM_ [Int
0 .. CLong -> Int
forall a b. (Integral a, Num b) => a -> b
fromIntegral CLong
num Int -> Int -> Int
forall a. Num a => a -> a -> a
- Int
1] ((Int -> IO ()) -> IO ()) -> (Int -> IO ()) -> IO ()
forall a b. (a -> b) -> a -> b
$ \Int
j -> do
    Ptr CFqNModPoly -> CString -> Ptr CFqNModCtx -> IO CInt
fq_nmod_poly_print_pretty (Ptr CFqNModPoly
poly Ptr CFqNModPoly -> Int -> Ptr CFqNModPoly
forall a. Storable a => Ptr a -> Int -> Ptr a
`advancePtr` Int
j) CString
var Ptr CFqNModCtx
ctx
    String -> IO ()
putStr String
" ^ "
    CLong
e <- Ptr CLong -> IO CLong
forall a. Storable a => Ptr a -> IO a
peek (Ptr CLong
exp Ptr CLong -> Int -> Ptr CLong
forall a. Storable a => Ptr a -> Int -> Ptr a
`advancePtr` Int
j)
    String -> IO ()
putStrLn (String -> IO ()) -> String -> IO ()
forall a b. (a -> b) -> a -> b
$ CLong -> String
forall a. Show a => a -> String
show CLong
e 


-- | /fq_nmod_poly_factor_print/ /fac/ /ctx/ 
--
-- Prints the entries of @fac@ to standard output.
foreign import ccall "fq_nmod_poly_factor.h fq_nmod_poly_factor_print"
  fq_nmod_poly_factor_print :: Ptr CFqNModPolyFactor -> Ptr CFqNModCtx -> IO ()

-- | /fq_nmod_poly_factor_insert/ /fac/ /poly/ /exp/ /ctx/ 
--
-- Inserts the factor @poly@ with multiplicity @exp@ into the factorisation
-- @fac@.
-- 
-- If @fac@ already contains @poly@, then @exp@ simply gets added to the
-- exponent of the existing entry.
foreign import ccall "fq_nmod_poly_factor.h fq_nmod_poly_factor_insert"
  fq_nmod_poly_factor_insert :: Ptr CFqNModPolyFactor -> Ptr CFqNModPoly -> CLong -> Ptr CFqNModCtx -> IO ()

-- | /fq_nmod_poly_factor_concat/ /res/ /fac/ /ctx/ 
--
-- Concatenates two factorisations.
-- 
-- This is equivalent to calling @fq_nmod_poly_factor_insert@ repeatedly
-- with the individual factors of @fac@.
-- 
-- Does not support aliasing between @res@ and @fac@.
foreign import ccall "fq_nmod_poly_factor.h fq_nmod_poly_factor_concat"
  fq_nmod_poly_factor_concat :: Ptr CFqNModPolyFactor -> Ptr CFqNModPolyFactor -> Ptr CFqNModCtx -> IO ()

-- | /fq_nmod_poly_factor_pow/ /fac/ /exp/ /ctx/ 
--
-- Raises @fac@ to the power @exp@.
foreign import ccall "fq_nmod_poly_factor.h fq_nmod_poly_factor_pow"
  fq_nmod_poly_factor_pow :: Ptr CFqNModPolyFactor -> CLong -> Ptr CFqNModCtx -> IO ()

-- | /fq_nmod_poly_remove/ /f/ /p/ /ctx/ 
--
-- Removes the highest possible power of @p@ from @f@ and returns the
-- exponent.
foreign import ccall "fq_nmod_poly_factor.h fq_nmod_poly_remove"
  fq_nmod_poly_remove :: Ptr CFqNModPoly -> Ptr CFqNModPoly -> Ptr CFqNModCtx -> IO CULong

-- Irreducibility Testing ------------------------------------------------------

-- | /fq_nmod_poly_is_irreducible/ /f/ /ctx/ 
--
-- Returns 1 if the polynomial @f@ is irreducible, otherwise returns 0.
foreign import ccall "fq_nmod_poly_factor.h fq_nmod_poly_is_irreducible"
  fq_nmod_poly_is_irreducible :: Ptr CFqNModPoly -> Ptr CFqNModCtx -> IO CInt

-- | /fq_nmod_poly_is_irreducible_ddf/ /f/ /ctx/ 
--
-- Returns 1 if the polynomial @f@ is irreducible, otherwise returns 0.
-- Uses fast distinct-degree factorisation.
foreign import ccall "fq_nmod_poly_factor.h fq_nmod_poly_is_irreducible_ddf"
  fq_nmod_poly_is_irreducible_ddf :: Ptr CFqNModPoly -> Ptr CFqNModCtx -> IO CInt

-- | /fq_nmod_poly_is_irreducible_ben_or/ /f/ /ctx/ 
--
-- Returns 1 if the polynomial @f@ is irreducible, otherwise returns 0.
-- Uses Ben-Or\'s irreducibility test.
foreign import ccall "fq_nmod_poly_factor.h fq_nmod_poly_is_irreducible_ben_or"
  fq_nmod_poly_is_irreducible_ben_or :: Ptr CFqNModPoly -> Ptr CFqNModCtx -> IO CInt

-- | /_fq_nmod_poly_is_squarefree/ /f/ /len/ /ctx/ 
--
-- Returns 1 if @(f, len)@ is squarefree, and 0 otherwise. As a special
-- case, the zero polynomial is not considered squarefree. There are no
-- restrictions on the length.
foreign import ccall "fq_nmod_poly_factor.h _fq_nmod_poly_is_squarefree"
  _fq_nmod_poly_is_squarefree :: Ptr (Ptr CFqNMod) -> CLong -> Ptr CFqNModCtx -> IO CInt

-- | /fq_nmod_poly_is_squarefree/ /f/ /ctx/ 
--
-- Returns 1 if @f@ is squarefree, and 0 otherwise. As a special case, the
-- zero polynomial is not considered squarefree.
foreign import ccall "fq_nmod_poly_factor.h fq_nmod_poly_is_squarefree"
  fq_nmod_poly_is_squarefree :: Ptr CFqNModPoly -> Ptr CFqNModCtx -> IO CInt

-- Factorisation ---------------------------------------------------------------

-- | /fq_nmod_poly_factor_equal_deg_prob/ /factor/ /state/ /pol/ /d/ /ctx/ 
--
-- Probabilistic equal degree factorisation of @pol@ into irreducible
-- factors of degree @d@. If it passes, a factor is placed in factor and 1
-- is returned, otherwise 0 is returned and the value of factor is
-- undetermined.
-- 
-- Requires that @pol@ be monic, non-constant and squarefree.
foreign import ccall "fq_nmod_poly_factor.h fq_nmod_poly_factor_equal_deg_prob"
  fq_nmod_poly_factor_equal_deg_prob :: Ptr CFqNModPoly -> Ptr CFRandState -> Ptr CFqNModPoly -> CLong -> Ptr CFqNModCtx -> IO CInt

-- | /fq_nmod_poly_factor_equal_deg/ /factors/ /pol/ /d/ /ctx/ 
--
-- Assuming @pol@ is a product of irreducible factors all of degree @d@,
-- finds all those factors and places them in factors. Requires that @pol@
-- be monic, non-constant and squarefree.
foreign import ccall "fq_nmod_poly_factor.h fq_nmod_poly_factor_equal_deg"
  fq_nmod_poly_factor_equal_deg :: Ptr CFqNModPolyFactor -> Ptr CFqNModPoly -> CLong -> Ptr CFqNModCtx -> IO ()

-- | /fq_nmod_poly_factor_split_single/ /linfactor/ /input/ /ctx/ 
--
-- Assuming @input@ is a product of factors all of degree 1, finds a single
-- linear factor of @input@ and places it in @linfactor@. Requires that
-- @input@ be monic and non-constant.
foreign import ccall "fq_nmod_poly_factor.h fq_nmod_poly_factor_split_single"
  fq_nmod_poly_factor_split_single :: Ptr CFqNModPoly -> Ptr CFqNModPoly -> Ptr CFqNModCtx -> IO ()

-- | /fq_nmod_poly_factor_distinct_deg/ /res/ /poly/ /degs/ /ctx/ 
--
-- Factorises a monic non-constant squarefree polynomial @poly@ of degree
-- \(n\) into factors \(f[d]\) such that for \(1 \leq d \leq n\) \(f[d]\)
-- is the product of the monic irreducible factors of @poly@ of degree
-- \(d\). Factors are stored in @res@, associated powers of irreducible
-- polynomials are stored in @degs@ in the same order as factors.
-- 
-- Requires that @degs@ have enough space for irreducible polynomials\'
-- powers (maximum space required is \(n * sizeof(slong)\)).
foreign import ccall "fq_nmod_poly_factor.h fq_nmod_poly_factor_distinct_deg"
  fq_nmod_poly_factor_distinct_deg :: Ptr CFqNModPolyFactor -> Ptr CFqNModPoly -> Ptr (Ptr CLong) -> Ptr CFqNModCtx -> IO ()

-- | /fq_nmod_poly_factor_squarefree/ /res/ /f/ /ctx/ 
--
-- Sets @res@ to a squarefree factorization of @f@.
foreign import ccall "fq_nmod_poly_factor.h fq_nmod_poly_factor_squarefree"
  fq_nmod_poly_factor_squarefree :: Ptr CFqNModPolyFactor -> Ptr CFqNModPoly -> Ptr CFqNModCtx -> IO ()

-- | /fq_nmod_poly_factor/ /res/ /lead/ /f/ /ctx/ 
--
-- Factorises a non-constant polynomial @f@ into monic irreducible factors
-- choosing the best algorithm for given modulo and degree. The output
-- @lead@ is set to the leading coefficient of \(f\) upon return. Choice of
-- algorithm is based on heuristic measurements.
foreign import ccall "fq_nmod_poly_factor.h fq_nmod_poly_factor"
  fq_nmod_poly_factor :: Ptr CFqNModPolyFactor -> Ptr CFqNMod -> Ptr CFqNModPoly -> Ptr CFqNModCtx -> IO ()

-- | /fq_nmod_poly_factor_cantor_zassenhaus/ /res/ /f/ /ctx/ 
--
-- Factorises a non-constant polynomial @f@ into monic irreducible factors
-- using the Cantor-Zassenhaus algorithm.
foreign import ccall "fq_nmod_poly_factor.h fq_nmod_poly_factor_cantor_zassenhaus"
  fq_nmod_poly_factor_cantor_zassenhaus :: Ptr CFqNModPolyFactor -> Ptr CFqNModPoly -> Ptr CFqNModCtx -> IO ()

-- | /fq_nmod_poly_factor_kaltofen_shoup/ /res/ /poly/ /ctx/ 
--
-- Factorises a non-constant polynomial @f@ into monic irreducible factors
-- using the fast version of Cantor-Zassenhaus algorithm proposed by
-- Kaltofen and Shoup (1998). More precisely this algorithm uses a “baby
-- step\/giant step” strategy for the distinct-degree factorization step.
foreign import ccall "fq_nmod_poly_factor.h fq_nmod_poly_factor_kaltofen_shoup"
  fq_nmod_poly_factor_kaltofen_shoup :: Ptr CFqNModPolyFactor -> Ptr CFqNModPoly -> Ptr CFqNModCtx -> IO ()

-- | /fq_nmod_poly_factor_berlekamp/ /factors/ /f/ /ctx/ 
--
-- Factorises a non-constant polynomial @f@ into monic irreducible factors
-- using the Berlekamp algorithm.
foreign import ccall "fq_nmod_poly_factor.h fq_nmod_poly_factor_berlekamp"
  fq_nmod_poly_factor_berlekamp :: Ptr CFqNModPolyFactor -> Ptr CFqNModPoly -> Ptr CFqNModCtx -> IO ()

-- | /fq_nmod_poly_factor_with_berlekamp/ /res/ /leading_coeff/ /f/ /ctx/ 
--
-- Factorises a general polynomial @f@ into monic irreducible factors and
-- sets @leading_coeff@ to the leading coefficient of @f@, or 0 if @f@ is
-- the zero polynomial.
-- 
-- This function first checks for small special cases, deflates @f@ if it
-- is of the form \(p(x^m)\) for some \(m > 1\), then performs a
-- square-free factorisation, and finally runs Berlekamp on all the
-- individual square-free factors.
foreign import ccall "fq_nmod_poly_factor.h fq_nmod_poly_factor_with_berlekamp"
  fq_nmod_poly_factor_with_berlekamp :: Ptr CFqNModPolyFactor -> Ptr CFqNMod -> Ptr CFqNModPoly -> Ptr CFqNModCtx -> IO ()

-- | /fq_nmod_poly_factor_with_cantor_zassenhaus/ /res/ /leading_coeff/ /f/ /ctx/ 
--
-- Factorises a general polynomial @f@ into monic irreducible factors and
-- sets @leading_coeff@ to the leading coefficient of @f@, or 0 if @f@ is
-- the zero polynomial.
-- 
-- This function first checks for small special cases, deflates @f@ if it
-- is of the form \(p(x^m)\) for some \(m > 1\), then performs a
-- square-free factorisation, and finally runs Cantor-Zassenhaus on all the
-- individual square-free factors.
foreign import ccall "fq_nmod_poly_factor.h fq_nmod_poly_factor_with_cantor_zassenhaus"
  fq_nmod_poly_factor_with_cantor_zassenhaus :: Ptr CFqNModPolyFactor -> Ptr CFqNMod -> Ptr CFqNModPoly -> Ptr CFqNModCtx -> IO ()

-- | /fq_nmod_poly_factor_with_kaltofen_shoup/ /res/ /leading_coeff/ /f/ /ctx/ 
--
-- Factorises a general polynomial @f@ into monic irreducible factors and
-- sets @leading_coeff@ to the leading coefficient of @f@, or 0 if @f@ is
-- the zero polynomial.
-- 
-- This function first checks for small special cases, deflates @f@ if it
-- is of the form \(p(x^m)\) for some \(m > 1\), then performs a
-- square-free factorisation, and finally runs Kaltofen-Shoup on all the
-- individual square-free factors.
foreign import ccall "fq_nmod_poly_factor.h fq_nmod_poly_factor_with_kaltofen_shoup"
  fq_nmod_poly_factor_with_kaltofen_shoup :: Ptr CFqNModPolyFactor -> Ptr CFqNMod -> Ptr CFqNModPoly -> Ptr CFqNModCtx -> IO ()

-- | /fq_nmod_poly_iterated_frobenius_preinv/ /rop/ /n/ /v/ /vinv/ /ctx/ 
--
-- Sets @rop[i]@ to be \(x^{q^i} \bmod v\) for \(0 \le i < n\).
-- 
-- It is required that @vinv@ is the inverse of the reverse of @v@ mod
-- @x^lenv@.
foreign import ccall "fq_nmod_poly_factor.h fq_nmod_poly_iterated_frobenius_preinv"
  fq_nmod_poly_iterated_frobenius_preinv :: Ptr (Ptr CFqNModPoly) -> CLong -> Ptr CFqNModPoly -> Ptr CFqNModPoly -> Ptr CFqNModCtx -> IO ()

-- Root Finding ----------------------------------------------------------------

-- | /fq_nmod_poly_roots/ /r/ /f/ /with_multiplicity/ /ctx/ 
--
-- Fill \(r\) with factors of the form \(x - r_i\) where the \(r_i\) are
-- the distinct roots of a nonzero \(f\) in \(F_q\). If
-- \(with\_multiplicity\) is zero, the exponent \(e_i\) of the factor
-- \(x - r_i\) is \(1\). Otherwise, it is the largest \(e_i\) such that
-- \((x-r_i)^e_i\) divides \(f\). This function throws if \(f\) is zero,
-- but is otherwise always successful.
foreign import ccall "fq_nmod_poly_factor.h fq_nmod_poly_roots"
  fq_nmod_poly_roots :: Ptr CFqNModPolyFactor -> Ptr CFqNModPoly -> CInt -> Ptr CFqNModCtx -> IO ()