Flint2-0.1.0.0: src/Data/Number/Flint/Fq/Poly/Factor/FFI.hsc
{-|
module : Data.Number.Flint.Fq.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.Poly.Factor.FFI (
-- * Factorisation of univariate polynomials over finite fields
FqPolyFactor (..)
, CFqPolyFactor (..)
, newFqPolyFactor
, withFqPolyFactor
, withNewFqPolyFactor
-- * Memory Management
, fq_poly_factor_init
, fq_poly_factor_clear
, fq_poly_factor_realloc
, fq_poly_factor_fit_length
-- * Basic Operations
, fq_poly_factor_set
, fq_poly_factor_print_pretty
, fq_poly_factor_print
, fq_poly_factor_insert
, fq_poly_factor_concat
, fq_poly_factor_pow
, fq_poly_remove
-- * Irreducibility Testing
, fq_poly_is_irreducible
, fq_poly_is_irreducible_ddf
, fq_poly_is_irreducible_ben_or
, _fq_poly_is_squarefree
, fq_poly_is_squarefree
-- * Factorisation
, fq_poly_factor_equal_deg_prob
, fq_poly_factor_equal_deg
, fq_poly_factor_split_single
, fq_poly_factor_distinct_deg
, fq_poly_factor_squarefree
, fq_poly_factor
, fq_poly_factor_cantor_zassenhaus
, fq_poly_factor_kaltofen_shoup
, fq_poly_factor_berlekamp
, fq_poly_factor_with_berlekamp
, fq_poly_factor_with_cantor_zassenhaus
, fq_poly_factor_with_kaltofen_shoup
, fq_poly_iterated_frobenius_preinv
-- * Root Finding
, fq_poly_roots
) where
-- Factorisation of univariate polynomials over finite fields ------------------
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.Storable
import Foreign.Marshal ( free )
import Foreign.Marshal.Array ( advancePtr )
import Data.Number.Flint.Flint
import Data.Number.Flint.Fmpz
import Data.Number.Flint.Fmpz.Mod.Poly
import Data.Number.Flint.Fmpz.Mod.Mat
import Data.Number.Flint.Fmpq
import Data.Number.Flint.Fq
import Data.Number.Flint.Fq.Poly
#include <flint/flint.h>
#include <flint/fmpz.h>
#include <flint/fmpz_poly.h>
#include <flint/fq.h>
#include <flint/fq_poly.h>
-- fq_poly_factor_t ------------------------------------------------------------
data FqPolyFactor = FqPolyFactor {-# UNPACK #-} !(ForeignPtr CFqPolyFactor)
data CFqPolyFactor = CFqPolyFactor (Ptr CFqPoly) (Ptr CLong) CLong CLong
instance Storable CFqPolyFactor where
{-# INLINE sizeOf #-}
sizeOf _ = #{size fq_poly_factor_t}
{-# INLINE alignment #-}
alignment _ = #{alignment fq_poly_factor_t}
peek ptr = do
poly <- #{peek fq_poly_factor_struct, poly } ptr
exp <- #{peek fq_poly_factor_struct, exp } ptr
num <- #{peek fq_poly_factor_struct, num } ptr
alloc <- #{peek fq_poly_factor_struct, alloc } ptr
return $ CFqPolyFactor poly exp num alloc
poke = undefined
newFqPolyFactor ctx@(FqCtx fctx) = do
x <- mallocForeignPtr
withForeignPtr x $ \x -> do
withFqCtx ctx $ \ctx -> do
fq_poly_factor_init x ctx
addForeignPtrFinalizerEnv p_fq_poly_factor_clear x fctx
return $ FqPolyFactor x
{-# INLINE withFqPolyFactor #-}
withFqPolyFactor (FqPolyFactor x) f = do
withForeignPtr x $ \px -> f px >>= return . (FqPolyFactor x,)
{-# INLINE withNewFqPolyFactor #-}
withNewFqPolyFactor ctx f = do
x <- newFqPolyFactor ctx
withFqPolyFactor x f
-- Memory Management -----------------------------------------------------------
-- | /fq_poly_factor_init/ /fac/ /ctx/
--
-- Initialises @fac@ for use. An @fq_poly_factor_t@ represents a polynomial
-- in factorised form as a product of polynomials with associated
-- exponents.
foreign import ccall "fq_poly_factor.h fq_poly_factor_init"
fq_poly_factor_init :: Ptr CFqPolyFactor -> Ptr CFqCtx -> IO ()
-- | /fq_poly_factor_clear/ /fac/ /ctx/
--
-- Frees all memory associated with @fac@.
foreign import ccall "fq_poly_factor.h fq_poly_factor_clear"
fq_poly_factor_clear :: Ptr CFqPolyFactor -> Ptr CFqCtx -> IO ()
foreign import ccall "fq_poly_factor.h &fq_poly_factor_clear"
p_fq_poly_factor_clear :: FunPtr (Ptr CFqPolyFactor -> Ptr CFqCtx -> IO ())
-- | /fq_poly_factor_realloc/ /fac/ /alloc/ /ctx/
--
-- Reallocates the factor structure to provide space for precisely @alloc@
-- factors.
foreign import ccall "fq_poly_factor.h fq_poly_factor_realloc"
fq_poly_factor_realloc :: Ptr CFqPolyFactor -> CLong -> Ptr CFqCtx -> IO ()
-- | /fq_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_poly_factor.h fq_poly_factor_fit_length"
fq_poly_factor_fit_length :: Ptr CFqPolyFactor -> CLong -> Ptr CFqCtx -> IO ()
-- Basic Operations ------------------------------------------------------------
-- | /fq_poly_factor_set/ /res/ /fac/ /ctx/
--
-- Sets @res@ to the same factorisation as @fac@.
foreign import ccall "fq_poly_factor.h fq_poly_factor_set"
fq_poly_factor_set :: Ptr CFqPolyFactor -> Ptr CFqPolyFactor -> Ptr CFqCtx -> IO ()
-- | /fq_poly_factor_print_pretty/ /fac/ /var/ /ctx/
--
-- Pretty-prints the entries of @fac@ to standard output.
fq_poly_factor_print_pretty fac var ctx = do
CFqPolyFactor poly exp num alloc <- peek fac
forM_ [0..fromIntegral num-1] $ \j -> do
fq_poly_print_pretty (poly `advancePtr` j) var ctx
m <- peek (exp `advancePtr` j)
putStrLn $ " ^ " ++ show m
-- | /fq_poly_factor_print/ /fac/ /ctx/
--
-- Prints the entries of @fac@ to standard output.
fq_poly_factor_print fac ctx = do
CFqPolyFactor poly exp num alloc <- peek fac
forM_ [0..fromIntegral num-1] $ \j -> do
fq_poly_print (poly `advancePtr` j) ctx
m <- peek (exp `advancePtr` j)
putStrLn $ " ^ " ++ show m
-- | /fq_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_poly_factor.h fq_poly_factor_insert"
fq_poly_factor_insert :: Ptr CFqPolyFactor -> Ptr CFqPoly -> CLong -> Ptr CFqCtx -> IO ()
-- | /fq_poly_factor_concat/ /res/ /fac/ /ctx/
--
-- Concatenates two factorisations.
--
-- This is equivalent to calling @fq_poly_factor_insert@ repeatedly with
-- the individual factors of @fac@.
--
-- Does not support aliasing between @res@ and @fac@.
foreign import ccall "fq_poly_factor.h fq_poly_factor_concat"
fq_poly_factor_concat :: Ptr CFqPolyFactor -> Ptr CFqPolyFactor -> Ptr CFqCtx -> IO ()
-- | /fq_poly_factor_pow/ /fac/ /exp/ /ctx/
--
-- Raises @fac@ to the power @exp@.
foreign import ccall "fq_poly_factor.h fq_poly_factor_pow"
fq_poly_factor_pow :: Ptr CFqPolyFactor -> CLong -> Ptr CFqCtx -> IO ()
-- | /fq_poly_remove/ /f/ /p/ /ctx/
--
-- Removes the highest possible power of @p@ from @f@ and returns the
-- exponent.
foreign import ccall "fq_poly_factor.h fq_poly_remove"
fq_poly_remove :: Ptr CFqPoly -> Ptr CFqPoly -> Ptr CFqCtx -> IO CULong
-- Irreducibility Testing ------------------------------------------------------
-- | /fq_poly_is_irreducible/ /f/ /ctx/
--
-- Returns 1 if the polynomial @f@ is irreducible, otherwise returns 0.
foreign import ccall "fq_poly_factor.h fq_poly_is_irreducible"
fq_poly_is_irreducible :: Ptr CFqPoly -> Ptr CFqCtx -> IO CInt
-- | /fq_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_poly_factor.h fq_poly_is_irreducible_ddf"
fq_poly_is_irreducible_ddf :: Ptr CFqPoly -> Ptr CFqCtx -> IO CInt
-- | /fq_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_poly_factor.h fq_poly_is_irreducible_ben_or"
fq_poly_is_irreducible_ben_or :: Ptr CFqPoly -> Ptr CFqCtx -> IO CInt
-- | /_fq_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_poly_factor.h _fq_poly_is_squarefree"
_fq_poly_is_squarefree :: Ptr (Ptr CFq) -> CLong -> Ptr CFqCtx -> IO CInt
-- | /fq_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_poly_factor.h fq_poly_is_squarefree"
fq_poly_is_squarefree :: Ptr CFqPoly -> Ptr CFqCtx -> IO CInt
-- Factorisation ---------------------------------------------------------------
-- | /fq_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_poly_factor.h fq_poly_factor_equal_deg_prob"
fq_poly_factor_equal_deg_prob :: Ptr CFqPoly -> Ptr CFRandState -> Ptr CFqPoly -> CLong -> Ptr CFqCtx -> IO CInt
-- | /fq_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_poly_factor.h fq_poly_factor_equal_deg"
fq_poly_factor_equal_deg :: Ptr CFqPolyFactor -> Ptr CFqPoly -> CLong -> Ptr CFqCtx -> IO ()
-- | /fq_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_poly_factor.h fq_poly_factor_split_single"
fq_poly_factor_split_single :: Ptr CFqPoly -> Ptr CFqPoly -> Ptr CFqCtx -> IO ()
-- | /fq_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_poly_factor.h fq_poly_factor_distinct_deg"
fq_poly_factor_distinct_deg :: Ptr CFqPolyFactor -> Ptr CFqPoly -> Ptr (Ptr CLong) -> Ptr CFqCtx -> IO ()
-- | /fq_poly_factor_squarefree/ /res/ /f/ /ctx/
--
-- Sets @res@ to a squarefree factorization of @f@.
foreign import ccall "fq_poly_factor.h fq_poly_factor_squarefree"
fq_poly_factor_squarefree :: Ptr CFqPolyFactor -> Ptr CFqPoly -> Ptr CFqCtx -> IO ()
-- | /fq_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_poly_factor.h fq_poly_factor"
fq_poly_factor :: Ptr CFqPolyFactor -> Ptr CFq -> Ptr CFqPoly -> Ptr CFqCtx -> IO ()
-- | /fq_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_poly_factor.h fq_poly_factor_cantor_zassenhaus"
fq_poly_factor_cantor_zassenhaus :: Ptr CFqPolyFactor -> Ptr CFqPoly -> Ptr CFqCtx -> IO ()
-- | /fq_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_poly_factor.h fq_poly_factor_kaltofen_shoup"
fq_poly_factor_kaltofen_shoup :: Ptr CFqPolyFactor -> Ptr CFqPoly -> Ptr CFqCtx -> IO ()
-- | /fq_poly_factor_berlekamp/ /factors/ /f/ /ctx/
--
-- Factorises a non-constant polynomial @f@ into monic irreducible factors
-- using the Berlekamp algorithm.
foreign import ccall "fq_poly_factor.h fq_poly_factor_berlekamp"
fq_poly_factor_berlekamp :: Ptr CFqPolyFactor -> Ptr CFqPoly -> Ptr CFqCtx -> IO ()
-- | /fq_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 factorisation on
-- all the individual square-free factors.
foreign import ccall "fq_poly_factor.h fq_poly_factor_with_berlekamp"
fq_poly_factor_with_berlekamp :: Ptr CFqPolyFactor -> Ptr CFq -> Ptr CFqPoly -> Ptr CFqCtx -> IO ()
-- | /fq_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_poly_factor.h fq_poly_factor_with_cantor_zassenhaus"
fq_poly_factor_with_cantor_zassenhaus :: Ptr CFqPolyFactor -> Ptr CFq -> Ptr CFqPoly -> Ptr CFqCtx -> IO ()
-- | /fq_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_poly_factor.h fq_poly_factor_with_kaltofen_shoup"
fq_poly_factor_with_kaltofen_shoup :: Ptr CFqPolyFactor -> Ptr CFq -> Ptr CFqPoly -> Ptr CFqCtx -> IO ()
-- | /fq_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_poly_factor.h fq_poly_iterated_frobenius_preinv"
fq_poly_iterated_frobenius_preinv :: Ptr (Ptr CFqPoly) -> CLong -> Ptr CFqPoly -> Ptr CFqPoly -> Ptr CFqCtx -> IO ()
-- Root Finding ----------------------------------------------------------------
-- | /fq_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_poly_factor.h fq_poly_roots"
fq_poly_roots :: Ptr CFqPolyFactor -> Ptr CFqPoly -> CInt -> Ptr CFqCtx -> IO ()