packages feed

Flint2-0.1.0.0: src/Data/Number/Flint/Fmpz/MPoly/Q/FFI.hsc

{-|
module      :  Data.Number.Flint.Fmpz.MPoly.Q.FFI
copyright   :  (c) 2022 Hartmut Monien
license     :  GNU GPL, version 2 or above (see LICENSE)
maintainer  :  hmonien@uni-bonn.de
-}
module Data.Number.Flint.Fmpz.MPoly.Q.FFI (
  -- * Multivariate rational functions over Q
  -- * Types
    FmpzMPolyQ (..)
  , CFmpzMPolyQ (..)
  , newFmpzMPolyQ
  , withFmpzMPolyQ
  , withFmpzMPolyQNumerator
  , withFmpzMPolyQDenominator
  -- * Memory management
  , fmpz_mpoly_q_init
  , fmpz_mpoly_q_clear
  -- * Assignment
  , fmpz_mpoly_q_swap
  , fmpz_mpoly_q_set
  -- * Canonicalisation
  , fmpz_mpoly_q_canonicalise
  , fmpz_mpoly_q_is_canonical
  -- * Properties
  , fmpz_mpoly_q_is_zero
  , fmpz_mpoly_q_is_one
  , fmpz_mpoly_q_used_vars
  -- * Special values
  , fmpz_mpoly_q_zero
  , fmpz_mpoly_q_one
  , fmpz_mpoly_q_gen
  -- * Input and output
  , fmpz_mpoly_q_get_str_pretty
  , fmpz_mpoly_q_fprint_pretty
  , fmpz_mpoly_q_print_pretty
  -- * Random generation
  , fmpz_mpoly_q_randtest
  -- * Comparisons
  , fmpz_mpoly_q_equal
  -- * Arithmetic
  , fmpz_mpoly_q_neg
  , fmpz_mpoly_q_add
  , fmpz_mpoly_q_sub
  , fmpz_mpoly_q_mul
  , fmpz_mpoly_q_div
  , fmpz_mpoly_q_inv
  -- * Content
  , _fmpz_mpoly_q_content
) where 

-- Multivariate rational functions over Q --------------------------------------

import System.IO.Unsafe

import Control.Monad

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

#include <flint/flint.h>
#include <flint/fmpz.h>
#include <flint/fmpz_poly.h>
#include <flint/fmpz_mpoly_q.h>

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

