{-# LINE 1 "src/Data/Number/Flint/Support/Mpfr/Mat/FFI.hsc" #-}
{-|
module      :  Data.Number.Flint.Support.Mpfr.Mat.FFI
copyright   :  (c) 2022 Hartmut Monien
license     :  GNU GPL, version 2 or above (see LICENSE)
maintainer  :  hmonien@uni-bonn.de
-}
module Data.Number.Flint.Support.Mpfr.Mat.FFI (
  -- * Matrices of MPFR floating-point numbers
    MpfrMat (..)
  , CMpfrMat (..)
  , newMpfrMat
  , withMpfrMat
  , withNewMpfrMat
  -- * Memory management
  , mpfr_mat_init
  , mpfr_mat_clear
  -- * Basic manipulation
  , mpfr_mat_swap
  , mpfr_mat_swap_entrywise
  , mpfr_mat_entry
  , mpfr_mat_set
  , mpfr_mat_zero
  -- * Comparison
  , mpfr_mat_equal
  -- * Randomisation
  , mpfr_mat_randtest
  -- * Basic arithmetic
  , mpfr_mat_mul_classical
) where

-- Matrices of MPFR floating-point numbers -------------------------------------

import Foreign.C.Types
import Foreign.Ptr
import Foreign.ForeignPtr
import Foreign.Marshal.Array
import Foreign.Storable

import Data.Number.Flint.Flint




-- mpfr_mat_t ------------------------------------------------------------------

data MpfrMat = MpfrMat {-# UNPACK #-} !(ForeignPtr CMpfrMat)
data CMpfrMat = CMpfrMat (Ptr CMpfr) CLong CLong (Ptr (Ptr CMpfr))

instance Storable CMpfrMat where
  {-# INLINE sizeOf #-}
  sizeOf :: CMpfrMat -> Int
sizeOf CMpfrMat
_ = (Int
40)
{-# LINE 52 "src/Data/Number/Flint/Support/Mpfr/Mat/FFI.hsc" #-}
  {-# INLINE alignment #-}
  alignment :: CMpfrMat -> Int
alignment CMpfrMat
_ = Int
8
{-# LINE 54 "src/Data/Number/Flint/Support/Mpfr/Mat/FFI.hsc" #-}
  peek ptr = CMpfrMat
    <$> (\hsc_ptr -> peekByteOff hsc_ptr 0) ptr
{-# LINE 56 "src/Data/Number/Flint/Support/Mpfr/Mat/FFI.hsc" #-}
    <*> (\hsc_ptr -> peekByteOff hsc_ptr 8) ptr
{-# LINE 57 "src/Data/Number/Flint/Support/Mpfr/Mat/FFI.hsc" #-}
    <*> (\hsc_ptr -> peekByteOff hsc_ptr 16) ptr
{-# LINE 58 "src/Data/Number/Flint/Support/Mpfr/Mat/FFI.hsc" #-}
    <*> (\hsc_ptr -> peekByteOff hsc_ptr 32) ptr
{-# LINE 59 "src/Data/Number/Flint/Support/Mpfr/Mat/FFI.hsc" #-}
  poke = error "CMpfrMat.poke: Not defined."

newMpfrMat :: CLong -> CLong -> CMpfrPrec -> IO MpfrMat
newMpfrMat CLong
rows CLong
cols CMpfrPrec
prec = do
  ForeignPtr CMpfrMat
x <- IO (ForeignPtr CMpfrMat)
forall a. Storable a => IO (ForeignPtr a)
mallocForeignPtr
  ForeignPtr CMpfrMat -> (Ptr CMpfrMat -> IO ()) -> IO ()
forall a b. ForeignPtr a -> (Ptr a -> IO b) -> IO b
withForeignPtr ForeignPtr CMpfrMat
x ((Ptr CMpfrMat -> IO ()) -> IO ())
-> (Ptr CMpfrMat -> IO ()) -> IO ()
forall a b. (a -> b) -> a -> b
$ \Ptr CMpfrMat
x -> Ptr CMpfrMat -> CLong -> CLong -> CMpfrPrec -> IO ()
mpfr_mat_init Ptr CMpfrMat
x CLong
rows CLong
cols CMpfrPrec
prec
  FinalizerPtr CMpfrMat -> ForeignPtr CMpfrMat -> IO ()
forall a. FinalizerPtr a -> ForeignPtr a -> IO ()
addForeignPtrFinalizer FinalizerPtr CMpfrMat
p_mpfr_mat_clear ForeignPtr CMpfrMat
x
  MpfrMat -> IO MpfrMat
forall a. a -> IO a
forall (m :: * -> *) a. Monad m => a -> m a
return (MpfrMat -> IO MpfrMat) -> MpfrMat -> IO MpfrMat
forall a b. (a -> b) -> a -> b
$ ForeignPtr CMpfrMat -> MpfrMat
MpfrMat ForeignPtr CMpfrMat
x

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

withNewMpfrMat :: CLong
-> CLong -> CMpfrPrec -> (Ptr CMpfrMat -> IO a) -> IO (MpfrMat, a)
withNewMpfrMat CLong
rows CLong
cols CMpfrPrec
prec Ptr CMpfrMat -> IO a
f = do
  MpfrMat
x <- CLong -> CLong -> CMpfrPrec -> IO MpfrMat
newMpfrMat CLong
rows CLong
cols CMpfrPrec
prec
  MpfrMat -> (Ptr CMpfrMat -> IO a) -> IO (MpfrMat, a)
forall {a}. MpfrMat -> (Ptr CMpfrMat -> IO a) -> IO (MpfrMat, a)
withMpfrMat MpfrMat
x Ptr CMpfrMat -> IO a
f
  
-- Memory management -----------------------------------------------------------

-- | /mpfr_mat_init/ /mat/ /rows/ /cols/ /prec/ 
-- 
-- Initialises a matrix with the given number of rows and columns and the
-- given precision for use. The precision is the exact precision of the
-- entries.
foreign import ccall "mpfr_mat.h mpfr_mat_init"
  mpfr_mat_init :: Ptr CMpfrMat -> CLong -> CLong -> CMpfrPrec -> IO ()

-- | /mpfr_mat_clear/ /mat/ 
-- 
-- Clears the given matrix.
foreign import ccall "mpfr_mat.h mpfr_mat_clear"
  mpfr_mat_clear :: Ptr CMpfrMat -> IO ()

foreign import ccall "mpfr_mat.h &mpfr_mat_clear"
  p_mpfr_mat_clear :: FunPtr (Ptr CMpfrMat -> IO ())

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

mpfr_mat_entry :: Ptr CMpfrMat -> CLong -> CLong -> IO (Ptr CMpfr)
mpfr_mat_entry Ptr CMpfrMat
mat CLong
i CLong
j = do
  CMpfrMat Ptr CMpfr
entries CLong
r CLong
c Ptr (Ptr CMpfr)
rows <- Ptr CMpfrMat -> IO CMpfrMat
forall a. Storable a => Ptr a -> IO a
peek Ptr CMpfrMat
mat
  Ptr CMpfr -> IO (Ptr CMpfr)
forall a. a -> IO a
forall (m :: * -> *) a. Monad m => a -> m a
return (Ptr CMpfr -> IO (Ptr CMpfr)) -> Ptr CMpfr -> IO (Ptr CMpfr)
forall a b. (a -> b) -> a -> b
$ Ptr CMpfr
entries Ptr CMpfr -> Int -> Ptr CMpfr
forall a. Storable a => Ptr a -> Int -> Ptr a
`advancePtr` (CLong -> Int
forall a b. (Integral a, Num b) => a -> b
fromIntegral (CLong
iCLong -> CLong -> CLong
forall a. Num a => a -> a -> a
*CLong
c CLong -> CLong -> CLong
forall a. Num a => a -> a -> a
+ CLong
j))

-- | /mpfr_mat_swap/ /mat1/ /mat2/ 
-- 
-- Efficiently swap matrices @mat1@ and @mat2@.
foreign import ccall "mpfr_mat.h mpfr_mat_swap"
  mpfr_mat_swap :: Ptr CMpfrMat -> Ptr CMpfrMat -> IO ()

-- | /mpfr_mat_swap_entrywise/ /mat1/ /mat2/ 
-- 
-- Swaps two matrices by swapping the individual entries rather than
-- swapping the contents of the structs.
foreign import ccall "mpfr_mat.h mpfr_mat_swap_entrywise_"
  mpfr_mat_swap_entrywise :: Ptr CMpfrMat -> Ptr CMpfrMat -> IO ()

-- | /mpfr_mat_set/ /mat1/ /mat2/ 
-- 
-- Set @mat1@ to the value of @mat2@.
foreign import ccall "mpfr_mat.h mpfr_mat_set"
  mpfr_mat_set :: Ptr CMpfrMat -> Ptr CMpfrMat -> IO ()

-- | /mpfr_mat_zero/ /mat/ 
-- 
-- Set @mat@ to the zero matrix.
foreign import ccall "mpfr_mat.h mpfr_mat_zero"
  mpfr_mat_zero :: Ptr CMpfrMat -> IO ()

-- Comparison ------------------------------------------------------------------

-- | /mpfr_mat_equal/ /mat1/ /mat2/ 
-- 
-- Return \(1\) if the two given matrices are equal, otherwise return
-- \(0\).
foreign import ccall "mpfr_mat.h mpfr_mat_equal"
  mpfr_mat_equal :: Ptr CMpfrMat -> Ptr CMpfrMat -> IO CInt

-- Randomisation ---------------------------------------------------------------

-- | /mpfr_mat_randtest/ /mat/ /state/ 
-- 
-- Generate a random matrix with random number of rows and columns and
-- random entries for use in test code.
foreign import ccall "mpfr_mat.h mpfr_mat_randtest"
  mpfr_mat_randtest :: Ptr CMpfrMat -> Ptr CFRandState -> IO ()

-- Basic arithmetic ------------------------------------------------------------

-- | /mpfr_mat_mul_classical/ /C/ /A/ /B/ /rnd/ 
-- 
-- Set \(C\) to the product of \(A\) and \(B\) with the given rounding
-- mode, using the classical algorithm.
foreign import ccall "mpfr_mat.h mpfr_mat_mul_classical"
  mpfr_mat_mul_classical :: Ptr CMpfrMat -> Ptr CMpfrMat -> Ptr CMpfrMat -> CMpfrRnd -> IO ()