{-# LANGUAGE Strict #-}
module Data.Approx
(
Approx (..)
) where
import Data.List (foldl')
import qualified Data.Vector.Unboxed as U
import qualified Data.Vector.Unboxed.Mutable as M
import qualified Data.Vector as V
import Data.Time (Day, UTCTime)
import Data.Time.Clock (diffUTCTime)
import qualified Data.HashMap.Strict as Hm
import Data.Hashable
import Data.Text (Text)
import qualified Data.Complex as Cx
import Data.Complex (Complex ( (:+) ) )
epsZeroDouble :: Double
epsZeroDouble :: Double
epsZeroDouble = Double
1e-8; {-# INLINE epsZeroDouble #-}
epsEqDouble :: Double
epsEqDouble :: Double
epsEqDouble = Double
1e-7; {-# INLINE epsEqDouble #-}
epsZeroFloat :: Float
epsZeroFloat :: Float
epsZeroFloat = Float
1e-6; {-# INLINE epsZeroFloat #-}
epsEqFloat :: Float
epsEqFloat :: Float
epsEqFloat = Float
1e-5; {-# INLINE epsEqFloat #-}
infix 4 =~, /~
class Approx a where
(=~), (/~) :: a -> a -> Bool
(=~) a
x a
y = Bool -> Bool
not (a
x a -> a -> Bool
forall a. Approx a => a -> a -> Bool
/~ a
y)
{-# INLINE (=~) #-}
(/~) a
x a
y = Bool -> Bool
not (a
x a -> a -> Bool
forall a. Approx a => a -> a -> Bool
=~ a
y)
{-# INLINE (/~) #-}
{-# MINIMAL (=~) | (/~) #-}
instance Approx Day where Day
x =~ :: Day -> Day -> Bool
=~ Day
y = Day
x Day -> Day -> Bool
forall a. Eq a => a -> a -> Bool
== Day
y; {-# INLINE (=~) #-}
instance Approx Char where Char
x =~ :: Char -> Char -> Bool
=~ Char
y = Char
x Char -> Char -> Bool
forall a. Eq a => a -> a -> Bool
== Char
y; {-# INLINE (=~) #-}
instance Approx Bool where Bool
x =~ :: Bool -> Bool -> Bool
=~ Bool
y = Bool
x Bool -> Bool -> Bool
forall a. Eq a => a -> a -> Bool
== Bool
y; {-# INLINE (=~) #-}
instance Approx Text where Text
x =~ :: Text -> Text -> Bool
=~ Text
y = Text
x Text -> Text -> Bool
forall a. Eq a => a -> a -> Bool
== Text
y; {-# INLINE (=~) #-}
instance Approx Int where Int
x =~ :: Int -> Int -> Bool
=~ Int
y = Int
x Int -> Int -> Bool
forall a. Eq a => a -> a -> Bool
== Int
y; {-# INLINE (=~) #-}
instance Approx Integer where Integer
x =~ :: Integer -> Integer -> Bool
=~ Integer
y = Integer
x Integer -> Integer -> Bool
forall a. Eq a => a -> a -> Bool
== Integer
y; {-# INLINE (=~) #-}
instance Approx UTCTime where
UTCTime
x =~ :: UTCTime -> UTCTime -> Bool
=~ UTCTime
y = (Double -> Integer
forall a b. (RealFrac a, Integral b) => a -> b
round (Double -> Integer)
-> (NominalDiffTime -> Double) -> NominalDiffTime -> Integer
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (Double -> Double -> Double
forall a. Fractional a => a -> a -> a
/Double
60.0) (Double -> Double)
-> (NominalDiffTime -> Double) -> NominalDiffTime -> Double
forall b c a. (b -> c) -> (a -> b) -> a -> c
. NominalDiffTime -> Double
forall a b. (Real a, Fractional b) => a -> b
realToFrac (NominalDiffTime -> Integer) -> NominalDiffTime -> Integer
forall a b. (a -> b) -> a -> b
$ UTCTime
x UTCTime -> UTCTime -> NominalDiffTime
`diffUTCTime` UTCTime
y) Integer -> Integer -> Bool
forall a. Eq a => a -> a -> Bool
== Integer
0
{-# INLINE (=~) #-}
instance Approx a => Approx (Cx.Complex a) where
(a
a :+ a
b) =~ :: Complex a -> Complex a -> Bool
=~ (a
x :+ a
y) = (a
a a -> a -> Bool
forall a. Approx a => a -> a -> Bool
=~ a
x) Bool -> Bool -> Bool
&& (a
b a -> a -> Bool
forall a. Approx a => a -> a -> Bool
=~ a
y); {-# INLINE (=~) #-}
instance Approx Float where
Float
x =~ :: Float -> Float -> Bool
=~ Float
y = if (Float
mx Float -> Float -> Bool
forall a. Ord a => a -> a -> Bool
< Float
epsZeroFloat) Bool -> Bool -> Bool
|| (Float -> Float
forall a. Num a => a -> a
abs (Float
xFloat -> Float -> Float
forall a. Num a => a -> a -> a
-Float
y)) Float -> Float -> Float
forall a. Fractional a => a -> a -> a
/ Float
mx Float -> Float -> Bool
forall a. Ord a => a -> a -> Bool
< Float
epsEqFloat then Bool
True else Bool
False
where mx :: Float
mx = (Float -> Float -> Float
forall a. Ord a => a -> a -> a
max (Float -> Float
forall a. Num a => a -> a
abs Float
x) (Float -> Float
forall a. Num a => a -> a
abs Float
y))
{-# INLINE (=~) #-}
instance Approx Double where
Double
x =~ :: Double -> Double -> Bool
=~ Double
y = if (Double
mx Double -> Double -> Bool
forall a. Ord a => a -> a -> Bool
< Double
epsZeroDouble) Bool -> Bool -> Bool
|| (Double -> Double
forall a. Num a => a -> a
abs (Double
xDouble -> Double -> Double
forall a. Num a => a -> a -> a
-Double
y)) Double -> Double -> Double
forall a. Fractional a => a -> a -> a
/ Double
mx Double -> Double -> Bool
forall a. Ord a => a -> a -> Bool
< Double
epsEqDouble then Bool
True else Bool
False
where mx :: Double
mx = (Double -> Double -> Double
forall a. Ord a => a -> a -> a
max (Double -> Double
forall a. Num a => a -> a
abs Double
x) (Double -> Double
forall a. Num a => a -> a
abs Double
y))
{-# INLINE (=~) #-}
instance Approx a => Approx (Maybe a) where
Maybe a
Nothing =~ :: Maybe a -> Maybe a -> Bool
=~ Maybe a
Nothing = Bool
True
Just a
x =~ Just a
y = a
x a -> a -> Bool
forall a. Approx a => a -> a -> Bool
=~ a
y
Maybe a
_ =~ Maybe a
_ = Bool
False
{-# INLINE (=~) #-}
instance Approx a => Approx [a] where
[a]
x =~ :: [a] -> [a] -> Bool
=~ [a]
y = ([a] -> Int
forall (t :: * -> *) a. Foldable t => t a -> Int
length [a]
x Int -> Int -> Bool
forall a. Eq a => a -> a -> Bool
== [a] -> Int
forall (t :: * -> *) a. Foldable t => t a -> Int
length [a]
y) Bool -> Bool -> Bool
&& ((Bool -> Bool -> Bool) -> Bool -> [Bool] -> Bool
forall (t :: * -> *) a b.
Foldable t =>
(a -> b -> b) -> b -> t a -> b
foldr Bool -> Bool -> Bool
(&&) Bool
True ([Bool] -> Bool) -> [Bool] -> Bool
forall a b. (a -> b) -> a -> b
$ (a -> a -> Bool) -> [a] -> [a] -> [Bool]
forall a b c. (a -> b -> c) -> [a] -> [b] -> [c]
zipWith a -> a -> Bool
forall a. Approx a => a -> a -> Bool
(=~) [a]
x [a]
y)
instance (Approx a, Approx b) => Approx (a, b) where
(a
x,b
y) =~ :: (a, b) -> (a, b) -> Bool
=~ (a
a,b
b) =
( (a
x a -> a -> Bool
forall a. Approx a => a -> a -> Bool
=~ a
a)
Bool -> Bool -> Bool
&& (b
y b -> b -> Bool
forall a. Approx a => a -> a -> Bool
=~ b
b)
)
{-# INLINE (=~) #-}
instance (Approx a, Approx b, Approx c) => Approx (a, b, c) where
(a
x,b
y,c
z) =~ :: (a, b, c) -> (a, b, c) -> Bool
=~ (a
a,b
b,c
c) =
( (a
x a -> a -> Bool
forall a. Approx a => a -> a -> Bool
=~ a
a)
Bool -> Bool -> Bool
&& (b
y b -> b -> Bool
forall a. Approx a => a -> a -> Bool
=~ b
b)
Bool -> Bool -> Bool
&& (c
z c -> c -> Bool
forall a. Approx a => a -> a -> Bool
=~ c
c)
)
{-# INLINE (=~) #-}
instance (Approx a,Approx b,Approx c,Approx d) => Approx (a,b,c,d) where
(a
x,b
y,c
z,d
u) =~ :: (a, b, c, d) -> (a, b, c, d) -> Bool
=~ (a
a,b
b,c
c,d
d) =
( (a
x a -> a -> Bool
forall a. Approx a => a -> a -> Bool
=~ a
a)
Bool -> Bool -> Bool
&& (b
y b -> b -> Bool
forall a. Approx a => a -> a -> Bool
=~ b
b)
Bool -> Bool -> Bool
&& (c
z c -> c -> Bool
forall a. Approx a => a -> a -> Bool
=~ c
c)
Bool -> Bool -> Bool
&& (d
u d -> d -> Bool
forall a. Approx a => a -> a -> Bool
=~ d
d)
)
{-# INLINE (=~) #-}
instance (Approx a,Approx b,Approx c,Approx d, Approx e) => Approx (a,b,c,d,e) where
(a
x,b
y,c
z,d
u,e
v) =~ :: (a, b, c, d, e) -> (a, b, c, d, e) -> Bool
=~ (a
a,b
b,c
c,d
d,e
e) =
( (a
x a -> a -> Bool
forall a. Approx a => a -> a -> Bool
=~ a
a)
Bool -> Bool -> Bool
&& (b
y b -> b -> Bool
forall a. Approx a => a -> a -> Bool
=~ b
b)
Bool -> Bool -> Bool
&& (c
z c -> c -> Bool
forall a. Approx a => a -> a -> Bool
=~ c
c)
Bool -> Bool -> Bool
&& (d
u d -> d -> Bool
forall a. Approx a => a -> a -> Bool
=~ d
d)
Bool -> Bool -> Bool
&& (e
v e -> e -> Bool
forall a. Approx a => a -> a -> Bool
=~ e
e)
)
{-# INLINE (=~) #-}
instance (Approx a,Approx b,Approx c,Approx d, Approx e, Approx f) => Approx (a,b,c,d,e,f) where
(a
x,b
y,c
z,d
u,e
v,f
w) =~ :: (a, b, c, d, e, f) -> (a, b, c, d, e, f) -> Bool
=~ (a
a,b
b,c
c,d
d,e
e,f
f) =
( (a
x a -> a -> Bool
forall a. Approx a => a -> a -> Bool
=~ a
a)
Bool -> Bool -> Bool
&& (b
y b -> b -> Bool
forall a. Approx a => a -> a -> Bool
=~ b
b)
Bool -> Bool -> Bool
&& (c
z c -> c -> Bool
forall a. Approx a => a -> a -> Bool
=~ c
c)
Bool -> Bool -> Bool
&& (d
u d -> d -> Bool
forall a. Approx a => a -> a -> Bool
=~ d
d)
Bool -> Bool -> Bool
&& (e
v e -> e -> Bool
forall a. Approx a => a -> a -> Bool
=~ e
e)
Bool -> Bool -> Bool
&& (f
w f -> f -> Bool
forall a. Approx a => a -> a -> Bool
=~ f
f)
)
{-# INLINE (=~) #-}
instance (Approx a,Approx b,Approx c,Approx d, Approx e, Approx f, Approx g) => Approx (a,b,c,d,e,f,g) where
(a
x,b
y,c
z,d
u,e
v,f
w,g
p) =~ :: (a, b, c, d, e, f, g) -> (a, b, c, d, e, f, g) -> Bool
=~ (a
a,b
b,c
c,d
d,e
e,f
f,g
g) =
( (a
x a -> a -> Bool
forall a. Approx a => a -> a -> Bool
=~ a
a)
Bool -> Bool -> Bool
&& (b
y b -> b -> Bool
forall a. Approx a => a -> a -> Bool
=~ b
b)
Bool -> Bool -> Bool
&& (c
z c -> c -> Bool
forall a. Approx a => a -> a -> Bool
=~ c
c)
Bool -> Bool -> Bool
&& (d
u d -> d -> Bool
forall a. Approx a => a -> a -> Bool
=~ d
d)
Bool -> Bool -> Bool
&& (e
v e -> e -> Bool
forall a. Approx a => a -> a -> Bool
=~ e
e)
Bool -> Bool -> Bool
&& (f
w f -> f -> Bool
forall a. Approx a => a -> a -> Bool
=~ f
f)
Bool -> Bool -> Bool
&& (g
p g -> g -> Bool
forall a. Approx a => a -> a -> Bool
=~ g
g)
)
{-# INLINE (=~) #-}
instance (Approx a,Approx b,Approx c,Approx d, Approx e, Approx f, Approx g, Approx h) => Approx (a,b,c,d,e,f,g,h) where
(a
x,b
y,c
z,d
u,e
v,f
w,g
p,h
q) =~ :: (a, b, c, d, e, f, g, h) -> (a, b, c, d, e, f, g, h) -> Bool
=~ (a
a,b
b,c
c,d
d,e
e,f
f,g
g,h
h) =
( (a
x a -> a -> Bool
forall a. Approx a => a -> a -> Bool
=~ a
a)
Bool -> Bool -> Bool
&& (b
y b -> b -> Bool
forall a. Approx a => a -> a -> Bool
=~ b
b)
Bool -> Bool -> Bool
&& (c
z c -> c -> Bool
forall a. Approx a => a -> a -> Bool
=~ c
c)
Bool -> Bool -> Bool
&& (d
u d -> d -> Bool
forall a. Approx a => a -> a -> Bool
=~ d
d)
Bool -> Bool -> Bool
&& (e
v e -> e -> Bool
forall a. Approx a => a -> a -> Bool
=~ e
e)
Bool -> Bool -> Bool
&& (f
w f -> f -> Bool
forall a. Approx a => a -> a -> Bool
=~ f
f)
Bool -> Bool -> Bool
&& (g
p g -> g -> Bool
forall a. Approx a => a -> a -> Bool
=~ g
g)
Bool -> Bool -> Bool
&& (h
q h -> h -> Bool
forall a. Approx a => a -> a -> Bool
=~ h
h)
)
{-# INLINE (=~) #-}
instance (Approx a,Approx b,Approx c,Approx d, Approx e, Approx f, Approx g, Approx h, Approx i) => Approx (a,b,c,d,e,f,g,h,i) where
(a
x,b
y,c
z,d
u,e
v,f
w,g
p,h
q,i
r) =~ :: (a, b, c, d, e, f, g, h, i) -> (a, b, c, d, e, f, g, h, i) -> Bool
=~ (a
a,b
b,c
c,d
d,e
e,f
f,g
g,h
h,i
i) =
( (a
x a -> a -> Bool
forall a. Approx a => a -> a -> Bool
=~ a
a)
Bool -> Bool -> Bool
&& (b
y b -> b -> Bool
forall a. Approx a => a -> a -> Bool
=~ b
b)
Bool -> Bool -> Bool
&& (c
z c -> c -> Bool
forall a. Approx a => a -> a -> Bool
=~ c
c)
Bool -> Bool -> Bool
&& (d
u d -> d -> Bool
forall a. Approx a => a -> a -> Bool
=~ d
d)
Bool -> Bool -> Bool
&& (e
v e -> e -> Bool
forall a. Approx a => a -> a -> Bool
=~ e
e)
Bool -> Bool -> Bool
&& (f
w f -> f -> Bool
forall a. Approx a => a -> a -> Bool
=~ f
f)
Bool -> Bool -> Bool
&& (g
p g -> g -> Bool
forall a. Approx a => a -> a -> Bool
=~ g
g)
Bool -> Bool -> Bool
&& (h
q h -> h -> Bool
forall a. Approx a => a -> a -> Bool
=~ h
h)
Bool -> Bool -> Bool
&& (i
r i -> i -> Bool
forall a. Approx a => a -> a -> Bool
=~ i
i)
)
{-# INLINE (=~) #-}
instance (Approx a,Approx b,Approx c,Approx d, Approx e, Approx f, Approx g, Approx h, Approx i, Approx j) => Approx (a,b,c,d,e,f,g,h,i,j) where
(a
x,b
y,c
z,d
u,e
v,f
w,g
p,h
q,i
r,j
s) =~ :: (a, b, c, d, e, f, g, h, i, j)
-> (a, b, c, d, e, f, g, h, i, j) -> Bool
=~ (a
a,b
b,c
c,d
d,e
e,f
f,g
g,h
h,i
i,j
j) =
( (a
x a -> a -> Bool
forall a. Approx a => a -> a -> Bool
=~ a
a)
Bool -> Bool -> Bool
&& (b
y b -> b -> Bool
forall a. Approx a => a -> a -> Bool
=~ b
b)
Bool -> Bool -> Bool
&& (c
z c -> c -> Bool
forall a. Approx a => a -> a -> Bool
=~ c
c)
Bool -> Bool -> Bool
&& (d
u d -> d -> Bool
forall a. Approx a => a -> a -> Bool
=~ d
d)
Bool -> Bool -> Bool
&& (e
v e -> e -> Bool
forall a. Approx a => a -> a -> Bool
=~ e
e)
Bool -> Bool -> Bool
&& (f
w f -> f -> Bool
forall a. Approx a => a -> a -> Bool
=~ f
f)
Bool -> Bool -> Bool
&& (g
p g -> g -> Bool
forall a. Approx a => a -> a -> Bool
=~ g
g)
Bool -> Bool -> Bool
&& (h
q h -> h -> Bool
forall a. Approx a => a -> a -> Bool
=~ h
h)
Bool -> Bool -> Bool
&& (i
r i -> i -> Bool
forall a. Approx a => a -> a -> Bool
=~ i
i)
Bool -> Bool -> Bool
&& (j
s j -> j -> Bool
forall a. Approx a => a -> a -> Bool
=~ j
j)
)
{-# INLINE (=~) #-}
instance (Approx a,Approx b,Approx c,Approx d, Approx e, Approx f, Approx g, Approx h, Approx i, Approx j, Approx k) => Approx (a,b,c,d,e,f,g,h,i,j,k) where
(a
x,b
y,c
z,d
u,e
v,f
w,g
p,h
q,i
r,j
s,k
t) =~ :: (a, b, c, d, e, f, g, h, i, j, k)
-> (a, b, c, d, e, f, g, h, i, j, k) -> Bool
=~ (a
a,b
b,c
c,d
d,e
e,f
f,g
g,h
h,i
i,j
j,k
k) =
( (a
x a -> a -> Bool
forall a. Approx a => a -> a -> Bool
=~ a
a)
Bool -> Bool -> Bool
&& (b
y b -> b -> Bool
forall a. Approx a => a -> a -> Bool
=~ b
b)
Bool -> Bool -> Bool
&& (c
z c -> c -> Bool
forall a. Approx a => a -> a -> Bool
=~ c
c)
Bool -> Bool -> Bool
&& (d
u d -> d -> Bool
forall a. Approx a => a -> a -> Bool
=~ d
d)
Bool -> Bool -> Bool
&& (e
v e -> e -> Bool
forall a. Approx a => a -> a -> Bool
=~ e
e)
Bool -> Bool -> Bool
&& (f
w f -> f -> Bool
forall a. Approx a => a -> a -> Bool
=~ f
f)
Bool -> Bool -> Bool
&& (g
p g -> g -> Bool
forall a. Approx a => a -> a -> Bool
=~ g
g)
Bool -> Bool -> Bool
&& (h
q h -> h -> Bool
forall a. Approx a => a -> a -> Bool
=~ h
h)
Bool -> Bool -> Bool
&& (i
r i -> i -> Bool
forall a. Approx a => a -> a -> Bool
=~ i
i)
Bool -> Bool -> Bool
&& (j
s j -> j -> Bool
forall a. Approx a => a -> a -> Bool
=~ j
j)
Bool -> Bool -> Bool
&& (k
t k -> k -> Bool
forall a. Approx a => a -> a -> Bool
=~ k
k)
)
{-# INLINE (=~) #-}
instance (M.Unbox a, Approx a) => Approx (U.Vector a) where
Vector a
x =~ :: Vector a -> Vector a -> Bool
=~ Vector a
y = (Vector a -> Int
forall a. Unbox a => Vector a -> Int
U.length Vector a
xInt -> Int -> Bool
forall a. Eq a => a -> a -> Bool
==Vector a -> Int
forall a. Unbox a => Vector a -> Int
U.length Vector a
y) Bool -> Bool -> Bool
&& ((Bool -> Bool -> Bool) -> Bool -> Vector Bool -> Bool
forall a b. Unbox a => (a -> b -> b) -> b -> Vector a -> b
U.foldr Bool -> Bool -> Bool
(&&) Bool
True (Vector Bool -> Bool) -> Vector Bool -> Bool
forall a b. (a -> b) -> a -> b
$ (a -> a -> Bool) -> Vector a -> Vector a -> Vector Bool
forall a b c.
(Unbox a, Unbox b, Unbox c) =>
(a -> b -> c) -> Vector a -> Vector b -> Vector c
U.zipWith a -> a -> Bool
forall a. Approx a => a -> a -> Bool
(=~) Vector a
x Vector a
y)
instance (Approx a) => Approx (V.Vector a) where
Vector a
x =~ :: Vector a -> Vector a -> Bool
=~ Vector a
y = (Vector a -> Int
forall a. Vector a -> Int
V.length Vector a
xInt -> Int -> Bool
forall a. Eq a => a -> a -> Bool
==Vector a -> Int
forall a. Vector a -> Int
V.length Vector a
y) Bool -> Bool -> Bool
&& ((Bool -> Bool -> Bool) -> Bool -> Vector Bool -> Bool
forall a b. (a -> b -> b) -> b -> Vector a -> b
V.foldr Bool -> Bool -> Bool
(&&) Bool
True (Vector Bool -> Bool) -> Vector Bool -> Bool
forall a b. (a -> b) -> a -> b
$ (a -> a -> Bool) -> Vector a -> Vector a -> Vector Bool
forall a b c. (a -> b -> c) -> Vector a -> Vector b -> Vector c
V.zipWith a -> a -> Bool
forall a. Approx a => a -> a -> Bool
(=~) Vector a
x Vector a
y)
instance (Eq a, Hashable a, Approx b) => Approx (Hm.HashMap a b) where
HashMap a b
x =~ :: HashMap a b -> HashMap a b -> Bool
=~ HashMap a b
y = (HashMap a b -> HashMap a b -> Bool
forall v k.
(Approx v, Eq k, Hashable k) =>
HashMap k v -> HashMap k v -> Bool
fz HashMap a b
x HashMap a b
y) Bool -> Bool -> Bool
&& (HashMap a b -> HashMap a b -> Bool
forall v k.
(Approx v, Eq k, Hashable k) =>
HashMap k v -> HashMap k v -> Bool
fz HashMap a b
y HashMap a b
x) where
fz :: HashMap k v -> HashMap k v -> Bool
fz HashMap k v
p HashMap k v
q = (Bool -> (k, v) -> Bool) -> Bool -> [(k, v)] -> Bool
forall (t :: * -> *) b a.
Foldable t =>
(b -> a -> b) -> b -> t a -> b
foldl' (HashMap k v -> Bool -> (k, v) -> Bool
forall v k.
(Approx v, Eq k, Hashable k) =>
HashMap k v -> Bool -> (k, v) -> Bool
f HashMap k v
p) Bool
True ([(k, v)] -> Bool) -> [(k, v)] -> Bool
forall a b. (a -> b) -> a -> b
$ HashMap k v -> [(k, v)]
forall k v. HashMap k v -> [(k, v)]
Hm.toList HashMap k v
q
f :: HashMap k v -> Bool -> (k, v) -> Bool
f HashMap k v
p Bool
t (k, v)
z = Bool
t Bool -> Bool -> Bool
&& ((k -> HashMap k v -> Maybe v
forall k v. (Eq k, Hashable k) => k -> HashMap k v -> Maybe v
Hm.lookup k
k HashMap k v
p) Maybe v -> Maybe v -> Bool
forall a. Approx a => a -> a -> Bool
=~ (v -> Maybe v
forall a. a -> Maybe a
Just v
v)) where (k
k,v
v) = (k, v)
z