linear-massiv-0.1.0.6: test/Test/Banded.hs
{-# LANGUAGE AllowAmbiguousTypes #-}
module Test.Banded (bandedTests) where
import Test.Tasty
import Test.Tasty.HUnit
import qualified Data.Massiv.Array as M
import Numeric.LinearAlgebra.Massiv.Internal
import Numeric.LinearAlgebra.Massiv.BLAS.Level2 (matvec)
import Numeric.LinearAlgebra.Massiv.BLAS.Level3 (matMul, transpose)
import Numeric.LinearAlgebra.Massiv.Solve.Banded
import Test.Types (matApproxEq, vecApproxEq)
bandedTests :: TestTree
bandedTests = testGroup "Banded"
[ testCase "bandLU + band solve (tridiagonal p=1, q=1)" test_bandLUTridiag
, testCase "bandLU + band solve (pentadiagonal p=2, q=2)" test_bandLUPentadiag
, testCase "bandCholesky reconstruction (p=1)" test_bandCholTridiag
, testCase "bandCholesky reconstruction (p=2)" test_bandCholPentadiag
, testCase "tridiagSolve SPD system" test_tridiagSolveSPD
]
test_bandLUTridiag :: Assertion
test_bandLUTridiag = do
-- Diagonally dominant tridiagonal 5x5 matrix
let a = makeMatrix @5 @5 @M.P $ \i j ->
case abs (i - j) of
0 -> 4.0 :: Double
1 -> -1.0
_ -> 0.0
b = makeVector @5 @M.P $ \i -> fromIntegral (i + 1) :: Double
lu = bandLU 1 1 a
y = bandForwardSub 1 lu b
x = bandBackSub 1 lu y
ax = matvec a x
assertBool "bandLU solve Ax ~= b" (vecApproxEq ax b)
test_bandLUPentadiag :: Assertion
test_bandLUPentadiag = do
-- Diagonally dominant pentadiagonal 6x6 matrix (p=2, q=2)
let a = makeMatrix @6 @6 @M.P $ \i j ->
case abs (i - j) of
0 -> 10.0 :: Double
1 -> -2.0
2 -> 0.5
_ -> 0.0
b = makeVector @6 @M.P $ \i -> fromIntegral (i * 2 + 1) :: Double
lu = bandLU 2 2 a
y = bandForwardSub 2 lu b
x = bandBackSub 2 lu y
ax = matvec a x
assertBool "bandLU pentadiagonal Ax ~= b" (vecApproxEq ax b)
test_bandCholTridiag :: Assertion
test_bandCholTridiag = do
-- Symmetric positive definite tridiagonal 5x5 matrix (p=1)
let a = makeMatrix @5 @5 @M.P $ \i j ->
case abs (i - j) of
0 -> 5.0 :: Double
1 -> 1.0
_ -> 0.0
g = bandCholesky 1 a
gt = transpose g
ggt = matMul g gt
assertBool "bandCholesky G*G^T ~= A (p=1)" (matApproxEq a ggt)
test_bandCholPentadiag :: Assertion
test_bandCholPentadiag = do
-- Symmetric positive definite pentadiagonal 5x5 matrix (p=2)
let a = makeMatrix @5 @5 @M.P $ \i j ->
case abs (i - j) of
0 -> 10.0 :: Double
1 -> 2.0
2 -> 0.5
_ -> 0.0
g = bandCholesky 2 a
gt = transpose g
ggt = matMul g gt
assertBool "bandCholesky G*G^T ~= A (p=2)" (matApproxEq a ggt)
test_tridiagSolveSPD :: Assertion
test_tridiagSolveSPD = do
-- 5x5 SPD tridiagonal system
let d = makeVector @5 @M.P $ \_ -> 4.0 :: Double
sd = makeVector @5 @M.P $ \i -> if i < 4 then 1.0 else 0.0 :: Double
b = makeVector @5 @M.P $ \i -> fromIntegral (i + 1) :: Double
x = tridiagSolve d sd b
-- Reconstructed explicit matrix
a = makeMatrix @5 @5 @M.P $ \i j ->
case abs (i - j) of
0 -> 4.0 :: Double
1 -> 1.0
_ -> 0.0
ax = matvec a x
assertBool "tridiagSolve Ax ~= b" (vecApproxEq ax b)