module Simulation.Aivika.Dynamics.Fold
(foldDynamics1,
foldDynamics) where
import Data.IORef
import Control.Monad
import Control.Monad.Trans
import Simulation.Aivika.Internal.Specs
import Simulation.Aivika.Internal.Simulation
import Simulation.Aivika.Internal.Dynamics
import Simulation.Aivika.Dynamics.Memo
foldDynamics1 :: (Dynamics a -> Simulation (Dynamics a))
-> (a -> a -> a)
-> Dynamics a
-> Simulation (Dynamics a)
foldDynamics1 tr f (Dynamics m) =
do r <- liftIO $ newIORef m
let z = Dynamics $ \p ->
case pointIteration p of
0 ->
m p
n -> do
let sc = pointSpecs p
ty = basicTime sc (n 1) 0
py = p { pointTime = ty, pointIteration = n 1, pointPhase = 0 }
y <- readIORef r
s <- y py
x <- m p
return $! f s x
y@(Dynamics m) <- tr z
liftIO $ writeIORef r m
return y
foldDynamics :: (Dynamics a -> Simulation (Dynamics a))
-> (a -> b -> a)
-> a
-> Dynamics b
-> Simulation (Dynamics a)
foldDynamics tr f acc (Dynamics m) =
do r <- liftIO $ newIORef $ const $ return acc
let z = Dynamics $ \p ->
case pointIteration p of
0 -> do
x <- m p
return $! f acc x
n -> do
let sc = pointSpecs p
ty = basicTime sc (n 1) 0
py = p { pointTime = ty, pointIteration = n 1, pointPhase = 0 }
y <- readIORef r
s <- y py
x <- m p
return $! f s x
y@(Dynamics m) <- tr z
liftIO $ writeIORef r m
return y