packages feed

linear-tests-0.1.1.0: test/Linear/V3Spec.hs

{-# LANGUAGE AllowAmbiguousTypes #-}
{-# LANGUAGE ExplicitForAll      #-}
{-# LANGUAGE ScopedTypeVariables #-}
{-# LANGUAGE TypeApplications    #-}


module Linear.V3Spec (
  spec
) where

import           Test.Hspec
import           Test.QuickCheck

import           Linear.Epsilon
import           Linear.Metric
import           Linear.Vector

import           Linear.V3.Arbitrary

-- | test for the property `|v| = 1`
prop_UnitV3_isUnit :: (Epsilon a, Floating a) => UnitV3 a -> Bool
prop_UnitV3_isUnit (UnitV3 v) = nearZero $ norm v - 1

-- | test for the property `|v| = 1`
prop_CartesianUnitV3_isUnit :: (Epsilon a, Floating a) => CartesianUnitV3 a -> Bool
prop_CartesianUnitV3_isUnit (CartesianUnitV3 v) = nearZero $ norm v - 1

-- | test for the property `|u·v| = 1 or 0`
prop_CartesianUnitV3_isOrthogonal :: (Epsilon a, Floating a) => CartesianUnitV3 a -> CartesianUnitV3 a -> Bool
prop_CartesianUnitV3_isOrthogonal (CartesianUnitV3 u) (CartesianUnitV3 v) = nearZero uv || nearZero (uv - 1) where
  uv = abs $ u `dot` v

-- | test for the property that all vectors are orthogonal and normal
prop_BasisV3_isOrthonormal  :: (Epsilon a, Floating a) => BasisV3 a -> Bool
prop_BasisV3_isOrthonormal (BasisV3 (x,y,z)) =
  nearZero (dot x y) && nearZero (dot y z) && nearZero (dot z x)
    && nearZero (norm x - 1) && nearZero (norm y - 1) && nearZero (norm z - 1)

-- | test for the property `|v*c| = c` for unit vector v and arbitrary scalar c
prop_Metric_V3_norm :: (Epsilon a, Floating a) => UnitV3 a -> a -> Bool
prop_Metric_V3_norm (UnitV3 v) c = nearZero $ norm (v ^* c) - (abs c)

-- | test for the property `signorm(v*c) = v` for unit vector v and c >= 0
prop_Metric_V3_signorm :: (Epsilon a, Floating a) => UnitV3 a -> NonZero a -> Bool
prop_Metric_V3_signorm (UnitV3 v) c = nearZero $ signorm (v ^* (abs (getNonZero c))) - v



spec :: Spec
spec = specTyped @Double

specTyped :: forall a. (Eq a, Show a, Arbitrary a, Epsilon a, Floating a) => Spec
specTyped = do
  describe "V3" $ do
    describe "Arbitrary" $ do
      describe "UnitV3" $ do
        it "satisfies the property `|v| = 1`" $ do
          property $ prop_UnitV3_isUnit @a
      describe "CartesianUnitV3" $ do
        it "satisfies the property `|v| = 1`" $ do
          property $ prop_CartesianUnitV3_isUnit @a
        it "satisfies the property `|u·v| = 1 or 0`" $ do
          property $ prop_CartesianUnitV3_isOrthogonal @a
      describe "BasisV3" $ do
        it "satisfies the property that vectors are orthonormal" $ do
          property $ prop_BasisV3_isOrthonormal @a
    describe "Metric" $ do
      it "satisfies property `|v*c| = c` for unit vectors" $
        property $ prop_Metric_V3_norm @a
      it "satisfies property `signorm(v*c) = v` for unit vectors" $
        property $ prop_Metric_V3_signorm @a