Skip to content

Commit 0be918e

Browse files
committed
real and complex tests
1 parent 7b7c051 commit 0be918e

File tree

2 files changed

+192
-0
lines changed

2 files changed

+192
-0
lines changed

test/linalg/CMakeLists.txt

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,10 +2,12 @@ set(
22
fppFiles
33
"test_linalg.fypp"
44
"test_blas_lapack.fypp"
5+
"test_linalg_solve.fypp"
56
"test_linalg_matrix_property_checks.fypp"
67
)
78
fypp_f90("${fyppFlags}" "${fppFiles}" outFiles)
89

910
ADDTEST(linalg)
1011
ADDTEST(linalg_matrix_property_checks)
12+
ADDTEST(linalg_solve)
1113
ADDTEST(blas_lapack)

test/linalg/test_linalg_solve.fypp

Lines changed: 190 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,190 @@
1+
#:include "common.fypp"
2+
#:set RC_KINDS_TYPES = REAL_KINDS_TYPES + CMPLX_KINDS_TYPES
3+
! Test linear system solver
4+
module test_linalg_solve
5+
use stdlib_linalg_constants
6+
use stdlib_linalg_state
7+
use stdlib_linalg, only: solve
8+
use testdrive, only: error_type, check, new_unittest, unittest_type
9+
10+
implicit none (type,external)
11+
private
12+
13+
public :: test_linear_systems
14+
15+
contains
16+
17+
!> Solve real and complex linear systems
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+
#:for rk,rt,ri in REAL_KINDS_TYPES
25+
#:if rk!="xdp"
26+
tests = [tests,new_unittest("solve_${ri}$",test_${ri}$_solve), &
27+
new_unittest("solve_${ri}$_multiple",test_${ri}$_solve_multiple)]
28+
#:endif
29+
#:endfor
30+
31+
#:for ck,ct,ci in CMPLX_KINDS_TYPES
32+
#:if ck!="xdp"
33+
tests = [tests,new_unittest("solve_complex_${ci}$",test_${ci}$_solve), &
34+
new_unittest("solve_2x2_complex_${ci}$",test_2x2_${ci}$_solve)]
35+
#:endif
36+
#:endfor
37+
38+
end subroutine test_linear_systems
39+
40+
#:for rk,rt,ri in REAL_KINDS_TYPES
41+
#:if rk!="xdp"
42+
!> Simple linear system
43+
subroutine test_${ri}$_solve(error)
44+
type(error_type), allocatable, intent(out) :: error
45+
46+
type(linalg_state_type) :: state
47+
48+
${rt}$ :: A(3,3) = transpose(reshape([${rt}$ :: 1, 3, 3, &
49+
1, 3, 4, &
50+
1, 4, 3], [3,3]))
51+
${rt}$ :: b (3) = [${rt}$ :: 1, 4, -1]
52+
${rt}$ :: res(3) = [${rt}$ :: -2, -2, 3]
53+
${rt}$ :: x(3)
54+
55+
x = solve(a,b,err=state)
56+
57+
call check(error,state%ok(),state%print())
58+
if (allocated(error)) return
59+
60+
call check(error, all(abs(x-res)<abs(res*epsilon(0.0_${rk}$))), 'results match expected')
61+
if (allocated(error)) return
62+
63+
end subroutine test_${ri}$_solve
64+
65+
!> Simple linear system with multiple right hand sides
66+
subroutine test_${ri}$_solve_multiple(error)
67+
type(error_type), allocatable, intent(out) :: error
68+
69+
type(linalg_state_type) :: state
70+
71+
${rt}$ :: A(3,3) = transpose(reshape([${rt}$ :: 1,-1, 2, &
72+
0, 1, 1, &
73+
1,-1, 3], [3,3]))
74+
${rt}$ :: b(3,3) = transpose(reshape([${rt}$ :: 0, 1, 2, &
75+
1,-2,-1, &
76+
2, 3,-1], [3,3]))
77+
${rt}$ :: res(3,3) = transpose(reshape([${rt}$ ::-5,-7,10, &
78+
-1,-4, 2, &
79+
2, 2,-3], [3,3]))
80+
${rt}$ :: x(3,3)
81+
82+
x = solve(a,b,err=state)
83+
84+
call check(error,state%ok(),state%print())
85+
if (allocated(error)) return
86+
87+
call check(error, all(abs(x-res)<abs(res*epsilon(0.0_${rk}$))), 'results match expected')
88+
if (allocated(error)) return
89+
90+
end subroutine test_${ri}$_solve_multiple
91+
#:endif
92+
#:endfor
93+
94+
#:for rk,rt,ri in CMPLX_KINDS_TYPES
95+
#:if rk!="xdp"
96+
!> Complex linear system
97+
!> Militaru, Popa, "On the numerical solving of complex linear systems",
98+
!> Int J Pure Appl Math 76(1), 113-122, 2012.
99+
subroutine test_${ri}$_solve(error)
100+
type(error_type), allocatable, intent(out) :: error
101+
102+
type(linalg_state_type) :: state
103+
104+
${rt}$ :: A(5,5), b(5), res(5), x(5)
105+
integer(ilp) :: i
106+
107+
! Fill in linear system
108+
A = (0.0_${rk}$,0.0_${rk}$)
109+
110+
A(1:2,1) = [(19.73_${rk}$,0.0_${rk}$),(0.0_${rk}$,-0.51_${rk}$)]
111+
A(1:3,2) = [(12.11_${rk}$,-1.0_${rk}$),(32.3_${rk}$,7.0_${rk}$),(0.0_${rk}$,-0.51_${rk}$)]
112+
A(1:4,3) = [(0.0_${rk}$,5.0_${rk}$),(23.07_${rk}$,0.0_${rk}$),(70.0_${rk}$,7.3_${rk}$),(1.0_${rk}$,1.1_${rk}$)]
113+
A(2:5,4) = [(0.0_${rk}$,1.0_${rk}$),(3.95_${rk}$,0.0_${rk}$),(50.17_${rk}$,0.0_${rk}$),(0.0_${rk}$,-9.351_${rk}$)]
114+
A(3:5,5) = [(19.0_${rk}$,31.83_${rk}$),(45.51_${rk}$,0.0_${rk}$),(55.0_${rk}$,0.0_${rk}$)]
115+
116+
b = [(77.38_${rk}$,8.82_${rk}$),(157.48_${rk}$,19.8_${rk}$),(1175.62_${rk}$,20.69_${rk}$),(912.12_${rk}$,-801.75_${rk}$),(550.0_${rk}$,-1060.4_${rk}$)]
117+
118+
! Exact result
119+
res = [(3.3_${rk}$,-1.0_${rk}$),(1.0_${rk}$,0.17_${rk}$),(5.5_${rk}$,0.0_${rk}$),(9.0_${rk}$,0.0_${rk}$),(10.0_${rk}$,-17.75_${rk}$)]
120+
121+
x = solve(a,b,err=state)
122+
123+
call check(error,state%ok(),state%print())
124+
if (allocated(error)) return
125+
126+
call check(error, all(abs(x-res)<abs(res)*1.0e-3_${rk}$), 'results match expected')
127+
if (allocated(error)) return
128+
129+
end subroutine test_${ri}$_solve
130+
131+
!> 2x2 Complex linear system
132+
!> https://math.stackexchange.com/questions/1996540/solving-linear-equation-systems-with-complex-coefficients-and-variables
133+
subroutine test_2x2_${ri}$_solve(error)
134+
type(error_type), allocatable, intent(out) :: error
135+
136+
type(linalg_state_type) :: state
137+
138+
${rt}$ :: A(2,2), b(2), res(2), x(2)
139+
integer(ilp) :: i
140+
141+
! Fill in linear system
142+
A(1,:) = [(+1.0_${rk}$,+1.0_${rk}$),(-1.0_${rk}$,0.0_${rk}$)]
143+
A(2,:) = [(+1.0_${rk}$,-1.0_${rk}$),(+1.0_${rk}$,1.0_${rk}$)]
144+
145+
b = [(0.0_${rk}$,1.0_${rk}$),(1.0_${rk}$,0.0_${rk}$)]
146+
147+
! Exact result
148+
res = [(0.5_${rk}$,0.5_${rk}$),(0.0_${rk}$,0.0_${rk}$)]
149+
150+
x = solve(a,b,err=state)
151+
152+
call check(error,state%ok(),state%print())
153+
if (allocated(error)) return
154+
155+
call check(error, all(abs(x-res)<max(tiny(0.0_${rk}$),abs(res)*epsilon(0.0_${rk}$))), 'results match expected')
156+
if (allocated(error)) return
157+
158+
159+
end subroutine test_2x2_${ri}$_solve
160+
#:endif
161+
#:endfor
162+
163+
end module test_linalg_solve
164+
165+
program test_solve
166+
use, intrinsic :: iso_fortran_env, only : error_unit
167+
use testdrive, only : run_testsuite, new_testsuite, testsuite_type
168+
use test_linalg_solve, only : test_linear_systems
169+
implicit none
170+
integer :: stat, is
171+
type(testsuite_type), allocatable :: testsuites(:)
172+
character(len=*), parameter :: fmt = '("#", *(1x, a))'
173+
174+
stat = 0
175+
176+
testsuites = [ &
177+
new_testsuite("linalg_solve", test_linear_systems) &
178+
]
179+
180+
do is = 1, size(testsuites)
181+
write(error_unit, fmt) "Testing:", testsuites(is)%name
182+
call run_testsuite(testsuites(is)%collect, error_unit, stat)
183+
end do
184+
185+
if (stat > 0) then
186+
write(error_unit, '(i0, 1x, a)') stat, "test(s) failed!"
187+
error stop
188+
end if
189+
end program test_solve
190+

0 commit comments

Comments
 (0)