# Commits

committed 71059bb

Add different implementations for approximate equality.

• Participants
• Parent commits 21e8c10

# File Numeric/ApproxEq.hs

` -- Stability   : experimental`
` -- Portability : portable`
` --`
`--- Different implementations of approximate equalities of floating`
`--- point values.`
`+-- Different implementations of approximate equality for floating`
`+-- point values. There are multiple ways to implement approximate`
`+-- equality. They have different semantics and it's up to programmer`
`+-- to choose right one.`
` module Numeric.ApproxEq (`
`-    within`
`+    eqRelative`
`+  , eqRelCompl`
`+  , eqAbsolute`
`+  , within`
`   ) where`
` `
` import Control.Monad.ST         (runST)`
`+`
`+import Data.Complex             (Complex(..))`
` import Data.Primitive.ByteArray (newByteArray, readByteArray, writeByteArray)`
` import Data.Int                 (Int64)`
` `
`+`
`+`
`+-- | Relative difference between two numbers are less than predefined`
`+--   value.  For example 1 is approximately equal to 1.0001 with 1e-4`
`+--   precision. Same is true for 10000 and 10001.`
`+--`
`+--   This method of camparison doesn't work for numbers which are`
`+--   approximately 0. 'eqAbsolute' should be used instead.`
`+eqRelative :: (Fractional a, Ord a)`
`+           => a            -- ^ Relative precision`
`+           -> a -> a -> Bool`
`+eqRelative eps a b = abs (a - b) <= abs (eps * a)`
`+{-# INLINE eqRelative #-}`
`+`
`+-- | Relative equality for comlex numbers. `
`+eqRelCompl :: (RealFloat a, Ord a)`
`+           => a                 -- ^ Relative precision`
`+           -> Complex a -> Complex a -> Bool`
`+eqRelCompl eps a b = d <= eps * r`
`+  where`
`+    (d :+ _) = abs (a - b)`
`+    (r :+ _) = abs a`
`+{-# INLINE eqRelCompl #-}`
`+`
`+-- | Difference between values is less than specified precision.`
`+eqAbsolute :: (Num a, Ord a)`
`+           => a                 -- ^ Absolute precision`
`+           -> a -> a -> Bool`
`+eqAbsolute eps a b = abs (a - b) <= eps`
`+{-# INLINE eqAbsolute #-}`
`+`
`+`
` -- | Compare two 'Double' values for approximate equality, using`
` -- Dawson's method.`
` --`
`       bi | bi0 < 0   = big - bi0`
`          | otherwise = bi0`
`   return \$! abs (ai - bi) <= fromIntegral ulps`
`+`