haskell-igraph-0.5.0: src/IGraph/Internal.chs
{-# LANGUAGE ForeignFunctionInterface #-}
module IGraph.Internal
( module IGraph.Internal.Types
-- * Vector type and basic operations
, igraphVectorNew
, fromList
, toList
, igraphVectorNull
, igraphVectorFill
, igraphVectorE
, igraphVectorSet
, igraphVectorTail
, igraphVectorSize
, igraphVectorCopyTo
-- * Pointer vector
, igraphVectorPtrNew
, fromPtrs
, toLists
-- * String vector
, igraphStrvectorNew
, igraphStrvectorGet
, toStrVector
-- * Bytestring
, asBS
, bsToByteString
-- * Bytestring vector
, bsvectorNew
, bsvectorSet
, toBSVector
-- * Igraph matrix type
, igraphMatrixNew
, igraphMatrixNull
, igraphMatrixFill
, igraphMatrixE
, igraphMatrixSet
, igraphMatrixCopyTo
, igraphMatrixNrow
, igraphMatrixNcol
, fromRowLists
, toRowLists
, toColumnLists
-- * Igraph vertex selector
, igraphVsAll
, igraphVsAdj
, igraphVsVector
-- * Igraph vertex iterator
, igraphVitNew
, vitToList
-- * Igraph edge Selector
, igraphEsAll
, igraphEsVector
-- * Igraph edge iterator
, igraphEitNew
, eitToList
-- * IGraph type and basic operations
, igraphNew
, igraphCopy
, igraphVcount
, igraphEcount
, igraphGetEid
, igraphEdge
, igraphAddVertices
, igraphAddEdge
, igraphAddEdges
, igraphDeleteVertices
, igraphDeleteEdges
-- * Igraph attribute record
, withAttr
, igraphHaskellAttributeHasAttr
, igraphHaskellAttributeGANSet
, igraphHaskellAttributeGAN
, igraphHaskellAttributeVAS
, igraphHaskellAttributeEAN
, igraphHaskellAttributeEAS
, igraphHaskellAttributeEASSetv
, igraphHaskellAttributeVASSet
, igraphHaskellAttributeEASSet
) 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 Data.List.Split (chunksOf)
import Foreign
import Foreign.C.Types
import Foreign.C.String
import IGraph.Internal.C2HS
{#import IGraph.Internal.Initialization #}
{#import IGraph.Internal.Types #}
{#import IGraph.Internal.Constants #}
#include "haskell_attributes.h"
#include "haskell_igraph.h"
--------------------------------------------------------------------------------
-- Igraph vector
--------------------------------------------------------------------------------
{#fun igraph_vector_init as igraphVectorNew
{ allocaVector- `Vector' addVectorFinalizer*
, `Int' } -> `CInt' void- #}
{#fun igraph_vector_init_copy as ^
{ allocaVector- `Vector' addVectorFinalizer*
, id `Ptr CDouble', `Int' } -> `CInt' void- #}
fromList :: [Double] -> IO Vector
fromList xs = withArrayLen (map realToFrac xs) $ \n ptr ->
igraphVectorInitCopy ptr n
{-# INLINE fromList #-}
toList :: Vector -> IO [Double]
toList vec = do
n <- igraphVectorSize vec
allocaArray n $ \ptr -> do
igraphVectorCopyTo vec ptr
liftM (map realToFrac) $ peekArray n ptr
{-# INLINE toList #-}
-- Initializing elements
{#fun igraph_vector_null as ^ { `Vector' } -> `()' #}
{#fun igraph_vector_fill as ^ { `Vector', `Double' } -> `()' #}
-- Accessing elements
{#fun pure igraph_vector_e as ^ { `Vector', `Int' } -> `Double' #}
{#fun igraph_vector_set as ^ { `Vector', `Int', `Double' } -> `()' #}
{#fun pure igraph_vector_tail as ^ { `Vector' } -> `Double' #}
-- Copying vectors
{#fun igraph_vector_copy_to as ^ { `Vector', id `Ptr CDouble' } -> `()' #}
-- Vector properties
{#fun igraph_vector_size as ^ { `Vector' } -> `Int' #}
{#fun igraph_vector_ptr_init as igraphVectorPtrNew
{ allocaVectorPtr- `VectorPtr' addVectorPtrFinalizer*
, `Int' } -> `CInt' void- #}
{#fun igraph_vector_ptr_e as ^ { `VectorPtr', `Int' } -> `Ptr ()' #}
{#fun igraph_vector_ptr_set as ^ { `VectorPtr', `Int', id `Ptr ()' } -> `()' #}
{#fun igraph_vector_ptr_size as ^ { `VectorPtr' } -> `Int' #}
fromPtrs :: [Ptr ()] -> IO VectorPtr
fromPtrs xs = do
vptr <- igraphVectorPtrNew n
forM_ (zip [0..] xs) $ \(i,x) -> igraphVectorPtrSet vptr i x
return vptr
where
n = length xs
{-# INLINE fromPtrs #-}
toLists :: VectorPtr -> IO [[Double]]
toLists vpptr = do
n <- igraphVectorPtrSize vpptr
forM [0..n-1] $ \i -> do
vptr <- igraphVectorPtrE vpptr i
vec <- newForeignPtr_ $ castPtr vptr
toList $ Vector vec
{-# INLINE toLists #-}
--------------------------------------------------------------------------------
-- Igraph string vector
--------------------------------------------------------------------------------
{#fun igraph_strvector_init as igraphStrvectorNew
{ allocaStrVector- `StrVector' addStrVectorFinalizer*
, `Int'
} -> `CInt' void-#}
{#fun igraph_strvector_get as ^
{ `StrVector'
, `Int'
, alloca- `String' peekString*
} -> `CInt' void-#}
peekString :: Ptr CString -> IO String
peekString ptr = peek ptr >>= peekCString
{-# INLINE peekString #-}
{#fun igraph_strvector_set as ^ { `StrVector', `Int', id `CString'} -> `()' #}
{#fun igraph_strvector_set2 as ^ { `StrVector', `Int', id `CString', `Int'} -> `()' #}
toStrVector :: [B.ByteString] -> IO StrVector
toStrVector xs = do
vec <- igraphStrvectorNew n
forM_ (zip [0..] xs) $ \(i,x) -> B.useAsCString x (igraphStrvectorSet vec i)
return vec
where
n = length xs
--------------------------------------------------------------------------------
-- Customized string vector
--------------------------------------------------------------------------------
bsToByteString :: Ptr BSLen -> IO B.ByteString
bsToByteString ptr = do
n <- {#get bytestring_t->len #} ptr
str <- {#get bytestring_t->value #} ptr
packCStringLen (str, fromIntegral n)
{-# INLINE bsToByteString #-}
asBS :: B.ByteString -> (Ptr BSLen -> IO a) -> IO a
asBS x f = unsafeUseAsCStringLen x $ \(str, n) -> do
fptr <- mallocForeignPtrBytes {#sizeof bytestring_t #}
withForeignPtr fptr $ \ptr -> do
{#set bytestring_t.len #} ptr (fromIntegral n)
{#set bytestring_t.value #} ptr str
f ptr
{-# INLINE asBS #-}
{#fun bsvector_init as bsvectorNew
{ allocaBSVector- `BSVector' addBSVectorFinalizer*
, `Int'
} -> `CInt' void- #}
{#fun bsvector_set as bsvectorSet' { `BSVector', `Int', castPtr `Ptr BSLen' } -> `()' #}
bsvectorSet :: BSVector -> Int -> B.ByteString -> IO ()
bsvectorSet vec i bs = asBS bs (bsvectorSet' vec i)
{-# INLINE bsvectorSet #-}
toBSVector :: [B.ByteString] -> IO BSVector
toBSVector xs = do
vec <- bsvectorNew n
foldM_ (\i x -> bsvectorSet vec i x >> return (i+1)) 0 xs
return vec
where
n = length xs
{#fun igraph_matrix_init as igraphMatrixNew
{ allocaMatrix- `Matrix' addMatrixFinalizer*
, `Int', `Int'
} -> `CInt' void- #}
{#fun igraph_matrix_null as ^ { `Matrix' } -> `()' #}
{#fun igraph_matrix_fill as ^ { `Matrix', `Double' } -> `()' #}
{#fun igraph_matrix_e as ^ { `Matrix', `Int', `Int' } -> `Double' #}
{#fun igraph_matrix_set as ^ { `Matrix', `Int', `Int', `Double' } -> `()' #}
{#fun igraph_matrix_copy_to as ^ { `Matrix', id `Ptr CDouble' } -> `()' #}
{#fun igraph_matrix_nrow as ^ { `Matrix' } -> `Int' #}
{#fun igraph_matrix_ncol as ^ { `Matrix' } -> `Int' #}
-- row lists to matrix
fromRowLists :: [[Double]] -> IO Matrix
fromRowLists xs
| all (==c) $ map length xs = do
mptr <- igraphMatrixNew r c
forM_ (zip [0..] xs) $ \(i, row) ->
forM_ (zip [0..] row) $ \(j,v) ->
igraphMatrixSet mptr i j v
return mptr
| otherwise = error "Not a matrix."
where
r = length xs
c = length $ head xs
-- to row lists
toRowLists :: Matrix -> IO [[Double]]
toRowLists = liftM transpose . toColumnLists
toColumnLists :: 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_vs_all as ^
{ allocaVs- `IGraphVs' addVsFinalizer*
} -> `CInt' void- #}
{#fun igraph_vs_adj as ^
{ allocaVs- `IGraphVs' addVsFinalizer*
, `Int', `Neimode'
} -> `CInt' void- #}
{#fun igraph_vs_vector as ^
{ allocaVs- `IGraphVs' addVsFinalizer*
, `Vector'
} -> `CInt' void- #}
-- Vertex iterator
#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_create as igraphVitNew
{ `IGraph'
, %`IGraphVs'
, allocaVit- `IGraphVit' addVitFinalizer*
} -> `CInt' void- #}
{#fun igraph_vit_end as ^ { `IGraphVit' } -> `Bool' #}
{#fun igraph_vit_next as ^ { `IGraphVit' } -> `()' #}
{#fun igraph_vit_get as ^ { `IGraphVit' } -> `Int' #}
vitToList :: IGraphVit -> IO [Int]
vitToList vit = do
isEnd <- igraphVitEnd vit
if isEnd
then return []
else do
cur <- igraphVitGet vit
igraphVitNext vit
acc <- vitToList vit
return $ cur : acc
-- Edge Selector
{#fun igraph_es_all as ^
{ allocaEs- `IGraphEs' addEsFinalizer*
, `EdgeOrderType'
} -> `CInt' void- #}
{# fun igraph_es_vector as ^
{ allocaEs- `IGraphEs' addEsFinalizer*
, `Vector'
} -> `CInt' void- #}
-- Edge iterator
#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_create as igraphEitNew
{ `IGraph'
, %`IGraphEs'
, allocaEit- `IGraphEit' addEitFinalizer*
} -> `CInt' void- #}
{#fun igraph_eit_end as ^ { `IGraphEit' } -> `Bool' #}
{#fun igraph_eit_next as ^ { `IGraphEit' } -> `()' #}
{#fun igraph_eit_get as ^ { `IGraphEit' } -> `Int' #}
eitToList :: IGraphEit -> IO [Int]
eitToList eit = do
isEnd <- igraphEitEnd eit
if isEnd
then return []
else do
cur <- igraphEitGet eit
igraphEitNext eit
acc <- eitToList eit
return $ cur : acc
--------------------------------------------------------------------------------
-- Graph Constructors and Destructors
--------------------------------------------------------------------------------
{#fun igraph_empty as igraphNew'
{ allocaIGraph- `IGraph' addIGraphFinalizer*
, `Int', `Bool'
} -> `CInt' void- #}
{#fun igraph_copy as ^
{ allocaIGraph- `IGraph' addIGraphFinalizer*
, `IGraph'
} -> `CInt' void- #}
-- | Create a igraph object and attach a finalizer
igraphNew :: Int -> Bool -> HasInit -> IO IGraph
igraphNew n directed _ = igraphNew' n directed
--------------------------------------------------------------------------------
-- 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.
, `Vector' -- ^ The edges themselves.
, id `Ptr ()' -- ^ The attributes of the new edges.
} -> `()' #}
-- | delete vertices
{# fun igraph_delete_vertices as ^ { `IGraph', %`IGraphVs' } -> `Int' #}
-- | delete edges
{# fun igraph_delete_edges as ^ { `IGraph', %`IGraphEs' } -> `Int' #}
withAttr :: String
-> BSVector -> (Ptr AttributeRecord -> IO a) -> IO a
withAttr name bs f = withBSVector bs $ \ptr -> do
fptr <- mallocForeignPtrBytes {#sizeof igraph_attribute_record_t #}
withForeignPtr fptr $ \attr -> withCString name $ \name' -> do
{#set igraph_attribute_record_t.name #} attr name'
{#set igraph_attribute_record_t.type #} attr 2
{#set igraph_attribute_record_t.value #} attr $ castPtr ptr
f attr
{-# INLINE withAttr #-}
{#fun igraph_haskell_attribute_has_attr as ^ { `IGraph', `AttributeElemtype', `String' } -> `Bool' #}
{#fun igraph_haskell_attribute_GAN_set as ^ { `IGraph', `String', `Double' } -> `Int' #}
{#fun igraph_haskell_attribute_GAN as ^ { `IGraph', `String' } -> `Double' #}
{#fun igraph_haskell_attribute_VAS as ^ { `IGraph', `String', `Int' } -> `Ptr BSLen' castPtr #}
{#fun igraph_haskell_attribute_EAN as ^ { `IGraph', `String', `Int' } -> `Double' #}
{#fun igraph_haskell_attribute_EAS as ^ { `IGraph', `String', `Int' } -> `Ptr BSLen' castPtr #}
{#fun igraph_haskell_attribute_EAS_setv as ^ { `IGraph', `String', `BSVector' } -> `Int' #}
{#fun igraph_haskell_attribute_VAS_set as ^ { `IGraph', `String', `Int', castPtr `Ptr BSLen' } -> `Int' #}
{#fun igraph_haskell_attribute_EAS_set as ^ { `IGraph', `String', `Int', castPtr `Ptr BSLen' } -> `Int' #}