packages feed

simple-vec3-0.3: tests/Tests.hs

{-# LANGUAGE ScopedTypeVariables #-}

import Test.Tasty
import Test.Tasty.QuickCheck

import Data.Vec3


infix 4 <~=>
(<~=>) :: CVec3 -> CVec3 -> Bool
(<~=>) a b = ax ~= bx &&
             ay ~= by &&
             az ~= bz
  where
    (ax, ay, az) = toXYZ (a :: CVec3)
    (bx, by, bz) = toXYZ (b :: CVec3)


infix 4 ~=
(~=) :: Double -> Double -> Bool
(~=) a b | a == b = True
         | a == 0 || b == 0 || isDenormalized absDiff = absDiff < maxError
         | otherwise = absDiff / (abs a + abs b) < maxError
  where
    absDiff = abs $ a - b
    maxError = 1e-13


tests :: [TestTree]
tests =
  [ testProperty
    "Commutativity of addition: a + b = b + a"
    (\(a :: CVec3) b -> a <+> b <~=> b <+> a)
  , testProperty
    "Associativity of addition: (a + b) + c = a + (b + c)"
    (\(a :: CVec3) b c -> (a <+> b) <+> c <~=> a <+> (b <+> c))
  , testProperty
    "Identity element of addition (zero): v + 0 = v"
    (\(v :: CVec3) -> (v <+> origin <~=> v))
  , testProperty
    "Inverse elements of addition: v + (-v) = 0"
    (\(v :: CVec3) -> (v <+> invert v <~=> origin))
  , testProperty
    "Compatibility of scalar and field multiplication"
    (\(v :: CVec3) p q -> (v .^ p .^ q <~=> v .^ (p * q)))
  , testProperty
    "Identity of scalar multiplication"
    (\(v :: CVec3) -> (v .^ 1 <~=> v))
  , testProperty
    "Distributivity wrt vector addition"
    (\(a :: CVec3) b p -> ((a <+> b) .^ p) <~=> (a .^ p) <+> (b .^ p))
  , testProperty
    "Distributivity wrt scalar addition"
    (\(a :: CVec3) p q -> (a .^ (p + q) <~=> (a .^ p) <+> (a .^ q)))
  , testProperty
    "Subtraction definition"
    (\(a :: CVec3) b -> (a <+> invert b <~=> a <-> b))
  , testProperty
    "Normalization"
    (\(v :: CVec3) -> (v <~=> origin || norm (normalize v) ~= 1))
  , testProperty
    "Triangle inequality"
    (\(a :: CVec3) b c -> (distance a b + distance b c >= distance a c))
  ]


main :: IO ()
main = defaultMain $ testGroup "Tests" tests