@@ -24,7 +24,8 @@ module test_linalg_inverse
2424 #:for rk,rt,ri in RC_KINDS_TYPES
2525 #:if rk!="xdp"
2626 tests = [tests,new_unittest("${ri}$_eye_inverse",test_${ri}$_eye_inverse), &
27- new_unittest("${ri}$_singular_inverse",test_${ri}$_singular_inverse)]
27+ new_unittest("${ri}$_singular_inverse",test_${ri}$_singular_inverse), &
28+ new_unittest("${ri}$_random_spd_inverse",test_${ri}$_random_spd_inverse)]
2829 #:endif
2930 #:endfor
3031
@@ -91,7 +92,53 @@ module test_linalg_inverse
9192 if (allocated(error)) return
9293
9394 end subroutine test_${ri}$_singular_inverse
95+
96+ !> Create a random symmetric positive definite matrix
97+ function random_spd_matrix_${ri}$(n) result(A)
98+ integer(ilp), intent(in) :: n
99+ ${rt}$ :: A(n,n)
100+
101+ ${rt}$, parameter :: one = 1.0_${rk}$
102+ ${rt}$, parameter :: half = 0.5_${rk}$
103+
104+ !> Initialize with randoms
105+ call random_number(A)
106+
107+ !> Make symmetric
108+ A = half*(A+transpose(A))
109+
110+ !> Add diagonally dominant part
111+ A = A + n*eye(n)
112+
113+ end function random_spd_matrix_${ri}$
94114
115+ !> Test random symmetric positive-definite matrix
116+ subroutine test_${ri}$_random_spd_inverse(error)
117+ type(error_type), allocatable, intent(out) :: error
118+
119+ !> Solution tolerance
120+ ${rt}$, parameter :: tol = sqrt(epsilon(0.0_${rk}$))
121+
122+ !> Local variables
123+ integer(ilp), parameter :: n = 5_ilp
124+ type(linalg_state_type) :: state
125+ ${rt}$ :: A(n,n),Am1(n,n)
126+
127+ !> Generate random SPD matrix
128+ A = random_spd_matrix_${ri}$(n)
129+
130+ !> Invert matrix
131+ call invert(A,Am1,err=state)
132+
133+ !> Check result
134+ call check(error,state%ok(),'random SPD matrix (${rk}$): '//state%print())
135+ if (allocated(error)) return
136+
137+ call check(error,all(abs(matmul(Am1,A)-eye(n))<tol),'random SPD matrix (${rk}$): accuracy test')
138+ if (allocated(error)) return
139+
140+ end subroutine test_${ri}$_random_spd_inverse
141+
95142 #:endif
96143 #:endfor
97144
@@ -160,6 +207,76 @@ module test_linalg_inverse
160207
161208 end subroutine test_${ci}$_eye_inverse
162209
210+ !> Create a random symmetric positive definite matrix
211+ function random_spd_matrix_${ci}$(n) result(A)
212+ integer(ilp), intent(in) :: n
213+ ${ct}$ :: A(n,n)
214+
215+ ${ct}$, parameter :: half = (0.5_${ck}$,0.0_${ck}$)
216+ real(${ck}$) :: reA(n,n),imA(n,n)
217+ integer(ilp) :: i
218+
219+ !> Initialize with randoms
220+ call random_number(reA)
221+ call random_number(imA)
222+
223+ A = cmplx(reA,imA,kind=${ck}$)
224+
225+ !> Make symmetric
226+ A = half*(A+transpose(A))
227+
228+ !> Add diagonally dominant part
229+ forall(i=1:n) A(i,i) = A(i,i) + n*(1.0_${ck}$,0.0_${ck}$)
230+
231+ end function random_spd_matrix_${ci}$
232+
233+ !> Test random symmetric positive-definite matrix
234+ subroutine test_${ci}$_random_spd_inverse(error)
235+ type(error_type), allocatable, intent(out) :: error
236+
237+ !> Local variables
238+ integer(ilp) :: failed,i,j
239+ integer(ilp), parameter :: n = 5_ilp
240+ type(linalg_state_type) :: state
241+ ${ct}$ :: A(n,n),Am1(n,n),AA(n,n)
242+
243+ !> Generate random SPD matrix
244+ A = random_spd_matrix_${ci}$(n)
245+
246+ !> Invert matrix
247+ call invert(A,Am1,err=state)
248+
249+ !> Check result
250+ call check(error,state%ok(),'random complex SPD matrix (${ck}$): '//state%print())
251+ if (allocated(error)) return
252+
253+ failed = 0
254+ AA = matmul(A,Am1)
255+ do i=1,n
256+ do j=1,n
257+ if (.not.is_complex_inverse(AA(i,j),i,j)) failed = failed+1
258+ end do
259+ end do
260+
261+ call check(error,failed==0,'inverse_${ci}$_eye (subroutine): data converged')
262+ if (allocated(error)) return
263+
264+ contains
265+
266+ elemental logical function is_complex_inverse(aij,i,j)
267+ ${ct}$, intent(in) :: aij
268+ integer(ilp), intent(in) :: i,j
269+ real(${ck}$), parameter :: tol = sqrt(epsilon(0.0_${ck}$))
270+ if (i/=j) then
271+ is_complex_inverse = abs(aij)<tol
272+ else
273+ ! Product should return the real identity
274+ is_complex_inverse = abs(aij - (1.0_${ck}$,0.0_${ck}$))<tol
275+ endif
276+ end function is_complex_inverse
277+
278+ end subroutine test_${ci}$_random_spd_inverse
279+
163280 !> Invert singular matrix
164281 subroutine test_${ci}$_singular_inverse(error)
165282 type(error_type), allocatable, intent(out) :: error
0 commit comments