Skip to content

Commit c596ac0

Browse files
committed
start unit testing
1 parent 7fd2586 commit c596ac0

File tree

2 files changed

+131
-0
lines changed

2 files changed

+131
-0
lines changed

test/linalg/CMakeLists.txt

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ set(
1313
"test_linalg_determinant.fypp"
1414
"test_linalg_qr.fypp"
1515
"test_linalg_schur.fypp"
16+
"test_linalg_solve_iterative.fypp"
1617
"test_linalg_svd.fypp"
1718
"test_linalg_matrix_property_checks.fypp"
1819
"test_linalg_sparse.fypp"
@@ -32,6 +33,7 @@ ADDTEST(linalg_solve)
3233
ADDTEST(linalg_lstsq)
3334
ADDTEST(linalg_qr)
3435
ADDTEST(linalg_schur)
36+
ADDTEST(linalg_solve_iterative)
3537
ADDTEST(linalg_svd)
3638
ADDTEST(blas_lapack)
3739
ADDTEST(linalg_sparse)
Lines changed: 129 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,129 @@
1+
#:include "common.fypp"
2+
#:set R_KINDS_TYPES = list(zip(REAL_KINDS, REAL_TYPES, REAL_SUFFIX))
3+
#:set MATRIX_TYPES = ["dense", "CSR"]
4+
! Test linear system iterative solvers
5+
module test_linalg_solve_iterative
6+
use stdlib_kinds
7+
use stdlib_sparse
8+
use stdlib_linalg_iterative_solvers
9+
use testdrive, only: error_type, check, new_unittest, unittest_type
10+
11+
implicit none
12+
private
13+
14+
public :: test_linear_systems
15+
16+
contains
17+
18+
subroutine test_linear_systems(tests)
19+
!> Collection of tests
20+
type(unittest_type), allocatable, intent(out) :: tests(:)
21+
22+
allocate(tests(0))
23+
24+
tests = [ new_unittest("factorize_ldlt",test_factorize_ldlt), &
25+
new_unittest("solve_ldlt",test_solve_ldlt) ]
26+
27+
end subroutine test_linear_systems
28+
29+
30+
!> Simple linear system
31+
subroutine test_factorize_ldlt(error)
32+
type(error_type), allocatable, intent(out) :: error
33+
34+
#:for k, t, s in R_KINDS_TYPES
35+
block
36+
${t}$, parameter :: tol = 1.e-4_${k}$
37+
${t}$ :: A(5,5) = reshape([${t}$ :: 5, -2, 0, -2, -2, &
38+
-2, 5, -2, 0, 0, &
39+
0, -2, 5, -2, 0, &
40+
-2, 0, -2, 5, -2, &
41+
-2, 0, 0, -2, 5], [5,5])
42+
${t}$ :: Lref(5,5) = transpose(reshape([${t}$ :: 1. , 0. , 0. , 0. , 0.,&
43+
-0.4, 1. , 0. , 0. , 0.,&
44+
0. , -0.47619048, 1. , 0. , 0.,&
45+
-0.4, -0.19047619, -0.58823529, 1. , 0., &
46+
-0.4, -0.19047619, -0.09411765, -1.2, 1.], [5,5]))
47+
48+
${t}$ :: Dref(5) = [${t}$ :: 5, 4.2, 4.04761904761904744987, 2.64705882352941124225, 0.2]
49+
50+
${t}$ :: L(5,5), D(5)
51+
52+
call factorize_ldlt(A, L, D)
53+
54+
call check(error, all(abs(L-Lref)<tol), 'LDLt factorization L doesnt match')
55+
if (allocated(error)) return
56+
call check(error, all(abs(D-Dref)<tol), 'LDLt factorization D doesnt match')
57+
if (allocated(error)) return
58+
59+
end block
60+
61+
#:endfor
62+
end subroutine test_factorize_ldlt
63+
64+
subroutine test_solve_ldlt(error)
65+
type(error_type), allocatable, intent(out) :: error
66+
67+
#:for k, t, s in R_KINDS_TYPES
68+
block
69+
${t}$, parameter :: tol = 1000*epsilon(0.0_${k}$)
70+
${t}$ :: A(3,3) = reshape([${t}$ :: 4, 12, -16, &
71+
12, 37, -43, &
72+
-16, -43, 98], [3,3])
73+
${t}$ :: Lref(3,3) = transpose(reshape([${t}$ :: 1, 0, 0, &
74+
3, 1, 0, &
75+
-4, 5, 1], [3,3]))
76+
${t}$ :: Dref(3) = [${t}$ :: 4, 1, 9]
77+
${t}$ :: L(3,3), D(3), b(3), x(3), res(3)
78+
79+
call factorize_ldlt(A, L, D)
80+
81+
call check(error, all(abs(L-Lref)<tol), 'LDLt factorization L doesnt match')
82+
if (allocated(error)) return
83+
call check(error, all(abs(D-Dref)<tol), 'LDLt factorization D doesnt match')
84+
if (allocated(error)) return
85+
86+
D = 1._${k}$ / D
87+
88+
b = [${t}$ :: 1,2,3]
89+
call solve_forward_triangular( L , b , x )
90+
x = D * x
91+
call solve_backward_triangular( L , x , x )
92+
93+
res = [343._${k}$/12,-23._${k}$/3,4._${k}$/3]
94+
call check(error, norm2(x-res)<tol*norm2(res), 'LDLt solve result doesnt match')
95+
if (allocated(error)) return
96+
end block
97+
98+
#:endfor
99+
end subroutine test_solve_ldlt
100+
101+
! TODO: add tests for solve_cg, solve_pccg, etc.
102+
103+
end module test_linalg_solve_iterative
104+
105+
program test_solve_iterative
106+
use, intrinsic :: iso_fortran_env, only : error_unit
107+
use testdrive, only : run_testsuite, new_testsuite, testsuite_type
108+
use test_linalg_solve_iterative, only : test_linear_systems
109+
implicit none
110+
integer :: stat, is
111+
type(testsuite_type), allocatable :: testsuites(:)
112+
character(len=*), parameter :: fmt = '("#", *(1x, a))'
113+
114+
stat = 0
115+
116+
testsuites = [ &
117+
new_testsuite("linalg_solve_iterative", test_linear_systems) &
118+
]
119+
120+
do is = 1, size(testsuites)
121+
write(error_unit, fmt) "Testing:", testsuites(is)%name
122+
call run_testsuite(testsuites(is)%collect, error_unit, stat)
123+
end do
124+
125+
if (stat > 0) then
126+
write(error_unit, '(i0, 1x, a)') stat, "test(s) failed!"
127+
error stop
128+
end if
129+
end program test_solve_iterative

0 commit comments

Comments
 (0)