data FmpzMPolyQ = FmpzMPolyQ {-# UNPACK #-} !(ForeignPtr CFmpzMPolyQ)
data CFmpzMPolyQ = CFmpzMPolyQ CFmpzMPoly CFmpzMPoly

instance Storable CFmpzMPolyQ where
  {-# INLINE sizeOf #-}
  sizeOf _ = #{size fmpz_mpoly_q_t}
  {-# INLINE alignment #-}
  alignment _ = #{alignment fmpz_mpoly_q_t}
  peek ptr = CFmpzMPolyQ
    <$> #{peek fmpz_mpoly_q_struct, num} ptr
    <*> #{peek fmpz_mpoly_q_struct, den} ptr
  poke ptr (CFmpzMPolyQ num den) = do
    #{poke fmpz_mpoly_q_struct, num} ptr num
    #{poke fmpz_mpoly_q_struct, den} ptr den

-- | Create a new `FmpzMPolyQ`
newFmpzMPolyQ ctx@(FmpzMPolyCtx pctx) = do
  p <- mallocForeignPtr
  withForeignPtr p $ \p ->
    withFmpzMPolyCtx ctx $ \ctx -> do 
      fmpz_mpoly_q_init p ctx
      addForeignPtrFinalizerEnv p_fmpz_mpoly_q_clear p pctx 
  return $ FmpzMPolyQ p

-- | Use a new `FmpzMPolyQ`
{-# INLINE withFmpzMPolyQ #-}
withFmpzMPolyQ (FmpzMPolyQ p) f = do
  withForeignPtr p $ \fp -> (FmpzMPolyQ p,) <$> f fp

-- | Use the numerator of `FmpzMPolyQ`
withFmpzMPolyQNumerator ::
  FmpzMPolyQ -> (Ptr CFmpzMPoly -> IO t) -> IO (FmpzMPolyQ, t)
withFmpzMPolyQNumerator (FmpzMPolyQ p) f = do
  withForeignPtr p $ \fp -> (FmpzMPolyQ p,) <$> f (castPtr fp)

-- | Use the denominator of `FmpzMPolyQ`
withFmpzMPolyQDenominator ::
  FmpzMPolyQ -> (Ptr CFmpzMPoly -> IO t) -> IO (FmpzMPolyQ, t)
withFmpzMPolyQDenominator (FmpzMPolyQ p) f = do
  withForeignPtr p $ \fp -> (FmpzMPolyQ p,) <$> f (castPtr fp `advancePtr` 1)

-- Memory management -----------------------------------------------------------

-- | /fmpz_mpoly_q_init/ /res/ /ctx/ 
-- 
-- Initializes /res/ for use, and sets its value to zero.
foreign import ccall "fmpz_mpoly_q.h fmpz_mpoly_q_init"
  fmpz_mpoly_q_init :: Ptr CFmpzMPolyQ -> Ptr CFmpzMPolyCtx -> IO ()

-- | /fmpz_mpoly_q_clear/ /res/ /ctx/ 
-- 
-- Clears /res/, freeing or recycling its allocated memory.
foreign import ccall "fmpz_mpoly_q.h fmpz_mpoly_q_clear"
  fmpz_mpoly_q_clear :: Ptr CFmpzMPolyQ -> Ptr CFmpzMPolyCtx -> IO ()

foreign import ccall "fmpz_mpoly_q.h &fmpz_mpoly_q_clear"
  p_fmpz_mpoly_q_clear :: FunPtr (Ptr CFmpzMPolyQ -> Ptr CFmpzMPolyCtx -> IO ())

-- Assignment ------------------------------------------------------------------

-- | /fmpz_mpoly_q_swap/ /x/ /y/ /ctx/ 
-- 
-- Swaps the values of /x/ and /y/ efficiently.
foreign import ccall "fmpz_mpoly_q.h fmpz_mpoly_q_swap"
  fmpz_mpoly_q_swap :: Ptr CFmpzMPolyQ -> Ptr CFmpzMPolyQ -> Ptr CFmpzMPolyCtx -> IO ()

-- | /fmpz_mpoly_q_set/ /res/ /x/ /ctx/ 
-- 
-- Sets /res/ to the value /x/.
foreign import ccall "fmpz_mpoly_q.h fmpz_mpoly_q_set"
  fmpz_mpoly_q_set :: Ptr CFmpzMPolyQ -> Ptr CFmpzMPolyQ -> Ptr CFmpzMPolyCtx -> IO ()

-- Canonicalisation ------------------------------------------------------------

-- | /fmpz_mpoly_q_canonicalise/ /x/ /ctx/ 
-- 
-- Puts the numerator and denominator of /x/ in canonical form by removing
-- common content and making the leading term of the denominator positive.
foreign import ccall "fmpz_mpoly_q.h fmpz_mpoly_q_canonicalise"
  fmpz_mpoly_q_canonicalise :: Ptr CFmpzMPolyQ -> Ptr CFmpzMPolyCtx -> IO ()

-- | /fmpz_mpoly_q_is_canonical/ /x/ /ctx/ 
-- 
-- Returns whether /x/ is in canonical form.
-- 
-- In addition to verifying that the numerator and denominator have no
-- common content and that the leading term of the denominator is positive,
-- this function checks that the denominator is nonzero and that the
-- numerator and denominator have correctly sorted terms (these properties
-- should normally hold; verifying them provides an extra consistency check
-- for test code).
foreign import ccall "fmpz_mpoly_q.h fmpz_mpoly_q_is_canonical"
  fmpz_mpoly_q_is_canonical :: Ptr CFmpzMPolyQ -> Ptr CFmpzMPolyCtx -> IO CInt

-- Properties ------------------------------------------------------------------

-- | /fmpz_mpoly_q_is_zero/ /x/ /ctx/ 
-- 
-- Returns whether /x/ is the constant 0.
foreign import ccall "fmpz_mpoly_q.h fmpz_mpoly_q_is_zero"
  fmpz_mpoly_q_is_zero :: Ptr CFmpzMPolyQ -> Ptr CFmpzMPolyCtx -> IO CInt

-- | /fmpz_mpoly_q_is_one/ /x/ /ctx/ 
-- 
-- Returns whether /x/ is the constant 1.
foreign import ccall "fmpz_mpoly_q.h fmpz_mpoly_q_is_one"
  fmpz_mpoly_q_is_one :: Ptr CFmpzMPolyQ -> Ptr CFmpzMPolyCtx -> IO CInt

-- | /fmpz_mpoly_q_used_vars/ /used/ /f/ /ctx/ 
-- 
-- For each variable, sets the corresponding entry in /used/ to the boolean
-- flag indicating whether that variable appears in the rational function
-- (respectively its numerator or denominator).
foreign import ccall "fmpz_mpoly_q.h fmpz_mpoly_q_used_vars"
  fmpz_mpoly_q_used_vars :: Ptr CInt -> Ptr CFmpzMPolyQ -> Ptr CFmpzMPolyCtx -> IO ()

-- Special values --------------------------------------------------------------

-- | /fmpz_mpoly_q_zero/ /res/ /ctx/ 
-- 
-- Sets /res/ to the constant 0.
foreign import ccall "fmpz_mpoly_q.h fmpz_mpoly_q_zero"
  fmpz_mpoly_q_zero :: Ptr CFmpzMPolyQ -> Ptr CFmpzMPolyCtx -> IO ()

-- | /fmpz_mpoly_q_one/ /res/ /ctx/ 
-- 
-- Sets /res/ to the constant 1.
foreign import ccall "fmpz_mpoly_q.h fmpz_mpoly_q_one"
  fmpz_mpoly_q_one :: Ptr CFmpzMPolyQ -> Ptr CFmpzMPolyCtx -> IO ()

-- | /fmpz_mpoly_q_gen/ /res/ /i/ /ctx/ 
-- 
-- Sets /res/ to the generator \(x_{i+1}\). Requires \(0 \le i < n\) where
-- /n/ is the number of variables of /ctx/.
foreign import ccall "fmpz_mpoly_q.h fmpz_mpoly_q_gen"
  fmpz_mpoly_q_gen :: Ptr CFmpzMPolyQ -> CLong -> Ptr CFmpzMPolyCtx -> IO ()

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

-- | /fmpz_mpoly_q_get_str_pretty/ /f/ /x/ /ctx/ 
-- 
-- Returns string representation of /f/. If /x/ is not /NULL/, the strings in
-- /x/ are used as the symbols for the variables.
foreign import ccall "fmpz_mpoly_q.h fmpz_mpoly_q_get_str_pretty"
  fmpz_mpoly_q_get_str_pretty :: Ptr CFmpzMPolyQ -> Ptr (Ptr CChar) -> Ptr CFmpzMPolyCtx -> IO CString
  
-- | /fmpz_mpoly_q_print_pretty/ /f/ /x/ /ctx/ 
-- 
-- Prints /f/ to standard output. If /x/ is not /NULL/, the strings in
-- /x/ are used as the symbols for the variables.
fmpz_mpoly_q_print_pretty :: Ptr CFmpzMPolyQ -> Ptr (Ptr CChar) -> Ptr CFmpzMPolyCtx -> IO CInt
fmpz_mpoly_q_print_pretty x vars ctx = do
  printCStr (\x -> fmpz_mpoly_q_get_str_pretty x vars ctx) x

-- | /fmpz_mpoly_q_fprint_pretty/ /out/ /f/ /x/ /ctx/ 
-- 
-- Prints /f/ to file /out/. If /x/ is not /NULL/, the strings in
-- /x/ are used as the symbols for the variables.
foreign import ccall "fmpz_mpoly_q.h fmpz_mpoly_q_fprint_pretty"
  fmpz_mpoly_q_fprint_pretty :: Ptr CFile -> Ptr CFmpzMPolyQ -> Ptr (Ptr CChar) -> Ptr CFmpzMPolyCtx -> IO CInt

-- Random generation -----------------------------------------------------------

-- | /fmpz_mpoly_q_randtest/ /res/ /state/ /length/ /coeff_bits/ /exp_bound/ /ctx/ 
-- 
-- Sets /res/ to a random rational function where both numerator and
-- denominator have up to /length/ terms, coefficients up to size
-- /coeff_bits/, and exponents strictly smaller than /exp_bound/.
foreign import ccall "fmpz_mpoly_q.h fmpz_mpoly_q_randtest"
  fmpz_mpoly_q_randtest :: Ptr CFmpzMPolyQ -> Ptr CFRandState -> CLong -> CMpLimb -> CLong -> Ptr CFmpzMPolyCtx -> IO ()

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

-- | /fmpz_mpoly_q_equal/ /x/ /y/ /ctx/ 
-- 
-- Returns whether /x/ and /y/ are equal.
foreign import ccall "fmpz_mpoly_q.h fmpz_mpoly_q_equal"
  fmpz_mpoly_q_equal :: Ptr CFmpzMPolyQ -> Ptr CFmpzMPolyQ -> Ptr CFmpzMPolyCtx -> IO CInt

-- Arithmetic ------------------------------------------------------------------

-- | /fmpz_mpoly_q_neg/ /res/ /x/ /ctx/ 
-- 
-- Sets /res/ to the negation of /x/.
foreign import ccall "fmpz_mpoly_q.h fmpz_mpoly_q_neg"
  fmpz_mpoly_q_neg :: Ptr CFmpzMPolyQ -> Ptr CFmpzMPolyQ -> Ptr CFmpzMPolyCtx -> IO ()

-- | /fmpz_mpoly_q_add/ /res/ /x/ /y/ /ctx/ 
-- 
-- Sets /res/ to the sum of /x/ and /y/.
foreign import ccall "fmpz_mpoly_q.h fmpz_mpoly_q_add"
  fmpz_mpoly_q_add :: Ptr CFmpzMPolyQ -> Ptr CFmpzMPolyQ -> Ptr CFmpzMPolyQ -> Ptr CFmpzMPolyCtx -> IO ()

-- | /fmpz_mpoly_q_sub/ /res/ /x/ /y/ /ctx/ 
-- 
-- Sets /res/ to the difference of /x/ and /y/.
foreign import ccall "fmpz_mpoly_q.h fmpz_mpoly_q_sub"
  fmpz_mpoly_q_sub :: Ptr CFmpzMPolyQ -> Ptr CFmpzMPolyQ -> Ptr CFmpzMPolyQ -> Ptr CFmpzMPolyCtx -> IO ()

-- | /fmpz_mpoly_q_mul/ /res/ /x/ /y/ /ctx/ 
-- 
-- Sets /res/ to the product of /x/ and /y/.
foreign import ccall "fmpz_mpoly_q.h fmpz_mpoly_q_mul"
  fmpz_mpoly_q_mul :: Ptr CFmpzMPolyQ -> Ptr CFmpzMPolyQ -> Ptr CFmpzMPolyQ -> Ptr CFmpzMPolyCtx -> IO ()

-- | /fmpz_mpoly_q_div/ /res/ /x/ /y/ /ctx/ 
-- 
-- Sets /res/ to the quotient of /x/ and /y/. Division by zero calls
-- /flint_abort/.
foreign import ccall "fmpz_mpoly_q.h fmpz_mpoly_q_div"
  fmpz_mpoly_q_div :: Ptr CFmpzMPolyQ -> Ptr CFmpzMPolyQ -> Ptr CFmpzMPolyQ -> Ptr CFmpzMPolyCtx -> IO ()

-- | /fmpz_mpoly_q_inv/ /res/ /x/ /ctx/ 
-- 
-- Sets /res/ to the inverse of /x/. Division by zero calls /flint_abort/.
foreign import ccall "fmpz_mpoly_q.h fmpz_mpoly_q_inv"
  fmpz_mpoly_q_inv :: Ptr CFmpzMPolyQ -> Ptr CFmpzMPolyQ -> Ptr CFmpzMPolyCtx -> IO ()

-- Content ---------------------------------------------------------------------

-- | /_fmpz_mpoly_q_content/ /num/ /den/ /xnum/ /xden/ /ctx/ 
-- 
-- Sets /res/ to the content of the coefficients of /x/.
foreign import ccall "fmpz_mpoly_q.h _fmpz_mpoly_q_content"
  _fmpz_mpoly_q_content :: Ptr CFmpz -> Ptr CFmpz -> Ptr CFmpzMPoly -> Ptr CFmpzMPoly -> Ptr CFmpzMPolyCtx -> IO ()