module Plankton.Metric
( Signed(..)
, Normed(..)
, Metric(..)
, Epsilon(..)
, (≈)
) where
import Data.Complex (Complex(..))
import Plankton.Additive
import Plankton.Field
import Plankton.Multiplicative
import qualified Protolude as P
import Protolude
(Bool(..), Double, Eq(..), Float, Int, Integer, Ord(..), ($), (&&))
class (MultiplicativeUnital a) =>
Signed a where
sign :: a -> a
abs :: a -> a
instance Signed Double where
sign a =
if a >= zero
then one
else negate one
abs = P.abs
instance Signed Float where
sign a =
if a >= zero
then one
else negate one
abs = P.abs
instance Signed Int where
sign a =
if a >= zero
then one
else negate one
abs = P.abs
instance Signed Integer where
sign a =
if a >= zero
then one
else negate one
abs = P.abs
class Normed a b where
size :: a -> b
instance Normed Double Double where
size = P.abs
instance Normed Float Float where
size = P.abs
instance Normed Int Int where
size = P.abs
instance Normed Integer Integer where
size = P.abs
instance (Multiplicative a, ExpField a, Normed a a) =>
Normed (Complex a) a where
size (rx :+ ix) = sqrt (rx * rx + ix * ix)
class Metric a b where
distance :: a -> a -> b
instance Metric Double Double where
distance a b = abs (a b)
instance Metric Float Float where
distance a b = abs (a b)
instance Metric Int Int where
distance a b = abs (a b)
instance Metric Integer Integer where
distance a b = abs (a b)
instance (Multiplicative a, ExpField a, Normed a a) =>
Metric (Complex a) a where
distance a b = size (a b)
class (AdditiveGroup a) =>
Epsilon a where
nearZero :: a -> Bool
aboutEqual :: a -> a -> Bool
positive :: (Eq a, Signed a) => a -> Bool
positive a = a == abs a
veryPositive :: (Eq a, Signed a) => a -> Bool
veryPositive a = P.not (nearZero a) && positive a
veryNegative :: (Eq a, Signed a) => a -> Bool
veryNegative a = P.not (nearZero a P.|| positive a)
infixl 4 ≈
(≈) :: (Epsilon a) => a -> a -> Bool
(≈) = aboutEqual
instance Epsilon Double where
nearZero a = abs a <= (1e-12 :: Double)
aboutEqual a b = nearZero $ a b
instance Epsilon Float where
nearZero a = abs a <= (1e-6 :: Float)
aboutEqual a b = nearZero $ a b
instance Epsilon Int where
nearZero a = a == zero
aboutEqual a b = nearZero $ a b
instance Epsilon Integer where
nearZero a = a == zero
aboutEqual a b = nearZero $ a b
instance (Epsilon a) => Epsilon (Complex a) where
nearZero (rx :+ ix) = nearZero rx && nearZero ix
aboutEqual a b = nearZero $ a b