AERN-RnToRm-0.5: src/Data/Number/ER/RnToRm/UnitDom/ChebyshevBase/Polynom/Compose.hs
{-# LANGUAGE FlexibleContexts #-}
{-|
Module : Data.Number.ER.RnToRm.UnitDom.ChebyshevBase.Polynom.Compose
Description : (internal) composition of polynomials
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 pointwise consistently rounded polynomial composition.
-}
module Data.Number.ER.RnToRm.UnitDom.ChebyshevBase.Polynom.Compose
where
import Data.Number.ER.RnToRm.UnitDom.ChebyshevBase.Polynom.Basic
import Data.Number.ER.RnToRm.UnitDom.ChebyshevBase.Polynom.Ring
import Data.Number.ER.RnToRm.UnitDom.ChebyshevBase.Polynom.Bounds
import Data.Number.ER.RnToRm.UnitDom.ChebyshevBase.Polynom.Enclosure
import qualified Data.Number.ER.Real.Approx as RA
import qualified Data.Number.ER.Real.Base as B
import qualified Data.Number.ER.BasicTypes.DomainBox as DBox
import Data.Number.ER.BasicTypes.DomainBox (VariableID(..), DomainBox, DomainIntBox, DomainBoxMappable)
import Data.Number.ER.Real.Approx.Interval
import Data.Number.ER.Misc
import qualified Data.Map as Map
{-|
Compose a polynomial and an enclosure, producing a correcly rounded enclosure,
assuming the second polynomial maps [-1,1] into [-1,1].
-}
enclCompose ::
(B.ERRealBase b,
DomainBox box varid Int, Ord box, Show varid,
DomainIntBox boxra varid (ERInterval b),
DomainBoxMappable boxra boxras varid (ERInterval b) [ERInterval b]) =>
Int {-^ max degree for result -} ->
Int {-^ max approx size for result -} ->
ERChebPoly box b {-^ @f@ -} ->
varid {-^ variable @v@ to substitute in @f@ -} ->
(ERChebPoly box b, ERChebPoly box b)
{-^ enclosure of a function @f_v@ to substitute for @v@
that maps @[-1,1]@ into @[-1,1]@ -} ->
(ERChebPoly box b, ERChebPoly box b)
{-^ lower bound and upper bound -}
enclCompose maxDegree maxSize p@(ERChebPoly coeffs) substVar substEncl =
result
{------------------------------
The algorithm: separate from the polynomial
all terms for each degree of the substituted variable,
giving rise to a number of polynomials.
These polynomials are then used as coefficients multiplying
the enclosure evaluations of the Chebyshev polynomials
over the substituted enclosure.
-------------------------------}
where
result =
Map.fold (+:) (enclConst 0) $ Map.mapWithKey evalDegree degreePolynomialMap
degreePolynomialMap =
Map.foldWithKey extractTerm Map.empty coeffs
extractTerm term c prevPolynomMap =
Map.insertWith Map.union substVarDegree (Map.singleton termNoSubstVar c) prevPolynomMap
where
substVarDegree = DBox.findWithDefault 0 substVar term
termNoSubstVar = DBox.delete substVar term
evalDegree degree degreeCoeffs =
enclMultiply maxDegree maxSize (substPolyDegrees !! degree) (chplNeg degreePoly, degreePoly)
where
degreePoly = ERChebPoly degreeCoeffs
substPolyDegrees =
enclEvalTs maxSize maxDegree substEncl
{------------------------------
The following algorithm is quite wasteful when the polynomial
contains other variables besides the one being substituted.
-------------------------------}
--chplComposeWithEncl maxDegree maxSize p@(ERChebPoly coeffs) substVar substEncl =
-- result
-- where
-- result =
-- foldl (+:) (enclConst 0) $ map evalTerm $ Map.toList coeffs
-- evalTerm (term, c) =
-- enclScale c $
-- foldl (enclMultiply maxDegree maxSize) (enclConst 1) $
-- map evalVar $ DBox.toList term
-- evalVar (var, degree) =
-- case var == substVar of
-- True ->
-- substPolyDegrees !! degree
-- False ->
-- (chplNeg varPoly, varPoly)
-- where
-- varPoly =
-- ERChebPoly $ Map.singleton (DBox.singleton var degree) 1
-- substPolyDegrees =
-- enclEvalTs maxSize maxDegree substEncl
{-|
Compose two polynomials, rounding upwards
provided the second polynomial maps [-1,1] into [-1,1].
-}
enclComposeMany ::
(B.ERRealBase b,
DomainBox box varid Int, Ord box, Show varid,
DomainIntBox boxra varid (ERInterval b),
DomainBoxMappable boxra boxras varid (ERInterval b) [ERInterval b]) =>
Int {-^ max degree for result -} ->
Int {-^ max approx size for result -} ->
ERChebPoly box b ->
Map.Map varid (ERChebPoly box b, ERChebPoly box b)
{-^ variables to substitute and the enclosures to substitute for each of them respectively -} ->
(ERChebPoly box b, ERChebPoly box b)
{-^ lower bound (negated) and upper bound -}
enclComposeMany maxDegree maxSize p@(ERChebPoly coeffs) substitutions =
-- unsafePrintReturn
-- (
-- "ChebyshevBase.Polynom.Compose: enclComposeMany:"
-- ++ "\n maxDegree = " ++ show maxDegree
-- ++ "\n maxSize = " ++ show maxSize
-- ++ "\n p = " ++ show p
-- ++ "\n substitutions = " ++ show substitutions
-- ++ "\n terms... \n" ++ (unlines $ map (show . (\t -> map evalVar (DBox.toList t) ) . fst) $ Map.toList coeffs)
-- ++ "\n result = "
-- )
result
where
result =
foldl (+:) (enclConst 0) $ map evalTerm $ Map.toList coeffs
evalTerm (term, c) =
enclScale maxDegree maxSize c $
foldl (enclMultiply maxDegree maxSize) (enclConst 1) $
map evalVar $ DBox.toList term
evalVar (varID, degree) =
case Map.lookup varID substDegrees of
Nothing ->
(chplNeg varPoly, varPoly)
Just pvDegrees ->
pvDegrees !! degree
where
varPoly =
ERChebPoly $ Map.singleton (DBox.singleton varID degree) 1
substDegrees =
Map.map mkPVDegrees substitutions
mkPVDegrees pvEncl =
enclEvalTs maxDegree maxSize pvEncl