-- GENERATED by C->Haskell Compiler, version 0.28.3 Switcheroo, 25 November 2017 (Haskell)
-- Edit the ORIGNAL .chs file instead!


{-# LINE 1 "src/IGraph/Structure.chs" #-}
{-# LANGUAGE ForeignFunctionInterface #-}
module IGraph.Structure
    ( inducedSubgraph
    , closeness
    , betweenness
    , eigenvectorCentrality
    , pagerank
    ) where
import qualified Foreign.C.Types as C2HSImp
import qualified Foreign.Marshal.Utils as C2HSImp
import qualified Foreign.Ptr as C2HSImp



import           Control.Monad
import           Data.Either               (fromRight)
import           Data.Hashable             (Hashable)
import qualified Data.HashMap.Strict       as M
import           Data.Serialize            (Serialize, decode)
import           System.IO.Unsafe          (unsafePerformIO)
import Data.Maybe
import Data.Singletons (SingI)

import Foreign
import Foreign.C.Types

import           IGraph
import           IGraph.Mutable (MGraph(..))
import IGraph.Internal
{-# LINE 24 "src/IGraph/Structure.chs" #-}

import IGraph.Internal.Constants
{-# LINE 25 "src/IGraph/Structure.chs" #-}




inducedSubgraph :: (Hashable v, Eq v, Serialize v)
                => Graph d v e
                -> [Int]
                -> Graph d v e
inducedSubgraph gr nds = unsafePerformIO $ withVerticesList nds $ \vs ->
    igraphInducedSubgraph (_graph gr) vs IgraphSubgraphCreateFromScratch >>=
        unsafeFreeze . MGraph
igraphInducedSubgraph :: (IGraph) -> (Ptr VertexSelector) -> (SubgraphImplementation) -> IO ((IGraph))
igraphInducedSubgraph a1 a3 a4 =
  (withIGraph) a1 $ \a1' ->
  allocaIGraph $ \a2' ->
  let {a3' = castPtr a3} in
  let {a4' = (fromIntegral . fromEnum) a4} in
  igraphInducedSubgraph'_ a1' a2' a3' a4' >>= \res ->
  addIGraphFinalizer  a2'>>= \a2'' ->
  return (a2'')

{-# LINE 41 "src/IGraph/Structure.chs" #-}


-- | Closeness centrality
closeness :: [Int]  -- ^ vertices
          -> Graph d v e
          -> Maybe [Double]  -- ^ optional edge weights
          -> Neimode
          -> Bool   -- ^ whether to normalize
          -> [Double]
closeness nds gr ws mode normal = unsafePerformIO $ allocaVector $ \result ->
    withVerticesList nds $ \vs -> withListMaybe ws $ \ws' -> do
        igraphCloseness (_graph gr) result vs mode ws' normal
        toList result
igraphCloseness :: (IGraph) -> (Ptr Vector) -> (Ptr VertexSelector) -> (Neimode) -> (Ptr Vector) -> (Bool) -> IO ()
igraphCloseness a1 a2 a3 a4 a5 a6 =
  (withIGraph) a1 $ \a1' ->
  let {a2' = castPtr a2} in
  let {a3' = castPtr a3} in
  let {a4' = (fromIntegral . fromEnum) a4} in
  let {a5' = castPtr a5} in
  let {a6' = C2HSImp.fromBool a6} in
  igraphCloseness'_ a1' a2' a3' a4' a5' a6' >>= \res ->
  return ()

{-# LINE 60 "src/IGraph/Structure.chs" #-}



-- | Betweenness centrality
betweenness :: [Int]
            -> Graph d v e
            -> Maybe [Double]
            -> [Double]
betweenness nds gr ws = unsafePerformIO $ allocaVector $ \result ->
    withVerticesList nds $ \vs -> withListMaybe ws $ \ws' -> do
        igraphBetweenness (_graph gr) result vs True ws' False
        toList result
igraphBetweenness :: (IGraph) -> (Ptr Vector) -> (Ptr VertexSelector) -> (Bool) -> (Ptr Vector) -> (Bool) -> IO ()
igraphBetweenness a1 a2 a3 a4 a5 a6 =
  (withIGraph) a1 $ \a1' ->
  let {a2' = castPtr a2} in
  let {a3' = castPtr a3} in
  let {a4' = C2HSImp.fromBool a4} in
  let {a5' = castPtr a5} in
  let {a6' = C2HSImp.fromBool a6} in
  igraphBetweenness'_ a1' a2' a3' a4' a5' a6' >>= \res ->
  return ()

{-# LINE 78 "src/IGraph/Structure.chs" #-}


-- | Eigenvector centrality
eigenvectorCentrality :: Graph d v e
                      -> Maybe [Double]
                      -> [Double]
eigenvectorCentrality gr ws = unsafePerformIO $ allocaArpackOpt $ \arparck ->
    allocaVector $ \result -> withListMaybe ws $ \ws' -> do
        igraphEigenvectorCentrality (_graph gr) result nullPtr True True ws' arparck
        toList result
igraphEigenvectorCentrality :: (IGraph) -> (Ptr Vector) -> (Ptr CDouble) -> (Bool) -> (Bool) -> (Ptr Vector) -> (Ptr ArpackOpt) -> IO ()
igraphEigenvectorCentrality a1 a2 a3 a4 a5 a6 a7 =
  (withIGraph) a1 $ \a1' ->
  let {a2' = castPtr a2} in
  let {a3' = id a3} in
  let {a4' = C2HSImp.fromBool a4} in
  let {a5' = C2HSImp.fromBool a5} in
  let {a6' = castPtr a6} in
  let {a7' = castPtr a7} in
  igraphEigenvectorCentrality'_ a1' a2' a3' a4' a5' a6' a7' >>= \res ->
  return ()

{-# LINE 95 "src/IGraph/Structure.chs" #-}


-- | Google's PageRank algorithm, with option to
pagerank :: SingI d
         => Graph d v e
         -> Maybe [Double]  -- ^ Node weights or reset probability. If provided,
                            -- the personalized PageRank will be used
         -> Maybe [Double]  -- ^ Edge weights
         -> Double  -- ^ damping factor, usually around 0.85
         -> [Double]
pagerank gr reset ws d
    | n == 0 = []
    | isJust ws && length (fromJust ws) /= m = error "incorrect length of edge weight vector"
    | otherwise = unsafePerformIO $ alloca $ \p -> allocaVector $ \result ->
        withVerticesAll $ \vs -> withListMaybe ws $ \ws' -> do
            case reset of
                Nothing -> igraphPagerank (_graph gr) IgraphPagerankAlgoPrpack
                    result p vs (isDirected gr) d ws' nullPtr
                Just reset' -> withList reset' $ \reset'' -> igraphPersonalizedPagerank
                    (_graph gr) IgraphPagerankAlgoPrpack result p vs
                    (isDirected gr) d reset'' ws' nullPtr
            toList result
  where
    n = nNodes gr
    m = nEdges gr

igraphPagerank :: (IGraph) -> (PagerankAlgo) -> (Ptr Vector) -> (Ptr CDouble) -> (Ptr VertexSelector) -> (Bool) -> (Double) -> (Ptr Vector) -> (Ptr ()) -> IO ()
igraphPagerank a1 a2 a3 a4 a5 a6 a7 a8 a9 =
  (withIGraph) a1 $ \a1' ->
  let {a2' = (fromIntegral . fromEnum) a2} in
  let {a3' = castPtr a3} in
  let {a4' = id a4} in
  let {a5' = castPtr a5} in
  let {a6' = C2HSImp.fromBool a6} in
  let {a7' = realToFrac a7} in
  let {a8' = castPtr a8} in
  let {a9' = id a9} in
  igraphPagerank'_ a1' a2' a3' a4' a5' a6' a7' a8' a9' >>= \res ->
  return ()

{-# LINE 131 "src/IGraph/Structure.chs" #-}


igraphPersonalizedPagerank :: (IGraph) -> (PagerankAlgo) -> (Ptr Vector) -> (Ptr CDouble) -> (Ptr VertexSelector) -> (Bool) -> (Double) -> (Ptr Vector) -> (Ptr Vector) -> (Ptr ()) -> IO ()
igraphPersonalizedPagerank a1 a2 a3 a4 a5 a6 a7 a8 a9 a10 =
  (withIGraph) a1 $ \a1' ->
  let {a2' = (fromIntegral . fromEnum) a2} in
  let {a3' = castPtr a3} in
  let {a4' = id a4} in
  let {a5' = castPtr a5} in
  let {a6' = C2HSImp.fromBool a6} in
  let {a7' = realToFrac a7} in
  let {a8' = castPtr a8} in
  let {a9' = castPtr a9} in
  let {a10' = id a10} in
  igraphPersonalizedPagerank'_ a1' a2' a3' a4' a5' a6' a7' a8' a9' a10' >>= \res ->
  return ()

{-# LINE 144 "src/IGraph/Structure.chs" #-}


foreign import ccall safe "IGraph/Structure.chs.h __c2hs_wrapped__igraph_induced_subgraph"
  igraphInducedSubgraph'_ :: ((C2HSImp.Ptr (IGraph)) -> ((C2HSImp.Ptr (IGraph)) -> ((C2HSImp.Ptr ()) -> (C2HSImp.CInt -> (IO C2HSImp.CInt)))))

foreign import ccall safe "IGraph/Structure.chs.h __c2hs_wrapped__igraph_closeness"
  igraphCloseness'_ :: ((C2HSImp.Ptr (IGraph)) -> ((C2HSImp.Ptr ()) -> ((C2HSImp.Ptr ()) -> (C2HSImp.CInt -> ((C2HSImp.Ptr ()) -> (C2HSImp.CInt -> (IO C2HSImp.CInt)))))))

foreign import ccall safe "IGraph/Structure.chs.h __c2hs_wrapped__igraph_betweenness"
  igraphBetweenness'_ :: ((C2HSImp.Ptr (IGraph)) -> ((C2HSImp.Ptr ()) -> ((C2HSImp.Ptr ()) -> (C2HSImp.CInt -> ((C2HSImp.Ptr ()) -> (C2HSImp.CInt -> (IO C2HSImp.CInt)))))))

foreign import ccall safe "IGraph/Structure.chs.h igraph_eigenvector_centrality"
  igraphEigenvectorCentrality'_ :: ((C2HSImp.Ptr (IGraph)) -> ((C2HSImp.Ptr ()) -> ((C2HSImp.Ptr C2HSImp.CDouble) -> (C2HSImp.CInt -> (C2HSImp.CInt -> ((C2HSImp.Ptr ()) -> ((C2HSImp.Ptr ()) -> (IO C2HSImp.CInt))))))))

foreign import ccall safe "IGraph/Structure.chs.h __c2hs_wrapped__igraph_pagerank"
  igraphPagerank'_ :: ((C2HSImp.Ptr (IGraph)) -> (C2HSImp.CInt -> ((C2HSImp.Ptr ()) -> ((C2HSImp.Ptr C2HSImp.CDouble) -> ((C2HSImp.Ptr ()) -> (C2HSImp.CInt -> (C2HSImp.CDouble -> ((C2HSImp.Ptr ()) -> ((C2HSImp.Ptr ()) -> (IO C2HSImp.CInt))))))))))

foreign import ccall safe "IGraph/Structure.chs.h __c2hs_wrapped__igraph_personalized_pagerank"
  igraphPersonalizedPagerank'_ :: ((C2HSImp.Ptr (IGraph)) -> (C2HSImp.CInt -> ((C2HSImp.Ptr ()) -> ((C2HSImp.Ptr C2HSImp.CDouble) -> ((C2HSImp.Ptr ()) -> (C2HSImp.CInt -> (C2HSImp.CDouble -> ((C2HSImp.Ptr ()) -> ((C2HSImp.Ptr ()) -> ((C2HSImp.Ptr ()) -> (IO C2HSImp.CInt)))))))))))