AERN-Real-Double-2011.1: src/Numeric/AERN/RealArithmetic/Basis/Double/FieldOps.hs
{-# LANGUAGE TypeFamilies #-}
{-# LANGUAGE UndecidableInstances #-}
{-|
Module : Numeric.AERN.RealArithmetic.Basis.Double.FieldOps
Description : rounded arithmetic instances for Double
Copyright : (c) Michal Konecny
License : BSD3
Maintainer : mikkonecny@gmail.com
Stability : experimental
Portability : portable
Rounded arithmetic instances for Double.
This is a private module reexported publicly via its parent.
-}
module Numeric.AERN.RealArithmetic.Basis.Double.FieldOps
(setMachineRoundingModeUp)
where
import Numeric.AERN.RealArithmetic.Basis.Double.NumericOrder
import Numeric.AERN.RealArithmetic.NumericOrderRounding
import Numeric.AERN.Basics.Effort
import Numeric.IEEE.RoundMode
import System.IO.Unsafe
import Numeric.AERN.Basics.Exception
import Control.Exception
withUpwardsRounding :: a -> a
withUpwardsRounding a =
unsafePerformIO $
do
setMachineRoundingModeUp
aa <- return $! a
return aa
setMachineRoundingModeUp :: IO ()
setMachineRoundingModeUp =
do
currentRndMode <- getRound
case currentRndMode == Upward of
True ->
do
-- putStrLn "setMachineRoundingModeUp: already up"
return ()
False ->
do
success <- setRound Upward
case success of
True ->
do
-- putStrLn $ "setMachineRoundingModeUp: switching up from " ++ show currentRndMode
return ()
False ->
error "Numeric.AERN.RealArithmetic.Basics.Double: failed to switch rounding mode"
detectNaNThrow :: String -> Double -> Double
detectNaNThrow msg a
| isNaN a =
throw (AERNDomViolationException $ "domain violation in " ++ msg)
| otherwise = a
detectNaNUp :: String -> Double -> Double
detectNaNUp _ a
| isNaN a = 1/0
| otherwise = a
detectNaNDn :: String -> Double -> Double
detectNaNDn _ a
| isNaN a = -1/0
| otherwise = a
instance RoundedAddEffort Double where
type AddEffortIndicator Double = ()
addDefaultEffort _ = ()
instance RoundedAdd Double where
addUpEff effort d1 d2 =
detectNaNUp ("addition " ++ show d1 ++ " +^ " ++ show d2 ) $
withUpwardsRounding $ d1 + d2
addDnEff effort d1 d2 =
detectNaNDn ("addition " ++ show d1 ++ " +. " ++ show d2 ) $
negate $ withUpwardsRounding $ (negate d1) + (negate d2)
-- the following is an exagerated rounding version meant for testing:
-- type AddEffortIndicator Double = Int1To100
-- addDefaultEffort _ = Int1To100 10
-- addUpEff effort d1 d2 =
-- withUpwardsRounding $
-- d1 + d2 + (1/effortD)
-- where
-- effortD = fromInteger $ toInteger $ fromInt1To100 $ effort
-- addDnEff effort d1 d2 =
-- negate $ withUpwardsRounding $
-- (negate d1) + (negate d2) + (1/effortD)
-- where
-- effortD = fromInteger $ toInteger $ fromInt1To100 $ effort
instance RoundedSubtr Double
instance RoundedAbsEffort Double where
type AbsEffortIndicator Double = ()
absDefaultEffort _ = ()
instance RoundedAbs Double where
absDnEff _ = abs
absUpEff _ = abs
instance RoundedMultiplyEffort Double where
type MultEffortIndicator Double = ()
multDefaultEffort _ = ()
instance RoundedMultiply Double where
multUpEff effort d1 d2 =
detectNaNUp ("multiplication " ++ show d1 ++ " *^ " ++ show d2 ) $
withUpwardsRounding $ d1 * d2
multDnEff effort d1 d2 =
detectNaNDn ("multiplication " ++ show d1 ++ " *. " ++ show d2 ) $
negate $ withUpwardsRounding $ (negate d1) * d2
-- the following is an exagerated rounding version meant for testing:
-- type MultEffortIndicator Double = Int1To100
-- multDefaultEffort _ = Int1To100 10
-- multUpEff effort d1 d2 =
-- withUpwardsRounding $
-- d1 * d2 + (1/effortD)
-- where
-- effortD = fromInteger $ toInteger $ fromInt1To100 $ effort
-- multDnEff effort d1 d2 =
-- negate $ withUpwardsRounding $
-- (negate d1) * d2 + (1/effortD)
-- where
-- effortD = fromInteger $ toInteger $ fromInt1To100 $ effort
instance RoundedPowerNonnegToNonnegIntEffort Double where
type PowerNonnegToNonnegIntEffortIndicator Double =
PowerNonnegToNonnegIntEffortIndicatorFromMult Double
powerNonnegToNonnegIntDefaultEffort =
powerNonnegToNonnegIntDefaultEffortFromMult
instance RoundedPowerNonnegToNonnegInt Double where
powerNonnegToNonnegIntUpEff =
powerNonnegToNonnegIntUpEffFromMult
powerNonnegToNonnegIntDnEff =
powerNonnegToNonnegIntDnEffFromMult
instance RoundedPowerToNonnegIntEffort Double where
type PowerToNonnegIntEffortIndicator Double =
PowerToNonnegIntEffortIndicatorFromMult Double
powerToNonnegIntDefaultEffort =
powerToNonnegIntDefaultEffortFromMult
instance RoundedPowerToNonnegInt Double where
powerToNonnegIntUpEff =
powerToNonnegIntUpEffFromMult
powerToNonnegIntDnEff =
powerToNonnegIntDnEffFromMult
instance RoundedDivideEffort Double where
type DivEffortIndicator Double = ()
divDefaultEffort _ = ()
instance RoundedDivide Double where
divUpEff effort d1 d2 =
detectNaNUp ("division " ++ show d1 ++ " /^ " ++ show d2 ) $
withUpwardsRounding $ d1 / d2
divDnEff effort d1 d2 =
detectNaNDn ("division " ++ show d1 ++ " /. " ++ show d2 ) $
negate $ withUpwardsRounding $ (negate d1) / d2
instance RoundedRingEffort Double
where
type RingOpsEffortIndicator Double = ()
ringOpsDefaultEffort _ = ()
ringEffortAdd _ _ = ()
ringEffortMult _ _ = ()
ringEffortPow _ _ = ()
instance RoundedRing Double
instance RoundedFieldEffort Double
where
type FieldOpsEffortIndicator Double = ()
fieldOpsDefaultEffort _ = ()
fldEffortAdd _ _ = ()
fldEffortMult _ _ = ()
fldEffortPow _ _ = ()
fldEffortDiv _ _ = ()
instance RoundedField Double
--test1 :: [Double]
--test1 =
-- let ?multUpDnEffort = () :: MultEffortIndicator Double in
-- let up = foldl1 (*^) [1/3,1/3,1/3]
-- dn = foldl1 (*.) [1/3,1/3,1/3]
-- in
-- [up, dn]