@@ -20,7 +20,7 @@
2020module Main (main) where
2121
2222import Control.DeepSeq (NFData(..))
23−import Control.Exception (SomeException)
23+import Control.Exception (SomeException, ErrorCall, try)
2424import Streamly.Internal.Data.Unfold (Unfold)
2525import System.IO (Handle, hClose)
2626import System.Random (randomRIO)
@@ -397,29 +397,13 @@ teeZipWith size start =
397397 drainProductDefault (size + start) (UF.teeZipWith (+)) start
398398
399399-------------------------------------------------------------------------------
400−-- Nested
400+-- Applicative
401401-------------------------------------------------------------------------------
402402
403−{-# INLINE concatMapM #-}
404−concatMapM :: Monad m => Int -> Int -> m ()
405−concatMapM size start =
406− drainGeneration (UF.concatMapM unfoldInGen unfoldOut) start
407−
408− where
409−
410− sizeOuter = 100
411− sizeInner = size `div` sizeOuter
412−
413− unfoldInGen i =
414− return
415− $ UF.supply (UF.enumerateFromToIntegral (i + sizeInner)) i
416−
417− unfoldOut = UF.enumerateFromToIntegral (start + sizeOuter)
418−
419403{-# INLINE toNullAp #-}
420404toNullAp :: Monad m => Int -> Int -> m ()
421−toNullAp linearCount start =
422− let end = start + Nested.nestedCount2 linearCount
405+toNullAp value start =
406+ let end = start + nthRoot 2 value
423407 s = Nested.source end
424408 in UF.fold ((+) <$> s <*> s) FL.drain start
425409
@@ -431,6 +415,128 @@ _apDiscardFst = undefined
431415_apDiscardSnd :: Int -> Int -> m ()
432416_apDiscardSnd = undefined
433417
418+-------------------------------------------------------------------------------
419+-- Monad
420+-------------------------------------------------------------------------------
421+
422+nthRoot :: Double -> Int -> Int
423+nthRoot n value = round (fromIntegral value**(1/n))
424+
425+{-# INLINE concatMapM #-}
426+concatMapM :: Monad m => Int -> Int -> m ()
427+concatMapM value start =
428+ val `seq` drainGeneration (UF.concatMapM unfoldInGen unfoldOut) start
429+
430+ where
431+
432+ val = nthRoot 2 value
433+ unfoldInGen i = return (UF.enumerateFromToIntegral (i + val))
434+ unfoldOut = UF.enumerateFromToIntegral (start + val)
435+
436+{-# INLINE toNull #-}
437+toNull :: Monad m => Int -> Int -> m ()
438+toNull value start =
439+ let end = start + nthRoot 2 value
440+ src = Nested.source end
441+ u = do
442+ x <- src
443+ y <- src
444+ return (x + y)
445+ in UF.fold u FL.drain start
446+
447+
448+{-# INLINE toNull3 #-}
449+toNull3 :: Monad m => Int -> Int -> m ()
450+toNull3 value start =
451+ let end = start + nthRoot 3 value
452+ src = Nested.source end
453+ u = do
454+ x <- src
455+ y <- src
456+ z <- src
457+ return (x + y + z)
458+ in UF.fold u FL.drain start
459+
460+{-# INLINE toList #-}
461+toList :: Monad m => Int -> Int -> m [Int]
462+toList value start = do
463+ let end = start + nthRoot 2 value
464+ src = Nested.source end
465+ u = do
466+ x <- src
467+ y <- src
468+ return (x + y)
469+ in UF.fold u FL.toList start
470+
471+{-# INLINE toListSome #-}
472+toListSome :: Monad m => Int -> Int -> m [Int]
473+toListSome value start = do
474+ let end = start + nthRoot 2 value
475+ src = Nested.source end
476+ u = do
477+ x <- src
478+ y <- src
479+ return (x + y)
480+ in UF.fold (UF.take 1000 u) FL.toList start
481+
482+{-# INLINE filterAllOut #-}
483+filterAllOut :: Monad m => Int -> Int -> m ()
484+filterAllOut value start = do
485+ let end = start + nthRoot 2 value
486+ src = Nested.source end
487+ u = do
488+ x <- src
489+ y <- src
490+ let s = x + y
491+ if s < 0
492+ then return s
493+ else UF.nilM (return . const ())
494+ in UF.fold u FL.drain start
495+
496+{-# INLINE filterAllIn #-}
497+filterAllIn :: Monad m => Int -> Int -> m ()
498+filterAllIn value start = do
499+ let end = start + nthRoot 2 value
500+ src = Nested.source end
501+ u = do
502+ x <- src
503+ y <- src
504+ let s = x + y
505+ if s > 0
506+ then return s
507+ else UF.nilM (return . const ())
508+ in UF.fold u FL.drain start
509+
510+{-# INLINE filterSome #-}
511+filterSome :: Monad m => Int -> Int -> m ()
512+filterSome value start = do
513+ let end = start + nthRoot 2 value
514+ src = Nested.source end
515+ u = do
516+ x <- src
517+ y <- src
518+ let s = x + y
519+ if s > 1100000
520+ then return s
521+ else UF.nilM (return . const ())
522+ in UF.fold u FL.drain start
523+
524+{-# INLINE breakAfterSome #-}
525+breakAfterSome :: Int -> Int -> IO ()
526+breakAfterSome value start =
527+ let end = start + nthRoot 2 value
528+ src = Nested.source end
529+ u = do
530+ x <- src
531+ y <- src
532+ let s = x + y
533+ if s > 1100000
534+ then error "break"
535+ else return s
536+ in do
537+ (_ :: Either ErrorCall ()) <- try $ UF.fold u FL.drain start
538+ return ()
539+
434540-------------------------------------------------------------------------------
435541-- Benchmarks
436542-------------------------------------------------------------------------------
@@ -529,29 +635,30 @@ o_1_space_zip size =
529635o_1_space_nested :: Int -> [Benchmark]
530636o_1_space_nested size =
531637 [ bgroup
532− "outer-product"
533− [ benchIO "toNullAp" $ toNullAp size
534− , benchIO "toNull" $ Nested.toNull size
535− , benchIO "toNull3" $ Nested.toNull3 size
536− , benchIO "concat" $ Nested.concat size
537− , benchIO "breakAfterSome" $ Nested.breakAfterSome size
538− , benchIO "filterAllOut" $ Nested.filterAllOut size
539− , benchIO "filterAllIn" $ Nested.filterAllIn size
540− , benchIO "filterSome" $ Nested.filterSome size
541− , benchIO "concatMapM (100 x n/100)" $ concatMapM size
638+ "nested"
639+ [ benchIO "(<*>) (sqrt n x sqrt n)" $ toNullAp size
542640 -- Unimplemented
543− -- , benchIO "ap" $ ap size
544641 -- , benchIO "apDiscardFst" $ apDiscardFst size
545642 -- , benchIO "apDiscardSnd" $ apDiscardSnd size
643+
644+ , benchIO "concatMapM (sqrt n x sqrt n)" $ concatMapM size
645+ , benchIO "(>>=) (sqrt n x sqrt n)" $ toNull size
646+ , benchIO "(>>=) (cubert n x cubert n x cubert n)" $ toNull3 size
647+ , benchIO "breakAfterSome" $ breakAfterSome size
648+ , benchIO "filterAllOut" $ filterAllOut size
649+ , benchIO "filterAllIn" $ filterAllIn size
650+ , benchIO "filterSome" $ filterSome size
651+
652+ , benchIO "concat" $ Nested.concat size
546653 ]
547654 ]
548655
549656o_n_space_nested :: Int -> [Benchmark]
550657o_n_space_nested size =
551658 [ bgroup
552− "outer-product"
553− [ benchIO "toList" $ Nested.toList size
554− , benchIO "toListSome" $ Nested.toListSome size
659+ "nested"
660+ [ benchIO "toList" $ toList size
661+ , benchIO "toListSome" $ toListSome size
555662 ]
556663 ]
557664