{-# LINE 1 "src/Data/Number/Flint/Groups/Bool/Mat/FFI.hsc" #-}
{-|
module      :  Data.Number.Flint.Groups.Bool.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.Groups.Bool.Mat.FFI (
  -- * Matrices over booleans
    BoolMat (..)
  , CBoolMat (..)
  , newBoolMat
  , withBoolMat
  , withNewBoolMat
  -- * Entries
  , bool_mat_get_entry
  , bool_mat_set_entry
  -- * Memory management
  , bool_mat_init
  , bool_mat_clear
  , bool_mat_is_empty
  , bool_mat_is_square
  -- * Conversions
  , bool_mat_entry
  , bool_mat_set
  -- * Input and output
  , bool_mat_get_str
  , bool_mat_print
  , bool_mat_fprint
  -- * Value comparisons
  , bool_mat_equal
  , bool_mat_any
  , bool_mat_all
  , bool_mat_is_diagonal
  , bool_mat_is_lower_triangular
  , bool_mat_is_transitive
  , bool_mat_is_nilpotent
  -- * Random generation
  , bool_mat_randtest
  , bool_mat_randtest_diagonal
  , bool_mat_randtest_nilpotent
  -- * Special matrices
  , bool_mat_zero
  , bool_mat_one
  , bool_mat_directed_path
  , bool_mat_directed_cycle
  -- * Transpose
  , bool_mat_transpose
  -- * Arithmetic
  , bool_mat_complement
  , bool_mat_add
  , bool_mat_mul
  , bool_mat_mul_entrywise
  , bool_mat_sqr
  , bool_mat_pow_ui
  -- * Special functions
  , bool_mat_trace
  , bool_mat_nilpotency_degree
  , bool_mat_transitive_closure
  , bool_mat_get_strongly_connected_components
  , bool_mat_all_pairs_longest_walk
) where 

-- Matrices over booleans ------------------------------------------------------

-- A @bool_mat_t@ represents a dense matrix over the boolean semiring
-- \(\langle \left\{0, 1\right\}, \vee, \wedge \rangle\), implemented as an
-- array of entries of type @int@.
--
-- The dimension (number of rows and columns) of a matrix is fixed at
-- initialization, and the user must ensure that inputs and outputs to an
-- operation have compatible dimensions. The number of rows or columns in a
-- matrix can be zero.
--

import System.IO.Unsafe

import Control.Monad

import Foreign.C.String
import Foreign.C.Types
import Foreign.ForeignPtr
import Foreign.Ptr ( Ptr, FunPtr, nullPtr, plusPtr )
import Foreign.Marshal.Array ( advancePtr )
import Foreign.Storable
import Foreign.Marshal ( free )

import Data.Number.Flint.Flint
import Data.Number.Flint.Fmpz
import Data.Number.Flint.Fmpz.Poly
import Data.Number.Flint.Fmpz.Mat
import Data.Number.Flint.Fmpq
import Data.Number.Flint.NMod.Types
import Data.Number.Flint.Support.D.Mat
import Data.Number.Flint.Support.Mpf.Mat




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

data BoolMat = BoolMat {-# UNPACK #-} !(ForeignPtr CBoolMat) 
data CBoolMat = CBoolMat (Ptr CInt) CLong CLong (Ptr (Ptr CInt)) 

instance Storable CBoolMat where
  {-# INLINE sizeOf #-}
  sizeOf :: CBoolMat -> Int
sizeOf CBoolMat
_ = (Int
32)
{-# LINE 107 "src/Data/Number/Flint/Groups/Bool/Mat/FFI.hsc" #-}
  {-# INLINE alignment #-}
  alignment :: CBoolMat -> Int
alignment CBoolMat
_ = Int
8
{-# LINE 109 "src/Data/Number/Flint/Groups/Bool/Mat/FFI.hsc" #-}
  peek ptr = CBoolMat
    <$> (\hsc_ptr -> peekByteOff hsc_ptr 0) ptr
{-# LINE 111 "src/Data/Number/Flint/Groups/Bool/Mat/FFI.hsc" #-}
    <*> (\hsc_ptr -> peekByteOff hsc_ptr 8) ptr
{-# LINE 112 "src/Data/Number/Flint/Groups/Bool/Mat/FFI.hsc" #-}
    <*> (\hsc_ptr -> peekByteOff hsc_ptr 16) ptr
{-# LINE 113 "src/Data/Number/Flint/Groups/Bool/Mat/FFI.hsc" #-}
    <*> (\hsc_ptr -> peekByteOff hsc_ptr 24) ptr 
{-# LINE 114 "src/Data/Number/Flint/Groups/Bool/Mat/FFI.hsc" #-}
  poke = error "CBoolMat.poke: Not defined."
 
newBoolMat :: CLong -> CLong -> IO BoolMat
newBoolMat CLong
rows CLong
cols = do
  ForeignPtr CBoolMat
x <- IO (ForeignPtr CBoolMat)
forall a. Storable a => IO (ForeignPtr a)
mallocForeignPtr
  ForeignPtr CBoolMat -> (Ptr CBoolMat -> IO ()) -> IO ()
forall a b. ForeignPtr a -> (Ptr a -> IO b) -> IO b
withForeignPtr ForeignPtr CBoolMat
x ((Ptr CBoolMat -> IO ()) -> IO ())
-> (Ptr CBoolMat -> IO ()) -> IO ()
forall a b. (a -> b) -> a -> b
$ \Ptr CBoolMat
x -> Ptr CBoolMat -> CLong -> CLong -> IO ()
bool_mat_init Ptr CBoolMat
x CLong
rows CLong
cols
  FinalizerPtr CBoolMat -> ForeignPtr CBoolMat -> IO ()
forall a. FinalizerPtr a -> ForeignPtr a -> IO ()
addForeignPtrFinalizer FinalizerPtr CBoolMat
p_bool_mat_clear ForeignPtr CBoolMat
x
  BoolMat -> IO BoolMat
forall a. a -> IO a
forall (m :: * -> *) a. Monad m => a -> m a
return (BoolMat -> IO BoolMat) -> BoolMat -> IO BoolMat
forall a b. (a -> b) -> a -> b
$ ForeignPtr CBoolMat -> BoolMat
BoolMat ForeignPtr CBoolMat
x

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

{-# INLINE withNewBoolMat #-}
withNewBoolMat :: CLong -> CLong -> (Ptr CBoolMat -> IO a) -> IO (BoolMat, a)
withNewBoolMat CLong
rows CLong
cols Ptr CBoolMat -> IO a
f = do
  BoolMat
x <- CLong -> CLong -> IO BoolMat
newBoolMat CLong
rows CLong
cols
  BoolMat -> (Ptr CBoolMat -> IO a) -> IO (BoolMat, a)
forall {a}. BoolMat -> (Ptr CBoolMat -> IO a) -> IO (BoolMat, a)
withBoolMat BoolMat
x Ptr CBoolMat -> IO a
f
  
--------------------------------------------------------------------------------

-- | /bool_mat_get_entry/ /mat/ /i/ /j/ 
--
-- Returns the entry of matrix /mat/ at row /i/ and column /j/.
-- foreign import ccall "bool_mat.h bool_mat_get_entry"
bool_mat_get_entry :: Ptr CBoolMat -> CLong -> CLong -> IO CInt
bool_mat_get_entry :: Ptr CBoolMat -> CLong -> CLong -> IO CInt
bool_mat_get_entry Ptr CBoolMat
mat CLong
i CLong
j = do
  CBoolMat Ptr CInt
p CLong
r CLong
c Ptr (Ptr CInt)
_ <- Ptr CBoolMat -> IO CBoolMat
forall a. Storable a => Ptr a -> IO a
peek Ptr CBoolMat
mat
  CInt
result <- Ptr CInt -> IO CInt
forall a. Storable a => Ptr a -> IO a
peek (Ptr CInt
p Ptr CInt -> Int -> Ptr CInt
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)))
  CInt -> IO CInt
forall a. a -> IO a
forall (m :: * -> *) a. Monad m => a -> m a
return CInt
result
  
-- | /bool_mat_set_entry/ /mat/ /i/ /j/ /x/ 
--
-- Sets the entry of matrix /mat/ at row /i/ and column /j/ to /x/.
bool_mat_set_entry :: Ptr CBoolMat -> CLong -> CLong -> CInt -> IO ()
bool_mat_set_entry :: Ptr CBoolMat -> CLong -> CLong -> CInt -> IO ()
bool_mat_set_entry Ptr CBoolMat
mat CLong
i CLong
j CInt
x = do 
  CBoolMat Ptr CInt
p CLong
r CLong
c Ptr (Ptr CInt)
_ <- Ptr CBoolMat -> IO CBoolMat
forall a. Storable a => Ptr a -> IO a
peek Ptr CBoolMat
mat
  Ptr CInt -> CInt -> IO ()
forall a. Storable a => Ptr a -> a -> IO ()
poke (Ptr CInt
p Ptr CInt -> Int -> Ptr CInt
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))) CInt
x
  
-- Memory management -----------------------------------------------------------

-- | /bool_mat_init/ /mat/ /r/ /c/ 
--
-- Initializes the matrix, setting it to the zero matrix with /r/ rows and
-- /c/ columns.
foreign import ccall "bool_mat.h bool_mat_init"
  bool_mat_init :: Ptr CBoolMat -> CLong -> CLong -> IO ()

-- | /bool_mat_clear/ /mat/ 
--
-- Clears the matrix, deallocating all entries.
foreign import ccall "bool_mat.h bool_mat_clear"
  bool_mat_clear :: Ptr CBoolMat -> IO ()

foreign import ccall "bool_mat.h &bool_mat_clear"
  p_bool_mat_clear :: FunPtr (Ptr CBoolMat -> IO ())

-- | /bool_mat_is_empty/ /mat/ 
--
-- Returns nonzero iff the number of rows or the number of columns in /mat/
-- is zero. Note that this does not depend on the entry values of /mat/.
bool_mat_is_empty :: Ptr CBoolMat -> IO CInt
bool_mat_is_empty :: Ptr CBoolMat -> IO CInt
bool_mat_is_empty Ptr CBoolMat
mat = do
  CBoolMat Ptr CInt
_ CLong
r CLong
c Ptr (Ptr CInt)
_ <- Ptr CBoolMat -> IO CBoolMat
forall a. Storable a => Ptr a -> IO a
peek Ptr CBoolMat
mat
  CInt -> IO CInt
forall a. a -> IO a
forall (m :: * -> *) a. Monad m => a -> m a
return (CInt -> IO CInt) -> CInt -> IO CInt
forall a b. (a -> b) -> a -> b
$ if CLong
r CLong -> CLong -> Bool
forall a. Eq a => a -> a -> Bool
== CLong
0 Bool -> Bool -> Bool
|| CLong
c CLong -> CLong -> Bool
forall a. Eq a => a -> a -> Bool
== CLong
0 then CInt
1 else CInt
0
  
-- | /bool_mat_is_square/ /mat/ 
--
-- Returns nonzero iff the number of rows is equal to the number of columns
-- in /mat/.
bool_mat_is_square :: Ptr CBoolMat -> IO CInt
bool_mat_is_square :: Ptr CBoolMat -> IO CInt
bool_mat_is_square Ptr CBoolMat
mat = do
  CBoolMat Ptr CInt
_ CLong
r CLong
c Ptr (Ptr CInt)
_ <- Ptr CBoolMat -> IO CBoolMat
forall a. Storable a => Ptr a -> IO a
peek Ptr CBoolMat
mat
  CInt -> IO CInt
forall a. a -> IO a
forall (m :: * -> *) a. Monad m => a -> m a
return (CInt -> IO CInt) -> CInt -> IO CInt
forall a b. (a -> b) -> a -> b
$ if CLong
r CLong -> CLong -> Bool
forall a. Eq a => a -> a -> Bool
== CLong
c then CInt
1 else CInt
0

-- Conversions -----------------------------------------------------------------

bool_mat_entry :: Ptr CBoolMat -> CLong -> CLong -> IO (Ptr CInt)
bool_mat_entry Ptr CBoolMat
mat CLong
i CLong
j = do
  CBoolMat Ptr CInt
entries CLong
r CLong
c Ptr (Ptr CInt)
rows <- Ptr CBoolMat -> IO CBoolMat
forall a. Storable a => Ptr a -> IO a
peek Ptr CBoolMat
mat
  Ptr CInt -> IO (Ptr CInt)
forall a. a -> IO a
forall (m :: * -> *) a. Monad m => a -> m a
return (Ptr CInt -> IO (Ptr CInt)) -> Ptr CInt -> IO (Ptr CInt)
forall a b. (a -> b) -> a -> b
$ Ptr CInt
entries Ptr CInt -> Int -> Ptr CInt
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))
  
-- | /bool_mat_set/ /dest/ /src/ 
--
-- Sets /dest/ to /src/. The operands must have identical dimensions.
foreign import ccall "bool_mat.h bool_mat_set"
  bool_mat_set :: Ptr CBoolMat -> Ptr CBoolMat -> IO ()

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

foreign import ccall "bool_mat.h bool_mat_get_str"
  bool_mat_get_str :: Ptr CBoolMat -> IO CString
  
-- | /bool_mat_print/ /mat/ 
--
-- Prints each entry in the matrix.
bool_mat_print :: Ptr CBoolMat -> IO ()
bool_mat_print :: Ptr CBoolMat -> IO ()
bool_mat_print Ptr CBoolMat
mat = do
  (Ptr CBoolMat -> IO CString) -> Ptr CBoolMat -> IO CInt
forall a. (Ptr a -> IO CString) -> Ptr a -> IO CInt
printCStr Ptr CBoolMat -> IO CString
bool_mat_get_str Ptr CBoolMat
mat
  () -> IO ()
forall a. a -> IO a
forall (m :: * -> *) a. Monad m => a -> m a
return ()

-- | /bool_mat_fprint/ /file/ /mat/ 
--
-- Prints each entry in the matrix to the stream /file/.
foreign import ccall "bool_mat.h bool_mat_fprint"
  bool_mat_fprint :: Ptr CFile -> Ptr CBoolMat -> IO ()

-- Value comparisons -----------------------------------------------------------

-- | /bool_mat_equal/ /mat1/ /mat2/ 
--
-- Returns nonzero iff the matrices have the same dimensions and identical
-- entries.
foreign import ccall "bool_mat.h bool_mat_equal"
  bool_mat_equal :: Ptr CBoolMat -> Ptr CBoolMat -> IO CInt

-- | /bool_mat_any/ /mat/ 
--
-- Returns nonzero iff /mat/ has a nonzero entry.
foreign import ccall "bool_mat.h bool_mat_any"
  bool_mat_any :: Ptr CBoolMat -> IO CInt

-- | /bool_mat_all/ /mat/ 
--
-- Returns nonzero iff all entries of /mat/ are nonzero.
foreign import ccall "bool_mat.h bool_mat_all"
  bool_mat_all :: Ptr CBoolMat -> IO CInt

-- | /bool_mat_is_diagonal/ /A/ 
--
-- Returns nonzero iff \(i \ne j \implies \bar{A_{ij}}\).
foreign import ccall "bool_mat.h bool_mat_is_diagonal"
  bool_mat_is_diagonal :: Ptr CBoolMat -> IO CInt

-- | /bool_mat_is_lower_triangular/ /A/ 
--
-- Returns nonzero iff \(i < j \implies \bar{A_{ij}}\).
foreign import ccall "bool_mat.h bool_mat_is_lower_triangular"
  bool_mat_is_lower_triangular :: Ptr CBoolMat -> IO CInt

-- | /bool_mat_is_transitive/ /mat/ 
--
-- Returns nonzero iff \(A_{ij} \wedge A_{jk} \implies A_{ik}\).
foreign import ccall "bool_mat.h bool_mat_is_transitive"
  bool_mat_is_transitive :: Ptr CBoolMat -> IO CInt

-- | /bool_mat_is_nilpotent/ /A/ 
--
-- Returns nonzero iff some positive matrix power of \(A\) is zero.
foreign import ccall "bool_mat.h bool_mat_is_nilpotent"
  bool_mat_is_nilpotent :: Ptr CBoolMat -> IO CInt

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

-- | /bool_mat_randtest/ /mat/ /state/ 
--
-- Sets /mat/ to a random matrix.
foreign import ccall "bool_mat.h bool_mat_randtest"
  bool_mat_randtest :: Ptr CBoolMat -> Ptr CFRandState -> IO ()

-- | /bool_mat_randtest_diagonal/ /mat/ /state/ 
--
-- Sets /mat/ to a random diagonal matrix.
foreign import ccall "bool_mat.h bool_mat_randtest_diagonal"
  bool_mat_randtest_diagonal :: Ptr CBoolMat -> Ptr CFRandState -> IO ()

-- | /bool_mat_randtest_nilpotent/ /mat/ /state/ 
--
-- Sets /mat/ to a random nilpotent matrix.
foreign import ccall "bool_mat.h bool_mat_randtest_nilpotent"
  bool_mat_randtest_nilpotent :: Ptr CBoolMat -> Ptr CFRandState -> IO ()

-- Special matrices ------------------------------------------------------------

-- | /bool_mat_zero/ /mat/ 
--
-- Sets all entries in mat to zero.
foreign import ccall "bool_mat.h bool_mat_zero"
  bool_mat_zero :: Ptr CBoolMat -> IO ()

-- | /bool_mat_one/ /mat/ 
--
-- Sets the entries on the main diagonal to ones, and all other entries to
-- zero.
foreign import ccall "bool_mat.h bool_mat_one"
  bool_mat_one :: Ptr CBoolMat -> IO ()

-- | /bool_mat_directed_path/ /A/ 
--
-- Sets \(A_{ij}\) to \(j = i + 1\). Requires that \(A\) is a square
-- matrix.
foreign import ccall "bool_mat.h bool_mat_directed_path"
  bool_mat_directed_path :: Ptr CBoolMat -> IO ()

-- | /bool_mat_directed_cycle/ /A/ 
--
-- Sets \(A_{ij}\) to \(j = (i + 1) \mod n\) where \(n\) is the order of
-- the square matrix \(A\).
foreign import ccall "bool_mat.h bool_mat_directed_cycle"
  bool_mat_directed_cycle :: Ptr CBoolMat -> IO ()

-- Transpose -------------------------------------------------------------------

-- | /bool_mat_transpose/ /dest/ /src/ 
--
-- Sets /dest/ to the transpose of /src/. The operands must have compatible
-- dimensions. Aliasing is allowed.
foreign import ccall "bool_mat.h bool_mat_transpose"
  bool_mat_transpose :: Ptr CBoolMat -> Ptr CBoolMat -> IO ()

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

-- | /bool_mat_complement/ /B/ /A/ 
--
-- Sets /B/ to the logical complement of /A/. That is \(B_{ij}\) is set to
-- \(\bar{A_{ij}}\). The operands must have the same dimensions.
foreign import ccall "bool_mat.h bool_mat_complement"
  bool_mat_complement :: Ptr CBoolMat -> Ptr CBoolMat -> IO ()

-- | /bool_mat_add/ /res/ /mat1/ /mat2/ 
--
-- Sets /res/ to the sum of /mat1/ and /mat2/. The operands must have the
-- same dimensions.
foreign import ccall "bool_mat.h bool_mat_add"
  bool_mat_add :: Ptr CBoolMat -> Ptr CBoolMat -> Ptr CBoolMat -> IO ()

-- | /bool_mat_mul/ /res/ /mat1/ /mat2/ 
--
-- Sets /res/ to the matrix product of /mat1/ and /mat2/. The operands must
-- have compatible dimensions for matrix multiplication.
foreign import ccall "bool_mat.h bool_mat_mul"
  bool_mat_mul :: Ptr CBoolMat -> Ptr CBoolMat -> Ptr CBoolMat -> IO ()

-- | /bool_mat_mul_entrywise/ /res/ /mat1/ /mat2/ 
--
-- Sets /res/ to the entrywise product of /mat1/ and /mat2/. The operands
-- must have the same dimensions.
foreign import ccall "bool_mat.h bool_mat_mul_entrywise"
  bool_mat_mul_entrywise :: Ptr CBoolMat -> Ptr CBoolMat -> Ptr CBoolMat -> IO ()

-- | /bool_mat_sqr/ /B/ /A/ 
--
-- Sets /B/ to the matrix square of /A/. The operands must both be square
-- with the same dimensions.
bool_mat_sqr :: Ptr CBoolMat -> Ptr CBoolMat -> IO ()
bool_mat_sqr :: Ptr CBoolMat -> Ptr CBoolMat -> IO ()
bool_mat_sqr Ptr CBoolMat
b Ptr CBoolMat
a = Ptr CBoolMat -> Ptr CBoolMat -> Ptr CBoolMat -> IO ()
bool_mat_mul Ptr CBoolMat
b Ptr CBoolMat
a Ptr CBoolMat
a
  
-- | /bool_mat_pow_ui/ /B/ /A/ /exp/ 
--
-- Sets /B/ to /A/ raised to the power /exp/. Requires that /A/ is a square
-- matrix.
foreign import ccall "bool_mat.h bool_mat_pow_ui"
  bool_mat_pow_ui :: Ptr CBoolMat -> Ptr CBoolMat -> CULong -> IO ()

-- Special functions -----------------------------------------------------------

-- | /bool_mat_trace/ /mat/ 
--
-- Returns the trace of the matrix, i.e. the sum of entries on the main
-- diagonal of /mat/. The matrix is required to be square. The sum is in
-- the boolean semiring, so this function returns nonzero iff any entry on
-- the diagonal of /mat/ is nonzero.
foreign import ccall "bool_mat.h bool_mat_trace"
  bool_mat_trace :: Ptr CBoolMat -> IO CInt

-- | /bool_mat_nilpotency_degree/ /A/ 
--
-- Returns the nilpotency degree of the \(n \times n\) matrix /A/. It
-- returns the smallest positive \(k\) such that \(A^k = 0\). If no such
-- \(k\) exists then the function returns \(-1\) if \(n\) is positive, and
-- otherwise it returns \(0\).
foreign import ccall "bool_mat.h bool_mat_nilpotency_degree"
  bool_mat_nilpotency_degree :: Ptr CBoolMat -> IO CLong

-- | /bool_mat_transitive_closure/ /B/ /A/ 
--
-- Sets /B/ to the transitive closure \(\sum_{k=1}^\infty A^k\). The matrix
-- /A/ is required to be square.
foreign import ccall "bool_mat.h bool_mat_transitive_closure"
  bool_mat_transitive_closure :: Ptr CBoolMat -> Ptr CBoolMat -> IO ()

-- | /bool_mat_get_strongly_connected_components/ /p/ /A/ 
--
-- Partitions the \(n\) row and column indices of the \(n \times n\) matrix
-- /A/ according to the strongly connected components (SCC) of the graph
-- for which /A/ is the adjacency matrix. If the graph has \(k\) SCCs then
-- the function returns \(k\), and for each vertex \(i \in [0, n-1]\),
-- \(p_i\) is set to the index of the SCC to which the vertex belongs. The
-- SCCs themselves can be considered as nodes in a directed acyclic graph
-- (DAG), and the SCCs are indexed in postorder with respect to that DAG.
foreign import ccall "bool_mat.h bool_mat_get_strongly_connected_components"
  bool_mat_get_strongly_connected_components :: Ptr CLong -> Ptr CBoolMat -> IO CLong

-- | /bool_mat_all_pairs_longest_walk/ /B/ /A/ 
--
-- Sets \(B_{ij}\) to the length of the longest walk with endpoint vertices
-- \(i\) and \(j\) in the graph whose adjacency matrix is /A/. The matrix
-- /A/ must be square. Empty walks with zero length which begin and end at
-- the same vertex are allowed. If \(j\) is not reachable from \(i\) then
-- no walk from \(i\) to \(j\) exists and \(B_{ij}\) is set to the special
-- value \(-1\). If arbitrarily long walks from \(i\) to \(j\) exist then
-- \(B_{ij}\) is set to the special value \(-2\).
-- 
-- The function returns \(-2\) if any entry of \(B_{ij}\) is \(-2\), and
-- otherwise it returns the maximum entry in \(B\), except if \(A\) is
-- empty in which case \(-1\) is returned. Note that the returned value is
-- one less than that of @nilpotency_degree@.
-- 
-- This function can help quantify entrywise errors in a truncated
-- evaluation of a matrix power series. If /A/ is an indicator matrix with
-- the same sparsity pattern as a matrix \(M\) over the real or complex
-- numbers, and if \(B_{ij}\) does not take the special value \(-2\), then
-- the tail \(\left[ \sum_{k=N}^\infty a_k M^k \right]_{ij}\) vanishes when
-- \(N > B_{ij}\).
foreign import ccall "bool_mat.h bool_mat_all_pairs_longest_walk"
  bool_mat_all_pairs_longest_walk :: Ptr CFmpzMat -> Ptr CBoolMat -> IO CLong