Skip to content

Commit daf7a5e

Browse files
committed
schur: real eigenvalues option
1 parent 9a3ba2c commit daf7a5e

File tree

2 files changed

+60
-0
lines changed

2 files changed

+60
-0
lines changed

src/stdlib_linalg.fypp

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -640,6 +640,24 @@ module stdlib_linalg
640640
!> [optional] State return flag. On error if not requested, the code will stop
641641
type(linalg_state_type), optional, intent(out) :: err
642642
end subroutine stdlib_linalg_${ri}$_schur
643+
644+
! Schur decomposition subroutine: real eigenvalue interface
645+
module subroutine stdlib_linalg_real_eig_${ri}$_schur(a,t,z,eigvals,overwrite_a,storage,err)
646+
!> Input matrix a[m,m]
647+
${rt}$, intent(inout), target :: a(:,:)
648+
!> Schur form of A: upper-triangular or quasi-upper-triangular matrix T
649+
${rt}$, intent(out), contiguous, target :: t(:,:)
650+
!> Unitary/orthonormal transformation matrix Z
651+
${rt}$, optional, intent(out), contiguous, target :: z(:,:)
652+
!> Output real eigenvalues that appear on the diagonal of T
653+
real(${rk}$), intent(out), contiguous, target :: eigvals(:)
654+
!> [optional] Provide pre-allocated workspace, size to be checked with schur_space
655+
${rt}$, optional, intent(out), target :: storage(:)
656+
!> [optional] Can A data be overwritten and destroyed?
657+
logical(lk), optional, intent(in) :: overwrite_a
658+
!> [optional] State return flag. On error if not requested, the code will stop
659+
type(linalg_state_type), optional, intent(out) :: err
660+
end subroutine stdlib_linalg_real_eig_${ri}$_schur
643661
#:endfor
644662
end interface schur
645663

src/stdlib_linalg_schur.fypp

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -310,6 +310,48 @@ submodule (stdlib_linalg) stdlib_linalg_schur
310310

311311
end subroutine stdlib_linalg_${ri}$_schur
312312

313+
! Schur decomposition subroutine: real eigenvalue interface
314+
module subroutine stdlib_linalg_real_eig_${ri}$_schur(a,t,z,eigvals,overwrite_a,storage,err)
315+
!> Input matrix a[m,m]
316+
${rt}$, intent(inout), target :: a(:,:)
317+
!> Schur form of A: upper-triangular or quasi-upper-triangular matrix T
318+
${rt}$, intent(out), contiguous, target :: t(:,:)
319+
!> Unitary/orthonormal transformation matrix Z
320+
${rt}$, optional, intent(out), contiguous, target :: z(:,:)
321+
!> Output eigenvalues that appear on the diagonal of T
322+
real(${rk}$), intent(out), contiguous, target :: eigvals(:)
323+
!> [optional] Provide pre-allocated workspace, size to be checked with schur_space
324+
${rt}$, optional, intent(out), target :: storage(:)
325+
!> [optional] Can A data be overwritten and destroyed?
326+
logical(lk), optional, intent(in) :: overwrite_a
327+
!> [optional] State return flag. On error if not requested, the code will stop
328+
type(linalg_state_type), optional, intent(out) :: err
329+
330+
type(linalg_state_type) :: err0
331+
integer(ilp) :: n
332+
complex(${rk}$), allocatable :: ceigvals(:)
333+
real(${rk}$), parameter :: rtol = epsilon(0.0_${rk}$)
334+
real(${rk}$), parameter :: atol = tiny(0.0_${rk}$)
335+
336+
n = size(eigvals,dim=1,kind=ilp)
337+
allocate(ceigvals(n))
338+
339+
!> Compute Schur decomposition with complex eigenvalues
340+
call stdlib_linalg_${ri}$_schur(a,t,z,ceigvals,overwrite_a,storage,err0)
341+
342+
! Check that no eigenvalues have meaningful imaginary part
343+
if (err0%ok() .and. any(aimag(ceigvals)>atol+rtol*abs(abs(ceigvals)))) then
344+
err0 = linalg_state_type(this,LINALG_VALUE_ERROR, &
345+
'complex eigenvalues detected: max(imag(lambda))=',maxval(aimag(ceigvals)))
346+
endif
347+
348+
! Return real components only
349+
eigvals(:n) = real(ceigvals,kind=${rk}$)
350+
351+
call linalg_error_handling(err0,err)
352+
353+
end subroutine stdlib_linalg_real_eig_${ri}$_schur
354+
313355
#:endfor
314356

315357
end submodule stdlib_linalg_schur

0 commit comments

Comments
 (0)