AERN-Real-2011.1: src/Numeric/AERN/RealArithmetic/RefinementOrderRounding/Elementary.hs
{-# LANGUAGE TypeFamilies #-}
{-# LANGUAGE FlexibleContexts #-}
{-|
Module : Numeric.AERN.RealArithmetic.RefinementOrderRounding.Elementary
Description : support for various common elementary functions
Copyright : (c) Michal Konecny
License : BSD3
Maintainer : mikkonecny@gmail.com
Stability : experimental
Portability : portable
Support for various common elementary functions.
This module is hidden and reexported via its parent RefinementOrderRounding.
-}
module Numeric.AERN.RealArithmetic.RefinementOrderRounding.Elementary where
import Numeric.AERN.RealArithmetic.ExactOps
import Numeric.AERN.RealArithmetic.RefinementOrderRounding.FieldOps
import Numeric.AERN.RealArithmetic.RefinementOrderRounding.MixedFieldOps
import qualified Numeric.AERN.RealArithmetic.NumericOrderRounding.Conversion as UpDnConversion
import Numeric.AERN.Basics.Effort
import Numeric.AERN.Basics.Exception
import Numeric.AERN.Basics.ShowInternals
import Numeric.AERN.Basics.Bench
import Numeric.AERN.Basics.Consistency
import Numeric.AERN.RealArithmetic.Laws
import Numeric.AERN.RealArithmetic.Bench
import Numeric.AERN.RealArithmetic.Measures
import qualified Numeric.AERN.Basics.NumericOrder as NumOrd
import qualified Numeric.AERN.Basics.RefinementOrder as RefOrd
import Numeric.AERN.Misc.Debug
import Test.QuickCheck
import Test.Framework (testGroup, Test)
import Test.Framework.Providers.QuickCheck2 (testProperty)
import Criterion
class RoundedExponentiationEffort t where
type ExpEffortIndicator t
expDefaultEffort :: t -> ExpEffortIndicator t
class (RoundedExponentiationEffort t) => RoundedExponentiation t where
expInEff :: (ExpEffortIndicator t) -> t -> t
expOutEff :: (ExpEffortIndicator t) -> t -> t
-- | @e^a*e^(-a) = 1@
propExpOfNegRecip ::
(RefOrd.PartialComparison t,
RoundedExponentiation t, RoundedMultiply t, Neg t, HasOne t,
Show t, HasAntiConsistency t, HasLegalValues t,
Show (ExpEffortIndicator t),
EffortIndicator (ExpEffortIndicator t),
Show (MultEffortIndicator t),
EffortIndicator (MultEffortIndicator t),
Show (RefOrd.PartialCompareEffortIndicator t),
EffortIndicator (RefOrd.PartialCompareEffortIndicator t)
) =>
t ->
(ConsistencyEffortIndicator t) ->
(RefOrd.PartialCompareEffortIndicator t,
(ExpEffortIndicator t, MultEffortIndicator t)) ->
(RefOrd.UniformlyOrderedSingleton t) ->
Bool
propExpOfNegRecip _ effortConsistency initEffort
(RefOrd.UniformlyOrderedSingleton e1) =
thinEqualConsLeqRoundingUpDnImprovement "e^a * e^(-a) ⊑/⊒ 1" [e1]
expr1In expr1Out expr2In expr2Out
RefOrd.pLeqEff
effortConsistency
initEffort
where
expr1In (effExp, effMult) =
-- unsafePrintReturn (
-- "propExpOfNegRecip: expr2In: "
-- ++ "\n e1 = " ++ (show e1)
-- ++ "\n expInEff effExp e1 = " ++ (show $ expInEff effExp e1)
-- ++ "\n expInEff effExp (neg e1) = " ++ (show $ expInEff effExp (neg e1))
-- ++ "\n product of the above = "
-- ) $
let (>*<) = multInEff effMult in
(expInEff effExp e1) >*< (expInEff effExp (neg e1))
expr1Out (effExp, effMult) =
let (<*>) = multOutEff effMult in
(expOutEff effExp e1) <*> (expOutEff effExp (neg e1))
expr2In (effExp, effMult) = one
expr2Out (effExp, effMult) = one
-- | @e^(b+c) = e^b * e^c@
propExpOfAddToMult ::
(RefOrd.PartialComparison t,
RoundedExponentiation t, RoundedMultiply t, RoundedAdd t,
Show t, HasLegalValues t,
Show (ExpEffortIndicator t),
EffortIndicator (ExpEffortIndicator t),
Show (MultEffortIndicator t),
EffortIndicator (MultEffortIndicator t),
Show (AddEffortIndicator t),
EffortIndicator (AddEffortIndicator t),
Show (RefOrd.PartialCompareEffortIndicator t),
EffortIndicator (RefOrd.PartialCompareEffortIndicator t)
) =>
t ->
(RefOrd.PartialCompareEffortIndicator t,
(ExpEffortIndicator t, MultEffortIndicator t, AddEffortIndicator t)) ->
(RefOrd.UniformlyOrderedPair t) ->
Bool
propExpOfAddToMult _ initEffort (RefOrd.UniformlyOrderedPair (e1, e2)) =
equalRoundingUpDn "e^(a + b) = e^a * e^b"
expr1In expr1Out expr2In expr2Out
RefOrd.pLeqEff initEffort
where
expr1In (effExp, effMult, effAdd) =
let (+^) = addInEff effAdd in
(expInEff effExp (e1 +^ e2))
expr1Out (effExp, effMult, effAdd) =
let (+.) = addOutEff effAdd in
(expOutEff effExp (e1 +. e2))
expr2In (effExp, effMult, effAdd) =
let (*^) = multInEff effMult in
(expInEff effExp e1) *^ (expInEff effExp e2)
expr2Out (effExp, effMult, effAdd) =
let (*.) = multOutEff effMult in
(expOutEff effExp e1) *. (expOutEff effExp e2)
testsInOutExp (name, sample) =
testGroup (name ++ " exp in/out") $
[
testProperty "e^a * e^(-a) ⊑/⊒ 1" (propExpOfNegRecip sample)
,
testProperty "e^(a + b) = e^a * e^b" (propExpOfAddToMult sample)
]
benchInOutExp (name, sample) areas =
bgroup (name ++ " exp") $
mkBenchAreasSequences1 (mkCommentImprecision1 expOutEff expInEff)
expOutEff areas 10 (expDefaultEffort sample) sample
benchExpAreasReal =
[
("near 0", NumOrd.AreaLinear (Just $ -1/2) True (Just $ 1/2) True [])
,
("near -10", NumOrd.AreaLinear (Just $ -10.5) True (Just $ -9.5) True [])
,
("near 10", NumOrd.AreaLinear (Just $ 9.5) True (Just $ 10.5) True [])
,
("near 20", NumOrd.AreaLinear (Just $ 19.5) True (Just $ 20.5) True [])
]
class RoundedSquareRootEffort t where
type SqrtEffortIndicator t
sqrtDefaultEffort :: t -> SqrtEffortIndicator t
class (RoundedSquareRootEffort t) => RoundedSquareRoot t where
sqrtInEff :: (SqrtEffortIndicator t) -> t -> t
sqrtOutEff :: (SqrtEffortIndicator t) -> t -> t
propSqrtSquare ::
(RefOrd.PartialComparison t,
RoundedSquareRoot t, RoundedMultiply t, HasZero t,
UpDnConversion.Convertible t Double,
RoundedMixedAdd t Double,
Show t, HasLegalValues t,
-- ShowInternals t,
Show (UpDnConversion.ConvertEffortIndicator t Double),
EffortIndicator (UpDnConversion.ConvertEffortIndicator t Double),
Show (MixedAddEffortIndicator t Double),
EffortIndicator (MixedAddEffortIndicator t Double),
Show (SqrtEffortIndicator t),
EffortIndicator (SqrtEffortIndicator t),
Show (MultEffortIndicator t),
EffortIndicator (MultEffortIndicator t),
Show (RefOrd.PartialCompareEffortIndicator t),
EffortIndicator (RefOrd.PartialCompareEffortIndicator t)
) =>
t ->
(tInArea -> t) ->
(UpDnConversion.ConvertEffortIndicator t Double,
MixedAddEffortIndicator t Double) ->
(RefOrd.PartialCompareEffortIndicator t,
(SqrtEffortIndicator t,
MultEffortIndicator t,
RefOrd.PartialCompareEffortIndicator t)) ->
tInArea -> Bool
propSqrtSquare _ fromArea (effortToDbl, effortAddDbl) initEffort e1InArea =
equalRoundingUpDn "sqrt(e)^2 = e"
expr1In expr1Out expr2In expr2Out
RefOrd.pLeqEff initEffort
where
e1Pos = fromArea e1InArea
-- case maybeE1LowerBoundD of
-- Just e1LowerBoundD
-- | e1LowerBoundD <= (0 :: Double) ->
-- mixedAddOutEff effortAddDbl e1 (0.5 - e1LowerBoundD)
-- | otherwise -> e1
-- _ -> e1
-- where
-- maybeE1LowerBoundD = UpDnConversion.convertDnEff effortToDbl e1
expr1In (effSqrt, effMult, effCompare) =
sqrtE1 >*< sqrtE1
where
(>*<) = multInEff effMult
sqrtE1 = sqrtInEff effSqrt e1Pos
expr1Out (effSqrt, effMult, effCompare) =
sqrtE1 <*> sqrtE1
where
(<*>) = multOutEff effMult
sqrtE1 = sqrtOutEff effSqrt e1Pos
expr2In _ = e1Pos
expr2Out _ = e1Pos
testsInOutSqrt (name, sample) fromArea =
testGroup (name ++ " sqrt in/out") $
[
testProperty "sqrt(e)^2 = e" (propSqrtSquare sample fromArea)
]