packages feed

elerea-examples-2.2.1: src/Bounce/Math.hs

{-# LANGUAGE NoMonomorphismRestriction #-}

module Math where

import Control.Applicative
import Data.List
import FRP.Elerea.Param

import Vector
import Util

{-| Scalar integral. -}
integral :: (Num a) => a -> Signal a -> SignalGen a (Signal a)
integral v0 s = transfer v0 (\dt v v0 -> v0+v*dt) s

{-| Vector integral. -}
integralV :: (Vector2D v c) => v -> Signal v -> SignalGen c (Signal v)
integralV v0 s = transfer v0 (\dt v v0 -> v0^+^(v^*.dt)) s

{-| Scalar derivative by the last two values. -}
deriv :: (Fractional a) => Signal a -> SignalGen a (Signal a)
deriv s = do
  sig <- transfer (0,0,1) (\dt v (v0,_,_) -> (v,v0,dt)) s
  initSignal 0 (d <$> sig)
  where d (x',x,dt) = (x'-x)/dt

{-| Vector derivative by the last two values. -}
derivV :: (Vector2D v c, Num c) => Signal v -> SignalGen c (Signal v)
derivV s = do
  sig <- transfer (vnull,vnull,1) (\dt v (v0,_,_) -> (v,v0,dt)) s
  initSignal vnull (d <$> sig)
  where d (x',x,dt) = (x'^-^x)^/.dt

{-| Scalar derivative by a given time period. -}
derivT :: (Fractional a, Ord a) => a -> Signal a -> SignalGen a (Signal a)
derivT wt s = do
  sig <- transfer (0,(0,0)) d s
  return (fst <$> sig)
  where d dt v (x,(v0,t)) = if t' > wt then ((v-v0)/t',(v,0)) else (x,(v0,t'))
          where t' = dt+t

{-| Vector derivative by a given time period. -}
derivTV :: (Vector2D v c, Ord c, Num c) => c -> Signal v -> SignalGen c (Signal v)
derivTV wt s = do
  sig <- transfer (vnull,(vnull,0)) d s
  return (fst <$> sig)
  where d dt v (x,(v0,t)) = if t' > wt then ((v^-^v0)^/.t',(v,0)) else (x,(v0,t'))
          where t' = dt+t

{-| Scalar moving average of a given number of recent samples. -}
movingAvg :: (Fractional a) => a -> Signal a -> SignalGen p (Signal a)
movingAvg n s = do
  sig <- scanM n (delay 0) s
  return $ ((/n).sum) <$> sequence sig

{-| Vector moving average of a given number of recent samples. -}
movingAvgV :: (Vector2D v c, Num c) => c -> Signal v -> SignalGen p (Signal v)
movingAvgV n s = do
  sig <- scanM n (delay vnull) s
  return $ ((^/.n).foldl1' (^+^)) <$> sequence sig