{-# LANGUAGE FlexibleContexts #-} {-| Module : Data.Number.ER.RnToRm.UnitDom.ChebyshevBase.Polynom.Integration Description : (internal) integration of polynomials etc Copyright : (c) 2007-2008 Michal Konecny License : BSD3 Maintainer : mik@konecny.aow.cz Stability : experimental Portability : portable Internal module for "Data.Number.ER.RnToRm.UnitDom.ChebyshevBase.Polynom". Implementation of safely rounded integration of polynomials and other related functions. -} module Data.Number.ER.RnToRm.UnitDom.ChebyshevBase.Polynom.Integration where import Data.Number.ER.RnToRm.UnitDom.ChebyshevBase.Polynom.Basic import Data.Number.ER.RnToRm.UnitDom.ChebyshevBase.Polynom.Eval import Data.Number.ER.RnToRm.UnitDom.ChebyshevBase.Polynom.Ring import Data.Number.ER.RnToRm.UnitDom.ChebyshevBase.Polynom.Bounds import qualified Data.Number.ER.Real.Base as B import qualified Data.Number.ER.Real.DomainBox as DBox import Data.Number.ER.Real.DomainBox (VariableID(..), DomainBox, DomainBoxMappable, DomainIntBox) import Data.Number.ER.Real.Approx.Interval import Data.Number.ER.Misc import qualified Data.Map as Map {-| Approximate from below and from above the integral of a polynomial. Based on the following formulas for Chebyshev polynomials: > \int T_n(x)dx = > T_{n+1}(x)/2(n+1) - T_{n-1}(x)/2(n-1) > \int T_1(x)dx = > T_2(x)/4 + 1/4 > \int T_0(x)dx = > T_1(x) -} chplIntegrate :: (B.ERRealBase b, DomainBox box varid Int, Ord box) => varid {-^ variable to integrate by -} -> ERChebPoly box b -> (ERChebPoly box b, ERChebPoly box b) chplIntegrate x p@(ERChebPoly coeffs) = -- unsafePrintReturn -- ( -- "ERChebPoly: integrate:" -- ++ "\n p = " ++ show p -- ++ "\n result = " -- ) (pNp1Down -. pNm1Up, pNp1Up -^ pNm1Down) -- (chplRemoveZeroTermsDown $ pNp1Down - pNm1Up, -- chplRemoveZeroTermsUp $ pNp1Up - pNm1Down) where pNp1Up = ERChebPoly $ Map.insertWith plusUp chplConstTermKey errBoundNp1 $ Map.fromList coeffsNp1 pNp1Down = ERChebPoly $ Map.insertWith plusDown chplConstTermKey (- errBoundNp1) $ Map.fromList coeffsNp1 pNm1Up = ERChebPoly $ Map.insertWith plusUp chplConstTermKey errBoundNm1 $ Map.fromList coeffsNm1 pNm1Down = ERChebPoly $ Map.insertWith plusDown chplConstTermKey (- errBoundNm1) $ Map.fromList coeffsNm1 (coeffsNp1, errBoundNp1) = foldl cfNp1 ([],0) coeffsList (coeffsNm1, errBoundNm1) = foldl cfNm1 ([],0) coeffsList coeffsList = Map.toList coeffs cfNp1 (prevTerms, prevErr) (termKey, coeff) | n == 0 = ((termKeyNp1, coeff):prevTerms, prevErr) | n == 1 = ((termKeyN0, coeff0Up):(termKeyNp1, coeffNp1Up):prevTerms, prevErr + coeff0Err + coeffNp1Err) | otherwise = ((termKeyNp1, coeffNp1Up):prevTerms, prevErr + coeffNp1Err) where termKeyNp1 = DBox.insert x (n + 1) termKey termKeyNm1 = DBox.insert x (n - 1) termKey termKeyN0 = DBox.delete x termKey n = DBox.findWithDefault 0 x termKey coeffNp1Err = coeffNp1Up - coeffNp1Down coeffNp1Up = coeff / (2*nB + 2) coeffNp1Down = -((-coeff) / (2*nB + 2)) nB = fromInteger $ toInteger n coeff0Up = coeff / 4 coeff0Down = - ((- coeff) / 4) coeff0Err = coeff0Up - coeff0Down cfNm1 (prevTerms, prevErr) (termKey, coeff) | n == 0 || n == 1 = (prevTerms, prevErr) | otherwise = ((termKeyNm1, coeffNm1Up):prevTerms, prevErr + coeffNm1Err) where termKeyNm1 = DBox.insert x (n - 1) termKey n = DBox.findWithDefault 0 x termKey coeffNm1Up = coeff / (2*nB - 2) coeffNm1Down = -((-coeff) / (2*nB - 2)) nB = fromInteger $ toInteger n coeffNm1Err = coeffNm1Up - coeffNm1Down --{-| -- measure the volume between a polynomial and the zero axis on [-1,1]^n ---} --chplVolumeAboveZero :: -- (B.ERRealBase b, DomainBox box varid Int, Ord box, -- DomainBoxMappable boxb boxbb varid b [ERInterval b]) => -- [varid] -> -- ERChebPoly box b -> -- (b,b) --chplVolumeAboveZero vars p@(ERChebPoly coeffs) = ---- unsafePrint ("chplVolumeAboveZero: returning:" ++ show result) $ ---- unsafePrint ("chplVolumeAboveZero: vars = " ++ show vars) $ -- result -- where -- result = -- (- (integUpAtOddCorners - integDownAtEvenCorners), integUpAtEvenCorners - integDownAtOddCorners) -- integUpAtEvenCorners = sumUp $ map (chplEvalUp integUp) evenCorners -- integUpAtOddCorners = sumUp $ map (chplEvalUp integUp) oddCorners -- integDownAtEvenCorners = sumDown $ map (chplEvalDown integDown) evenCorners -- integDownAtOddCorners = sumDown $ map (chplEvalDown integDown) oddCorners -- evenCorners = map (DBox.fromList) evenCornersL -- oddCorners = map (DBox.fromList) oddCornersL -- (evenCornersL, oddCornersL) = -- allPairsCombinationsEvenOdd $ zip vars $ repeat (1,-1) -- integUp = integrateByAllVars snd p vars -- integDown = integrateByAllVars fst p vars -- integrateByAllVars pick p [] = p -- integrateByAllVars pick p (x : xs) = -- integrateByAllVars pick ip xs -- where -- ip = pick $ chplIntegrate x p ---- vars = chplGetVars p -- --{-| -- Differentiate a polynomial using one of its variables. -- -- This is not implemented yet and will probably never be needed -- because differentiation is not a computable operator -- and thus we have to rely on automatic differentiation -- when we need derivative enclosures. ---} --chplDifferentiate :: -- (B.ERRealBase b, DomainBox box varid Int, Ord box) => -- ERChebPoly box b -> -- varid {-^ variable to differentiate over -} -> -- ERChebPoly box b --chplDifferentiate (ERChebPoly coeffs) varName = -- errorModule "chplDifferentiate: not implemented yet"