packages feed

erf-native-1.0.0.0: src/NR/Ch5/S8.hs

{-# LANGUAGE RecordWildCards, BangPatterns, FlexibleContexts #-}
-- |Evaluating Chebyshev polynomials, translated from code given
-- in Numerical Recipes, 3d Ed., Section 5.8.
module NR.Ch5.S8 where

import Data.Vector.Generic (Vector, generate, (!))

data Chebyshev v a b = Chebyshev
    { chebOrder     :: Int
    -- ^ Order of the (truncated) approximation, which may be different
    -- from the order of the fitted approximation, which is
    -- @length chebCoeffs - 1@
    , chebCoeffs    :: v b
    , chebA         :: a
    , chebB         :: a
    } deriving (Eq, Show)

chebEval :: (Real a, Fractional b, Vector v b) => Chebyshev v a b -> a -> b
chebEval c = chebEvalM (chebOrder c) c

chebEvalM :: (Real a, Fractional b, Vector v b) => Int -> Chebyshev v a b -> a -> b
chebEvalM order Chebyshev{..} x = go order 0 0 
    where
        go !j !dd !d
            | j > 0     = go (j-1) d (y2*d - dd + (chebCoeffs!j))
            | otherwise = y * d - dd + 0.5 * (chebCoeffs!0)
        
        y  = (2 * realToFrac x - a - b) / (b - a)
        y2 = 2 * y
        
        a = realToFrac chebA
        b = realToFrac chebB