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


{-# LINE 1 "src/IGraph/Generators.chs" #-}
{-# LANGUAGE ForeignFunctionInterface #-}
{-# LANGUAGE DataKinds #-}
{-# LANGUAGE ScopedTypeVariables #-}
module IGraph.Generators
    ( full
    , star
    , ErdosRenyiModel(..)
    , erdosRenyiGame
    , degreeSequenceGame
    , rewire
    ) where
import qualified Foreign.C.Types as C2HSImp
import qualified Foreign.Marshal.Utils as C2HSImp
import qualified Foreign.Ptr as C2HSImp



import           Control.Monad                  (when, forM_)
import           Data.Hashable                  (Hashable)
import           Data.Serialize                 (Serialize)
import Data.Singletons (SingI, Sing, sing, fromSing)
import System.IO.Unsafe (unsafePerformIO)

import qualified Foreign.Ptr as C2HSImp
import Foreign

import           IGraph
import           IGraph.Mutable (MGraph(..))
import qualified IGraph.Mutable as M
import IGraph.Internal
{-# LINE 25 "src/IGraph/Generators.chs" #-}

import IGraph.Internal.Constants
{-# LINE 26 "src/IGraph/Generators.chs" #-}

import IGraph.Internal.Initialization
{-# LINE 27 "src/IGraph/Generators.chs" #-}




full :: forall d. SingI d
     => Int   -- ^ The number of vertices in the graph.
     -> Bool  -- ^ Whether to include self-edges (loops)
     -> Graph d () ()
full n hasLoop = unsafePerformIO $ do
    gr <- MGraph <$> igraphFull n directed hasLoop
    M.initializeNullAttribute gr
    unsafeFreeze gr
  where
    directed = case fromSing (sing :: Sing d) of
        D -> True
        U -> False
igraphFull :: (Int) -> (Bool) -> (Bool) -> IO ((IGraph))
igraphFull a2 a3 a4 =
  allocaIGraph $ \a1' ->
  let {a2' = fromIntegral a2} in
  let {a3' = C2HSImp.fromBool a3} in
  let {a4' = C2HSImp.fromBool a4} in
  igraphFull'_ a1' a2' a3' a4' >>= \res ->
  addIGraphFinalizer  a1'>>= \a1'' ->
  return (a1'')

{-# LINE 46 "src/IGraph/Generators.chs" #-}


-- | Return the Star graph. The center node is always associated with id 0.
star :: Int    -- ^ The number of nodes
     -> Graph 'U () ()
star n = unsafePerformIO $ do
    gr <- MGraph <$> igraphStar n IgraphStarUndirected 0
    M.initializeNullAttribute gr
    unsafeFreeze gr
igraphStar :: (Int) -> (StarMode) -> (Int) -> IO ((IGraph))
igraphStar a2 a3 a4 =
  allocaIGraph $ \a1' ->
  let {a2' = fromIntegral a2} in
  let {a3' = (fromIntegral . fromEnum) a3} in
  let {a4' = fromIntegral a4} in
  igraphStar'_ a1' a2' a3' a4' >>= \res ->
  addIGraphFinalizer  a1'>>= \a1'' ->
  return (a1'')

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


data ErdosRenyiModel = GNP Int Double
                     | GNM Int Int

erdosRenyiGame :: forall d. SingI d
               => ErdosRenyiModel
               -> Bool  -- ^ self-loop
               -> IO (Graph d () ())
erdosRenyiGame model self = do
    igraphInit
    gr <- fmap MGraph $ case model of
        GNP n p -> igraphErdosRenyiGame IgraphErdosRenyiGnp n p directed self
        GNM n m -> igraphErdosRenyiGame IgraphErdosRenyiGnm n (fromIntegral m)
            directed self
    M.initializeNullAttribute gr
    unsafeFreeze gr
  where
    directed = case fromSing (sing :: Sing d) of
        D -> True
        U -> False
igraphErdosRenyiGame :: (ErdosRenyi) -> (Int) -> (Double) -> (Bool) -> (Bool) -> IO ((IGraph))
igraphErdosRenyiGame a2 a3 a4 a5 a6 =
  allocaIGraph $ \a1' ->
  let {a2' = (fromIntegral . fromEnum) a2} in
  let {a3' = fromIntegral a3} in
  let {a4' = realToFrac a4} in
  let {a5' = C2HSImp.fromBool a5} in
  let {a6' = C2HSImp.fromBool a6} in
  igraphErdosRenyiGame'_ a1' a2' a3' a4' a5' a6' >>= \res ->
  addIGraphFinalizer  a1'>>= \a1'' ->
  return (a1'')

{-# LINE 84 "src/IGraph/Generators.chs" #-}


-- | Generates a random graph with a given degree sequence.
degreeSequenceGame :: [Int]   -- ^ Out degree
                   -> [Int]   -- ^ In degree
                   -> IO (Graph 'D () ())
degreeSequenceGame out_deg in_deg = withList out_deg $ \out_deg' ->
    withList in_deg $ \in_deg' -> do
        gr <- MGraph <$> igraphDegreeSequenceGame out_deg' in_deg' IgraphDegseqSimple
        M.initializeNullAttribute gr
        unsafeFreeze gr
igraphDegreeSequenceGame :: (Ptr Vector) -> (Ptr Vector) -> (Degseq) -> IO ((IGraph))
igraphDegreeSequenceGame a2 a3 a4 =
  allocaIGraph $ \a1' ->
  let {a2' = castPtr a2} in
  let {a3' = castPtr a3} in
  let {a4' = (fromIntegral . fromEnum) a4} in
  igraphDegreeSequenceGame'_ a1' a2' a3' a4' >>= \res ->
  addIGraphFinalizer  a1'>>= \a1'' ->
  return (a1'')

{-# LINE 98 "src/IGraph/Generators.chs" #-}


-- | Randomly rewires a graph while preserving the degree distribution.
rewire :: (Hashable v, Serialize v, Eq v, Serialize e)
       => Int    -- ^ Number of rewiring trials to perform.
       -> Graph d v e
       -> IO (Graph d v e)
rewire n gr = do
    (MGraph gptr) <- thaw gr
    igraphRewire gptr n IgraphRewiringSimple
    unsafeFreeze $ MGraph gptr
igraphRewire :: (IGraph) -> (Int) -> (Rewiring) -> IO ()
igraphRewire a1 a2 a3 =
  (withIGraph) a1 $ \a1' ->
  let {a2' = fromIntegral a2} in
  let {a3' = (fromIntegral . fromEnum) a3} in
  igraphRewire'_ a1' a2' a3' >>= \res ->
  return ()

{-# LINE 109 "src/IGraph/Generators.chs" #-}


foreign import ccall safe "IGraph/Generators.chs.h igraph_full"
  igraphFull'_ :: ((C2HSImp.Ptr (IGraph)) -> (C2HSImp.CInt -> (C2HSImp.CInt -> (C2HSImp.CInt -> (IO C2HSImp.CInt)))))

foreign import ccall safe "IGraph/Generators.chs.h igraph_star"
  igraphStar'_ :: ((C2HSImp.Ptr (IGraph)) -> (C2HSImp.CInt -> (C2HSImp.CInt -> (C2HSImp.CInt -> (IO C2HSImp.CInt)))))

foreign import ccall safe "IGraph/Generators.chs.h igraph_erdos_renyi_game"
  igraphErdosRenyiGame'_ :: ((C2HSImp.Ptr (IGraph)) -> (C2HSImp.CInt -> (C2HSImp.CInt -> (C2HSImp.CDouble -> (C2HSImp.CInt -> (C2HSImp.CInt -> (IO C2HSImp.CInt)))))))

foreign import ccall safe "IGraph/Generators.chs.h igraph_degree_sequence_game"
  igraphDegreeSequenceGame'_ :: ((C2HSImp.Ptr (IGraph)) -> ((C2HSImp.Ptr ()) -> ((C2HSImp.Ptr ()) -> (C2HSImp.CInt -> (IO C2HSImp.CInt)))))

foreign import ccall safe "IGraph/Generators.chs.h igraph_rewire"
  igraphRewire'_ :: ((C2HSImp.Ptr (IGraph)) -> (C2HSImp.CInt -> (C2HSImp.CInt -> (IO C2HSImp.CInt))))