packages feed

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

{-# LANGUAGE TypeFamilies #-}
{-# LANGUAGE MultiParamTypeClasses #-}
{-# LANGUAGE ImplicitParams #-}
{-|
    Module      :  Numeric.AERN.RealArithmetic.RefinementOrderRounding.Conversion
    Description :  conversion between approximations and other types  
    Copyright   :  (c) Michal Konecny
    License     :  BSD3

    Maintainer  :  mikkonecny@gmail.com
    Stability   :  experimental
    Portability :  portable
    
    Conversion between approximations and other types.
    
    This module is hidden and reexported via its parent RefinementOrderRounding. 
-}
module Numeric.AERN.RealArithmetic.RefinementOrderRounding.Conversion where

import Prelude hiding (EQ, LT, GT)

import Numeric.AERN.RealArithmetic.ExactOps

import Numeric.AERN.Basics.Effort
import Numeric.AERN.Basics.PartialOrdering
import qualified Numeric.AERN.Basics.RefinementOrder as RefOrd
import qualified Numeric.AERN.Basics.NumericOrder as NumOrd
import Numeric.AERN.Basics.NumericOrder.OpsImplicitEffort

import qualified Numeric.AERN.RealArithmetic.NumericOrderRounding.Conversion as UpDnConversion

import Numeric.AERN.Misc.Bool
import Numeric.AERN.Misc.Maybe

import Data.Ratio
import Data.Maybe

import Test.QuickCheck
import Test.Framework (testGroup, Test)
import Test.Framework.Providers.QuickCheck2 (testProperty)

class Convertible t1 t2 where
    type ConvertEffortIndicator t1 t2
    convertDefaultEffort :: t1 -> t2 -> ConvertEffortIndicator t1 t2 
    convertInEff :: ConvertEffortIndicator t1 t2 -> t1 -> t2
    convertOutEff :: ConvertEffortIndicator t1 t2 -> t1 -> t2

propConvertMonotoneFromNumOrd ::
    (Convertible t1 t2, NumOrd.ArbitraryOrderedTuple t1, NumOrd.PartialComparison t2) =>
    t1 -> t2 ->
    (ConvertEffortIndicator t1 t2, NumOrd.PartialCompareEffortIndicator t2) ->  
    NumOrd.LEPair t1 -> Bool
propConvertMonotoneFromNumOrd sample1 sample2 (effortFrom, effortComp) (NumOrd.LEPair (a, b)) = 
    (trueOrNothing $ let ?pCompareEffort = effortComp in aOut <=? bOut)
    &&
    (trueOrNothing $ let ?pCompareEffort = effortComp in aIn <=? bIn)
    where
    aOut = convertOutEff effortFrom a 
    aIn = convertInEff effortFrom a 
    bOut = convertOutEff effortFrom b 
    bIn = convertInEff effortFrom b
    _ = [sample2, aOut, aIn]

propConvertRoundTripNumOrd ::
    (UpDnConversion.Convertible t1 t2, Convertible t2 t1, 
     NumOrd.PartialComparison t1, Show t1, Show t2) =>
    t1 -> t2 -> 
    (NumOrd.PartialCompareEffortIndicator t1, 
     ConvertEffortIndicator t2 t1, 
     UpDnConversion.ConvertEffortIndicator t1 t2) ->
    t1 -> Bool
propConvertRoundTripNumOrd sample1 sample2 (effortComp, effortFrom, effortTo) a =
    (defined maDn && defined maUp) ===>
    let ?pCompareEffort = effortComp in
    case (aDnOut <=? a, a <=? aUpOut) of
       (Just False, _) -> printErrorDetail
       (_, Just False) -> printErrorDetail
       _ -> True
    where
    aDnOut = convertOutEff effortFrom aDn 
    maDn = UpDnConversion.convertDnEff effortTo a
    aDn = fromJust maDn 
    aUpOut = convertOutEff effortFrom aUp
    maUp = UpDnConversion.convertUpEff effortTo a
    aUp = fromJust maUp 
    _ = [sample2, aDn, aUp]
    printErrorDetail =
        error $
           "propToFromInteger failed:"
           ++ "\n  a = " ++ show a
           ++ "\n  aDnOut = " ++ show aDnOut
           ++ "\n  aUpOut = " ++ show aUpOut


testsConvertNumOrd (name1, sample1, name2, sample2) =
    testGroup (name1 ++ " -> " ++ name2 ++  " conversions") $
        [
            testProperty "monotone" (propConvertMonotoneFromNumOrd sample1 sample2)
        ,
            testProperty "round trip" (propConvertRoundTripNumOrd sample2 sample1)
        ]