{-# LANGUAGE NoImplicitPrelude #-}
{- |
Copyright   :  (c) Henning Thielemann 2008
License     :  GPL

Maintainer  :  synthesizer@henning-thielemann.de
Stability   :  provisional
Portability :  requires multi-parameter type classes

Filter operators from calculus
-}
module Synthesizer.Generic.Filter.Recursive.Integration where

import qualified Synthesizer.Generic.Signal as SigG

import qualified Algebra.Additive              as Additive

import NumericPrelude.Numeric
import NumericPrelude.Base



{- |
Integrate with initial value zero.
However the first emitted value is the value of the input signal.
It maintains the length of the signal.
-}
{-# INLINE run #-}
run :: (Additive.C v, SigG.Transform sig v) =>
   sig v -> sig v
run :: forall v (sig :: * -> *). (C v, Transform sig v) => sig v -> sig v
run =
   (v -> v -> Maybe (v, v)) -> v -> sig v -> sig v
forall y0 y1 s.
(Storage (sig y0), Storage (sig y1)) =>
(y0 -> s -> Maybe (y1, s)) -> s -> sig y0 -> sig y1
forall (sig :: * -> *) y0 y1 s.
(Transform0 sig, Storage (sig y0), Storage (sig y1)) =>
(y0 -> s -> Maybe (y1, s)) -> s -> sig y0 -> sig y1
SigG.crochetL (\v
x v
acc -> let y :: v
y = v
xv -> v -> v
forall a. C a => a -> a -> a
+v
acc in (v, v) -> Maybe (v, v)
forall a. a -> Maybe a
Just (v
y,v
y)) v
forall a. C a => a
zero
   -- scanl1 (+)

{- |
Integrate with initial condition.
First emitted value is the initial condition.
The signal become one element longer.
-}
{-# INLINE runInit #-}
runInit :: (Additive.C v, SigG.Transform sig v) =>
   v -> sig v -> sig v
runInit :: forall v (sig :: * -> *).
(C v, Transform sig v) =>
v -> sig v -> sig v
runInit = (v -> v -> v) -> v -> sig v -> sig v
forall y0 y1.
(Storage (sig y0), Storage (sig y1)) =>
(y1 -> y0 -> y1) -> y1 -> sig y0 -> sig y1
forall (sig :: * -> *) y0 y1.
(Transform0 sig, Storage (sig y0), Storage (sig y1)) =>
(y1 -> y0 -> y1) -> y1 -> sig y0 -> sig y1
SigG.scanL v -> v -> v
forall a. C a => a -> a -> a
(+)

{- other quadrature methods may follow -}