packages feed

streamly-0.7.0: benchmark/NestedUnfoldOps.hs

-- |
-- Module      : NestedUnfoldOps
-- Copyright   : (c) 2019 Composewell Technologies
--
-- License     : BSD3
-- Maintainer  : streamly@composewell.com

module NestedUnfoldOps where

import Control.Monad.IO.Class (MonadIO (..))
import Streamly.Internal.Data.Unfold (Unfold)

import qualified Streamly.Internal.Data.Unfold as UF
import qualified Streamly.Internal.Data.Fold as FL

linearCount :: Int
linearCount = 100000

-- n * (n + 1) / 2 == linearCount
concatCount :: Int
concatCount = 450

-- double nested loop
nestedCount2 :: Int
nestedCount2 = round (fromIntegral linearCount**(1/2::Double))

-- triple nested loop
nestedCount3 :: Int
nestedCount3 = round (fromIntegral linearCount**(1/3::Double))

-------------------------------------------------------------------------------
-- Stream generation and elimination
-------------------------------------------------------------------------------

-- generate numbers up to the argument value
{-# INLINE source #-}
source :: Monad m => Int -> Unfold m Int Int
source n = UF.enumerateFromToIntegral n

-------------------------------------------------------------------------------
-- Benchmark ops
-------------------------------------------------------------------------------

{-# INLINE toNull #-}
toNull :: MonadIO m => Int -> m ()
toNull start = do
    let end = start + nestedCount2
    UF.fold
        (UF.map (\(x, y) -> x + y)
        $ UF.outerProduct (source end) (source end))
        FL.drain (start, start)

{-# INLINE toNull3 #-}
toNull3 :: MonadIO m => Int -> m ()
toNull3 start = do
    let end = start + nestedCount3
    UF.fold
            (UF.map (\(x, y) -> x + y)
            $ UF.outerProduct (source end)
                ((UF.map (\(x, y) -> x + y)
                $ UF.outerProduct (source end) (source end))))
            FL.drain (start, (start, start))

{-# INLINE concat #-}
concat :: MonadIO m => Int -> m ()
concat start = do
    let end = start + concatCount
    UF.fold
        (UF.concat (source end) (source end))
        FL.drain start

{-# INLINE toList #-}
toList :: MonadIO m => Int -> m [Int]
toList start = do
    let end = start + nestedCount2
    UF.fold
        (UF.map (\(x, y) -> x + y)
        $ UF.outerProduct (source end) (source end))
        FL.toList (start, start)

{-# INLINE toListSome #-}
toListSome :: MonadIO m => Int -> m [Int]
toListSome start = do
    let end = start + nestedCount2
    UF.fold
        (UF.take 1000 $ (UF.map (\(x, y) -> x + y)
            $ UF.outerProduct (source end) (source end)))
        FL.toList (start, start)

{-# INLINE filterAllOut #-}
filterAllOut :: MonadIO m => Int -> m ()
filterAllOut start = do
    let end = start + nestedCount2
    UF.fold
        (UF.filter (< 0)
        $ UF.map (\(x, y) -> x + y)
        $ UF.outerProduct (source end) (source end))
        FL.drain (start, start)

{-# INLINE filterAllIn #-}
filterAllIn :: MonadIO m => Int -> m ()
filterAllIn start = do
    let end = start + nestedCount2
    UF.fold
        (UF.filter (> 0)
        $ UF.map (\(x, y) -> x + y)
        $ UF.outerProduct (source end) (source end))
        FL.drain (start, start)

{-# INLINE filterSome #-}
filterSome :: MonadIO m => Int -> m ()
filterSome start = do
    let end = start + nestedCount2
    UF.fold
        (UF.filter (> 1100000)
        $ UF.map (\(x, y) -> x + y)
        $ UF.outerProduct (source end) (source end))
        FL.drain (start, start)

{-# INLINE breakAfterSome #-}
breakAfterSome :: MonadIO m => Int -> m ()
breakAfterSome start = do
    let end = start + nestedCount2
    UF.fold
        (UF.takeWhile (<= 1100000)
        $ UF.map (\(x, y) -> x + y)
        $ UF.outerProduct (source end) (source end))
        FL.drain (start, start)