{-# LINE 1 "src/Data/Number/Flint/NF/FFI.hsc" #-}
{-|
module      :  Data.Number.Flint.NF.FFI
copyright   :  (c) 2022 Hartmut Monien
license     :  GNU GPL, version 2 or above (see LICENSE)
maintainer  :  hmonien@uni-bonn.de
-}
module Data.Number.Flint.NF.FFI (
  -- Number fields
    NF (..)
  , CNF (..)
  , newNF
  , withNF
  , nf_init
  , nf_clear
) where

-- Number fields ---------------------------------------------------------------

import Foreign.ForeignPtr
import Foreign.Ptr
import Foreign.Storable

import Data.Number.Flint.Fmpq.Poly



-- nf_t ------------------------------------------------------------------------

data NF = NF {-# UNPACK #-} !(ForeignPtr CNF)
data CNF = CNF

instance Storable CNF where
  {-# INLINE sizeOf #-}
  sizeOf :: CNF -> Int
sizeOf CNF
_ = (Int
112)
{-# LINE 35 "src/Data/Number/Flint/NF/FFI.hsc" #-}
  {-# INLINE alignment #-}
  alignment :: CNF -> Int
alignment CNF
_ = Int
8
{-# LINE 37 "src/Data/Number/Flint/NF/FFI.hsc" #-}
  peek = error "CNF.peek is not defined."
  poke :: Ptr CNF -> CNF -> IO ()
poke = [Char] -> Ptr CNF -> CNF -> IO ()
forall a. HasCallStack => [Char] -> a
error [Char]
"CNF.poke is not defined."

--------------------------------------------------------------------------------

-- | Create a new number field
newNF :: FmpqPoly -> IO NF
newNF FmpqPoly
poly = do
  ForeignPtr CNF
nf <- IO (ForeignPtr CNF)
forall a. Storable a => IO (ForeignPtr a)
mallocForeignPtr
  ForeignPtr CNF
-> (Ptr CNF -> IO (FmpqPoly, ())) -> IO (FmpqPoly, ())
forall a b. ForeignPtr a -> (Ptr a -> IO b) -> IO b
withForeignPtr ForeignPtr CNF
nf ((Ptr CNF -> IO (FmpqPoly, ())) -> IO (FmpqPoly, ()))
-> (Ptr CNF -> IO (FmpqPoly, ())) -> IO (FmpqPoly, ())
forall a b. (a -> b) -> a -> b
$ \Ptr CNF
nf ->
    FmpqPoly -> (Ptr CFmpqPoly -> IO ()) -> IO (FmpqPoly, ())
forall {a}. FmpqPoly -> (Ptr CFmpqPoly -> IO a) -> IO (FmpqPoly, a)
withFmpqPoly FmpqPoly
poly ((Ptr CFmpqPoly -> IO ()) -> IO (FmpqPoly, ()))
-> (Ptr CFmpqPoly -> IO ()) -> IO (FmpqPoly, ())
forall a b. (a -> b) -> a -> b
$ \Ptr CFmpqPoly
poly ->
      Ptr CNF -> Ptr CFmpqPoly -> IO ()
nf_init Ptr CNF
nf Ptr CFmpqPoly
poly
  FinalizerPtr CNF -> ForeignPtr CNF -> IO ()
forall a. FinalizerPtr a -> ForeignPtr a -> IO ()
addForeignPtrFinalizer FinalizerPtr CNF
p_nf_clear ForeignPtr CNF
nf 
  NF -> IO NF
forall a. a -> IO a
forall (m :: * -> *) a. Monad m => a -> m a
return (NF -> IO NF) -> NF -> IO NF
forall a b. (a -> b) -> a -> b
$ ForeignPtr CNF -> NF
NF ForeignPtr CNF
nf

-- | Use number field
withNF :: NF -> (Ptr CNF -> IO a) -> IO (NF, a)
withNF (NF ForeignPtr CNF
nf) Ptr CNF -> IO a
f = do
  ForeignPtr CNF -> (Ptr CNF -> IO (NF, a)) -> IO (NF, a)
forall a b. ForeignPtr a -> (Ptr a -> IO b) -> IO b
withForeignPtr ForeignPtr CNF
nf ((Ptr CNF -> IO (NF, a)) -> IO (NF, a))
-> (Ptr CNF -> IO (NF, a)) -> IO (NF, a)
forall a b. (a -> b) -> a -> b
$ \Ptr CNF
fp -> (ForeignPtr CNF -> NF
NF ForeignPtr CNF
nf,) (a -> (NF, a)) -> IO a -> IO (NF, a)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Ptr CNF -> IO a
f Ptr CNF
fp

--------------------------------------------------------------------------------

-- | /nf_init/ /nf/ /pol/ 
-- 
-- Perform basic initialisation of a number field (for element arithmetic)
-- given a defining polynomial over \(\mathbb{Q}\).
foreign import ccall "nf.h nf_init"
  nf_init :: Ptr CNF -> Ptr CFmpqPoly -> IO ()

-- | /nf_clear/ /nf/ 
-- 
-- Release resources used by a number field object. The object will need
-- initialisation again before it can be used.
foreign import ccall "nf.h nf_clear"
  nf_clear :: Ptr CNF -> IO ()

foreign import ccall "nf.h &nf_clear"
  p_nf_clear :: FunPtr (Ptr CNF -> IO ())