module Streamly.Internal.Data.Fold.Window
(
windowLmap
, cumulative
, windowRollingMap
, windowRollingMapM
, windowLength
, windowSum
, windowSumInt
, windowPowerSum
, windowPowerSumFrac
, windowMinimum
, windowMaximum
, windowRange
, windowMean
)
where
import Control.Monad.IO.Class (MonadIO (liftIO))
import Data.Bifunctor(bimap)
import Foreign.Storable (Storable, peek)
import Streamly.Internal.Data.Fold.Type (Fold(..), Step(..))
import Streamly.Internal.Data.Tuple.Strict
(Tuple'(..), Tuple3Fused' (Tuple3Fused'))
import Foreign.ForeignPtr.Unsafe (unsafeForeignPtrToPtr)
import qualified Streamly.Internal.Data.Fold.Type as Fold
import qualified Streamly.Internal.Data.Ring as Ring
import Prelude hiding (length, sum, minimum, maximum)
{-# INLINE windowLmap #-}
windowLmap :: (c -> a) -> Fold m (a, Maybe a) b -> Fold m (c, Maybe c) b
windowLmap :: forall c a (m :: * -> *) b.
(c -> a) -> Fold m (a, Maybe a) b -> Fold m (c, Maybe c) b
windowLmap c -> a
f = forall a b (m :: * -> *) r. (a -> b) -> Fold m b r -> Fold m a r
Fold.lmap (forall (p :: * -> * -> *) a b c d.
Bifunctor p =>
(a -> b) -> (c -> d) -> p a c -> p b d
bimap c -> a
f (c -> a
f forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$>))
{-# INLINE cumulative #-}
cumulative :: Fold m (a, Maybe a) b -> Fold m a b
cumulative :: forall (m :: * -> *) a b. Fold m (a, Maybe a) b -> Fold m a b
cumulative = forall a b (m :: * -> *) r. (a -> b) -> Fold m b r -> Fold m a r
Fold.lmap (, forall a. Maybe a
Nothing)
{-# INLINE windowRollingMapM #-}
windowRollingMapM :: Monad m =>
(Maybe a -> a -> m (Maybe b)) -> Fold m (a, Maybe a) (Maybe b)
windowRollingMapM :: forall (m :: * -> *) a b.
Monad m =>
(Maybe a -> a -> m (Maybe b)) -> Fold m (a, Maybe a) (Maybe b)
windowRollingMapM Maybe a -> a -> m (Maybe b)
f = forall (m :: * -> *) b a.
Monad m =>
(b -> a -> m b) -> m b -> Fold m a b
Fold.foldlM' forall {p}. p -> (a, Maybe a) -> m (Maybe b)
f1 forall {a}. m (Maybe a)
initial
where
initial :: m (Maybe a)
initial = forall (m :: * -> *) a. Monad m => a -> m a
return forall a. Maybe a
Nothing
f1 :: p -> (a, Maybe a) -> m (Maybe b)
f1 p
_ (a
a, Maybe a
ma) = Maybe a -> a -> m (Maybe b)
f Maybe a
ma a
a
{-# INLINE windowRollingMap #-}
windowRollingMap :: Monad m =>
(Maybe a -> a -> Maybe b) -> Fold m (a, Maybe a) (Maybe b)
windowRollingMap :: forall (m :: * -> *) a b.
Monad m =>
(Maybe a -> a -> Maybe b) -> Fold m (a, Maybe a) (Maybe b)
windowRollingMap Maybe a -> a -> Maybe b
f = forall (m :: * -> *) b a.
Monad m =>
(b -> a -> b) -> b -> Fold m a b
Fold.foldl' forall {p}. p -> (a, Maybe a) -> Maybe b
f1 forall a. Maybe a
initial
where
initial :: Maybe a
initial = forall a. Maybe a
Nothing
f1 :: p -> (a, Maybe a) -> Maybe b
f1 p
_ (a
a, Maybe a
ma) = Maybe a -> a -> Maybe b
f Maybe a
ma a
a
{-# INLINE windowSumInt #-}
windowSumInt :: forall m a. (Monad m, Integral a) => Fold m (a, Maybe a) a
windowSumInt :: forall (m :: * -> *) a.
(Monad m, Integral a) =>
Fold m (a, Maybe a) a
windowSumInt = forall (m :: * -> *) a b s.
(s -> a -> m (Step s b))
-> m (Step s b) -> (s -> m b) -> (s -> m b) -> Fold m a b
Fold forall {m :: * -> *} {s} {b}.
(Monad m, Num s) =>
s -> (s, Maybe s) -> m (Step s b)
step forall {b}. m (Step a b)
initial forall {a}. a -> m a
extract forall {a}. a -> m a
extract
where
initial :: m (Step a b)
initial = forall (m :: * -> *) a. Monad m => a -> m a
return forall a b. (a -> b) -> a -> b
$ forall s b. s -> Step s b
Partial (a
0 :: a)
step :: s -> (s, Maybe s) -> m (Step s b)
step s
s (s
a, Maybe s
ma) =
forall (m :: * -> *) a. Monad m => a -> m a
return
forall a b. (a -> b) -> a -> b
$ forall s b. s -> Step s b
Partial
forall a b. (a -> b) -> a -> b
$ case Maybe s
ma of
Maybe s
Nothing -> s
s forall a. Num a => a -> a -> a
+ s
a
Just s
old -> s
s forall a. Num a => a -> a -> a
+ s
a forall a. Num a => a -> a -> a
- s
old
extract :: a -> m a
extract = forall (m :: * -> *) a. Monad m => a -> m a
return
{-# INLINE windowSum #-}
windowSum :: forall m a. (Monad m, Num a) => Fold m (a, Maybe a) a
windowSum :: forall (m :: * -> *) a. (Monad m, Num a) => Fold m (a, Maybe a) a
windowSum = forall (m :: * -> *) a b s.
(s -> a -> m (Step s b))
-> m (Step s b) -> (s -> m b) -> (s -> m b) -> Fold m a b
Fold forall {m :: * -> *} {b} {b}.
(Monad m, Num b) =>
Tuple' b b -> (b, Maybe b) -> m (Step (Tuple' b b) b)
step forall {b}. m (Step (Tuple' a a) b)
initial forall {m :: * -> *} {a} {b}. Monad m => Tuple' a b -> m a
extract forall {m :: * -> *} {a} {b}. Monad m => Tuple' a b -> m a
extract
where
initial :: m (Step (Tuple' a a) b)
initial =
forall (m :: * -> *) a. Monad m => a -> m a
return
forall a b. (a -> b) -> a -> b
$ forall s b. s -> Step s b
Partial
forall a b. (a -> b) -> a -> b
$ forall a b. a -> b -> Tuple' a b
Tuple'
(a
0 :: a)
(a
0 :: a)
step :: Tuple' b b -> (b, Maybe b) -> m (Step (Tuple' b b) b)
step (Tuple' b
total b
err) (b
new, Maybe b
mOld) =
let incr :: b
incr =
case Maybe b
mOld of
Maybe b
Nothing -> b
new forall a. Num a => a -> a -> a
- b
err
Just b
old -> (b
new forall a. Num a => a -> a -> a
- b
old) forall a. Num a => a -> a -> a
- b
err
total1 :: b
total1 = b
total forall a. Num a => a -> a -> a
+ b
incr
err1 :: b
err1 = (b
total1 forall a. Num a => a -> a -> a
- b
total) forall a. Num a => a -> a -> a
- b
incr
in forall (m :: * -> *) a. Monad m => a -> m a
return forall a b. (a -> b) -> a -> b
$ forall s b. s -> Step s b
Partial forall a b. (a -> b) -> a -> b
$ forall a b. a -> b -> Tuple' a b
Tuple' b
total1 b
err1
extract :: Tuple' a b -> m a
extract (Tuple' a
total b
_) = forall (m :: * -> *) a. Monad m => a -> m a
return a
total
{-# INLINE windowLength #-}
windowLength :: (Monad m, Num b) => Fold m (a, Maybe a) b
windowLength :: forall (m :: * -> *) b a. (Monad m, Num b) => Fold m (a, Maybe a) b
windowLength = forall (m :: * -> *) b a.
Monad m =>
(b -> a -> b) -> b -> Fold m a b
Fold.foldl' forall {a} {a} {a}. Num a => a -> (a, Maybe a) -> a
step b
0
where
step :: a -> (a, Maybe a) -> a
step a
w (a
_, Maybe a
Nothing) = a
w forall a. Num a => a -> a -> a
+ a
1
step a
w (a, Maybe a)
_ = a
w
{-# INLINE windowPowerSum #-}
windowPowerSum :: (Monad m, Num a) => Int -> Fold m (a, Maybe a) a
windowPowerSum :: forall (m :: * -> *) a.
(Monad m, Num a) =>
Int -> Fold m (a, Maybe a) a
windowPowerSum Int
k = forall c a (m :: * -> *) b.
(c -> a) -> Fold m (a, Maybe a) b -> Fold m (c, Maybe c) b
windowLmap (forall a b. (Num a, Integral b) => a -> b -> a
^ Int
k) forall (m :: * -> *) a. (Monad m, Num a) => Fold m (a, Maybe a) a
windowSum
{-# INLINE windowPowerSumFrac #-}
windowPowerSumFrac :: (Monad m, Floating a) => a -> Fold m (a, Maybe a) a
windowPowerSumFrac :: forall (m :: * -> *) a.
(Monad m, Floating a) =>
a -> Fold m (a, Maybe a) a
windowPowerSumFrac a
p = forall c a (m :: * -> *) b.
(c -> a) -> Fold m (a, Maybe a) b -> Fold m (c, Maybe c) b
windowLmap (forall a. Floating a => a -> a -> a
** a
p) forall (m :: * -> *) a. (Monad m, Num a) => Fold m (a, Maybe a) a
windowSum
{-# INLINE windowRange #-}
windowRange :: (MonadIO m, Storable a, Ord a) => Int -> Fold m a (Maybe (a, a))
windowRange :: forall (m :: * -> *) a.
(MonadIO m, Storable a, Ord a) =>
Int -> Fold m a (Maybe (a, a))
windowRange Int
n = forall (m :: * -> *) a b s.
(s -> a -> m (Step s b))
-> m (Step s b) -> (s -> m b) -> (s -> m b) -> Fold m a b
Fold forall {m :: * -> *} {a} {c} {b}.
(MonadIO m, Storable a, Num c) =>
Tuple3Fused' (Ring a) (Ptr a) c
-> a -> m (Step (Tuple3Fused' (Ring a) (Ptr a) c) b)
step forall {b}. m (Step (Tuple3Fused' (Ring a) (Ptr a) Int) b)
initial forall {m :: * -> *} {a}.
(MonadIO m, Storable a, Ord a) =>
Tuple3Fused' (Ring a) (Ptr a) Int -> m (Maybe (a, a))
extract forall {m :: * -> *} {a}.
(MonadIO m, Storable a, Ord a) =>
Tuple3Fused' (Ring a) (Ptr a) Int -> m (Maybe (a, a))
extract
where
initial :: m (Step (Tuple3Fused' (Ring a) (Ptr a) Int) b)
initial =
if Int
n forall a. Ord a => a -> a -> Bool
<= Int
0
then forall a. HasCallStack => [Char] -> a
error [Char]
"range: window size must be > 0"
else
let f :: (a, b) -> Step (Tuple3Fused' a b Int) b
f (a
a, b
b) = forall s b. s -> Step s b
Partial forall a b. (a -> b) -> a -> b
$ forall a b c. a -> b -> c -> Tuple3Fused' a b c
Tuple3Fused' a
a b
b (Int
0 :: Int)
in forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap forall {a} {b} {b}. (a, b) -> Step (Tuple3Fused' a b Int) b
f forall a b. (a -> b) -> a -> b
$ forall (m :: * -> *) a. MonadIO m => IO a -> m a
liftIO forall a b. (a -> b) -> a -> b
$ forall a. Storable a => Int -> IO (Ring a, Ptr a)
Ring.new Int
n
step :: Tuple3Fused' (Ring a) (Ptr a) c
-> a -> m (Step (Tuple3Fused' (Ring a) (Ptr a) c) b)
step (Tuple3Fused' Ring a
rb Ptr a
rh c
i) a
a = do
Ptr a
rh1 <- forall (m :: * -> *) a. MonadIO m => IO a -> m a
liftIO forall a b. (a -> b) -> a -> b
$ forall a. Storable a => Ring a -> Ptr a -> a -> IO (Ptr a)
Ring.unsafeInsert Ring a
rb Ptr a
rh a
a
forall (m :: * -> *) a. Monad m => a -> m a
return forall a b. (a -> b) -> a -> b
$ forall s b. s -> Step s b
Partial forall a b. (a -> b) -> a -> b
$ forall a b c. a -> b -> c -> Tuple3Fused' a b c
Tuple3Fused' Ring a
rb Ptr a
rh1 (c
i forall a. Num a => a -> a -> a
+ c
1)
foldFunc :: Int -> Ptr a -> (b -> a -> m b) -> b -> Ring a -> m b
foldFunc Int
i
| Int
i forall a. Ord a => a -> a -> Bool
< Int
n = forall (m :: * -> *) a b.
(MonadIO m, Storable a) =>
Ptr a -> (b -> a -> m b) -> b -> Ring a -> m b
Ring.unsafeFoldRingM
| Bool
otherwise = forall (m :: * -> *) a b.
(MonadIO m, Storable a) =>
Ptr a -> (b -> a -> m b) -> b -> Ring a -> m b
Ring.unsafeFoldRingFullM
extract :: Tuple3Fused' (Ring a) (Ptr a) Int -> m (Maybe (a, a))
extract (Tuple3Fused' Ring a
rb Ptr a
rh Int
i) =
if Int
i forall a. Eq a => a -> a -> Bool
== Int
0
then forall (m :: * -> *) a. Monad m => a -> m a
return forall a. Maybe a
Nothing
else do
a
x <- forall (m :: * -> *) a. MonadIO m => IO a -> m a
liftIO forall a b. (a -> b) -> a -> b
$ forall a. Storable a => Ptr a -> IO a
peek (forall a. ForeignPtr a -> Ptr a
unsafeForeignPtrToPtr (forall a. Ring a -> ForeignPtr a
Ring.ringStart Ring a
rb))
let accum :: (b, b) -> b -> m (b, b)
accum (b
mn, b
mx) b
a = forall (m :: * -> *) a. Monad m => a -> m a
return (forall a. Ord a => a -> a -> a
min b
mn b
a, forall a. Ord a => a -> a -> a
max b
mx b
a)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap forall a. a -> Maybe a
Just forall a b. (a -> b) -> a -> b
$ forall {m :: * -> *} {a} {b}.
(MonadIO m, Storable a) =>
Int -> Ptr a -> (b -> a -> m b) -> b -> Ring a -> m b
foldFunc Int
i Ptr a
rh forall {m :: * -> *} {b}.
(Monad m, Ord b) =>
(b, b) -> b -> m (b, b)
accum (a
x, a
x) Ring a
rb
{-# INLINE windowMinimum #-}
windowMinimum :: (MonadIO m, Storable a, Ord a) => Int -> Fold m a (Maybe a)
windowMinimum :: forall (m :: * -> *) a.
(MonadIO m, Storable a, Ord a) =>
Int -> Fold m a (Maybe a)
windowMinimum Int
n = forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap (forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap forall a b. (a, b) -> a
fst) forall a b. (a -> b) -> a -> b
$ forall (m :: * -> *) a.
(MonadIO m, Storable a, Ord a) =>
Int -> Fold m a (Maybe (a, a))
windowRange Int
n
{-# INLINE windowMaximum #-}
windowMaximum :: (MonadIO m, Storable a, Ord a) => Int -> Fold m a (Maybe a)
windowMaximum :: forall (m :: * -> *) a.
(MonadIO m, Storable a, Ord a) =>
Int -> Fold m a (Maybe a)
windowMaximum Int
n = forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap (forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap forall a b. (a, b) -> b
snd) forall a b. (a -> b) -> a -> b
$ forall (m :: * -> *) a.
(MonadIO m, Storable a, Ord a) =>
Int -> Fold m a (Maybe (a, a))
windowRange Int
n
{-# INLINE windowMean #-}
windowMean :: forall m a. (Monad m, Fractional a) => Fold m (a, Maybe a) a
windowMean :: forall (m :: * -> *) a.
(Monad m, Fractional a) =>
Fold m (a, Maybe a) a
windowMean = forall (m :: * -> *) a b c x.
Monad m =>
(a -> b -> c) -> Fold m x a -> Fold m x b -> Fold m x c
Fold.teeWith forall a. Fractional a => a -> a -> a
(/) forall (m :: * -> *) a. (Monad m, Num a) => Fold m (a, Maybe a) a
windowSum forall (m :: * -> *) b a. (Monad m, Num b) => Fold m (a, Maybe a) b
windowLength