packages feed

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

{-# LANGUAGE TypeFamilies #-}
{-# LANGUAGE FlexibleContexts #-}
{-# LANGUAGE ImplicitParams #-}
{-# LANGUAGE RankNTypes #-}
{-|
    Module      :  Numeric.AERN.RealArithmetic.RefinementOrderRounding.InPlace.FieldOps
    Description :  rounded basic arithmetic operations  
    Copyright   :  (c) Michal Konecny, Jan Duracz
    License     :  BSD3

    Maintainer  :  mikkonecny@gmail.com
    Stability   :  experimental
    Portability :  portable
    
    In-place versions of rounded basic arithmetic operations.
    
    Each operations takes mutable parameters instead of pure parameters
    and has one extra mutable parameter before the other parameters, 
    in which it stores the result.
    The mutable parameters can alias arbitrarily, making it possible
    to eg add to a number overwriting the original number.
    
    The operations have as their first paramter a non-mutable sample value
    to aid type-checking, ie to help work out which type the mutable parameters
    contain.
    
    This module is hidden and reexported via its parent RefinementOrderRounding.InPlace. 
-}
module Numeric.AERN.RealArithmetic.RefinementOrderRounding.InPlace.FieldOps 
where

import Prelude hiding (EQ, LT, GT)
import Numeric.AERN.Basics.PartialOrdering

import Numeric.AERN.RealArithmetic.RefinementOrderRounding.FieldOps

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

import Numeric.AERN.Basics.Effort
import Numeric.AERN.Basics.Exception (HasLegalValues)
import Numeric.AERN.Basics.Mutable
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)

import Control.Monad.ST
import Data.Maybe

class (RoundedAddEffort t, CanBeMutable t) => RoundedAddInPlace t where
    addInInPlaceEff :: OpMutable2Eff (AddEffortIndicator t) t s
    addOutInPlaceEff :: OpMutable2Eff (AddEffortIndicator t) t s

addInInPlaceEffFromPure,
 addOutInPlaceEffFromPure ::
    (CanBeMutable t, RoundedAdd t) =>
    OpMutable2Eff (AddEffortIndicator t) t s
addInInPlaceEffFromPure = pureToMutable2Eff addInEff 
addOutInPlaceEffFromPure = pureToMutable2Eff addOutEff 

addInInPlaceEffFromInPlace,
 addOutInPlaceEffFromInPlace :: 
    (RoundedAddInPlace t) =>
    (AddEffortIndicator t) -> t -> t -> t
addInInPlaceEffFromInPlace = mutable2EffToPure addInInPlaceEff 
addOutInPlaceEffFromInPlace = mutable2EffToPure addOutInPlaceEff 

propInOutAddInPlace ::
    (RefOrd.PartialComparison t, 
     RoundedAddInPlace t, 
     RoundedAdd t, 
     Neg t,
     Show t, HasLegalValues t,
     Show (AddEffortIndicator t),
     EffortIndicator (AddEffortIndicator t),
     Show (RefOrd.PartialCompareEffortIndicator t),
     EffortIndicator (RefOrd.PartialCompareEffortIndicator t)
     ) =>
    t ->
    (RefOrd.PartialCompareEffortIndicator t, 
     AddEffortIndicator t) -> 
    (RefOrd.UniformlyOrderedPair t) -> Bool
propInOutAddInPlace sample initEffort (RefOrd.UniformlyOrderedPair (e1, e2)) =
    roundedInPlace2ConsistentWithPure "addition"
        addInInPlaceEff addOutInPlaceEff addInEff addOutEff
        RefOrd.pLeqEff initEffort
        e1 e2

class (RoundedAddInPlace t, NegInPlace t) => RoundedSubtrInPlace t where
    subtrInInPlaceEff :: OpMutable2Eff (AddEffortIndicator t) t s
    subtrOutInPlaceEff :: OpMutable2Eff (AddEffortIndicator t) t s
    subtrInInPlaceEff effort rM aM bM =
        do
        bbM <- cloneMutable bM
        negInPlace bbM bM
        addInInPlaceEff effort rM aM bbM
    subtrOutInPlaceEff effort rM aM bM = 
        do
        bbM <- cloneMutable bM
        negInPlace bbM bM
        addOutInPlaceEff effort rM aM bbM

propInOutSubtrInPlace ::
    (RefOrd.PartialComparison t, 
     RoundedSubtrInPlace t, 
     RoundedSubtr t, 
     Neg t,
     Show t, HasLegalValues t,
     Show (AddEffortIndicator t),
     EffortIndicator (AddEffortIndicator t),
     Show (RefOrd.PartialCompareEffortIndicator t),
     EffortIndicator (RefOrd.PartialCompareEffortIndicator t)
     ) =>
    t ->
    (RefOrd.PartialCompareEffortIndicator t, 
     AddEffortIndicator t) -> 
    (RefOrd.UniformlyOrderedPair t) -> Bool
propInOutSubtrInPlace sample initEffort (RefOrd.UniformlyOrderedPair (e1, e2)) =
    roundedInPlace2ConsistentWithPure "subtraction"
        subtrInInPlaceEff subtrOutInPlaceEff subtrInEff subtrOutEff
        RefOrd.pLeqEff initEffort
        e1 e2

class (RoundedAbs t, CanBeMutable t) => RoundedAbsInPlace t where
    absInInPlaceEff :: OpMutable1Eff (AbsEffortIndicator t) t s
    absOutInPlaceEff :: OpMutable1Eff (AbsEffortIndicator t) t s
    absInInPlaceEff = pureToMutable1Eff absInEff 
    absOutInPlaceEff = pureToMutable1Eff absOutEff 

propInOutAbsInPlace ::
    (RefOrd.PartialComparison t, RoundedAbsInPlace t, Neg t,
     Show t, HasLegalValues t,
     Show (AbsEffortIndicator t),
     EffortIndicator (AbsEffortIndicator t),
     Show (RefOrd.PartialCompareEffortIndicator t),
     EffortIndicator (RefOrd.PartialCompareEffortIndicator t)
     ) =>
    t ->
    (RefOrd.PartialCompareEffortIndicator t, 
     AbsEffortIndicator t) -> 
    (RefOrd.UniformlyOrderedSingleton t) -> Bool
propInOutAbsInPlace sample initEffort (RefOrd.UniformlyOrderedSingleton e) =
    roundedInPlace1ConsistentWithPure "abs"
        absInInPlaceEff absOutInPlaceEff absInEff absOutEff
        RefOrd.pLeqEff initEffort
        e


class (RoundedMultiplyEffort t, CanBeMutable t) => RoundedMultiplyInPlace t where
    multInInPlaceEff :: OpMutable2Eff (MultEffortIndicator t) t s
    multOutInPlaceEff :: OpMutable2Eff (MultEffortIndicator t) t s

multInInPlaceEffFromPure,
 multOutInPlaceEffFromPure ::
    (CanBeMutable t, RoundedMultiply t) =>
    OpMutable2Eff (MultEffortIndicator t) t s
multInInPlaceEffFromPure = pureToMutable2Eff multInEff 
multOutInPlaceEffFromPure = pureToMutable2Eff multOutEff 

multInInPlaceEffFromInPlace,
 multOutInPlaceEffFromInPlace ::
    (RoundedMultiplyInPlace t) =>
    (MultEffortIndicator t) -> t -> t -> t
multInInPlaceEffFromInPlace = mutable2EffToPure multInInPlaceEff 
multOutInPlaceEffFromInPlace = mutable2EffToPure multOutInPlaceEff 

propInOutMultInPlace ::
    (RefOrd.PartialComparison t, 
     RoundedMultiplyInPlace t, 
     RoundedMultiply t, 
     Neg t,
     Show t, HasLegalValues t,
     Show (MultEffortIndicator t),
     EffortIndicator (MultEffortIndicator t),
     Show (RefOrd.PartialCompareEffortIndicator t),
     EffortIndicator (RefOrd.PartialCompareEffortIndicator t)
     ) =>
    t ->
    (RefOrd.PartialCompareEffortIndicator t, 
     MultEffortIndicator t) -> 
    (RefOrd.UniformlyOrderedPair t) -> Bool
propInOutMultInPlace sample initEffort (RefOrd.UniformlyOrderedPair (e1, e2)) =
    roundedInPlace2ConsistentWithPure "multiplication"
        multInInPlaceEff multOutInPlaceEff multInEff multOutEff
        RefOrd.pLeqEff initEffort
        e1 e2

powerToNonnegIntInInPlaceEffFromMult ::
    (RoundedMultiplyInPlace t, HasOne t) =>
    OpMutableNonmutEff (PowerToNonnegIntEffortIndicatorFromMult t) t Int s 
powerToNonnegIntInInPlaceEffFromMult effMult rM eM n =
    powerFromMultInPlace (multInInPlaceEff effMult) rM eM n

powerToNonnegIntOutInPlaceEffFromMult ::
    (RoundedMultiplyInPlace t, HasOne t) =>
    OpMutableNonmutEff (PowerToNonnegIntEffortIndicatorFromMult t) t Int s 
powerToNonnegIntOutInPlaceEffFromMult effMult rM eM n =
    powerFromMultInPlace (multOutInPlaceEff effMult) rM eM n


class (RoundedPowerToNonnegIntEffort t, CanBeMutable t) => 
    RoundedPowerToNonnegIntInPlace t 
    where
    powerToNonnegIntInInPlaceEff ::
        OpMutableNonmutEff (PowerToNonnegIntEffortIndicator t) t Int s
    powerToNonnegIntOutInPlaceEff ::
        OpMutableNonmutEff (PowerToNonnegIntEffortIndicator t) t Int s

powerToNonnegIntInInPlaceEffFromPure,
 powerToNonnegIntOutInPlaceEffFromPure ::
    (CanBeMutable t, RoundedPowerToNonnegInt t) =>
    OpMutableNonmutEff (PowerToNonnegIntEffortIndicator t) t Int s
powerToNonnegIntInInPlaceEffFromPure =
    pureToMutableNonmutEff powerToNonnegIntInEff 
powerToNonnegIntOutInPlaceEffFromPure =
    pureToMutableNonmutEff powerToNonnegIntOutEff 

powerToNonnegIntInInPlaceEffFromInPlace,
 powerToNonnegIntOutInPlaceEffFromInPlace ::
    (RoundedPowerToNonnegIntInPlace t) =>
    (PowerToNonnegIntEffortIndicator t) -> t -> Int -> t
powerToNonnegIntInInPlaceEffFromInPlace = 
    mutableNonmutEffToPure powerToNonnegIntInInPlaceEff 
powerToNonnegIntOutInPlaceEffFromInPlace = 
    mutableNonmutEffToPure powerToNonnegIntOutInPlaceEff

propInOutPowerToNonnegInPlace ::
    (RefOrd.PartialComparison t, 
     RoundedPowerToNonnegIntInPlace t, 
     RoundedPowerToNonnegInt t, 
     Neg t,
     Show t, HasLegalValues t,
     Show (PowerToNonnegIntEffortIndicator t),
     EffortIndicator (PowerToNonnegIntEffortIndicator t),
     Show (RefOrd.PartialCompareEffortIndicator t),
     EffortIndicator (RefOrd.PartialCompareEffortIndicator t)
     ) =>
    t ->
    (RefOrd.PartialCompareEffortIndicator t, 
     PowerToNonnegIntEffortIndicator t) -> 
    (RefOrd.UniformlyOrderedSingleton t) -> Int -> Bool
propInOutPowerToNonnegInPlace sample initEffort (RefOrd.UniformlyOrderedSingleton e) n =
    roundedInPlace1ConsistentWithPure "non-neg integer power"
        (\eff r e -> powerToNonnegIntInInPlaceEff eff r e n) 
        (\eff r e -> powerToNonnegIntOutInPlaceEff eff r e n) 
        (\eff e -> powerToNonnegIntInEff eff e n) 
        (\eff e -> powerToNonnegIntOutEff eff e n)
        RefOrd.pLeqEff initEffort
        e

class (HasOne t, RoundedDivideEffort t, CanBeMutable t) => RoundedDivideInPlace t where
    divInInPlaceEff :: OpMutable2Eff (DivEffortIndicator t) t s
    divOutInPlaceEff :: OpMutable2Eff (DivEffortIndicator t) t s
    recipInInPlaceEff :: OpMutable1Eff (DivEffortIndicator t) t s
    recipOutInPlaceEff :: OpMutable1Eff (DivEffortIndicator t) t s
    
    recipInInPlaceEff effort resM aM =
        do
        oneM <- unsafeMakeMutable one
        divInInPlaceEff effort resM oneM aM
    recipOutInPlaceEff effort resM aM =
        do
        oneM <- unsafeMakeMutable one
        divOutInPlaceEff effort resM oneM aM

divInInPlaceEffFromPure,
 divOutInPlaceEffFromPure ::
    (CanBeMutable t, RoundedDivide t) =>
    OpMutable2Eff (DivEffortIndicator t) t s
divInInPlaceEffFromPure = pureToMutable2Eff divInEff 
divOutInPlaceEffFromPure = pureToMutable2Eff divOutEff 

divInInPlaceEffFromInPlace,
 divOutInPlaceEffFromInPlace :: 
    (RoundedDivideInPlace t) =>
    (DivEffortIndicator t) -> t -> t -> t 
divInInPlaceEffFromInPlace = mutable2EffToPure divInInPlaceEff 
divOutInPlaceEffFromInPlace = mutable2EffToPure divOutInPlaceEff 

recipInInPlaceEffFromPure,
 recipOutInPlaceEffFromPure ::
    (CanBeMutable t, RoundedDivide t) =>
    OpMutable1Eff (DivEffortIndicator t) t s
recipInInPlaceEffFromPure = pureToMutable1Eff recipInEff 
recipOutInPlaceEffFromPure = pureToMutable1Eff recipOutEff 

recipInInPlaceEffFromInPlace,
 recipOutInPlaceEffFromInPlace ::
    (RoundedDivideInPlace t) =>
    (DivEffortIndicator t) -> t -> t
recipInInPlaceEffFromInPlace = mutable1EffToPure recipInInPlaceEff 
recipOutInPlaceEffFromInPlace = mutable1EffToPure recipOutInPlaceEff 

propInOutDivInPlace ::
    (RefOrd.PartialComparison t, 
     RoundedDivideInPlace t, 
     RoundedDivide t, 
     Neg t,
     Show t, HasZero t, HasLegalValues t,
     Show (DivEffortIndicator t),
     EffortIndicator (DivEffortIndicator t),
     Show (RefOrd.PartialCompareEffortIndicator t),
     EffortIndicator (RefOrd.PartialCompareEffortIndicator t)
     ) =>
    t ->
    (RefOrd.PartialCompareEffortIndicator t, 
     DivEffortIndicator t) -> 
    (RefOrd.UniformlyOrderedPair t) -> Bool
propInOutDivInPlace sample initEffort@(effComp, _) (RefOrd.UniformlyOrderedPair (e1, e2)) 
    =
    roundedInPlace2ConsistentWithPure "division"
        divInInPlaceEff divOutInPlaceEff divInEff divOutEff
        RefOrd.pLeqEff initEffort
        e1 e2

testsInOutFieldOpsInPlace (name, sample) =
    testGroup (name ++ " in-place up/down rounded ops match pure ops") $
        [
            testProperty "addition" (propInOutAddInPlace sample)
        ,
            testProperty "subtraction" (propInOutSubtrInPlace sample)
        ,
            testProperty "absolute value" (propInOutAbsInPlace sample)
        ,
            testProperty "multiplication" (propInOutMultInPlace sample)
        ,
            testProperty "integer power" (propInOutMultInPlace sample)
        ,
            testProperty "division" (propInOutDivInPlace sample)
        ]


class 
        (RoundedSubtrInPlace t, 
         RoundedMultiplyInPlace t, 
         RoundedRingEffort t) => 
    RoundedRingInPlace t

class
        (RoundedRingInPlace t,
         RoundedDivideInPlace t,
         RoundedFieldEffort t) => 
    RoundedFieldInPlace t