packages feed

haskell-igraph-0.1.0: src/IGraph/Internal/Data.chs

{-# LANGUAGE ForeignFunctionInterface #-}
module IGraph.Internal.Data where

import Control.Monad
import qualified Data.ByteString.Char8 as B
import Foreign
import Foreign.C.Types
import Foreign.C.String
import System.IO.Unsafe (unsafePerformIO)
import Data.List (transpose)
import Data.List.Split (chunksOf)

#include "cbits/haskelligraph.c"

{#pointer *igraph_vector_t as VectorPtr foreign finalizer igraph_vector_destroy newtype#}

-- Construtors and destructors

{#fun igraph_vector_init as igraphVectorNew { +, `Int' } -> `VectorPtr' #}

listToVector :: [Double] -> IO VectorPtr
listToVector xs = do
    vec <- igraphVectorNew n
    forM_ (zip [0..] xs) $ \(i,x) -> igraphVectorSet vec i x
    return vec
  where
    n = length xs

vectorPtrToList :: VectorPtr -> IO [Double]
vectorPtrToList vptr = do
    n <- igraphVectorSize vptr
    allocaArray n $ \ptr -> do
        igraphVectorCopyTo vptr ptr
        liftM (map realToFrac) $ peekArray n ptr

-- Initializing elements

{#fun igraph_vector_null as ^ { `VectorPtr' } -> `()' #}

{#fun igraph_vector_fill as ^ { `VectorPtr', `Double' } -> `()' #}


-- Accessing elements

{#fun pure igraph_vector_e as ^ { `VectorPtr', `Int' } -> `Double' #}

{#fun igraph_vector_set as ^ { `VectorPtr', `Int', `Double' } -> `()' #}

{#fun pure igraph_vector_tail as ^ { `VectorPtr' } -> `Double' #}


-- Copying vectors

{#fun igraph_vector_copy_to as ^ { `VectorPtr', id `Ptr CDouble' } -> `()' #}

-- Vector properties
{#fun igraph_vector_size as ^ { `VectorPtr' } -> `Int' #}


{#pointer *igraph_vector_ptr_t as VectorPPtr foreign finalizer igraph_vector_ptr_destroy_all newtype#}

{#fun igraph_vector_ptr_init as igraphVectorPtrNew { +, `Int' } -> `VectorPPtr' #}

{#fun igraph_vector_ptr_e as ^ { `VectorPPtr', `Int' } -> `Ptr ()' #}
{#fun igraph_vector_ptr_set as ^ { `VectorPPtr', `Int', id `Ptr ()' } -> `()' #}
{#fun igraph_vector_ptr_size as ^ { `VectorPPtr' } -> `Int' #}

listToVectorP :: [Ptr ()] -> IO VectorPPtr
listToVectorP xs = do
    vptr <- igraphVectorPtrNew n
    forM_ (zip [0..] xs) $ \(i,x) -> igraphVectorPtrSet vptr i x
    return vptr
  where
    n = length xs

vectorPPtrToList :: VectorPPtr -> IO [[Double]]
vectorPPtrToList vpptr = do
    n <- igraphVectorPtrSize vpptr
    forM [0..n-1] $ \i -> do
        vptr <- igraphVectorPtrE vpptr i
        fptr <- newForeignPtr_ $ castPtr vptr
        vectorPtrToList $ VectorPtr fptr


{#pointer *igraph_strvector_t as StrVectorPtr foreign finalizer igraph_strvector_destroy newtype#}

{#fun igraph_strvector_init as igraphStrvectorNew { +, `Int' } -> `StrVectorPtr' #}

{#fun igraph_strvector_get_ as igraphStrvectorGet' { `StrVectorPtr', `Int' } -> `Ptr CString' id #}

igraphStrvectorGet :: StrVectorPtr -> Int -> String
igraphStrvectorGet vec i = unsafePerformIO $ do
    ptr <- igraphStrvectorGet' vec i
    peek ptr >>= peekCString

{#fun igraph_strvector_set as ^ { `StrVectorPtr', `Int', id `CString'} -> `()' #}
{#fun igraph_strvector_set2 as ^ { `StrVectorPtr', `Int', id `CString', `Int'} -> `()' #}

listToStrVector :: [B.ByteString] -> IO StrVectorPtr
listToStrVector xs = do
    vec <- igraphStrvectorNew n
    forM_ (zip [0..] xs) $ \(i,x) -> B.useAsCString x (igraphStrvectorSet vec i)
    return vec
  where
    n = length xs


{#pointer *igraph_matrix_t as MatrixPtr foreign finalizer igraph_matrix_destroy newtype#}

{#fun igraph_matrix_init as igraphMatrixNew { +, `Int', `Int' } -> `MatrixPtr' #}

{#fun igraph_matrix_null as ^ { `MatrixPtr' } -> `()' #}

{#fun igraph_matrix_fill as ^ { `MatrixPtr', `Double' } -> `()' #}

{#fun igraph_matrix_e as ^ { `MatrixPtr', `Int', `Int' } -> `Double' #}

{#fun igraph_matrix_set as ^ { `MatrixPtr', `Int', `Int', `Double' } -> `()' #}

{#fun igraph_matrix_copy_to as ^ { `MatrixPtr', id `Ptr CDouble' } -> `()' #}

{#fun igraph_matrix_nrow as ^ { `MatrixPtr' } -> `Int' #}

{#fun igraph_matrix_ncol as ^ { `MatrixPtr' } -> `Int' #}

-- row lists to matrix
listsToMatrixPtr :: [[Double]] -> IO MatrixPtr
listsToMatrixPtr 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
  where
    r = length xs
    c = maximum $ map length xs

-- to row lists
matrixPtrToLists :: MatrixPtr -> IO [[Double]]
matrixPtrToLists = liftM transpose . matrixPtrToColumnLists

matrixPtrToColumnLists :: MatrixPtr -> IO [[Double]]
matrixPtrToColumnLists 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