packages feed

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

{-# LANGUAGE TypeFamilies #-}
{-# LANGUAGE MultiParamTypeClasses #-}
{-# LANGUAGE ImplicitParams #-}
{-|
    Module      :  Numeric.AERN.RealArithmetic.NumericOrderRounding.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 NumericOrderRounding. 
-}
module Numeric.AERN.RealArithmetic.NumericOrderRounding.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.NumericOrder as NumOrd
import Numeric.AERN.Basics.NumericOrder.OpsImplicitEffort

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 
    convertUpEff :: ConvertEffortIndicator t1 t2 -> t1 -> Maybe t2
    convertDnEff :: ConvertEffortIndicator t1 t2 -> t1 -> Maybe t2

propConvertMonotone ::
    (Convertible t1 t2, 
     NumOrd.ArbitraryOrderedTuple t1, 
     NumOrd.PartialComparison t2) =>
    t1 -> t2 ->
    (ConvertEffortIndicator t1 t2,
     NumOrd.PartialCompareEffortIndicator t2) ->  
    NumOrd.LEPair t1 -> Bool
propConvertMonotone sample1 sample2 (effortConvert, effortComp2) (NumOrd.LEPair (a1, a2)) =
    (defined ma1Dn && defined ma2Up) ===>
    (trueOrNothing $ 
        let ?pCompareEffort = effortComp2 in
        a1Dn <=? a2Up)
    where
    ma1Dn = convertDnEff effortConvert a1 
    ma2Up = convertUpEff effortConvert a2
    a1Dn = fromJust ma1Dn
    a2Up = fromJust ma2Up
    _ = [sample2, a1Dn, a2Up]
    
propConvertRoundTrip ::
    (Convertible t1 t2, Convertible t2 t1, NumOrd.PartialComparison t1) =>
    t1 -> t2 -> 
    (NumOrd.PartialCompareEffortIndicator t1, 
     ConvertEffortIndicator t2 t1, 
     ConvertEffortIndicator t1 t2) ->
    t1 -> Bool
propConvertRoundTrip _ sample2 (effortComp, effortFrom2, effortTo2) a =
    (defined maDn2 && defined maDn && defined maUp2 && defined maUp) ===>
    let ?pCompareEffort = effortComp in
    case (aDn <=? a, a <=? aUp) of
       (Just False, _) -> False
       (_, Just False) -> False
       _ -> True
    where
    maDn = convertDnEff effortFrom2 aDn2
    aDn = fromJust maDn 
    maDn2 = convertDnEff effortTo2 a
    aDn2 = fromJust maDn2 
    maUp = convertUpEff effortFrom2 aUp2
    aUp = fromJust maUp 
    maUp2 = convertUpEff effortTo2 a
    aUp2 = fromJust maUp2
    _ = [sample2, aUp2, aDn2] 
    
testsConvert (name1, sample1, name2, sample2) =
    testGroup (name1 ++ " -> " ++ name2 ++  " conversions") $
        [
            testProperty "monotone" (propConvertMonotone sample1 sample2)
        ,
            testProperty "round trip" (propConvertRoundTrip sample1 sample2)
        ]