linear-tests-0.1.1.0: test/Linear/MatrixSpec.hs
{-# LANGUAGE AllowAmbiguousTypes #-}
{-# LANGUAGE ExplicitForAll #-}
{-# LANGUAGE ScopedTypeVariables #-}
{-# LANGUAGE TypeApplications #-}
module Linear.MatrixSpec (
spec
) where
import Test.Hspec
import Test.QuickCheck
import Control.Lens
import Linear.Epsilon
import qualified Linear.Matrix as M
import qualified Linear.V3 as V3
import qualified Linear.V4 as V4
import Linear.Matrix.Arbitrary
-- | test the property `m * m^-1 == identity`
prop_Matrix_InvertibleM33_isInvertible :: (Epsilon a, Floating a) => InvertibleM33 a -> Bool
prop_Matrix_InvertibleM33_isInvertible (InvertibleM33 m) = nearZero ((m M.!*! M.inv33 m ) - M.identity)
isDiagonal :: (Epsilon a) => M.M33 a -> Bool
isDiagonal m33 = all nearZero $ map (`view` m33) [
V3._x . V3._y
, V3._x . V3._z
, V3._y . V3._x
, V3._y . V3._z
, V3._z . V3._x
, V3._z . V3._y]
-- | test the property that all off diagonal entries are zero
prop_Matrix_DiagM33_isDiagonal :: (Epsilon a, Floating a) => DiagM33 a -> Bool
prop_Matrix_DiagM33_isDiagonal = isDiagonal . unDiagM33
isAffine :: (Epsilon a, Floating a) => M.M44 a -> Bool
isAffine m44 = nearZero $ view V4._w m44 - V4.V4 0 0 0 1
-- | test the property `m * m^-1 == identity`
prop_Matrix_InvertibleM44_isInvertible :: (Epsilon a, Floating a) => InvertibleM44 a -> Bool
prop_Matrix_InvertibleM44_isInvertible (InvertibleM44 m) = nearZero ((m M.!*! M.inv44 m ) - M.identity)
-- | test the property that last row is [0,0,0,1]
prop_Matrix_AffineM44_isAffine :: (Epsilon a, Floating a) => AffineM44 a -> Bool
prop_Matrix_AffineM44_isAffine (AffineM44 m44) = isAffine m44
-- | test that it is closed under multiplication
prop_Matrix_AffineM44_isClosedUnderMultiplication :: (Epsilon a, Floating a) => NonEmptyList (AffineM44 a) -> Bool
prop_Matrix_AffineM44_isClosedUnderMultiplication = isAffine . foldr1 (M.!*!) . map unAffineM44 . getNonEmpty
-- | test the property that last row is [0,0,0,1]
prop_Matrix_InvertibleAffineM44_isAffine :: (Epsilon a, Floating a) => InvertibleAffineM44 a -> Bool
prop_Matrix_InvertibleAffineM44_isAffine (InvertibleAffineM44 m44) = isAffine m44
-- | test the property `m * m^-1 == identity`
prop_Matrix_InvertibleAffineM44_isInvertible :: (Epsilon a, Floating a) => InvertibleAffineM44 a -> Bool
prop_Matrix_InvertibleAffineM44_isInvertible (InvertibleAffineM44 m44) = isAffine m44
spec :: Spec
spec = specTyped @Double
specTyped :: forall a. (Eq a, Show a, Arbitrary a, Epsilon a, Floating a) => Spec
specTyped = do
describe "Matrix" $ do
describe "M33" $ do
describe "Arbitrary" $ do
describe "InvertibleM33" $ do
it "satifies property `m * m^-1 == identity`" $
property $ prop_Matrix_InvertibleM33_isInvertible @a
describe "DiagM33" $ do
it "satisfies property that all off diagonal entries are zero" $
property $ prop_Matrix_DiagM33_isDiagonal @a
describe "M44" $ do
describe "Arbitrary" $ do
describe "InvertibleM44" $ do
it "satifies property `m * m^-1 == identity`" $
property $ prop_Matrix_InvertibleM44_isInvertible @a
describe "AffineM44" $ do
it "satisfies property [0,0,0,1] in last row" $
property $ prop_Matrix_AffineM44_isAffine @a
it "is closed under multiplication" $
property $ prop_Matrix_AffineM44_isClosedUnderMultiplication @a
describe "InvertibleAffineM44" $ do
it "satisfies property [0,0,0,1] in last row" $
property $ prop_Matrix_InvertibleAffineM44_isAffine @a
it "satifies `m * m^-1 == identity`" $
property $ prop_Matrix_InvertibleAffineM44_isInvertible @a