{-# LANGUAGE ForeignFunctionInterface #-} module IGraph.Internal ( -- * Data structure library: vector, matrix, other data types -- ** Igraph vector type and basic operations Vector , allocaVector , allocaVectorN , withList , withListMaybe , toList , igraphVectorNull , igraphVectorFill , igraphVectorE , igraphVectorSet , igraphVectorTail , igraphVectorSize , igraphVectorCopyTo -- ** Igraph pointer vector , VectorPtr , allocaVectorPtr , allocaVectorPtrN , withPtrs , toLists , igraphVectorPtrSize , igraphVectorPtrE , igraphVectorPtrSet -- ** Customized bytestring for storing attributes , BSLen , withByteString , toByteString -- ** Customized bytestring vector , BSVector , allocaBSVectorN , withByteStrings , bsvectorSet -- ** Igraph matrix type , Matrix , allocaMatrix , allocaMatrixN , withRowLists , toRowLists , toColumnLists , igraphMatrixNull , igraphMatrixFill , igraphMatrixE , igraphMatrixSet , igraphMatrixCopyTo , igraphMatrixNrow , igraphMatrixNcol -- * Igraph type and constructors , IGraph , withIGraph , allocaIGraph , addIGraphFinalizer , mkLabelToId , initializeNullAttribute , igraphNew , igraphCreate , igraphIsSimple , igraphHasMultiple -- * Selector and iterator for edge and vertex -- ** Igraph vertex selector , VertexSelector , withVerticesAll , withVerticesAdj , withVerticesVector , withVerticesList -- ** Igraph vertex iterator , VertexIterator , iterateVertices , iterateVerticesC -- ** Igraph edge Selector , EdgeSelector , withEdgesAll , withEdgeIdsVector , withEdgeIdsList -- ** Igraph edge iterator , EdgeIterator , iterateEdges , iterateEdgesC -- * Basic graph operations , igraphCopy , igraphVcount , igraphEcount , igraphGetEid , igraphEdge , igraphAddVertices , igraphAddEdge , igraphAddEdges , igraphDeleteVertices , igraphDeleteEdges -- * Igraph attribute record , AttributeRecord , withAttr , withBSAttr , igraphHaskellAttributeHasAttr , igraphHaskellAttributeVAS , igraphHaskellAttributeEAS , igraphHaskellAttributeVASSet , igraphHaskellAttributeVASSetv , igraphHaskellAttributeEASSet , igraphHaskellAttributeEASSetv -- * Igraph arpack options type , ArpackOpt , allocaArpackOpt ) where import Control.Monad import qualified Data.ByteString.Char8 as B import Data.ByteString (packCStringLen) import Data.ByteString.Unsafe (unsafeUseAsCStringLen) import Data.List (transpose) import qualified Data.Map.Strict as M import System.IO.Unsafe (unsafePerformIO) import Data.Either (fromRight) import Data.List.Split (chunksOf) import Data.Serialize (Serialize, decode, encode) import Control.Monad.Primitive import Control.Exception (bracket_) import Conduit (ConduitT, yield, liftIO) import Foreign import Foreign.C.Types import Foreign.C.String import IGraph.Internal.C2HS {#import IGraph.Internal.Initialization #} {#import IGraph.Internal.Constants #} import IGraph.Types #include "haskell_attributes.h" #include "haskell_igraph.h" -------------------------------------------------------------------------------- -- Igraph vector -------------------------------------------------------------------------------- data Vector -- | Allocate and initialize a vector. allocaVector :: (Ptr Vector -> IO a) -> IO a allocaVector fun = allocaBytes {# sizeof igraph_vector_t #} $ \vec -> bracket_ (igraphVectorInit vec 0) (igraphVectorDestroy vec) (fun vec) {-# INLINE allocaVector #-} allocaVectorN :: Int -> (Ptr Vector -> IO a) -> IO a allocaVectorN n fun = allocaBytes {# sizeof igraph_vector_t #} $ \vec -> bracket_ (igraphVectorInit vec n) (igraphVectorDestroy vec) (fun vec) {-# INLINE allocaVectorN #-} {#fun igraph_vector_init as ^ { castPtr `Ptr Vector', `Int' } -> `CInt' void- #} {#fun igraph_vector_destroy as ^ { castPtr `Ptr Vector' } -> `CInt' void- #} withList :: Real a => [a] -> (Ptr Vector -> IO b) -> IO b withList xs fun = withArrayLen (map realToFrac xs) $ \n ptr -> allocaBytes {# sizeof igraph_vector_t #} $ \vec -> bracket_ (igraphVectorInitCopy vec ptr n) (igraphVectorDestroy vec) (fun vec) {-# INLINE withList #-} {#fun igraph_vector_init_copy as ^ { castPtr `Ptr Vector' , id `Ptr CDouble', `Int' } -> `CInt' void- #} -- | Allocate a nullPtr if Nothing withListMaybe :: Real a => Maybe [a] -> (Ptr Vector -> IO b) -> IO b withListMaybe (Just xs) fun = withList xs fun withListMaybe Nothing fun = fun $ castPtr nullPtr {-# INLINE withListMaybe #-} toList :: Ptr Vector -> IO [Double] toList vec = do n <- igraphVectorSize vec allocaArray n $ \ptr -> do igraphVectorCopyTo vec ptr map realToFrac <$> peekArray n ptr {-# INLINE toList #-} {#fun igraph_vector_copy_to as ^ { castPtr `Ptr Vector', id `Ptr CDouble' } -> `()' #} -- Initializing elements {#fun igraph_vector_null as ^ { castPtr `Ptr Vector' } -> `()' #} {#fun igraph_vector_fill as ^ { castPtr `Ptr Vector', `Double' } -> `()' #} -- Accessing elements {#fun igraph_vector_e as ^ { castPtr `Ptr Vector', `Int' } -> `Double' #} {#fun igraph_vector_set as ^ { castPtr `Ptr Vector', `Int', `Double' } -> `()' #} {#fun igraph_vector_tail as ^ { castPtr `Ptr Vector' } -> `Double' #} -- Vector properties {#fun igraph_vector_size as ^ { castPtr `Ptr Vector' } -> `Int' #} -------------------------------------------------------------------------------- -- Pointer Vector -------------------------------------------------------------------------------- data VectorPtr -- | Allocate and initialize a pointer vector. allocaVectorPtr :: (Ptr VectorPtr -> IO a) -> IO a allocaVectorPtr fun = allocaBytes {# sizeof igraph_vector_ptr_t #} $ \ptr -> bracket_ (igraphVectorPtrInit ptr 0) (igraphVectorPtrDestroy ptr) (fun ptr) {-# INLINE allocaVectorPtr #-} allocaVectorPtrN :: Int -> (Ptr VectorPtr -> IO a) -> IO a allocaVectorPtrN n fun = allocaBytes {# sizeof igraph_vector_ptr_t #} $ \ptr -> bracket_ (igraphVectorPtrInit ptr n) (igraphVectorPtrDestroy ptr) (fun ptr) {-# INLINE allocaVectorPtrN #-} {#fun igraph_vector_ptr_init as ^ { castPtr `Ptr VectorPtr', `Int' } -> `CInt' void- #} {#fun igraph_vector_ptr_destroy as ^ { castPtr `Ptr VectorPtr' } -> `()' #} withPtrs :: [Ptr a] -> (Ptr VectorPtr -> IO b) -> IO b withPtrs xs fun = allocaVectorPtrN n $ \vptr -> do sequence_ $ zipWith (igraphVectorPtrSet vptr) [0..] $ map castPtr xs fun vptr where n = length xs {-# INLINE withPtrs #-} toLists :: Ptr VectorPtr -> IO [[Double]] toLists vptr = do n <- igraphVectorPtrSize vptr forM [0..n-1] $ \i -> igraphVectorPtrE vptr i >>= toList . castPtr {-# INLINE toLists #-} {#fun igraph_vector_ptr_e as ^ { castPtr `Ptr VectorPtr', `Int' } -> `Ptr ()' #} {#fun igraph_vector_ptr_set as ^ { castPtr `Ptr VectorPtr', `Int', id `Ptr ()' } -> `()' #} {#fun igraph_vector_ptr_size as ^ { castPtr `Ptr VectorPtr' } -> `Int' #} -------------------------------------------------------------------------------- -- Customized string vector -------------------------------------------------------------------------------- data BSLen toByteString :: Ptr BSLen -> IO B.ByteString toByteString ptr = do n <- {#get bytestring_t->len #} ptr str <- {#get bytestring_t->value #} ptr packCStringLen (str, fromIntegral n) {-# INLINE toByteString #-} withByteString :: B.ByteString -> (Ptr BSLen -> IO a) -> IO a withByteString x f = unsafeUseAsCStringLen x $ \(str, n) -> allocaBytes {#sizeof bytestring_t #} $ \ptr -> do {#set bytestring_t.len #} ptr (fromIntegral n) {#set bytestring_t.value #} ptr str f ptr {-# INLINE withByteString #-} data BSVector allocaBSVectorN :: Int -> (Ptr BSVector -> IO a) -> IO a allocaBSVectorN n fun = allocaBytes {# sizeof bsvector_t #} $ \ptr -> bracket_ (bsvectorInit ptr n) (bsvectorDestroy ptr) (fun ptr) {-# INLINE allocaBSVectorN #-} {#fun bsvector_init as ^ { castPtr `Ptr BSVector', `Int' } -> `CInt' void- #} {#fun bsvector_destroy as ^ { castPtr `Ptr BSVector' } -> `()' #} withByteStrings :: [B.ByteString] -> (Ptr BSVector -> IO a) -> IO a withByteStrings xs fun = allocaBSVectorN n $ \bsvec -> do foldM_ (\i x -> bsvectorSet bsvec i x >> return (i+1)) 0 xs fun bsvec where n = length xs {-# INLINE withByteStrings #-} bsvectorSet :: Ptr BSVector -> Int -> B.ByteString -> IO () bsvectorSet vec i bs = withByteString bs (bsvectorSet' vec i) {-# INLINE bsvectorSet #-} {#fun bsvector_set as bsvectorSet' { castPtr `Ptr BSVector', `Int', castPtr `Ptr BSLen' } -> `()' #} -------------------------------------------------------------------------------- -- Matrix -------------------------------------------------------------------------------- data Matrix allocaMatrix :: (Ptr Matrix -> IO a) -> IO a allocaMatrix fun = allocaBytes {# sizeof igraph_matrix_t #} $ \mat -> bracket_ (igraphMatrixInit mat 0 0) (igraphMatrixDestroy mat) (fun mat) {-# INLINE allocaMatrix #-} allocaMatrixN :: Int -- ^ Number of rows -> Int -- ^ Number of columns -> (Ptr Matrix -> IO a) -> IO a allocaMatrixN r c fun = allocaBytes {# sizeof igraph_matrix_t #} $ \mat -> bracket_ (igraphMatrixInit mat r c) (igraphMatrixDestroy mat) (fun mat) {-# INLINE allocaMatrixN #-} {#fun igraph_matrix_init as ^ { castPtr `Ptr Matrix', `Int', `Int' } -> `CInt' void- #} {#fun igraph_matrix_destroy as ^ { castPtr `Ptr Matrix' } -> `()' #} -- row lists to matrix withRowLists :: Real a => [[a]] -> (Ptr Matrix -> IO b) -> IO b withRowLists xs fun | all (==c) $ map length xs = allocaMatrixN r c $ \mat -> do forM_ (zip [0..] xs) $ \(i, row) -> forM_ (zip [0..] row) $ \(j,v) -> igraphMatrixSet mat i j $ realToFrac v fun mat | otherwise = error "Not a matrix." where r = length xs c = length $ head xs {-# INLINE withRowLists #-} -- to row lists toRowLists :: Ptr Matrix -> IO [[Double]] toRowLists = fmap transpose . toColumnLists toColumnLists :: Ptr Matrix -> IO [[Double]] toColumnLists mptr = do r <- igraphMatrixNrow mptr c <- igraphMatrixNcol mptr xs <- allocaArray (r*c) $ \ptr -> do igraphMatrixCopyTo mptr ptr peekArray (r*c) ptr return $ chunksOf r $ map realToFrac xs {#fun igraph_matrix_null as ^ { castPtr `Ptr Matrix' } -> `()' #} {#fun igraph_matrix_fill as ^ { castPtr `Ptr Matrix', `Double' } -> `()' #} {#fun igraph_matrix_e as ^ { castPtr `Ptr Matrix', `Int', `Int' } -> `Double' #} {#fun igraph_matrix_set as ^ { castPtr `Ptr Matrix', `Int', `Int', `Double' } -> `()' #} {#fun igraph_matrix_copy_to as ^ { castPtr `Ptr Matrix', id `Ptr CDouble' } -> `()' #} {#fun igraph_matrix_nrow as ^ { castPtr `Ptr Matrix' } -> `Int' #} {#fun igraph_matrix_ncol as ^ { castPtr `Ptr Matrix' } -> `Int' #} -------------------------------------------------------------------------------- -- Graph Constructors and Destructors -------------------------------------------------------------------------------- {#pointer *igraph_t as IGraph foreign finalizer igraph_destroy newtype#} allocaIGraph :: (Ptr IGraph -> IO a) -> IO a allocaIGraph f = mallocBytes {# sizeof igraph_t #} >>= f {-# INLINE allocaIGraph #-} mkLabelToId :: (Ord v, Serialize v) => IGraph -> M.Map v [Int] mkLabelToId gr = unsafePerformIO $ do n <- igraphVcount gr fmap (M.fromListWith (++)) $ forM [0..n-1] $ \i -> do l <- igraphHaskellAttributeVAS gr vertexAttr i >>= toByteString >>= return . fromRight (error "decode failed") . decode return (l, [i]) {-# INLINE mkLabelToId #-} initializeNullAttribute :: PrimMonad m => IGraph -> m () initializeNullAttribute gr = unsafePrimToPrim $ do nn <- igraphVcount gr unsafePrimToPrim $ withByteStrings (map encode $ replicate nn ()) $ igraphHaskellAttributeVASSetv gr vertexAttr ne <- igraphEcount gr unsafePrimToPrim $ withByteStrings (map encode $ replicate ne ()) $ igraphHaskellAttributeEASSetv gr edgeAttr {-# INLINE initializeNullAttribute #-} addIGraphFinalizer :: Ptr IGraph -> IO IGraph addIGraphFinalizer ptr = do vec <- newForeignPtr igraph_destroy ptr return $ IGraph vec {-# INLINE addIGraphFinalizer #-} -- | Create a igraph object and attach a finalizer igraphNew :: Int -> Bool -> HasInit -> IO IGraph igraphNew n directed _ = igraphNew' n directed {#fun igraph_empty as igraphNew' { allocaIGraph- `IGraph' addIGraphFinalizer* , `Int', `Bool' } -> `CInt' void- #} {#fun igraph_copy as ^ { allocaIGraph- `IGraph' addIGraphFinalizer* , `IGraph' } -> `CInt' void- #} {#fun igraph_create as ^ { allocaIGraph- `IGraph' addIGraphFinalizer* , castPtr `Ptr Vector' -- ^ The edges to add, the first two elements are -- the first edge, etc. , `Int' -- ^ The number of vertices in the graph, if smaller or equal to -- the highest vertex id in the edges vector it will be -- increased automatically. So it is safe to give 0 here. , `Bool' -- ^ Whether to create a directed graph or not. If yes, -- then the first edge points from the first vertex id in edges -- to the second, etc. } -> `CInt' void- #} -- | A graph is a simple graph if it does not contain loop edges and multiple edges. {#fun igraph_is_simple as ^ { `IGraph' , alloca- `Bool' peekBool* } -> `CInt' void- #} {#fun igraph_has_multiple as ^ { `IGraph' , alloca- `Bool' peekBool* } -> `CInt' void- #} {#fun igraph_to_directed as ^ { `IGraph' -- ^ The graph object to convert. , `ToDirected' -- ^ Specifies the details of how exactly the conversion is -- done. Possible values: IGRAPH_TO_DIRECTED_ARBITRARY: -- the number of edges in the graph stays the same, -- an arbitrarily directed edge is created for each -- undirected edge; IGRAPH_TO_DIRECTED_MUTUAL: two directed -- edges are created for each undirected edge, one in each direction. } -> `CInt' void- #} -------------------------------------------------------------------------------- -- Vertex selector -------------------------------------------------------------------------------- data VertexSelector allocaVertexSelector :: (Ptr VertexSelector -> IO a) -> IO a allocaVertexSelector fun = allocaBytes {# sizeof igraph_vs_t #} $ \vs -> do r <- fun vs igraphVsDestroy vs return r {-# INLINE allocaVertexSelector #-} {#fun igraph_vs_destroy as ^ { castPtr `Ptr VertexSelector' } -> `()' #} withVerticesAll :: (Ptr VertexSelector -> IO a) -> IO a withVerticesAll fun = allocaVertexSelector $ \vs -> igraphVsAll vs >> fun vs {-# INLINE withVerticesAll #-} {#fun igraph_vs_all as ^ { castPtr `Ptr VertexSelector' } -> `CInt' void- #} withVerticesAdj :: Int -> Neimode -> (Ptr VertexSelector -> IO a) -> IO a withVerticesAdj i mode fun = allocaVertexSelector $ \vs -> igraphVsAdj vs i mode >> fun vs {-# INLINE withVerticesAdj #-} {#fun igraph_vs_adj as ^ { castPtr `Ptr VertexSelector', `Int', `Neimode' } -> `CInt' void- #} withVerticesVector :: Ptr Vector -> (Ptr VertexSelector -> IO a) -> IO a withVerticesVector vec fun = allocaVertexSelector $ \vs -> igraphVsVector vs vec >> fun vs {-# INLINE withVerticesVector #-} {#fun igraph_vs_vector as ^ { castPtr `Ptr VertexSelector', castPtr `Ptr Vector' } -> `CInt' void- #} withVerticesList :: Real a => [a] -> (Ptr VertexSelector -> IO b) -> IO b withVerticesList xs fun = withList xs $ \vec -> withVerticesVector vec fun {-# INLINE withVerticesList #-} -------------------------------------------------------------------------------- -- Vertex iterator -------------------------------------------------------------------------------- data VertexIterator iterateVertices :: IGraph -> Ptr VertexSelector -> (Ptr VertexIterator -> IO a) -> IO a iterateVertices gr vs fun = allocaBytes {# sizeof igraph_vit_t #} $ \vit -> bracket_ (igraphVitCreate gr vs vit) (igraphVitDestroy vit) (fun vit) {-# INLINE iterateVertices #-} iterateVerticesC :: IGraph -> Ptr VertexSelector -> (ConduitT i Int IO () -> IO a) -> IO a iterateVerticesC gr vs fun = allocaBytes {# sizeof igraph_vit_t #} $ \vit -> bracket_ (igraphVitCreate gr vs vit) (igraphVitDestroy vit) (fun $ sourceVertexIterator vit) {-# INLINE iterateVerticesC #-} {#fun igraph_vit_create as ^ { `IGraph' , castPtr %`Ptr VertexSelector' , castPtr `Ptr VertexIterator' } -> `CInt' void- #} {#fun igraph_vit_destroy as ^ { castPtr `Ptr VertexIterator' } -> `()' #} sourceVertexIterator :: Ptr VertexIterator -> ConduitT i Int IO () sourceVertexIterator vit = do isEnd <- liftIO $ igraphVitEnd vit if isEnd then return () else do liftIO (igraphVitGet vit) >>= yield liftIO $ igraphVitNext vit sourceVertexIterator vit {-# INLINE sourceVertexIterator #-} #c igraph_bool_t igraph_vit_end(igraph_vit_t *vit) { return IGRAPH_VIT_END(*vit); } void igraph_vit_next(igraph_vit_t *vit) { IGRAPH_VIT_NEXT(*vit); } igraph_integer_t igraph_vit_get(igraph_vit_t *vit) { return IGRAPH_VIT_GET(*vit); } #endc {#fun igraph_vit_end as ^ { castPtr `Ptr VertexIterator' } -> `Bool' #} {#fun igraph_vit_next as ^ { castPtr `Ptr VertexIterator' } -> `()' #} {#fun igraph_vit_get as ^ { castPtr `Ptr VertexIterator' } -> `Int' #} -------------------------------------------------------------------------------- -- Edge Selector -------------------------------------------------------------------------------- data EdgeSelector allocaEdgeSelector :: (Ptr EdgeSelector -> IO a) -> IO a allocaEdgeSelector fun = allocaBytes {# sizeof igraph_es_t #} $ \es -> do r <- fun es igraphEsDestroy es return r {-# INLINE allocaEdgeSelector #-} {#fun igraph_es_destroy as ^ { castPtr `Ptr EdgeSelector' } -> `()' #} withEdgesAll :: EdgeOrderType -> (Ptr EdgeSelector -> IO a) -> IO a withEdgesAll ord fun = allocaEdgeSelector $ \es -> igraphEsAll es ord >> fun es {-# INLINE withEdgesAll #-} {#fun igraph_es_all as ^ { castPtr `Ptr EdgeSelector', `EdgeOrderType'} -> `CInt' void- #} withEdgeIdsVector :: Ptr Vector -> (Ptr EdgeSelector -> IO a) -> IO a withEdgeIdsVector vec fun = allocaEdgeSelector $ \es -> igraphEsVector es vec >> fun es {-# INLINE withEdgeIdsVector #-} {# fun igraph_es_vector as ^ { castPtr `Ptr EdgeSelector', castPtr `Ptr Vector' } -> `CInt' void- #} withEdgeIdsList :: [Int] -> (Ptr EdgeSelector -> IO b) -> IO b withEdgeIdsList xs fun = withList xs $ \vec -> withEdgeIdsVector vec fun {-# INLINE withEdgeIdsList #-} -------------------------------------------------------------------------------- -- Edge iterator -------------------------------------------------------------------------------- data EdgeIterator iterateEdges :: IGraph -> Ptr EdgeSelector -> (Ptr EdgeIterator -> IO a) -> IO a iterateEdges gr es fun = allocaBytes {# sizeof igraph_eit_t #} $ \eit -> bracket_ (igraphEitCreate gr es eit) (igraphEitDestroy eit) (fun eit) {-# INLINE iterateEdges #-} {#fun igraph_eit_create as ^ { `IGraph', castPtr %`Ptr EdgeSelector', castPtr `Ptr EdgeIterator' } -> `CInt' void- #} {#fun igraph_eit_destroy as ^ { castPtr `Ptr EdgeIterator' } -> `()' #} iterateEdgesC :: IGraph -> Ptr EdgeSelector -> (ConduitT i Int IO () -> IO a) -> IO a iterateEdgesC gr es fun = allocaBytes {# sizeof igraph_eit_t #} $ \eit -> bracket_ (igraphEitCreate gr es eit) (igraphEitDestroy eit) (fun $ sourceEdgeIterator eit) {-# INLINE iterateEdgesC #-} sourceEdgeIterator :: Ptr EdgeIterator -> ConduitT i Int IO () sourceEdgeIterator eit = do isEnd <- liftIO $ igraphEitEnd eit if isEnd then return () else do liftIO (igraphEitGet eit) >>= yield liftIO $ igraphEitNext eit sourceEdgeIterator eit {-# INLINE sourceEdgeIterator #-} #c igraph_bool_t igraph_eit_end(igraph_eit_t *eit) { return IGRAPH_EIT_END(*eit); } void igraph_eit_next(igraph_eit_t *eit) { IGRAPH_EIT_NEXT(*eit); } igraph_integer_t igraph_eit_get(igraph_eit_t *eit) { return IGRAPH_EIT_GET(*eit); } #endc {#fun igraph_eit_end as ^ { castPtr `Ptr EdgeIterator' } -> `Bool' #} {#fun igraph_eit_next as ^ { castPtr `Ptr EdgeIterator' } -> `()' #} {#fun igraph_eit_get as ^ { castPtr `Ptr EdgeIterator' } -> `Int' #} -------------------------------------------------------------------------------- -- Basic Query Operations -------------------------------------------------------------------------------- {#fun igraph_vcount as ^ { `IGraph' } -> `Int' #} {#fun igraph_ecount as ^ { `IGraph' } -> `Int' #} {#fun igraph_get_eid as ^ { `IGraph' , alloca- `Int' peekIntConv* , `Int' , `Int' , `Bool' , `Bool' } -> `CInt' void-#} {#fun igraph_edge as ^ { `IGraph' , `Int' , alloca- `Int' peekIntConv* , alloca- `Int' peekIntConv* } -> `CInt' void-#} -- Adding and Deleting Vertices and Edges {# fun igraph_add_vertices as ^ { `IGraph', `Int', id `Ptr ()' } -> `()' #} {# fun igraph_add_edge as ^ { `IGraph', `Int', `Int' } -> `()' #} -- | The edges are given in a vector, the first two elements define the first -- edge (the order is from , to for directed graphs). The vector should -- contain even number of integer numbers between zero and the number of -- vertices in the graph minus one (inclusive). If you also want to add -- new vertices, call igraph_add_vertices() first. {# fun igraph_add_edges as ^ { `IGraph' -- ^ The graph to which the edges will be added. , castPtr `Ptr Vector' -- ^ The edges themselves. , id `Ptr ()' -- ^ The attributes of the new edges. } -> `()' #} -- | delete vertices {# fun igraph_delete_vertices as ^ { `IGraph', castPtr %`Ptr VertexSelector' } -> `CInt' void- #} -- | delete edges {# fun igraph_delete_edges as ^ { `IGraph', castPtr %`Ptr EdgeSelector' } -> `CInt' void- #} data AttributeRecord withAttr :: Serialize a => String -- ^ Attribute name -> [a] -- ^ Attributes -> (Ptr AttributeRecord -> IO b) -> IO b withAttr name xs fun = withByteStrings (map encode xs) $ \bsvec -> withBSAttr name bsvec fun {-# INLINE withAttr #-} withBSAttr :: String -- ^ Attribute name -> Ptr BSVector -- ^ Attributes -> (Ptr AttributeRecord -> IO b) -> IO b withBSAttr name bsvec fun = withCString name $ \name' -> allocaBytes {#sizeof igraph_attribute_record_t #} $ \attr -> setAttribute attr name' (castPtr bsvec) >> fun attr where setAttribute attr x y = do {#set igraph_attribute_record_t.name #} attr x {#set igraph_attribute_record_t.type #} attr 2 {#set igraph_attribute_record_t.value #} attr y {-# INLINE withBSAttr #-} -- | Checks whether a (graph, vertex or edge) attribute exists {#fun igraph_haskell_attribute_has_attr as ^ { `IGraph' , `AttributeElemtype' -- ^ The type of the attribute , `String' -- ^ The name of the attribute } -> `Bool' #} -- | Query a string vertex attribute {#fun igraph_haskell_attribute_VAS as ^ { `IGraph' , `String' -- ^ The name of the attribute , `Int' -- ^ The id of the queried vertex } -> `Ptr BSLen' castPtr #} -- | Query a string edge attribute. {#fun igraph_haskell_attribute_EAS as ^ { `IGraph' , `String' -- ^ The name of the attribute , `Int' -- ^ The id of the queried edge } -> `Ptr BSLen' castPtr #} {#fun igraph_haskell_attribute_VAS_set as ^ { `IGraph' , `String' , `Int' , castPtr `Ptr BSLen' } -> `CInt' void-#} {#fun igraph_haskell_attribute_VAS_setv as ^ { `IGraph' , `String' -- ^ Name of the attribute , castPtr `Ptr BSVector' -- ^ String vector, the new attribute values. -- The length of this vector must match the -- number of vertices. } -> `CInt' void-#} -- | Set a string edge attribute. {#fun igraph_haskell_attribute_EAS_set as ^ { `IGraph' , `String' -- ^ The name of the attribute , `Int' -- ^ The id of the queried vertex , castPtr `Ptr BSLen' -- ^ The (new) value of the attribute. } -> `CInt' void-#} -- | Set a string edge attribute for all edges. {#fun igraph_haskell_attribute_EAS_setv as ^ { `IGraph' , `String' -- ^ Name of the attribute , castPtr `Ptr BSVector' -- ^ String vector, the new attribute values. -- The length of this vector must match the -- number of edges. } -> `CInt' void-#} -------------------------------------------------------------------------------- -- Arpack options -------------------------------------------------------------------------------- data ArpackOpt allocaArpackOpt :: (Ptr ArpackOpt -> IO a) -> IO a allocaArpackOpt fun = allocaBytes {# sizeof igraph_arpack_options_t #} $ \opt -> do igraphArpackOptionsInit opt >> fun opt {-# INLINE allocaArpackOpt #-} {#fun igraph_arpack_options_init as ^ { castPtr `Ptr ArpackOpt' } -> `CInt' void- #}