packages feed

AERN-Real-2011.1: src/Numeric/AERN/RealArithmetic/RefinementOrderRounding/MixedFieldOps.hs

{-# LANGUAGE TypeFamilies #-}
{-# LANGUAGE MultiParamTypeClasses #-}
{-# LANGUAGE FlexibleContexts #-}
{-# LANGUAGE ImplicitParams #-}
{-|
    Module      :  Numeric.AERN.RefinementOrderRounding.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 RefinementOrderRounding. 
-}
module Numeric.AERN.RealArithmetic.RefinementOrderRounding.MixedFieldOps where

import Numeric.AERN.RealArithmetic.RefinementOrderRounding.FieldOps
import Numeric.AERN.RealArithmetic.RefinementOrderRounding.Conversion
import Numeric.AERN.RealArithmetic.ExactOps

import Numeric.AERN.Basics.Effort
import Numeric.AERN.Basics.Exception (HasLegalValues)
import Numeric.AERN.RealArithmetic.Laws
import Numeric.AERN.RealArithmetic.Measures
import qualified Numeric.AERN.Basics.NumericOrder as NumOrd
import qualified Numeric.AERN.Basics.RefinementOrder as RefOrd
import Numeric.AERN.Basics.RefinementOrder.OpsImplicitEffort

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
    mixedAddInEff :: MixedAddEffortIndicator t tn -> t -> tn -> t
    mixedAddOutEff :: MixedAddEffortIndicator t tn -> t -> tn -> t

mixedAddDefaultEffortByConversion d n = 
        (addDefaultEffort d, convertDefaultEffort n d)

mixedAddInEffByConversion ::
    (Convertible tn t, RoundedAdd t) =>
    (AddEffortIndicator t, ConvertEffortIndicator tn t) ->
    t -> tn -> t
mixedAddInEffByConversion (effAdd, effConv) d n = 
    addInEff effAdd d (convertInEff effConv n)

mixedAddOutEffByConversion ::
    (Convertible tn t, RoundedAdd t) =>
    (AddEffortIndicator t, ConvertEffortIndicator tn t) ->
    t -> tn -> t
mixedAddOutEffByConversion (effAdd, effConv) d n = 
    addOutEff effAdd d (convertOutEff effConv n)


propMixedAddEqualsConvert ::
    (RefOrd.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 (RefOrd.PartialCompareEffortIndicator t),
     EffortIndicator (RefOrd.PartialCompareEffortIndicator t)
     ) =>
    t -> tn ->
    (RefOrd.PartialCompareEffortIndicator t,
     (MixedAddEffortIndicator t tn,      
      AddEffortIndicator t,
      ConvertEffortIndicator tn t)) -> 
    (RefOrd.UniformlyOrderedSingleton t) -> 
    tn -> Bool
propMixedAddEqualsConvert sample sampleN initEffort 
        (RefOrd.UniformlyOrderedSingleton d) n =
    equalRoundingUpDn "mixed addition by conversion"
        expr1In expr1Out expr2In expr2Out
        RefOrd.pLeqEff initEffort
    where
    expr1In (effMAdd,_,_) =
        let (>+<|) = mixedAddInEff effMAdd in d >+<| n
    expr1Out (effMAdd,_,_) =
        let (<+>|) = mixedAddOutEff effMAdd in d <+>| n
    expr2In (_,effAdd,effConv) =
        let (>+<) = addInEff effAdd in  d >+< (convertInEff effConv n)
    expr2Out (_,effAdd,effConv) =
        let (<+>) = addOutEff effAdd in  d <+> (convertOutEff 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
    mixedMultInEff :: MixedMultEffortIndicator t tn -> t -> tn -> t
    mixedMultOutEff :: MixedMultEffortIndicator t tn -> t -> tn -> t

mixedMultDefaultEffortByConversion d n = 
        (multDefaultEffort d, convertDefaultEffort n d)

mixedMultInEffByConversion ::
    (Convertible tn t, RoundedMultiply t) =>
    (MultEffortIndicator t, ConvertEffortIndicator tn t) ->
    t -> tn -> t
mixedMultInEffByConversion (effMult, effConv) d n = 
    multInEff effMult d (convertInEff effConv n)

mixedMultOutEffByConversion ::
    (Convertible tn t, RoundedMultiply t) =>
    (MultEffortIndicator t, ConvertEffortIndicator tn t) ->
    t -> tn -> t
mixedMultOutEffByConversion (effMult, effConv) d n = 
    multOutEff effMult d (convertOutEff effConv n)


propMixedMultEqualsConvert ::
    (RefOrd.PartialComparison 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 (RefOrd.PartialCompareEffortIndicator t),
     EffortIndicator (RefOrd.PartialCompareEffortIndicator t)
     ) =>
    t -> tn ->
    (RefOrd.PartialCompareEffortIndicator t,
      (MixedMultEffortIndicator t tn,      
       MultEffortIndicator t,
       ConvertEffortIndicator tn t)) -> 
    (RefOrd.UniformlyOrderedSingleton t) -> 
    tn -> Bool
propMixedMultEqualsConvert sample sampleN initEffort 
        (RefOrd.UniformlyOrderedSingleton d) n =
    equalRoundingUpDn "mixed multiplication by conversion"
        expr1In expr1Out expr2In expr2Out
        RefOrd.pLeqEff initEffort
    where
    expr1In (effMMult,_,_) =
        let (>*<|) = mixedMultInEff effMMult in d >*<| n
    expr1Out (effMMult,_,_) =
        let (<*>|) = mixedMultOutEff effMMult in d <*>| n
    expr2In (_,effMult,effConv) =
        let (>*<) = multInEff effMult in d >*< (convertInEff effConv n)
    expr2Out (_,effMult,effConv) =
        let (<*>) = multOutEff effMult in d <*> (convertOutEff 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
    mixedDivInEff :: MixedDivEffortIndicator t tn -> t -> tn -> t
    mixedDivOutEff :: MixedDivEffortIndicator t tn -> t -> tn -> t

mixedDivDefaultEffortByConversion d n = 
        (divDefaultEffort d, convertDefaultEffort n d)

mixedDivInEffByConversion ::
    (Convertible tn t, RoundedDivide t) =>
    (DivEffortIndicator t, ConvertEffortIndicator tn t) ->
    t -> tn -> t
mixedDivInEffByConversion (effDiv, effConv) d n = 
    divInEff effDiv d (convertInEff effConv n)

mixedDivOutEffByConversion ::
    (Convertible tn t, RoundedDivide t) =>
    (DivEffortIndicator t, ConvertEffortIndicator tn t) ->
    t -> tn -> t
mixedDivOutEffByConversion (effDiv, effConv) d n = 
    divOutEff effDiv d (convertOutEff effConv n)


propMixedDivEqualsConvert ::
    (RefOrd.PartialComparison t, Convertible tn t,
     RoundedMixedDivide t tn, RoundedDivide t,
     Show t, HasZero t, HasLegalValues t,
     Show (MixedDivEffortIndicator t tn),
     EffortIndicator (MixedDivEffortIndicator t tn),
     Show (ConvertEffortIndicator tn t),
     EffortIndicator (ConvertEffortIndicator tn t),
     Show (DivEffortIndicator t),
     EffortIndicator (DivEffortIndicator t),
     Show (RefOrd.PartialCompareEffortIndicator t),
     EffortIndicator (RefOrd.PartialCompareEffortIndicator t)
     ) =>
    t -> tn ->
    (RefOrd.PartialCompareEffortIndicator t,
     (MixedDivEffortIndicator t tn,      
      DivEffortIndicator t,
      ConvertEffortIndicator tn t)) -> 
    (RefOrd.UniformlyOrderedSingleton t) -> 
    tn -> Bool
propMixedDivEqualsConvert sample sampleN initEffort@(effComp,(_,_,effConv)) 
        (RefOrd.UniformlyOrderedSingleton d) n
    =
    equalRoundingUpDn "mixed division by conversion"
        expr1In expr1Out expr2In expr2Out
        RefOrd.pLeqEff initEffort
    where
    expr1In (effMDiv,_,_) =
        let (>/<|) = mixedDivInEff effMDiv in d >/<| n
    expr1Out (effMDiv,_,_) =
        let (</>|) = mixedDivOutEff effMDiv in d </>| n
    expr2In (_,effDiv,effConv) =
        let (>/<) = divInEff effDiv in d >/< (convertInEff effConv n)
    expr2Out (_,effDiv,effConv) =
        let (</>) = divOutEff effDiv in d </> (convertOutEff effConv n)

    
testsInOutMixedFieldOps (name, sample) (nameN, sampleN) =
    testGroup (name ++ " with " ++ nameN ++ ": mixed in/out 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) => 
    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