Skip to content

Commit 6d9848f

Browse files
committed
Fix is_diagonal and add some tests
1 parent 3d86036 commit 6d9848f

File tree

2 files changed

+370
-16
lines changed

2 files changed

+370
-16
lines changed

src/stdlib_linalg.fypp

Lines changed: 116 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -10,15 +10,15 @@ module stdlib_linalg
1010

1111
public :: diag
1212
public :: eye
13+
public :: trace
14+
public :: outer_product
1315
public :: is_square
1416
public :: is_diagonal
1517
public :: is_symmetric
1618
public :: is_skew_symmetric
1719
public :: is_hermitian
18-
!public :: is_triangular
19-
!public :: is_hessenberg
20-
public :: trace
21-
public :: outer_product
20+
public :: is_triangular
21+
public :: is_hessenberg
2222

2323
interface diag
2424
!! version: experimental
@@ -146,8 +146,31 @@ module stdlib_linalg
146146
module procedure is_hermitian_${t1[0]}$${k1}$
147147
#:endfor
148148
end interface is_hermitian
149+
150+
151+
! Check for triangularity
152+
interface is_triangular
153+
!! version: experimental
154+
!!
155+
!! Checks if a matrix (rank-2 array) is triangular.
156+
!! ([Specification](../page/specs/stdlib_linalg.html#description_9))
157+
#:for k1, t1 in RCI_KINDS_TYPES
158+
module procedure is_triangular_${t1[0]}$${k1}$
159+
#:endfor
160+
end interface is_triangular
149161

150162

163+
! Check for matrix being Hessenberg
164+
interface is_hessenberg
165+
!! version: experimental
166+
!!
167+
!! Checks if a matrix (rank-2 array) is Hessenberg
168+
!! ([Specification](../page/specs/stdlib_linalg.html#description_10))
169+
#:for k1, t1 in RCI_KINDS_TYPES
170+
module procedure is_Hessenberg_${t1[0]}$${k1}$
171+
#:endfor
172+
end interface is_hessenberg
173+
151174
contains
152175

153176

@@ -200,15 +223,15 @@ contains
200223
A_shape = shape(A)
201224
m = A_shape(1)
202225
n = A_shape(2)
203-
o = min(m,n) !minimum/lower dimension
204-
do i=1,n !loop over all columns
205-
do j=1,o-1 !loop over rows above diagonal
226+
do j=1,n !loop over all columns
227+
o = min(j-1,m) !index of row above diagonal (or last row)
228+
do i=1,o !loop over rows above diagonal
206229
if (.not. (A(i,j) .eq. zero)) then
207230
res = .false.
208231
return
209232
end if
210233
end do
211-
do j=o+1,m !loop over rows below diagonal
234+
do i=o+2,m !loop over rows below diagonal
212235
if (.not. (A(i,j) .eq. zero)) then
213236
res = .false.
214237
return
@@ -231,8 +254,8 @@ contains
231254
end if
232255
A_shape = shape(A)
233256
n = A_shape(1) !symmetric dimension of A
234-
do i=1,n !loop over all rows
235-
do j=j+1,n !loop over all columns right of diagonal
257+
do j=1,n !loop over all columns
258+
do i=1,j-1 !loop over all rows above diagonal
236259
if (.not. (A(i,j) .eq. A(j,i))) then
237260
res = .false.
238261
return
@@ -255,8 +278,8 @@ contains
255278
end if
256279
A_shape = shape(A)
257280
n = A_shape(1) !symmetric dimension of A
258-
do i=1,n !loop over all rows
259-
do j=j,n !loop over all columns right of diagonal (including diagonal)
281+
do j=1,n !loop over all columns
282+
do i=1,j !loop over all rows above diagonal (and diagonal)
260283
if (.not. (A(i,j) .eq. -A(j,i))) then
261284
res = .false.
262285
return
@@ -279,8 +302,8 @@ contains
279302
end if
280303
A_shape = shape(A)
281304
n = A_shape(1) !symmetric dimension of A
282-
do i=1,n !loop over all rows
283-
do j=j+1,n !loop over all columns right of diagonal
305+
do j=1,n !loop over all columns
306+
do i=1,j !loop over all rows above diagonal (and diagonal)
284307
if (.not. (A(i,j) .eq. conjg(A(j,i)))) then
285308
res = .false.
286309
return
@@ -291,4 +314,83 @@ contains
291314
end function is_hermitian_${t1[0]}$${k1}$
292315
#:endfor
293316

317+
318+
#:for k1, t1 in RCI_KINDS_TYPES
319+
pure function is_triangular_${t1[0]}$${k1}$(A,uplo) result(res)
320+
${t1}$, intent(in) :: A(:,:)
321+
character, intent(in) :: uplo
322+
logical :: res
323+
${t1}$ :: zero
324+
integer :: A_shape(2), m, n, o, i, j
325+
zero = 0 !zero of relevant type
326+
A_shape = shape(A)
327+
m = A_shape(1)
328+
n = A_shape(2)
329+
if ((uplo .eq. 'u') .or. (uplo .eq. 'U')) then !check for upper triangularity
330+
do j=1,n !loop over all columns
331+
o = min(j-1,m) !index of row above diagonal (or last row)
332+
do i=o+2,m !loop over rows below diagonal
333+
if (.not. (A(i,j) .eq. zero)) then
334+
res = .false.
335+
return
336+
end if
337+
end do
338+
end do
339+
else if ((uplo .eq. 'l') .or. (uplo .eq. 'L')) then !check for lower triangularity
340+
do j=1,n !loop over all columns
341+
o = min(j-1,m) !index of row above diagonal (or last row)
342+
do i=1,o !loop over rows above diagonal
343+
if (.not. (A(i,j) .eq. zero)) then
344+
res = .false.
345+
return
346+
end if
347+
end do
348+
end do
349+
else
350+
!return error on uplo parameter needing to be in {u,U,l,L}
351+
end if
352+
353+
res = .true. !otherwise A is triangular of the requested type
354+
end function is_triangular_${t1[0]}$${k1}$
355+
#:endfor
356+
357+
358+
#:for k1, t1 in RCI_KINDS_TYPES
359+
pure function is_hessenberg_${t1[0]}$${k1}$(A,uplo) result(res)
360+
${t1}$, intent(in) :: A(:,:)
361+
character, intent(in) :: uplo
362+
logical :: res
363+
${t1}$ :: zero
364+
integer :: A_shape(2), m, n, o, i, j
365+
zero = 0 !zero of relevant type
366+
A_shape = shape(A)
367+
m = A_shape(1)
368+
n = A_shape(2)
369+
if ((uplo .eq. 'u') .or. (uplo .eq. 'U')) then !check for upper Hessenberg
370+
do j=1,n !loop over all columns
371+
o = min(j-2,m) !index of row two above diagonal (or last row)
372+
do i=o+4,m !loop over rows two or more below main diagonal
373+
if (.not. (A(i,j) .eq. zero)) then
374+
res = .false.
375+
return
376+
end if
377+
end do
378+
end do
379+
else if ((uplo .eq. 'l') .or. (uplo .eq. 'L')) then !check for lower Hessenberg
380+
do j=1,n !loop over all columns
381+
o = min(j-2,m) !index of row two above diagonal (or last row)
382+
do i=1,o !loop over rows one or more above main diagonal
383+
if (.not. (A(i,j) .eq. zero)) then
384+
res = .false.
385+
return
386+
end if
387+
end do
388+
end do
389+
else
390+
!return error on uplo parameter needing to be in {u,U,l,L}
391+
end if
392+
res = .true. !otherwise A is Hessenberg of the requested type
393+
end function is_hessenberg_${t1[0]}$${k1}$
394+
#:endfor
395+
294396
end module

0 commit comments

Comments
 (0)