module Numeric.MathFunctions.Comparison
(
relativeError
, eqRelErr
, addUlps
, ulpDistance
, ulpDelta
, within
) where
import Control.Monad.ST (runST)
import Data.Primitive.ByteArray (newByteArray, readByteArray, writeByteArray)
import Data.Word (Word64)
import Data.Int (Int64)
relativeError :: Double -> Double -> Double
relativeError :: Double -> Double -> Double
relativeError Double
a Double
b
| Double
a Double -> Double -> Bool
forall a. Eq a => a -> a -> Bool
== Double
0 Bool -> Bool -> Bool
&& Double
b Double -> Double -> Bool
forall a. Eq a => a -> a -> Bool
== Double
0 = Double
0
| Bool
otherwise = Double -> Double
forall a. Num a => a -> a
abs (Double
a Double -> Double -> Double
forall a. Num a => a -> a -> a
- Double
b) Double -> Double -> Double
forall a. Fractional a => a -> a -> a
/ Double -> Double -> Double
forall a. Ord a => a -> a -> a
max (Double -> Double
forall a. Num a => a -> a
abs Double
a) (Double -> Double
forall a. Num a => a -> a
abs Double
b)
eqRelErr :: Double
-> Double
-> Double
-> Bool
eqRelErr :: Double -> Double -> Double -> Bool
eqRelErr Double
eps Double
a Double
b = Double -> Double -> Double
relativeError Double
a Double
b Double -> Double -> Bool
forall a. Ord a => a -> a -> Bool
< Double
eps
addUlps :: Int -> Double -> Double
addUlps :: Int -> Double -> Double
addUlps Int
n Double
a = (forall s. ST s Double) -> Double
forall a. (forall s. ST s a) -> a
runST ((forall s. ST s Double) -> Double)
-> (forall s. ST s Double) -> Double
forall a b. (a -> b) -> a -> b
$ do
MutableByteArray s
buf <- Int -> ST s (MutableByteArray (PrimState (ST s)))
forall (m :: * -> *).
PrimMonad m =>
Int -> m (MutableByteArray (PrimState m))
newByteArray Int
8
Word64
ai0 <- MutableByteArray (PrimState (ST s)) -> Int -> Double -> ST s ()
forall a (m :: * -> *).
(Prim a, PrimMonad m) =>
MutableByteArray (PrimState m) -> Int -> a -> m ()
writeByteArray MutableByteArray s
MutableByteArray (PrimState (ST s))
buf Int
0 Double
a ST s () -> ST s Word64 -> ST s Word64
forall (m :: * -> *) a b. Monad m => m a -> m b -> m b
>> MutableByteArray (PrimState (ST s)) -> Int -> ST s Word64
forall a (m :: * -> *).
(Prim a, PrimMonad m) =>
MutableByteArray (PrimState m) -> Int -> m a
readByteArray MutableByteArray s
MutableByteArray (PrimState (ST s))
buf Int
0
let big :: Word64
big = Word64
0x8000000000000000
order :: Word64 -> Int64
order :: Word64 -> Int64
order Word64
i | Word64
i Word64 -> Word64 -> Bool
forall a. Ord a => a -> a -> Bool
< Word64
big = Word64 -> Int64
forall a b. (Integral a, Num b) => a -> b
fromIntegral Word64
i
| Bool
otherwise = Word64 -> Int64
forall a b. (Integral a, Num b) => a -> b
fromIntegral (Word64 -> Int64) -> Word64 -> Int64
forall a b. (a -> b) -> a -> b
$ Word64
forall a. Bounded a => a
maxBound Word64 -> Word64 -> Word64
forall a. Num a => a -> a -> a
- (Word64
i Word64 -> Word64 -> Word64
forall a. Num a => a -> a -> a
- Word64
big)
unorder :: Int64 -> Word64
unorder :: Int64 -> Word64
unorder Int64
i | Int64
i Int64 -> Int64 -> Bool
forall a. Ord a => a -> a -> Bool
>= Int64
0 = Int64 -> Word64
forall a b. (Integral a, Num b) => a -> b
fromIntegral Int64
i
| Bool
otherwise = Word64
big Word64 -> Word64 -> Word64
forall a. Num a => a -> a -> a
+ (Word64
forall a. Bounded a => a
maxBound Word64 -> Word64 -> Word64
forall a. Num a => a -> a -> a
- (Int64 -> Word64
forall a b. (Integral a, Num b) => a -> b
fromIntegral Int64
i))
let ai0' :: Word64
ai0' = Int64 -> Word64
unorder (Int64 -> Word64) -> Int64 -> Word64
forall a b. (a -> b) -> a -> b
$ Word64 -> Int64
order Word64
ai0 Int64 -> Int64 -> Int64
forall a. Num a => a -> a -> a
+ Int -> Int64
forall a b. (Integral a, Num b) => a -> b
fromIntegral Int
n
MutableByteArray (PrimState (ST s)) -> Int -> Word64 -> ST s ()
forall a (m :: * -> *).
(Prim a, PrimMonad m) =>
MutableByteArray (PrimState m) -> Int -> a -> m ()
writeByteArray MutableByteArray s
MutableByteArray (PrimState (ST s))
buf Int
0 Word64
ai0' ST s () -> ST s Double -> ST s Double
forall (m :: * -> *) a b. Monad m => m a -> m b -> m b
>> MutableByteArray (PrimState (ST s)) -> Int -> ST s Double
forall a (m :: * -> *).
(Prim a, PrimMonad m) =>
MutableByteArray (PrimState m) -> Int -> m a
readByteArray MutableByteArray s
MutableByteArray (PrimState (ST s))
buf Int
0
ulpDistance :: Double
-> Double
-> Word64
ulpDistance :: Double -> Double -> Word64
ulpDistance Double
a Double
b = (forall s. ST s Word64) -> Word64
forall a. (forall s. ST s a) -> a
runST ((forall s. ST s Word64) -> Word64)
-> (forall s. ST s Word64) -> Word64
forall a b. (a -> b) -> a -> b
$ do
MutableByteArray s
buf <- Int -> ST s (MutableByteArray (PrimState (ST s)))
forall (m :: * -> *).
PrimMonad m =>
Int -> m (MutableByteArray (PrimState m))
newByteArray Int
8
Word64
ai0 <- MutableByteArray (PrimState (ST s)) -> Int -> Double -> ST s ()
forall a (m :: * -> *).
(Prim a, PrimMonad m) =>
MutableByteArray (PrimState m) -> Int -> a -> m ()
writeByteArray MutableByteArray s
MutableByteArray (PrimState (ST s))
buf Int
0 Double
a ST s () -> ST s Word64 -> ST s Word64
forall (m :: * -> *) a b. Monad m => m a -> m b -> m b
>> MutableByteArray (PrimState (ST s)) -> Int -> ST s Word64
forall a (m :: * -> *).
(Prim a, PrimMonad m) =>
MutableByteArray (PrimState m) -> Int -> m a
readByteArray MutableByteArray s
MutableByteArray (PrimState (ST s))
buf Int
0
Word64
bi0 <- MutableByteArray (PrimState (ST s)) -> Int -> Double -> ST s ()
forall a (m :: * -> *).
(Prim a, PrimMonad m) =>
MutableByteArray (PrimState m) -> Int -> a -> m ()
writeByteArray MutableByteArray s
MutableByteArray (PrimState (ST s))
buf Int
0 Double
b ST s () -> ST s Word64 -> ST s Word64
forall (m :: * -> *) a b. Monad m => m a -> m b -> m b
>> MutableByteArray (PrimState (ST s)) -> Int -> ST s Word64
forall a (m :: * -> *).
(Prim a, PrimMonad m) =>
MutableByteArray (PrimState m) -> Int -> m a
readByteArray MutableByteArray s
MutableByteArray (PrimState (ST s))
buf Int
0
let big :: Word64
big = Word64
0x8000000000000000
order :: Word64 -> Word64
order Word64
i | Word64
i Word64 -> Word64 -> Bool
forall a. Ord a => a -> a -> Bool
< Word64
big = Word64
i Word64 -> Word64 -> Word64
forall a. Num a => a -> a -> a
+ Word64
big
| Bool
otherwise = Word64
forall a. Bounded a => a
maxBound Word64 -> Word64 -> Word64
forall a. Num a => a -> a -> a
- Word64
i
ai :: Word64
ai = Word64 -> Word64
order Word64
ai0
bi :: Word64
bi = Word64 -> Word64
order Word64
bi0
d :: Word64
d | Word64
ai Word64 -> Word64 -> Bool
forall a. Ord a => a -> a -> Bool
> Word64
bi = Word64
ai Word64 -> Word64 -> Word64
forall a. Num a => a -> a -> a
- Word64
bi
| Bool
otherwise = Word64
bi Word64 -> Word64 -> Word64
forall a. Num a => a -> a -> a
- Word64
ai
Word64 -> ST s Word64
forall (m :: * -> *) a. Monad m => a -> m a
return (Word64 -> ST s Word64) -> Word64 -> ST s Word64
forall a b. (a -> b) -> a -> b
$! Word64
d
ulpDelta :: Double
-> Double
-> Int64
ulpDelta :: Double -> Double -> Int64
ulpDelta Double
a Double
b = (forall s. ST s Int64) -> Int64
forall a. (forall s. ST s a) -> a
runST ((forall s. ST s Int64) -> Int64)
-> (forall s. ST s Int64) -> Int64
forall a b. (a -> b) -> a -> b
$ do
MutableByteArray s
buf <- Int -> ST s (MutableByteArray (PrimState (ST s)))
forall (m :: * -> *).
PrimMonad m =>
Int -> m (MutableByteArray (PrimState m))
newByteArray Int
8
Word64
ai0 <- MutableByteArray (PrimState (ST s)) -> Int -> Double -> ST s ()
forall a (m :: * -> *).
(Prim a, PrimMonad m) =>
MutableByteArray (PrimState m) -> Int -> a -> m ()
writeByteArray MutableByteArray s
MutableByteArray (PrimState (ST s))
buf Int
0 Double
a ST s () -> ST s Word64 -> ST s Word64
forall (m :: * -> *) a b. Monad m => m a -> m b -> m b
>> MutableByteArray (PrimState (ST s)) -> Int -> ST s Word64
forall a (m :: * -> *).
(Prim a, PrimMonad m) =>
MutableByteArray (PrimState m) -> Int -> m a
readByteArray MutableByteArray s
MutableByteArray (PrimState (ST s))
buf Int
0
Word64
bi0 <- MutableByteArray (PrimState (ST s)) -> Int -> Double -> ST s ()
forall a (m :: * -> *).
(Prim a, PrimMonad m) =>
MutableByteArray (PrimState m) -> Int -> a -> m ()
writeByteArray MutableByteArray s
MutableByteArray (PrimState (ST s))
buf Int
0 Double
b ST s () -> ST s Word64 -> ST s Word64
forall (m :: * -> *) a b. Monad m => m a -> m b -> m b
>> MutableByteArray (PrimState (ST s)) -> Int -> ST s Word64
forall a (m :: * -> *).
(Prim a, PrimMonad m) =>
MutableByteArray (PrimState m) -> Int -> m a
readByteArray MutableByteArray s
MutableByteArray (PrimState (ST s))
buf Int
0
let big :: Word64
big = Word64
0x8000000000000000 :: Word64
order :: Word64 -> Word64
order Word64
i | Word64
i Word64 -> Word64 -> Bool
forall a. Ord a => a -> a -> Bool
< Word64
big = Word64
i Word64 -> Word64 -> Word64
forall a. Num a => a -> a -> a
+ Word64
big
| Bool
otherwise = Word64
forall a. Bounded a => a
maxBound Word64 -> Word64 -> Word64
forall a. Num a => a -> a -> a
- Word64
i
ai :: Word64
ai = Word64 -> Word64
order Word64
ai0
bi :: Word64
bi = Word64 -> Word64
order Word64
bi0
Int64 -> ST s Int64
forall (m :: * -> *) a. Monad m => a -> m a
return (Int64 -> ST s Int64) -> Int64 -> ST s Int64
forall a b. (a -> b) -> a -> b
$! Word64 -> Int64
forall a b. (Integral a, Num b) => a -> b
fromIntegral (Word64 -> Int64) -> Word64 -> Int64
forall a b. (a -> b) -> a -> b
$ Word64
bi Word64 -> Word64 -> Word64
forall a. Num a => a -> a -> a
- Word64
ai
within :: Int
-> Double -> Double -> Bool
within :: Int -> Double -> Double -> Bool
within Int
ulps Double
a Double
b
| Int
ulps Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
< Int
0 = Bool
False
| Bool
otherwise = Double -> Double -> Word64
ulpDistance Double
a Double
b Word64 -> Word64 -> Bool
forall a. Ord a => a -> a -> Bool
<= Int -> Word64
forall a b. (Integral a, Num b) => a -> b
fromIntegral Int
ulps