{-# LANGUAGE MultiParamTypeClasses #-}
{-# LANGUAGE FlexibleInstances #-}
{-# LANGUAGE UndecidableInstances #-}
{-|
    Module      :  Data.Number.ER.RnToRm.UnitDom.ChebyshevBase.Polynom
    Description :  multivariate polynomials in the Chebyshev basis
    Copyright   :  (c) 2007-2008 Michal Konecny
    License     :  BSD3

    Maintainer  :  mik@konecny.aow.cz
    Stability   :  experimental
    Portability :  portable
    
    Arithmetic of multivariate polynomials 
    represented by their coefficients it the Chebyshev basis.
    
    The polynomials are never to be used outside the domain @[-1,1]^n@.
    
    All operations are rounded in such a way that the resulting polynomial
    is a /point-wise upper or lower bound/ of the exact result. 
-}
module Data.Number.ER.RnToRm.UnitDom.ChebyshevBase.Polynom
(
    ERChebPoly(..), TermKey
)
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.Reduce
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 Data.Number.ER.RnToRm.UnitDom.ChebyshevBase.Polynom.Compose
import Data.Number.ER.RnToRm.UnitDom.ChebyshevBase.Polynom.Integration
import Data.Number.ER.RnToRm.UnitDom.ChebyshevBase.Polynom.Division
import Data.Number.ER.RnToRm.UnitDom.ChebyshevBase.Polynom.Elementary

import qualified Data.Number.ER.RnToRm.UnitDom.Base as UFB
import qualified Data.Number.ER.Real.Base as B
import Data.Number.ER.Real.Approx.Interval
import Data.Number.ER.Real.DomainBox (VariableID(..), DomainBox, DomainBoxMappable, DomainIntBox)

import qualified Data.Map as Map

{- code for testing purpose, to be deleted later -}
import Data.Number.ER.Real.DefaultRepr
import Data.Number.ER.Real.DomainBox.IntMap
type P = ERChebPoly (Box Int) B
x0 = chplVar 0 :: P
x1 = chplVar 1 :: P
x2 = chplVar 2 :: P
x3 = chplVar 3 :: P
x4 = chplVar 4 :: P
p1 = x1 *^ x1 *^ x1 +^ x1 *^ (x2 +^ (chplConst 2)) *^ (x3 -^ (chplConst 3))
{- end of code for testing purposes -}

instance 
    (B.ERRealBase rb, RealFrac rb,
     DomainBox box varid Int, Ord box,
     DomainBoxMappable boxb boxras varid rb [ERInterval rb],
     DomainBoxMappable boxra boxras varid (ERInterval rb) [ERInterval rb],
     DomainIntBox boxra varid (ERInterval rb)) =>
    (UFB.ERUnitFnBase boxb boxra varid rb (ERInterval rb) (ERChebPoly box rb))
    where
    {----- Miscellaneous associated operations -----}
    raEndpoints _ (ERInterval l h) = (l,h)
    raEndpoints _ ERIntervalAny = (- B.plusInfinity, B.plusInfinity)
    raFromEndpoints _ (l,h) = normaliseERInterval (ERInterval l h)
    compareApprox = chplCompareApprox
    showDiGrCmp = chplShow 
    
    {----- Structural analysis and update of functions -----}
    isValid = chplHasNoNaNOrInfty
    check = chplCheck
    getGranularity = chplGetGranularity
    setMinGranularity = chplSetMinGranularity
    setGranularity = chplSetGranularity
    getDegree = chplGetDegree
    reduceDegreeUp = chplReduceDegreeUp
    getSize = chplCountTerms
    reduceSizeUp = chplReduceTermCountUp
    getVariables = chplGetVars
    
    {----- Construction of basic functions -----}
    const = chplConst
    constEncl (low, high) = (chplConst (-low), chplConst high)
    affine = chplAffine
    
    {----- Pointwise order operations ----------}    
    upperBound = chplUpperBound
    maxUp = chplMaxUp
    minUp = chplMinUp
    
    {----- Field operations ----------}
    neg = chplNeg
    scaleUp = chplScaleUp
    scaleApproxUp = chplScaleRAUp
    (+^) = (+^)
    (-^) = (-^)
    (*^) = (*^)
    multiplyEncl = enclMultiply
    recipUp md mt ix f = snd $ enclRecip md mt ix (md + 1) (chplNeg f, f)
    recipEncl md mt ix = enclRecip md mt ix (md + 1)
    
    {----- Evaluation and composition of functions -----}
    evalUp pt f = chplEvalUp f pt
    evalApprox x ufb = chplRAEval (\ b -> ERInterval b b) ufb x
    
    partialEvalApproxUp substitutions ufb =
        snd $ 
        chplPartialRAEval (UFB.raEndpoints ufb) ufb substitutions
    composeUp m n f v fv = snd $ enclCompose m n f v (enclThin fv) 
    composeEncl = enclCompose
    composeManyUp m n f subst = snd $ enclComposeMany m n f (Map.map enclThin subst)
    composeManyEncls = enclComposeMany

    {----- Selected elementary operations ----------}
    sqrtEncl = enclSqrt    
    expEncl = enclExp
    logEncl = enclLog
    sinEncl = enclSine
    cosEncl = enclCosine
    atanEncl = enclAtan
    
    integrate = chplIntegrate