packages feed

accelerate-examples-1.0.0.0: examples/pagerank/Page.hs

{-# LANGUAGE PatternGuards   #-}
{-# LANGUAGE RecordWildCards #-}
{-# LANGUAGE TypeFamilies    #-}

module Page (

  PageId, Rank, Link, MLinks(..),
  parsePage, parsePageId

) where

import Prelude                                   as P
import qualified Data.ByteString.Lazy.Char8      as BL
import qualified Data.Vector.Storable.Mutable    as UM
import Data.Word


-- | Unique identifier for a page.
type PageId
        = Word32


-- | Represents a link in the page raph.
type Link
        = (PageId, PageId)


-- | A single PageRank value.
type Rank
        = Float

-- | A mutable set of links
data MLinks
        = MLinks
            { ml_ix    :: Int
            , ml_size  :: Int
            , ml_from  :: UM.IOVector PageId
            , ml_to    :: UM.IOVector PageId
            , ml_sizes :: UM.IOVector Int
            }


-- | Parse just the PageId from a line in the links file.
parsePageId :: BL.ByteString -> Maybe PageId
parsePageId bs
        | Just (pid, _)         <- BL.readInt bs
        = Just $ fromIntegral pid

        | otherwise
        = Nothing


-- | Parse a whole line of the links file.
parsePage :: BL.ByteString -> MLinks -> IO (Maybe MLinks)
parsePage bs links
        | Just (pid, bs2)       <- BL.readInt bs
        , Just bs3              <- char ':' bs2
        = do
             links'             <- pageIds (fromIntegral pid) bs3 links
             return (Just links')

        | otherwise
        = return Nothing


-- | Parse a single character.
char   :: Char -> BL.ByteString -> Maybe BL.ByteString
char c bs
 | BL.null bs           = Nothing
 | BL.head bs == c      = Just (BL.tail bs)
 | otherwise            = Nothing
{-# INLINE char #-}


-- | Parse a vector of PageIds.
pageIds    :: PageId -> BL.ByteString -> MLinks -> IO (MLinks)
pageIds pid bs0 links0
 = go links0 0 bs0

 where  go links@(MLinks{..}) count bs
         | ml_ix >= ml_size
         = do   from'  <- UM.grow ml_from ml_size
                to'    <- UM.grow ml_to   ml_size
                go (MLinks ml_ix (2*ml_size) from' to' ml_sizes) count bs

         | BL.null bs
         = final

         | Just bs2     <- char ' ' bs
         = go links count bs2

         | Just (i, bs2) <- BL.readInt bs
         = do   UM.write ml_from ml_ix pid
                UM.write ml_to   ml_ix (fromIntegral i)
                go (MLinks (ml_ix+1) ml_size ml_from ml_to ml_sizes) (count+1) bs2

         | otherwise
         = final
         where
            final =
                do
                    UM.write ml_sizes (fromIntegral pid) count
                    return links