{-# LINE 1 "src/Data/Number/Flint/NMod/MPoly/Factor/FFI.hsc" #-}
{-|
module      :  Data.Number.Flint.NMod.MPoly.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.NMod.MPoly.Factor.FFI (
  -- * Factorisation of multivariate polynomials over integers mod n
  -- (word-size n)
    NModMPolyFactor (..)
  , CNModMPolyFactor (..)
  , newNModMPolyFactor
  , withNModMPolyFactor
  -- * Memory managment
  , nmod_mpoly_factor_init
  , nmod_mpoly_factor_clear
  -- * Basic manipulation
  , nmod_mpoly_factor_swap
  , nmod_mpoly_factor_length
  , nmod_mpoly_factor_get_constant_ui
  , nmod_mpoly_factor_get_base
  , nmod_mpoly_factor_swap_base
  , nmod_mpoly_factor_get_exp_si
  , nmod_mpoly_factor_sort
  -- * Factorisation
  , nmod_mpoly_factor_squarefree
  , nmod_mpoly_factor
) where 

-- Factorisation of multivariate polynomials over integers mod n (word-size n) -

import Control.Monad

import Foreign.C.String
import Foreign.C.Types
import Foreign.ForeignPtr
import Foreign.Ptr ( Ptr, FunPtr, nullPtr, 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.MPoly
import Data.Number.Flint.NMod
import Data.Number.Flint.NMod.Types
import Data.Number.Flint.NMod.MPoly






-- Types -----------------------------------------------------------------------

data NModMPolyFactor =
  NModMPolyFactor {-# UNPACK #-} !(ForeignPtr CNModMPolyFactor)
data CNModMPolyFactor =
  CNModMPolyFactor CMpLimb (Ptr CNModMPoly)
                   (Ptr CFmpz) CLong CLong

instance Storable CNModMPolyFactor where
  {-# INLINE sizeOf #-}
  sizeOf :: CNModMPolyFactor -> Int
sizeOf CNModMPolyFactor
_ = (Int
40)
{-# LINE 65 "src/Data/Number/Flint/NMod/MPoly/Factor/FFI.hsc" #-}
  {-# INLINE alignment #-}
  alignment :: CNModMPolyFactor -> Int
alignment CNModMPolyFactor
_ = Int
8
{-# LINE 67 "src/Data/Number/Flint/NMod/MPoly/Factor/FFI.hsc" #-}
  peek ptr = CNModMPolyFactor
    <$> (\hsc_ptr -> peekByteOff hsc_ptr 0) ptr
{-# LINE 69 "src/Data/Number/Flint/NMod/MPoly/Factor/FFI.hsc" #-}
    <*> (\hsc_ptr -> peekByteOff hsc_ptr 8) ptr
{-# LINE 70 "src/Data/Number/Flint/NMod/MPoly/Factor/FFI.hsc" #-}
    <*> (\hsc_ptr -> peekByteOff hsc_ptr 16) ptr
{-# LINE 71 "src/Data/Number/Flint/NMod/MPoly/Factor/FFI.hsc" #-}
    <*> (\hsc_ptr -> peekByteOff hsc_ptr 24) ptr
{-# LINE 72 "src/Data/Number/Flint/NMod/MPoly/Factor/FFI.hsc" #-}
    <*> (\hsc_ptr -> peekByteOff hsc_ptr 32) ptr
{-# LINE 73 "src/Data/Number/Flint/NMod/MPoly/Factor/FFI.hsc" #-}
  poke = error "CNModMPolyFactor.poke: Not defined"

newNModMPolyFactor :: NModMPolyCtx -> IO NModMPolyFactor
newNModMPolyFactor ctx :: NModMPolyCtx
ctx@(NModMPolyCtx ForeignPtr CNModMPolyCtx
pctx) = do
  ForeignPtr CNModMPolyFactor
x <- IO (ForeignPtr CNModMPolyFactor)
forall a. Storable a => IO (ForeignPtr a)
mallocForeignPtr
  ForeignPtr CNModMPolyFactor
-> (Ptr CNModMPolyFactor -> IO (NModMPolyCtx, ()))
-> IO (NModMPolyCtx, ())
forall a b. ForeignPtr a -> (Ptr a -> IO b) -> IO b
withForeignPtr ForeignPtr CNModMPolyFactor
x ((Ptr CNModMPolyFactor -> IO (NModMPolyCtx, ()))
 -> IO (NModMPolyCtx, ()))
-> (Ptr CNModMPolyFactor -> IO (NModMPolyCtx, ()))
-> IO (NModMPolyCtx, ())
forall a b. (a -> b) -> a -> b
$ \Ptr CNModMPolyFactor
x -> do
    NModMPolyCtx
-> (Ptr CNModMPolyCtx -> IO ()) -> IO (NModMPolyCtx, ())
forall {a}.
NModMPolyCtx -> (Ptr CNModMPolyCtx -> IO a) -> IO (NModMPolyCtx, a)
withNModMPolyCtx NModMPolyCtx
ctx ((Ptr CNModMPolyCtx -> IO ()) -> IO (NModMPolyCtx, ()))
-> (Ptr CNModMPolyCtx -> IO ()) -> IO (NModMPolyCtx, ())
forall a b. (a -> b) -> a -> b
$ \Ptr CNModMPolyCtx
ctx -> do
      Ptr CNModMPolyFactor -> Ptr CNModMPolyCtx -> IO ()
nmod_mpoly_factor_init Ptr CNModMPolyFactor
x Ptr CNModMPolyCtx
ctx
      FinalizerEnvPtr CNModMPolyFactor CNModMPolyCtx
-> Ptr CNModMPolyFactor -> ForeignPtr CNModMPolyCtx -> IO ()
forall env a.
FinalizerEnvPtr env a -> Ptr env -> ForeignPtr a -> IO ()
addForeignPtrFinalizerEnv FinalizerEnvPtr CNModMPolyFactor CNModMPolyCtx
p_nmod_mpoly_factor_clear Ptr CNModMPolyFactor
x ForeignPtr CNModMPolyCtx
pctx
  NModMPolyFactor -> IO NModMPolyFactor
forall a. a -> IO a
forall (m :: * -> *) a. Monad m => a -> m a
return (NModMPolyFactor -> IO NModMPolyFactor)
-> NModMPolyFactor -> IO NModMPolyFactor
forall a b. (a -> b) -> a -> b
$ ForeignPtr CNModMPolyFactor -> NModMPolyFactor
NModMPolyFactor ForeignPtr CNModMPolyFactor
x

withNModMPolyFactor :: NModMPolyFactor
-> (Ptr CNModMPolyFactor -> IO a) -> IO (NModMPolyFactor, a)
withNModMPolyFactor (NModMPolyFactor ForeignPtr CNModMPolyFactor
p) Ptr CNModMPolyFactor -> IO a
f = do
  ForeignPtr CNModMPolyFactor
-> (Ptr CNModMPolyFactor -> IO (NModMPolyFactor, a))
-> IO (NModMPolyFactor, a)
forall a b. ForeignPtr a -> (Ptr a -> IO b) -> IO b
withForeignPtr ForeignPtr CNModMPolyFactor
p ((Ptr CNModMPolyFactor -> IO (NModMPolyFactor, a))
 -> IO (NModMPolyFactor, a))
-> (Ptr CNModMPolyFactor -> IO (NModMPolyFactor, a))
-> IO (NModMPolyFactor, a)
forall a b. (a -> b) -> a -> b
$ \Ptr CNModMPolyFactor
fp -> Ptr CNModMPolyFactor -> IO a
f Ptr CNModMPolyFactor
fp IO a -> (a -> IO (NModMPolyFactor, a)) -> IO (NModMPolyFactor, a)
forall a b. IO a -> (a -> IO b) -> IO b
forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
>>= (NModMPolyFactor, a) -> IO (NModMPolyFactor, a)
forall a. a -> IO a
forall (m :: * -> *) a. Monad m => a -> m a
return ((NModMPolyFactor, a) -> IO (NModMPolyFactor, a))
-> (a -> (NModMPolyFactor, a)) -> a -> IO (NModMPolyFactor, a)
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (ForeignPtr CNModMPolyFactor -> NModMPolyFactor
NModMPolyFactor ForeignPtr CNModMPolyFactor
p,)
  
-- Memory management -----------------------------------------------------------

-- | /nmod_mpoly_factor_init/ /f/ /ctx/ 
--
-- Initialise /f/.
foreign import ccall "nmod_mpoly_factor.h nmod_mpoly_factor_init"
  nmod_mpoly_factor_init :: Ptr CNModMPolyFactor -> Ptr CNModMPolyCtx -> IO ()

-- | /nmod_mpoly_factor_clear/ /f/ /ctx/ 
--
-- Clear /f/.
foreign import ccall "nmod_mpoly_factor.h nmod_mpoly_factor_clear"
  nmod_mpoly_factor_clear :: Ptr CNModMPolyFactor -> Ptr CNModMPolyCtx -> IO ()

foreign import ccall "nmod_mpoly_factor.h &nmod_mpoly_factor_clear"
  p_nmod_mpoly_factor_clear :: FunPtr (Ptr CNModMPolyFactor -> Ptr CNModMPolyCtx -> IO ())

-- Basic manipulation ----------------------------------------------------------

-- | /nmod_mpoly_factor_swap/ /f/ /g/ /ctx/ 
--
-- Efficiently swap /f/ and /g/.
foreign import ccall "nmod_mpoly_factor.h nmod_mpoly_factor_swap"
  nmod_mpoly_factor_swap :: Ptr CNModMPolyFactor -> Ptr CNModMPolyFactor -> Ptr CNModMPolyCtx -> IO ()

-- | /nmod_mpoly_factor_length/ /f/ /ctx/ 
--
-- Return the length of the product in /f/.
foreign import ccall "nmod_mpoly_factor.h nmod_mpoly_factor_length"
  nmod_mpoly_factor_length :: Ptr CNModMPolyFactor -> Ptr CNModMPolyCtx -> IO CLong

-- | /nmod_mpoly_factor_get_constant_ui/ /f/ /ctx/ 
--
-- Return the constant of /f/.
foreign import ccall "nmod_mpoly_factor.h nmod_mpoly_factor_get_constant_ui"
  nmod_mpoly_factor_get_constant_ui :: Ptr CNModMPolyFactor -> Ptr CNModMPolyCtx -> IO ()

-- | /nmod_mpoly_factor_get_base/ /p/ /f/ /i/ /ctx/ 
foreign import ccall "nmod_mpoly_factor.h nmod_mpoly_factor_get_base"
  nmod_mpoly_factor_get_base :: Ptr CNModMPoly -> Ptr CNModMPolyFactor -> CLong -> Ptr CNModMPolyCtx -> IO ()
-- | /nmod_mpoly_factor_swap_base/ /p/ /f/ /i/ /ctx/ 
--
-- Set (resp. swap) /B/ to (resp. with) the base of the term of index \(i\)
-- in /A/.
foreign import ccall "nmod_mpoly_factor.h nmod_mpoly_factor_swap_base"
  nmod_mpoly_factor_swap_base :: Ptr CNModMPoly -> Ptr CNModMPolyFactor -> CLong -> Ptr CNModMPolyCtx -> IO ()

-- | /nmod_mpoly_factor_get_exp_si/ /f/ /i/ /ctx/ 
--
-- Return the exponent of the term of index \(i\) in /A/. It is assumed to
-- fit an @slong@.
foreign import ccall "nmod_mpoly_factor.h nmod_mpoly_factor_get_exp_si"
  nmod_mpoly_factor_get_exp_si :: Ptr CNModMPolyFactor -> CLong -> Ptr CNModMPolyCtx -> IO CLong

-- | /nmod_mpoly_factor_sort/ /f/ /ctx/ 
--
-- Sort the product of /f/ first by exponent and then by base.
foreign import ccall "nmod_mpoly_factor.h nmod_mpoly_factor_sort"
  nmod_mpoly_factor_sort :: Ptr CNModMPolyFactor -> Ptr CNModMPolyCtx -> IO ()

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

-- | /nmod_mpoly_factor_squarefree/ /f/ /A/ /ctx/ 
--
-- Set /f/ to a factorization of /A/ where the bases are primitive and
-- pairwise relatively prime. If the product of all irreducible factors
-- with a given exponent is desired, it is recommended to call
-- @nmod_mpoly_factor_sort@ and then multiply the bases with the desired
-- exponent.
foreign import ccall "nmod_mpoly_factor.h nmod_mpoly_factor_squarefree"
  nmod_mpoly_factor_squarefree :: Ptr CNModMPolyFactor -> Ptr CNModMPoly -> Ptr CNModMPolyCtx -> IO CInt

-- | /nmod_mpoly_factor/ /f/ /A/ /ctx/ 
--
-- Set /f/ to a factorization of /A/ where the bases are irreducible.
foreign import ccall "nmod_mpoly_factor.h nmod_mpoly_factor"
  nmod_mpoly_factor :: Ptr CNModMPolyFactor -> Ptr CNModMPoly -> Ptr CNModMPolyCtx -> IO CInt