-- | 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)