module Data.Periodic (
polyG1
, trigPolyCos
, trigPolySin
, trigPoly
, periodizer
, concatPeriodizer
, polyG2
, polyG3
) where
import qualified Data.Vector as V
trigPolySin :: (Floating a) => (a -> a) -> V.Vector a -> a -> a
trigPolySin f = polyG1 f (sin)
trigPolyCos :: (Floating a) => (a -> a) -> V.Vector a -> a -> a
trigPolyCos f = polyG1 f (cos)
trigPoly :: (Floating a) => (a -> a) -> V.Vector a -> (a -> a) -> V.Vector a -> a -> a
trigPoly f v1 g v2 y
| V.null v1 = polyG1 g (sin) v2 y
| V.null v2 = polyG1 f (cos) v1 y
| otherwise = (V.sum . V.zipWith (*) (V.map g v2) . V.generate (V.length v2) $ (\i -> sin (fromIntegral (i + 1) * y))) +
(V.sum . V.zipWith (*) (V.map f v1) . V.generate (V.length v1) $ (\i -> cos (fromIntegral (i + 1) * y)))
periodizer :: (RealFrac a) => (a -> b) -> a -> a -> a -> b
periodizer f x0 period x
| period /= 0.0 = let delta = (x - x0) / abs period in f (x0 + (abs period) * (delta - (fromIntegral . truncate $ delta)))
| otherwise = error "Data.Periodic.periodizer: Not defined for the zero period. "
concatPeriodizer :: (RealFrac a, Num b) => (a -> b) -> a -> a -> a -> b
concatPeriodizer f x0 period x
| period /= 0.0 =
let delta = (x - x0) / abs period
deltaI = truncate delta in f (x0 + (abs period) * (delta - (fromIntegral deltaI))) + fromIntegral deltaI * (f (x0 + abs period) - f x0)
| otherwise = error "Data.Periodic.concatPeriodizer: Not defined for the zero period. "
polyG1 :: (Floating a) => (a -> a) -> (a -> a) -> V.Vector a -> a -> a
polyG1 f g v y
| V.null v = 0.0
| otherwise = V.sum . V.zipWith (*) (V.map f v) . V.generate (V.length v) $ (\i -> g (fromIntegral (i + 1) * y))
polyG2 :: (RealFrac a) => (a -> a) -> (a -> a) -> a -> a -> V.Vector a -> a -> a
polyG2 f g period y0 v y
| V.null v = 0.0
| otherwise = V.sum . V.zipWith (*) (V.map f v) . V.generate (V.length v) $ (\i -> periodizer g y0 period (fromIntegral (i + 1) * y))
polyG3 :: (RealFrac a) => (a -> a) -> (a -> a) -> a -> a -> V.Vector a -> a -> a
polyG3 f g period y0 v y
| V.null v = 0.0
| otherwise = V.sum . V.zipWith (*) (V.map f v) . V.generate (V.length v) $ (\i -> concatPeriodizer g y0 period (fromIntegral (i + 1) * y))