AERN-RnToRm 0.3.0.3 → 0.4
raw patch · 12 files changed
+517/−204 lines, 12 files
Files
- AERN-RnToRm.cabal +1/−1
- ChangeLog +3/−0
- src/Data/Number/ER/RnToRm/Approx/DomEdges.hs +1/−0
- src/Data/Number/ER/RnToRm/Approx/DomTransl.hs +2/−0
- src/Data/Number/ER/RnToRm/Approx/PieceWise.hs +7/−6
- src/Data/Number/ER/RnToRm/Approx/Tuple.hs +1/−0
- src/Data/Number/ER/RnToRm/TestingDefs.hs +10/−2
- src/Data/Number/ER/RnToRm/UnitDom/Approx/Interval.hs +160/−17
- src/Data/Number/ER/RnToRm/UnitDom/Base.hs +12/−2
- src/Data/Number/ER/RnToRm/UnitDom/ChebyshevBase/Polynom.hs +4/−3
- src/Data/Number/ER/RnToRm/UnitDom/ChebyshevBase/Polynom/Bounds.hs +47/−3
- src/Data/Number/ER/RnToRm/UnitDom/ChebyshevBase/Polynom/Elementary.hs +269/−170
AERN-RnToRm.cabal view
@@ -1,5 +1,5 @@ Name: AERN-RnToRm-Version: 0.3.0.3+Version: 0.4 Cabal-Version: >= 1.2 Build-Type: Simple License: BSD3
ChangeLog view
@@ -1,3 +1,6 @@+0.4: 20 August 2008+ * fixed several serious bugs in sin and cos+ * added arctan 0.3.0.3: 7 August 2008 * revamped package description to make it much shorter and linked it to the main module
src/Data/Number/ER/RnToRm/Approx/DomEdges.hs view
@@ -251,6 +251,7 @@ log ix = edgesLift1 $ RAEL.log ix sin ix = edgesLift1 $ RAEL.sin ix cos ix = edgesLift1 $ RAEL.cos ix+ atan ix = edgesLift1 $ RAEL.atan ix instance (FA.ERFnDomApprox box varid domra ranra fa, VariableID varid) =>
src/Data/Number/ER/RnToRm/Approx/DomTransl.hs view
@@ -323,6 +323,8 @@ ERFnDomTranslApprox (RAEL.sin ix ufa) dtrB cos ix (ERFnDomTranslApprox ufa dtrB) = ERFnDomTranslApprox (RAEL.cos ix ufa) dtrB+ atan ix (ERFnDomTranslApprox ufa dtrB) =+ ERFnDomTranslApprox (RAEL.atan ix ufa) dtrB instance (UFA.ERUnitFnApprox box varid domra ranra ufa,
src/Data/Number/ER/RnToRm/Approx/PieceWise.hs view
@@ -232,6 +232,7 @@ log ix = pwLift1 $ RAEL.log ix sin ix = pwLift1 $ RAEL.sin ix cos ix = pwLift1 $ RAEL.cos ix+ atan ix = pwLift1 $ RAEL.atan ix instance (FA.ERFnDomApprox box varid domra ranra fa, @@ -343,12 +344,12 @@ integrateOriginHigher [bistrD, bistrInit] zipOutsideRange maybeFromL maybeFromR [bistrD, bistrInit] =- unsafePrint- (- "ERFnPiecewise: integrateMeasureImprovement: zipOutsideRange: "- ++ "\n domB = " ++ show domB- ++ "\n bottomFn = " ++ show bottomFn- )+-- unsafePrint+-- (+-- "ERFnPiecewise: integrateMeasureImprovement: zipOutsideRange: "+-- ++ "\n domB = " ++ show domB+-- ++ "\n bottomFn = " ++ show bottomFn+-- ) [bistrPadj] where (ERFnPiecewise bistrPadj) =
src/Data/Number/ER/RnToRm/Approx/Tuple.hs view
@@ -203,6 +203,7 @@ log ix = tuplesLift1 $ RAEL.log ix sin ix = tuplesLift1 $ RAEL.sin ix cos ix = tuplesLift1 $ RAEL.cos ix+ atan ix = tuplesLift1 $ RAEL.atan ix instance (FA.ERFnDomApprox box varid domra ranra fa) =>
src/Data/Number/ER/RnToRm/TestingDefs.hs view
@@ -13,6 +13,7 @@ module Data.Number.ER.RnToRm.TestingDefs where import Data.Number.ER.RnToRm.DefaultRepr+import Data.Number.ER.Real.DefaultRepr import qualified Data.Number.ER.RnToRm.Approx as FA import qualified Data.Number.ER.RnToRm.UnitDom.Approx as UFA@@ -50,7 +51,7 @@ fapeUConst13 = (FA.const (DBox.unary $ (0)RA.\/1) [1 RA.\/ 3]) :: FAPE fapeUConst13InitPt = FA.partialIntersect 1 (DBox.unary 0) fapeUConst13 fapeUConst1 -fapwUUX0 = (FA.proj (DBox.fromAscList [(0,(1) RA.\/ 1)]) 0) :: FAPWP+fapwUUX0 = (FA.proj (DBox.fromAscList [(0,(-1) RA.\/ 1)]) 0) :: FAPWP fapwUUX1 = (FA.proj (DBox.fromAscList [(1,(-1) RA.\/ 1)]) 1) :: FAPWP fapwUX0 = (FA.proj (DBox.fromAscList [(0,(0) RA.\/ 1)]) 0) :: FAPWP@@ -66,7 +67,14 @@ testIntegrP = FA.integrateMeasureImprovement 1 (FA.setMaxDegree 0 fapwUConst13InitPt) 0 (DBox.unary $ 0 RA.\/ 0.5) 0 fapwUConst13InitPt -x = FA.setMaxDegree 4 fapwUX0+x = +-- FA.bisectUnbisectDepth 1 $+ FA.setMaxDegree 4 + fapwUUX0+ +xLR = + snd $ FA.bisect 0 Nothing $ fst $ FA.bisect 0 Nothing $ x+ fn1 = (1 + x) RA.\/ (1 + 3*x) fn2 = FA.integrateUnary 0 fn1 0 (0 RA.\/ 1) [1] fn3 = FA.integrateUnary 0 fn2 0 (0 RA.\/ 1) [1] -- this seems wrong!
src/Data/Number/ER/RnToRm/UnitDom/Approx/Interval.hs view
@@ -124,9 +124,9 @@ where (ERFnInterval h1 ln1 ctxt1 gl1) == (ERFnInterval h2 ln2 ctxt2 gl2) =- error "ERFnInterval: equality not implemented yet"+ error "ERFnInterval: equality not implemented" _ == _ =- error "ERFnInterval: equality not implemented yet"+ error "ERFnInterval: equality not implemented" instance (UFB.ERUnitFnBase boxb boxra varid b ra fb) =>@@ -135,10 +135,11 @@ compare (ERFnInterval h1 ln1 ctxt1 gl1) (ERFnInterval h2 ln2 ctxt2 gl2) =- error "ERFnInterval: comparison not implemented yet"+ error "ERFnInterval: comparison not implemented; consider leqReals from class ERApprox instead" compare _ _ =- error "ERFnInterval: comparison not implemented yet"+ error "ERFnInterval: comparison not implemented; consider leqReals from class ERApprox instead" + instance (UFB.ERUnitFnBase boxb boxra varid b ra fb) => Num (ERFnInterval fb ra)@@ -312,7 +313,7 @@ ctxt = erfnContextUnify (erfnContext f1) (erfnContext f2) instance- (UFB.ERUnitFnBase boxb boxra varid b ra fb, RAEL.ERApproxElementary ra) =>+ (UFB.ERUnitFnBase boxb boxra varid b ra fb, RAEL.ERApproxElementary ra, RealFrac b) => RAEL.ERApproxElementary (ERFnInterval fb ra) where -- default abs does not work because we do not have Prelude.abs@@ -345,31 +346,173 @@ -- ++ "\n uSin = " ++ show uSin -- ++ "\n lSinNeg = " ++ show lSinNeg -- ) $- ERFnInterval uSin lSinNeg c (RAEL.sin ix g)+ ERFnInterval uSin (- lSin) c (RAEL.sin ix g) where+ (lSin, uSin) = sincos True maxDegree ix u (-ln) maxDegree = erfnMaxDegree c--- ix = int2effIx maxDegree- uSin = snd $ UFB.sin maxDegree ix u- lSinNeg = - negate $ fst $ UFB.sin maxDegree ix (negate ln) cos ix f@(ERFnIntervalAny c) = ERFnInterval 1 1 c ((-1) RA.\/ 1) cos ix (ERFnInterval u ln c g) = -- unsafePrint -- (--- "ERFnInterval: RAEL.sin: "+-- "ERFnInterval: RAEL.cos: " -- ++ "\n u = " ++ show u -- ++ "\n ln = " ++ show ln--- ++ "\n uSin = " ++ show uSin--- ++ "\n lSinNeg = " ++ show lSinNeg+-- ++ "\n uCos = " ++ show uCos+-- ++ "\n lCosNeg = " ++ show lCosNeg -- ) $- ERFnInterval uCos lCosNeg c (RAEL.cos ix g)+ ERFnInterval uCos (- lCos) c (RAEL.cos ix g) where+ (lCos, uCos) = sincos False maxDegree ix u (-ln) maxDegree = erfnMaxDegree c+ atan ix f@(ERFnIntervalAny c) =+ ERFnInterval 1 1 c ((-1) RA.\/ 1)+ atan ix (ERFnInterval u ln c g) =+-- unsafePrint+-- (+-- "ERFnInterval: RAEL.atan: "+-- ++ "\n u = " ++ show u+-- ++ "\n ln = " ++ show ln+-- ++ "\n uAtan = " ++ show uAtan+-- ++ "\n lAtanNeg = " ++ show lAtanNeg+-- ) $+ ERFnInterval uAtan lAtanNeg c (RAEL.atan ix g)+ where+ maxDegree = erfnMaxDegree c -- ix = int2effIx maxDegree- uCos = snd $ UFB.cos maxDegree ix u- lCosNeg = - negate $ fst $ UFB.cos maxDegree ix (negate ln) + uAtan = snd $ UFB.atan maxDegree ix u+ lAtanNeg = + negate $ fst $ UFB.atan maxDegree ix (negate ln) ++sincos ::+ (UFB.ERUnitFnBase boxb boxra varid b ra fb, RAEL.ERApproxElementary ra, RealFrac b) =>+ Bool {-^ True iff sine, False iff cosine -} -> + Int {-^ maximum representation degree -} -> + EffortIndex {-^ how hard to try to eliminate truncation errors -} -> + fb ->+ fb ->+ (fb, fb)+sincos isSine maxDegree ix u l+ -- p - 2k*pi range within [-pi/2, pi/2]: + | ranfNear0 `RA.refines` plusMinusPiHalf =+-- unsafePrint+-- (+-- "ERFnInterval: sincos: [-pi/2, pi/2]: "+-- ++ "\n u = " ++ show u+-- ++ "\n l = " ++ show l+-- ++ "\n ranf = " ++ show ranf+-- ++ "\n k = " ++ show k+-- ++ "\n ranfNear0 = " ++ show ranfNear0+-- ) $+ case isSine of+ True -> sineShifted (- k2pi)+ False -> cosineShifted (- k2pi)+ -- p - 2k*pi range within [0, pi]: + | (ranfNear0 - piHalf) `RA.refines` plusMinusPiHalf =+-- unsafePrint+-- (+-- "ERFnInterval: sincos: [0, pi]: "+-- ++ "\n u = " ++ show u+-- ++ "\n l = " ++ show l+-- ++ "\n ranf = " ++ show ranf+-- ++ "\n k = " ++ show k+-- ++ "\n ranfNear0 = " ++ show ranfNear0+-- ) $+ case isSine of+ -- use sin(x) = cos(x - pi/2) and cos(x) = - sin(x - pi/2):+ True -> cosineShifted (- k2pi - piHalf)+ False -> sineShiftedNegated (- k2pi - piHalf)+ -- p - 2k*pi range within [-pi, 0]: + | (ranfNear0 + piHalf) `RA.refines` plusMinusPiHalf =+-- unsafePrint+-- (+-- "ERFnInterval: sincos: [-pi, 0]: "+-- ++ "\n u = " ++ show u+-- ++ "\n l = " ++ show l+-- ++ "\n ranf = " ++ show ranf+-- ++ "\n k = " ++ show k+-- ++ "\n ranfNear0 = " ++ show ranfNear0+-- ) $+ case isSine of+ -- use sin(x) = - cos(x + pi/2) and cos(x) = sin(x + pi/2):+ True -> cosineShiftedNegated (-k2pi + piHalf)+ False -> sineShifted (-k2pi + piHalf)+ -- p - 2k*pi range within [pi/2, 3pi/2]: + | (ranfNear0 - pi) `RA.refines` plusMinusPiHalf =+-- unsafePrint+-- (+-- "ERFnInterval: sincos: [pi/2, 3pi/2]: "+-- ++ "\n u = " ++ show u+-- ++ "\n l = " ++ show l+-- ++ "\n ranf = " ++ show ranf+-- ++ "\n k = " ++ show k+-- ++ "\n ranfNear0 = " ++ show ranfNear0+-- ) $+ -- use sin(x) = - sin(x - pi) and cos(x) = - cos(x - pi)+ case isSine of+ True -> sineShiftedNegated (- k2pi - pi)+ False -> cosineShiftedNegated (- k2pi - pi)+ | otherwise = +-- unsafePrint+-- (+-- "ERFnInterval: sincos: big range: "+-- ++ "\n u = " ++ show u+-- ++ "\n l = " ++ show l+-- ++ "\n ranf = " ++ show ranf+-- ++ "\n k = " ++ show k+-- ++ "\n ranfNear0 = " ++ show ranfNear0+-- ) $+ (UFB.const (-1), UFB.const 1)+-- (expDownwards, expUpwards + valueAtRDnNeg + (UFB.const expRUp))+ where+ ranfNear0 = ranf - k2pi+ k2pi = k * 2 * pi+ plusMinusPiHalf = (-piHalfLO) RA.\/ piHalfLO+ pi = RAEL.pi ix + piHalf = pi / 2+ (piHalfLO, piHalfHI) = RA.bounds piHalf+ ranf = + ERInterval + (UFB.lowerBound 10 l) + (UFB.upperBound 10 u)+ k = + fromInteger $ floor $ + case (pi + ranf) / (2 * pi) of ERInterval lo hi -> lo++ sineShiftedNegated shift =+ boundsNegate $ sineShifted shift+ + cosineShiftedNegated shift =+ boundsNegate $ cosineShifted shift++ boundsNegate (pLO, pHI) = (- pHI, - pLO)+ + sineShifted shift =+ boundsAddErr shiftWidthB (lSinDown, uSinUp)+ where+ lSinDown = fst $ UFB.sin maxDegree ix (l `plusUp` shiftPoly)+ uSinUp = snd $ UFB.sin maxDegree ix (u `plusDown` shiftPoly) + shiftPoly = UFB.const shiftLOB+ ERInterval shiftLOB shiftHIB = shift+ shiftWidthB = shiftHIB - shiftLOB+ + cosineShifted shift =+ boundsAddErr shiftWidthB $ + (UFB.minDown maxDegree lCosDown uCosDown,+ UFB.maxUp maxDegree lCosUp uCosUp + + (snd $ UFB.scale 0.5 (u-l))) -- important near 0+ where+ (lCosDown, lCosUp) = UFB.cos maxDegree ix (l `plusUp` shiftPoly)+ (uCosDown, uCosUp) = UFB.cos maxDegree ix (u `plusDown` shiftPoly) + shiftPoly = UFB.const shiftLOB+ ERInterval shiftLOB shiftHIB = shift+ shiftWidthB = shiftHIB - shiftLOB+ + boundsAddErr errB (pLO, pHI) =+ (pLO `plusDown` (- errPoly), pHI + errPoly)+ where+ errPoly = UFB.const errB+ instance (UFB.ERUnitFnBase boxb boxra varid b ra fb) =>
src/Data/Number/ER/RnToRm/UnitDom/Base.hs view
@@ -237,7 +237,8 @@ ufb {-^ p(x) -} -> (ufb, ufb) {-| - Approximate @sin(p(x))@ from below and from above.+ Approximate @sin(p(x))@ from below and from above,+ assuming the range of p is within [-pi/2,pi/2]. -} sin :: Int {-^ max degree for result -} -> @@ -245,9 +246,18 @@ ufb {-^ p(x) -} -> (ufb, ufb) {-|- Approximate @cos(p(x))@ from below and from above.+ Approximate @cos(p(x))@ from below and from above,+ assuming the range of p is within [-pi/2,pi/2]. -} cos :: + Int {-^ max degree for result -} -> + EffortIndex {-^ how hard to try when approximating cos as a polynomial -} -> + ufb {-^ p(x) -} -> + (ufb, ufb)+ {-|+ Approximate @atan(p(x))@ from below and from above.+ -}+ atan :: Int {-^ max degree for result -} -> EffortIndex {-^ how hard to try when approximating cos as a polynomial -} -> ufb {-^ p(x) -} ->
src/Data/Number/ER/RnToRm/UnitDom/ChebyshevBase/Polynom.hs view
@@ -23,7 +23,7 @@ module Data.Number.ER.RnToRm.UnitDom.ChebyshevBase.Polynom ( ERChebPoly(..), TermKey-) +) where import Data.Number.ER.RnToRm.UnitDom.ChebyshevBase.Polynom.Basic@@ -80,8 +80,9 @@ sqrt = chplSqrt exp = chplExp log = chplLog- sin = chplSineCosine True- cos = chplSineCosine False+ sin = chplSine+ cos = chplCosine+ atan = chplAtan eval = chplEval evalApprox ufb x = chplEvalApprox (\ b -> ERInterval b b) ufb x partialEvalApprox substitutions ufb =
src/Data/Number/ER/RnToRm/UnitDom/ChebyshevBase/Polynom/Bounds.hs view
@@ -187,6 +187,16 @@ _ -> [(term, coeff)] +chplMaxDn m a b = fst $ chplMax m a b+chplMaxUp m a b = snd $ chplMax m a b+chplMinDn m a b = fst $ chplMin m a b+chplMinUp m a b = snd $ chplMin m a b++chplMin m a b =+ (-u,-l)+ where+ (l,u) = chplMax m (-a) (-b)+ {-| Approximate from below and from above the pointwise maximum of two polynomials -}@@ -197,7 +207,7 @@ ERChebPoly box b -> (ERChebPoly box b, ERChebPoly box b) chplMax maxDegree p1 p2 =- (- (-p1 - differenceDown), p1 + differenceUp)+ (p1 `plusDown` differenceDown, p1 `plusUp` differenceUp) where (differenceDown, differenceUp) = chplNonneg maxDegree $ p2 - p1 @@ -241,9 +251,9 @@ p2 = multiplyByP p3 + (chplConst a2) -- ie p * a3 + a2 p3 = chplConst a3 multiplyByPUp =- snd . chplReduceDegree maxDegree . (p *)+ chplReduceDegreeUp maxDegree . (p *) multiplyByPDown =- fst . chplReduceDegree maxDegree . (p *)+ chplReduceDegreeDown maxDegree . (p *) {- The cubic polynomial's coefficients are calculated by solving a system of 4 linear eqs. The generic solution is as follows:@@ -291,3 +301,37 @@ we subtract its value at 0 rounded upwards. -} valueAt0 = chplConst $ a0 / b++{-|+ Multiply a thin enclosure by a non-thin enclosure+-}+chplThinTimesEncl ::+ (B.ERRealBase b, DomainBox box varid Int, Ord box) => + Int {-^ maximum polynomial degree -} -> + ERChebPoly box b ->+ (ERChebPoly box b, ERChebPoly box b) ->+ (ERChebPoly box b, ERChebPoly box b)+chplThinTimesEncl maxDegree p1 (p2LO, p2HI) =+ (prodLO, prodHI)+ where+ prodHI =+ chplMaxUp maxDegree + (p1 `timesUp` p2HI)+ (p1 `timesUp` p2LO) -- beware: p1 can be negative+ prodLO =+ negate $+ chplMaxUp maxDegree + (p1n `timesUp` p2HI)+ (p1n `timesUp` p2LO)+ p1n = negate p1++{-|+ Safely multiply a polynomial by itself.+-}+chplSquare ::+ (B.ERRealBase b, DomainBox box varid Int, Ord box) => + Int {-^ maximum polynomial degree -} -> + ERChebPoly box b ->+ (ERChebPoly box b, ERChebPoly box b)+chplSquare maxDegree p =+ (p `timesDown` p, p `timesUp` p)
src/Data/Number/ER/RnToRm/UnitDom/ChebyshevBase/Polynom/Elementary.hs view
@@ -136,188 +136,132 @@ {-| Approximate the pointwise sine of a polynomial - by another polynomial from below and from above. + by another polynomial from below and from above.+ + Assuming the polynomial range is [-pi/2, pi/2]. -}-chplSineCosine ::+chplSine :: (B.ERRealBase b, RealFrac b, DomainBox box varid Int, Ord box) =>- Bool {-^ True iff sine, False iff cosine -} -> Int {-^ maximum polynomial degree -} -> - EffortIndex {-^ minimum approx Taylor degree -} -> + EffortIndex {-^ how hard to try (determines Taylor degree and granularity) -} -> ERChebPoly box b -> (ERChebPoly box b, ERChebPoly box b)-chplSineCosine isSine maxDegree ix p- -- p - 2k*pi range within [-pi/2, pi/2]: - | ranfNear0 `RA.refines` plusMinusPiHalf =--- unsafePrint--- (--- "ERChebPoly: chplSineCosine: [-pi/2, pi/2]: "--- ++ "\n p = " ++ show p--- ++ "\n ranf = " ++ show ranf--- ++ "\n k = " ++ show k--- ++ "\n ranfNear0 = " ++ show ranfNear0--- ) $- case isSine of- True -> sineShifted (- k2pi)- False -> cosineShifted (- k2pi)- -- p - 2k*pi range within [0, pi]: - | (ranfNear0 - piHalf) `RA.refines` plusMinusPiHalf =+chplSine maxDegree ix p = -- unsafePrint -- (--- "ERChebPoly: chplSineCosine: [0, pi]: "+-- "ERChebPoly: sineTaylor: " -- ++ "\n p = " ++ show p--- ++ "\n ranf = " ++ show ranf--- ++ "\n k = " ++ show k--- ++ "\n ranfNear0 = " ++ show ranfNear0+-- ++ "\n ranLargerEndpoint = " ++ show ranLargerEndpoint+-- ++ "\n sineUp = " ++ show sineUp+-- ++ "\n sineDown = " ++ show sineDown -- ) $- case isSine of- -- use sin(x) = cos(x - pi/2) and cos(x) = - sin(x - pi/2):- True -> cosineShifted (- k2pi - piHalf)- False -> sineShiftedNegated (- k2pi - piHalf)- -- p - 2k*pi range within [-pi, 0]: - | (ranfNear0 + piHalf) `RA.refines` plusMinusPiHalf =- case isSine of- -- use sin(x) = - cos(x + pi/2) and cos(x) = sin(x + pi/2):- True -> cosineShiftedNegated (-k2pi + piHalf)- False -> sineShifted (-k2pi + piHalf)- -- p - 2k*pi range within [pi/2, 3pi/2]: - | (ranfNear0 - pi) `RA.refines` plusMinusPiHalf =- -- use sin(x) = - sin(x - pi) and cos(x) = - cos(x - pi)- case isSine of- True -> sineShiftedNegated (- k2pi - pi)- False -> cosineShiftedNegated (- k2pi - pi)- | otherwise = (chplConst (-1), chplConst 1)--- (expDownwards, expUpwards + valueAtRDnNeg + (chplConst expRUp))- where- ranfNear0 = ranf - k2pi - k2pi = k * 2 * pi- plusMinusPiHalf = (-piHalfLO) RA.\/ piHalfLO- pi = RAEL.pi ix - piHalf = pi / 2- (piHalfLO, piHalfHI) = RA.bounds piHalf- ranf = - ERInterval - (negate $ chplUpperBoundAffine 10 (-p)) - (chplUpperBoundAffine 10 p)- k = - fromInteger $ floor $ - case (pi + ranf) / (2 * pi) of ERInterval lo hi -> lo- - sineShiftedNegated shift =- boundsNegate $ sineShifted shift- - cosineShiftedNegated shift =- boundsNegate $ cosineShifted shift-- boundsNegate (pLO, pHI) = (- pHI, - pLO)- - sineShifted shift =- boundsAddErr shiftWidthB $ sineTaylor (p + shiftPoly) (ranf + shift)- where- shiftPoly = chplConst shiftLOB- ERInterval shiftLOB shiftHIB = shift- shiftWidthB = shiftHIB - shiftLOB- - cosineShifted shift =- boundsAddErr shiftWidthB $ cosineTaylor (p + shiftPoly) (ranf + shift)- where- shiftPoly = chplConst shiftLOB- ERInterval shiftLOB shiftHIB = shift- shiftWidthB = shiftHIB - shiftLOB- - boundsAddErr errB (pLO, pHI) =- (pLO `plusDown` (- errPoly), pHI + errPoly)- where- errPoly = chplConst errB- - sineTaylor x xran = (sineDown, sineUp) where- sineUp =- chplReduceDegreeUp maxDegree $ - x * sineUpTaylor + (chplConst sineUpErrorBound)- (sineUpTaylor, sineUpErrorTermDegree, sineUpErrorTermCoeff) =- taylorAux x 1 (B.setGranularity coeffGr 1)- sineUpErrorBound =- case sineUpErrorBoundRA of ERInterval lo hi -> hi- where- sineUpErrorBoundRA = - (xranLargerEndpoint ^ (1 + sineUpErrorTermDegree)) * sineUpErrorTermCoeffRA- sineUpErrorTermCoeffRA =- abs $- ERInterval sineUpErrorTermCoeff sineUpErrorTermCoeff- sineDown = - negate $ chplReduceDegreeUp maxDegree $ - x * sineDownTaylorNeg + (chplConst $ sineDownErrorBound)- (sineDownTaylorNeg, sineDownErrorTermDegree, sineDownErrorTermCoeff) =- taylorAux x 1 (B.setGranularity coeffGr (-1))- sineDownErrorBound =- case sineDownErrorBoundRA of ERInterval lo hi -> hi+ (sineDown, sineUp) =+ boundsAddErr sineErrorBound $+ chplThinTimesEncl maxDegree p (sineDownTaylor, sineUpTaylor) + ((sineDownTaylor, sineUpTaylor), + sineErrorTermDegree, + (sineErrorTermCoeffDown, sineErrorTermCoeffUp)) =+ sincosTaylorAux True (chplSquare maxDegree p) taylorDegree 1 (one, one)+ one = B.setGranularity coeffGr 1+ sineErrorBound =+ case sineErrorBoundRA of ERInterval lo hi -> hi where- sineDownErrorBoundRA =- (xranLargerEndpoint ^ (1 + sineDownErrorTermDegree)) * sineDownErrorTermCoeffRA- sineDownErrorTermCoeffRA =- abs $- ERInterval sineDownErrorTermCoeff sineDownErrorTermCoeff- xranLargerEndpoint = - max (abs xranLO) (abs xranHI)- (xranLO, xranHI) = RA.bounds xran+ sineErrorBoundRA = + (ranLargerEndpointRA ^ (sineErrorTermDegree)) * sineErrorTermCoeffRA+ sineErrorTermCoeffRA =+ ERInterval sineErrorTermCoeff sineErrorTermCoeff+ sineErrorTermCoeff =+ max (abs sineErrorTermCoeffDown) (abs sineErrorTermCoeffUp)+ ranLargerEndpointRA =+ ERInterval ranLargerEndpoint ranLargerEndpoint+ ranLargerEndpoint =+ max (abs ranLO) (abs ranHI)+ ranLO = negate $ chplUpperBoundAffine ix (-p)+ ranHI = chplUpperBoundAffine ix p+ taylorDegree = effIx2int $ ix `div` 3+ coeffGr = effIx2gran $ ix+ +boundsAddErr errB (pLO, pHI) =+ (pLO `plusDown` (- errPoly), pHI + errPoly)+ where+ errPoly = chplConst errB - cosineTaylor x xran =+{-|+ Approximate the pointwise sine of a polynomial + by another polynomial from below and from above.+ + Assuming the polynomial range is [-pi/2, pi/2]. +-}+chplCosine ::+ (B.ERRealBase b, RealFrac b, DomainBox box varid Int, Ord box) =>+ Int {-^ maximum polynomial degree -} -> + EffortIndex {-^ how hard to try (determines Taylor degree and granularity) -} -> + ERChebPoly box b ->+ (ERChebPoly box b, ERChebPoly box b)+chplCosine maxDegree ix p = -- unsafePrint -- (--- "ERChebPoly.Elementary: chplSineCosine: cosineTaylor: "--- ++ "\n xran = " ++ show xran--- ++ "\n cosineUpErrorBound = " ++ show cosineUpErrorBound--- ++ "\n cosineUpErrorTermDegree = " ++ show cosineUpErrorTermDegree--- ++ "\n cosineUpErrorTermCoeff = " ++ show cosineUpErrorTermCoeff--- ++ "\n xranLargerEndpoint = " ++ show xranLargerEndpoint--- )+-- "ERChebPoly: chplCosine: "+-- ++ "\n p = " ++ show p+-- ++ "\n ranLargerEndpoint = " ++ show ranLargerEndpoint+-- ++ "\n cosineUp = " ++ show cosineUp+-- ++ "\n cosineDown = " ++ show cosineDown+-- ) $ (cosineDown, cosineUp) where- cosineUp =- chplReduceDegreeUp maxDegree $ - cosineUpTaylor + (chplConst cosineUpErrorBound)- (cosineUpTaylor, cosineUpErrorTermDegree, cosineUpErrorTermCoeff) =- taylorAux x 0 (B.setGranularity coeffGr 1)- cosineUpErrorBound- | odd (cosineUpErrorTermDegree `div` 2) = 0- | otherwise =- case cosineUpErrorBoundRA of ERInterval lo hi -> hi- where- cosineUpErrorBoundRA = - (xranLargerEndpoint ^ (cosineUpErrorTermDegree)) * cosineUpErrorTermCoeffRA- cosineUpErrorTermCoeffRA =- abs $- ERInterval cosineUpErrorTermCoeff cosineUpErrorTermCoeff- cosineDown = - negate $ chplReduceDegreeUp maxDegree $ - cosineDownTaylorNeg + (chplConst $ cosineDownErrorBound)- (cosineDownTaylorNeg, cosineDownErrorTermDegree, cosineDownErrorTermCoeff) =- taylorAux x 0 (B.setGranularity coeffGr (-1))- cosineDownErrorBound - | even (cosineDownErrorTermDegree `div` 2) = 0- | otherwise =- case cosineDownErrorBoundRA of ERInterval lo hi -> hi- where- cosineDownErrorBoundRA =- (xranLargerEndpoint ^ (cosineDownErrorTermDegree)) * cosineDownErrorTermCoeffRA- cosineDownErrorTermCoeffRA =- abs $- ERInterval cosineDownErrorTermCoeff cosineDownErrorTermCoeff- xranLargerEndpoint = - max (abs xranLO) (abs xranHI)- (xranLO, xranHI) = RA.bounds xran+ (cosineDown, cosineUp) =+ boundsAddErr cosineErrorBound $+ (cosineDownTaylor, cosineUpTaylor) + ((cosineDownTaylor, cosineUpTaylor), + cosineErrorTermDegree, + (cosineErrorTermCoeffDown, cosineErrorTermCoeffUp)) =+ sincosTaylorAux True (chplSquare maxDegree p) taylorDegree 0 (one, one)+ one = B.setGranularity coeffGr 1+ cosineErrorBound =+ case cosineErrorBoundRA of ERInterval lo hi -> hi+ where+ cosineErrorBoundRA =+ (ranLargerEndpointRA ^ (cosineErrorTermDegree)) * cosineErrorTermCoeffRA+ cosineErrorTermCoeffRA =+ ERInterval cosineErrorTermCoeff cosineErrorTermCoeff+ cosineErrorTermCoeff =+ max (abs cosineErrorTermCoeffDown) (abs cosineErrorTermCoeffUp)+ ranLargerEndpointRA =+ ERInterval ranLargerEndpoint ranLargerEndpoint+ ranLargerEndpoint =+ max (abs ranLO) (abs ranHI)+ ranLO = negate $ chplUpperBoundAffine ix (-p)+ ranHI = chplUpperBoundAffine ix p+ taylorDegree = effIx2int $ ix `div` 3+ coeffGr = effIx2gran $ ix - taylorAux p0 thisDegree thisCoeff- | nextDegree > taylorDegree =+sincosTaylorAux ::+ (B.ERRealBase b, RealFrac b, DomainBox box varid Int, Ord box) =>+ Bool -> + (ERChebPoly box b, ERChebPoly box b) ->+ Int {-^ how far to go in the Taylor series -} ->+ Int {-^ degree of the term now being constructed -} ->+ (b,b) -> + ((ERChebPoly box b, ERChebPoly box b),+ Int,+ (b,b))+ {-^ + Bounds for the series result and information about the first discarded term,+ from which some bound on the uniform error can be deduced.+ -} +sincosTaylorAux resultPositive pSquares@(pSquareDown, pSquareUp) + maxDegree thisDegree (thisCoeffDown, thisCoeffUp)+ | nextDegree > maxDegree = -- unsafePrint -- ( -- "ERChebPoly: chplSine: taylorAux: " -- ++ "\n thisCoeff = " ++ show thisCoeff -- ++ "\n nextDegree = " ++ show nextDegree -- )- (chplConst thisCoeff, nextDegree, nextCoeff)- | otherwise =+ ((thisCoeffDownP, thisCoeffUpP), nextDegree, (nextCoeffDown, nextCoeffUp))+ | otherwise = -- unsafePrint -- ( -- "ERChebPoly: chplSine: taylorAux: "@@ -326,19 +270,174 @@ -- ++ "\n errorTermCoeff = " ++ show errorTermCoeff -- ++ "\n errorTermDegree = " ++ show errorTermDegree -- )- (chplReduceDegreeUp maxDegree $- (chplConst thisCoeff) + p0 * p0 * rest,- errorTermDegree, errorTermCoeff) - where- (rest, errorTermDegree, errorTermCoeff) =- taylorAux p0 nextDegree nextCoeff- nextDegree = thisDegree + 2- nextCoeff = - thisCoeff / (fromInteger $ negate $ nextDegree * (nextDegree - 1))- taylorDegree = ix `div` 3- coeffGr = effIx2gran $ ix+ ((resultDown, resultUp), errorTermDegree, errorTermCoeffs) + where+ thisCoeffDownP = chplConst thisCoeffDown+ thisCoeffUpP = chplConst thisCoeffUp+ resultDown+ | resultPositive = + -- ie rest's ideal value is negative and thisCoeff is positive+ chplReduceDegreeDown maxDegree $+ thisCoeffDownP `plusDown` (pSquareUp `timesDown` restDown)+ | otherwise =+ -- ie rest's ideal value is positive and thisCoeff is negative+ chplReduceDegreeDown maxDegree $+ thisCoeffDownP `plusDown` (pSquareDown `timesDown` restDown)+ resultUp+ | resultPositive = + -- ie rest's ideal value is negative and thisCoeff is positive+ chplReduceDegreeUp maxDegree $+ thisCoeffUpP `plusUp` (pSquareDown `timesUp` restUp)+ | otherwise =+ -- ie rest's ideal value is positive and thisCoeff is negative+ chplReduceDegreeUp maxDegree $+ thisCoeffUpP `plusUp` (pSquareUp `timesUp` restUp)+ ((restDown, restUp), errorTermDegree, errorTermCoeffs) =+ sincosTaylorAux (not resultPositive) pSquares maxDegree nextDegree (nextCoeffDown, nextCoeffUp)+ nextDegree = thisDegree + 2+ nextCoeffUp+ | resultPositive = + thisCoeffDown / nextCoeffDenominator -- positive / negative+ | otherwise = + thisCoeffUp / nextCoeffDenominator -- negative / negative+ nextCoeffDown + | resultPositive = + thisCoeffUp `divDown` nextCoeffDenominator -- positive / negative+ | otherwise = + thisCoeffDown `divDown` nextCoeffDenominator -- negative / negative+ nextCoeffDenominator =+ fromInteger $ toInteger $ negate $ nextDegree * (nextDegree - 1)+ divDown a b = negate $ a / (negate b) {-|+ Approximate the pointwise natural logarithm of a polynomial + by another polynomial from below and from above. +-}+chplAtan ::+ (B.ERRealBase b, RealFrac b, DomainBox box varid Int, Ord box) => + Int {-^ maximum polynomial degree -} -> + EffortIndex {-^ ?? -} -> + ERChebPoly box b ->+ (ERChebPoly box b, ERChebPoly box b)+{- atan using Euler's series: + x / (1 + x^2) * (1 + t*2*1/(2*1 + 1)*(1 + t*2*2/(2*2 + 1)*(1 + ... (1 + t*2*n/(2*n+1)*(1 + ...)))))+ where+ t = x^2/(1 + x^2)+ + where the tail (1 + t*2*n/(2*n+1)*(1 + ...)) is inside the interval:+ [1 + (x^2*2n/(2n + 1)), 1 + x^2]+-}+chplAtan maxDegree ix p + | avoidingDivBy0 = +-- unsafePrint+-- (+-- "ERChebPoly.Elementary: chplAtan: "+-- ++ "\n maxDegree = " ++ show maxDegree+-- ++ "\n p = " ++ show p+-- ++ "\n pSquareDn = " ++ show pSquareDn+-- ++ "\n pSquareUp = " ++ show pSquareUp+-- ++ "\n pOverPSquarePlus1Dn = " ++ show pOverPSquarePlus1Dn+-- ++ "\n pOverPSquarePlus1Up = " ++ show pOverPSquarePlus1Up+-- ++ "\n preresDn = " ++ show preresDn+-- ++ "\n preresUp = " ++ show preresUp+-- ++ "\n resDn = " ++ show resDn+-- ++ "\n resUp = " ++ show resUp+-- )+ (resDn, resUp)+ | otherwise =+ (chplConst (-2), chplConst 2) -- this is always safe... + where+ avoidingDivBy0 = + (chplUpperBoundAffine ix (- pSquarePlus1Dn) < 0)+ &&+ (chplUpperBoundAffine ix (- pSquarePlus1Up) < 0)+ resDn = + negate $+ chplMaxUp maxDegree + (chplReduceDegreeUp maxDegree $ + pOverPSquarePlus1DnNeg `timesUp` preresDn) -- beware: pOverPSquarePlus1Dn can be negative+ (chplReduceDegreeUp maxDegree $+ pOverPSquarePlus1DnNeg `timesUp` preresUp)+ where+ pOverPSquarePlus1DnNeg = negate pOverPSquarePlus1Dn+ resUp = + chplMaxUp maxDegree + (chplReduceDegreeUp maxDegree $+ pOverPSquarePlus1Up `timesUp` preresDn) -- beware: pOverPSquarePlus1Up can be negative+ (chplReduceDegreeUp maxDegree $+ pOverPSquarePlus1Up `timesUp` preresUp)+ (preresDn, preresUp) = seriesDnUp termsCount 2+ termsCount = max 0 $ ix `div` 3+ gran = effIx2gran ix+ seriesDnUp termsCount coeffBase + | termsCount > 0 =+ (+ chplReduceDegreeDown maxDegree $+ 1 `plusDown` + (pSquareOverPSquarePlus1Dn -- >=0 + `timesDown` (chplConst coeffDn) -- >=0 + `timesDown` restDn -- >=0+ )+ ,+ chplReduceDegreeUp maxDegree $+ 1 `plusUp`+ (pSquareOverPSquarePlus1Up -- >=0 + `timesUp` (chplConst coeffUp) -- >=0 + `timesUp` restUp -- >=0+ )+ )+ | otherwise =+ (+ 1 `plusDown` (pSquareDn `timesDown` (chplConst coeffDn)) -- both >=0+ ,+ 1 `plusUp` pSquareUp+ )+ where+ (restDn, restUp) = seriesDnUp (termsCount - 1) (coeffBase + 2)+ coeffUp = coeffBaseB / (coeffBaseB `plusDown` 1)+ coeffDn = negate $ coeffBaseB / (negate $ coeffBaseB `plusUp` 1)+ coeffBaseB = B.setMinGranularity gran $ fromInteger coeffBase+ (pSquareDn, pSquareUp) = chplSquare maxDegree p+ pSquarePlus1Dn = pSquareDn `plusDown` 1+ pSquarePlus1Up = pSquareUp `plusUp` 1+ recipPSquarePlus1Dn = chplRecipDn maxDegree ix pSquarePlus1Up+ recipPSquarePlus1Up = chplRecipUp maxDegree ix pSquarePlus1Dn+-- -- safely compute the square of an enclosure:+-- pSquareDn = chplMinDn m pUpTDnpUp (chplMinDn m pDnTDnpUp pDnTDnpDn)+-- pSquareUp = chplMaxUp m pUpTUppUp (chplMaxUp m pDnTUppUp pDnTUppDn) +-- pUpTDnpUp = pUp `timesDown` pUp+-- pDnTDnpUp = pDn `timesDown` pUp+-- pDnTDnpDn = pDn `timesDown` pDn+-- pUpTUppUp = pUp `timesUp` pUp+-- pDnTUppUp = pDn `timesUp` pUp+-- pDnTUppDn = pDn `timesUp` pDn+-- mMinus1 = m - 1+ pSquareOverPSquarePlus1Up = + pSquareUp `timesUp` recipPSquarePlus1Up -- both >=0+ pSquareOverPSquarePlus1Dn = + pSquareDn `timesDown` recipPSquarePlus1Dn -- both >=0 (one enclosure may dip below 0, not a problem)+-- negate $+-- chplMaxUp maxDegree+-- (pSquareDnNeg `timesUp` recipPSquarePlus1Up) -- beware: pSquareDn may dip below 0+-- (pSquareDnNeg `timesUp` recipPSquarePlus1Dn)+-- where+-- pSquareDnNeg = negate pSquareDn+ pOverPSquarePlus1Up =+ chplMaxUp maxDegree + (p `timesUp` recipPSquarePlus1Up)+ (p `timesUp` recipPSquarePlus1Dn) -- beware: p can be negative+ pOverPSquarePlus1Dn =+ negate $+ chplMaxUp maxDegree+ (pn `timesUp` recipPSquarePlus1Up) -- beware: pn can be positive+ (pn `timesUp` recipPSquarePlus1Dn)+ where+ pn = negate p++chplRecipDn m i = fst . chplRecip m i+chplRecipUp m i = snd . chplRecip m i++{-| Approximate the pointwise cosine of a polynomial by another polynomial from below and from above using the tau method @@ -372,7 +471,7 @@ lowerB = - (chplUpperBoundAffine ix (- p)) upperB = chplUpperBoundAffine ix p - tauDegree = effIx2int (ix `div` 3)+ tauDegree = effIx2int (max 2 $ ix `div` 3) coeffGr = effIx2gran $ ix -- translate p to have range above 1: