----------------------------------------------------------------------------
-- |
-- Module  :  ForSyDe.Shallow.Utility.FIR
-- Copyright   :  (c) ForSyDe Group, KTH 2007-2008
-- License     :  BSD-style (see the file LICENSE)
-- 
-- Maintainer  :  forsyde-dev@ict.kth.se
-- Stability   :  experimental
-- Portability :  portable
--
-- This module implements a FIR filters for the synchronous computational model.
-----------------------------------------------------------------------------
module ForSyDe.Shallow.Utility.FIR (firSY) where

import ForSyDe.Shallow.MoC.Synchronous
import ForSyDe.Shallow.Core

-- | The function firSY implements a FIR-filter for the synchronous computational model. All kinds of FIR-filters can now be modeled by means of 'firSY'. The only argument needed is the list of coefficients, which is given as a vector of any size. To illustrate this, an 8-th order band pass filter is modeled as follows. 
--
-- > bp = firSY (vector [0.06318761339784, 0.08131651217682, 0.09562326700432, 
-- >         0.10478344432968, 0.10793629404886, 0.10478344432968, 
-- >         0.09562326700432, 0.08131651217682, 0.06318761339784 ])
-- 
firSY :: Fractional a => Vector a -> Signal a -> Signal a
firSY :: Vector a -> Signal a -> Signal a
firSY Vector a
h = Vector a -> Vector (Signal a) -> Signal a
forall a. Num a => Vector a -> Vector (Signal a) -> Signal a
innerProdSY Vector a
h (Vector (Signal a) -> Signal a)
-> (Signal a -> Vector (Signal a)) -> Signal a -> Signal a
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Int -> a -> Signal a -> Vector (Signal a)
forall b. Int -> b -> Signal b -> Vector (Signal b)
sipoSY Int
k a
0.0
    where k :: Int
k = Vector a -> Int
forall a. Vector a -> Int
lengthV Vector a
h

-- sipoSY :: Int -> b -> Signal b -> Vector (Signal b) 
-- sipoSY n s0 = unzipxSY . scanlSY shiftrV initState
--     where initState = copyV n s0

-- | Create the tapped, or delayed signals for later consumption.
sipoSY :: Int -> b -> Signal b -> Vector (Signal b) 
sipoSY :: Int -> b -> Signal b -> Vector (Signal b)
sipoSY Int
n b
s0 = Int -> (Signal b -> Signal b) -> Signal b -> Vector (Signal b)
forall a b. (Num a, Eq a) => a -> (b -> b) -> b -> Vector b
iterateV Int
n Signal b -> Signal b
tap 
    where tap :: Signal b -> Signal b
tap = b -> Signal b -> Signal b
forall a. a -> Signal a -> Signal a
delaySY b
s0

innerProdSY :: (Num a) => Vector a -> Vector (Signal a) -> Signal a
innerProdSY :: Vector a -> Vector (Signal a) -> Signal a
innerProdSY Vector a
coeffs = (Vector a -> a) -> Vector (Signal a) -> Signal a
forall a b. (Vector a -> b) -> Vector (Signal a) -> Signal b
zipWithxSY (Vector a -> Vector a -> a
forall p. Num p => Vector p -> Vector p -> p
ipV Vector a
coeffs)
   where ipV :: Vector p -> Vector p -> p
ipV Vector p
NullV   Vector p
NullV   = p
0
         ipV (p
h:>Vector p
hv) (p
x:>Vector p
xv) = p
hp -> p -> p
forall a. Num a => a -> a -> a
*p
x p -> p -> p
forall a. Num a => a -> a -> a
+ Vector p -> Vector p -> p
ipV Vector p
hv Vector p
xv
         ipV Vector p
_   Vector p
_   = [Char] -> p
forall a. HasCallStack => [Char] -> a
error [Char]
"Vector of different length"