AERN-Real-2011.1: src/Numeric/AERN/RealArithmetic/NumericOrderRounding/MixedFieldOps.hs
{-# LANGUAGE TypeFamilies #-}
{-# LANGUAGE MultiParamTypeClasses #-}
{-# LANGUAGE FlexibleContexts #-}
{-# LANGUAGE ImplicitParams #-}
{-|
Module : Numeric.AERN.RealArithmetic.NumericOrderRounding.MixedFieldOps
Description : rounded basic arithmetic operations mixing 2 types
Copyright : (c) Michal Konecny
License : BSD3
Maintainer : mikkonecny@gmail.com
Stability : experimental
Portability : portable
Rounded basic arithmetical operations mixing 2 types.
This module is hidden and reexported via its parent NumericOrderRounding.
-}
module Numeric.AERN.RealArithmetic.NumericOrderRounding.MixedFieldOps where
import Numeric.AERN.RealArithmetic.NumericOrderRounding.FieldOps
import Numeric.AERN.RealArithmetic.NumericOrderRounding.Conversion
import Numeric.AERN.RealArithmetic.ExactOps
import Numeric.AERN.Basics.Exception
import Numeric.AERN.Basics.Effort
import Numeric.AERN.RealArithmetic.Laws
import Numeric.AERN.RealArithmetic.Measures
import qualified Numeric.AERN.Basics.NumericOrder as NumOrd
import Numeric.AERN.Basics.NumericOrder.OpsImplicitEffort
import Control.Exception
import Data.Maybe
import Test.QuickCheck
import Test.Framework (testGroup, Test)
import Test.Framework.Providers.QuickCheck2 (testProperty)
class RoundedMixedAddEffort t tn where
type MixedAddEffortIndicator t tn
mixedAddDefaultEffort :: t -> tn -> MixedAddEffortIndicator t tn
class (RoundedMixedAddEffort t tn) => RoundedMixedAdd t tn where
mixedAddUpEff :: MixedAddEffortIndicator t tn -> t -> tn -> t
mixedAddDnEff :: MixedAddEffortIndicator t tn -> t -> tn -> t
{- tools to easily make a RoundedMixedAdd instance
via the composition of conversion and homogeneous addition -}
type MixedAddEffortIndicatorByConversion t tn =
(AddEffortIndicator t, ConvertEffortIndicator tn t)
mixedAddDefaultEffortByConversion d n =
(addDefaultEffort d, convertDefaultEffort n d)
mixedAddUpEffByConversion ::
(Convertible tn t, RoundedAdd t, Show tn) =>
(AddEffortIndicator t, ConvertEffortIndicator tn t) ->
t -> tn -> t
mixedAddUpEffByConversion (effAdd, effConv) d n =
addUpEff effAdd nUp d
where
nUp =
case convertUpEff effConv n of
(Just nUp) -> nUp
_ -> throw $ AERNException $
"conversion failed during mixed addition: n = " ++ show n
mixedAddDnEffByConversion ::
(Convertible tn t, RoundedAdd t, Show tn) =>
(AddEffortIndicator t, ConvertEffortIndicator tn t) ->
t -> tn -> t
mixedAddDnEffByConversion (effAdd, effConv) d n =
addDnEff effAdd nDn d
where
nDn =
case convertDnEff effConv n of
(Just nDn) -> nDn
_ -> throw $ AERNException $
"conversion failed during mixed addition: n = " ++ show n
{- properties of mixed addition -}
propMixedAddEqualsConvert ::
(NumOrd.PartialComparison t, Convertible tn t,
RoundedMixedAdd t tn, RoundedAdd t,
Show t, HasLegalValues t,
Show (MixedAddEffortIndicator t tn),
EffortIndicator (MixedAddEffortIndicator t tn),
Show (ConvertEffortIndicator tn t),
EffortIndicator (ConvertEffortIndicator tn t),
Show (AddEffortIndicator t),
EffortIndicator (AddEffortIndicator t),
Show (NumOrd.PartialCompareEffortIndicator t),
EffortIndicator (NumOrd.PartialCompareEffortIndicator t)
) =>
t -> tn ->
(NumOrd.PartialCompareEffortIndicator t,
(MixedAddEffortIndicator t tn,
AddEffortIndicator t,
ConvertEffortIndicator tn t)) ->
(NumOrd.UniformlyOrderedSingleton t) ->
tn ->
Bool
propMixedAddEqualsConvert sampleN sample initEffort
(NumOrd.UniformlyOrderedSingleton d) n =
equalRoundingUpDn "mixed addition by conversion"
expr1Up expr1Dn expr2Up expr2Dn
NumOrd.pLeqEff initEffort
where
expr1Up (effMAdd,_,_) =
let (+^|) = mixedAddUpEff effMAdd in d +^| n
expr1Dn (effMAdd,_,_) =
let (+.|) = mixedAddDnEff effMAdd in d +.| n
expr2Up (_,effAdd,effConv) =
let (+^) = addUpEff effAdd in d +^ (fromJust $ convertUpEff effConv n)
expr2Dn (_,effAdd,effConv) =
let (+.) = addDnEff effAdd in d +. (fromJust $ convertDnEff effConv n)
class RoundedMixedMultiplyEffort t tn where
type MixedMultEffortIndicator t tn
mixedMultDefaultEffort :: t -> tn -> MixedMultEffortIndicator t tn
class (RoundedMixedMultiplyEffort t tn) => RoundedMixedMultiply t tn where
mixedMultUpEff :: MixedMultEffortIndicator t tn -> t -> tn -> t
mixedMultDnEff :: MixedMultEffortIndicator t tn -> t -> tn -> t
{- tools to easily make a RoundedMixedMultiply instance
via the composition of conversion and homogeneous addition -}
type MixedMultEffortIndicatorByConversion t tn =
(MultEffortIndicator t,
ConvertEffortIndicator tn t,
NumOrd.MinmaxEffortIndicator t)
mixedMultDefaultEffortByConversion d n =
(addDefaultEffort d,
convertDefaultEffort n d,
NumOrd.minmaxDefaultEffort d)
mixedMultUpEffByConversion ::
(Convertible tn t, RoundedMultiply t, NumOrd.RoundedLattice t, Show tn) =>
(MultEffortIndicator t,
ConvertEffortIndicator tn t,
NumOrd.MinmaxEffortIndicator t) ->
t -> tn -> t
mixedMultUpEffByConversion (effMult, effConv, effMinmax) d n =
NumOrd.maxUpEff effMinmax
(multUpEff effMult d nDn)
(multUpEff effMult d nUp)
where
(nUp, nDn) =
case (convertUpEff effConv n, convertDnEff effConv n) of
(Just nUp, Just nDn) -> (nUp, nDn)
_ -> throw $ AERNException $
"conversion failed during mixed multiplication: n = " ++ show n
mixedMultDnEffByConversion ::
(Convertible tn t, RoundedMultiply t, NumOrd.RoundedLattice t, Show tn) =>
(MultEffortIndicator t,
ConvertEffortIndicator tn t,
NumOrd.MinmaxEffortIndicator t) ->
t -> tn -> t
mixedMultDnEffByConversion (effMult, effConv, effMinmax) d n =
NumOrd.minDnEff effMinmax
(multDnEff effMult d nDn)
(multDnEff effMult d nUp)
where
(nUp, nDn) =
case (convertUpEff effConv n, convertDnEff effConv n) of
(Just nUp, Just nDn) -> (nUp, nDn)
_ -> throw $ AERNException $
"conversion failed during mixed multiplication: n = " ++ show n
{- properties of mixed multiplication -}
propMixedMultEqualsConvert ::
(NumOrd.PartialComparison t, NumOrd.RoundedLattice t,
Convertible tn t,
RoundedMixedMultiply t tn, RoundedMultiply t,
Show t, HasLegalValues t,
Show (MixedMultEffortIndicator t tn),
EffortIndicator (MixedMultEffortIndicator t tn),
Show (ConvertEffortIndicator tn t),
EffortIndicator (ConvertEffortIndicator tn t),
Show (MultEffortIndicator t),
EffortIndicator (MultEffortIndicator t),
Show (NumOrd.MinmaxEffortIndicator t),
EffortIndicator (NumOrd.MinmaxEffortIndicator t),
Show (NumOrd.PartialCompareEffortIndicator t),
EffortIndicator (NumOrd.PartialCompareEffortIndicator t)
) =>
t -> tn ->
(NumOrd.PartialCompareEffortIndicator t,
(MixedMultEffortIndicator t tn,
(MultEffortIndicator t,
ConvertEffortIndicator tn t,
NumOrd.MinmaxEffortIndicator t))) ->
(NumOrd.UniformlyOrderedSingleton t) ->
tn -> Bool
propMixedMultEqualsConvert sample sampleN initEffort
(NumOrd.UniformlyOrderedSingleton d) n =
equalRoundingUpDn "mixed multiplication by conversion"
expr1Up expr1Dn expr2Up expr2Dn
NumOrd.pLeqEff initEffort
where
expr1Up (effMMult,_) =
let (*^|) = mixedMultUpEff effMMult in d *^| n
expr1Dn (effMMult,_) =
let (*.|) = mixedMultDnEff effMMult in d *.| n
expr2Up (_,(effMult,effConv,effMinmax)) =
let (*^) = multUpEff effMult in
NumOrd.maxUpEff effMinmax
(d *^ (fromJust $ convertUpEff effConv n))
(d *^ (fromJust $ convertDnEff effConv n))
expr2Dn (_,(effMult,effConv,effMinmax)) =
let (*.) = multDnEff effMult in
NumOrd.minDnEff effMinmax
(d *. (fromJust $ convertUpEff effConv n))
(d *. (fromJust $ convertDnEff effConv n))
class RoundedMixedDivideEffort t tn where
type MixedDivEffortIndicator t tn
mixedDivDefaultEffort :: t -> tn -> MixedDivEffortIndicator t tn
class (RoundedMixedDivideEffort t tn) => RoundedMixedDivide t tn where
mixedDivUpEff :: MixedDivEffortIndicator t tn -> t -> tn -> t
mixedDivDnEff :: MixedDivEffortIndicator t tn -> t -> tn -> t
{- tools to easily make a RoundedMixedDivide instance
via the composition of conversion and homogeneous addition -}
type MixedDivEffortIndicatorByConversion t tn =
(DivEffortIndicator t,
ConvertEffortIndicator tn t,
(NumOrd.MinmaxEffortIndicator t,
NumOrd.PartialCompareEffortIndicator t))
mixedDivDefaultEffortByConversion d n =
(addDefaultEffort d,
convertDefaultEffort n d,
(NumOrd.minmaxDefaultEffort d,
NumOrd.pCompareDefaultEffort d))
mixedDivUpEffByConversion ::
(Convertible tn t,
RoundedDivide t,
HasZero t, HasInfinities t,
NumOrd.PartialComparison t,
NumOrd.RoundedLattice t,
Show tn) =>
(DivEffortIndicator t,
ConvertEffortIndicator tn t,
(NumOrd.MinmaxEffortIndicator t,
NumOrd.PartialCompareEffortIndicator t)) ->
t -> tn -> t
mixedDivUpEffByConversion (effDiv, effConv, (effMinmax, effComp)) d n =
let ?pCompareEffort = effComp in
case (nDn >=? zero, nUp <=? zero) of
(Just True, _) -> normalResult
(_, Just True) -> normalResult
_ -> plusInfinity -- b is too close to zero
where
normalResult =
NumOrd.maxDnEff effMinmax -- we do not know the sign of a
(divUpEff effDiv d nDn)
(divUpEff effDiv d nUp)
(nUp, nDn) =
case (convertUpEff effConv n, convertDnEff effConv n) of
(Just nUp, Just nDn) -> (nUp, nDn)
_ -> throw $ AERNException $
"conversion failed during mixed division: n = " ++ show n
mixedDivDnEffByConversion ::
(Convertible tn t,
RoundedDivide t,
HasZero t, HasInfinities t,
NumOrd.PartialComparison t,
NumOrd.RoundedLattice t,
Show tn) =>
(DivEffortIndicator t,
ConvertEffortIndicator tn t,
(NumOrd.MinmaxEffortIndicator t,
NumOrd.PartialCompareEffortIndicator t)) ->
t -> tn -> t
mixedDivDnEffByConversion (effDiv, effConv, (effMinmax, effComp)) d n =
let ?pCompareEffort = effComp in
case (nDn >=? zero, nUp <=? zero) of
(Just True, _) -> normalResult
(_, Just True) -> normalResult
_ -> minusInfinity -- b is too close to zero
where
normalResult =
NumOrd.minDnEff effMinmax -- we do not know the sign of a
(divDnEff effDiv d nDn)
(divDnEff effDiv d nUp)
(nUp, nDn) =
case (convertUpEff effConv n, convertDnEff effConv n) of
(Just nUp, Just nDn) -> (nUp, nDn)
_ -> throw $ AERNException $
"conversion failed during mixed division: n = " ++ show n
{- properties of mixed multiplication -}
propMixedDivEqualsConvert ::
(NumOrd.PartialComparison t, NumOrd.RoundedLattice t,
Convertible tn t,
RoundedMixedDivide t tn, RoundedDivide t,
Show t, HasLegalValues t,
HasZero t,
Show (MixedDivEffortIndicator t tn),
EffortIndicator (MixedDivEffortIndicator t tn),
Show (ConvertEffortIndicator tn t),
EffortIndicator (ConvertEffortIndicator tn t),
Show (DivEffortIndicator t),
EffortIndicator (DivEffortIndicator t),
Show (NumOrd.MinmaxEffortIndicator t),
EffortIndicator (NumOrd.MinmaxEffortIndicator t),
Show (NumOrd.PartialCompareEffortIndicator t),
EffortIndicator (NumOrd.PartialCompareEffortIndicator t)
) =>
t -> tn ->
(NumOrd.PartialCompareEffortIndicator t,
(MixedDivEffortIndicator t tn,
(DivEffortIndicator t,
ConvertEffortIndicator tn t,
NumOrd.MinmaxEffortIndicator t))) ->
(NumOrd.UniformlyOrderedSingleton t) ->
tn -> Bool
propMixedDivEqualsConvert sample sampleN initEffort@(effComp,(_,(_,effConv,_)))
(NumOrd.UniformlyOrderedSingleton d) n
=
equalRoundingUpDn "mixed division by conversion"
expr1Up expr1Dn expr2Up expr2Dn
NumOrd.pLeqEff initEffort
where
expr1Up (effMDiv,_) =
let (/^|) = mixedDivUpEff effMDiv in d /^| n
expr1Dn (effMDiv,_) =
let (/.|) = mixedDivDnEff effMDiv in d /.| n
expr2Up (_,(effDiv,effConv,effMinmax)) =
let (/^) = divUpEff effDiv in
NumOrd.maxUpEff effMinmax
(d /^ (fromJust $ convertUpEff effConv n))
(d /^ (fromJust $ convertDnEff effConv n))
expr2Dn (_,(effDiv,effConv,effMinmax)) =
let (/.) = divDnEff effDiv in
NumOrd.minDnEff effMinmax
(d /. (fromJust $ convertUpEff effConv n))
(d /. (fromJust $ convertDnEff effConv n))
testsUpDnMixedFieldOps (name, sample) (nameN, sampleN) =
testGroup (name ++ " with " ++ nameN ++ ": mixed up/dn rounded ops") $
[
testProperty "addition" (propMixedAddEqualsConvert sample sampleN)
,
testProperty "multiplication" (propMixedMultEqualsConvert sample sampleN)
,
testProperty "division" (propMixedDivEqualsConvert sample sampleN)
]
class (RoundedMixedAddEffort t tn, RoundedMixedMultiplyEffort t tn) =>
RoundedMixedRingEffort t tn
where
type MixedRingOpsEffortIndicator t tn
mixedRingOpsDefaultEffort :: t -> tn -> MixedRingOpsEffortIndicator t tn
mxringEffortAdd :: t -> tn -> MixedRingOpsEffortIndicator t tn -> MixedAddEffortIndicator t tn
mxringEffortMult :: t -> tn -> MixedRingOpsEffortIndicator t tn -> MixedMultEffortIndicator t tn
class (RoundedMixedAdd t tn, RoundedMixedMultiply t tn, RoundedMixedRingEffort t tn) =>
RoundedMixedRing t tn
class (RoundedMixedRingEffort t tn, RoundedMixedDivideEffort t tn) =>
RoundedMixedFieldEffort t tn
where
type MixedFieldOpsEffortIndicator t tn
mixedFieldOpsDefaultEffort :: t -> tn -> MixedFieldOpsEffortIndicator t tn
mxfldEffortAdd :: t -> tn -> MixedFieldOpsEffortIndicator t tn -> MixedAddEffortIndicator t tn
mxfldEffortMult :: t -> tn -> MixedFieldOpsEffortIndicator t tn -> MixedMultEffortIndicator t tn
mxfldEffortDiv :: t -> tn -> MixedFieldOpsEffortIndicator t tn -> MixedDivEffortIndicator t tn
class (RoundedMixedRing t tn, RoundedMixedDivide t tn, RoundedMixedFieldEffort t tn) =>
RoundedMixedField t tn