hafar-0.1.0.0: src/Numeric/AffineForm/ExplicitRounding.hs
-- | ExplicitRounding defines the ExplicitRounding class and
-- instances for some more common numeric types
module Numeric.AffineForm.ExplicitRounding (
ExplicitRounding,
eps, prev, next,
(+/), (+\),
(-/), (-\),
(*/), (*\)
) where
import Numeric.Interval as IA
import Data.Ratio
-- | The class of numeric values that can be rounded explicitly
class (Ord a, Num a) => ExplicitRounding a where
-- | Return some number so that all the values that could be rounded to the parameter of this function
-- would be at most that distance away from that parameter.
eps :: a -> a
-- | Returns parameter plus its epsilon
prev :: a -> a
-- | Returns parameter minus its epsilon
next :: a -> a
-- | Add the two values, rounding the result up
(+/) :: a -> a -> a
-- | Add the two values, rounding the result down
(+\) :: a -> a -> a
-- | Subtract the two values, rounding the result up
(-/) :: a -> a -> a
-- | Subtract the two values, rounding the result down
(-\) :: a -> a -> a
-- | Multiply the two values, rounding the result up
(*/) :: a -> a -> a
-- | Multiply the two values, rounding the result down
(*\) :: a -> a -> a
prev x = x - eps x
next x = x + eps x
x +/ y = next $ x + y
x +\ y = prev $ x + y
x -/ y = next $ x - y
x -\ y = prev $ x - y
x */ y = next $ x * y
x *\ y = prev $ x * y
instance ExplicitRounding Int where
eps = const 0
instance (Integral a, ExplicitRounding a) => ExplicitRounding (Ratio a) where
eps x = (eps $ numerator x) % (abs (denominator x) - (eps $ denominator x))
instance ExplicitRounding Float where
eps 0 = eps $ 2e-36
eps x = encodeFloat 2 (snd $ decodeFloat x)
instance ExplicitRounding Double where
eps 0 = eps $ 1e-300
eps x = encodeFloat 2 (snd $ decodeFloat x)