streamly/benchmark/Streamly/Benchmark/Data/ArrayOps.hs
2021-11-17 12:55:57 +05:30

247 lines
7.2 KiB
Haskell

-- |
-- Module : Streamly.Benchmark.Data.ArrayOps
-- Copyright : (c) 2020 Composewell Technologies
--
-- License : BSD-3-Clause
-- Maintainer : streamly@composewell.com
{-# LANGUAGE CPP #-}
{-# LANGUAGE FlexibleContexts #-}
{-# LANGUAGE ScopedTypeVariables #-}
-- CPP:
-- MEMORY_ARRAY
-- DATA_ARRAY
-- DATA_ARRAY_PRIM
-- DATA_ARRAY_PRIM_PINNED
-- DATA_SMALLARRAY
module Streamly.Benchmark.Data.ArrayOps where
import Control.Monad.IO.Class (MonadIO)
import Prelude (Bool, Int, Maybe(..), ($), (+), (.), (==), (>), undefined)
import qualified Prelude as P
import qualified Streamly.Prelude as S
#if !defined(DATA_ARRAY_PRIM) && !defined(DATA_ARRAY_PRIM_PINNED)
#ifdef DEVBUILD
{-
import qualified Data.Foldable as F
-}
#endif
#endif
#ifdef DATA_SMALLARRAY
import qualified Streamly.Internal.Data.SmallArray as A
type Stream = A.SmallArray
#elif defined(MEMORY_ARRAY)
import qualified GHC.Exts as GHC
import qualified Streamly.Data.Array.Foreign as A
import qualified Streamly.Internal.Data.Array.Foreign as A
type Stream = A.Array
#elif defined(DATA_ARRAY_PRIM)
import qualified Streamly.Internal.Data.Array.Prim as A
type Stream = A.Array
#elif defined(DATA_ARRAY_PRIM_PINNED)
import qualified Streamly.Internal.Data.Array.Prim.Pinned as A
type Stream = A.Array
#elif defined(DATA_ARRAY)
import qualified Streamly.Internal.Data.Array as A
type Stream = A.Array
#endif
-------------------------------------------------------------------------------
-- Benchmark ops
-------------------------------------------------------------------------------
-------------------------------------------------------------------------------
-- Stream generation and elimination
-------------------------------------------------------------------------------
-------------------------------------------------------------------------------
-- CPP Common to:
-- MEMORY_ARRAY
-- DATA_ARRAY
-- DATA_ARRAY_PRIM
-- DATA_ARRAY_PRIM_PINNED
-- DATA_SMALLARRAY
-------------------------------------------------------------------------------
{-# INLINE sourceUnfoldr #-}
sourceUnfoldr :: MonadIO m => Int -> Int -> m (Stream Int)
sourceUnfoldr value n = S.fold (A.writeN value) $ S.unfoldr step n
where
step cnt =
if cnt > n + value
then Nothing
else (Just (cnt, cnt + 1))
{-# INLINE sourceIntFromTo #-}
sourceIntFromTo :: MonadIO m => Int -> Int -> m (Stream Int)
sourceIntFromTo value n = S.fold (A.writeN value) $ S.enumerateFromTo n (n + value)
{-# INLINE sourceFromList #-}
sourceFromList :: MonadIO m => Int -> Int -> m (Stream Int)
sourceFromList value n = S.fold (A.writeN value) $ S.fromList [n..n+value]
-- Different defination of sourceIntFromToFromList for DATA_SMALLARRAY
-- CPP:
{-# INLINE sourceIntFromToFromList #-}
sourceIntFromToFromList :: MonadIO m => Int -> Int -> m (Stream Int)
#ifndef DATA_SMALLARRAY
sourceIntFromToFromList value n = P.return $ A.fromList $ [n..n + value]
#else
sourceIntFromToFromList value n = P.return $ A.fromListN value $ [n..n + value]
#endif
-------------------------------------------------------------------------------
-- CPP Common to:
-- MEMORY_ARRAY
-- DATA_ARRAY
-- DATA_ARRAY_PRIM
-- DATA_ARRAY_PRIM_PINNED
-------------------------------------------------------------------------------
-- CPP:
#ifndef DATA_SMALLARRAY
{-# INLINE sourceIntFromToFromStream #-}
sourceIntFromToFromStream :: MonadIO m => Int -> Int -> m (Stream Int)
sourceIntFromToFromStream value n = S.fold A.write $ S.enumerateFromTo n (n + value)
#endif
-------------------------------------------------------------------------------
-- CPP Common to:
-- MEMORY_ARRAY
-------------------------------------------------------------------------------
-- CPP:
#ifdef MEMORY_ARRAY
{-# INLINE sourceIsList #-}
sourceIsList :: Int -> Int -> Stream Int
sourceIsList value n = GHC.fromList [n..n+value]
{-# INLINE sourceIsString #-}
sourceIsString :: Int -> Int -> Stream P.Char
sourceIsString value n = GHC.fromString (P.replicate (n + value) 'a')
#endif
-------------------------------------------------------------------------------
-- Transformation
-------------------------------------------------------------------------------
-------------------------------------------------------------------------------
-- CPP Common to:
-- MEMORY_ARRAY
-- DATA_ARRAY
-- DATA_ARRAY_PRIM
-- DATA_ARRAY_PRIM_PINNED
-- DATA_SMALLARRAY
-------------------------------------------------------------------------------
{-# INLINE composeN #-}
composeN :: P.Monad m
=> Int -> (Stream Int -> m (Stream Int)) -> Stream Int -> m (Stream Int)
composeN n f x =
case n of
1 -> f x
2 -> f x P.>>= f
3 -> f x P.>>= f P.>>= f
4 -> f x P.>>= f P.>>= f P.>>= f
_ -> undefined
{-# INLINE scanl' #-}
{-# INLINE scanl1' #-}
{-# INLINE map #-}
scanl' , scanl1', map
:: MonadIO m => Int -> Int -> Stream Int -> m (Stream Int)
{-# INLINE onArray #-}
onArray
:: MonadIO m => Int -> (S.SerialT m Int -> S.SerialT m Int)
-> Stream Int
-> m (Stream Int)
onArray value f arr = S.fold (A.writeN value) $ f $ (S.unfold A.read arr)
scanl' value n = composeN n $ onArray value $ S.scanl' (+) 0
scanl1' value n = composeN n $ onArray value $ S.scanl1' (+)
map value n = composeN n $ onArray value $ S.map (+1)
-- map n = composeN n $ A.map (+1)
{-# INLINE eqInstance #-}
eqInstance :: Stream Int -> Bool
eqInstance src = src == src
{-# INLINE eqInstanceNotEq #-}
eqInstanceNotEq :: Stream Int -> Bool
eqInstanceNotEq src = src P./= src
{-# INLINE ordInstance #-}
ordInstance :: Stream Int -> Bool
ordInstance src = src P.< src
{-# INLINE ordInstanceMin #-}
ordInstanceMin :: Stream Int -> Stream Int
ordInstanceMin src = P.min src src
{-# INLINE showInstance #-}
showInstance :: Stream Int -> P.String
showInstance src = P.show src
{-# INLINE pureFoldl' #-}
pureFoldl' :: MonadIO m => Stream Int -> m Int
pureFoldl' = S.foldl' (+) 0 . S.unfold A.read
-------------------------------------------------------------------------------
-- CPP Common to:
-- MEMORY_ARRAY
-- DATA_ARRAY
-- DATA_SMALLARRAY
-------------------------------------------------------------------------------
-- CPP:
#if !defined(DATA_ARRAY_PRIM) && !defined(DATA_ARRAY_PRIM_PINNED)
{-# INLINE readInstance #-}
readInstance :: P.String -> Stream Int
readInstance str =
let r = P.reads str
in case r of
[(x,"")] -> x
_ -> P.error "readInstance: no parse"
#ifdef DEVBUILD
{-
{-# INLINE foldableFoldl' #-}
foldableFoldl' :: Stream Int -> Int
foldableFoldl' = F.foldl' (+) 0
{-# INLINE foldableSum #-}
foldableSum :: Stream Int -> Int
foldableSum = P.sum
-}
#endif
#endif
-------------------------------------------------------------------------------
-- Elimination
-------------------------------------------------------------------------------
-------------------------------------------------------------------------------
-- CPP Common to:
-- MEMORY_ARRAY
-- DATA_ARRAY
-- DATA_ARRAY_PRIM
-- DATA_ARRAY_PRIM_PINNED
-- DATA_SMALLARRAY
-------------------------------------------------------------------------------
{-# INLINE unfoldReadDrain #-}
unfoldReadDrain :: MonadIO m => Stream Int -> m ()
unfoldReadDrain = S.drain . S.unfold A.read
{-# INLINE toStreamRevDrain #-}
toStreamRevDrain :: MonadIO m => Stream Int -> m ()
toStreamRevDrain = S.drain . A.toStreamRev