-- |
-- Module     : Simulation.Aivika.Trans.Transform.Memo
-- Copyright  : Copyright (c) 2009-2017, David Sorokin <david.sorokin@gmail.com>
-- License    : BSD3
-- Maintainer : David Sorokin <david.sorokin@gmail.com>
-- Stability  : experimental
-- Tested with: GHC 8.0.1
--
-- This module defines memoization transforms. The memoization creates such 'Dynamics'
-- computations, which values are cached in the integration time points. Then
-- these values are interpolated in all other time points.
--

module Simulation.Aivika.Trans.Transform.Memo
       (memoTransform,
        memo0Transform,
        iteratingTransform) where

import Simulation.Aivika.Trans.Dynamics
import Simulation.Aivika.Trans.Dynamics.Memo
import Simulation.Aivika.Trans.Transform
import Simulation.Aivika.Trans.SD

-- | A transform that memoizes and order the computation in the integration time points
-- using the interpolation that knows of the Runge-Kutta method. The values are
-- calculated sequentially starting from 'starttime'.
memoTransform :: MonadSD m => Transform m e e
{-# INLINE memoTransform #-}
memoTransform :: forall (m :: * -> *) e. MonadSD m => Transform m e e
memoTransform = (Dynamics m e -> Simulation m (Dynamics m e)) -> Transform m e e
forall (m :: * -> *) a b.
(Dynamics m a -> Simulation m (Dynamics m b)) -> Transform m a b
Transform Dynamics m e -> Simulation m (Dynamics m e)
forall e. Dynamics m e -> Simulation m (Dynamics m e)
forall (m :: * -> *) e.
MonadMemo m =>
Dynamics m e -> Simulation m (Dynamics m e)
memoDynamics 

-- | A transform that memoizes and order the computation in the integration time points using 
-- the 'discreteDynamics' interpolation. It consumes less memory than the 'memoTransform'
-- computation but it is not aware of the Runge-Kutta method. There is a subtle
-- difference when we request for values in the intermediate time points
-- that are used by this method to integrate. In general case you should 
-- prefer the 'memo0Transform' computation above 'memoTransform'.
memo0Transform :: MonadSD m => Transform m e e
{-# INLINE memo0Transform #-}
memo0Transform :: forall (m :: * -> *) e. MonadSD m => Transform m e e
memo0Transform =  (Dynamics m e -> Simulation m (Dynamics m e)) -> Transform m e e
forall (m :: * -> *) a b.
(Dynamics m a -> Simulation m (Dynamics m b)) -> Transform m a b
Transform Dynamics m e -> Simulation m (Dynamics m e)
forall e. Dynamics m e -> Simulation m (Dynamics m e)
forall (m :: * -> *) e.
MonadMemo m =>
Dynamics m e -> Simulation m (Dynamics m e)
memo0Dynamics

-- | A transform that iterates sequentially the dynamic process with side effects in 
-- the integration time points. It is equivalent to the 'memo0Transform' computation
-- but significantly more efficient, for the internal array is not created.
iteratingTransform :: MonadSD m => Transform m () ()
{-# INLINE iteratingTransform #-}
iteratingTransform :: forall (m :: * -> *). MonadSD m => Transform m () ()
iteratingTransform = (Dynamics m () -> Simulation m (Dynamics m ()))
-> Transform m () ()
forall (m :: * -> *) a b.
(Dynamics m a -> Simulation m (Dynamics m b)) -> Transform m a b
Transform Dynamics m () -> Simulation m (Dynamics m ())
forall (m :: * -> *).
MonadMemo m =>
Dynamics m () -> Simulation m (Dynamics m ())
iterateDynamics