packages feed

linear-massiv-0.1.0.6: test/Test/Linear.hs

{-# LANGUAGE AllowAmbiguousTypes #-}

module Test.Linear (linearTests) where

import Test.Tasty
import Test.Tasty.HUnit
import qualified Data.Massiv.Array as M
import qualified Data.Vector as BV
import Data.Maybe (fromJust)

import qualified Linear.V as L
import Linear.V2 (V2(..))
import Linear.V3 (V3(..))
import Linear.V4 (V4(..))

import Numeric.LinearAlgebra.Massiv.Types
import Numeric.LinearAlgebra.Massiv.Internal
import Numeric.LinearAlgebra.Massiv.Linear
import Test.Types (matApproxEq)

linearTests :: TestTree
linearTests = testGroup "Linear"
  [ testCase "fromLinearV / toLinearV roundtrip" test_linearVRoundtrip
  , testCase "fromV2 element indexing" test_fromV2
  , testCase "fromV3 element indexing" test_fromV3
  , testCase "fromV4 element indexing" test_fromV4
  , testCase "toListMatrix / fromListMatrix roundtrip" test_listMatrixRoundtrip
  , testCase "fromListMatrix dimension mismatch" test_fromListMatrixMismatch
  ]

test_linearVRoundtrip :: Assertion
test_linearVRoundtrip = do
  let origVec = BV.fromList [1.0, -2.5, 3.14, 42.0, 0.007] :: BV.Vector Double
      lv = fromJust (L.fromVector origVec) :: L.V 5 Double
      mv = fromLinearV lv
      lv' = toLinearV mv
  L.toVector lv' @?= origVec

test_fromV2 :: Assertion
test_fromV2 = do
  let v = fromV2 @M.P (V2 10.0 20.0 :: V2 Double)
  v !. 0 @?= 10.0
  v !. 1 @?= 20.0

test_fromV3 :: Assertion
test_fromV3 = do
  let v = fromV3 @M.P (V3 1.0 2.0 3.0 :: V3 Double)
  v !. 0 @?= 1.0
  v !. 1 @?= 2.0
  v !. 2 @?= 3.0

test_fromV4 :: Assertion
test_fromV4 = do
  let v = fromV4 @M.P (V4 10.0 20.0 30.0 40.0 :: V4 Double)
  v !. 0 @?= 10.0
  v !. 1 @?= 20.0
  v !. 2 @?= 30.0
  v !. 3 @?= 40.0

test_listMatrixRoundtrip :: Assertion
test_listMatrixRoundtrip = do
  let expectedList = [[1.0, 2.0], [3.0, 4.0], [5.0, 6.0]] :: [[Double]]
      m = makeMatrix @3 @2 @M.P $ \i j -> (expectedList !! i) !! j
      actualList = toListMatrix m
  actualList @?= expectedList
  case fromListMatrix @3 @2 @M.P actualList of
    Nothing -> assertFailure "fromListMatrix returned Nothing"
    Just m' -> assertBool "matrix roundtrip equality" (matApproxEq m m')

test_fromListMatrixMismatch :: Assertion
test_fromListMatrixMismatch = do
  -- Wrong number of rows: 2 instead of 3
  let shortRows = [[1.0, 2.0], [3.0, 4.0]] :: [[Double]]
  fromListMatrix @3 @2 @M.P shortRows @?= Nothing
  -- Wrong number of columns: 3 instead of 2
  let badCols = [[1.0, 2.0, 0.0], [3.0, 4.0, 0.0], [5.0, 6.0, 0.0]] :: [[Double]]
  fromListMatrix @3 @2 @M.P badCols @?= Nothing