#:include "common.fypp" submodule(stdlib_lapack_eig_svd_lsq) stdlib_lapack_eigv_gen implicit none contains #:for ik,it,ii in LINALG_INT_KINDS_TYPES module subroutine stdlib${ii}$_sgeev( jobvl, jobvr, n, a, lda, wr, wi, vl, ldvl, vr,ldvr, work, lwork, & !! SGEEV computes for an N-by-N real nonsymmetric matrix A, the !! eigenvalues and, optionally, the left and/or right eigenvectors. !! The right eigenvector v(j) of A satisfies !! A * v(j) = lambda(j) * v(j) !! where lambda(j) is its eigenvalue. !! The left eigenvector u(j) of A satisfies !! u(j)**H * A = lambda(j) * u(j)**H !! where u(j)**H denotes the conjugate-transpose of u(j). !! The computed eigenvectors are normalized to have Euclidean norm !! equal to 1 and largest component real. info ) ! -- lapack driver routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_sp, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments character, intent(in) :: jobvl, jobvr integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: lda, ldvl, ldvr, lwork, n ! Array Arguments real(sp), intent(inout) :: a(lda,*) real(sp), intent(out) :: vl(ldvl,*), vr(ldvr,*), wi(*), work(*), wr(*) ! ===================================================================== ! Local Scalars logical(lk) :: lquery, scalea, wantvl, wantvr character :: side integer(${ik}$) :: hswork, i, ibal, ierr, ihi, ilo, itau, iwrk, k, lwork_trevc, maxwrk, & minwrk, nout real(sp) :: anrm, bignum, cs, cscale, eps, r, scl, smlnum, sn ! Local Arrays logical(lk) :: select(1_${ik}$) real(sp) :: dum(1_${ik}$) ! Intrinsic Functions ! Executable Statements ! test the input arguments info = 0_${ik}$ lquery = ( lwork==-1_${ik}$ ) wantvl = stdlib_lsame( jobvl, 'V' ) wantvr = stdlib_lsame( jobvr, 'V' ) if( ( .not.wantvl ) .and. ( .not.stdlib_lsame( jobvl, 'N' ) ) ) then info = -1_${ik}$ else if( ( .not.wantvr ) .and. ( .not.stdlib_lsame( jobvr, 'N' ) ) ) then info = -2_${ik}$ else if( n<0_${ik}$ ) then info = -3_${ik}$ else if( lda<max( 1_${ik}$, n ) ) then info = -5_${ik}$ else if( ldvl<1_${ik}$ .or. ( wantvl .and. ldvl<n ) ) then info = -9_${ik}$ else if( ldvr<1_${ik}$ .or. ( wantvr .and. ldvr<n ) ) then info = -11_${ik}$ end if ! compute workspace ! (note: comments in the code beginning "workspace:" describe the ! minimal amount of workspace needed at that point in the code, ! as well as the preferred amount for good performance. ! nb refers to the optimal block size for the immediately ! following subroutine, as returned by stdlib${ii}$_ilaenv. ! hswork refers to the workspace preferred by stdlib${ii}$_shseqr, as ! calculated below. hswork is computed assuming ilo=1 and ihi=n, ! the worst case.) if( info==0_${ik}$ ) then if( n==0_${ik}$ ) then minwrk = 1_${ik}$ maxwrk = 1_${ik}$ else maxwrk = 2_${ik}$*n + n*stdlib${ii}$_ilaenv( 1_${ik}$, 'SGEHRD', ' ', n, 1_${ik}$, n, 0_${ik}$ ) if( wantvl ) then minwrk = 4_${ik}$*n maxwrk = max( maxwrk, 2_${ik}$*n + ( n - 1_${ik}$ )*stdlib${ii}$_ilaenv( 1_${ik}$,'SORGHR', ' ', n, 1_${ik}$, n,& -1_${ik}$ ) ) call stdlib${ii}$_shseqr( 'S', 'V', n, 1_${ik}$, n, a, lda, wr, wi, vl, ldvl,work, -1_${ik}$, & info ) hswork = int( work(1_${ik}$),KIND=${ik}$) maxwrk = max( maxwrk, n + 1_${ik}$, n + hswork ) call stdlib${ii}$_strevc3( 'L', 'B', select, n, a, lda,vl, ldvl, vr, ldvr, n, nout,& work, -1_${ik}$, ierr ) lwork_trevc = int( work(1_${ik}$),KIND=${ik}$) maxwrk = max( maxwrk, n + lwork_trevc ) maxwrk = max( maxwrk, 4_${ik}$*n ) else if( wantvr ) then minwrk = 4_${ik}$*n maxwrk = max( maxwrk, 2_${ik}$*n + ( n - 1_${ik}$ )*stdlib${ii}$_ilaenv( 1_${ik}$,'SORGHR', ' ', n, 1_${ik}$, n,& -1_${ik}$ ) ) call stdlib${ii}$_shseqr( 'S', 'V', n, 1_${ik}$, n, a, lda, wr, wi, vr, ldvr,work, -1_${ik}$, & info ) hswork = int( work(1_${ik}$),KIND=${ik}$) maxwrk = max( maxwrk, n + 1_${ik}$, n + hswork ) call stdlib${ii}$_strevc3( 'R', 'B', select, n, a, lda,vl, ldvl, vr, ldvr, n, nout,& work, -1_${ik}$, ierr ) lwork_trevc = int( work(1_${ik}$),KIND=${ik}$) maxwrk = max( maxwrk, n + lwork_trevc ) maxwrk = max( maxwrk, 4_${ik}$*n ) else minwrk = 3_${ik}$*n call stdlib${ii}$_shseqr( 'E', 'N', n, 1_${ik}$, n, a, lda, wr, wi, vr, ldvr,work, -1_${ik}$, & info ) hswork = int( work(1_${ik}$),KIND=${ik}$) maxwrk = max( maxwrk, n + 1_${ik}$, n + hswork ) end if maxwrk = max( maxwrk, minwrk ) end if work( 1_${ik}$ ) = maxwrk if( lwork<minwrk .and. .not.lquery ) then info = -13_${ik}$ end if end if if( info/=0_${ik}$ ) then call stdlib${ii}$_xerbla( 'SGEEV ', -info ) return else if( lquery ) then return end if ! quick return if possible if( n==0 )return ! get machine constants eps = stdlib${ii}$_slamch( 'P' ) smlnum = stdlib${ii}$_slamch( 'S' ) bignum = one / smlnum call stdlib${ii}$_slabad( smlnum, bignum ) smlnum = sqrt( smlnum ) / eps bignum = one / smlnum ! scale a if max element outside range [smlnum,bignum] anrm = stdlib${ii}$_slange( 'M', n, n, a, lda, dum ) scalea = .false. if( anrm>zero .and. anrm<smlnum ) then scalea = .true. cscale = smlnum else if( anrm>bignum ) then scalea = .true. cscale = bignum end if if( scalea )call stdlib${ii}$_slascl( 'G', 0_${ik}$, 0_${ik}$, anrm, cscale, n, n, a, lda, ierr ) ! balance the matrix ! (workspace: need n) ibal = 1_${ik}$ call stdlib${ii}$_sgebal( 'B', n, a, lda, ilo, ihi, work( ibal ), ierr ) ! reduce to upper hessenberg form ! (workspace: need 3*n, prefer 2*n+n*nb) itau = ibal + n iwrk = itau + n call stdlib${ii}$_sgehrd( n, ilo, ihi, a, lda, work( itau ), work( iwrk ),lwork-iwrk+1, ierr & ) if( wantvl ) then ! want left eigenvectors ! copy householder vectors to vl side = 'L' call stdlib${ii}$_slacpy( 'L', n, n, a, lda, vl, ldvl ) ! generate orthogonal matrix in vl ! (workspace: need 3*n-1, prefer 2*n+(n-1)*nb) call stdlib${ii}$_sorghr( n, ilo, ihi, vl, ldvl, work( itau ), work( iwrk ),lwork-iwrk+1, & ierr ) ! perform qr iteration, accumulating schur vectors in vl ! (workspace: need n+1, prefer n+hswork (see comments) ) iwrk = itau call stdlib${ii}$_shseqr( 'S', 'V', n, ilo, ihi, a, lda, wr, wi, vl, ldvl,work( iwrk ), & lwork-iwrk+1, info ) if( wantvr ) then ! want left and right eigenvectors ! copy schur vectors to vr side = 'B' call stdlib${ii}$_slacpy( 'F', n, n, vl, ldvl, vr, ldvr ) end if else if( wantvr ) then ! want right eigenvectors ! copy householder vectors to vr side = 'R' call stdlib${ii}$_slacpy( 'L', n, n, a, lda, vr, ldvr ) ! generate orthogonal matrix in vr ! (workspace: need 3*n-1, prefer 2*n+(n-1)*nb) call stdlib${ii}$_sorghr( n, ilo, ihi, vr, ldvr, work( itau ), work( iwrk ),lwork-iwrk+1, & ierr ) ! perform qr iteration, accumulating schur vectors in vr ! (workspace: need n+1, prefer n+hswork (see comments) ) iwrk = itau call stdlib${ii}$_shseqr( 'S', 'V', n, ilo, ihi, a, lda, wr, wi, vr, ldvr,work( iwrk ), & lwork-iwrk+1, info ) else ! compute eigenvalues only ! (workspace: need n+1, prefer n+hswork (see comments) ) iwrk = itau call stdlib${ii}$_shseqr( 'E', 'N', n, ilo, ihi, a, lda, wr, wi, vr, ldvr,work( iwrk ), & lwork-iwrk+1, info ) end if ! if info /= 0 from stdlib${ii}$_shseqr, then quit if( info/=0 )go to 50 if( wantvl .or. wantvr ) then ! compute left and/or right eigenvectors ! (workspace: need 4*n, prefer n + n + 2*n*nb) call stdlib${ii}$_strevc3( side, 'B', select, n, a, lda, vl, ldvl, vr, ldvr,n, nout, work(& iwrk ), lwork-iwrk+1, ierr ) end if if( wantvl ) then ! undo balancing of left eigenvectors ! (workspace: need n) call stdlib${ii}$_sgebak( 'B', 'L', n, ilo, ihi, work( ibal ), n, vl, ldvl,ierr ) ! normalize left eigenvectors and make largest component real do i = 1, n if( wi( i )==zero ) then scl = one / stdlib${ii}$_snrm2( n, vl( 1_${ik}$, i ), 1_${ik}$ ) call stdlib${ii}$_sscal( n, scl, vl( 1_${ik}$, i ), 1_${ik}$ ) else if( wi( i )>zero ) then scl = one / stdlib${ii}$_slapy2( stdlib${ii}$_snrm2( n, vl( 1_${ik}$, i ), 1_${ik}$ ),stdlib${ii}$_snrm2( n, & vl( 1_${ik}$, i+1 ), 1_${ik}$ ) ) call stdlib${ii}$_sscal( n, scl, vl( 1_${ik}$, i ), 1_${ik}$ ) call stdlib${ii}$_sscal( n, scl, vl( 1_${ik}$, i+1 ), 1_${ik}$ ) do k = 1, n work( iwrk+k-1 ) = vl( k, i )**2_${ik}$ + vl( k, i+1 )**2_${ik}$ end do k = stdlib${ii}$_isamax( n, work( iwrk ), 1_${ik}$ ) call stdlib${ii}$_slartg( vl( k, i ), vl( k, i+1 ), cs, sn, r ) call stdlib${ii}$_srot( n, vl( 1_${ik}$, i ), 1_${ik}$, vl( 1_${ik}$, i+1 ), 1_${ik}$, cs, sn ) vl( k, i+1 ) = zero end if end do end if if( wantvr ) then ! undo balancing of right eigenvectors ! (workspace: need n) call stdlib${ii}$_sgebak( 'B', 'R', n, ilo, ihi, work( ibal ), n, vr, ldvr,ierr ) ! normalize right eigenvectors and make largest component real do i = 1, n if( wi( i )==zero ) then scl = one / stdlib${ii}$_snrm2( n, vr( 1_${ik}$, i ), 1_${ik}$ ) call stdlib${ii}$_sscal( n, scl, vr( 1_${ik}$, i ), 1_${ik}$ ) else if( wi( i )>zero ) then scl = one / stdlib${ii}$_slapy2( stdlib${ii}$_snrm2( n, vr( 1_${ik}$, i ), 1_${ik}$ ),stdlib${ii}$_snrm2( n, & vr( 1_${ik}$, i+1 ), 1_${ik}$ ) ) call stdlib${ii}$_sscal( n, scl, vr( 1_${ik}$, i ), 1_${ik}$ ) call stdlib${ii}$_sscal( n, scl, vr( 1_${ik}$, i+1 ), 1_${ik}$ ) do k = 1, n work( iwrk+k-1 ) = vr( k, i )**2_${ik}$ + vr( k, i+1 )**2_${ik}$ end do k = stdlib${ii}$_isamax( n, work( iwrk ), 1_${ik}$ ) call stdlib${ii}$_slartg( vr( k, i ), vr( k, i+1 ), cs, sn, r ) call stdlib${ii}$_srot( n, vr( 1_${ik}$, i ), 1_${ik}$, vr( 1_${ik}$, i+1 ), 1_${ik}$, cs, sn ) vr( k, i+1 ) = zero end if end do end if ! undo scaling if necessary 50 continue if( scalea ) then call stdlib${ii}$_slascl( 'G', 0_${ik}$, 0_${ik}$, cscale, anrm, n-info, 1_${ik}$, wr( info+1 ),max( n-info, 1_${ik}$ & ), ierr ) call stdlib${ii}$_slascl( 'G', 0_${ik}$, 0_${ik}$, cscale, anrm, n-info, 1_${ik}$, wi( info+1 ),max( n-info, 1_${ik}$ & ), ierr ) if( info>0_${ik}$ ) then call stdlib${ii}$_slascl( 'G', 0_${ik}$, 0_${ik}$, cscale, anrm, ilo-1, 1_${ik}$, wr, n,ierr ) call stdlib${ii}$_slascl( 'G', 0_${ik}$, 0_${ik}$, cscale, anrm, ilo-1, 1_${ik}$, wi, n,ierr ) end if end if work( 1_${ik}$ ) = maxwrk return end subroutine stdlib${ii}$_sgeev module subroutine stdlib${ii}$_dgeev( jobvl, jobvr, n, a, lda, wr, wi, vl, ldvl, vr,ldvr, work, lwork, & !! DGEEV computes for an N-by-N real nonsymmetric matrix A, the !! eigenvalues and, optionally, the left and/or right eigenvectors. !! The right eigenvector v(j) of A satisfies !! A * v(j) = lambda(j) * v(j) !! where lambda(j) is its eigenvalue. !! The left eigenvector u(j) of A satisfies !! u(j)**H * A = lambda(j) * u(j)**H !! where u(j)**H denotes the conjugate-transpose of u(j). !! The computed eigenvectors are normalized to have Euclidean norm !! equal to 1 and largest component real. info ) ! -- lapack driver routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_dp, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments character, intent(in) :: jobvl, jobvr integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: lda, ldvl, ldvr, lwork, n ! Array Arguments real(dp), intent(inout) :: a(lda,*) real(dp), intent(out) :: vl(ldvl,*), vr(ldvr,*), wi(*), work(*), wr(*) ! ===================================================================== ! Local Scalars logical(lk) :: lquery, scalea, wantvl, wantvr character :: side integer(${ik}$) :: hswork, i, ibal, ierr, ihi, ilo, itau, iwrk, k, lwork_trevc, maxwrk, & minwrk, nout real(dp) :: anrm, bignum, cs, cscale, eps, r, scl, smlnum, sn ! Local Arrays logical(lk) :: select(1_${ik}$) real(dp) :: dum(1_${ik}$) ! Intrinsic Functions ! Executable Statements ! test the input arguments info = 0_${ik}$ lquery = ( lwork==-1_${ik}$ ) wantvl = stdlib_lsame( jobvl, 'V' ) wantvr = stdlib_lsame( jobvr, 'V' ) if( ( .not.wantvl ) .and. ( .not.stdlib_lsame( jobvl, 'N' ) ) ) then info = -1_${ik}$ else if( ( .not.wantvr ) .and. ( .not.stdlib_lsame( jobvr, 'N' ) ) ) then info = -2_${ik}$ else if( n<0_${ik}$ ) then info = -3_${ik}$ else if( lda<max( 1_${ik}$, n ) ) then info = -5_${ik}$ else if( ldvl<1_${ik}$ .or. ( wantvl .and. ldvl<n ) ) then info = -9_${ik}$ else if( ldvr<1_${ik}$ .or. ( wantvr .and. ldvr<n ) ) then info = -11_${ik}$ end if ! compute workspace ! (note: comments in the code beginning "workspace:" describe the ! minimal amount of workspace needed at that point in the code, ! as well as the preferred amount for good performance. ! nb refers to the optimal block size for the immediately ! following subroutine, as returned by stdlib${ii}$_ilaenv. ! hswork refers to the workspace preferred by stdlib${ii}$_dhseqr, as ! calculated below. hswork is computed assuming ilo=1 and ihi=n, ! the worst case.) if( info==0_${ik}$ ) then if( n==0_${ik}$ ) then minwrk = 1_${ik}$ maxwrk = 1_${ik}$ else maxwrk = 2_${ik}$*n + n*stdlib${ii}$_ilaenv( 1_${ik}$, 'DGEHRD', ' ', n, 1_${ik}$, n, 0_${ik}$ ) if( wantvl ) then minwrk = 4_${ik}$*n maxwrk = max( maxwrk, 2_${ik}$*n + ( n - 1_${ik}$ )*stdlib${ii}$_ilaenv( 1_${ik}$,'DORGHR', ' ', n, 1_${ik}$, n,& -1_${ik}$ ) ) call stdlib${ii}$_dhseqr( 'S', 'V', n, 1_${ik}$, n, a, lda, wr, wi, vl, ldvl,work, -1_${ik}$, & info ) hswork = int( work(1_${ik}$),KIND=${ik}$) maxwrk = max( maxwrk, n + 1_${ik}$, n + hswork ) call stdlib${ii}$_dtrevc3( 'L', 'B', select, n, a, lda,vl, ldvl, vr, ldvr, n, nout,& work, -1_${ik}$, ierr ) lwork_trevc = int( work(1_${ik}$),KIND=${ik}$) maxwrk = max( maxwrk, n + lwork_trevc ) maxwrk = max( maxwrk, 4_${ik}$*n ) else if( wantvr ) then minwrk = 4_${ik}$*n maxwrk = max( maxwrk, 2_${ik}$*n + ( n - 1_${ik}$ )*stdlib${ii}$_ilaenv( 1_${ik}$,'DORGHR', ' ', n, 1_${ik}$, n,& -1_${ik}$ ) ) call stdlib${ii}$_dhseqr( 'S', 'V', n, 1_${ik}$, n, a, lda, wr, wi, vr, ldvr,work, -1_${ik}$, & info ) hswork = int( work(1_${ik}$),KIND=${ik}$) maxwrk = max( maxwrk, n + 1_${ik}$, n + hswork ) call stdlib${ii}$_dtrevc3( 'R', 'B', select, n, a, lda,vl, ldvl, vr, ldvr, n, nout,& work, -1_${ik}$, ierr ) lwork_trevc = int( work(1_${ik}$),KIND=${ik}$) maxwrk = max( maxwrk, n + lwork_trevc ) maxwrk = max( maxwrk, 4_${ik}$*n ) else minwrk = 3_${ik}$*n call stdlib${ii}$_dhseqr( 'E', 'N', n, 1_${ik}$, n, a, lda, wr, wi, vr, ldvr,work, -1_${ik}$, & info ) hswork = int( work(1_${ik}$),KIND=${ik}$) maxwrk = max( maxwrk, n + 1_${ik}$, n + hswork ) end if maxwrk = max( maxwrk, minwrk ) end if work( 1_${ik}$ ) = maxwrk if( lwork<minwrk .and. .not.lquery ) then info = -13_${ik}$ end if end if if( info/=0_${ik}$ ) then call stdlib${ii}$_xerbla( 'DGEEV ', -info ) return else if( lquery ) then return end if ! quick return if possible if( n==0 )return ! get machine constants eps = stdlib${ii}$_dlamch( 'P' ) smlnum = stdlib${ii}$_dlamch( 'S' ) bignum = one / smlnum call stdlib${ii}$_dlabad( smlnum, bignum ) smlnum = sqrt( smlnum ) / eps bignum = one / smlnum ! scale a if max element outside range [smlnum,bignum] anrm = stdlib${ii}$_dlange( 'M', n, n, a, lda, dum ) scalea = .false. if( anrm>zero .and. anrm<smlnum ) then scalea = .true. cscale = smlnum else if( anrm>bignum ) then scalea = .true. cscale = bignum end if if( scalea )call stdlib${ii}$_dlascl( 'G', 0_${ik}$, 0_${ik}$, anrm, cscale, n, n, a, lda, ierr ) ! balance the matrix ! (workspace: need n) ibal = 1_${ik}$ call stdlib${ii}$_dgebal( 'B', n, a, lda, ilo, ihi, work( ibal ), ierr ) ! reduce to upper hessenberg form ! (workspace: need 3*n, prefer 2*n+n*nb) itau = ibal + n iwrk = itau + n call stdlib${ii}$_dgehrd( n, ilo, ihi, a, lda, work( itau ), work( iwrk ),lwork-iwrk+1, ierr & ) if( wantvl ) then ! want left eigenvectors ! copy householder vectors to vl side = 'L' call stdlib${ii}$_dlacpy( 'L', n, n, a, lda, vl, ldvl ) ! generate orthogonal matrix in vl ! (workspace: need 3*n-1, prefer 2*n+(n-1)*nb) call stdlib${ii}$_dorghr( n, ilo, ihi, vl, ldvl, work( itau ), work( iwrk ),lwork-iwrk+1, & ierr ) ! perform qr iteration, accumulating schur vectors in vl ! (workspace: need n+1, prefer n+hswork (see comments) ) iwrk = itau call stdlib${ii}$_dhseqr( 'S', 'V', n, ilo, ihi, a, lda, wr, wi, vl, ldvl,work( iwrk ), & lwork-iwrk+1, info ) if( wantvr ) then ! want left and right eigenvectors ! copy schur vectors to vr side = 'B' call stdlib${ii}$_dlacpy( 'F', n, n, vl, ldvl, vr, ldvr ) end if else if( wantvr ) then ! want right eigenvectors ! copy householder vectors to vr side = 'R' call stdlib${ii}$_dlacpy( 'L', n, n, a, lda, vr, ldvr ) ! generate orthogonal matrix in vr ! (workspace: need 3*n-1, prefer 2*n+(n-1)*nb) call stdlib${ii}$_dorghr( n, ilo, ihi, vr, ldvr, work( itau ), work( iwrk ),lwork-iwrk+1, & ierr ) ! perform qr iteration, accumulating schur vectors in vr ! (workspace: need n+1, prefer n+hswork (see comments) ) iwrk = itau call stdlib${ii}$_dhseqr( 'S', 'V', n, ilo, ihi, a, lda, wr, wi, vr, ldvr,work( iwrk ), & lwork-iwrk+1, info ) else ! compute eigenvalues only ! (workspace: need n+1, prefer n+hswork (see comments) ) iwrk = itau call stdlib${ii}$_dhseqr( 'E', 'N', n, ilo, ihi, a, lda, wr, wi, vr, ldvr,work( iwrk ), & lwork-iwrk+1, info ) end if ! if info /= 0 from stdlib${ii}$_dhseqr, then quit if( info/=0 )go to 50 if( wantvl .or. wantvr ) then ! compute left and/or right eigenvectors ! (workspace: need 4*n, prefer n + n + 2*n*nb) call stdlib${ii}$_dtrevc3( side, 'B', select, n, a, lda, vl, ldvl, vr, ldvr,n, nout, work(& iwrk ), lwork-iwrk+1, ierr ) end if if( wantvl ) then ! undo balancing of left eigenvectors ! (workspace: need n) call stdlib${ii}$_dgebak( 'B', 'L', n, ilo, ihi, work( ibal ), n, vl, ldvl,ierr ) ! normalize left eigenvectors and make largest component real do i = 1, n if( wi( i )==zero ) then scl = one / stdlib${ii}$_dnrm2( n, vl( 1_${ik}$, i ), 1_${ik}$ ) call stdlib${ii}$_dscal( n, scl, vl( 1_${ik}$, i ), 1_${ik}$ ) else if( wi( i )>zero ) then scl = one / stdlib${ii}$_dlapy2( stdlib${ii}$_dnrm2( n, vl( 1_${ik}$, i ), 1_${ik}$ ),stdlib${ii}$_dnrm2( n, & vl( 1_${ik}$, i+1 ), 1_${ik}$ ) ) call stdlib${ii}$_dscal( n, scl, vl( 1_${ik}$, i ), 1_${ik}$ ) call stdlib${ii}$_dscal( n, scl, vl( 1_${ik}$, i+1 ), 1_${ik}$ ) do k = 1, n work( iwrk+k-1 ) = vl( k, i )**2_${ik}$ + vl( k, i+1 )**2_${ik}$ end do k = stdlib${ii}$_idamax( n, work( iwrk ), 1_${ik}$ ) call stdlib${ii}$_dlartg( vl( k, i ), vl( k, i+1 ), cs, sn, r ) call stdlib${ii}$_drot( n, vl( 1_${ik}$, i ), 1_${ik}$, vl( 1_${ik}$, i+1 ), 1_${ik}$, cs, sn ) vl( k, i+1 ) = zero end if end do end if if( wantvr ) then ! undo balancing of right eigenvectors ! (workspace: need n) call stdlib${ii}$_dgebak( 'B', 'R', n, ilo, ihi, work( ibal ), n, vr, ldvr,ierr ) ! normalize right eigenvectors and make largest component real do i = 1, n if( wi( i )==zero ) then scl = one / stdlib${ii}$_dnrm2( n, vr( 1_${ik}$, i ), 1_${ik}$ ) call stdlib${ii}$_dscal( n, scl, vr( 1_${ik}$, i ), 1_${ik}$ ) else if( wi( i )>zero ) then scl = one / stdlib${ii}$_dlapy2( stdlib${ii}$_dnrm2( n, vr( 1_${ik}$, i ), 1_${ik}$ ),stdlib${ii}$_dnrm2( n, & vr( 1_${ik}$, i+1 ), 1_${ik}$ ) ) call stdlib${ii}$_dscal( n, scl, vr( 1_${ik}$, i ), 1_${ik}$ ) call stdlib${ii}$_dscal( n, scl, vr( 1_${ik}$, i+1 ), 1_${ik}$ ) do k = 1, n work( iwrk+k-1 ) = vr( k, i )**2_${ik}$ + vr( k, i+1 )**2_${ik}$ end do k = stdlib${ii}$_idamax( n, work( iwrk ), 1_${ik}$ ) call stdlib${ii}$_dlartg( vr( k, i ), vr( k, i+1 ), cs, sn, r ) call stdlib${ii}$_drot( n, vr( 1_${ik}$, i ), 1_${ik}$, vr( 1_${ik}$, i+1 ), 1_${ik}$, cs, sn ) vr( k, i+1 ) = zero end if end do end if ! undo scaling if necessary 50 continue if( scalea ) then call stdlib${ii}$_dlascl( 'G', 0_${ik}$, 0_${ik}$, cscale, anrm, n-info, 1_${ik}$, wr( info+1 ),max( n-info, 1_${ik}$ & ), ierr ) call stdlib${ii}$_dlascl( 'G', 0_${ik}$, 0_${ik}$, cscale, anrm, n-info, 1_${ik}$, wi( info+1 ),max( n-info, 1_${ik}$ & ), ierr ) if( info>0_${ik}$ ) then call stdlib${ii}$_dlascl( 'G', 0_${ik}$, 0_${ik}$, cscale, anrm, ilo-1, 1_${ik}$, wr, n,ierr ) call stdlib${ii}$_dlascl( 'G', 0_${ik}$, 0_${ik}$, cscale, anrm, ilo-1, 1_${ik}$, wi, n,ierr ) end if end if work( 1_${ik}$ ) = maxwrk return end subroutine stdlib${ii}$_dgeev #:for rk,rt,ri in REAL_KINDS_TYPES #:if not rk in ["sp","dp"] module subroutine stdlib${ii}$_${ri}$geev( jobvl, jobvr, n, a, lda, wr, wi, vl, ldvl, vr,ldvr, work, lwork, & !! DGEEV: computes for an N-by-N real nonsymmetric matrix A, the !! eigenvalues and, optionally, the left and/or right eigenvectors. !! The right eigenvector v(j) of A satisfies !! A * v(j) = lambda(j) * v(j) !! where lambda(j) is its eigenvalue. !! The left eigenvector u(j) of A satisfies !! u(j)**H * A = lambda(j) * u(j)**H !! where u(j)**H denotes the conjugate-transpose of u(j). !! The computed eigenvectors are normalized to have Euclidean norm !! equal to 1 and largest component real. info ) ! -- lapack driver routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_${rk}$, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments character, intent(in) :: jobvl, jobvr integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: lda, ldvl, ldvr, lwork, n ! Array Arguments real(${rk}$), intent(inout) :: a(lda,*) real(${rk}$), intent(out) :: vl(ldvl,*), vr(ldvr,*), wi(*), work(*), wr(*) ! ===================================================================== ! Local Scalars logical(lk) :: lquery, scalea, wantvl, wantvr character :: side integer(${ik}$) :: hswork, i, ibal, ierr, ihi, ilo, itau, iwrk, k, lwork_trevc, maxwrk, & minwrk, nout real(${rk}$) :: anrm, bignum, cs, cscale, eps, r, scl, smlnum, sn ! Local Arrays logical(lk) :: select(1_${ik}$) real(${rk}$) :: dum(1_${ik}$) ! Intrinsic Functions ! Executable Statements ! test the input arguments info = 0_${ik}$ lquery = ( lwork==-1_${ik}$ ) wantvl = stdlib_lsame( jobvl, 'V' ) wantvr = stdlib_lsame( jobvr, 'V' ) if( ( .not.wantvl ) .and. ( .not.stdlib_lsame( jobvl, 'N' ) ) ) then info = -1_${ik}$ else if( ( .not.wantvr ) .and. ( .not.stdlib_lsame( jobvr, 'N' ) ) ) then info = -2_${ik}$ else if( n<0_${ik}$ ) then info = -3_${ik}$ else if( lda<max( 1_${ik}$, n ) ) then info = -5_${ik}$ else if( ldvl<1_${ik}$ .or. ( wantvl .and. ldvl<n ) ) then info = -9_${ik}$ else if( ldvr<1_${ik}$ .or. ( wantvr .and. ldvr<n ) ) then info = -11_${ik}$ end if ! compute workspace ! (note: comments in the code beginning "workspace:" describe the ! minimal amount of workspace needed at that point in the code, ! as well as the preferred amount for good performance. ! nb refers to the optimal block size for the immediately ! following subroutine, as returned by stdlib${ii}$_ilaenv. ! hswork refers to the workspace preferred by stdlib${ii}$_${ri}$hseqr, as ! calculated below. hswork is computed assuming ilo=1 and ihi=n, ! the worst case.) if( info==0_${ik}$ ) then if( n==0_${ik}$ ) then minwrk = 1_${ik}$ maxwrk = 1_${ik}$ else maxwrk = 2_${ik}$*n + n*stdlib${ii}$_ilaenv( 1_${ik}$, 'DGEHRD', ' ', n, 1_${ik}$, n, 0_${ik}$ ) if( wantvl ) then minwrk = 4_${ik}$*n maxwrk = max( maxwrk, 2_${ik}$*n + ( n - 1_${ik}$ )*stdlib${ii}$_ilaenv( 1_${ik}$,'DORGHR', ' ', n, 1_${ik}$, n,& -1_${ik}$ ) ) call stdlib${ii}$_${ri}$hseqr( 'S', 'V', n, 1_${ik}$, n, a, lda, wr, wi, vl, ldvl,work, -1_${ik}$, & info ) hswork = int( work(1_${ik}$),KIND=${ik}$) maxwrk = max( maxwrk, n + 1_${ik}$, n + hswork ) call stdlib${ii}$_${ri}$trevc3( 'L', 'B', select, n, a, lda,vl, ldvl, vr, ldvr, n, nout,& work, -1_${ik}$, ierr ) lwork_trevc = int( work(1_${ik}$),KIND=${ik}$) maxwrk = max( maxwrk, n + lwork_trevc ) maxwrk = max( maxwrk, 4_${ik}$*n ) else if( wantvr ) then minwrk = 4_${ik}$*n maxwrk = max( maxwrk, 2_${ik}$*n + ( n - 1_${ik}$ )*stdlib${ii}$_ilaenv( 1_${ik}$,'DORGHR', ' ', n, 1_${ik}$, n,& -1_${ik}$ ) ) call stdlib${ii}$_${ri}$hseqr( 'S', 'V', n, 1_${ik}$, n, a, lda, wr, wi, vr, ldvr,work, -1_${ik}$, & info ) hswork = int( work(1_${ik}$),KIND=${ik}$) maxwrk = max( maxwrk, n + 1_${ik}$, n + hswork ) call stdlib${ii}$_${ri}$trevc3( 'R', 'B', select, n, a, lda,vl, ldvl, vr, ldvr, n, nout,& work, -1_${ik}$, ierr ) lwork_trevc = int( work(1_${ik}$),KIND=${ik}$) maxwrk = max( maxwrk, n + lwork_trevc ) maxwrk = max( maxwrk, 4_${ik}$*n ) else minwrk = 3_${ik}$*n call stdlib${ii}$_${ri}$hseqr( 'E', 'N', n, 1_${ik}$, n, a, lda, wr, wi, vr, ldvr,work, -1_${ik}$, & info ) hswork = int( work(1_${ik}$),KIND=${ik}$) maxwrk = max( maxwrk, n + 1_${ik}$, n + hswork ) end if maxwrk = max( maxwrk, minwrk ) end if work( 1_${ik}$ ) = maxwrk if( lwork<minwrk .and. .not.lquery ) then info = -13_${ik}$ end if end if if( info/=0_${ik}$ ) then call stdlib${ii}$_xerbla( 'DGEEV ', -info ) return else if( lquery ) then return end if ! quick return if possible if( n==0 )return ! get machine constants eps = stdlib${ii}$_${ri}$lamch( 'P' ) smlnum = stdlib${ii}$_${ri}$lamch( 'S' ) bignum = one / smlnum call stdlib${ii}$_${ri}$labad( smlnum, bignum ) smlnum = sqrt( smlnum ) / eps bignum = one / smlnum ! scale a if max element outside range [smlnum,bignum] anrm = stdlib${ii}$_${ri}$lange( 'M', n, n, a, lda, dum ) scalea = .false. if( anrm>zero .and. anrm<smlnum ) then scalea = .true. cscale = smlnum else if( anrm>bignum ) then scalea = .true. cscale = bignum end if if( scalea )call stdlib${ii}$_${ri}$lascl( 'G', 0_${ik}$, 0_${ik}$, anrm, cscale, n, n, a, lda, ierr ) ! balance the matrix ! (workspace: need n) ibal = 1_${ik}$ call stdlib${ii}$_${ri}$gebal( 'B', n, a, lda, ilo, ihi, work( ibal ), ierr ) ! reduce to upper hessenberg form ! (workspace: need 3*n, prefer 2*n+n*nb) itau = ibal + n iwrk = itau + n call stdlib${ii}$_${ri}$gehrd( n, ilo, ihi, a, lda, work( itau ), work( iwrk ),lwork-iwrk+1, ierr & ) if( wantvl ) then ! want left eigenvectors ! copy householder vectors to vl side = 'L' call stdlib${ii}$_${ri}$lacpy( 'L', n, n, a, lda, vl, ldvl ) ! generate orthogonal matrix in vl ! (workspace: need 3*n-1, prefer 2*n+(n-1)*nb) call stdlib${ii}$_${ri}$orghr( n, ilo, ihi, vl, ldvl, work( itau ), work( iwrk ),lwork-iwrk+1, & ierr ) ! perform qr iteration, accumulating schur vectors in vl ! (workspace: need n+1, prefer n+hswork (see comments) ) iwrk = itau call stdlib${ii}$_${ri}$hseqr( 'S', 'V', n, ilo, ihi, a, lda, wr, wi, vl, ldvl,work( iwrk ), & lwork-iwrk+1, info ) if( wantvr ) then ! want left and right eigenvectors ! copy schur vectors to vr side = 'B' call stdlib${ii}$_${ri}$lacpy( 'F', n, n, vl, ldvl, vr, ldvr ) end if else if( wantvr ) then ! want right eigenvectors ! copy householder vectors to vr side = 'R' call stdlib${ii}$_${ri}$lacpy( 'L', n, n, a, lda, vr, ldvr ) ! generate orthogonal matrix in vr ! (workspace: need 3*n-1, prefer 2*n+(n-1)*nb) call stdlib${ii}$_${ri}$orghr( n, ilo, ihi, vr, ldvr, work( itau ), work( iwrk ),lwork-iwrk+1, & ierr ) ! perform qr iteration, accumulating schur vectors in vr ! (workspace: need n+1, prefer n+hswork (see comments) ) iwrk = itau call stdlib${ii}$_${ri}$hseqr( 'S', 'V', n, ilo, ihi, a, lda, wr, wi, vr, ldvr,work( iwrk ), & lwork-iwrk+1, info ) else ! compute eigenvalues only ! (workspace: need n+1, prefer n+hswork (see comments) ) iwrk = itau call stdlib${ii}$_${ri}$hseqr( 'E', 'N', n, ilo, ihi, a, lda, wr, wi, vr, ldvr,work( iwrk ), & lwork-iwrk+1, info ) end if ! if info /= 0 from stdlib${ii}$_${ri}$hseqr, then quit if( info/=0 )go to 50 if( wantvl .or. wantvr ) then ! compute left and/or right eigenvectors ! (workspace: need 4*n, prefer n + n + 2*n*nb) call stdlib${ii}$_${ri}$trevc3( side, 'B', select, n, a, lda, vl, ldvl, vr, ldvr,n, nout, work(& iwrk ), lwork-iwrk+1, ierr ) end if if( wantvl ) then ! undo balancing of left eigenvectors ! (workspace: need n) call stdlib${ii}$_${ri}$gebak( 'B', 'L', n, ilo, ihi, work( ibal ), n, vl, ldvl,ierr ) ! normalize left eigenvectors and make largest component real do i = 1, n if( wi( i )==zero ) then scl = one / stdlib${ii}$_${ri}$nrm2( n, vl( 1_${ik}$, i ), 1_${ik}$ ) call stdlib${ii}$_${ri}$scal( n, scl, vl( 1_${ik}$, i ), 1_${ik}$ ) else if( wi( i )>zero ) then scl = one / stdlib${ii}$_${ri}$lapy2( stdlib${ii}$_${ri}$nrm2( n, vl( 1_${ik}$, i ), 1_${ik}$ ),stdlib${ii}$_${ri}$nrm2( n, & vl( 1_${ik}$, i+1 ), 1_${ik}$ ) ) call stdlib${ii}$_${ri}$scal( n, scl, vl( 1_${ik}$, i ), 1_${ik}$ ) call stdlib${ii}$_${ri}$scal( n, scl, vl( 1_${ik}$, i+1 ), 1_${ik}$ ) do k = 1, n work( iwrk+k-1 ) = vl( k, i )**2_${ik}$ + vl( k, i+1 )**2_${ik}$ end do k = stdlib${ii}$_i${ri}$amax( n, work( iwrk ), 1_${ik}$ ) call stdlib${ii}$_${ri}$lartg( vl( k, i ), vl( k, i+1 ), cs, sn, r ) call stdlib${ii}$_${ri}$rot( n, vl( 1_${ik}$, i ), 1_${ik}$, vl( 1_${ik}$, i+1 ), 1_${ik}$, cs, sn ) vl( k, i+1 ) = zero end if end do end if if( wantvr ) then ! undo balancing of right eigenvectors ! (workspace: need n) call stdlib${ii}$_${ri}$gebak( 'B', 'R', n, ilo, ihi, work( ibal ), n, vr, ldvr,ierr ) ! normalize right eigenvectors and make largest component real do i = 1, n if( wi( i )==zero ) then scl = one / stdlib${ii}$_${ri}$nrm2( n, vr( 1_${ik}$, i ), 1_${ik}$ ) call stdlib${ii}$_${ri}$scal( n, scl, vr( 1_${ik}$, i ), 1_${ik}$ ) else if( wi( i )>zero ) then scl = one / stdlib${ii}$_${ri}$lapy2( stdlib${ii}$_${ri}$nrm2( n, vr( 1_${ik}$, i ), 1_${ik}$ ),stdlib${ii}$_${ri}$nrm2( n, & vr( 1_${ik}$, i+1 ), 1_${ik}$ ) ) call stdlib${ii}$_${ri}$scal( n, scl, vr( 1_${ik}$, i ), 1_${ik}$ ) call stdlib${ii}$_${ri}$scal( n, scl, vr( 1_${ik}$, i+1 ), 1_${ik}$ ) do k = 1, n work( iwrk+k-1 ) = vr( k, i )**2_${ik}$ + vr( k, i+1 )**2_${ik}$ end do k = stdlib${ii}$_i${ri}$amax( n, work( iwrk ), 1_${ik}$ ) call stdlib${ii}$_${ri}$lartg( vr( k, i ), vr( k, i+1 ), cs, sn, r ) call stdlib${ii}$_${ri}$rot( n, vr( 1_${ik}$, i ), 1_${ik}$, vr( 1_${ik}$, i+1 ), 1_${ik}$, cs, sn ) vr( k, i+1 ) = zero end if end do end if ! undo scaling if necessary 50 continue if( scalea ) then call stdlib${ii}$_${ri}$lascl( 'G', 0_${ik}$, 0_${ik}$, cscale, anrm, n-info, 1_${ik}$, wr( info+1 ),max( n-info, 1_${ik}$ & ), ierr ) call stdlib${ii}$_${ri}$lascl( 'G', 0_${ik}$, 0_${ik}$, cscale, anrm, n-info, 1_${ik}$, wi( info+1 ),max( n-info, 1_${ik}$ & ), ierr ) if( info>0_${ik}$ ) then call stdlib${ii}$_${ri}$lascl( 'G', 0_${ik}$, 0_${ik}$, cscale, anrm, ilo-1, 1_${ik}$, wr, n,ierr ) call stdlib${ii}$_${ri}$lascl( 'G', 0_${ik}$, 0_${ik}$, cscale, anrm, ilo-1, 1_${ik}$, wi, n,ierr ) end if end if work( 1_${ik}$ ) = maxwrk return end subroutine stdlib${ii}$_${ri}$geev #:endif #:endfor module subroutine stdlib${ii}$_cgeev( jobvl, jobvr, n, a, lda, w, vl, ldvl, vr, ldvr,work, lwork, rwork, & !! CGEEV computes for an N-by-N complex nonsymmetric matrix A, the !! eigenvalues and, optionally, the left and/or right eigenvectors. !! The right eigenvector v(j) of A satisfies !! A * v(j) = lambda(j) * v(j) !! where lambda(j) is its eigenvalue. !! The left eigenvector u(j) of A satisfies !! u(j)**H * A = lambda(j) * u(j)**H !! where u(j)**H denotes the conjugate transpose of u(j). !! The computed eigenvectors are normalized to have Euclidean norm !! equal to 1 and largest component real. info ) ! -- lapack driver routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_sp, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments character, intent(in) :: jobvl, jobvr integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: lda, ldvl, ldvr, lwork, n ! Array Arguments real(sp), intent(out) :: rwork(*) complex(sp), intent(inout) :: a(lda,*) complex(sp), intent(out) :: vl(ldvl,*), vr(ldvr,*), w(*), work(*) ! ===================================================================== ! Local Scalars logical(lk) :: lquery, scalea, wantvl, wantvr character :: side integer(${ik}$) :: hswork, i, ibal, ierr, ihi, ilo, irwork, itau, iwrk, k, lwork_trevc, & maxwrk, minwrk, nout real(sp) :: anrm, bignum, cscale, eps, scl, smlnum complex(sp) :: tmp ! Local Arrays logical(lk) :: select(1_${ik}$) real(sp) :: dum(1_${ik}$) ! Intrinsic Functions ! Executable Statements ! test the input arguments info = 0_${ik}$ lquery = ( lwork==-1_${ik}$ ) wantvl = stdlib_lsame( jobvl, 'V' ) wantvr = stdlib_lsame( jobvr, 'V' ) if( ( .not.wantvl ) .and. ( .not.stdlib_lsame( jobvl, 'N' ) ) ) then info = -1_${ik}$ else if( ( .not.wantvr ) .and. ( .not.stdlib_lsame( jobvr, 'N' ) ) ) then info = -2_${ik}$ else if( n<0_${ik}$ ) then info = -3_${ik}$ else if( lda<max( 1_${ik}$, n ) ) then info = -5_${ik}$ else if( ldvl<1_${ik}$ .or. ( wantvl .and. ldvl<n ) ) then info = -8_${ik}$ else if( ldvr<1_${ik}$ .or. ( wantvr .and. ldvr<n ) ) then info = -10_${ik}$ end if ! compute workspace ! (note: comments in the code beginning "workspace:" describe the ! minimal amount of workspace needed at that point in the code, ! as well as the preferred amount for good performance. ! cworkspace refers to complex workspace, and rworkspace to real ! workspace. nb refers to the optimal block size for the ! immediately following subroutine, as returned by stdlib${ii}$_ilaenv. ! hswork refers to the workspace preferred by stdlib${ii}$_chseqr, as ! calculated below. hswork is computed assuming ilo=1 and ihi=n, ! the worst case.) if( info==0_${ik}$ ) then if( n==0_${ik}$ ) then minwrk = 1_${ik}$ maxwrk = 1_${ik}$ else maxwrk = n + n*stdlib${ii}$_ilaenv( 1_${ik}$, 'CGEHRD', ' ', n, 1_${ik}$, n, 0_${ik}$ ) minwrk = 2_${ik}$*n if( wantvl ) then maxwrk = max( maxwrk, n + ( n - 1_${ik}$ )*stdlib${ii}$_ilaenv( 1_${ik}$, 'CUNGHR',' ', n, 1_${ik}$, n, -& 1_${ik}$ ) ) call stdlib${ii}$_ctrevc3( 'L', 'B', select, n, a, lda,vl, ldvl, vr, ldvr,n, nout, & work, -1_${ik}$, rwork, -1_${ik}$, ierr ) lwork_trevc = int( work(1_${ik}$),KIND=${ik}$) maxwrk = max( maxwrk, n + lwork_trevc ) call stdlib${ii}$_chseqr( 'S', 'V', n, 1_${ik}$, n, a, lda, w, vl, ldvl,work, -1_${ik}$, info ) else if( wantvr ) then maxwrk = max( maxwrk, n + ( n - 1_${ik}$ )*stdlib${ii}$_ilaenv( 1_${ik}$, 'CUNGHR',' ', n, 1_${ik}$, n, -& 1_${ik}$ ) ) call stdlib${ii}$_ctrevc3( 'R', 'B', select, n, a, lda,vl, ldvl, vr, ldvr,n, nout, & work, -1_${ik}$, rwork, -1_${ik}$, ierr ) lwork_trevc = int( work(1_${ik}$),KIND=${ik}$) maxwrk = max( maxwrk, n + lwork_trevc ) call stdlib${ii}$_chseqr( 'S', 'V', n, 1_${ik}$, n, a, lda, w, vr, ldvr,work, -1_${ik}$, info ) else call stdlib${ii}$_chseqr( 'E', 'N', n, 1_${ik}$, n, a, lda, w, vr, ldvr,work, -1_${ik}$, info ) end if hswork = int( work(1_${ik}$),KIND=${ik}$) maxwrk = max( maxwrk, hswork, minwrk ) end if work( 1_${ik}$ ) = maxwrk if( lwork<minwrk .and. .not.lquery ) then info = -12_${ik}$ end if end if if( info/=0_${ik}$ ) then call stdlib${ii}$_xerbla( 'CGEEV ', -info ) return else if( lquery ) then return end if ! quick return if possible if( n==0 )return ! get machine constants eps = stdlib${ii}$_slamch( 'P' ) smlnum = stdlib${ii}$_slamch( 'S' ) bignum = one / smlnum call stdlib${ii}$_slabad( smlnum, bignum ) smlnum = sqrt( smlnum ) / eps bignum = one / smlnum ! scale a if max element outside range [smlnum,bignum] anrm = stdlib${ii}$_clange( 'M', n, n, a, lda, dum ) scalea = .false. if( anrm>zero .and. anrm<smlnum ) then scalea = .true. cscale = smlnum else if( anrm>bignum ) then scalea = .true. cscale = bignum end if if( scalea )call stdlib${ii}$_clascl( 'G', 0_${ik}$, 0_${ik}$, anrm, cscale, n, n, a, lda, ierr ) ! balance the matrix ! (cworkspace: none) ! (rworkspace: need n) ibal = 1_${ik}$ call stdlib${ii}$_cgebal( 'B', n, a, lda, ilo, ihi, rwork( ibal ), ierr ) ! reduce to upper hessenberg form ! (cworkspace: need 2*n, prefer n+n*nb) ! (rworkspace: none) itau = 1_${ik}$ iwrk = itau + n call stdlib${ii}$_cgehrd( n, ilo, ihi, a, lda, work( itau ), work( iwrk ),lwork-iwrk+1, ierr & ) if( wantvl ) then ! want left eigenvectors ! copy householder vectors to vl side = 'L' call stdlib${ii}$_clacpy( 'L', n, n, a, lda, vl, ldvl ) ! generate unitary matrix in vl ! (cworkspace: need 2*n-1, prefer n+(n-1)*nb) ! (rworkspace: none) call stdlib${ii}$_cunghr( n, ilo, ihi, vl, ldvl, work( itau ), work( iwrk ),lwork-iwrk+1, & ierr ) ! perform qr iteration, accumulating schur vectors in vl ! (cworkspace: need 1, prefer hswork (see comments) ) ! (rworkspace: none) iwrk = itau call stdlib${ii}$_chseqr( 'S', 'V', n, ilo, ihi, a, lda, w, vl, ldvl,work( iwrk ), lwork-& iwrk+1, info ) if( wantvr ) then ! want left and right eigenvectors ! copy schur vectors to vr side = 'B' call stdlib${ii}$_clacpy( 'F', n, n, vl, ldvl, vr, ldvr ) end if else if( wantvr ) then ! want right eigenvectors ! copy householder vectors to vr side = 'R' call stdlib${ii}$_clacpy( 'L', n, n, a, lda, vr, ldvr ) ! generate unitary matrix in vr ! (cworkspace: need 2*n-1, prefer n+(n-1)*nb) ! (rworkspace: none) call stdlib${ii}$_cunghr( n, ilo, ihi, vr, ldvr, work( itau ), work( iwrk ),lwork-iwrk+1, & ierr ) ! perform qr iteration, accumulating schur vectors in vr ! (cworkspace: need 1, prefer hswork (see comments) ) ! (rworkspace: none) iwrk = itau call stdlib${ii}$_chseqr( 'S', 'V', n, ilo, ihi, a, lda, w, vr, ldvr,work( iwrk ), lwork-& iwrk+1, info ) else ! compute eigenvalues only ! (cworkspace: need 1, prefer hswork (see comments) ) ! (rworkspace: none) iwrk = itau call stdlib${ii}$_chseqr( 'E', 'N', n, ilo, ihi, a, lda, w, vr, ldvr,work( iwrk ), lwork-& iwrk+1, info ) end if ! if info /= 0 from stdlib${ii}$_chseqr, then quit if( info/=0 )go to 50 if( wantvl .or. wantvr ) then ! compute left and/or right eigenvectors ! (cworkspace: need 2*n, prefer n + 2*n*nb) ! (rworkspace: need 2*n) irwork = ibal + n call stdlib${ii}$_ctrevc3( side, 'B', select, n, a, lda, vl, ldvl, vr, ldvr,n, nout, work(& iwrk ), lwork-iwrk+1,rwork( irwork ), n, ierr ) end if if( wantvl ) then ! undo balancing of left eigenvectors ! (cworkspace: none) ! (rworkspace: need n) call stdlib${ii}$_cgebak( 'B', 'L', n, ilo, ihi, rwork( ibal ), n, vl, ldvl,ierr ) ! normalize left eigenvectors and make largest component real do i = 1, n scl = one / stdlib${ii}$_scnrm2( n, vl( 1_${ik}$, i ), 1_${ik}$ ) call stdlib${ii}$_csscal( n, scl, vl( 1_${ik}$, i ), 1_${ik}$ ) do k = 1, n rwork( irwork+k-1 ) = real( vl( k, i ),KIND=sp)**2_${ik}$ +aimag( vl( k, i ) )& **2_${ik}$ end do k = stdlib${ii}$_isamax( n, rwork( irwork ), 1_${ik}$ ) tmp = conjg( vl( k, i ) ) / sqrt( rwork( irwork+k-1 ) ) call stdlib${ii}$_cscal( n, tmp, vl( 1_${ik}$, i ), 1_${ik}$ ) vl( k, i ) = cmplx( real( vl( k, i ),KIND=sp), zero,KIND=sp) end do end if if( wantvr ) then ! undo balancing of right eigenvectors ! (cworkspace: none) ! (rworkspace: need n) call stdlib${ii}$_cgebak( 'B', 'R', n, ilo, ihi, rwork( ibal ), n, vr, ldvr,ierr ) ! normalize right eigenvectors and make largest component real do i = 1, n scl = one / stdlib${ii}$_scnrm2( n, vr( 1_${ik}$, i ), 1_${ik}$ ) call stdlib${ii}$_csscal( n, scl, vr( 1_${ik}$, i ), 1_${ik}$ ) do k = 1, n rwork( irwork+k-1 ) = real( vr( k, i ),KIND=sp)**2_${ik}$ +aimag( vr( k, i ) )& **2_${ik}$ end do k = stdlib${ii}$_isamax( n, rwork( irwork ), 1_${ik}$ ) tmp = conjg( vr( k, i ) ) / sqrt( rwork( irwork+k-1 ) ) call stdlib${ii}$_cscal( n, tmp, vr( 1_${ik}$, i ), 1_${ik}$ ) vr( k, i ) = cmplx( real( vr( k, i ),KIND=sp), zero,KIND=sp) end do end if ! undo scaling if necessary 50 continue if( scalea ) then call stdlib${ii}$_clascl( 'G', 0_${ik}$, 0_${ik}$, cscale, anrm, n-info, 1_${ik}$, w( info+1 ),max( n-info, 1_${ik}$ )& , ierr ) if( info>0_${ik}$ ) then call stdlib${ii}$_clascl( 'G', 0_${ik}$, 0_${ik}$, cscale, anrm, ilo-1, 1_${ik}$, w, n, ierr ) end if end if work( 1_${ik}$ ) = maxwrk return end subroutine stdlib${ii}$_cgeev module subroutine stdlib${ii}$_zgeev( jobvl, jobvr, n, a, lda, w, vl, ldvl, vr, ldvr,work, lwork, rwork, & !! ZGEEV computes for an N-by-N complex nonsymmetric matrix A, the !! eigenvalues and, optionally, the left and/or right eigenvectors. !! The right eigenvector v(j) of A satisfies !! A * v(j) = lambda(j) * v(j) !! where lambda(j) is its eigenvalue. !! The left eigenvector u(j) of A satisfies !! u(j)**H * A = lambda(j) * u(j)**H !! where u(j)**H denotes the conjugate transpose of u(j). !! The computed eigenvectors are normalized to have Euclidean norm !! equal to 1 and largest component real. info ) ! -- lapack driver routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_dp, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments character, intent(in) :: jobvl, jobvr integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: lda, ldvl, ldvr, lwork, n ! Array Arguments real(dp), intent(out) :: rwork(*) complex(dp), intent(inout) :: a(lda,*) complex(dp), intent(out) :: vl(ldvl,*), vr(ldvr,*), w(*), work(*) ! ===================================================================== ! Local Scalars logical(lk) :: lquery, scalea, wantvl, wantvr character :: side integer(${ik}$) :: hswork, i, ibal, ierr, ihi, ilo, irwork, itau, iwrk, k, lwork_trevc, & maxwrk, minwrk, nout real(dp) :: anrm, bignum, cscale, eps, scl, smlnum complex(dp) :: tmp ! Local Arrays logical(lk) :: select(1_${ik}$) real(dp) :: dum(1_${ik}$) ! Intrinsic Functions ! Executable Statements ! test the input arguments info = 0_${ik}$ lquery = ( lwork==-1_${ik}$ ) wantvl = stdlib_lsame( jobvl, 'V' ) wantvr = stdlib_lsame( jobvr, 'V' ) if( ( .not.wantvl ) .and. ( .not.stdlib_lsame( jobvl, 'N' ) ) ) then info = -1_${ik}$ else if( ( .not.wantvr ) .and. ( .not.stdlib_lsame( jobvr, 'N' ) ) ) then info = -2_${ik}$ else if( n<0_${ik}$ ) then info = -3_${ik}$ else if( lda<max( 1_${ik}$, n ) ) then info = -5_${ik}$ else if( ldvl<1_${ik}$ .or. ( wantvl .and. ldvl<n ) ) then info = -8_${ik}$ else if( ldvr<1_${ik}$ .or. ( wantvr .and. ldvr<n ) ) then info = -10_${ik}$ end if ! compute workspace ! (note: comments in the code beginning "workspace:" describe the ! minimal amount of workspace needed at that point in the code, ! as well as the preferred amount for good performance. ! cworkspace refers to complex workspace, and rworkspace to real ! workspace. nb refers to the optimal block size for the ! immediately following subroutine, as returned by stdlib${ii}$_ilaenv. ! hswork refers to the workspace preferred by stdlib${ii}$_zhseqr, as ! calculated below. hswork is computed assuming ilo=1 and ihi=n, ! the worst case.) if( info==0_${ik}$ ) then if( n==0_${ik}$ ) then minwrk = 1_${ik}$ maxwrk = 1_${ik}$ else maxwrk = n + n*stdlib${ii}$_ilaenv( 1_${ik}$, 'ZGEHRD', ' ', n, 1_${ik}$, n, 0_${ik}$ ) minwrk = 2_${ik}$*n if( wantvl ) then maxwrk = max( maxwrk, n + ( n - 1_${ik}$ )*stdlib${ii}$_ilaenv( 1_${ik}$, 'ZUNGHR',' ', n, 1_${ik}$, n, -& 1_${ik}$ ) ) call stdlib${ii}$_ztrevc3( 'L', 'B', select, n, a, lda,vl, ldvl, vr, ldvr,n, nout, & work, -1_${ik}$, rwork, -1_${ik}$, ierr ) lwork_trevc = int( work(1_${ik}$),KIND=${ik}$) maxwrk = max( maxwrk, n + lwork_trevc ) call stdlib${ii}$_zhseqr( 'S', 'V', n, 1_${ik}$, n, a, lda, w, vl, ldvl,work, -1_${ik}$, info ) else if( wantvr ) then maxwrk = max( maxwrk, n + ( n - 1_${ik}$ )*stdlib${ii}$_ilaenv( 1_${ik}$, 'ZUNGHR',' ', n, 1_${ik}$, n, -& 1_${ik}$ ) ) call stdlib${ii}$_ztrevc3( 'R', 'B', select, n, a, lda,vl, ldvl, vr, ldvr,n, nout, & work, -1_${ik}$, rwork, -1_${ik}$, ierr ) lwork_trevc = int( work(1_${ik}$),KIND=${ik}$) maxwrk = max( maxwrk, n + lwork_trevc ) call stdlib${ii}$_zhseqr( 'S', 'V', n, 1_${ik}$, n, a, lda, w, vr, ldvr,work, -1_${ik}$, info ) else call stdlib${ii}$_zhseqr( 'E', 'N', n, 1_${ik}$, n, a, lda, w, vr, ldvr,work, -1_${ik}$, info ) end if hswork = int( work(1_${ik}$),KIND=${ik}$) maxwrk = max( maxwrk, hswork, minwrk ) end if work( 1_${ik}$ ) = maxwrk if( lwork<minwrk .and. .not.lquery ) then info = -12_${ik}$ end if end if if( info/=0_${ik}$ ) then call stdlib${ii}$_xerbla( 'ZGEEV ', -info ) return else if( lquery ) then return end if ! quick return if possible if( n==0 )return ! get machine constants eps = stdlib${ii}$_dlamch( 'P' ) smlnum = stdlib${ii}$_dlamch( 'S' ) bignum = one / smlnum call stdlib${ii}$_dlabad( smlnum, bignum ) smlnum = sqrt( smlnum ) / eps bignum = one / smlnum ! scale a if max element outside range [smlnum,bignum] anrm = stdlib${ii}$_zlange( 'M', n, n, a, lda, dum ) scalea = .false. if( anrm>zero .and. anrm<smlnum ) then scalea = .true. cscale = smlnum else if( anrm>bignum ) then scalea = .true. cscale = bignum end if if( scalea )call stdlib${ii}$_zlascl( 'G', 0_${ik}$, 0_${ik}$, anrm, cscale, n, n, a, lda, ierr ) ! balance the matrix ! (cworkspace: none) ! (rworkspace: need n) ibal = 1_${ik}$ call stdlib${ii}$_zgebal( 'B', n, a, lda, ilo, ihi, rwork( ibal ), ierr ) ! reduce to upper hessenberg form ! (cworkspace: need 2*n, prefer n+n*nb) ! (rworkspace: none) itau = 1_${ik}$ iwrk = itau + n call stdlib${ii}$_zgehrd( n, ilo, ihi, a, lda, work( itau ), work( iwrk ),lwork-iwrk+1, ierr & ) if( wantvl ) then ! want left eigenvectors ! copy householder vectors to vl side = 'L' call stdlib${ii}$_zlacpy( 'L', n, n, a, lda, vl, ldvl ) ! generate unitary matrix in vl ! (cworkspace: need 2*n-1, prefer n+(n-1)*nb) ! (rworkspace: none) call stdlib${ii}$_zunghr( n, ilo, ihi, vl, ldvl, work( itau ), work( iwrk ),lwork-iwrk+1, & ierr ) ! perform qr iteration, accumulating schur vectors in vl ! (cworkspace: need 1, prefer hswork (see comments) ) ! (rworkspace: none) iwrk = itau call stdlib${ii}$_zhseqr( 'S', 'V', n, ilo, ihi, a, lda, w, vl, ldvl,work( iwrk ), lwork-& iwrk+1, info ) if( wantvr ) then ! want left and right eigenvectors ! copy schur vectors to vr side = 'B' call stdlib${ii}$_zlacpy( 'F', n, n, vl, ldvl, vr, ldvr ) end if else if( wantvr ) then ! want right eigenvectors ! copy householder vectors to vr side = 'R' call stdlib${ii}$_zlacpy( 'L', n, n, a, lda, vr, ldvr ) ! generate unitary matrix in vr ! (cworkspace: need 2*n-1, prefer n+(n-1)*nb) ! (rworkspace: none) call stdlib${ii}$_zunghr( n, ilo, ihi, vr, ldvr, work( itau ), work( iwrk ),lwork-iwrk+1, & ierr ) ! perform qr iteration, accumulating schur vectors in vr ! (cworkspace: need 1, prefer hswork (see comments) ) ! (rworkspace: none) iwrk = itau call stdlib${ii}$_zhseqr( 'S', 'V', n, ilo, ihi, a, lda, w, vr, ldvr,work( iwrk ), lwork-& iwrk+1, info ) else ! compute eigenvalues only ! (cworkspace: need 1, prefer hswork (see comments) ) ! (rworkspace: none) iwrk = itau call stdlib${ii}$_zhseqr( 'E', 'N', n, ilo, ihi, a, lda, w, vr, ldvr,work( iwrk ), lwork-& iwrk+1, info ) end if ! if info /= 0 from stdlib${ii}$_zhseqr, then quit if( info/=0 )go to 50 if( wantvl .or. wantvr ) then ! compute left and/or right eigenvectors ! (cworkspace: need 2*n, prefer n + 2*n*nb) ! (rworkspace: need 2*n) irwork = ibal + n call stdlib${ii}$_ztrevc3( side, 'B', select, n, a, lda, vl, ldvl, vr, ldvr,n, nout, work(& iwrk ), lwork-iwrk+1,rwork( irwork ), n, ierr ) end if if( wantvl ) then ! undo balancing of left eigenvectors ! (cworkspace: none) ! (rworkspace: need n) call stdlib${ii}$_zgebak( 'B', 'L', n, ilo, ihi, rwork( ibal ), n, vl, ldvl,ierr ) ! normalize left eigenvectors and make largest component real do i = 1, n scl = one / stdlib${ii}$_dznrm2( n, vl( 1_${ik}$, i ), 1_${ik}$ ) call stdlib${ii}$_zdscal( n, scl, vl( 1_${ik}$, i ), 1_${ik}$ ) do k = 1, n rwork( irwork+k-1 ) = real( vl( k, i ),KIND=dp)**2_${ik}$ +aimag( vl( k, i ) )& **2_${ik}$ end do k = stdlib${ii}$_idamax( n, rwork( irwork ), 1_${ik}$ ) tmp = conjg( vl( k, i ) ) / sqrt( rwork( irwork+k-1 ) ) call stdlib${ii}$_zscal( n, tmp, vl( 1_${ik}$, i ), 1_${ik}$ ) vl( k, i ) = cmplx( real( vl( k, i ),KIND=dp), zero,KIND=dp) end do end if if( wantvr ) then ! undo balancing of right eigenvectors ! (cworkspace: none) ! (rworkspace: need n) call stdlib${ii}$_zgebak( 'B', 'R', n, ilo, ihi, rwork( ibal ), n, vr, ldvr,ierr ) ! normalize right eigenvectors and make largest component real do i = 1, n scl = one / stdlib${ii}$_dznrm2( n, vr( 1_${ik}$, i ), 1_${ik}$ ) call stdlib${ii}$_zdscal( n, scl, vr( 1_${ik}$, i ), 1_${ik}$ ) do k = 1, n rwork( irwork+k-1 ) = real( vr( k, i ),KIND=dp)**2_${ik}$ +aimag( vr( k, i ) )& **2_${ik}$ end do k = stdlib${ii}$_idamax( n, rwork( irwork ), 1_${ik}$ ) tmp = conjg( vr( k, i ) ) / sqrt( rwork( irwork+k-1 ) ) call stdlib${ii}$_zscal( n, tmp, vr( 1_${ik}$, i ), 1_${ik}$ ) vr( k, i ) = cmplx( real( vr( k, i ),KIND=dp), zero,KIND=dp) end do end if ! undo scaling if necessary 50 continue if( scalea ) then call stdlib${ii}$_zlascl( 'G', 0_${ik}$, 0_${ik}$, cscale, anrm, n-info, 1_${ik}$, w( info+1 ),max( n-info, 1_${ik}$ )& , ierr ) if( info>0_${ik}$ ) then call stdlib${ii}$_zlascl( 'G', 0_${ik}$, 0_${ik}$, cscale, anrm, ilo-1, 1_${ik}$, w, n, ierr ) end if end if work( 1_${ik}$ ) = maxwrk return end subroutine stdlib${ii}$_zgeev #:for ck,ct,ci in CMPLX_KINDS_TYPES #:if not ck in ["sp","dp"] module subroutine stdlib${ii}$_${ci}$geev( jobvl, jobvr, n, a, lda, w, vl, ldvl, vr, ldvr,work, lwork, rwork, & !! ZGEEV: computes for an N-by-N complex nonsymmetric matrix A, the !! eigenvalues and, optionally, the left and/or right eigenvectors. !! The right eigenvector v(j) of A satisfies !! A * v(j) = lambda(j) * v(j) !! where lambda(j) is its eigenvalue. !! The left eigenvector u(j) of A satisfies !! u(j)**H * A = lambda(j) * u(j)**H !! where u(j)**H denotes the conjugate transpose of u(j). !! The computed eigenvectors are normalized to have Euclidean norm !! equal to 1 and largest component real. info ) ! -- lapack driver routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_${ck}$, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments character, intent(in) :: jobvl, jobvr integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: lda, ldvl, ldvr, lwork, n ! Array Arguments real(${ck}$), intent(out) :: rwork(*) complex(${ck}$), intent(inout) :: a(lda,*) complex(${ck}$), intent(out) :: vl(ldvl,*), vr(ldvr,*), w(*), work(*) ! ===================================================================== ! Local Scalars logical(lk) :: lquery, scalea, wantvl, wantvr character :: side integer(${ik}$) :: hswork, i, ibal, ierr, ihi, ilo, irwork, itau, iwrk, k, lwork_trevc, & maxwrk, minwrk, nout real(${ck}$) :: anrm, bignum, cscale, eps, scl, smlnum complex(${ck}$) :: tmp ! Local Arrays logical(lk) :: select(1_${ik}$) real(${ck}$) :: dum(1_${ik}$) ! Intrinsic Functions ! Executable Statements ! test the input arguments info = 0_${ik}$ lquery = ( lwork==-1_${ik}$ ) wantvl = stdlib_lsame( jobvl, 'V' ) wantvr = stdlib_lsame( jobvr, 'V' ) if( ( .not.wantvl ) .and. ( .not.stdlib_lsame( jobvl, 'N' ) ) ) then info = -1_${ik}$ else if( ( .not.wantvr ) .and. ( .not.stdlib_lsame( jobvr, 'N' ) ) ) then info = -2_${ik}$ else if( n<0_${ik}$ ) then info = -3_${ik}$ else if( lda<max( 1_${ik}$, n ) ) then info = -5_${ik}$ else if( ldvl<1_${ik}$ .or. ( wantvl .and. ldvl<n ) ) then info = -8_${ik}$ else if( ldvr<1_${ik}$ .or. ( wantvr .and. ldvr<n ) ) then info = -10_${ik}$ end if ! compute workspace ! (note: comments in the code beginning "workspace:" describe the ! minimal amount of workspace needed at that point in the code, ! as well as the preferred amount for good performance. ! cworkspace refers to complex workspace, and rworkspace to real ! workspace. nb refers to the optimal block size for the ! immediately following subroutine, as returned by stdlib${ii}$_ilaenv. ! hswork refers to the workspace preferred by stdlib${ii}$_${ci}$hseqr, as ! calculated below. hswork is computed assuming ilo=1 and ihi=n, ! the worst case.) if( info==0_${ik}$ ) then if( n==0_${ik}$ ) then minwrk = 1_${ik}$ maxwrk = 1_${ik}$ else maxwrk = n + n*stdlib${ii}$_ilaenv( 1_${ik}$, 'ZGEHRD', ' ', n, 1_${ik}$, n, 0_${ik}$ ) minwrk = 2_${ik}$*n if( wantvl ) then maxwrk = max( maxwrk, n + ( n - 1_${ik}$ )*stdlib${ii}$_ilaenv( 1_${ik}$, 'ZUNGHR',' ', n, 1_${ik}$, n, -& 1_${ik}$ ) ) call stdlib${ii}$_${ci}$trevc3( 'L', 'B', select, n, a, lda,vl, ldvl, vr, ldvr,n, nout, & work, -1_${ik}$, rwork, -1_${ik}$, ierr ) lwork_trevc = int( work(1_${ik}$),KIND=${ik}$) maxwrk = max( maxwrk, n + lwork_trevc ) call stdlib${ii}$_${ci}$hseqr( 'S', 'V', n, 1_${ik}$, n, a, lda, w, vl, ldvl,work, -1_${ik}$, info ) else if( wantvr ) then maxwrk = max( maxwrk, n + ( n - 1_${ik}$ )*stdlib${ii}$_ilaenv( 1_${ik}$, 'ZUNGHR',' ', n, 1_${ik}$, n, -& 1_${ik}$ ) ) call stdlib${ii}$_${ci}$trevc3( 'R', 'B', select, n, a, lda,vl, ldvl, vr, ldvr,n, nout, & work, -1_${ik}$, rwork, -1_${ik}$, ierr ) lwork_trevc = int( work(1_${ik}$),KIND=${ik}$) maxwrk = max( maxwrk, n + lwork_trevc ) call stdlib${ii}$_${ci}$hseqr( 'S', 'V', n, 1_${ik}$, n, a, lda, w, vr, ldvr,work, -1_${ik}$, info ) else call stdlib${ii}$_${ci}$hseqr( 'E', 'N', n, 1_${ik}$, n, a, lda, w, vr, ldvr,work, -1_${ik}$, info ) end if hswork = int( work(1_${ik}$),KIND=${ik}$) maxwrk = max( maxwrk, hswork, minwrk ) end if work( 1_${ik}$ ) = maxwrk if( lwork<minwrk .and. .not.lquery ) then info = -12_${ik}$ end if end if if( info/=0_${ik}$ ) then call stdlib${ii}$_xerbla( 'ZGEEV ', -info ) return else if( lquery ) then return end if ! quick return if possible if( n==0 )return ! get machine constants eps = stdlib${ii}$_${c2ri(ci)}$lamch( 'P' ) smlnum = stdlib${ii}$_${c2ri(ci)}$lamch( 'S' ) bignum = one / smlnum call stdlib${ii}$_${c2ri(ci)}$labad( smlnum, bignum ) smlnum = sqrt( smlnum ) / eps bignum = one / smlnum ! scale a if max element outside range [smlnum,bignum] anrm = stdlib${ii}$_${ci}$lange( 'M', n, n, a, lda, dum ) scalea = .false. if( anrm>zero .and. anrm<smlnum ) then scalea = .true. cscale = smlnum else if( anrm>bignum ) then scalea = .true. cscale = bignum end if if( scalea )call stdlib${ii}$_${ci}$lascl( 'G', 0_${ik}$, 0_${ik}$, anrm, cscale, n, n, a, lda, ierr ) ! balance the matrix ! (cworkspace: none) ! (rworkspace: need n) ibal = 1_${ik}$ call stdlib${ii}$_${ci}$gebal( 'B', n, a, lda, ilo, ihi, rwork( ibal ), ierr ) ! reduce to upper hessenberg form ! (cworkspace: need 2*n, prefer n+n*nb) ! (rworkspace: none) itau = 1_${ik}$ iwrk = itau + n call stdlib${ii}$_${ci}$gehrd( n, ilo, ihi, a, lda, work( itau ), work( iwrk ),lwork-iwrk+1, ierr & ) if( wantvl ) then ! want left eigenvectors ! copy householder vectors to vl side = 'L' call stdlib${ii}$_${ci}$lacpy( 'L', n, n, a, lda, vl, ldvl ) ! generate unitary matrix in vl ! (cworkspace: need 2*n-1, prefer n+(n-1)*nb) ! (rworkspace: none) call stdlib${ii}$_${ci}$unghr( n, ilo, ihi, vl, ldvl, work( itau ), work( iwrk ),lwork-iwrk+1, & ierr ) ! perform qr iteration, accumulating schur vectors in vl ! (cworkspace: need 1, prefer hswork (see comments) ) ! (rworkspace: none) iwrk = itau call stdlib${ii}$_${ci}$hseqr( 'S', 'V', n, ilo, ihi, a, lda, w, vl, ldvl,work( iwrk ), lwork-& iwrk+1, info ) if( wantvr ) then ! want left and right eigenvectors ! copy schur vectors to vr side = 'B' call stdlib${ii}$_${ci}$lacpy( 'F', n, n, vl, ldvl, vr, ldvr ) end if else if( wantvr ) then ! want right eigenvectors ! copy householder vectors to vr side = 'R' call stdlib${ii}$_${ci}$lacpy( 'L', n, n, a, lda, vr, ldvr ) ! generate unitary matrix in vr ! (cworkspace: need 2*n-1, prefer n+(n-1)*nb) ! (rworkspace: none) call stdlib${ii}$_${ci}$unghr( n, ilo, ihi, vr, ldvr, work( itau ), work( iwrk ),lwork-iwrk+1, & ierr ) ! perform qr iteration, accumulating schur vectors in vr ! (cworkspace: need 1, prefer hswork (see comments) ) ! (rworkspace: none) iwrk = itau call stdlib${ii}$_${ci}$hseqr( 'S', 'V', n, ilo, ihi, a, lda, w, vr, ldvr,work( iwrk ), lwork-& iwrk+1, info ) else ! compute eigenvalues only ! (cworkspace: need 1, prefer hswork (see comments) ) ! (rworkspace: none) iwrk = itau call stdlib${ii}$_${ci}$hseqr( 'E', 'N', n, ilo, ihi, a, lda, w, vr, ldvr,work( iwrk ), lwork-& iwrk+1, info ) end if ! if info /= 0 from stdlib${ii}$_${ci}$hseqr, then quit if( info/=0 )go to 50 if( wantvl .or. wantvr ) then ! compute left and/or right eigenvectors ! (cworkspace: need 2*n, prefer n + 2*n*nb) ! (rworkspace: need 2*n) irwork = ibal + n call stdlib${ii}$_${ci}$trevc3( side, 'B', select, n, a, lda, vl, ldvl, vr, ldvr,n, nout, work(& iwrk ), lwork-iwrk+1,rwork( irwork ), n, ierr ) end if if( wantvl ) then ! undo balancing of left eigenvectors ! (cworkspace: none) ! (rworkspace: need n) call stdlib${ii}$_${ci}$gebak( 'B', 'L', n, ilo, ihi, rwork( ibal ), n, vl, ldvl,ierr ) ! normalize left eigenvectors and make largest component real do i = 1, n scl = one / stdlib${ii}$_${c2ri(ci)}$znrm2( n, vl( 1_${ik}$, i ), 1_${ik}$ ) call stdlib${ii}$_${ci}$dscal( n, scl, vl( 1_${ik}$, i ), 1_${ik}$ ) do k = 1, n rwork( irwork+k-1 ) = real( vl( k, i ),KIND=${ck}$)**2_${ik}$ +aimag( vl( k, i ) )& **2_${ik}$ end do k = stdlib${ii}$_i${c2ri(ci)}$amax( n, rwork( irwork ), 1_${ik}$ ) tmp = conjg( vl( k, i ) ) / sqrt( rwork( irwork+k-1 ) ) call stdlib${ii}$_${ci}$scal( n, tmp, vl( 1_${ik}$, i ), 1_${ik}$ ) vl( k, i ) = cmplx( real( vl( k, i ),KIND=${ck}$), zero,KIND=${ck}$) end do end if if( wantvr ) then ! undo balancing of right eigenvectors ! (cworkspace: none) ! (rworkspace: need n) call stdlib${ii}$_${ci}$gebak( 'B', 'R', n, ilo, ihi, rwork( ibal ), n, vr, ldvr,ierr ) ! normalize right eigenvectors and make largest component real do i = 1, n scl = one / stdlib${ii}$_${c2ri(ci)}$znrm2( n, vr( 1_${ik}$, i ), 1_${ik}$ ) call stdlib${ii}$_${ci}$dscal( n, scl, vr( 1_${ik}$, i ), 1_${ik}$ ) do k = 1, n rwork( irwork+k-1 ) = real( vr( k, i ),KIND=${ck}$)**2_${ik}$ +aimag( vr( k, i ) )& **2_${ik}$ end do k = stdlib${ii}$_i${c2ri(ci)}$amax( n, rwork( irwork ), 1_${ik}$ ) tmp = conjg( vr( k, i ) ) / sqrt( rwork( irwork+k-1 ) ) call stdlib${ii}$_${ci}$scal( n, tmp, vr( 1_${ik}$, i ), 1_${ik}$ ) vr( k, i ) = cmplx( real( vr( k, i ),KIND=${ck}$), zero,KIND=${ck}$) end do end if ! undo scaling if necessary 50 continue if( scalea ) then call stdlib${ii}$_${ci}$lascl( 'G', 0_${ik}$, 0_${ik}$, cscale, anrm, n-info, 1_${ik}$, w( info+1 ),max( n-info, 1_${ik}$ )& , ierr ) if( info>0_${ik}$ ) then call stdlib${ii}$_${ci}$lascl( 'G', 0_${ik}$, 0_${ik}$, cscale, anrm, ilo-1, 1_${ik}$, w, n, ierr ) end if end if work( 1_${ik}$ ) = maxwrk return end subroutine stdlib${ii}$_${ci}$geev #:endif #:endfor module subroutine stdlib${ii}$_sgeevx( balanc, jobvl, jobvr, sense, n, a, lda, wr, wi,vl, ldvl, vr, ldvr, & !! SGEEVX computes for an N-by-N real nonsymmetric matrix A, the !! eigenvalues and, optionally, the left and/or right eigenvectors. !! Optionally also, it computes a balancing transformation to improve !! the conditioning of the eigenvalues and eigenvectors (ILO, IHI, !! SCALE, and ABNRM), reciprocal condition numbers for the eigenvalues !! (RCONDE), and reciprocal condition numbers for the right !! eigenvectors (RCONDV). !! The right eigenvector v(j) of A satisfies !! A * v(j) = lambda(j) * v(j) !! where lambda(j) is its eigenvalue. !! The left eigenvector u(j) of A satisfies !! u(j)**H * A = lambda(j) * u(j)**H !! where u(j)**H denotes the conjugate-transpose of u(j). !! The computed eigenvectors are normalized to have Euclidean norm !! equal to 1 and largest component real. !! Balancing a matrix means permuting the rows and columns to make it !! more nearly upper triangular, and applying a diagonal similarity !! transformation D * A * D**(-1), where D is a diagonal matrix, to !! make its rows and columns closer in norm and the condition numbers !! of its eigenvalues and eigenvectors smaller. The computed !! reciprocal condition numbers correspond to the balanced matrix. !! Permuting rows and columns will not change the condition numbers !! (in exact arithmetic) but diagonal scaling will. For further !! explanation of balancing, see section 4.10.2_sp of the LAPACK !! Users' Guide. ilo, ihi, scale, abnrm,rconde, rcondv, work, lwork, iwork, info ) ! -- lapack driver routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_sp, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments character, intent(in) :: balanc, jobvl, jobvr, sense integer(${ik}$), intent(out) :: ihi, ilo, info integer(${ik}$), intent(in) :: lda, ldvl, ldvr, lwork, n real(sp), intent(out) :: abnrm ! Array Arguments integer(${ik}$), intent(out) :: iwork(*) real(sp), intent(inout) :: a(lda,*) real(sp), intent(out) :: rconde(*), rcondv(*), scale(*), vl(ldvl,*), vr(ldvr,*), wi(*),& work(*), wr(*) ! ===================================================================== ! Local Scalars logical(lk) :: lquery, scalea, wantvl, wantvr, wntsnb, wntsne, wntsnn, wntsnv character :: job, side integer(${ik}$) :: hswork, i, icond, ierr, itau, iwrk, k, lwork_trevc, maxwrk, minwrk, & nout real(sp) :: anrm, bignum, cs, cscale, eps, r, scl, smlnum, sn ! Local Arrays logical(lk) :: select(1_${ik}$) real(sp) :: dum(1_${ik}$) ! Intrinsic Functions ! Executable Statements ! test the input arguments info = 0_${ik}$ lquery = ( lwork==-1_${ik}$ ) wantvl = stdlib_lsame( jobvl, 'V' ) wantvr = stdlib_lsame( jobvr, 'V' ) wntsnn = stdlib_lsame( sense, 'N' ) wntsne = stdlib_lsame( sense, 'E' ) wntsnv = stdlib_lsame( sense, 'V' ) wntsnb = stdlib_lsame( sense, 'B' ) if( .not.( stdlib_lsame( balanc, 'N' ) .or. stdlib_lsame( balanc, 'S' ).or. & stdlib_lsame( balanc, 'P' ) .or. stdlib_lsame( balanc, 'B' ) ) )then info = -1_${ik}$ else if( ( .not.wantvl ) .and. ( .not.stdlib_lsame( jobvl, 'N' ) ) ) then info = -2_${ik}$ else if( ( .not.wantvr ) .and. ( .not.stdlib_lsame( jobvr, 'N' ) ) ) then info = -3_${ik}$ else if( .not.( wntsnn .or. wntsne .or. wntsnb .or. wntsnv ) .or.( ( wntsne .or. & wntsnb ) .and. .not.( wantvl .and.wantvr ) ) ) then info = -4_${ik}$ else if( n<0_${ik}$ ) then info = -5_${ik}$ else if( lda<max( 1_${ik}$, n ) ) then info = -7_${ik}$ else if( ldvl<1_${ik}$ .or. ( wantvl .and. ldvl<n ) ) then info = -11_${ik}$ else if( ldvr<1_${ik}$ .or. ( wantvr .and. ldvr<n ) ) then info = -13_${ik}$ end if ! compute workspace ! (note: comments in the code beginning "workspace:" describe the ! minimal amount of workspace needed at that point in the code, ! as well as the preferred amount for good performance. ! nb refers to the optimal block size for the immediately ! following subroutine, as returned by stdlib${ii}$_ilaenv. ! hswork refers to the workspace preferred by stdlib${ii}$_shseqr, as ! calculated below. hswork is computed assuming ilo=1 and ihi=n, ! the worst case.) if( info==0_${ik}$ ) then if( n==0_${ik}$ ) then minwrk = 1_${ik}$ maxwrk = 1_${ik}$ else maxwrk = n + n*stdlib${ii}$_ilaenv( 1_${ik}$, 'SGEHRD', ' ', n, 1_${ik}$, n, 0_${ik}$ ) if( wantvl ) then call stdlib${ii}$_strevc3( 'L', 'B', select, n, a, lda,vl, ldvl, vr, ldvr,n, nout, & work, -1_${ik}$, ierr ) lwork_trevc = int( work(1_${ik}$),KIND=${ik}$) maxwrk = max( maxwrk, n + lwork_trevc ) call stdlib${ii}$_shseqr( 'S', 'V', n, 1_${ik}$, n, a, lda, wr, wi, vl, ldvl,work, -1_${ik}$, & info ) else if( wantvr ) then call stdlib${ii}$_strevc3( 'R', 'B', select, n, a, lda,vl, ldvl, vr, ldvr,n, nout, & work, -1_${ik}$, ierr ) lwork_trevc = int( work(1_${ik}$),KIND=${ik}$) maxwrk = max( maxwrk, n + lwork_trevc ) call stdlib${ii}$_shseqr( 'S', 'V', n, 1_${ik}$, n, a, lda, wr, wi, vr, ldvr,work, -1_${ik}$, & info ) else if( wntsnn ) then call stdlib${ii}$_shseqr( 'E', 'N', n, 1_${ik}$, n, a, lda, wr, wi, vr,ldvr, work, -1_${ik}$, & info ) else call stdlib${ii}$_shseqr( 'S', 'N', n, 1_${ik}$, n, a, lda, wr, wi, vr,ldvr, work, -1_${ik}$, & info ) end if end if hswork = int( work(1_${ik}$),KIND=${ik}$) if( ( .not.wantvl ) .and. ( .not.wantvr ) ) then minwrk = 2_${ik}$*n if( .not.wntsnn )minwrk = max( minwrk, n*n+6*n ) maxwrk = max( maxwrk, hswork ) if( .not.wntsnn )maxwrk = max( maxwrk, n*n + 6_${ik}$*n ) else minwrk = 3_${ik}$*n if( ( .not.wntsnn ) .and. ( .not.wntsne ) )minwrk = max( minwrk, n*n + 6_${ik}$*n ) maxwrk = max( maxwrk, hswork ) maxwrk = max( maxwrk, n + ( n - 1_${ik}$ )*stdlib${ii}$_ilaenv( 1_${ik}$, 'SORGHR',' ', n, 1_${ik}$, n, -& 1_${ik}$ ) ) if( ( .not.wntsnn ) .and. ( .not.wntsne ) )maxwrk = max( maxwrk, n*n + 6_${ik}$*n ) maxwrk = max( maxwrk, 3_${ik}$*n ) end if maxwrk = max( maxwrk, minwrk ) end if work( 1_${ik}$ ) = maxwrk if( lwork<minwrk .and. .not.lquery ) then info = -21_${ik}$ end if end if if( info/=0_${ik}$ ) then call stdlib${ii}$_xerbla( 'SGEEVX', -info ) return else if( lquery ) then return end if ! quick return if possible if( n==0 )return ! get machine constants eps = stdlib${ii}$_slamch( 'P' ) smlnum = stdlib${ii}$_slamch( 'S' ) bignum = one / smlnum call stdlib${ii}$_slabad( smlnum, bignum ) smlnum = sqrt( smlnum ) / eps bignum = one / smlnum ! scale a if max element outside range [smlnum,bignum] icond = 0_${ik}$ anrm = stdlib${ii}$_slange( 'M', n, n, a, lda, dum ) scalea = .false. if( anrm>zero .and. anrm<smlnum ) then scalea = .true. cscale = smlnum else if( anrm>bignum ) then scalea = .true. cscale = bignum end if if( scalea )call stdlib${ii}$_slascl( 'G', 0_${ik}$, 0_${ik}$, anrm, cscale, n, n, a, lda, ierr ) ! balance the matrix and compute abnrm call stdlib${ii}$_sgebal( balanc, n, a, lda, ilo, ihi, scale, ierr ) abnrm = stdlib${ii}$_slange( '1', n, n, a, lda, dum ) if( scalea ) then dum( 1_${ik}$ ) = abnrm call stdlib${ii}$_slascl( 'G', 0_${ik}$, 0_${ik}$, cscale, anrm, 1_${ik}$, 1_${ik}$, dum, 1_${ik}$, ierr ) abnrm = dum( 1_${ik}$ ) end if ! reduce to upper hessenberg form ! (workspace: need 2*n, prefer n+n*nb) itau = 1_${ik}$ iwrk = itau + n call stdlib${ii}$_sgehrd( n, ilo, ihi, a, lda, work( itau ), work( iwrk ),lwork-iwrk+1, ierr & ) if( wantvl ) then ! want left eigenvectors ! copy householder vectors to vl side = 'L' call stdlib${ii}$_slacpy( 'L', n, n, a, lda, vl, ldvl ) ! generate orthogonal matrix in vl ! (workspace: need 2*n-1, prefer n+(n-1)*nb) call stdlib${ii}$_sorghr( n, ilo, ihi, vl, ldvl, work( itau ), work( iwrk ),lwork-iwrk+1, & ierr ) ! perform qr iteration, accumulating schur vectors in vl ! (workspace: need 1, prefer hswork (see comments) ) iwrk = itau call stdlib${ii}$_shseqr( 'S', 'V', n, ilo, ihi, a, lda, wr, wi, vl, ldvl,work( iwrk ), & lwork-iwrk+1, info ) if( wantvr ) then ! want left and right eigenvectors ! copy schur vectors to vr side = 'B' call stdlib${ii}$_slacpy( 'F', n, n, vl, ldvl, vr, ldvr ) end if else if( wantvr ) then ! want right eigenvectors ! copy householder vectors to vr side = 'R' call stdlib${ii}$_slacpy( 'L', n, n, a, lda, vr, ldvr ) ! generate orthogonal matrix in vr ! (workspace: need 2*n-1, prefer n+(n-1)*nb) call stdlib${ii}$_sorghr( n, ilo, ihi, vr, ldvr, work( itau ), work( iwrk ),lwork-iwrk+1, & ierr ) ! perform qr iteration, accumulating schur vectors in vr ! (workspace: need 1, prefer hswork (see comments) ) iwrk = itau call stdlib${ii}$_shseqr( 'S', 'V', n, ilo, ihi, a, lda, wr, wi, vr, ldvr,work( iwrk ), & lwork-iwrk+1, info ) else ! compute eigenvalues only ! if condition numbers desired, compute schur form if( wntsnn ) then job = 'E' else job = 'S' end if ! (workspace: need 1, prefer hswork (see comments) ) iwrk = itau call stdlib${ii}$_shseqr( job, 'N', n, ilo, ihi, a, lda, wr, wi, vr, ldvr,work( iwrk ), & lwork-iwrk+1, info ) end if ! if info /= 0 from stdlib${ii}$_shseqr, then quit if( info/=0 )go to 50 if( wantvl .or. wantvr ) then ! compute left and/or right eigenvectors ! (workspace: need 3*n, prefer n + 2*n*nb) call stdlib${ii}$_strevc3( side, 'B', select, n, a, lda, vl, ldvl, vr, ldvr,n, nout, work(& iwrk ), lwork-iwrk+1, ierr ) end if ! compute condition numbers if desired ! (workspace: need n*n+6*n unless sense = 'e') if( .not.wntsnn ) then call stdlib${ii}$_strsna( sense, 'A', select, n, a, lda, vl, ldvl, vr, ldvr,rconde, & rcondv, n, nout, work( iwrk ), n, iwork,icond ) end if if( wantvl ) then ! undo balancing of left eigenvectors call stdlib${ii}$_sgebak( balanc, 'L', n, ilo, ihi, scale, n, vl, ldvl,ierr ) ! normalize left eigenvectors and make largest component real do i = 1, n if( wi( i )==zero ) then scl = one / stdlib${ii}$_snrm2( n, vl( 1_${ik}$, i ), 1_${ik}$ ) call stdlib${ii}$_sscal( n, scl, vl( 1_${ik}$, i ), 1_${ik}$ ) else if( wi( i )>zero ) then scl = one / stdlib${ii}$_slapy2( stdlib${ii}$_snrm2( n, vl( 1_${ik}$, i ), 1_${ik}$ ),stdlib${ii}$_snrm2( n, & vl( 1_${ik}$, i+1 ), 1_${ik}$ ) ) call stdlib${ii}$_sscal( n, scl, vl( 1_${ik}$, i ), 1_${ik}$ ) call stdlib${ii}$_sscal( n, scl, vl( 1_${ik}$, i+1 ), 1_${ik}$ ) do k = 1, n work( k ) = vl( k, i )**2_${ik}$ + vl( k, i+1 )**2_${ik}$ end do k = stdlib${ii}$_isamax( n, work, 1_${ik}$ ) call stdlib${ii}$_slartg( vl( k, i ), vl( k, i+1 ), cs, sn, r ) call stdlib${ii}$_srot( n, vl( 1_${ik}$, i ), 1_${ik}$, vl( 1_${ik}$, i+1 ), 1_${ik}$, cs, sn ) vl( k, i+1 ) = zero end if end do end if if( wantvr ) then ! undo balancing of right eigenvectors call stdlib${ii}$_sgebak( balanc, 'R', n, ilo, ihi, scale, n, vr, ldvr,ierr ) ! normalize right eigenvectors and make largest component real do i = 1, n if( wi( i )==zero ) then scl = one / stdlib${ii}$_snrm2( n, vr( 1_${ik}$, i ), 1_${ik}$ ) call stdlib${ii}$_sscal( n, scl, vr( 1_${ik}$, i ), 1_${ik}$ ) else if( wi( i )>zero ) then scl = one / stdlib${ii}$_slapy2( stdlib${ii}$_snrm2( n, vr( 1_${ik}$, i ), 1_${ik}$ ),stdlib${ii}$_snrm2( n, & vr( 1_${ik}$, i+1 ), 1_${ik}$ ) ) call stdlib${ii}$_sscal( n, scl, vr( 1_${ik}$, i ), 1_${ik}$ ) call stdlib${ii}$_sscal( n, scl, vr( 1_${ik}$, i+1 ), 1_${ik}$ ) do k = 1, n work( k ) = vr( k, i )**2_${ik}$ + vr( k, i+1 )**2_${ik}$ end do k = stdlib${ii}$_isamax( n, work, 1_${ik}$ ) call stdlib${ii}$_slartg( vr( k, i ), vr( k, i+1 ), cs, sn, r ) call stdlib${ii}$_srot( n, vr( 1_${ik}$, i ), 1_${ik}$, vr( 1_${ik}$, i+1 ), 1_${ik}$, cs, sn ) vr( k, i+1 ) = zero end if end do end if ! undo scaling if necessary 50 continue if( scalea ) then call stdlib${ii}$_slascl( 'G', 0_${ik}$, 0_${ik}$, cscale, anrm, n-info, 1_${ik}$, wr( info+1 ),max( n-info, 1_${ik}$ & ), ierr ) call stdlib${ii}$_slascl( 'G', 0_${ik}$, 0_${ik}$, cscale, anrm, n-info, 1_${ik}$, wi( info+1 ),max( n-info, 1_${ik}$ & ), ierr ) if( info==0_${ik}$ ) then if( ( wntsnv .or. wntsnb ) .and. icond==0_${ik}$ )call stdlib${ii}$_slascl( 'G', 0_${ik}$, 0_${ik}$, cscale,& anrm, n, 1_${ik}$, rcondv, n,ierr ) else call stdlib${ii}$_slascl( 'G', 0_${ik}$, 0_${ik}$, cscale, anrm, ilo-1, 1_${ik}$, wr, n,ierr ) call stdlib${ii}$_slascl( 'G', 0_${ik}$, 0_${ik}$, cscale, anrm, ilo-1, 1_${ik}$, wi, n,ierr ) end if end if work( 1_${ik}$ ) = maxwrk return end subroutine stdlib${ii}$_sgeevx module subroutine stdlib${ii}$_dgeevx( balanc, jobvl, jobvr, sense, n, a, lda, wr, wi,vl, ldvl, vr, ldvr, & !! DGEEVX computes for an N-by-N real nonsymmetric matrix A, the !! eigenvalues and, optionally, the left and/or right eigenvectors. !! Optionally also, it computes a balancing transformation to improve !! the conditioning of the eigenvalues and eigenvectors (ILO, IHI, !! SCALE, and ABNRM), reciprocal condition numbers for the eigenvalues !! (RCONDE), and reciprocal condition numbers for the right !! eigenvectors (RCONDV). !! The right eigenvector v(j) of A satisfies !! A * v(j) = lambda(j) * v(j) !! where lambda(j) is its eigenvalue. !! The left eigenvector u(j) of A satisfies !! u(j)**H * A = lambda(j) * u(j)**H !! where u(j)**H denotes the conjugate-transpose of u(j). !! The computed eigenvectors are normalized to have Euclidean norm !! equal to 1 and largest component real. !! Balancing a matrix means permuting the rows and columns to make it !! more nearly upper triangular, and applying a diagonal similarity !! transformation D * A * D**(-1), where D is a diagonal matrix, to !! make its rows and columns closer in norm and the condition numbers !! of its eigenvalues and eigenvectors smaller. The computed !! reciprocal condition numbers correspond to the balanced matrix. !! Permuting rows and columns will not change the condition numbers !! (in exact arithmetic) but diagonal scaling will. For further !! explanation of balancing, see section 4.10.2_dp of the LAPACK !! Users' Guide. ilo, ihi, scale, abnrm,rconde, rcondv, work, lwork, iwork, info ) ! -- lapack driver routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_dp, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments character, intent(in) :: balanc, jobvl, jobvr, sense integer(${ik}$), intent(out) :: ihi, ilo, info integer(${ik}$), intent(in) :: lda, ldvl, ldvr, lwork, n real(dp), intent(out) :: abnrm ! Array Arguments integer(${ik}$), intent(out) :: iwork(*) real(dp), intent(inout) :: a(lda,*) real(dp), intent(out) :: rconde(*), rcondv(*), scale(*), vl(ldvl,*), vr(ldvr,*), wi(*),& work(*), wr(*) ! ===================================================================== ! Local Scalars logical(lk) :: lquery, scalea, wantvl, wantvr, wntsnb, wntsne, wntsnn, wntsnv character :: job, side integer(${ik}$) :: hswork, i, icond, ierr, itau, iwrk, k, lwork_trevc, maxwrk, minwrk, & nout real(dp) :: anrm, bignum, cs, cscale, eps, r, scl, smlnum, sn ! Local Arrays logical(lk) :: select(1_${ik}$) real(dp) :: dum(1_${ik}$) ! Intrinsic Functions ! Executable Statements ! test the input arguments info = 0_${ik}$ lquery = ( lwork==-1_${ik}$ ) wantvl = stdlib_lsame( jobvl, 'V' ) wantvr = stdlib_lsame( jobvr, 'V' ) wntsnn = stdlib_lsame( sense, 'N' ) wntsne = stdlib_lsame( sense, 'E' ) wntsnv = stdlib_lsame( sense, 'V' ) wntsnb = stdlib_lsame( sense, 'B' ) if( .not.( stdlib_lsame( balanc, 'N' ) .or. stdlib_lsame( balanc, 'S' ).or. & stdlib_lsame( balanc, 'P' ) .or. stdlib_lsame( balanc, 'B' ) ) )then info = -1_${ik}$ else if( ( .not.wantvl ) .and. ( .not.stdlib_lsame( jobvl, 'N' ) ) ) then info = -2_${ik}$ else if( ( .not.wantvr ) .and. ( .not.stdlib_lsame( jobvr, 'N' ) ) ) then info = -3_${ik}$ else if( .not.( wntsnn .or. wntsne .or. wntsnb .or. wntsnv ) .or.( ( wntsne .or. & wntsnb ) .and. .not.( wantvl .and.wantvr ) ) ) then info = -4_${ik}$ else if( n<0_${ik}$ ) then info = -5_${ik}$ else if( lda<max( 1_${ik}$, n ) ) then info = -7_${ik}$ else if( ldvl<1_${ik}$ .or. ( wantvl .and. ldvl<n ) ) then info = -11_${ik}$ else if( ldvr<1_${ik}$ .or. ( wantvr .and. ldvr<n ) ) then info = -13_${ik}$ end if ! compute workspace ! (note: comments in the code beginning "workspace:" describe the ! minimal amount of workspace needed at that point in the code, ! as well as the preferred amount for good performance. ! nb refers to the optimal block size for the immediately ! following subroutine, as returned by stdlib${ii}$_ilaenv. ! hswork refers to the workspace preferred by stdlib${ii}$_dhseqr, as ! calculated below. hswork is computed assuming ilo=1 and ihi=n, ! the worst case.) if( info==0_${ik}$ ) then if( n==0_${ik}$ ) then minwrk = 1_${ik}$ maxwrk = 1_${ik}$ else maxwrk = n + n*stdlib${ii}$_ilaenv( 1_${ik}$, 'DGEHRD', ' ', n, 1_${ik}$, n, 0_${ik}$ ) if( wantvl ) then call stdlib${ii}$_dtrevc3( 'L', 'B', select, n, a, lda,vl, ldvl, vr, ldvr,n, nout, & work, -1_${ik}$, ierr ) lwork_trevc = int( work(1_${ik}$),KIND=${ik}$) maxwrk = max( maxwrk, n + lwork_trevc ) call stdlib${ii}$_dhseqr( 'S', 'V', n, 1_${ik}$, n, a, lda, wr, wi, vl, ldvl,work, -1_${ik}$, & info ) else if( wantvr ) then call stdlib${ii}$_dtrevc3( 'R', 'B', select, n, a, lda,vl, ldvl, vr, ldvr,n, nout, & work, -1_${ik}$, ierr ) lwork_trevc = int( work(1_${ik}$),KIND=${ik}$) maxwrk = max( maxwrk, n + lwork_trevc ) call stdlib${ii}$_dhseqr( 'S', 'V', n, 1_${ik}$, n, a, lda, wr, wi, vr, ldvr,work, -1_${ik}$, & info ) else if( wntsnn ) then call stdlib${ii}$_dhseqr( 'E', 'N', n, 1_${ik}$, n, a, lda, wr, wi, vr,ldvr, work, -1_${ik}$, & info ) else call stdlib${ii}$_dhseqr( 'S', 'N', n, 1_${ik}$, n, a, lda, wr, wi, vr,ldvr, work, -1_${ik}$, & info ) end if end if hswork = int( work(1_${ik}$),KIND=${ik}$) if( ( .not.wantvl ) .and. ( .not.wantvr ) ) then minwrk = 2_${ik}$*n if( .not.wntsnn )minwrk = max( minwrk, n*n+6*n ) maxwrk = max( maxwrk, hswork ) if( .not.wntsnn )maxwrk = max( maxwrk, n*n + 6_${ik}$*n ) else minwrk = 3_${ik}$*n if( ( .not.wntsnn ) .and. ( .not.wntsne ) )minwrk = max( minwrk, n*n + 6_${ik}$*n ) maxwrk = max( maxwrk, hswork ) maxwrk = max( maxwrk, n + ( n - 1_${ik}$ )*stdlib${ii}$_ilaenv( 1_${ik}$, 'DORGHR',' ', n, 1_${ik}$, n, -& 1_${ik}$ ) ) if( ( .not.wntsnn ) .and. ( .not.wntsne ) )maxwrk = max( maxwrk, n*n + 6_${ik}$*n ) maxwrk = max( maxwrk, 3_${ik}$*n ) end if maxwrk = max( maxwrk, minwrk ) end if work( 1_${ik}$ ) = maxwrk if( lwork<minwrk .and. .not.lquery ) then info = -21_${ik}$ end if end if if( info/=0_${ik}$ ) then call stdlib${ii}$_xerbla( 'DGEEVX', -info ) return else if( lquery ) then return end if ! quick return if possible if( n==0 )return ! get machine constants eps = stdlib${ii}$_dlamch( 'P' ) smlnum = stdlib${ii}$_dlamch( 'S' ) bignum = one / smlnum call stdlib${ii}$_dlabad( smlnum, bignum ) smlnum = sqrt( smlnum ) / eps bignum = one / smlnum ! scale a if max element outside range [smlnum,bignum] icond = 0_${ik}$ anrm = stdlib${ii}$_dlange( 'M', n, n, a, lda, dum ) scalea = .false. if( anrm>zero .and. anrm<smlnum ) then scalea = .true. cscale = smlnum else if( anrm>bignum ) then scalea = .true. cscale = bignum end if if( scalea )call stdlib${ii}$_dlascl( 'G', 0_${ik}$, 0_${ik}$, anrm, cscale, n, n, a, lda, ierr ) ! balance the matrix and compute abnrm call stdlib${ii}$_dgebal( balanc, n, a, lda, ilo, ihi, scale, ierr ) abnrm = stdlib${ii}$_dlange( '1', n, n, a, lda, dum ) if( scalea ) then dum( 1_${ik}$ ) = abnrm call stdlib${ii}$_dlascl( 'G', 0_${ik}$, 0_${ik}$, cscale, anrm, 1_${ik}$, 1_${ik}$, dum, 1_${ik}$, ierr ) abnrm = dum( 1_${ik}$ ) end if ! reduce to upper hessenberg form ! (workspace: need 2*n, prefer n+n*nb) itau = 1_${ik}$ iwrk = itau + n call stdlib${ii}$_dgehrd( n, ilo, ihi, a, lda, work( itau ), work( iwrk ),lwork-iwrk+1, ierr & ) if( wantvl ) then ! want left eigenvectors ! copy householder vectors to vl side = 'L' call stdlib${ii}$_dlacpy( 'L', n, n, a, lda, vl, ldvl ) ! generate orthogonal matrix in vl ! (workspace: need 2*n-1, prefer n+(n-1)*nb) call stdlib${ii}$_dorghr( n, ilo, ihi, vl, ldvl, work( itau ), work( iwrk ),lwork-iwrk+1, & ierr ) ! perform qr iteration, accumulating schur vectors in vl ! (workspace: need 1, prefer hswork (see comments) ) iwrk = itau call stdlib${ii}$_dhseqr( 'S', 'V', n, ilo, ihi, a, lda, wr, wi, vl, ldvl,work( iwrk ), & lwork-iwrk+1, info ) if( wantvr ) then ! want left and right eigenvectors ! copy schur vectors to vr side = 'B' call stdlib${ii}$_dlacpy( 'F', n, n, vl, ldvl, vr, ldvr ) end if else if( wantvr ) then ! want right eigenvectors ! copy householder vectors to vr side = 'R' call stdlib${ii}$_dlacpy( 'L', n, n, a, lda, vr, ldvr ) ! generate orthogonal matrix in vr ! (workspace: need 2*n-1, prefer n+(n-1)*nb) call stdlib${ii}$_dorghr( n, ilo, ihi, vr, ldvr, work( itau ), work( iwrk ),lwork-iwrk+1, & ierr ) ! perform qr iteration, accumulating schur vectors in vr ! (workspace: need 1, prefer hswork (see comments) ) iwrk = itau call stdlib${ii}$_dhseqr( 'S', 'V', n, ilo, ihi, a, lda, wr, wi, vr, ldvr,work( iwrk ), & lwork-iwrk+1, info ) else ! compute eigenvalues only ! if condition numbers desired, compute schur form if( wntsnn ) then job = 'E' else job = 'S' end if ! (workspace: need 1, prefer hswork (see comments) ) iwrk = itau call stdlib${ii}$_dhseqr( job, 'N', n, ilo, ihi, a, lda, wr, wi, vr, ldvr,work( iwrk ), & lwork-iwrk+1, info ) end if ! if info /= 0 from stdlib${ii}$_dhseqr, then quit if( info/=0 )go to 50 if( wantvl .or. wantvr ) then ! compute left and/or right eigenvectors ! (workspace: need 3*n, prefer n + 2*n*nb) call stdlib${ii}$_dtrevc3( side, 'B', select, n, a, lda, vl, ldvl, vr, ldvr,n, nout, work(& iwrk ), lwork-iwrk+1, ierr ) end if ! compute condition numbers if desired ! (workspace: need n*n+6*n unless sense = 'e') if( .not.wntsnn ) then call stdlib${ii}$_dtrsna( sense, 'A', select, n, a, lda, vl, ldvl, vr, ldvr,rconde, & rcondv, n, nout, work( iwrk ), n, iwork,icond ) end if if( wantvl ) then ! undo balancing of left eigenvectors call stdlib${ii}$_dgebak( balanc, 'L', n, ilo, ihi, scale, n, vl, ldvl,ierr ) ! normalize left eigenvectors and make largest component real do i = 1, n if( wi( i )==zero ) then scl = one / stdlib${ii}$_dnrm2( n, vl( 1_${ik}$, i ), 1_${ik}$ ) call stdlib${ii}$_dscal( n, scl, vl( 1_${ik}$, i ), 1_${ik}$ ) else if( wi( i )>zero ) then scl = one / stdlib${ii}$_dlapy2( stdlib${ii}$_dnrm2( n, vl( 1_${ik}$, i ), 1_${ik}$ ),stdlib${ii}$_dnrm2( n, & vl( 1_${ik}$, i+1 ), 1_${ik}$ ) ) call stdlib${ii}$_dscal( n, scl, vl( 1_${ik}$, i ), 1_${ik}$ ) call stdlib${ii}$_dscal( n, scl, vl( 1_${ik}$, i+1 ), 1_${ik}$ ) do k = 1, n work( k ) = vl( k, i )**2_${ik}$ + vl( k, i+1 )**2_${ik}$ end do k = stdlib${ii}$_idamax( n, work, 1_${ik}$ ) call stdlib${ii}$_dlartg( vl( k, i ), vl( k, i+1 ), cs, sn, r ) call stdlib${ii}$_drot( n, vl( 1_${ik}$, i ), 1_${ik}$, vl( 1_${ik}$, i+1 ), 1_${ik}$, cs, sn ) vl( k, i+1 ) = zero end if end do end if if( wantvr ) then ! undo balancing of right eigenvectors call stdlib${ii}$_dgebak( balanc, 'R', n, ilo, ihi, scale, n, vr, ldvr,ierr ) ! normalize right eigenvectors and make largest component real do i = 1, n if( wi( i )==zero ) then scl = one / stdlib${ii}$_dnrm2( n, vr( 1_${ik}$, i ), 1_${ik}$ ) call stdlib${ii}$_dscal( n, scl, vr( 1_${ik}$, i ), 1_${ik}$ ) else if( wi( i )>zero ) then scl = one / stdlib${ii}$_dlapy2( stdlib${ii}$_dnrm2( n, vr( 1_${ik}$, i ), 1_${ik}$ ),stdlib${ii}$_dnrm2( n, & vr( 1_${ik}$, i+1 ), 1_${ik}$ ) ) call stdlib${ii}$_dscal( n, scl, vr( 1_${ik}$, i ), 1_${ik}$ ) call stdlib${ii}$_dscal( n, scl, vr( 1_${ik}$, i+1 ), 1_${ik}$ ) do k = 1, n work( k ) = vr( k, i )**2_${ik}$ + vr( k, i+1 )**2_${ik}$ end do k = stdlib${ii}$_idamax( n, work, 1_${ik}$ ) call stdlib${ii}$_dlartg( vr( k, i ), vr( k, i+1 ), cs, sn, r ) call stdlib${ii}$_drot( n, vr( 1_${ik}$, i ), 1_${ik}$, vr( 1_${ik}$, i+1 ), 1_${ik}$, cs, sn ) vr( k, i+1 ) = zero end if end do end if ! undo scaling if necessary 50 continue if( scalea ) then call stdlib${ii}$_dlascl( 'G', 0_${ik}$, 0_${ik}$, cscale, anrm, n-info, 1_${ik}$, wr( info+1 ),max( n-info, 1_${ik}$ & ), ierr ) call stdlib${ii}$_dlascl( 'G', 0_${ik}$, 0_${ik}$, cscale, anrm, n-info, 1_${ik}$, wi( info+1 ),max( n-info, 1_${ik}$ & ), ierr ) if( info==0_${ik}$ ) then if( ( wntsnv .or. wntsnb ) .and. icond==0_${ik}$ )call stdlib${ii}$_dlascl( 'G', 0_${ik}$, 0_${ik}$, cscale,& anrm, n, 1_${ik}$, rcondv, n,ierr ) else call stdlib${ii}$_dlascl( 'G', 0_${ik}$, 0_${ik}$, cscale, anrm, ilo-1, 1_${ik}$, wr, n,ierr ) call stdlib${ii}$_dlascl( 'G', 0_${ik}$, 0_${ik}$, cscale, anrm, ilo-1, 1_${ik}$, wi, n,ierr ) end if end if work( 1_${ik}$ ) = maxwrk return end subroutine stdlib${ii}$_dgeevx #:for rk,rt,ri in REAL_KINDS_TYPES #:if not rk in ["sp","dp"] module subroutine stdlib${ii}$_${ri}$geevx( balanc, jobvl, jobvr, sense, n, a, lda, wr, wi,vl, ldvl, vr, ldvr, & !! DGEEVX: computes for an N-by-N real nonsymmetric matrix A, the !! eigenvalues and, optionally, the left and/or right eigenvectors. !! Optionally also, it computes a balancing transformation to improve !! the conditioning of the eigenvalues and eigenvectors (ILO, IHI, !! SCALE, and ABNRM), reciprocal condition numbers for the eigenvalues !! (RCONDE), and reciprocal condition numbers for the right !! eigenvectors (RCONDV). !! The right eigenvector v(j) of A satisfies !! A * v(j) = lambda(j) * v(j) !! where lambda(j) is its eigenvalue. !! The left eigenvector u(j) of A satisfies !! u(j)**H * A = lambda(j) * u(j)**H !! where u(j)**H denotes the conjugate-transpose of u(j). !! The computed eigenvectors are normalized to have Euclidean norm !! equal to 1 and largest component real. !! Balancing a matrix means permuting the rows and columns to make it !! more nearly upper triangular, and applying a diagonal similarity !! transformation D * A * D**(-1), where D is a diagonal matrix, to !! make its rows and columns closer in norm and the condition numbers !! of its eigenvalues and eigenvectors smaller. The computed !! reciprocal condition numbers correspond to the balanced matrix. !! Permuting rows and columns will not change the condition numbers !! (in exact arithmetic) but diagonal scaling will. For further !! explanation of balancing, see section 4.10.2_${rk}$ of the LAPACK !! Users' Guide. ilo, ihi, scale, abnrm,rconde, rcondv, work, lwork, iwork, info ) ! -- lapack driver routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_${rk}$, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments character, intent(in) :: balanc, jobvl, jobvr, sense integer(${ik}$), intent(out) :: ihi, ilo, info integer(${ik}$), intent(in) :: lda, ldvl, ldvr, lwork, n real(${rk}$), intent(out) :: abnrm ! Array Arguments integer(${ik}$), intent(out) :: iwork(*) real(${rk}$), intent(inout) :: a(lda,*) real(${rk}$), intent(out) :: rconde(*), rcondv(*), scale(*), vl(ldvl,*), vr(ldvr,*), wi(*),& work(*), wr(*) ! ===================================================================== ! Local Scalars logical(lk) :: lquery, scalea, wantvl, wantvr, wntsnb, wntsne, wntsnn, wntsnv character :: job, side integer(${ik}$) :: hswork, i, icond, ierr, itau, iwrk, k, lwork_trevc, maxwrk, minwrk, & nout real(${rk}$) :: anrm, bignum, cs, cscale, eps, r, scl, smlnum, sn ! Local Arrays logical(lk) :: select(1_${ik}$) real(${rk}$) :: dum(1_${ik}$) ! Intrinsic Functions ! Executable Statements ! test the input arguments info = 0_${ik}$ lquery = ( lwork==-1_${ik}$ ) wantvl = stdlib_lsame( jobvl, 'V' ) wantvr = stdlib_lsame( jobvr, 'V' ) wntsnn = stdlib_lsame( sense, 'N' ) wntsne = stdlib_lsame( sense, 'E' ) wntsnv = stdlib_lsame( sense, 'V' ) wntsnb = stdlib_lsame( sense, 'B' ) if( .not.( stdlib_lsame( balanc, 'N' ) .or. stdlib_lsame( balanc, 'S' ).or. & stdlib_lsame( balanc, 'P' ) .or. stdlib_lsame( balanc, 'B' ) ) )then info = -1_${ik}$ else if( ( .not.wantvl ) .and. ( .not.stdlib_lsame( jobvl, 'N' ) ) ) then info = -2_${ik}$ else if( ( .not.wantvr ) .and. ( .not.stdlib_lsame( jobvr, 'N' ) ) ) then info = -3_${ik}$ else if( .not.( wntsnn .or. wntsne .or. wntsnb .or. wntsnv ) .or.( ( wntsne .or. & wntsnb ) .and. .not.( wantvl .and.wantvr ) ) ) then info = -4_${ik}$ else if( n<0_${ik}$ ) then info = -5_${ik}$ else if( lda<max( 1_${ik}$, n ) ) then info = -7_${ik}$ else if( ldvl<1_${ik}$ .or. ( wantvl .and. ldvl<n ) ) then info = -11_${ik}$ else if( ldvr<1_${ik}$ .or. ( wantvr .and. ldvr<n ) ) then info = -13_${ik}$ end if ! compute workspace ! (note: comments in the code beginning "workspace:" describe the ! minimal amount of workspace needed at that point in the code, ! as well as the preferred amount for good performance. ! nb refers to the optimal block size for the immediately ! following subroutine, as returned by stdlib${ii}$_ilaenv. ! hswork refers to the workspace preferred by stdlib${ii}$_${ri}$hseqr, as ! calculated below. hswork is computed assuming ilo=1 and ihi=n, ! the worst case.) if( info==0_${ik}$ ) then if( n==0_${ik}$ ) then minwrk = 1_${ik}$ maxwrk = 1_${ik}$ else maxwrk = n + n*stdlib${ii}$_ilaenv( 1_${ik}$, 'DGEHRD', ' ', n, 1_${ik}$, n, 0_${ik}$ ) if( wantvl ) then call stdlib${ii}$_${ri}$trevc3( 'L', 'B', select, n, a, lda,vl, ldvl, vr, ldvr,n, nout, & work, -1_${ik}$, ierr ) lwork_trevc = int( work(1_${ik}$),KIND=${ik}$) maxwrk = max( maxwrk, n + lwork_trevc ) call stdlib${ii}$_${ri}$hseqr( 'S', 'V', n, 1_${ik}$, n, a, lda, wr, wi, vl, ldvl,work, -1_${ik}$, & info ) else if( wantvr ) then call stdlib${ii}$_${ri}$trevc3( 'R', 'B', select, n, a, lda,vl, ldvl, vr, ldvr,n, nout, & work, -1_${ik}$, ierr ) lwork_trevc = int( work(1_${ik}$),KIND=${ik}$) maxwrk = max( maxwrk, n + lwork_trevc ) call stdlib${ii}$_${ri}$hseqr( 'S', 'V', n, 1_${ik}$, n, a, lda, wr, wi, vr, ldvr,work, -1_${ik}$, & info ) else if( wntsnn ) then call stdlib${ii}$_${ri}$hseqr( 'E', 'N', n, 1_${ik}$, n, a, lda, wr, wi, vr,ldvr, work, -1_${ik}$, & info ) else call stdlib${ii}$_${ri}$hseqr( 'S', 'N', n, 1_${ik}$, n, a, lda, wr, wi, vr,ldvr, work, -1_${ik}$, & info ) end if end if hswork = int( work(1_${ik}$),KIND=${ik}$) if( ( .not.wantvl ) .and. ( .not.wantvr ) ) then minwrk = 2_${ik}$*n if( .not.wntsnn )minwrk = max( minwrk, n*n+6*n ) maxwrk = max( maxwrk, hswork ) if( .not.wntsnn )maxwrk = max( maxwrk, n*n + 6_${ik}$*n ) else minwrk = 3_${ik}$*n if( ( .not.wntsnn ) .and. ( .not.wntsne ) )minwrk = max( minwrk, n*n + 6_${ik}$*n ) maxwrk = max( maxwrk, hswork ) maxwrk = max( maxwrk, n + ( n - 1_${ik}$ )*stdlib${ii}$_ilaenv( 1_${ik}$, 'DORGHR',' ', n, 1_${ik}$, n, -& 1_${ik}$ ) ) if( ( .not.wntsnn ) .and. ( .not.wntsne ) )maxwrk = max( maxwrk, n*n + 6_${ik}$*n ) maxwrk = max( maxwrk, 3_${ik}$*n ) end if maxwrk = max( maxwrk, minwrk ) end if work( 1_${ik}$ ) = maxwrk if( lwork<minwrk .and. .not.lquery ) then info = -21_${ik}$ end if end if if( info/=0_${ik}$ ) then call stdlib${ii}$_xerbla( 'DGEEVX', -info ) return else if( lquery ) then return end if ! quick return if possible if( n==0 )return ! get machine constants eps = stdlib${ii}$_${ri}$lamch( 'P' ) smlnum = stdlib${ii}$_${ri}$lamch( 'S' ) bignum = one / smlnum call stdlib${ii}$_${ri}$labad( smlnum, bignum ) smlnum = sqrt( smlnum ) / eps bignum = one / smlnum ! scale a if max element outside range [smlnum,bignum] icond = 0_${ik}$ anrm = stdlib${ii}$_${ri}$lange( 'M', n, n, a, lda, dum ) scalea = .false. if( anrm>zero .and. anrm<smlnum ) then scalea = .true. cscale = smlnum else if( anrm>bignum ) then scalea = .true. cscale = bignum end if if( scalea )call stdlib${ii}$_${ri}$lascl( 'G', 0_${ik}$, 0_${ik}$, anrm, cscale, n, n, a, lda, ierr ) ! balance the matrix and compute abnrm call stdlib${ii}$_${ri}$gebal( balanc, n, a, lda, ilo, ihi, scale, ierr ) abnrm = stdlib${ii}$_${ri}$lange( '1', n, n, a, lda, dum ) if( scalea ) then dum( 1_${ik}$ ) = abnrm call stdlib${ii}$_${ri}$lascl( 'G', 0_${ik}$, 0_${ik}$, cscale, anrm, 1_${ik}$, 1_${ik}$, dum, 1_${ik}$, ierr ) abnrm = dum( 1_${ik}$ ) end if ! reduce to upper hessenberg form ! (workspace: need 2*n, prefer n+n*nb) itau = 1_${ik}$ iwrk = itau + n call stdlib${ii}$_${ri}$gehrd( n, ilo, ihi, a, lda, work( itau ), work( iwrk ),lwork-iwrk+1, ierr & ) if( wantvl ) then ! want left eigenvectors ! copy householder vectors to vl side = 'L' call stdlib${ii}$_${ri}$lacpy( 'L', n, n, a, lda, vl, ldvl ) ! generate orthogonal matrix in vl ! (workspace: need 2*n-1, prefer n+(n-1)*nb) call stdlib${ii}$_${ri}$orghr( n, ilo, ihi, vl, ldvl, work( itau ), work( iwrk ),lwork-iwrk+1, & ierr ) ! perform qr iteration, accumulating schur vectors in vl ! (workspace: need 1, prefer hswork (see comments) ) iwrk = itau call stdlib${ii}$_${ri}$hseqr( 'S', 'V', n, ilo, ihi, a, lda, wr, wi, vl, ldvl,work( iwrk ), & lwork-iwrk+1, info ) if( wantvr ) then ! want left and right eigenvectors ! copy schur vectors to vr side = 'B' call stdlib${ii}$_${ri}$lacpy( 'F', n, n, vl, ldvl, vr, ldvr ) end if else if( wantvr ) then ! want right eigenvectors ! copy householder vectors to vr side = 'R' call stdlib${ii}$_${ri}$lacpy( 'L', n, n, a, lda, vr, ldvr ) ! generate orthogonal matrix in vr ! (workspace: need 2*n-1, prefer n+(n-1)*nb) call stdlib${ii}$_${ri}$orghr( n, ilo, ihi, vr, ldvr, work( itau ), work( iwrk ),lwork-iwrk+1, & ierr ) ! perform qr iteration, accumulating schur vectors in vr ! (workspace: need 1, prefer hswork (see comments) ) iwrk = itau call stdlib${ii}$_${ri}$hseqr( 'S', 'V', n, ilo, ihi, a, lda, wr, wi, vr, ldvr,work( iwrk ), & lwork-iwrk+1, info ) else ! compute eigenvalues only ! if condition numbers desired, compute schur form if( wntsnn ) then job = 'E' else job = 'S' end if ! (workspace: need 1, prefer hswork (see comments) ) iwrk = itau call stdlib${ii}$_${ri}$hseqr( job, 'N', n, ilo, ihi, a, lda, wr, wi, vr, ldvr,work( iwrk ), & lwork-iwrk+1, info ) end if ! if info /= 0 from stdlib${ii}$_${ri}$hseqr, then quit if( info/=0 )go to 50 if( wantvl .or. wantvr ) then ! compute left and/or right eigenvectors ! (workspace: need 3*n, prefer n + 2*n*nb) call stdlib${ii}$_${ri}$trevc3( side, 'B', select, n, a, lda, vl, ldvl, vr, ldvr,n, nout, work(& iwrk ), lwork-iwrk+1, ierr ) end if ! compute condition numbers if desired ! (workspace: need n*n+6*n unless sense = 'e') if( .not.wntsnn ) then call stdlib${ii}$_${ri}$trsna( sense, 'A', select, n, a, lda, vl, ldvl, vr, ldvr,rconde, & rcondv, n, nout, work( iwrk ), n, iwork,icond ) end if if( wantvl ) then ! undo balancing of left eigenvectors call stdlib${ii}$_${ri}$gebak( balanc, 'L', n, ilo, ihi, scale, n, vl, ldvl,ierr ) ! normalize left eigenvectors and make largest component real do i = 1, n if( wi( i )==zero ) then scl = one / stdlib${ii}$_${ri}$nrm2( n, vl( 1_${ik}$, i ), 1_${ik}$ ) call stdlib${ii}$_${ri}$scal( n, scl, vl( 1_${ik}$, i ), 1_${ik}$ ) else if( wi( i )>zero ) then scl = one / stdlib${ii}$_${ri}$lapy2( stdlib${ii}$_${ri}$nrm2( n, vl( 1_${ik}$, i ), 1_${ik}$ ),stdlib${ii}$_${ri}$nrm2( n, & vl( 1_${ik}$, i+1 ), 1_${ik}$ ) ) call stdlib${ii}$_${ri}$scal( n, scl, vl( 1_${ik}$, i ), 1_${ik}$ ) call stdlib${ii}$_${ri}$scal( n, scl, vl( 1_${ik}$, i+1 ), 1_${ik}$ ) do k = 1, n work( k ) = vl( k, i )**2_${ik}$ + vl( k, i+1 )**2_${ik}$ end do k = stdlib${ii}$_i${ri}$amax( n, work, 1_${ik}$ ) call stdlib${ii}$_${ri}$lartg( vl( k, i ), vl( k, i+1 ), cs, sn, r ) call stdlib${ii}$_${ri}$rot( n, vl( 1_${ik}$, i ), 1_${ik}$, vl( 1_${ik}$, i+1 ), 1_${ik}$, cs, sn ) vl( k, i+1 ) = zero end if end do end if if( wantvr ) then ! undo balancing of right eigenvectors call stdlib${ii}$_${ri}$gebak( balanc, 'R', n, ilo, ihi, scale, n, vr, ldvr,ierr ) ! normalize right eigenvectors and make largest component real do i = 1, n if( wi( i )==zero ) then scl = one / stdlib${ii}$_${ri}$nrm2( n, vr( 1_${ik}$, i ), 1_${ik}$ ) call stdlib${ii}$_${ri}$scal( n, scl, vr( 1_${ik}$, i ), 1_${ik}$ ) else if( wi( i )>zero ) then scl = one / stdlib${ii}$_${ri}$lapy2( stdlib${ii}$_${ri}$nrm2( n, vr( 1_${ik}$, i ), 1_${ik}$ ),stdlib${ii}$_${ri}$nrm2( n, & vr( 1_${ik}$, i+1 ), 1_${ik}$ ) ) call stdlib${ii}$_${ri}$scal( n, scl, vr( 1_${ik}$, i ), 1_${ik}$ ) call stdlib${ii}$_${ri}$scal( n, scl, vr( 1_${ik}$, i+1 ), 1_${ik}$ ) do k = 1, n work( k ) = vr( k, i )**2_${ik}$ + vr( k, i+1 )**2_${ik}$ end do k = stdlib${ii}$_i${ri}$amax( n, work, 1_${ik}$ ) call stdlib${ii}$_${ri}$lartg( vr( k, i ), vr( k, i+1 ), cs, sn, r ) call stdlib${ii}$_${ri}$rot( n, vr( 1_${ik}$, i ), 1_${ik}$, vr( 1_${ik}$, i+1 ), 1_${ik}$, cs, sn ) vr( k, i+1 ) = zero end if end do end if ! undo scaling if necessary 50 continue if( scalea ) then call stdlib${ii}$_${ri}$lascl( 'G', 0_${ik}$, 0_${ik}$, cscale, anrm, n-info, 1_${ik}$, wr( info+1 ),max( n-info, 1_${ik}$ & ), ierr ) call stdlib${ii}$_${ri}$lascl( 'G', 0_${ik}$, 0_${ik}$, cscale, anrm, n-info, 1_${ik}$, wi( info+1 ),max( n-info, 1_${ik}$ & ), ierr ) if( info==0_${ik}$ ) then if( ( wntsnv .or. wntsnb ) .and. icond==0_${ik}$ )call stdlib${ii}$_${ri}$lascl( 'G', 0_${ik}$, 0_${ik}$, cscale,& anrm, n, 1_${ik}$, rcondv, n,ierr ) else call stdlib${ii}$_${ri}$lascl( 'G', 0_${ik}$, 0_${ik}$, cscale, anrm, ilo-1, 1_${ik}$, wr, n,ierr ) call stdlib${ii}$_${ri}$lascl( 'G', 0_${ik}$, 0_${ik}$, cscale, anrm, ilo-1, 1_${ik}$, wi, n,ierr ) end if end if work( 1_${ik}$ ) = maxwrk return end subroutine stdlib${ii}$_${ri}$geevx #:endif #:endfor module subroutine stdlib${ii}$_cgeevx( balanc, jobvl, jobvr, sense, n, a, lda, w, vl,ldvl, vr, ldvr, ilo, & !! CGEEVX computes for an N-by-N complex nonsymmetric matrix A, the !! eigenvalues and, optionally, the left and/or right eigenvectors. !! Optionally also, it computes a balancing transformation to improve !! the conditioning of the eigenvalues and eigenvectors (ILO, IHI, !! SCALE, and ABNRM), reciprocal condition numbers for the eigenvalues !! (RCONDE), and reciprocal condition numbers for the right !! eigenvectors (RCONDV). !! The right eigenvector v(j) of A satisfies !! A * v(j) = lambda(j) * v(j) !! where lambda(j) is its eigenvalue. !! The left eigenvector u(j) of A satisfies !! u(j)**H * A = lambda(j) * u(j)**H !! where u(j)**H denotes the conjugate transpose of u(j). !! The computed eigenvectors are normalized to have Euclidean norm !! equal to 1 and largest component real. !! Balancing a matrix means permuting the rows and columns to make it !! more nearly upper triangular, and applying a diagonal similarity !! transformation D * A * D**(-1), where D is a diagonal matrix, to !! make its rows and columns closer in norm and the condition numbers !! of its eigenvalues and eigenvectors smaller. The computed !! reciprocal condition numbers correspond to the balanced matrix. !! Permuting rows and columns will not change the condition numbers !! (in exact arithmetic) but diagonal scaling will. For further !! explanation of balancing, see section 4.10.2_sp of the LAPACK !! Users' Guide. ihi, scale, abnrm, rconde,rcondv, work, lwork, rwork, info ) ! -- lapack driver routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_sp, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments character, intent(in) :: balanc, jobvl, jobvr, sense integer(${ik}$), intent(out) :: ihi, ilo, info integer(${ik}$), intent(in) :: lda, ldvl, ldvr, lwork, n real(sp), intent(out) :: abnrm ! Array Arguments real(sp), intent(out) :: rconde(*), rcondv(*), rwork(*), scale(*) complex(sp), intent(inout) :: a(lda,*) complex(sp), intent(out) :: vl(ldvl,*), vr(ldvr,*), w(*), work(*) ! ===================================================================== ! Local Scalars logical(lk) :: lquery, scalea, wantvl, wantvr, wntsnb, wntsne, wntsnn, wntsnv character :: job, side integer(${ik}$) :: hswork, i, icond, ierr, itau, iwrk, k, lwork_trevc, maxwrk, minwrk, & nout real(sp) :: anrm, bignum, cscale, eps, scl, smlnum complex(sp) :: tmp ! Local Arrays logical(lk) :: select(1_${ik}$) real(sp) :: dum(1_${ik}$) ! Intrinsic Functions ! Executable Statements ! test the input arguments info = 0_${ik}$ lquery = ( lwork==-1_${ik}$ ) wantvl = stdlib_lsame( jobvl, 'V' ) wantvr = stdlib_lsame( jobvr, 'V' ) wntsnn = stdlib_lsame( sense, 'N' ) wntsne = stdlib_lsame( sense, 'E' ) wntsnv = stdlib_lsame( sense, 'V' ) wntsnb = stdlib_lsame( sense, 'B' ) if( .not.( stdlib_lsame( balanc, 'N' ) .or. stdlib_lsame( balanc, 'S' ) & .or.stdlib_lsame( balanc, 'P' ) .or. stdlib_lsame( balanc, 'B' ) ) ) then info = -1_${ik}$ else if( ( .not.wantvl ) .and. ( .not.stdlib_lsame( jobvl, 'N' ) ) ) then info = -2_${ik}$ else if( ( .not.wantvr ) .and. ( .not.stdlib_lsame( jobvr, 'N' ) ) ) then info = -3_${ik}$ else if( .not.( wntsnn .or. wntsne .or. wntsnb .or. wntsnv ) .or.( ( wntsne .or. & wntsnb ) .and. .not.( wantvl .and.wantvr ) ) ) then info = -4_${ik}$ else if( n<0_${ik}$ ) then info = -5_${ik}$ else if( lda<max( 1_${ik}$, n ) ) then info = -7_${ik}$ else if( ldvl<1_${ik}$ .or. ( wantvl .and. ldvl<n ) ) then info = -10_${ik}$ else if( ldvr<1_${ik}$ .or. ( wantvr .and. ldvr<n ) ) then info = -12_${ik}$ end if ! compute workspace ! (note: comments in the code beginning "workspace:" describe the ! minimal amount of workspace needed at that point in the code, ! as well as the preferred amount for good performance. ! cworkspace refers to complex workspace, and rworkspace to real ! workspace. nb refers to the optimal block size for the ! immediately following subroutine, as returned by stdlib${ii}$_ilaenv. ! hswork refers to the workspace preferred by stdlib${ii}$_chseqr, as ! calculated below. hswork is computed assuming ilo=1 and ihi=n, ! the worst case.) if( info==0_${ik}$ ) then if( n==0_${ik}$ ) then minwrk = 1_${ik}$ maxwrk = 1_${ik}$ else maxwrk = n + n*stdlib${ii}$_ilaenv( 1_${ik}$, 'CGEHRD', ' ', n, 1_${ik}$, n, 0_${ik}$ ) if( wantvl ) then call stdlib${ii}$_ctrevc3( 'L', 'B', select, n, a, lda,vl, ldvl, vr, ldvr,n, nout, & work, -1_${ik}$, rwork, -1_${ik}$, ierr ) lwork_trevc = int( work(1_${ik}$),KIND=${ik}$) maxwrk = max( maxwrk, lwork_trevc ) call stdlib${ii}$_chseqr( 'S', 'V', n, 1_${ik}$, n, a, lda, w, vl, ldvl,work, -1_${ik}$, info ) else if( wantvr ) then call stdlib${ii}$_ctrevc3( 'R', 'B', select, n, a, lda,vl, ldvl, vr, ldvr,n, nout, & work, -1_${ik}$, rwork, -1_${ik}$, ierr ) lwork_trevc = int( work(1_${ik}$),KIND=${ik}$) maxwrk = max( maxwrk, lwork_trevc ) call stdlib${ii}$_chseqr( 'S', 'V', n, 1_${ik}$, n, a, lda, w, vr, ldvr,work, -1_${ik}$, info ) else if( wntsnn ) then call stdlib${ii}$_chseqr( 'E', 'N', n, 1_${ik}$, n, a, lda, w, vr, ldvr,work, -1_${ik}$, info ) else call stdlib${ii}$_chseqr( 'S', 'N', n, 1_${ik}$, n, a, lda, w, vr, ldvr,work, -1_${ik}$, info ) end if end if hswork = int( work(1_${ik}$),KIND=${ik}$) if( ( .not.wantvl ) .and. ( .not.wantvr ) ) then minwrk = 2_${ik}$*n if( .not.( wntsnn .or. wntsne ) )minwrk = max( minwrk, n*n + 2_${ik}$*n ) maxwrk = max( maxwrk, hswork ) if( .not.( wntsnn .or. wntsne ) )maxwrk = max( maxwrk, n*n + 2_${ik}$*n ) else minwrk = 2_${ik}$*n if( .not.( wntsnn .or. wntsne ) )minwrk = max( minwrk, n*n + 2_${ik}$*n ) maxwrk = max( maxwrk, hswork ) maxwrk = max( maxwrk, n + ( n - 1_${ik}$ )*stdlib${ii}$_ilaenv( 1_${ik}$, 'CUNGHR',' ', n, 1_${ik}$, n, -& 1_${ik}$ ) ) if( .not.( wntsnn .or. wntsne ) )maxwrk = max( maxwrk, n*n + 2_${ik}$*n ) maxwrk = max( maxwrk, 2_${ik}$*n ) end if maxwrk = max( maxwrk, minwrk ) end if work( 1_${ik}$ ) = maxwrk if( lwork<minwrk .and. .not.lquery ) then info = -20_${ik}$ end if end if if( info/=0_${ik}$ ) then call stdlib${ii}$_xerbla( 'CGEEVX', -info ) return else if( lquery ) then return end if ! quick return if possible if( n==0 )return ! get machine constants eps = stdlib${ii}$_slamch( 'P' ) smlnum = stdlib${ii}$_slamch( 'S' ) bignum = one / smlnum call stdlib${ii}$_slabad( smlnum, bignum ) smlnum = sqrt( smlnum ) / eps bignum = one / smlnum ! scale a if max element outside range [smlnum,bignum] icond = 0_${ik}$ anrm = stdlib${ii}$_clange( 'M', n, n, a, lda, dum ) scalea = .false. if( anrm>zero .and. anrm<smlnum ) then scalea = .true. cscale = smlnum else if( anrm>bignum ) then scalea = .true. cscale = bignum end if if( scalea )call stdlib${ii}$_clascl( 'G', 0_${ik}$, 0_${ik}$, anrm, cscale, n, n, a, lda, ierr ) ! balance the matrix and compute abnrm call stdlib${ii}$_cgebal( balanc, n, a, lda, ilo, ihi, scale, ierr ) abnrm = stdlib${ii}$_clange( '1', n, n, a, lda, dum ) if( scalea ) then dum( 1_${ik}$ ) = abnrm call stdlib${ii}$_slascl( 'G', 0_${ik}$, 0_${ik}$, cscale, anrm, 1_${ik}$, 1_${ik}$, dum, 1_${ik}$, ierr ) abnrm = dum( 1_${ik}$ ) end if ! reduce to upper hessenberg form ! (cworkspace: need 2*n, prefer n+n*nb) ! (rworkspace: none) itau = 1_${ik}$ iwrk = itau + n call stdlib${ii}$_cgehrd( n, ilo, ihi, a, lda, work( itau ), work( iwrk ),lwork-iwrk+1, ierr & ) if( wantvl ) then ! want left eigenvectors ! copy householder vectors to vl side = 'L' call stdlib${ii}$_clacpy( 'L', n, n, a, lda, vl, ldvl ) ! generate unitary matrix in vl ! (cworkspace: need 2*n-1, prefer n+(n-1)*nb) ! (rworkspace: none) call stdlib${ii}$_cunghr( n, ilo, ihi, vl, ldvl, work( itau ), work( iwrk ),lwork-iwrk+1, & ierr ) ! perform qr iteration, accumulating schur vectors in vl ! (cworkspace: need 1, prefer hswork (see comments) ) ! (rworkspace: none) iwrk = itau call stdlib${ii}$_chseqr( 'S', 'V', n, ilo, ihi, a, lda, w, vl, ldvl,work( iwrk ), lwork-& iwrk+1, info ) if( wantvr ) then ! want left and right eigenvectors ! copy schur vectors to vr side = 'B' call stdlib${ii}$_clacpy( 'F', n, n, vl, ldvl, vr, ldvr ) end if else if( wantvr ) then ! want right eigenvectors ! copy householder vectors to vr side = 'R' call stdlib${ii}$_clacpy( 'L', n, n, a, lda, vr, ldvr ) ! generate unitary matrix in vr ! (cworkspace: need 2*n-1, prefer n+(n-1)*nb) ! (rworkspace: none) call stdlib${ii}$_cunghr( n, ilo, ihi, vr, ldvr, work( itau ), work( iwrk ),lwork-iwrk+1, & ierr ) ! perform qr iteration, accumulating schur vectors in vr ! (cworkspace: need 1, prefer hswork (see comments) ) ! (rworkspace: none) iwrk = itau call stdlib${ii}$_chseqr( 'S', 'V', n, ilo, ihi, a, lda, w, vr, ldvr,work( iwrk ), lwork-& iwrk+1, info ) else ! compute eigenvalues only ! if condition numbers desired, compute schur form if( wntsnn ) then job = 'E' else job = 'S' end if ! (cworkspace: need 1, prefer hswork (see comments) ) ! (rworkspace: none) iwrk = itau call stdlib${ii}$_chseqr( job, 'N', n, ilo, ihi, a, lda, w, vr, ldvr,work( iwrk ), lwork-& iwrk+1, info ) end if ! if info /= 0 from stdlib${ii}$_chseqr, then quit if( info/=0 )go to 50 if( wantvl .or. wantvr ) then ! compute left and/or right eigenvectors ! (cworkspace: need 2*n, prefer n + 2*n*nb) ! (rworkspace: need n) call stdlib${ii}$_ctrevc3( side, 'B', select, n, a, lda, vl, ldvl, vr, ldvr,n, nout, work(& iwrk ), lwork-iwrk+1,rwork, n, ierr ) end if ! compute condition numbers if desired ! (cworkspace: need n*n+2*n unless sense = 'e') ! (rworkspace: need 2*n unless sense = 'e') if( .not.wntsnn ) then call stdlib${ii}$_ctrsna( sense, 'A', select, n, a, lda, vl, ldvl, vr, ldvr,rconde, & rcondv, n, nout, work( iwrk ), n, rwork,icond ) end if if( wantvl ) then ! undo balancing of left eigenvectors call stdlib${ii}$_cgebak( balanc, 'L', n, ilo, ihi, scale, n, vl, ldvl,ierr ) ! normalize left eigenvectors and make largest component real do i = 1, n scl = one / stdlib${ii}$_scnrm2( n, vl( 1_${ik}$, i ), 1_${ik}$ ) call stdlib${ii}$_csscal( n, scl, vl( 1_${ik}$, i ), 1_${ik}$ ) do k = 1, n rwork( k ) = real( vl( k, i ),KIND=sp)**2_${ik}$ +aimag( vl( k, i ) )**2_${ik}$ end do k = stdlib${ii}$_isamax( n, rwork, 1_${ik}$ ) tmp = conjg( vl( k, i ) ) / sqrt( rwork( k ) ) call stdlib${ii}$_cscal( n, tmp, vl( 1_${ik}$, i ), 1_${ik}$ ) vl( k, i ) = cmplx( real( vl( k, i ),KIND=sp), zero,KIND=sp) end do end if if( wantvr ) then ! undo balancing of right eigenvectors call stdlib${ii}$_cgebak( balanc, 'R', n, ilo, ihi, scale, n, vr, ldvr,ierr ) ! normalize right eigenvectors and make largest component real do i = 1, n scl = one / stdlib${ii}$_scnrm2( n, vr( 1_${ik}$, i ), 1_${ik}$ ) call stdlib${ii}$_csscal( n, scl, vr( 1_${ik}$, i ), 1_${ik}$ ) do k = 1, n rwork( k ) = real( vr( k, i ),KIND=sp)**2_${ik}$ +aimag( vr( k, i ) )**2_${ik}$ end do k = stdlib${ii}$_isamax( n, rwork, 1_${ik}$ ) tmp = conjg( vr( k, i ) ) / sqrt( rwork( k ) ) call stdlib${ii}$_cscal( n, tmp, vr( 1_${ik}$, i ), 1_${ik}$ ) vr( k, i ) = cmplx( real( vr( k, i ),KIND=sp), zero,KIND=sp) end do end if ! undo scaling if necessary 50 continue if( scalea ) then call stdlib${ii}$_clascl( 'G', 0_${ik}$, 0_${ik}$, cscale, anrm, n-info, 1_${ik}$, w( info+1 ),max( n-info, 1_${ik}$ )& , ierr ) if( info==0_${ik}$ ) then if( ( wntsnv .or. wntsnb ) .and. icond==0_${ik}$ )call stdlib${ii}$_slascl( 'G', 0_${ik}$, 0_${ik}$, cscale,& anrm, n, 1_${ik}$, rcondv, n,ierr ) else call stdlib${ii}$_clascl( 'G', 0_${ik}$, 0_${ik}$, cscale, anrm, ilo-1, 1_${ik}$, w, n, ierr ) end if end if work( 1_${ik}$ ) = maxwrk return end subroutine stdlib${ii}$_cgeevx module subroutine stdlib${ii}$_zgeevx( balanc, jobvl, jobvr, sense, n, a, lda, w, vl,ldvl, vr, ldvr, ilo, & !! ZGEEVX computes for an N-by-N complex nonsymmetric matrix A, the !! eigenvalues and, optionally, the left and/or right eigenvectors. !! Optionally also, it computes a balancing transformation to improve !! the conditioning of the eigenvalues and eigenvectors (ILO, IHI, !! SCALE, and ABNRM), reciprocal condition numbers for the eigenvalues !! (RCONDE), and reciprocal condition numbers for the right !! eigenvectors (RCONDV). !! The right eigenvector v(j) of A satisfies !! A * v(j) = lambda(j) * v(j) !! where lambda(j) is its eigenvalue. !! The left eigenvector u(j) of A satisfies !! u(j)**H * A = lambda(j) * u(j)**H !! where u(j)**H denotes the conjugate transpose of u(j). !! The computed eigenvectors are normalized to have Euclidean norm !! equal to 1 and largest component real. !! Balancing a matrix means permuting the rows and columns to make it !! more nearly upper triangular, and applying a diagonal similarity !! transformation D * A * D**(-1), where D is a diagonal matrix, to !! make its rows and columns closer in norm and the condition numbers !! of its eigenvalues and eigenvectors smaller. The computed !! reciprocal condition numbers correspond to the balanced matrix. !! Permuting rows and columns will not change the condition numbers !! (in exact arithmetic) but diagonal scaling will. For further !! explanation of balancing, see section 4.10.2_dp of the LAPACK !! Users' Guide. ihi, scale, abnrm, rconde,rcondv, work, lwork, rwork, info ) ! -- lapack driver routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_dp, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments character, intent(in) :: balanc, jobvl, jobvr, sense integer(${ik}$), intent(out) :: ihi, ilo, info integer(${ik}$), intent(in) :: lda, ldvl, ldvr, lwork, n real(dp), intent(out) :: abnrm ! Array Arguments real(dp), intent(out) :: rconde(*), rcondv(*), rwork(*), scale(*) complex(dp), intent(inout) :: a(lda,*) complex(dp), intent(out) :: vl(ldvl,*), vr(ldvr,*), w(*), work(*) ! ===================================================================== ! Local Scalars logical(lk) :: lquery, scalea, wantvl, wantvr, wntsnb, wntsne, wntsnn, wntsnv character :: job, side integer(${ik}$) :: hswork, i, icond, ierr, itau, iwrk, k, lwork_trevc, maxwrk, minwrk, & nout real(dp) :: anrm, bignum, cscale, eps, scl, smlnum complex(dp) :: tmp ! Local Arrays logical(lk) :: select(1_${ik}$) real(dp) :: dum(1_${ik}$) ! Intrinsic Functions ! Executable Statements ! test the input arguments info = 0_${ik}$ lquery = ( lwork==-1_${ik}$ ) wantvl = stdlib_lsame( jobvl, 'V' ) wantvr = stdlib_lsame( jobvr, 'V' ) wntsnn = stdlib_lsame( sense, 'N' ) wntsne = stdlib_lsame( sense, 'E' ) wntsnv = stdlib_lsame( sense, 'V' ) wntsnb = stdlib_lsame( sense, 'B' ) if( .not.( stdlib_lsame( balanc, 'N' ) .or. stdlib_lsame( balanc, 'S' ) & .or.stdlib_lsame( balanc, 'P' ) .or. stdlib_lsame( balanc, 'B' ) ) ) then info = -1_${ik}$ else if( ( .not.wantvl ) .and. ( .not.stdlib_lsame( jobvl, 'N' ) ) ) then info = -2_${ik}$ else if( ( .not.wantvr ) .and. ( .not.stdlib_lsame( jobvr, 'N' ) ) ) then info = -3_${ik}$ else if( .not.( wntsnn .or. wntsne .or. wntsnb .or. wntsnv ) .or.( ( wntsne .or. & wntsnb ) .and. .not.( wantvl .and.wantvr ) ) ) then info = -4_${ik}$ else if( n<0_${ik}$ ) then info = -5_${ik}$ else if( lda<max( 1_${ik}$, n ) ) then info = -7_${ik}$ else if( ldvl<1_${ik}$ .or. ( wantvl .and. ldvl<n ) ) then info = -10_${ik}$ else if( ldvr<1_${ik}$ .or. ( wantvr .and. ldvr<n ) ) then info = -12_${ik}$ end if ! compute workspace ! (note: comments in the code beginning "workspace:" describe the ! minimal amount of workspace needed at that point in the code, ! as well as the preferred amount for good performance. ! cworkspace refers to complex workspace, and rworkspace to real ! workspace. nb refers to the optimal block size for the ! immediately following subroutine, as returned by stdlib${ii}$_ilaenv. ! hswork refers to the workspace preferred by stdlib${ii}$_zhseqr, as ! calculated below. hswork is computed assuming ilo=1 and ihi=n, ! the worst case.) if( info==0_${ik}$ ) then if( n==0_${ik}$ ) then minwrk = 1_${ik}$ maxwrk = 1_${ik}$ else maxwrk = n + n*stdlib${ii}$_ilaenv( 1_${ik}$, 'ZGEHRD', ' ', n, 1_${ik}$, n, 0_${ik}$ ) if( wantvl ) then call stdlib${ii}$_ztrevc3( 'L', 'B', select, n, a, lda,vl, ldvl, vr, ldvr,n, nout, & work, -1_${ik}$, rwork, -1_${ik}$, ierr ) lwork_trevc = int( work(1_${ik}$),KIND=${ik}$) maxwrk = max( maxwrk, lwork_trevc ) call stdlib${ii}$_zhseqr( 'S', 'V', n, 1_${ik}$, n, a, lda, w, vl, ldvl,work, -1_${ik}$, info ) else if( wantvr ) then call stdlib${ii}$_ztrevc3( 'R', 'B', select, n, a, lda,vl, ldvl, vr, ldvr,n, nout, & work, -1_${ik}$, rwork, -1_${ik}$, ierr ) lwork_trevc = int( work(1_${ik}$),KIND=${ik}$) maxwrk = max( maxwrk, lwork_trevc ) call stdlib${ii}$_zhseqr( 'S', 'V', n, 1_${ik}$, n, a, lda, w, vr, ldvr,work, -1_${ik}$, info ) else if( wntsnn ) then call stdlib${ii}$_zhseqr( 'E', 'N', n, 1_${ik}$, n, a, lda, w, vr, ldvr,work, -1_${ik}$, info ) else call stdlib${ii}$_zhseqr( 'S', 'N', n, 1_${ik}$, n, a, lda, w, vr, ldvr,work, -1_${ik}$, info ) end if end if hswork = int( work(1_${ik}$),KIND=${ik}$) if( ( .not.wantvl ) .and. ( .not.wantvr ) ) then minwrk = 2_${ik}$*n if( .not.( wntsnn .or. wntsne ) )minwrk = max( minwrk, n*n + 2_${ik}$*n ) maxwrk = max( maxwrk, hswork ) if( .not.( wntsnn .or. wntsne ) )maxwrk = max( maxwrk, n*n + 2_${ik}$*n ) else minwrk = 2_${ik}$*n if( .not.( wntsnn .or. wntsne ) )minwrk = max( minwrk, n*n + 2_${ik}$*n ) maxwrk = max( maxwrk, hswork ) maxwrk = max( maxwrk, n + ( n - 1_${ik}$ )*stdlib${ii}$_ilaenv( 1_${ik}$, 'ZUNGHR',' ', n, 1_${ik}$, n, -& 1_${ik}$ ) ) if( .not.( wntsnn .or. wntsne ) )maxwrk = max( maxwrk, n*n + 2_${ik}$*n ) maxwrk = max( maxwrk, 2_${ik}$*n ) end if maxwrk = max( maxwrk, minwrk ) end if work( 1_${ik}$ ) = maxwrk if( lwork<minwrk .and. .not.lquery ) then info = -20_${ik}$ end if end if if( info/=0_${ik}$ ) then call stdlib${ii}$_xerbla( 'ZGEEVX', -info ) return else if( lquery ) then return end if ! quick return if possible if( n==0 )return ! get machine constants eps = stdlib${ii}$_dlamch( 'P' ) smlnum = stdlib${ii}$_dlamch( 'S' ) bignum = one / smlnum call stdlib${ii}$_dlabad( smlnum, bignum ) smlnum = sqrt( smlnum ) / eps bignum = one / smlnum ! scale a if max element outside range [smlnum,bignum] icond = 0_${ik}$ anrm = stdlib${ii}$_zlange( 'M', n, n, a, lda, dum ) scalea = .false. if( anrm>zero .and. anrm<smlnum ) then scalea = .true. cscale = smlnum else if( anrm>bignum ) then scalea = .true. cscale = bignum end if if( scalea )call stdlib${ii}$_zlascl( 'G', 0_${ik}$, 0_${ik}$, anrm, cscale, n, n, a, lda, ierr ) ! balance the matrix and compute abnrm call stdlib${ii}$_zgebal( balanc, n, a, lda, ilo, ihi, scale, ierr ) abnrm = stdlib${ii}$_zlange( '1', n, n, a, lda, dum ) if( scalea ) then dum( 1_${ik}$ ) = abnrm call stdlib${ii}$_dlascl( 'G', 0_${ik}$, 0_${ik}$, cscale, anrm, 1_${ik}$, 1_${ik}$, dum, 1_${ik}$, ierr ) abnrm = dum( 1_${ik}$ ) end if ! reduce to upper hessenberg form ! (cworkspace: need 2*n, prefer n+n*nb) ! (rworkspace: none) itau = 1_${ik}$ iwrk = itau + n call stdlib${ii}$_zgehrd( n, ilo, ihi, a, lda, work( itau ), work( iwrk ),lwork-iwrk+1, ierr & ) if( wantvl ) then ! want left eigenvectors ! copy householder vectors to vl side = 'L' call stdlib${ii}$_zlacpy( 'L', n, n, a, lda, vl, ldvl ) ! generate unitary matrix in vl ! (cworkspace: need 2*n-1, prefer n+(n-1)*nb) ! (rworkspace: none) call stdlib${ii}$_zunghr( n, ilo, ihi, vl, ldvl, work( itau ), work( iwrk ),lwork-iwrk+1, & ierr ) ! perform qr iteration, accumulating schur vectors in vl ! (cworkspace: need 1, prefer hswork (see comments) ) ! (rworkspace: none) iwrk = itau call stdlib${ii}$_zhseqr( 'S', 'V', n, ilo, ihi, a, lda, w, vl, ldvl,work( iwrk ), lwork-& iwrk+1, info ) if( wantvr ) then ! want left and right eigenvectors ! copy schur vectors to vr side = 'B' call stdlib${ii}$_zlacpy( 'F', n, n, vl, ldvl, vr, ldvr ) end if else if( wantvr ) then ! want right eigenvectors ! copy householder vectors to vr side = 'R' call stdlib${ii}$_zlacpy( 'L', n, n, a, lda, vr, ldvr ) ! generate unitary matrix in vr ! (cworkspace: need 2*n-1, prefer n+(n-1)*nb) ! (rworkspace: none) call stdlib${ii}$_zunghr( n, ilo, ihi, vr, ldvr, work( itau ), work( iwrk ),lwork-iwrk+1, & ierr ) ! perform qr iteration, accumulating schur vectors in vr ! (cworkspace: need 1, prefer hswork (see comments) ) ! (rworkspace: none) iwrk = itau call stdlib${ii}$_zhseqr( 'S', 'V', n, ilo, ihi, a, lda, w, vr, ldvr,work( iwrk ), lwork-& iwrk+1, info ) else ! compute eigenvalues only ! if condition numbers desired, compute schur form if( wntsnn ) then job = 'E' else job = 'S' end if ! (cworkspace: need 1, prefer hswork (see comments) ) ! (rworkspace: none) iwrk = itau call stdlib${ii}$_zhseqr( job, 'N', n, ilo, ihi, a, lda, w, vr, ldvr,work( iwrk ), lwork-& iwrk+1, info ) end if ! if info /= 0 from stdlib${ii}$_zhseqr, then quit if( info/=0 )go to 50 if( wantvl .or. wantvr ) then ! compute left and/or right eigenvectors ! (cworkspace: need 2*n, prefer n + 2*n*nb) ! (rworkspace: need n) call stdlib${ii}$_ztrevc3( side, 'B', select, n, a, lda, vl, ldvl, vr, ldvr,n, nout, work(& iwrk ), lwork-iwrk+1,rwork, n, ierr ) end if ! compute condition numbers if desired ! (cworkspace: need n*n+2*n unless sense = 'e') ! (rworkspace: need 2*n unless sense = 'e') if( .not.wntsnn ) then call stdlib${ii}$_ztrsna( sense, 'A', select, n, a, lda, vl, ldvl, vr, ldvr,rconde, & rcondv, n, nout, work( iwrk ), n, rwork,icond ) end if if( wantvl ) then ! undo balancing of left eigenvectors call stdlib${ii}$_zgebak( balanc, 'L', n, ilo, ihi, scale, n, vl, ldvl,ierr ) ! normalize left eigenvectors and make largest component real do i = 1, n scl = one / stdlib${ii}$_dznrm2( n, vl( 1_${ik}$, i ), 1_${ik}$ ) call stdlib${ii}$_zdscal( n, scl, vl( 1_${ik}$, i ), 1_${ik}$ ) do k = 1, n rwork( k ) = real( vl( k, i ),KIND=dp)**2_${ik}$ +aimag( vl( k, i ) )**2_${ik}$ end do k = stdlib${ii}$_idamax( n, rwork, 1_${ik}$ ) tmp = conjg( vl( k, i ) ) / sqrt( rwork( k ) ) call stdlib${ii}$_zscal( n, tmp, vl( 1_${ik}$, i ), 1_${ik}$ ) vl( k, i ) = cmplx( real( vl( k, i ),KIND=dp), zero,KIND=dp) end do end if if( wantvr ) then ! undo balancing of right eigenvectors call stdlib${ii}$_zgebak( balanc, 'R', n, ilo, ihi, scale, n, vr, ldvr,ierr ) ! normalize right eigenvectors and make largest component real do i = 1, n scl = one / stdlib${ii}$_dznrm2( n, vr( 1_${ik}$, i ), 1_${ik}$ ) call stdlib${ii}$_zdscal( n, scl, vr( 1_${ik}$, i ), 1_${ik}$ ) do k = 1, n rwork( k ) = real( vr( k, i ),KIND=dp)**2_${ik}$ +aimag( vr( k, i ) )**2_${ik}$ end do k = stdlib${ii}$_idamax( n, rwork, 1_${ik}$ ) tmp = conjg( vr( k, i ) ) / sqrt( rwork( k ) ) call stdlib${ii}$_zscal( n, tmp, vr( 1_${ik}$, i ), 1_${ik}$ ) vr( k, i ) = cmplx( real( vr( k, i ),KIND=dp), zero,KIND=dp) end do end if ! undo scaling if necessary 50 continue if( scalea ) then call stdlib${ii}$_zlascl( 'G', 0_${ik}$, 0_${ik}$, cscale, anrm, n-info, 1_${ik}$, w( info+1 ),max( n-info, 1_${ik}$ )& , ierr ) if( info==0_${ik}$ ) then if( ( wntsnv .or. wntsnb ) .and. icond==0_${ik}$ )call stdlib${ii}$_dlascl( 'G', 0_${ik}$, 0_${ik}$, cscale,& anrm, n, 1_${ik}$, rcondv, n,ierr ) else call stdlib${ii}$_zlascl( 'G', 0_${ik}$, 0_${ik}$, cscale, anrm, ilo-1, 1_${ik}$, w, n, ierr ) end if end if work( 1_${ik}$ ) = maxwrk return end subroutine stdlib${ii}$_zgeevx #:for ck,ct,ci in CMPLX_KINDS_TYPES #:if not ck in ["sp","dp"] module subroutine stdlib${ii}$_${ci}$geevx( balanc, jobvl, jobvr, sense, n, a, lda, w, vl,ldvl, vr, ldvr, ilo, & !! ZGEEVX: computes for an N-by-N complex nonsymmetric matrix A, the !! eigenvalues and, optionally, the left and/or right eigenvectors. !! Optionally also, it computes a balancing transformation to improve !! the conditioning of the eigenvalues and eigenvectors (ILO, IHI, !! SCALE, and ABNRM), reciprocal condition numbers for the eigenvalues !! (RCONDE), and reciprocal condition numbers for the right !! eigenvectors (RCONDV). !! The right eigenvector v(j) of A satisfies !! A * v(j) = lambda(j) * v(j) !! where lambda(j) is its eigenvalue. !! The left eigenvector u(j) of A satisfies !! u(j)**H * A = lambda(j) * u(j)**H !! where u(j)**H denotes the conjugate transpose of u(j). !! The computed eigenvectors are normalized to have Euclidean norm !! equal to 1 and largest component real. !! Balancing a matrix means permuting the rows and columns to make it !! more nearly upper triangular, and applying a diagonal similarity !! transformation D * A * D**(-1), where D is a diagonal matrix, to !! make its rows and columns closer in norm and the condition numbers !! of its eigenvalues and eigenvectors smaller. The computed !! reciprocal condition numbers correspond to the balanced matrix. !! Permuting rows and columns will not change the condition numbers !! (in exact arithmetic) but diagonal scaling will. For further !! explanation of balancing, see section 4.10.2_${ck}$ of the LAPACK !! Users' Guide. ihi, scale, abnrm, rconde,rcondv, work, lwork, rwork, info ) ! -- lapack driver routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_${ck}$, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments character, intent(in) :: balanc, jobvl, jobvr, sense integer(${ik}$), intent(out) :: ihi, ilo, info integer(${ik}$), intent(in) :: lda, ldvl, ldvr, lwork, n real(${ck}$), intent(out) :: abnrm ! Array Arguments real(${ck}$), intent(out) :: rconde(*), rcondv(*), rwork(*), scale(*) complex(${ck}$), intent(inout) :: a(lda,*) complex(${ck}$), intent(out) :: vl(ldvl,*), vr(ldvr,*), w(*), work(*) ! ===================================================================== ! Local Scalars logical(lk) :: lquery, scalea, wantvl, wantvr, wntsnb, wntsne, wntsnn, wntsnv character :: job, side integer(${ik}$) :: hswork, i, icond, ierr, itau, iwrk, k, lwork_trevc, maxwrk, minwrk, & nout real(${ck}$) :: anrm, bignum, cscale, eps, scl, smlnum complex(${ck}$) :: tmp ! Local Arrays logical(lk) :: select(1_${ik}$) real(${ck}$) :: dum(1_${ik}$) ! Intrinsic Functions ! Executable Statements ! test the input arguments info = 0_${ik}$ lquery = ( lwork==-1_${ik}$ ) wantvl = stdlib_lsame( jobvl, 'V' ) wantvr = stdlib_lsame( jobvr, 'V' ) wntsnn = stdlib_lsame( sense, 'N' ) wntsne = stdlib_lsame( sense, 'E' ) wntsnv = stdlib_lsame( sense, 'V' ) wntsnb = stdlib_lsame( sense, 'B' ) if( .not.( stdlib_lsame( balanc, 'N' ) .or. stdlib_lsame( balanc, 'S' ) & .or.stdlib_lsame( balanc, 'P' ) .or. stdlib_lsame( balanc, 'B' ) ) ) then info = -1_${ik}$ else if( ( .not.wantvl ) .and. ( .not.stdlib_lsame( jobvl, 'N' ) ) ) then info = -2_${ik}$ else if( ( .not.wantvr ) .and. ( .not.stdlib_lsame( jobvr, 'N' ) ) ) then info = -3_${ik}$ else if( .not.( wntsnn .or. wntsne .or. wntsnb .or. wntsnv ) .or.( ( wntsne .or. & wntsnb ) .and. .not.( wantvl .and.wantvr ) ) ) then info = -4_${ik}$ else if( n<0_${ik}$ ) then info = -5_${ik}$ else if( lda<max( 1_${ik}$, n ) ) then info = -7_${ik}$ else if( ldvl<1_${ik}$ .or. ( wantvl .and. ldvl<n ) ) then info = -10_${ik}$ else if( ldvr<1_${ik}$ .or. ( wantvr .and. ldvr<n ) ) then info = -12_${ik}$ end if ! compute workspace ! (note: comments in the code beginning "workspace:" describe the ! minimal amount of workspace needed at that point in the code, ! as well as the preferred amount for good performance. ! cworkspace refers to complex workspace, and rworkspace to real ! workspace. nb refers to the optimal block size for the ! immediately following subroutine, as returned by stdlib${ii}$_ilaenv. ! hswork refers to the workspace preferred by stdlib${ii}$_${ci}$hseqr, as ! calculated below. hswork is computed assuming ilo=1 and ihi=n, ! the worst case.) if( info==0_${ik}$ ) then if( n==0_${ik}$ ) then minwrk = 1_${ik}$ maxwrk = 1_${ik}$ else maxwrk = n + n*stdlib${ii}$_ilaenv( 1_${ik}$, 'ZGEHRD', ' ', n, 1_${ik}$, n, 0_${ik}$ ) if( wantvl ) then call stdlib${ii}$_${ci}$trevc3( 'L', 'B', select, n, a, lda,vl, ldvl, vr, ldvr,n, nout, & work, -1_${ik}$, rwork, -1_${ik}$, ierr ) lwork_trevc = int( work(1_${ik}$),KIND=${ik}$) maxwrk = max( maxwrk, lwork_trevc ) call stdlib${ii}$_${ci}$hseqr( 'S', 'V', n, 1_${ik}$, n, a, lda, w, vl, ldvl,work, -1_${ik}$, info ) else if( wantvr ) then call stdlib${ii}$_${ci}$trevc3( 'R', 'B', select, n, a, lda,vl, ldvl, vr, ldvr,n, nout, & work, -1_${ik}$, rwork, -1_${ik}$, ierr ) lwork_trevc = int( work(1_${ik}$),KIND=${ik}$) maxwrk = max( maxwrk, lwork_trevc ) call stdlib${ii}$_${ci}$hseqr( 'S', 'V', n, 1_${ik}$, n, a, lda, w, vr, ldvr,work, -1_${ik}$, info ) else if( wntsnn ) then call stdlib${ii}$_${ci}$hseqr( 'E', 'N', n, 1_${ik}$, n, a, lda, w, vr, ldvr,work, -1_${ik}$, info ) else call stdlib${ii}$_${ci}$hseqr( 'S', 'N', n, 1_${ik}$, n, a, lda, w, vr, ldvr,work, -1_${ik}$, info ) end if end if hswork = int( work(1_${ik}$),KIND=${ik}$) if( ( .not.wantvl ) .and. ( .not.wantvr ) ) then minwrk = 2_${ik}$*n if( .not.( wntsnn .or. wntsne ) )minwrk = max( minwrk, n*n + 2_${ik}$*n ) maxwrk = max( maxwrk, hswork ) if( .not.( wntsnn .or. wntsne ) )maxwrk = max( maxwrk, n*n + 2_${ik}$*n ) else minwrk = 2_${ik}$*n if( .not.( wntsnn .or. wntsne ) )minwrk = max( minwrk, n*n + 2_${ik}$*n ) maxwrk = max( maxwrk, hswork ) maxwrk = max( maxwrk, n + ( n - 1_${ik}$ )*stdlib${ii}$_ilaenv( 1_${ik}$, 'ZUNGHR',' ', n, 1_${ik}$, n, -& 1_${ik}$ ) ) if( .not.( wntsnn .or. wntsne ) )maxwrk = max( maxwrk, n*n + 2_${ik}$*n ) maxwrk = max( maxwrk, 2_${ik}$*n ) end if maxwrk = max( maxwrk, minwrk ) end if work( 1_${ik}$ ) = maxwrk if( lwork<minwrk .and. .not.lquery ) then info = -20_${ik}$ end if end if if( info/=0_${ik}$ ) then call stdlib${ii}$_xerbla( 'ZGEEVX', -info ) return else if( lquery ) then return end if ! quick return if possible if( n==0 )return ! get machine constants eps = stdlib${ii}$_${c2ri(ci)}$lamch( 'P' ) smlnum = stdlib${ii}$_${c2ri(ci)}$lamch( 'S' ) bignum = one / smlnum call stdlib${ii}$_${c2ri(ci)}$labad( smlnum, bignum ) smlnum = sqrt( smlnum ) / eps bignum = one / smlnum ! scale a if max element outside range [smlnum,bignum] icond = 0_${ik}$ anrm = stdlib${ii}$_${ci}$lange( 'M', n, n, a, lda, dum ) scalea = .false. if( anrm>zero .and. anrm<smlnum ) then scalea = .true. cscale = smlnum else if( anrm>bignum ) then scalea = .true. cscale = bignum end if if( scalea )call stdlib${ii}$_${ci}$lascl( 'G', 0_${ik}$, 0_${ik}$, anrm, cscale, n, n, a, lda, ierr ) ! balance the matrix and compute abnrm call stdlib${ii}$_${ci}$gebal( balanc, n, a, lda, ilo, ihi, scale, ierr ) abnrm = stdlib${ii}$_${ci}$lange( '1', n, n, a, lda, dum ) if( scalea ) then dum( 1_${ik}$ ) = abnrm call stdlib${ii}$_${c2ri(ci)}$lascl( 'G', 0_${ik}$, 0_${ik}$, cscale, anrm, 1_${ik}$, 1_${ik}$, dum, 1_${ik}$, ierr ) abnrm = dum( 1_${ik}$ ) end if ! reduce to upper hessenberg form ! (cworkspace: need 2*n, prefer n+n*nb) ! (rworkspace: none) itau = 1_${ik}$ iwrk = itau + n call stdlib${ii}$_${ci}$gehrd( n, ilo, ihi, a, lda, work( itau ), work( iwrk ),lwork-iwrk+1, ierr & ) if( wantvl ) then ! want left eigenvectors ! copy householder vectors to vl side = 'L' call stdlib${ii}$_${ci}$lacpy( 'L', n, n, a, lda, vl, ldvl ) ! generate unitary matrix in vl ! (cworkspace: need 2*n-1, prefer n+(n-1)*nb) ! (rworkspace: none) call stdlib${ii}$_${ci}$unghr( n, ilo, ihi, vl, ldvl, work( itau ), work( iwrk ),lwork-iwrk+1, & ierr ) ! perform qr iteration, accumulating schur vectors in vl ! (cworkspace: need 1, prefer hswork (see comments) ) ! (rworkspace: none) iwrk = itau call stdlib${ii}$_${ci}$hseqr( 'S', 'V', n, ilo, ihi, a, lda, w, vl, ldvl,work( iwrk ), lwork-& iwrk+1, info ) if( wantvr ) then ! want left and right eigenvectors ! copy schur vectors to vr side = 'B' call stdlib${ii}$_${ci}$lacpy( 'F', n, n, vl, ldvl, vr, ldvr ) end if else if( wantvr ) then ! want right eigenvectors ! copy householder vectors to vr side = 'R' call stdlib${ii}$_${ci}$lacpy( 'L', n, n, a, lda, vr, ldvr ) ! generate unitary matrix in vr ! (cworkspace: need 2*n-1, prefer n+(n-1)*nb) ! (rworkspace: none) call stdlib${ii}$_${ci}$unghr( n, ilo, ihi, vr, ldvr, work( itau ), work( iwrk ),lwork-iwrk+1, & ierr ) ! perform qr iteration, accumulating schur vectors in vr ! (cworkspace: need 1, prefer hswork (see comments) ) ! (rworkspace: none) iwrk = itau call stdlib${ii}$_${ci}$hseqr( 'S', 'V', n, ilo, ihi, a, lda, w, vr, ldvr,work( iwrk ), lwork-& iwrk+1, info ) else ! compute eigenvalues only ! if condition numbers desired, compute schur form if( wntsnn ) then job = 'E' else job = 'S' end if ! (cworkspace: need 1, prefer hswork (see comments) ) ! (rworkspace: none) iwrk = itau call stdlib${ii}$_${ci}$hseqr( job, 'N', n, ilo, ihi, a, lda, w, vr, ldvr,work( iwrk ), lwork-& iwrk+1, info ) end if ! if info /= 0 from stdlib${ii}$_${ci}$hseqr, then quit if( info/=0 )go to 50 if( wantvl .or. wantvr ) then ! compute left and/or right eigenvectors ! (cworkspace: need 2*n, prefer n + 2*n*nb) ! (rworkspace: need n) call stdlib${ii}$_${ci}$trevc3( side, 'B', select, n, a, lda, vl, ldvl, vr, ldvr,n, nout, work(& iwrk ), lwork-iwrk+1,rwork, n, ierr ) end if ! compute condition numbers if desired ! (cworkspace: need n*n+2*n unless sense = 'e') ! (rworkspace: need 2*n unless sense = 'e') if( .not.wntsnn ) then call stdlib${ii}$_${ci}$trsna( sense, 'A', select, n, a, lda, vl, ldvl, vr, ldvr,rconde, & rcondv, n, nout, work( iwrk ), n, rwork,icond ) end if if( wantvl ) then ! undo balancing of left eigenvectors call stdlib${ii}$_${ci}$gebak( balanc, 'L', n, ilo, ihi, scale, n, vl, ldvl,ierr ) ! normalize left eigenvectors and make largest component real do i = 1, n scl = one / stdlib${ii}$_${c2ri(ci)}$znrm2( n, vl( 1_${ik}$, i ), 1_${ik}$ ) call stdlib${ii}$_${ci}$dscal( n, scl, vl( 1_${ik}$, i ), 1_${ik}$ ) do k = 1, n rwork( k ) = real( vl( k, i ),KIND=${ck}$)**2_${ik}$ +aimag( vl( k, i ) )**2_${ik}$ end do k = stdlib${ii}$_i${c2ri(ci)}$amax( n, rwork, 1_${ik}$ ) tmp = conjg( vl( k, i ) ) / sqrt( rwork( k ) ) call stdlib${ii}$_${ci}$scal( n, tmp, vl( 1_${ik}$, i ), 1_${ik}$ ) vl( k, i ) = cmplx( real( vl( k, i ),KIND=${ck}$), zero,KIND=${ck}$) end do end if if( wantvr ) then ! undo balancing of right eigenvectors call stdlib${ii}$_${ci}$gebak( balanc, 'R', n, ilo, ihi, scale, n, vr, ldvr,ierr ) ! normalize right eigenvectors and make largest component real do i = 1, n scl = one / stdlib${ii}$_${c2ri(ci)}$znrm2( n, vr( 1_${ik}$, i ), 1_${ik}$ ) call stdlib${ii}$_${ci}$dscal( n, scl, vr( 1_${ik}$, i ), 1_${ik}$ ) do k = 1, n rwork( k ) = real( vr( k, i ),KIND=${ck}$)**2_${ik}$ +aimag( vr( k, i ) )**2_${ik}$ end do k = stdlib${ii}$_i${c2ri(ci)}$amax( n, rwork, 1_${ik}$ ) tmp = conjg( vr( k, i ) ) / sqrt( rwork( k ) ) call stdlib${ii}$_${ci}$scal( n, tmp, vr( 1_${ik}$, i ), 1_${ik}$ ) vr( k, i ) = cmplx( real( vr( k, i ),KIND=${ck}$), zero,KIND=${ck}$) end do end if ! undo scaling if necessary 50 continue if( scalea ) then call stdlib${ii}$_${ci}$lascl( 'G', 0_${ik}$, 0_${ik}$, cscale, anrm, n-info, 1_${ik}$, w( info+1 ),max( n-info, 1_${ik}$ )& , ierr ) if( info==0_${ik}$ ) then if( ( wntsnv .or. wntsnb ) .and. icond==0_${ik}$ )call stdlib${ii}$_${c2ri(ci)}$lascl( 'G', 0_${ik}$, 0_${ik}$, cscale,& anrm, n, 1_${ik}$, rcondv, n,ierr ) else call stdlib${ii}$_${ci}$lascl( 'G', 0_${ik}$, 0_${ik}$, cscale, anrm, ilo-1, 1_${ik}$, w, n, ierr ) end if end if work( 1_${ik}$ ) = maxwrk return end subroutine stdlib${ii}$_${ci}$geevx #:endif #:endfor module subroutine stdlib${ii}$_sgees( jobvs, sort, select, n, a, lda, sdim, wr, wi,vs, ldvs, work, lwork, & !! SGEES computes for an N-by-N real nonsymmetric matrix A, the !! eigenvalues, the real Schur form T, and, optionally, the matrix of !! Schur vectors Z. This gives the Schur factorization A = Z*T*(Z**T). !! Optionally, it also orders the eigenvalues on the diagonal of the !! real Schur form so that selected eigenvalues are at the top left. !! The leading columns of Z then form an orthonormal basis for the !! invariant subspace corresponding to the selected eigenvalues. !! A matrix is in real Schur form if it is upper quasi-triangular with !! 1-by-1 and 2-by-2 blocks. 2-by-2 blocks will be standardized in the !! form !! [ a b ] !! [ c a ] !! where b*c < 0. The eigenvalues of such a block are a +- sqrt(bc). bwork, info ) ! -- lapack driver routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_sp, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments character, intent(in) :: jobvs, sort integer(${ik}$), intent(out) :: info, sdim integer(${ik}$), intent(in) :: lda, ldvs, lwork, n ! Array Arguments logical(lk), intent(out) :: bwork(*) real(sp), intent(inout) :: a(lda,*) real(sp), intent(out) :: vs(ldvs,*), wi(*), work(*), wr(*) ! Function Arguments procedure(stdlib_select_s) :: select ! ===================================================================== ! Local Scalars logical(lk) :: cursl, lastsl, lquery, lst2sl, scalea, wantst, wantvs integer(${ik}$) :: hswork, i, i1, i2, ibal, icond, ierr, ieval, ihi, ilo, inxt, ip, itau, & iwrk, maxwrk, minwrk real(sp) :: anrm, bignum, cscale, eps, s, sep, smlnum ! Local Arrays integer(${ik}$) :: idum(1_${ik}$) real(sp) :: dum(1_${ik}$) ! Intrinsic Functions ! Executable Statements ! test the input arguments info = 0_${ik}$ lquery = ( lwork==-1_${ik}$ ) wantvs = stdlib_lsame( jobvs, 'V' ) wantst = stdlib_lsame( sort, 'S' ) if( ( .not.wantvs ) .and. ( .not.stdlib_lsame( jobvs, 'N' ) ) ) then info = -1_${ik}$ else if( ( .not.wantst ) .and. ( .not.stdlib_lsame( sort, 'N' ) ) ) then info = -2_${ik}$ else if( n<0_${ik}$ ) then info = -4_${ik}$ else if( lda<max( 1_${ik}$, n ) ) then info = -6_${ik}$ else if( ldvs<1_${ik}$ .or. ( wantvs .and. ldvs<n ) ) then info = -11_${ik}$ end if ! compute workspace ! (note: comments in the code beginning "workspace:" describe the ! minimal amount of workspace needed at that point in the code, ! as well as the preferred amount for good performance. ! nb refers to the optimal block size for the immediately ! following subroutine, as returned by stdlib${ii}$_ilaenv. ! hswork refers to the workspace preferred by stdlib${ii}$_shseqr, as ! calculated below. hswork is computed assuming ilo=1 and ihi=n, ! the worst case.) if( info==0_${ik}$ ) then if( n==0_${ik}$ ) then minwrk = 1_${ik}$ maxwrk = 1_${ik}$ else maxwrk = 2_${ik}$*n + n*stdlib${ii}$_ilaenv( 1_${ik}$, 'SGEHRD', ' ', n, 1_${ik}$, n, 0_${ik}$ ) minwrk = 3_${ik}$*n call stdlib${ii}$_shseqr( 'S', jobvs, n, 1_${ik}$, n, a, lda, wr, wi, vs, ldvs,work, -1_${ik}$, & ieval ) hswork = work( 1_${ik}$ ) if( .not.wantvs ) then maxwrk = max( maxwrk, n + hswork ) else maxwrk = max( maxwrk, 2_${ik}$*n + ( n - 1_${ik}$ )*stdlib${ii}$_ilaenv( 1_${ik}$,'SORGHR', ' ', n, 1_${ik}$, n,& -1_${ik}$ ) ) maxwrk = max( maxwrk, n + hswork ) end if end if work( 1_${ik}$ ) = maxwrk if( lwork<minwrk .and. .not.lquery ) then info = -13_${ik}$ end if end if if( info/=0_${ik}$ ) then call stdlib${ii}$_xerbla( 'SGEES ', -info ) return else if( lquery ) then return end if ! quick return if possible if( n==0_${ik}$ ) then sdim = 0_${ik}$ return end if ! get machine constants eps = stdlib${ii}$_slamch( 'P' ) smlnum = stdlib${ii}$_slamch( 'S' ) bignum = one / smlnum call stdlib${ii}$_slabad( smlnum, bignum ) smlnum = sqrt( smlnum ) / eps bignum = one / smlnum ! scale a if max element outside range [smlnum,bignum] anrm = stdlib${ii}$_slange( 'M', n, n, a, lda, dum ) scalea = .false. if( anrm>zero .and. anrm<smlnum ) then scalea = .true. cscale = smlnum else if( anrm>bignum ) then scalea = .true. cscale = bignum end if if( scalea )call stdlib${ii}$_slascl( 'G', 0_${ik}$, 0_${ik}$, anrm, cscale, n, n, a, lda, ierr ) ! permute the matrix to make it more nearly triangular ! (workspace: need n) ibal = 1_${ik}$ call stdlib${ii}$_sgebal( 'P', n, a, lda, ilo, ihi, work( ibal ), ierr ) ! reduce to upper hessenberg form ! (workspace: need 3*n, prefer 2*n+n*nb) itau = n + ibal iwrk = n + itau call stdlib${ii}$_sgehrd( n, ilo, ihi, a, lda, work( itau ), work( iwrk ),lwork-iwrk+1, ierr & ) if( wantvs ) then ! copy householder vectors to vs call stdlib${ii}$_slacpy( 'L', n, n, a, lda, vs, ldvs ) ! generate orthogonal matrix in vs ! (workspace: need 3*n-1, prefer 2*n+(n-1)*nb) call stdlib${ii}$_sorghr( n, ilo, ihi, vs, ldvs, work( itau ), work( iwrk ),lwork-iwrk+1, & ierr ) end if sdim = 0_${ik}$ ! perform qr iteration, accumulating schur vectors in vs if desired ! (workspace: need n+1, prefer n+hswork (see comments) ) iwrk = itau call stdlib${ii}$_shseqr( 'S', jobvs, n, ilo, ihi, a, lda, wr, wi, vs, ldvs,work( iwrk ), & lwork-iwrk+1, ieval ) if( ieval>0_${ik}$ )info = ieval ! sort eigenvalues if desired if( wantst .and. info==0_${ik}$ ) then if( scalea ) then call stdlib${ii}$_slascl( 'G', 0_${ik}$, 0_${ik}$, cscale, anrm, n, 1_${ik}$, wr, n, ierr ) call stdlib${ii}$_slascl( 'G', 0_${ik}$, 0_${ik}$, cscale, anrm, n, 1_${ik}$, wi, n, ierr ) end if do i = 1, n bwork( i ) = select( wr( i ), wi( i ) ) end do ! reorder eigenvalues and transform schur vectors ! (workspace: none needed) call stdlib${ii}$_strsen( 'N', jobvs, bwork, n, a, lda, vs, ldvs, wr, wi,sdim, s, sep, & work( iwrk ), lwork-iwrk+1, idum, 1_${ik}$,icond ) if( icond>0_${ik}$ )info = n + icond end if if( wantvs ) then ! undo balancing ! (workspace: need n) call stdlib${ii}$_sgebak( 'P', 'R', n, ilo, ihi, work( ibal ), n, vs, ldvs,ierr ) end if if( scalea ) then ! undo scaling for the schur form of a call stdlib${ii}$_slascl( 'H', 0_${ik}$, 0_${ik}$, cscale, anrm, n, n, a, lda, ierr ) call stdlib${ii}$_scopy( n, a, lda+1, wr, 1_${ik}$ ) if( cscale==smlnum ) then ! if scaling back towards underflow, adjust wi if an ! offdiagonal element of a 2-by-2 block in the schur form ! underflows. if( ieval>0_${ik}$ ) then i1 = ieval + 1_${ik}$ i2 = ihi - 1_${ik}$ call stdlib${ii}$_slascl( 'G', 0_${ik}$, 0_${ik}$, cscale, anrm, ilo-1, 1_${ik}$, wi,max( ilo-1, 1_${ik}$ ), & ierr ) else if( wantst ) then i1 = 1_${ik}$ i2 = n - 1_${ik}$ else i1 = ilo i2 = ihi - 1_${ik}$ end if inxt = i1 - 1_${ik}$ loop_20: do i = i1, i2 if( i<inxt )cycle loop_20 if( wi( i )==zero ) then inxt = i + 1_${ik}$ else if( a( i+1, i )==zero ) then wi( i ) = zero wi( i+1 ) = zero else if( a( i+1, i )/=zero .and. a( i, i+1 )==zero ) then wi( i ) = zero wi( i+1 ) = zero if( i>1_${ik}$ )call stdlib${ii}$_sswap( i-1, a( 1_${ik}$, i ), 1_${ik}$, a( 1_${ik}$, i+1 ), 1_${ik}$ ) if( n>i+1 )call stdlib${ii}$_sswap( n-i-1, a( i, i+2 ), lda,a( i+1, i+2 ), & lda ) if( wantvs ) then call stdlib${ii}$_sswap( n, vs( 1_${ik}$, i ), 1_${ik}$, vs( 1_${ik}$, i+1 ), 1_${ik}$ ) end if a( i, i+1 ) = a( i+1, i ) a( i+1, i ) = zero end if inxt = i + 2_${ik}$ end if end do loop_20 end if ! undo scaling for the imaginary part of the eigenvalues call stdlib${ii}$_slascl( 'G', 0_${ik}$, 0_${ik}$, cscale, anrm, n-ieval, 1_${ik}$,wi( ieval+1 ), max( n-ieval,& 1_${ik}$ ), ierr ) end if if( wantst .and. info==0_${ik}$ ) then ! check if reordering successful lastsl = .true. lst2sl = .true. sdim = 0_${ik}$ ip = 0_${ik}$ do i = 1, n cursl = select( wr( i ), wi( i ) ) if( wi( i )==zero ) then if( cursl )sdim = sdim + 1_${ik}$ ip = 0_${ik}$ if( cursl .and. .not.lastsl )info = n + 2_${ik}$ else if( ip==1_${ik}$ ) then ! last eigenvalue of conjugate pair cursl = cursl .or. lastsl lastsl = cursl if( cursl )sdim = sdim + 2_${ik}$ ip = -1_${ik}$ if( cursl .and. .not.lst2sl )info = n + 2_${ik}$ else ! first eigenvalue of conjugate pair ip = 1_${ik}$ end if end if lst2sl = lastsl lastsl = cursl end do end if work( 1_${ik}$ ) = maxwrk return end subroutine stdlib${ii}$_sgees module subroutine stdlib${ii}$_dgees( jobvs, sort, select, n, a, lda, sdim, wr, wi,vs, ldvs, work, lwork, & !! DGEES computes for an N-by-N real nonsymmetric matrix A, the !! eigenvalues, the real Schur form T, and, optionally, the matrix of !! Schur vectors Z. This gives the Schur factorization A = Z*T*(Z**T). !! Optionally, it also orders the eigenvalues on the diagonal of the !! real Schur form so that selected eigenvalues are at the top left. !! The leading columns of Z then form an orthonormal basis for the !! invariant subspace corresponding to the selected eigenvalues. !! A matrix is in real Schur form if it is upper quasi-triangular with !! 1-by-1 and 2-by-2 blocks. 2-by-2 blocks will be standardized in the !! form !! [ a b ] !! [ c a ] !! where b*c < 0. The eigenvalues of such a block are a +- sqrt(bc). bwork, info ) ! -- lapack driver routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_dp, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments character, intent(in) :: jobvs, sort integer(${ik}$), intent(out) :: info, sdim integer(${ik}$), intent(in) :: lda, ldvs, lwork, n ! Array Arguments logical(lk), intent(out) :: bwork(*) real(dp), intent(inout) :: a(lda,*) real(dp), intent(out) :: vs(ldvs,*), wi(*), work(*), wr(*) ! Function Arguments procedure(stdlib_select_d) :: select ! ===================================================================== ! Local Scalars logical(lk) :: cursl, lastsl, lquery, lst2sl, scalea, wantst, wantvs integer(${ik}$) :: hswork, i, i1, i2, ibal, icond, ierr, ieval, ihi, ilo, inxt, ip, itau, & iwrk, maxwrk, minwrk real(dp) :: anrm, bignum, cscale, eps, s, sep, smlnum ! Local Arrays integer(${ik}$) :: idum(1_${ik}$) real(dp) :: dum(1_${ik}$) ! Intrinsic Functions ! Executable Statements ! test the input arguments info = 0_${ik}$ lquery = ( lwork==-1_${ik}$ ) wantvs = stdlib_lsame( jobvs, 'V' ) wantst = stdlib_lsame( sort, 'S' ) if( ( .not.wantvs ) .and. ( .not.stdlib_lsame( jobvs, 'N' ) ) ) then info = -1_${ik}$ else if( ( .not.wantst ) .and. ( .not.stdlib_lsame( sort, 'N' ) ) ) then info = -2_${ik}$ else if( n<0_${ik}$ ) then info = -4_${ik}$ else if( lda<max( 1_${ik}$, n ) ) then info = -6_${ik}$ else if( ldvs<1_${ik}$ .or. ( wantvs .and. ldvs<n ) ) then info = -11_${ik}$ end if ! compute workspace ! (note: comments in the code beginning "workspace:" describe the ! minimal amount of workspace needed at that point in the code, ! as well as the preferred amount for good performance. ! nb refers to the optimal block size for the immediately ! following subroutine, as returned by stdlib${ii}$_ilaenv. ! hswork refers to the workspace preferred by stdlib${ii}$_dhseqr, as ! calculated below. hswork is computed assuming ilo=1 and ihi=n, ! the worst case.) if( info==0_${ik}$ ) then if( n==0_${ik}$ ) then minwrk = 1_${ik}$ maxwrk = 1_${ik}$ else maxwrk = 2_${ik}$*n + n*stdlib${ii}$_ilaenv( 1_${ik}$, 'DGEHRD', ' ', n, 1_${ik}$, n, 0_${ik}$ ) minwrk = 3_${ik}$*n call stdlib${ii}$_dhseqr( 'S', jobvs, n, 1_${ik}$, n, a, lda, wr, wi, vs, ldvs,work, -1_${ik}$, & ieval ) hswork = work( 1_${ik}$ ) if( .not.wantvs ) then maxwrk = max( maxwrk, n + hswork ) else maxwrk = max( maxwrk, 2_${ik}$*n + ( n - 1_${ik}$ )*stdlib${ii}$_ilaenv( 1_${ik}$,'DORGHR', ' ', n, 1_${ik}$, n,& -1_${ik}$ ) ) maxwrk = max( maxwrk, n + hswork ) end if end if work( 1_${ik}$ ) = maxwrk if( lwork<minwrk .and. .not.lquery ) then info = -13_${ik}$ end if end if if( info/=0_${ik}$ ) then call stdlib${ii}$_xerbla( 'DGEES ', -info ) return else if( lquery ) then return end if ! quick return if possible if( n==0_${ik}$ ) then sdim = 0_${ik}$ return end if ! get machine constants eps = stdlib${ii}$_dlamch( 'P' ) smlnum = stdlib${ii}$_dlamch( 'S' ) bignum = one / smlnum call stdlib${ii}$_dlabad( smlnum, bignum ) smlnum = sqrt( smlnum ) / eps bignum = one / smlnum ! scale a if max element outside range [smlnum,bignum] anrm = stdlib${ii}$_dlange( 'M', n, n, a, lda, dum ) scalea = .false. if( anrm>zero .and. anrm<smlnum ) then scalea = .true. cscale = smlnum else if( anrm>bignum ) then scalea = .true. cscale = bignum end if if( scalea )call stdlib${ii}$_dlascl( 'G', 0_${ik}$, 0_${ik}$, anrm, cscale, n, n, a, lda, ierr ) ! permute the matrix to make it more nearly triangular ! (workspace: need n) ibal = 1_${ik}$ call stdlib${ii}$_dgebal( 'P', n, a, lda, ilo, ihi, work( ibal ), ierr ) ! reduce to upper hessenberg form ! (workspace: need 3*n, prefer 2*n+n*nb) itau = n + ibal iwrk = n + itau call stdlib${ii}$_dgehrd( n, ilo, ihi, a, lda, work( itau ), work( iwrk ),lwork-iwrk+1, ierr & ) if( wantvs ) then ! copy householder vectors to vs call stdlib${ii}$_dlacpy( 'L', n, n, a, lda, vs, ldvs ) ! generate orthogonal matrix in vs ! (workspace: need 3*n-1, prefer 2*n+(n-1)*nb) call stdlib${ii}$_dorghr( n, ilo, ihi, vs, ldvs, work( itau ), work( iwrk ),lwork-iwrk+1, & ierr ) end if sdim = 0_${ik}$ ! perform qr iteration, accumulating schur vectors in vs if desired ! (workspace: need n+1, prefer n+hswork (see comments) ) iwrk = itau call stdlib${ii}$_dhseqr( 'S', jobvs, n, ilo, ihi, a, lda, wr, wi, vs, ldvs,work( iwrk ), & lwork-iwrk+1, ieval ) if( ieval>0_${ik}$ )info = ieval ! sort eigenvalues if desired if( wantst .and. info==0_${ik}$ ) then if( scalea ) then call stdlib${ii}$_dlascl( 'G', 0_${ik}$, 0_${ik}$, cscale, anrm, n, 1_${ik}$, wr, n, ierr ) call stdlib${ii}$_dlascl( 'G', 0_${ik}$, 0_${ik}$, cscale, anrm, n, 1_${ik}$, wi, n, ierr ) end if do i = 1, n bwork( i ) = select( wr( i ), wi( i ) ) end do ! reorder eigenvalues and transform schur vectors ! (workspace: none needed) call stdlib${ii}$_dtrsen( 'N', jobvs, bwork, n, a, lda, vs, ldvs, wr, wi,sdim, s, sep, & work( iwrk ), lwork-iwrk+1, idum, 1_${ik}$,icond ) if( icond>0_${ik}$ )info = n + icond end if if( wantvs ) then ! undo balancing ! (workspace: need n) call stdlib${ii}$_dgebak( 'P', 'R', n, ilo, ihi, work( ibal ), n, vs, ldvs,ierr ) end if if( scalea ) then ! undo scaling for the schur form of a call stdlib${ii}$_dlascl( 'H', 0_${ik}$, 0_${ik}$, cscale, anrm, n, n, a, lda, ierr ) call stdlib${ii}$_dcopy( n, a, lda+1, wr, 1_${ik}$ ) if( cscale==smlnum ) then ! if scaling back towards underflow, adjust wi if an ! offdiagonal element of a 2-by-2 block in the schur form ! underflows. if( ieval>0_${ik}$ ) then i1 = ieval + 1_${ik}$ i2 = ihi - 1_${ik}$ call stdlib${ii}$_dlascl( 'G', 0_${ik}$, 0_${ik}$, cscale, anrm, ilo-1, 1_${ik}$, wi,max( ilo-1, 1_${ik}$ ), & ierr ) else if( wantst ) then i1 = 1_${ik}$ i2 = n - 1_${ik}$ else i1 = ilo i2 = ihi - 1_${ik}$ end if inxt = i1 - 1_${ik}$ loop_20: do i = i1, i2 if( i<inxt )cycle loop_20 if( wi( i )==zero ) then inxt = i + 1_${ik}$ else if( a( i+1, i )==zero ) then wi( i ) = zero wi( i+1 ) = zero else if( a( i+1, i )/=zero .and. a( i, i+1 )==zero ) then wi( i ) = zero wi( i+1 ) = zero if( i>1_${ik}$ )call stdlib${ii}$_dswap( i-1, a( 1_${ik}$, i ), 1_${ik}$, a( 1_${ik}$, i+1 ), 1_${ik}$ ) if( n>i+1 )call stdlib${ii}$_dswap( n-i-1, a( i, i+2 ), lda,a( i+1, i+2 ), & lda ) if( wantvs ) then call stdlib${ii}$_dswap( n, vs( 1_${ik}$, i ), 1_${ik}$, vs( 1_${ik}$, i+1 ), 1_${ik}$ ) end if a( i, i+1 ) = a( i+1, i ) a( i+1, i ) = zero end if inxt = i + 2_${ik}$ end if end do loop_20 end if ! undo scaling for the imaginary part of the eigenvalues call stdlib${ii}$_dlascl( 'G', 0_${ik}$, 0_${ik}$, cscale, anrm, n-ieval, 1_${ik}$,wi( ieval+1 ), max( n-ieval,& 1_${ik}$ ), ierr ) end if if( wantst .and. info==0_${ik}$ ) then ! check if reordering successful lastsl = .true. lst2sl = .true. sdim = 0_${ik}$ ip = 0_${ik}$ do i = 1, n cursl = select( wr( i ), wi( i ) ) if( wi( i )==zero ) then if( cursl )sdim = sdim + 1_${ik}$ ip = 0_${ik}$ if( cursl .and. .not.lastsl )info = n + 2_${ik}$ else if( ip==1_${ik}$ ) then ! last eigenvalue of conjugate pair cursl = cursl .or. lastsl lastsl = cursl if( cursl )sdim = sdim + 2_${ik}$ ip = -1_${ik}$ if( cursl .and. .not.lst2sl )info = n + 2_${ik}$ else ! first eigenvalue of conjugate pair ip = 1_${ik}$ end if end if lst2sl = lastsl lastsl = cursl end do end if work( 1_${ik}$ ) = maxwrk return end subroutine stdlib${ii}$_dgees #:for rk,rt,ri in REAL_KINDS_TYPES #:if not rk in ["sp","dp"] module subroutine stdlib${ii}$_${ri}$gees( jobvs, sort, select, n, a, lda, sdim, wr, wi,vs, ldvs, work, lwork, & !! DGEES: computes for an N-by-N real nonsymmetric matrix A, the !! eigenvalues, the real Schur form T, and, optionally, the matrix of !! Schur vectors Z. This gives the Schur factorization A = Z*T*(Z**T). !! Optionally, it also orders the eigenvalues on the diagonal of the !! real Schur form so that selected eigenvalues are at the top left. !! The leading columns of Z then form an orthonormal basis for the !! invariant subspace corresponding to the selected eigenvalues. !! A matrix is in real Schur form if it is upper quasi-triangular with !! 1-by-1 and 2-by-2 blocks. 2-by-2 blocks will be standardized in the !! form !! [ a b ] !! [ c a ] !! where b*c < 0. The eigenvalues of such a block are a +- sqrt(bc). bwork, info ) ! -- lapack driver routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_${rk}$, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments character, intent(in) :: jobvs, sort integer(${ik}$), intent(out) :: info, sdim integer(${ik}$), intent(in) :: lda, ldvs, lwork, n ! Array Arguments logical(lk), intent(out) :: bwork(*) real(${rk}$), intent(inout) :: a(lda,*) real(${rk}$), intent(out) :: vs(ldvs,*), wi(*), work(*), wr(*) ! Function Arguments procedure(stdlib_select_${ri}$) :: select ! ===================================================================== ! Local Scalars logical(lk) :: cursl, lastsl, lquery, lst2sl, scalea, wantst, wantvs integer(${ik}$) :: hswork, i, i1, i2, ibal, icond, ierr, ieval, ihi, ilo, inxt, ip, itau, & iwrk, maxwrk, minwrk real(${rk}$) :: anrm, bignum, cscale, eps, s, sep, smlnum ! Local Arrays integer(${ik}$) :: idum(1_${ik}$) real(${rk}$) :: dum(1_${ik}$) ! Intrinsic Functions ! Executable Statements ! test the input arguments info = 0_${ik}$ lquery = ( lwork==-1_${ik}$ ) wantvs = stdlib_lsame( jobvs, 'V' ) wantst = stdlib_lsame( sort, 'S' ) if( ( .not.wantvs ) .and. ( .not.stdlib_lsame( jobvs, 'N' ) ) ) then info = -1_${ik}$ else if( ( .not.wantst ) .and. ( .not.stdlib_lsame( sort, 'N' ) ) ) then info = -2_${ik}$ else if( n<0_${ik}$ ) then info = -4_${ik}$ else if( lda<max( 1_${ik}$, n ) ) then info = -6_${ik}$ else if( ldvs<1_${ik}$ .or. ( wantvs .and. ldvs<n ) ) then info = -11_${ik}$ end if ! compute workspace ! (note: comments in the code beginning "workspace:" describe the ! minimal amount of workspace needed at that point in the code, ! as well as the preferred amount for good performance. ! nb refers to the optimal block size for the immediately ! following subroutine, as returned by stdlib${ii}$_ilaenv. ! hswork refers to the workspace preferred by stdlib${ii}$_${ri}$hseqr, as ! calculated below. hswork is computed assuming ilo=1 and ihi=n, ! the worst case.) if( info==0_${ik}$ ) then if( n==0_${ik}$ ) then minwrk = 1_${ik}$ maxwrk = 1_${ik}$ else maxwrk = 2_${ik}$*n + n*stdlib${ii}$_ilaenv( 1_${ik}$, 'DGEHRD', ' ', n, 1_${ik}$, n, 0_${ik}$ ) minwrk = 3_${ik}$*n call stdlib${ii}$_${ri}$hseqr( 'S', jobvs, n, 1_${ik}$, n, a, lda, wr, wi, vs, ldvs,work, -1_${ik}$, & ieval ) hswork = work( 1_${ik}$ ) if( .not.wantvs ) then maxwrk = max( maxwrk, n + hswork ) else maxwrk = max( maxwrk, 2_${ik}$*n + ( n - 1_${ik}$ )*stdlib${ii}$_ilaenv( 1_${ik}$,'DORGHR', ' ', n, 1_${ik}$, n,& -1_${ik}$ ) ) maxwrk = max( maxwrk, n + hswork ) end if end if work( 1_${ik}$ ) = maxwrk if( lwork<minwrk .and. .not.lquery ) then info = -13_${ik}$ end if end if if( info/=0_${ik}$ ) then call stdlib${ii}$_xerbla( 'DGEES ', -info ) return else if( lquery ) then return end if ! quick return if possible if( n==0_${ik}$ ) then sdim = 0_${ik}$ return end if ! get machine constants eps = stdlib${ii}$_${ri}$lamch( 'P' ) smlnum = stdlib${ii}$_${ri}$lamch( 'S' ) bignum = one / smlnum call stdlib${ii}$_${ri}$labad( smlnum, bignum ) smlnum = sqrt( smlnum ) / eps bignum = one / smlnum ! scale a if max element outside range [smlnum,bignum] anrm = stdlib${ii}$_${ri}$lange( 'M', n, n, a, lda, dum ) scalea = .false. if( anrm>zero .and. anrm<smlnum ) then scalea = .true. cscale = smlnum else if( anrm>bignum ) then scalea = .true. cscale = bignum end if if( scalea )call stdlib${ii}$_${ri}$lascl( 'G', 0_${ik}$, 0_${ik}$, anrm, cscale, n, n, a, lda, ierr ) ! permute the matrix to make it more nearly triangular ! (workspace: need n) ibal = 1_${ik}$ call stdlib${ii}$_${ri}$gebal( 'P', n, a, lda, ilo, ihi, work( ibal ), ierr ) ! reduce to upper hessenberg form ! (workspace: need 3*n, prefer 2*n+n*nb) itau = n + ibal iwrk = n + itau call stdlib${ii}$_${ri}$gehrd( n, ilo, ihi, a, lda, work( itau ), work( iwrk ),lwork-iwrk+1, ierr & ) if( wantvs ) then ! copy householder vectors to vs call stdlib${ii}$_${ri}$lacpy( 'L', n, n, a, lda, vs, ldvs ) ! generate orthogonal matrix in vs ! (workspace: need 3*n-1, prefer 2*n+(n-1)*nb) call stdlib${ii}$_${ri}$orghr( n, ilo, ihi, vs, ldvs, work( itau ), work( iwrk ),lwork-iwrk+1, & ierr ) end if sdim = 0_${ik}$ ! perform qr iteration, accumulating schur vectors in vs if desired ! (workspace: need n+1, prefer n+hswork (see comments) ) iwrk = itau call stdlib${ii}$_${ri}$hseqr( 'S', jobvs, n, ilo, ihi, a, lda, wr, wi, vs, ldvs,work( iwrk ), & lwork-iwrk+1, ieval ) if( ieval>0_${ik}$ )info = ieval ! sort eigenvalues if desired if( wantst .and. info==0_${ik}$ ) then if( scalea ) then call stdlib${ii}$_${ri}$lascl( 'G', 0_${ik}$, 0_${ik}$, cscale, anrm, n, 1_${ik}$, wr, n, ierr ) call stdlib${ii}$_${ri}$lascl( 'G', 0_${ik}$, 0_${ik}$, cscale, anrm, n, 1_${ik}$, wi, n, ierr ) end if do i = 1, n bwork( i ) = select( wr( i ), wi( i ) ) end do ! reorder eigenvalues and transform schur vectors ! (workspace: none needed) call stdlib${ii}$_${ri}$trsen( 'N', jobvs, bwork, n, a, lda, vs, ldvs, wr, wi,sdim, s, sep, & work( iwrk ), lwork-iwrk+1, idum, 1_${ik}$,icond ) if( icond>0_${ik}$ )info = n + icond end if if( wantvs ) then ! undo balancing ! (workspace: need n) call stdlib${ii}$_${ri}$gebak( 'P', 'R', n, ilo, ihi, work( ibal ), n, vs, ldvs,ierr ) end if if( scalea ) then ! undo scaling for the schur form of a call stdlib${ii}$_${ri}$lascl( 'H', 0_${ik}$, 0_${ik}$, cscale, anrm, n, n, a, lda, ierr ) call stdlib${ii}$_${ri}$copy( n, a, lda+1, wr, 1_${ik}$ ) if( cscale==smlnum ) then ! if scaling back towards underflow, adjust wi if an ! offdiagonal element of a 2-by-2 block in the schur form ! underflows. if( ieval>0_${ik}$ ) then i1 = ieval + 1_${ik}$ i2 = ihi - 1_${ik}$ call stdlib${ii}$_${ri}$lascl( 'G', 0_${ik}$, 0_${ik}$, cscale, anrm, ilo-1, 1_${ik}$, wi,max( ilo-1, 1_${ik}$ ), & ierr ) else if( wantst ) then i1 = 1_${ik}$ i2 = n - 1_${ik}$ else i1 = ilo i2 = ihi - 1_${ik}$ end if inxt = i1 - 1_${ik}$ loop_20: do i = i1, i2 if( i<inxt )cycle loop_20 if( wi( i )==zero ) then inxt = i + 1_${ik}$ else if( a( i+1, i )==zero ) then wi( i ) = zero wi( i+1 ) = zero else if( a( i+1, i )/=zero .and. a( i, i+1 )==zero ) then wi( i ) = zero wi( i+1 ) = zero if( i>1_${ik}$ )call stdlib${ii}$_${ri}$swap( i-1, a( 1_${ik}$, i ), 1_${ik}$, a( 1_${ik}$, i+1 ), 1_${ik}$ ) if( n>i+1 )call stdlib${ii}$_${ri}$swap( n-i-1, a( i, i+2 ), lda,a( i+1, i+2 ), & lda ) if( wantvs ) then call stdlib${ii}$_${ri}$swap( n, vs( 1_${ik}$, i ), 1_${ik}$, vs( 1_${ik}$, i+1 ), 1_${ik}$ ) end if a( i, i+1 ) = a( i+1, i ) a( i+1, i ) = zero end if inxt = i + 2_${ik}$ end if end do loop_20 end if ! undo scaling for the imaginary part of the eigenvalues call stdlib${ii}$_${ri}$lascl( 'G', 0_${ik}$, 0_${ik}$, cscale, anrm, n-ieval, 1_${ik}$,wi( ieval+1 ), max( n-ieval,& 1_${ik}$ ), ierr ) end if if( wantst .and. info==0_${ik}$ ) then ! check if reordering successful lastsl = .true. lst2sl = .true. sdim = 0_${ik}$ ip = 0_${ik}$ do i = 1, n cursl = select( wr( i ), wi( i ) ) if( wi( i )==zero ) then if( cursl )sdim = sdim + 1_${ik}$ ip = 0_${ik}$ if( cursl .and. .not.lastsl )info = n + 2_${ik}$ else if( ip==1_${ik}$ ) then ! last eigenvalue of conjugate pair cursl = cursl .or. lastsl lastsl = cursl if( cursl )sdim = sdim + 2_${ik}$ ip = -1_${ik}$ if( cursl .and. .not.lst2sl )info = n + 2_${ik}$ else ! first eigenvalue of conjugate pair ip = 1_${ik}$ end if end if lst2sl = lastsl lastsl = cursl end do end if work( 1_${ik}$ ) = maxwrk return end subroutine stdlib${ii}$_${ri}$gees #:endif #:endfor module subroutine stdlib${ii}$_cgees( jobvs, sort, select, n, a, lda, sdim, w, vs,ldvs, work, lwork, & !! CGEES computes for an N-by-N complex nonsymmetric matrix A, the !! eigenvalues, the Schur form T, and, optionally, the matrix of Schur !! vectors Z. This gives the Schur factorization A = Z*T*(Z**H). !! Optionally, it also orders the eigenvalues on the diagonal of the !! Schur form so that selected eigenvalues are at the top left. !! The leading columns of Z then form an orthonormal basis for the !! invariant subspace corresponding to the selected eigenvalues. !! A complex matrix is in Schur form if it is upper triangular. rwork, bwork, info ) ! -- lapack driver routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_sp, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments character, intent(in) :: jobvs, sort integer(${ik}$), intent(out) :: info, sdim integer(${ik}$), intent(in) :: lda, ldvs, lwork, n ! Array Arguments logical(lk), intent(out) :: bwork(*) real(sp), intent(out) :: rwork(*) complex(sp), intent(inout) :: a(lda,*) complex(sp), intent(out) :: vs(ldvs,*), w(*), work(*) ! Function Arguments procedure(stdlib_select_c) :: select ! ===================================================================== ! Local Scalars logical(lk) :: lquery, scalea, wantst, wantvs integer(${ik}$) :: hswork, i, ibal, icond, ierr, ieval, ihi, ilo, itau, iwrk, maxwrk, & minwrk real(sp) :: anrm, bignum, cscale, eps, s, sep, smlnum ! Local Arrays real(sp) :: dum(1_${ik}$) ! Intrinsic Functions ! Executable Statements ! test the input arguments info = 0_${ik}$ lquery = ( lwork==-1_${ik}$ ) wantvs = stdlib_lsame( jobvs, 'V' ) wantst = stdlib_lsame( sort, 'S' ) if( ( .not.wantvs ) .and. ( .not.stdlib_lsame( jobvs, 'N' ) ) ) then info = -1_${ik}$ else if( ( .not.wantst ) .and. ( .not.stdlib_lsame( sort, 'N' ) ) ) then info = -2_${ik}$ else if( n<0_${ik}$ ) then info = -4_${ik}$ else if( lda<max( 1_${ik}$, n ) ) then info = -6_${ik}$ else if( ldvs<1_${ik}$ .or. ( wantvs .and. ldvs<n ) ) then info = -10_${ik}$ end if ! compute workspace ! (note: comments in the code beginning "workspace:" describe the ! minimal amount of workspace needed at that point in the code, ! as well as the preferred amount for good performance. ! cworkspace refers to complex workspace, and rworkspace to real ! workspace. nb refers to the optimal block size for the ! immediately following subroutine, as returned by stdlib${ii}$_ilaenv. ! hswork refers to the workspace preferred by stdlib${ii}$_chseqr, as ! calculated below. hswork is computed assuming ilo=1 and ihi=n, ! the worst case.) if( info==0_${ik}$ ) then if( n==0_${ik}$ ) then minwrk = 1_${ik}$ maxwrk = 1_${ik}$ else maxwrk = n + n*stdlib${ii}$_ilaenv( 1_${ik}$, 'CGEHRD', ' ', n, 1_${ik}$, n, 0_${ik}$ ) minwrk = 2_${ik}$*n call stdlib${ii}$_chseqr( 'S', jobvs, n, 1_${ik}$, n, a, lda, w, vs, ldvs,work, -1_${ik}$, ieval ) hswork = real( work( 1_${ik}$ ),KIND=sp) if( .not.wantvs ) then maxwrk = max( maxwrk, hswork ) else maxwrk = max( maxwrk, n + ( n - 1_${ik}$ )*stdlib${ii}$_ilaenv( 1_${ik}$, 'CUNGHR',' ', n, 1_${ik}$, n, -& 1_${ik}$ ) ) maxwrk = max( maxwrk, hswork ) end if end if work( 1_${ik}$ ) = maxwrk if( lwork<minwrk .and. .not.lquery ) then info = -12_${ik}$ end if end if if( info/=0_${ik}$ ) then call stdlib${ii}$_xerbla( 'CGEES ', -info ) return else if( lquery ) then return end if ! quick return if possible if( n==0_${ik}$ ) then sdim = 0_${ik}$ return end if ! get machine constants eps = stdlib${ii}$_slamch( 'P' ) smlnum = stdlib${ii}$_slamch( 'S' ) bignum = one / smlnum call stdlib${ii}$_slabad( smlnum, bignum ) smlnum = sqrt( smlnum ) / eps bignum = one / smlnum ! scale a if max element outside range [smlnum,bignum] anrm = stdlib${ii}$_clange( 'M', n, n, a, lda, dum ) scalea = .false. if( anrm>zero .and. anrm<smlnum ) then scalea = .true. cscale = smlnum else if( anrm>bignum ) then scalea = .true. cscale = bignum end if if( scalea )call stdlib${ii}$_clascl( 'G', 0_${ik}$, 0_${ik}$, anrm, cscale, n, n, a, lda, ierr ) ! permute the matrix to make it more nearly triangular ! (cworkspace: none) ! (rworkspace: need n) ibal = 1_${ik}$ call stdlib${ii}$_cgebal( 'P', n, a, lda, ilo, ihi, rwork( ibal ), ierr ) ! reduce to upper hessenberg form ! (cworkspace: need 2*n, prefer n+n*nb) ! (rworkspace: none) itau = 1_${ik}$ iwrk = n + itau call stdlib${ii}$_cgehrd( n, ilo, ihi, a, lda, work( itau ), work( iwrk ),lwork-iwrk+1, ierr & ) if( wantvs ) then ! copy householder vectors to vs call stdlib${ii}$_clacpy( 'L', n, n, a, lda, vs, ldvs ) ! generate unitary matrix in vs ! (cworkspace: need 2*n-1, prefer n+(n-1)*nb) ! (rworkspace: none) call stdlib${ii}$_cunghr( n, ilo, ihi, vs, ldvs, work( itau ), work( iwrk ),lwork-iwrk+1, & ierr ) end if sdim = 0_${ik}$ ! perform qr iteration, accumulating schur vectors in vs if desired ! (cworkspace: need 1, prefer hswork (see comments) ) ! (rworkspace: none) iwrk = itau call stdlib${ii}$_chseqr( 'S', jobvs, n, ilo, ihi, a, lda, w, vs, ldvs,work( iwrk ), lwork-& iwrk+1, ieval ) if( ieval>0_${ik}$ )info = ieval ! sort eigenvalues if desired if( wantst .and. info==0_${ik}$ ) then if( scalea )call stdlib${ii}$_clascl( 'G', 0_${ik}$, 0_${ik}$, cscale, anrm, n, 1_${ik}$, w, n, ierr ) do i = 1, n bwork( i ) = select( w( i ) ) end do ! reorder eigenvalues and transform schur vectors ! (cworkspace: none) ! (rworkspace: none) call stdlib${ii}$_ctrsen( 'N', jobvs, bwork, n, a, lda, vs, ldvs, w, sdim,s, sep, work( & iwrk ), lwork-iwrk+1, icond ) end if if( wantvs ) then ! undo balancing ! (cworkspace: none) ! (rworkspace: need n) call stdlib${ii}$_cgebak( 'P', 'R', n, ilo, ihi, rwork( ibal ), n, vs, ldvs,ierr ) end if if( scalea ) then ! undo scaling for the schur form of a call stdlib${ii}$_clascl( 'U', 0_${ik}$, 0_${ik}$, cscale, anrm, n, n, a, lda, ierr ) call stdlib${ii}$_ccopy( n, a, lda+1, w, 1_${ik}$ ) end if work( 1_${ik}$ ) = maxwrk return end subroutine stdlib${ii}$_cgees module subroutine stdlib${ii}$_zgees( jobvs, sort, select, n, a, lda, sdim, w, vs,ldvs, work, lwork, & !! ZGEES computes for an N-by-N complex nonsymmetric matrix A, the !! eigenvalues, the Schur form T, and, optionally, the matrix of Schur !! vectors Z. This gives the Schur factorization A = Z*T*(Z**H). !! Optionally, it also orders the eigenvalues on the diagonal of the !! Schur form so that selected eigenvalues are at the top left. !! The leading columns of Z then form an orthonormal basis for the !! invariant subspace corresponding to the selected eigenvalues. !! A complex matrix is in Schur form if it is upper triangular. rwork, bwork, info ) ! -- lapack driver routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_dp, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments character, intent(in) :: jobvs, sort integer(${ik}$), intent(out) :: info, sdim integer(${ik}$), intent(in) :: lda, ldvs, lwork, n ! Array Arguments logical(lk), intent(out) :: bwork(*) real(dp), intent(out) :: rwork(*) complex(dp), intent(inout) :: a(lda,*) complex(dp), intent(out) :: vs(ldvs,*), w(*), work(*) ! Function Arguments procedure(stdlib_select_z) :: select ! ===================================================================== ! Local Scalars logical(lk) :: lquery, scalea, wantst, wantvs integer(${ik}$) :: hswork, i, ibal, icond, ierr, ieval, ihi, ilo, itau, iwrk, maxwrk, & minwrk real(dp) :: anrm, bignum, cscale, eps, s, sep, smlnum ! Local Arrays real(dp) :: dum(1_${ik}$) ! Intrinsic Functions ! Executable Statements ! test the input arguments info = 0_${ik}$ lquery = ( lwork==-1_${ik}$ ) wantvs = stdlib_lsame( jobvs, 'V' ) wantst = stdlib_lsame( sort, 'S' ) if( ( .not.wantvs ) .and. ( .not.stdlib_lsame( jobvs, 'N' ) ) ) then info = -1_${ik}$ else if( ( .not.wantst ) .and. ( .not.stdlib_lsame( sort, 'N' ) ) ) then info = -2_${ik}$ else if( n<0_${ik}$ ) then info = -4_${ik}$ else if( lda<max( 1_${ik}$, n ) ) then info = -6_${ik}$ else if( ldvs<1_${ik}$ .or. ( wantvs .and. ldvs<n ) ) then info = -10_${ik}$ end if ! compute workspace ! (note: comments in the code beginning "workspace:" describe the ! minimal amount of workspace needed at that point in the code, ! as well as the preferred amount for good performance. ! cworkspace refers to complex workspace, and rworkspace to real ! workspace. nb refers to the optimal block size for the ! immediately following subroutine, as returned by stdlib${ii}$_ilaenv. ! hswork refers to the workspace preferred by stdlib${ii}$_zhseqr, as ! calculated below. hswork is computed assuming ilo=1 and ihi=n, ! the worst case.) if( info==0_${ik}$ ) then if( n==0_${ik}$ ) then minwrk = 1_${ik}$ maxwrk = 1_${ik}$ else maxwrk = n + n*stdlib${ii}$_ilaenv( 1_${ik}$, 'ZGEHRD', ' ', n, 1_${ik}$, n, 0_${ik}$ ) minwrk = 2_${ik}$*n call stdlib${ii}$_zhseqr( 'S', jobvs, n, 1_${ik}$, n, a, lda, w, vs, ldvs,work, -1_${ik}$, ieval ) hswork = real( work( 1_${ik}$ ),KIND=dp) if( .not.wantvs ) then maxwrk = max( maxwrk, hswork ) else maxwrk = max( maxwrk, n + ( n - 1_${ik}$ )*stdlib${ii}$_ilaenv( 1_${ik}$, 'ZUNGHR',' ', n, 1_${ik}$, n, -& 1_${ik}$ ) ) maxwrk = max( maxwrk, hswork ) end if end if work( 1_${ik}$ ) = maxwrk if( lwork<minwrk .and. .not.lquery ) then info = -12_${ik}$ end if end if if( info/=0_${ik}$ ) then call stdlib${ii}$_xerbla( 'ZGEES ', -info ) return else if( lquery ) then return end if ! quick return if possible if( n==0_${ik}$ ) then sdim = 0_${ik}$ return end if ! get machine constants eps = stdlib${ii}$_dlamch( 'P' ) smlnum = stdlib${ii}$_dlamch( 'S' ) bignum = one / smlnum call stdlib${ii}$_dlabad( smlnum, bignum ) smlnum = sqrt( smlnum ) / eps bignum = one / smlnum ! scale a if max element outside range [smlnum,bignum] anrm = stdlib${ii}$_zlange( 'M', n, n, a, lda, dum ) scalea = .false. if( anrm>zero .and. anrm<smlnum ) then scalea = .true. cscale = smlnum else if( anrm>bignum ) then scalea = .true. cscale = bignum end if if( scalea )call stdlib${ii}$_zlascl( 'G', 0_${ik}$, 0_${ik}$, anrm, cscale, n, n, a, lda, ierr ) ! permute the matrix to make it more nearly triangular ! (cworkspace: none) ! (rworkspace: need n) ibal = 1_${ik}$ call stdlib${ii}$_zgebal( 'P', n, a, lda, ilo, ihi, rwork( ibal ), ierr ) ! reduce to upper hessenberg form ! (cworkspace: need 2*n, prefer n+n*nb) ! (rworkspace: none) itau = 1_${ik}$ iwrk = n + itau call stdlib${ii}$_zgehrd( n, ilo, ihi, a, lda, work( itau ), work( iwrk ),lwork-iwrk+1, ierr & ) if( wantvs ) then ! copy householder vectors to vs call stdlib${ii}$_zlacpy( 'L', n, n, a, lda, vs, ldvs ) ! generate unitary matrix in vs ! (cworkspace: need 2*n-1, prefer n+(n-1)*nb) ! (rworkspace: none) call stdlib${ii}$_zunghr( n, ilo, ihi, vs, ldvs, work( itau ), work( iwrk ),lwork-iwrk+1, & ierr ) end if sdim = 0_${ik}$ ! perform qr iteration, accumulating schur vectors in vs if desired ! (cworkspace: need 1, prefer hswork (see comments) ) ! (rworkspace: none) iwrk = itau call stdlib${ii}$_zhseqr( 'S', jobvs, n, ilo, ihi, a, lda, w, vs, ldvs,work( iwrk ), lwork-& iwrk+1, ieval ) if( ieval>0_${ik}$ )info = ieval ! sort eigenvalues if desired if( wantst .and. info==0_${ik}$ ) then if( scalea )call stdlib${ii}$_zlascl( 'G', 0_${ik}$, 0_${ik}$, cscale, anrm, n, 1_${ik}$, w, n, ierr ) do i = 1, n bwork( i ) = select( w( i ) ) end do ! reorder eigenvalues and transform schur vectors ! (cworkspace: none) ! (rworkspace: none) call stdlib${ii}$_ztrsen( 'N', jobvs, bwork, n, a, lda, vs, ldvs, w, sdim,s, sep, work( & iwrk ), lwork-iwrk+1, icond ) end if if( wantvs ) then ! undo balancing ! (cworkspace: none) ! (rworkspace: need n) call stdlib${ii}$_zgebak( 'P', 'R', n, ilo, ihi, rwork( ibal ), n, vs, ldvs,ierr ) end if if( scalea ) then ! undo scaling for the schur form of a call stdlib${ii}$_zlascl( 'U', 0_${ik}$, 0_${ik}$, cscale, anrm, n, n, a, lda, ierr ) call stdlib${ii}$_zcopy( n, a, lda+1, w, 1_${ik}$ ) end if work( 1_${ik}$ ) = maxwrk return end subroutine stdlib${ii}$_zgees #:for ck,ct,ci in CMPLX_KINDS_TYPES #:if not ck in ["sp","dp"] module subroutine stdlib${ii}$_${ci}$gees( jobvs, sort, select, n, a, lda, sdim, w, vs,ldvs, work, lwork, & !! ZGEES: computes for an N-by-N complex nonsymmetric matrix A, the !! eigenvalues, the Schur form T, and, optionally, the matrix of Schur !! vectors Z. This gives the Schur factorization A = Z*T*(Z**H). !! Optionally, it also orders the eigenvalues on the diagonal of the !! Schur form so that selected eigenvalues are at the top left. !! The leading columns of Z then form an orthonormal basis for the !! invariant subspace corresponding to the selected eigenvalues. !! A complex matrix is in Schur form if it is upper triangular. rwork, bwork, info ) ! -- lapack driver routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_${ck}$, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments character, intent(in) :: jobvs, sort integer(${ik}$), intent(out) :: info, sdim integer(${ik}$), intent(in) :: lda, ldvs, lwork, n ! Array Arguments logical(lk), intent(out) :: bwork(*) real(${ck}$), intent(out) :: rwork(*) complex(${ck}$), intent(inout) :: a(lda,*) complex(${ck}$), intent(out) :: vs(ldvs,*), w(*), work(*) ! Function Arguments procedure(stdlib_select_${ci}$) :: select ! ===================================================================== ! Local Scalars logical(lk) :: lquery, scalea, wantst, wantvs integer(${ik}$) :: hswork, i, ibal, icond, ierr, ieval, ihi, ilo, itau, iwrk, maxwrk, & minwrk real(${ck}$) :: anrm, bignum, cscale, eps, s, sep, smlnum ! Local Arrays real(${ck}$) :: dum(1_${ik}$) ! Intrinsic Functions ! Executable Statements ! test the input arguments info = 0_${ik}$ lquery = ( lwork==-1_${ik}$ ) wantvs = stdlib_lsame( jobvs, 'V' ) wantst = stdlib_lsame( sort, 'S' ) if( ( .not.wantvs ) .and. ( .not.stdlib_lsame( jobvs, 'N' ) ) ) then info = -1_${ik}$ else if( ( .not.wantst ) .and. ( .not.stdlib_lsame( sort, 'N' ) ) ) then info = -2_${ik}$ else if( n<0_${ik}$ ) then info = -4_${ik}$ else if( lda<max( 1_${ik}$, n ) ) then info = -6_${ik}$ else if( ldvs<1_${ik}$ .or. ( wantvs .and. ldvs<n ) ) then info = -10_${ik}$ end if ! compute workspace ! (note: comments in the code beginning "workspace:" describe the ! minimal amount of workspace needed at that point in the code, ! as well as the preferred amount for good performance. ! cworkspace refers to complex workspace, and rworkspace to real ! workspace. nb refers to the optimal block size for the ! immediately following subroutine, as returned by stdlib${ii}$_ilaenv. ! hswork refers to the workspace preferred by stdlib${ii}$_${ci}$hseqr, as ! calculated below. hswork is computed assuming ilo=1 and ihi=n, ! the worst case.) if( info==0_${ik}$ ) then if( n==0_${ik}$ ) then minwrk = 1_${ik}$ maxwrk = 1_${ik}$ else maxwrk = n + n*stdlib${ii}$_ilaenv( 1_${ik}$, 'ZGEHRD', ' ', n, 1_${ik}$, n, 0_${ik}$ ) minwrk = 2_${ik}$*n call stdlib${ii}$_${ci}$hseqr( 'S', jobvs, n, 1_${ik}$, n, a, lda, w, vs, ldvs,work, -1_${ik}$, ieval ) hswork = real( work( 1_${ik}$ ),KIND=${ck}$) if( .not.wantvs ) then maxwrk = max( maxwrk, hswork ) else maxwrk = max( maxwrk, n + ( n - 1_${ik}$ )*stdlib${ii}$_ilaenv( 1_${ik}$, 'ZUNGHR',' ', n, 1_${ik}$, n, -& 1_${ik}$ ) ) maxwrk = max( maxwrk, hswork ) end if end if work( 1_${ik}$ ) = maxwrk if( lwork<minwrk .and. .not.lquery ) then info = -12_${ik}$ end if end if if( info/=0_${ik}$ ) then call stdlib${ii}$_xerbla( 'ZGEES ', -info ) return else if( lquery ) then return end if ! quick return if possible if( n==0_${ik}$ ) then sdim = 0_${ik}$ return end if ! get machine constants eps = stdlib${ii}$_${c2ri(ci)}$lamch( 'P' ) smlnum = stdlib${ii}$_${c2ri(ci)}$lamch( 'S' ) bignum = one / smlnum call stdlib${ii}$_${c2ri(ci)}$labad( smlnum, bignum ) smlnum = sqrt( smlnum ) / eps bignum = one / smlnum ! scale a if max element outside range [smlnum,bignum] anrm = stdlib${ii}$_${ci}$lange( 'M', n, n, a, lda, dum ) scalea = .false. if( anrm>zero .and. anrm<smlnum ) then scalea = .true. cscale = smlnum else if( anrm>bignum ) then scalea = .true. cscale = bignum end if if( scalea )call stdlib${ii}$_${ci}$lascl( 'G', 0_${ik}$, 0_${ik}$, anrm, cscale, n, n, a, lda, ierr ) ! permute the matrix to make it more nearly triangular ! (cworkspace: none) ! (rworkspace: need n) ibal = 1_${ik}$ call stdlib${ii}$_${ci}$gebal( 'P', n, a, lda, ilo, ihi, rwork( ibal ), ierr ) ! reduce to upper hessenberg form ! (cworkspace: need 2*n, prefer n+n*nb) ! (rworkspace: none) itau = 1_${ik}$ iwrk = n + itau call stdlib${ii}$_${ci}$gehrd( n, ilo, ihi, a, lda, work( itau ), work( iwrk ),lwork-iwrk+1, ierr & ) if( wantvs ) then ! copy householder vectors to vs call stdlib${ii}$_${ci}$lacpy( 'L', n, n, a, lda, vs, ldvs ) ! generate unitary matrix in vs ! (cworkspace: need 2*n-1, prefer n+(n-1)*nb) ! (rworkspace: none) call stdlib${ii}$_${ci}$unghr( n, ilo, ihi, vs, ldvs, work( itau ), work( iwrk ),lwork-iwrk+1, & ierr ) end if sdim = 0_${ik}$ ! perform qr iteration, accumulating schur vectors in vs if desired ! (cworkspace: need 1, prefer hswork (see comments) ) ! (rworkspace: none) iwrk = itau call stdlib${ii}$_${ci}$hseqr( 'S', jobvs, n, ilo, ihi, a, lda, w, vs, ldvs,work( iwrk ), lwork-& iwrk+1, ieval ) if( ieval>0_${ik}$ )info = ieval ! sort eigenvalues if desired if( wantst .and. info==0_${ik}$ ) then if( scalea )call stdlib${ii}$_${ci}$lascl( 'G', 0_${ik}$, 0_${ik}$, cscale, anrm, n, 1_${ik}$, w, n, ierr ) do i = 1, n bwork( i ) = select( w( i ) ) end do ! reorder eigenvalues and transform schur vectors ! (cworkspace: none) ! (rworkspace: none) call stdlib${ii}$_${ci}$trsen( 'N', jobvs, bwork, n, a, lda, vs, ldvs, w, sdim,s, sep, work( & iwrk ), lwork-iwrk+1, icond ) end if if( wantvs ) then ! undo balancing ! (cworkspace: none) ! (rworkspace: need n) call stdlib${ii}$_${ci}$gebak( 'P', 'R', n, ilo, ihi, rwork( ibal ), n, vs, ldvs,ierr ) end if if( scalea ) then ! undo scaling for the schur form of a call stdlib${ii}$_${ci}$lascl( 'U', 0_${ik}$, 0_${ik}$, cscale, anrm, n, n, a, lda, ierr ) call stdlib${ii}$_${ci}$copy( n, a, lda+1, w, 1_${ik}$ ) end if work( 1_${ik}$ ) = maxwrk return end subroutine stdlib${ii}$_${ci}$gees #:endif #:endfor module subroutine stdlib${ii}$_sgeesx( jobvs, sort, select, sense, n, a, lda, sdim,wr, wi, vs, ldvs, & !! SGEESX computes for an N-by-N real nonsymmetric matrix A, the !! eigenvalues, the real Schur form T, and, optionally, the matrix of !! Schur vectors Z. This gives the Schur factorization A = Z*T*(Z**T). !! Optionally, it also orders the eigenvalues on the diagonal of the !! real Schur form so that selected eigenvalues are at the top left; !! computes a reciprocal condition number for the average of the !! selected eigenvalues (RCONDE); and computes a reciprocal condition !! number for the right invariant subspace corresponding to the !! selected eigenvalues (RCONDV). The leading columns of Z form an !! orthonormal basis for this invariant subspace. !! For further explanation of the reciprocal condition numbers RCONDE !! and RCONDV, see Section 4.10_sp of the LAPACK Users' Guide (where !! these quantities are called s and sep respectively). !! A real matrix is in real Schur form if it is upper quasi-triangular !! with 1-by-1 and 2-by-2 blocks. 2-by-2 blocks will be standardized in !! the form !! [ a b ] !! [ c a ] !! where b*c < 0. The eigenvalues of such a block are a +- sqrt(bc). rconde, rcondv, work, lwork,iwork, liwork, bwork, info ) ! -- lapack driver routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_sp, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments character, intent(in) :: jobvs, sense, sort integer(${ik}$), intent(out) :: info, sdim integer(${ik}$), intent(in) :: lda, ldvs, liwork, lwork, n real(sp), intent(out) :: rconde, rcondv ! Array Arguments logical(lk), intent(out) :: bwork(*) integer(${ik}$), intent(out) :: iwork(*) real(sp), intent(inout) :: a(lda,*) real(sp), intent(out) :: vs(ldvs,*), wi(*), work(*), wr(*) ! Function Arguments procedure(stdlib_select_s) :: select ! ===================================================================== ! Local Scalars logical(lk) :: cursl, lastsl, lquery, lst2sl, scalea, wantsb, wantse, wantsn, wantst, & wantsv, wantvs integer(${ik}$) :: hswork, i, i1, i2, ibal, icond, ierr, ieval, ihi, ilo, inxt, ip, itau, & iwrk, lwrk, liwrk, maxwrk, minwrk real(sp) :: anrm, bignum, cscale, eps, smlnum ! Local Arrays real(sp) :: dum(1_${ik}$) ! Intrinsic Functions ! Executable Statements ! test the input arguments info = 0_${ik}$ wantvs = stdlib_lsame( jobvs, 'V' ) wantst = stdlib_lsame( sort, 'S' ) wantsn = stdlib_lsame( sense, 'N' ) wantse = stdlib_lsame( sense, 'E' ) wantsv = stdlib_lsame( sense, 'V' ) wantsb = stdlib_lsame( sense, 'B' ) lquery = ( lwork==-1_${ik}$ .or. liwork==-1_${ik}$ ) if( ( .not.wantvs ) .and. ( .not.stdlib_lsame( jobvs, 'N' ) ) ) then info = -1_${ik}$ else if( ( .not.wantst ) .and. ( .not.stdlib_lsame( sort, 'N' ) ) ) then info = -2_${ik}$ else if( .not.( wantsn .or. wantse .or. wantsv .or. wantsb ) .or.( .not.wantst .and. & .not.wantsn ) ) then info = -4_${ik}$ else if( n<0_${ik}$ ) then info = -5_${ik}$ else if( lda<max( 1_${ik}$, n ) ) then info = -7_${ik}$ else if( ldvs<1_${ik}$ .or. ( wantvs .and. ldvs<n ) ) then info = -12_${ik}$ end if ! compute workspace ! (note: comments in the code beginning "rworkspace:" describe the ! minimal amount of real workspace needed at that point in the ! code, as well as the preferred amount for good performance. ! iworkspace refers to integer workspace. ! nb refers to the optimal block size for the immediately ! following subroutine, as returned by stdlib${ii}$_ilaenv. ! hswork refers to the workspace preferred by stdlib${ii}$_shseqr, as ! calculated below. hswork is computed assuming ilo=1 and ihi=n, ! the worst case. ! if sense = 'e', 'v' or 'b', then the amount of workspace needed ! depends on sdim, which is computed by the routine stdlib${ii}$_strsen later ! in the code.) if( info==0_${ik}$ ) then liwrk = 1_${ik}$ if( n==0_${ik}$ ) then minwrk = 1_${ik}$ lwrk = 1_${ik}$ else maxwrk = 2_${ik}$*n + n*stdlib${ii}$_ilaenv( 1_${ik}$, 'SGEHRD', ' ', n, 1_${ik}$, n, 0_${ik}$ ) minwrk = 3_${ik}$*n call stdlib${ii}$_shseqr( 'S', jobvs, n, 1_${ik}$, n, a, lda, wr, wi, vs, ldvs,work, -1_${ik}$, & ieval ) hswork = work( 1_${ik}$ ) if( .not.wantvs ) then maxwrk = max( maxwrk, n + hswork ) else maxwrk = max( maxwrk, 2_${ik}$*n + ( n - 1_${ik}$ )*stdlib${ii}$_ilaenv( 1_${ik}$,'SORGHR', ' ', n, 1_${ik}$, n,& -1_${ik}$ ) ) maxwrk = max( maxwrk, n + hswork ) end if lwrk = maxwrk if( .not.wantsn )lwrk = max( lwrk, n + ( n*n )/2_${ik}$ ) if( wantsv .or. wantsb )liwrk = ( n*n )/4_${ik}$ end if iwork( 1_${ik}$ ) = liwrk work( 1_${ik}$ ) = lwrk if( lwork<minwrk .and. .not.lquery ) then info = -16_${ik}$ else if( liwork<1_${ik}$ .and. .not.lquery ) then info = -18_${ik}$ end if end if if( info/=0_${ik}$ ) then call stdlib${ii}$_xerbla( 'SGEESX', -info ) return else if( lquery ) then return end if ! quick return if possible if( n==0_${ik}$ ) then sdim = 0_${ik}$ return end if ! get machine constants eps = stdlib${ii}$_slamch( 'P' ) smlnum = stdlib${ii}$_slamch( 'S' ) bignum = one / smlnum call stdlib${ii}$_slabad( smlnum, bignum ) smlnum = sqrt( smlnum ) / eps bignum = one / smlnum ! scale a if max element outside range [smlnum,bignum] anrm = stdlib${ii}$_slange( 'M', n, n, a, lda, dum ) scalea = .false. if( anrm>zero .and. anrm<smlnum ) then scalea = .true. cscale = smlnum else if( anrm>bignum ) then scalea = .true. cscale = bignum end if if( scalea )call stdlib${ii}$_slascl( 'G', 0_${ik}$, 0_${ik}$, anrm, cscale, n, n, a, lda, ierr ) ! permute the matrix to make it more nearly triangular ! (rworkspace: need n) ibal = 1_${ik}$ call stdlib${ii}$_sgebal( 'P', n, a, lda, ilo, ihi, work( ibal ), ierr ) ! reduce to upper hessenberg form ! (rworkspace: need 3*n, prefer 2*n+n*nb) itau = n + ibal iwrk = n + itau call stdlib${ii}$_sgehrd( n, ilo, ihi, a, lda, work( itau ), work( iwrk ),lwork-iwrk+1, ierr & ) if( wantvs ) then ! copy householder vectors to vs call stdlib${ii}$_slacpy( 'L', n, n, a, lda, vs, ldvs ) ! generate orthogonal matrix in vs ! (rworkspace: need 3*n-1, prefer 2*n+(n-1)*nb) call stdlib${ii}$_sorghr( n, ilo, ihi, vs, ldvs, work( itau ), work( iwrk ),lwork-iwrk+1, & ierr ) end if sdim = 0_${ik}$ ! perform qr iteration, accumulating schur vectors in vs if desired ! (rworkspace: need n+1, prefer n+hswork (see comments) ) iwrk = itau call stdlib${ii}$_shseqr( 'S', jobvs, n, ilo, ihi, a, lda, wr, wi, vs, ldvs,work( iwrk ), & lwork-iwrk+1, ieval ) if( ieval>0_${ik}$ )info = ieval ! sort eigenvalues if desired if( wantst .and. info==0_${ik}$ ) then if( scalea ) then call stdlib${ii}$_slascl( 'G', 0_${ik}$, 0_${ik}$, cscale, anrm, n, 1_${ik}$, wr, n, ierr ) call stdlib${ii}$_slascl( 'G', 0_${ik}$, 0_${ik}$, cscale, anrm, n, 1_${ik}$, wi, n, ierr ) end if do i = 1, n bwork( i ) = select( wr( i ), wi( i ) ) end do ! reorder eigenvalues, transform schur vectors, and compute ! reciprocal condition numbers ! (rworkspace: if sense is not 'n', need n+2*sdim*(n-sdim) ! otherwise, need n ) ! (iworkspace: if sense is 'v' or 'b', need sdim*(n-sdim) ! otherwise, need 0 ) call stdlib${ii}$_strsen( sense, jobvs, bwork, n, a, lda, vs, ldvs, wr, wi,sdim, rconde, & rcondv, work( iwrk ), lwork-iwrk+1,iwork, liwork, icond ) if( .not.wantsn )maxwrk = max( maxwrk, n+2*sdim*( n-sdim ) ) if( icond==-15_${ik}$ ) then ! not enough real workspace info = -16_${ik}$ else if( icond==-17_${ik}$ ) then ! not enough integer workspace info = -18_${ik}$ else if( icond>0_${ik}$ ) then ! stdlib${ii}$_strsen failed to reorder or to restore standard schur form info = icond + n end if end if if( wantvs ) then ! undo balancing ! (rworkspace: need n) call stdlib${ii}$_sgebak( 'P', 'R', n, ilo, ihi, work( ibal ), n, vs, ldvs,ierr ) end if if( scalea ) then ! undo scaling for the schur form of a call stdlib${ii}$_slascl( 'H', 0_${ik}$, 0_${ik}$, cscale, anrm, n, n, a, lda, ierr ) call stdlib${ii}$_scopy( n, a, lda+1, wr, 1_${ik}$ ) if( ( wantsv .or. wantsb ) .and. info==0_${ik}$ ) then dum( 1_${ik}$ ) = rcondv call stdlib${ii}$_slascl( 'G', 0_${ik}$, 0_${ik}$, cscale, anrm, 1_${ik}$, 1_${ik}$, dum, 1_${ik}$, ierr ) rcondv = dum( 1_${ik}$ ) end if if( cscale==smlnum ) then ! if scaling back towards underflow, adjust wi if an ! offdiagonal element of a 2-by-2 block in the schur form ! underflows. if( ieval>0_${ik}$ ) then i1 = ieval + 1_${ik}$ i2 = ihi - 1_${ik}$ call stdlib${ii}$_slascl( 'G', 0_${ik}$, 0_${ik}$, cscale, anrm, ilo-1, 1_${ik}$, wi, n,ierr ) else if( wantst ) then i1 = 1_${ik}$ i2 = n - 1_${ik}$ else i1 = ilo i2 = ihi - 1_${ik}$ end if inxt = i1 - 1_${ik}$ loop_20: do i = i1, i2 if( i<inxt )cycle loop_20 if( wi( i )==zero ) then inxt = i + 1_${ik}$ else if( a( i+1, i )==zero ) then wi( i ) = zero wi( i+1 ) = zero else if( a( i+1, i )/=zero .and. a( i, i+1 )==zero ) then wi( i ) = zero wi( i+1 ) = zero if( i>1_${ik}$ )call stdlib${ii}$_sswap( i-1, a( 1_${ik}$, i ), 1_${ik}$, a( 1_${ik}$, i+1 ), 1_${ik}$ ) if( n>i+1 )call stdlib${ii}$_sswap( n-i-1, a( i, i+2 ), lda,a( i+1, i+2 ), & lda ) if( wantvs ) then call stdlib${ii}$_sswap( n, vs( 1_${ik}$, i ), 1_${ik}$, vs( 1_${ik}$, i+1 ), 1_${ik}$ ) end if a( i, i+1 ) = a( i+1, i ) a( i+1, i ) = zero end if inxt = i + 2_${ik}$ end if end do loop_20 end if call stdlib${ii}$_slascl( 'G', 0_${ik}$, 0_${ik}$, cscale, anrm, n-ieval, 1_${ik}$,wi( ieval+1 ), max( n-ieval,& 1_${ik}$ ), ierr ) end if if( wantst .and. info==0_${ik}$ ) then ! check if reordering successful lastsl = .true. lst2sl = .true. sdim = 0_${ik}$ ip = 0_${ik}$ do i = 1, n cursl = select( wr( i ), wi( i ) ) if( wi( i )==zero ) then if( cursl )sdim = sdim + 1_${ik}$ ip = 0_${ik}$ if( cursl .and. .not.lastsl )info = n + 2_${ik}$ else if( ip==1_${ik}$ ) then ! last eigenvalue of conjugate pair cursl = cursl .or. lastsl lastsl = cursl if( cursl )sdim = sdim + 2_${ik}$ ip = -1_${ik}$ if( cursl .and. .not.lst2sl )info = n + 2_${ik}$ else ! first eigenvalue of conjugate pair ip = 1_${ik}$ end if end if lst2sl = lastsl lastsl = cursl end do end if work( 1_${ik}$ ) = maxwrk if( wantsv .or. wantsb ) then iwork( 1_${ik}$ ) = sdim*(n-sdim) else iwork( 1_${ik}$ ) = 1_${ik}$ end if return end subroutine stdlib${ii}$_sgeesx module subroutine stdlib${ii}$_dgeesx( jobvs, sort, select, sense, n, a, lda, sdim,wr, wi, vs, ldvs, & !! DGEESX computes for an N-by-N real nonsymmetric matrix A, the !! eigenvalues, the real Schur form T, and, optionally, the matrix of !! Schur vectors Z. This gives the Schur factorization A = Z*T*(Z**T). !! Optionally, it also orders the eigenvalues on the diagonal of the !! real Schur form so that selected eigenvalues are at the top left; !! computes a reciprocal condition number for the average of the !! selected eigenvalues (RCONDE); and computes a reciprocal condition !! number for the right invariant subspace corresponding to the !! selected eigenvalues (RCONDV). The leading columns of Z form an !! orthonormal basis for this invariant subspace. !! For further explanation of the reciprocal condition numbers RCONDE !! and RCONDV, see Section 4.10_dp of the LAPACK Users' Guide (where !! these quantities are called s and sep respectively). !! A real matrix is in real Schur form if it is upper quasi-triangular !! with 1-by-1 and 2-by-2 blocks. 2-by-2 blocks will be standardized in !! the form !! [ a b ] !! [ c a ] !! where b*c < 0. The eigenvalues of such a block are a +- sqrt(bc). rconde, rcondv, work, lwork,iwork, liwork, bwork, info ) ! -- lapack driver routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_dp, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments character, intent(in) :: jobvs, sense, sort integer(${ik}$), intent(out) :: info, sdim integer(${ik}$), intent(in) :: lda, ldvs, liwork, lwork, n real(dp), intent(out) :: rconde, rcondv ! Array Arguments logical(lk), intent(out) :: bwork(*) integer(${ik}$), intent(out) :: iwork(*) real(dp), intent(inout) :: a(lda,*) real(dp), intent(out) :: vs(ldvs,*), wi(*), work(*), wr(*) ! Function Arguments procedure(stdlib_select_d) :: select ! ===================================================================== ! Local Scalars logical(lk) :: cursl, lastsl, lquery, lst2sl, scalea, wantsb, wantse, wantsn, wantst, & wantsv, wantvs integer(${ik}$) :: hswork, i, i1, i2, ibal, icond, ierr, ieval, ihi, ilo, inxt, ip, itau, & iwrk, liwrk, lwrk, maxwrk, minwrk real(dp) :: anrm, bignum, cscale, eps, smlnum ! Local Arrays real(dp) :: dum(1_${ik}$) ! Intrinsic Functions ! Executable Statements ! test the input arguments info = 0_${ik}$ wantvs = stdlib_lsame( jobvs, 'V' ) wantst = stdlib_lsame( sort, 'S' ) wantsn = stdlib_lsame( sense, 'N' ) wantse = stdlib_lsame( sense, 'E' ) wantsv = stdlib_lsame( sense, 'V' ) wantsb = stdlib_lsame( sense, 'B' ) lquery = ( lwork==-1_${ik}$ .or. liwork==-1_${ik}$ ) if( ( .not.wantvs ) .and. ( .not.stdlib_lsame( jobvs, 'N' ) ) ) then info = -1_${ik}$ else if( ( .not.wantst ) .and. ( .not.stdlib_lsame( sort, 'N' ) ) ) then info = -2_${ik}$ else if( .not.( wantsn .or. wantse .or. wantsv .or. wantsb ) .or.( .not.wantst .and. & .not.wantsn ) ) then info = -4_${ik}$ else if( n<0_${ik}$ ) then info = -5_${ik}$ else if( lda<max( 1_${ik}$, n ) ) then info = -7_${ik}$ else if( ldvs<1_${ik}$ .or. ( wantvs .and. ldvs<n ) ) then info = -12_${ik}$ end if ! compute workspace ! (note: comments in the code beginning "rworkspace:" describe the ! minimal amount of real workspace needed at that point in the ! code, as well as the preferred amount for good performance. ! iworkspace refers to integer workspace. ! nb refers to the optimal block size for the immediately ! following subroutine, as returned by stdlib${ii}$_ilaenv. ! hswork refers to the workspace preferred by stdlib${ii}$_dhseqr, as ! calculated below. hswork is computed assuming ilo=1 and ihi=n, ! the worst case. ! if sense = 'e', 'v' or 'b', then the amount of workspace needed ! depends on sdim, which is computed by the routine stdlib${ii}$_dtrsen later ! in the code.) if( info==0_${ik}$ ) then liwrk = 1_${ik}$ if( n==0_${ik}$ ) then minwrk = 1_${ik}$ lwrk = 1_${ik}$ else maxwrk = 2_${ik}$*n + n*stdlib${ii}$_ilaenv( 1_${ik}$, 'DGEHRD', ' ', n, 1_${ik}$, n, 0_${ik}$ ) minwrk = 3_${ik}$*n call stdlib${ii}$_dhseqr( 'S', jobvs, n, 1_${ik}$, n, a, lda, wr, wi, vs, ldvs,work, -1_${ik}$, & ieval ) hswork = work( 1_${ik}$ ) if( .not.wantvs ) then maxwrk = max( maxwrk, n + hswork ) else maxwrk = max( maxwrk, 2_${ik}$*n + ( n - 1_${ik}$ )*stdlib${ii}$_ilaenv( 1_${ik}$,'DORGHR', ' ', n, 1_${ik}$, n,& -1_${ik}$ ) ) maxwrk = max( maxwrk, n + hswork ) end if lwrk = maxwrk if( .not.wantsn )lwrk = max( lwrk, n + ( n*n )/2_${ik}$ ) if( wantsv .or. wantsb )liwrk = ( n*n )/4_${ik}$ end if iwork( 1_${ik}$ ) = liwrk work( 1_${ik}$ ) = lwrk if( lwork<minwrk .and. .not.lquery ) then info = -16_${ik}$ else if( liwork<1_${ik}$ .and. .not.lquery ) then info = -18_${ik}$ end if end if if( info/=0_${ik}$ ) then call stdlib${ii}$_xerbla( 'DGEESX', -info ) return else if( lquery ) then return end if ! quick return if possible if( n==0_${ik}$ ) then sdim = 0_${ik}$ return end if ! get machine constants eps = stdlib${ii}$_dlamch( 'P' ) smlnum = stdlib${ii}$_dlamch( 'S' ) bignum = one / smlnum call stdlib${ii}$_dlabad( smlnum, bignum ) smlnum = sqrt( smlnum ) / eps bignum = one / smlnum ! scale a if max element outside range [smlnum,bignum] anrm = stdlib${ii}$_dlange( 'M', n, n, a, lda, dum ) scalea = .false. if( anrm>zero .and. anrm<smlnum ) then scalea = .true. cscale = smlnum else if( anrm>bignum ) then scalea = .true. cscale = bignum end if if( scalea )call stdlib${ii}$_dlascl( 'G', 0_${ik}$, 0_${ik}$, anrm, cscale, n, n, a, lda, ierr ) ! permute the matrix to make it more nearly triangular ! (rworkspace: need n) ibal = 1_${ik}$ call stdlib${ii}$_dgebal( 'P', n, a, lda, ilo, ihi, work( ibal ), ierr ) ! reduce to upper hessenberg form ! (rworkspace: need 3*n, prefer 2*n+n*nb) itau = n + ibal iwrk = n + itau call stdlib${ii}$_dgehrd( n, ilo, ihi, a, lda, work( itau ), work( iwrk ),lwork-iwrk+1, ierr & ) if( wantvs ) then ! copy householder vectors to vs call stdlib${ii}$_dlacpy( 'L', n, n, a, lda, vs, ldvs ) ! generate orthogonal matrix in vs ! (rworkspace: need 3*n-1, prefer 2*n+(n-1)*nb) call stdlib${ii}$_dorghr( n, ilo, ihi, vs, ldvs, work( itau ), work( iwrk ),lwork-iwrk+1, & ierr ) end if sdim = 0_${ik}$ ! perform qr iteration, accumulating schur vectors in vs if desired ! (rworkspace: need n+1, prefer n+hswork (see comments) ) iwrk = itau call stdlib${ii}$_dhseqr( 'S', jobvs, n, ilo, ihi, a, lda, wr, wi, vs, ldvs,work( iwrk ), & lwork-iwrk+1, ieval ) if( ieval>0_${ik}$ )info = ieval ! sort eigenvalues if desired if( wantst .and. info==0_${ik}$ ) then if( scalea ) then call stdlib${ii}$_dlascl( 'G', 0_${ik}$, 0_${ik}$, cscale, anrm, n, 1_${ik}$, wr, n, ierr ) call stdlib${ii}$_dlascl( 'G', 0_${ik}$, 0_${ik}$, cscale, anrm, n, 1_${ik}$, wi, n, ierr ) end if do i = 1, n bwork( i ) = select( wr( i ), wi( i ) ) end do ! reorder eigenvalues, transform schur vectors, and compute ! reciprocal condition numbers ! (rworkspace: if sense is not 'n', need n+2*sdim*(n-sdim) ! otherwise, need n ) ! (iworkspace: if sense is 'v' or 'b', need sdim*(n-sdim) ! otherwise, need 0 ) call stdlib${ii}$_dtrsen( sense, jobvs, bwork, n, a, lda, vs, ldvs, wr, wi,sdim, rconde, & rcondv, work( iwrk ), lwork-iwrk+1,iwork, liwork, icond ) if( .not.wantsn )maxwrk = max( maxwrk, n+2*sdim*( n-sdim ) ) if( icond==-15_${ik}$ ) then ! not enough real workspace info = -16_${ik}$ else if( icond==-17_${ik}$ ) then ! not enough integer workspace info = -18_${ik}$ else if( icond>0_${ik}$ ) then ! stdlib${ii}$_dtrsen failed to reorder or to restore standard schur form info = icond + n end if end if if( wantvs ) then ! undo balancing ! (rworkspace: need n) call stdlib${ii}$_dgebak( 'P', 'R', n, ilo, ihi, work( ibal ), n, vs, ldvs,ierr ) end if if( scalea ) then ! undo scaling for the schur form of a call stdlib${ii}$_dlascl( 'H', 0_${ik}$, 0_${ik}$, cscale, anrm, n, n, a, lda, ierr ) call stdlib${ii}$_dcopy( n, a, lda+1, wr, 1_${ik}$ ) if( ( wantsv .or. wantsb ) .and. info==0_${ik}$ ) then dum( 1_${ik}$ ) = rcondv call stdlib${ii}$_dlascl( 'G', 0_${ik}$, 0_${ik}$, cscale, anrm, 1_${ik}$, 1_${ik}$, dum, 1_${ik}$, ierr ) rcondv = dum( 1_${ik}$ ) end if if( cscale==smlnum ) then ! if scaling back towards underflow, adjust wi if an ! offdiagonal element of a 2-by-2 block in the schur form ! underflows. if( ieval>0_${ik}$ ) then i1 = ieval + 1_${ik}$ i2 = ihi - 1_${ik}$ call stdlib${ii}$_dlascl( 'G', 0_${ik}$, 0_${ik}$, cscale, anrm, ilo-1, 1_${ik}$, wi, n,ierr ) else if( wantst ) then i1 = 1_${ik}$ i2 = n - 1_${ik}$ else i1 = ilo i2 = ihi - 1_${ik}$ end if inxt = i1 - 1_${ik}$ loop_20: do i = i1, i2 if( i<inxt )cycle loop_20 if( wi( i )==zero ) then inxt = i + 1_${ik}$ else if( a( i+1, i )==zero ) then wi( i ) = zero wi( i+1 ) = zero else if( a( i+1, i )/=zero .and. a( i, i+1 )==zero ) then wi( i ) = zero wi( i+1 ) = zero if( i>1_${ik}$ )call stdlib${ii}$_dswap( i-1, a( 1_${ik}$, i ), 1_${ik}$, a( 1_${ik}$, i+1 ), 1_${ik}$ ) if( n>i+1 )call stdlib${ii}$_dswap( n-i-1, a( i, i+2 ), lda,a( i+1, i+2 ), & lda ) if( wantvs ) then call stdlib${ii}$_dswap( n, vs( 1_${ik}$, i ), 1_${ik}$, vs( 1_${ik}$, i+1 ), 1_${ik}$ ) end if a( i, i+1 ) = a( i+1, i ) a( i+1, i ) = zero end if inxt = i + 2_${ik}$ end if end do loop_20 end if call stdlib${ii}$_dlascl( 'G', 0_${ik}$, 0_${ik}$, cscale, anrm, n-ieval, 1_${ik}$,wi( ieval+1 ), max( n-ieval,& 1_${ik}$ ), ierr ) end if if( wantst .and. info==0_${ik}$ ) then ! check if reordering successful lastsl = .true. lst2sl = .true. sdim = 0_${ik}$ ip = 0_${ik}$ do i = 1, n cursl = select( wr( i ), wi( i ) ) if( wi( i )==zero ) then if( cursl )sdim = sdim + 1_${ik}$ ip = 0_${ik}$ if( cursl .and. .not.lastsl )info = n + 2_${ik}$ else if( ip==1_${ik}$ ) then ! last eigenvalue of conjugate pair cursl = cursl .or. lastsl lastsl = cursl if( cursl )sdim = sdim + 2_${ik}$ ip = -1_${ik}$ if( cursl .and. .not.lst2sl )info = n + 2_${ik}$ else ! first eigenvalue of conjugate pair ip = 1_${ik}$ end if end if lst2sl = lastsl lastsl = cursl end do end if work( 1_${ik}$ ) = maxwrk if( wantsv .or. wantsb ) then iwork( 1_${ik}$ ) = max( 1_${ik}$, sdim*( n-sdim ) ) else iwork( 1_${ik}$ ) = 1_${ik}$ end if return end subroutine stdlib${ii}$_dgeesx #:for rk,rt,ri in REAL_KINDS_TYPES #:if not rk in ["sp","dp"] module subroutine stdlib${ii}$_${ri}$geesx( jobvs, sort, select, sense, n, a, lda, sdim,wr, wi, vs, ldvs, & !! DGEESX: computes for an N-by-N real nonsymmetric matrix A, the !! eigenvalues, the real Schur form T, and, optionally, the matrix of !! Schur vectors Z. This gives the Schur factorization A = Z*T*(Z**T). !! Optionally, it also orders the eigenvalues on the diagonal of the !! real Schur form so that selected eigenvalues are at the top left; !! computes a reciprocal condition number for the average of the !! selected eigenvalues (RCONDE); and computes a reciprocal condition !! number for the right invariant subspace corresponding to the !! selected eigenvalues (RCONDV). The leading columns of Z form an !! orthonormal basis for this invariant subspace. !! For further explanation of the reciprocal condition numbers RCONDE !! and RCONDV, see Section 4.10_${rk}$ of the LAPACK Users' Guide (where !! these quantities are called s and sep respectively). !! A real matrix is in real Schur form if it is upper quasi-triangular !! with 1-by-1 and 2-by-2 blocks. 2-by-2 blocks will be standardized in !! the form !! [ a b ] !! [ c a ] !! where b*c < 0. The eigenvalues of such a block are a +- sqrt(bc). rconde, rcondv, work, lwork,iwork, liwork, bwork, info ) ! -- lapack driver routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_${rk}$, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments character, intent(in) :: jobvs, sense, sort integer(${ik}$), intent(out) :: info, sdim integer(${ik}$), intent(in) :: lda, ldvs, liwork, lwork, n real(${rk}$), intent(out) :: rconde, rcondv ! Array Arguments logical(lk), intent(out) :: bwork(*) integer(${ik}$), intent(out) :: iwork(*) real(${rk}$), intent(inout) :: a(lda,*) real(${rk}$), intent(out) :: vs(ldvs,*), wi(*), work(*), wr(*) ! Function Arguments procedure(stdlib_select_${ri}$) :: select ! ===================================================================== ! Local Scalars logical(lk) :: cursl, lastsl, lquery, lst2sl, scalea, wantsb, wantse, wantsn, wantst, & wantsv, wantvs integer(${ik}$) :: hswork, i, i1, i2, ibal, icond, ierr, ieval, ihi, ilo, inxt, ip, itau, & iwrk, liwrk, lwrk, maxwrk, minwrk real(${rk}$) :: anrm, bignum, cscale, eps, smlnum ! Local Arrays real(${rk}$) :: dum(1_${ik}$) ! Intrinsic Functions ! Executable Statements ! test the input arguments info = 0_${ik}$ wantvs = stdlib_lsame( jobvs, 'V' ) wantst = stdlib_lsame( sort, 'S' ) wantsn = stdlib_lsame( sense, 'N' ) wantse = stdlib_lsame( sense, 'E' ) wantsv = stdlib_lsame( sense, 'V' ) wantsb = stdlib_lsame( sense, 'B' ) lquery = ( lwork==-1_${ik}$ .or. liwork==-1_${ik}$ ) if( ( .not.wantvs ) .and. ( .not.stdlib_lsame( jobvs, 'N' ) ) ) then info = -1_${ik}$ else if( ( .not.wantst ) .and. ( .not.stdlib_lsame( sort, 'N' ) ) ) then info = -2_${ik}$ else if( .not.( wantsn .or. wantse .or. wantsv .or. wantsb ) .or.( .not.wantst .and. & .not.wantsn ) ) then info = -4_${ik}$ else if( n<0_${ik}$ ) then info = -5_${ik}$ else if( lda<max( 1_${ik}$, n ) ) then info = -7_${ik}$ else if( ldvs<1_${ik}$ .or. ( wantvs .and. ldvs<n ) ) then info = -12_${ik}$ end if ! compute workspace ! (note: comments in the code beginning "rworkspace:" describe the ! minimal amount of real workspace needed at that point in the ! code, as well as the preferred amount for good performance. ! iworkspace refers to integer workspace. ! nb refers to the optimal block size for the immediately ! following subroutine, as returned by stdlib${ii}$_ilaenv. ! hswork refers to the workspace preferred by stdlib${ii}$_${ri}$hseqr, as ! calculated below. hswork is computed assuming ilo=1 and ihi=n, ! the worst case. ! if sense = 'e', 'v' or 'b', then the amount of workspace needed ! depends on sdim, which is computed by the routine stdlib${ii}$_${ri}$trsen later ! in the code.) if( info==0_${ik}$ ) then liwrk = 1_${ik}$ if( n==0_${ik}$ ) then minwrk = 1_${ik}$ lwrk = 1_${ik}$ else maxwrk = 2_${ik}$*n + n*stdlib${ii}$_ilaenv( 1_${ik}$, 'DGEHRD', ' ', n, 1_${ik}$, n, 0_${ik}$ ) minwrk = 3_${ik}$*n call stdlib${ii}$_${ri}$hseqr( 'S', jobvs, n, 1_${ik}$, n, a, lda, wr, wi, vs, ldvs,work, -1_${ik}$, & ieval ) hswork = work( 1_${ik}$ ) if( .not.wantvs ) then maxwrk = max( maxwrk, n + hswork ) else maxwrk = max( maxwrk, 2_${ik}$*n + ( n - 1_${ik}$ )*stdlib${ii}$_ilaenv( 1_${ik}$,'DORGHR', ' ', n, 1_${ik}$, n,& -1_${ik}$ ) ) maxwrk = max( maxwrk, n + hswork ) end if lwrk = maxwrk if( .not.wantsn )lwrk = max( lwrk, n + ( n*n )/2_${ik}$ ) if( wantsv .or. wantsb )liwrk = ( n*n )/4_${ik}$ end if iwork( 1_${ik}$ ) = liwrk work( 1_${ik}$ ) = lwrk if( lwork<minwrk .and. .not.lquery ) then info = -16_${ik}$ else if( liwork<1_${ik}$ .and. .not.lquery ) then info = -18_${ik}$ end if end if if( info/=0_${ik}$ ) then call stdlib${ii}$_xerbla( 'DGEESX', -info ) return else if( lquery ) then return end if ! quick return if possible if( n==0_${ik}$ ) then sdim = 0_${ik}$ return end if ! get machine constants eps = stdlib${ii}$_${ri}$lamch( 'P' ) smlnum = stdlib${ii}$_${ri}$lamch( 'S' ) bignum = one / smlnum call stdlib${ii}$_${ri}$labad( smlnum, bignum ) smlnum = sqrt( smlnum ) / eps bignum = one / smlnum ! scale a if max element outside range [smlnum,bignum] anrm = stdlib${ii}$_${ri}$lange( 'M', n, n, a, lda, dum ) scalea = .false. if( anrm>zero .and. anrm<smlnum ) then scalea = .true. cscale = smlnum else if( anrm>bignum ) then scalea = .true. cscale = bignum end if if( scalea )call stdlib${ii}$_${ri}$lascl( 'G', 0_${ik}$, 0_${ik}$, anrm, cscale, n, n, a, lda, ierr ) ! permute the matrix to make it more nearly triangular ! (rworkspace: need n) ibal = 1_${ik}$ call stdlib${ii}$_${ri}$gebal( 'P', n, a, lda, ilo, ihi, work( ibal ), ierr ) ! reduce to upper hessenberg form ! (rworkspace: need 3*n, prefer 2*n+n*nb) itau = n + ibal iwrk = n + itau call stdlib${ii}$_${ri}$gehrd( n, ilo, ihi, a, lda, work( itau ), work( iwrk ),lwork-iwrk+1, ierr & ) if( wantvs ) then ! copy householder vectors to vs call stdlib${ii}$_${ri}$lacpy( 'L', n, n, a, lda, vs, ldvs ) ! generate orthogonal matrix in vs ! (rworkspace: need 3*n-1, prefer 2*n+(n-1)*nb) call stdlib${ii}$_${ri}$orghr( n, ilo, ihi, vs, ldvs, work( itau ), work( iwrk ),lwork-iwrk+1, & ierr ) end if sdim = 0_${ik}$ ! perform qr iteration, accumulating schur vectors in vs if desired ! (rworkspace: need n+1, prefer n+hswork (see comments) ) iwrk = itau call stdlib${ii}$_${ri}$hseqr( 'S', jobvs, n, ilo, ihi, a, lda, wr, wi, vs, ldvs,work( iwrk ), & lwork-iwrk+1, ieval ) if( ieval>0_${ik}$ )info = ieval ! sort eigenvalues if desired if( wantst .and. info==0_${ik}$ ) then if( scalea ) then call stdlib${ii}$_${ri}$lascl( 'G', 0_${ik}$, 0_${ik}$, cscale, anrm, n, 1_${ik}$, wr, n, ierr ) call stdlib${ii}$_${ri}$lascl( 'G', 0_${ik}$, 0_${ik}$, cscale, anrm, n, 1_${ik}$, wi, n, ierr ) end if do i = 1, n bwork( i ) = select( wr( i ), wi( i ) ) end do ! reorder eigenvalues, transform schur vectors, and compute ! reciprocal condition numbers ! (rworkspace: if sense is not 'n', need n+2*sdim*(n-sdim) ! otherwise, need n ) ! (iworkspace: if sense is 'v' or 'b', need sdim*(n-sdim) ! otherwise, need 0 ) call stdlib${ii}$_${ri}$trsen( sense, jobvs, bwork, n, a, lda, vs, ldvs, wr, wi,sdim, rconde, & rcondv, work( iwrk ), lwork-iwrk+1,iwork, liwork, icond ) if( .not.wantsn )maxwrk = max( maxwrk, n+2*sdim*( n-sdim ) ) if( icond==-15_${ik}$ ) then ! not enough real workspace info = -16_${ik}$ else if( icond==-17_${ik}$ ) then ! not enough integer workspace info = -18_${ik}$ else if( icond>0_${ik}$ ) then ! stdlib${ii}$_${ri}$trsen failed to reorder or to restore standard schur form info = icond + n end if end if if( wantvs ) then ! undo balancing ! (rworkspace: need n) call stdlib${ii}$_${ri}$gebak( 'P', 'R', n, ilo, ihi, work( ibal ), n, vs, ldvs,ierr ) end if if( scalea ) then ! undo scaling for the schur form of a call stdlib${ii}$_${ri}$lascl( 'H', 0_${ik}$, 0_${ik}$, cscale, anrm, n, n, a, lda, ierr ) call stdlib${ii}$_${ri}$copy( n, a, lda+1, wr, 1_${ik}$ ) if( ( wantsv .or. wantsb ) .and. info==0_${ik}$ ) then dum( 1_${ik}$ ) = rcondv call stdlib${ii}$_${ri}$lascl( 'G', 0_${ik}$, 0_${ik}$, cscale, anrm, 1_${ik}$, 1_${ik}$, dum, 1_${ik}$, ierr ) rcondv = dum( 1_${ik}$ ) end if if( cscale==smlnum ) then ! if scaling back towards underflow, adjust wi if an ! offdiagonal element of a 2-by-2 block in the schur form ! underflows. if( ieval>0_${ik}$ ) then i1 = ieval + 1_${ik}$ i2 = ihi - 1_${ik}$ call stdlib${ii}$_${ri}$lascl( 'G', 0_${ik}$, 0_${ik}$, cscale, anrm, ilo-1, 1_${ik}$, wi, n,ierr ) else if( wantst ) then i1 = 1_${ik}$ i2 = n - 1_${ik}$ else i1 = ilo i2 = ihi - 1_${ik}$ end if inxt = i1 - 1_${ik}$ loop_20: do i = i1, i2 if( i<inxt )cycle loop_20 if( wi( i )==zero ) then inxt = i + 1_${ik}$ else if( a( i+1, i )==zero ) then wi( i ) = zero wi( i+1 ) = zero else if( a( i+1, i )/=zero .and. a( i, i+1 )==zero ) then wi( i ) = zero wi( i+1 ) = zero if( i>1_${ik}$ )call stdlib${ii}$_${ri}$swap( i-1, a( 1_${ik}$, i ), 1_${ik}$, a( 1_${ik}$, i+1 ), 1_${ik}$ ) if( n>i+1 )call stdlib${ii}$_${ri}$swap( n-i-1, a( i, i+2 ), lda,a( i+1, i+2 ), & lda ) if( wantvs ) then call stdlib${ii}$_${ri}$swap( n, vs( 1_${ik}$, i ), 1_${ik}$, vs( 1_${ik}$, i+1 ), 1_${ik}$ ) end if a( i, i+1 ) = a( i+1, i ) a( i+1, i ) = zero end if inxt = i + 2_${ik}$ end if end do loop_20 end if call stdlib${ii}$_${ri}$lascl( 'G', 0_${ik}$, 0_${ik}$, cscale, anrm, n-ieval, 1_${ik}$,wi( ieval+1 ), max( n-ieval,& 1_${ik}$ ), ierr ) end if if( wantst .and. info==0_${ik}$ ) then ! check if reordering successful lastsl = .true. lst2sl = .true. sdim = 0_${ik}$ ip = 0_${ik}$ do i = 1, n cursl = select( wr( i ), wi( i ) ) if( wi( i )==zero ) then if( cursl )sdim = sdim + 1_${ik}$ ip = 0_${ik}$ if( cursl .and. .not.lastsl )info = n + 2_${ik}$ else if( ip==1_${ik}$ ) then ! last eigenvalue of conjugate pair cursl = cursl .or. lastsl lastsl = cursl if( cursl )sdim = sdim + 2_${ik}$ ip = -1_${ik}$ if( cursl .and. .not.lst2sl )info = n + 2_${ik}$ else ! first eigenvalue of conjugate pair ip = 1_${ik}$ end if end if lst2sl = lastsl lastsl = cursl end do end if work( 1_${ik}$ ) = maxwrk if( wantsv .or. wantsb ) then iwork( 1_${ik}$ ) = max( 1_${ik}$, sdim*( n-sdim ) ) else iwork( 1_${ik}$ ) = 1_${ik}$ end if return end subroutine stdlib${ii}$_${ri}$geesx #:endif #:endfor module subroutine stdlib${ii}$_cgeesx( jobvs, sort, select, sense, n, a, lda, sdim, w,vs, ldvs, rconde, & !! CGEESX computes for an N-by-N complex nonsymmetric matrix A, the !! eigenvalues, the Schur form T, and, optionally, the matrix of Schur !! vectors Z. This gives the Schur factorization A = Z*T*(Z**H). !! Optionally, it also orders the eigenvalues on the diagonal of the !! Schur form so that selected eigenvalues are at the top left; !! computes a reciprocal condition number for the average of the !! selected eigenvalues (RCONDE); and computes a reciprocal condition !! number for the right invariant subspace corresponding to the !! selected eigenvalues (RCONDV). The leading columns of Z form an !! orthonormal basis for this invariant subspace. !! For further explanation of the reciprocal condition numbers RCONDE !! and RCONDV, see Section 4.10_sp of the LAPACK Users' Guide (where !! these quantities are called s and sep respectively). !! A complex matrix is in Schur form if it is upper triangular. rcondv, work, lwork, rwork,bwork, info ) ! -- lapack driver routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_sp, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments character, intent(in) :: jobvs, sense, sort integer(${ik}$), intent(out) :: info, sdim integer(${ik}$), intent(in) :: lda, ldvs, lwork, n real(sp), intent(out) :: rconde, rcondv ! Array Arguments logical(lk), intent(out) :: bwork(*) real(sp), intent(out) :: rwork(*) complex(sp), intent(inout) :: a(lda,*) complex(sp), intent(out) :: vs(ldvs,*), w(*), work(*) ! Function Arguments procedure(stdlib_select_c) :: select ! ===================================================================== ! Local Scalars logical(lk) :: lquery, scalea, wantsb, wantse, wantsn, wantst, wantsv, wantvs integer(${ik}$) :: hswork, i, ibal, icond, ierr, ieval, ihi, ilo, itau, iwrk, lwrk, & maxwrk, minwrk real(sp) :: anrm, bignum, cscale, eps, smlnum ! Local Arrays real(sp) :: dum(1_${ik}$) ! Intrinsic Functions ! Executable Statements ! test the input arguments info = 0_${ik}$ wantvs = stdlib_lsame( jobvs, 'V' ) wantst = stdlib_lsame( sort, 'S' ) wantsn = stdlib_lsame( sense, 'N' ) wantse = stdlib_lsame( sense, 'E' ) wantsv = stdlib_lsame( sense, 'V' ) wantsb = stdlib_lsame( sense, 'B' ) lquery = ( lwork==-1_${ik}$ ) if( ( .not.wantvs ) .and. ( .not.stdlib_lsame( jobvs, 'N' ) ) ) then info = -1_${ik}$ else if( ( .not.wantst ) .and. ( .not.stdlib_lsame( sort, 'N' ) ) ) then info = -2_${ik}$ else if( .not.( wantsn .or. wantse .or. wantsv .or. wantsb ) .or.( .not.wantst .and. & .not.wantsn ) ) then info = -4_${ik}$ else if( n<0_${ik}$ ) then info = -5_${ik}$ else if( lda<max( 1_${ik}$, n ) ) then info = -7_${ik}$ else if( ldvs<1_${ik}$ .or. ( wantvs .and. ldvs<n ) ) then info = -11_${ik}$ end if ! compute workspace ! (note: comments in the code beginning "workspace:" describe the ! minimal amount of real workspace needed at that point in the ! code, as well as the preferred amount for good performance. ! cworkspace refers to complex workspace, and rworkspace to real ! workspace. nb refers to the optimal block size for the ! immediately following subroutine, as returned by stdlib${ii}$_ilaenv. ! hswork refers to the workspace preferred by stdlib${ii}$_chseqr, as ! calculated below. hswork is computed assuming ilo=1 and ihi=n, ! the worst case. ! if sense = 'e', 'v' or 'b', then the amount of workspace needed ! depends on sdim, which is computed by the routine stdlib${ii}$_ctrsen later ! in the code.) if( info==0_${ik}$ ) then if( n==0_${ik}$ ) then minwrk = 1_${ik}$ lwrk = 1_${ik}$ else maxwrk = n + n*stdlib${ii}$_ilaenv( 1_${ik}$, 'CGEHRD', ' ', n, 1_${ik}$, n, 0_${ik}$ ) minwrk = 2_${ik}$*n call stdlib${ii}$_chseqr( 'S', jobvs, n, 1_${ik}$, n, a, lda, w, vs, ldvs,work, -1_${ik}$, ieval ) hswork = real( work( 1_${ik}$ ),KIND=sp) if( .not.wantvs ) then maxwrk = max( maxwrk, hswork ) else maxwrk = max( maxwrk, n + ( n - 1_${ik}$ )*stdlib${ii}$_ilaenv( 1_${ik}$, 'CUNGHR',' ', n, 1_${ik}$, n, -& 1_${ik}$ ) ) maxwrk = max( maxwrk, hswork ) end if lwrk = maxwrk if( .not.wantsn )lwrk = max( lwrk, ( n*n )/2_${ik}$ ) end if work( 1_${ik}$ ) = lwrk if( lwork<minwrk .and. .not.lquery ) then info = -15_${ik}$ end if end if if( info/=0_${ik}$ ) then call stdlib${ii}$_xerbla( 'CGEESX', -info ) return else if( lquery ) then return end if ! quick return if possible if( n==0_${ik}$ ) then sdim = 0_${ik}$ return end if ! get machine constants eps = stdlib${ii}$_slamch( 'P' ) smlnum = stdlib${ii}$_slamch( 'S' ) bignum = one / smlnum call stdlib${ii}$_slabad( smlnum, bignum ) smlnum = sqrt( smlnum ) / eps bignum = one / smlnum ! scale a if max element outside range [smlnum,bignum] anrm = stdlib${ii}$_clange( 'M', n, n, a, lda, dum ) scalea = .false. if( anrm>zero .and. anrm<smlnum ) then scalea = .true. cscale = smlnum else if( anrm>bignum ) then scalea = .true. cscale = bignum end if if( scalea )call stdlib${ii}$_clascl( 'G', 0_${ik}$, 0_${ik}$, anrm, cscale, n, n, a, lda, ierr ) ! permute the matrix to make it more nearly triangular ! (cworkspace: none) ! (rworkspace: need n) ibal = 1_${ik}$ call stdlib${ii}$_cgebal( 'P', n, a, lda, ilo, ihi, rwork( ibal ), ierr ) ! reduce to upper hessenberg form ! (cworkspace: need 2*n, prefer n+n*nb) ! (rworkspace: none) itau = 1_${ik}$ iwrk = n + itau call stdlib${ii}$_cgehrd( n, ilo, ihi, a, lda, work( itau ), work( iwrk ),lwork-iwrk+1, ierr & ) if( wantvs ) then ! copy householder vectors to vs call stdlib${ii}$_clacpy( 'L', n, n, a, lda, vs, ldvs ) ! generate unitary matrix in vs ! (cworkspace: need 2*n-1, prefer n+(n-1)*nb) ! (rworkspace: none) call stdlib${ii}$_cunghr( n, ilo, ihi, vs, ldvs, work( itau ), work( iwrk ),lwork-iwrk+1, & ierr ) end if sdim = 0_${ik}$ ! perform qr iteration, accumulating schur vectors in vs if desired ! (cworkspace: need 1, prefer hswork (see comments) ) ! (rworkspace: none) iwrk = itau call stdlib${ii}$_chseqr( 'S', jobvs, n, ilo, ihi, a, lda, w, vs, ldvs,work( iwrk ), lwork-& iwrk+1, ieval ) if( ieval>0_${ik}$ )info = ieval ! sort eigenvalues if desired if( wantst .and. info==0_${ik}$ ) then if( scalea )call stdlib${ii}$_clascl( 'G', 0_${ik}$, 0_${ik}$, cscale, anrm, n, 1_${ik}$, w, n, ierr ) do i = 1, n bwork( i ) = select( w( i ) ) end do ! reorder eigenvalues, transform schur vectors, and compute ! reciprocal condition numbers ! (cworkspace: if sense is not 'n', need 2*sdim*(n-sdim) ! otherwise, need none ) ! (rworkspace: none) call stdlib${ii}$_ctrsen( sense, jobvs, bwork, n, a, lda, vs, ldvs, w, sdim,rconde, & rcondv, work( iwrk ), lwork-iwrk+1,icond ) if( .not.wantsn )maxwrk = max( maxwrk, 2_${ik}$*sdim*( n-sdim ) ) if( icond==-14_${ik}$ ) then ! not enough complex workspace info = -15_${ik}$ end if end if if( wantvs ) then ! undo balancing ! (cworkspace: none) ! (rworkspace: need n) call stdlib${ii}$_cgebak( 'P', 'R', n, ilo, ihi, rwork( ibal ), n, vs, ldvs,ierr ) end if if( scalea ) then ! undo scaling for the schur form of a call stdlib${ii}$_clascl( 'U', 0_${ik}$, 0_${ik}$, cscale, anrm, n, n, a, lda, ierr ) call stdlib${ii}$_ccopy( n, a, lda+1, w, 1_${ik}$ ) if( ( wantsv .or. wantsb ) .and. info==0_${ik}$ ) then dum( 1_${ik}$ ) = rcondv call stdlib${ii}$_slascl( 'G', 0_${ik}$, 0_${ik}$, cscale, anrm, 1_${ik}$, 1_${ik}$, dum, 1_${ik}$, ierr ) rcondv = dum( 1_${ik}$ ) end if end if work( 1_${ik}$ ) = maxwrk return end subroutine stdlib${ii}$_cgeesx module subroutine stdlib${ii}$_zgeesx( jobvs, sort, select, sense, n, a, lda, sdim, w,vs, ldvs, rconde, & !! ZGEESX computes for an N-by-N complex nonsymmetric matrix A, the !! eigenvalues, the Schur form T, and, optionally, the matrix of Schur !! vectors Z. This gives the Schur factorization A = Z*T*(Z**H). !! Optionally, it also orders the eigenvalues on the diagonal of the !! Schur form so that selected eigenvalues are at the top left; !! computes a reciprocal condition number for the average of the !! selected eigenvalues (RCONDE); and computes a reciprocal condition !! number for the right invariant subspace corresponding to the !! selected eigenvalues (RCONDV). The leading columns of Z form an !! orthonormal basis for this invariant subspace. !! For further explanation of the reciprocal condition numbers RCONDE !! and RCONDV, see Section 4.10_dp of the LAPACK Users' Guide (where !! these quantities are called s and sep respectively). !! A complex matrix is in Schur form if it is upper triangular. rcondv, work, lwork, rwork,bwork, info ) ! -- lapack driver routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_dp, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments character, intent(in) :: jobvs, sense, sort integer(${ik}$), intent(out) :: info, sdim integer(${ik}$), intent(in) :: lda, ldvs, lwork, n real(dp), intent(out) :: rconde, rcondv ! Array Arguments logical(lk), intent(out) :: bwork(*) real(dp), intent(out) :: rwork(*) complex(dp), intent(inout) :: a(lda,*) complex(dp), intent(out) :: vs(ldvs,*), w(*), work(*) ! Function Arguments procedure(stdlib_select_z) :: select ! ===================================================================== ! Local Scalars logical(lk) :: lquery, scalea, wantsb, wantse, wantsn, wantst, wantsv, wantvs integer(${ik}$) :: hswork, i, ibal, icond, ierr, ieval, ihi, ilo, itau, iwrk, lwrk, & maxwrk, minwrk real(dp) :: anrm, bignum, cscale, eps, smlnum ! Local Arrays real(dp) :: dum(1_${ik}$) ! Intrinsic Functions ! Executable Statements ! test the input arguments info = 0_${ik}$ wantvs = stdlib_lsame( jobvs, 'V' ) wantst = stdlib_lsame( sort, 'S' ) wantsn = stdlib_lsame( sense, 'N' ) wantse = stdlib_lsame( sense, 'E' ) wantsv = stdlib_lsame( sense, 'V' ) wantsb = stdlib_lsame( sense, 'B' ) lquery = ( lwork==-1_${ik}$ ) if( ( .not.wantvs ) .and. ( .not.stdlib_lsame( jobvs, 'N' ) ) ) then info = -1_${ik}$ else if( ( .not.wantst ) .and. ( .not.stdlib_lsame( sort, 'N' ) ) ) then info = -2_${ik}$ else if( .not.( wantsn .or. wantse .or. wantsv .or. wantsb ) .or.( .not.wantst .and. & .not.wantsn ) ) then info = -4_${ik}$ else if( n<0_${ik}$ ) then info = -5_${ik}$ else if( lda<max( 1_${ik}$, n ) ) then info = -7_${ik}$ else if( ldvs<1_${ik}$ .or. ( wantvs .and. ldvs<n ) ) then info = -11_${ik}$ end if ! compute workspace ! (note: comments in the code beginning "workspace:" describe the ! minimal amount of real workspace needed at that point in the ! code, as well as the preferred amount for good performance. ! cworkspace refers to complex workspace, and rworkspace to real ! workspace. nb refers to the optimal block size for the ! immediately following subroutine, as returned by stdlib${ii}$_ilaenv. ! hswork refers to the workspace preferred by stdlib${ii}$_zhseqr, as ! calculated below. hswork is computed assuming ilo=1 and ihi=n, ! the worst case. ! if sense = 'e', 'v' or 'b', then the amount of workspace needed ! depends on sdim, which is computed by the routine stdlib${ii}$_ztrsen later ! in the code.) if( info==0_${ik}$ ) then if( n==0_${ik}$ ) then minwrk = 1_${ik}$ lwrk = 1_${ik}$ else maxwrk = n + n*stdlib${ii}$_ilaenv( 1_${ik}$, 'ZGEHRD', ' ', n, 1_${ik}$, n, 0_${ik}$ ) minwrk = 2_${ik}$*n call stdlib${ii}$_zhseqr( 'S', jobvs, n, 1_${ik}$, n, a, lda, w, vs, ldvs,work, -1_${ik}$, ieval ) hswork = real( work( 1_${ik}$ ),KIND=dp) if( .not.wantvs ) then maxwrk = max( maxwrk, hswork ) else maxwrk = max( maxwrk, n + ( n - 1_${ik}$ )*stdlib${ii}$_ilaenv( 1_${ik}$, 'ZUNGHR',' ', n, 1_${ik}$, n, -& 1_${ik}$ ) ) maxwrk = max( maxwrk, hswork ) end if lwrk = maxwrk if( .not.wantsn )lwrk = max( lwrk, ( n*n )/2_${ik}$ ) end if work( 1_${ik}$ ) = lwrk if( lwork<minwrk .and. .not.lquery ) then info = -15_${ik}$ end if end if if( info/=0_${ik}$ ) then call stdlib${ii}$_xerbla( 'ZGEESX', -info ) return else if( lquery ) then return end if ! quick return if possible if( n==0_${ik}$ ) then sdim = 0_${ik}$ return end if ! get machine constants eps = stdlib${ii}$_dlamch( 'P' ) smlnum = stdlib${ii}$_dlamch( 'S' ) bignum = one / smlnum call stdlib${ii}$_dlabad( smlnum, bignum ) smlnum = sqrt( smlnum ) / eps bignum = one / smlnum ! scale a if max element outside range [smlnum,bignum] anrm = stdlib${ii}$_zlange( 'M', n, n, a, lda, dum ) scalea = .false. if( anrm>zero .and. anrm<smlnum ) then scalea = .true. cscale = smlnum else if( anrm>bignum ) then scalea = .true. cscale = bignum end if if( scalea )call stdlib${ii}$_zlascl( 'G', 0_${ik}$, 0_${ik}$, anrm, cscale, n, n, a, lda, ierr ) ! permute the matrix to make it more nearly triangular ! (cworkspace: none) ! (rworkspace: need n) ibal = 1_${ik}$ call stdlib${ii}$_zgebal( 'P', n, a, lda, ilo, ihi, rwork( ibal ), ierr ) ! reduce to upper hessenberg form ! (cworkspace: need 2*n, prefer n+n*nb) ! (rworkspace: none) itau = 1_${ik}$ iwrk = n + itau call stdlib${ii}$_zgehrd( n, ilo, ihi, a, lda, work( itau ), work( iwrk ),lwork-iwrk+1, ierr & ) if( wantvs ) then ! copy householder vectors to vs call stdlib${ii}$_zlacpy( 'L', n, n, a, lda, vs, ldvs ) ! generate unitary matrix in vs ! (cworkspace: need 2*n-1, prefer n+(n-1)*nb) ! (rworkspace: none) call stdlib${ii}$_zunghr( n, ilo, ihi, vs, ldvs, work( itau ), work( iwrk ),lwork-iwrk+1, & ierr ) end if sdim = 0_${ik}$ ! perform qr iteration, accumulating schur vectors in vs if desired ! (cworkspace: need 1, prefer hswork (see comments) ) ! (rworkspace: none) iwrk = itau call stdlib${ii}$_zhseqr( 'S', jobvs, n, ilo, ihi, a, lda, w, vs, ldvs,work( iwrk ), lwork-& iwrk+1, ieval ) if( ieval>0_${ik}$ )info = ieval ! sort eigenvalues if desired if( wantst .and. info==0_${ik}$ ) then if( scalea )call stdlib${ii}$_zlascl( 'G', 0_${ik}$, 0_${ik}$, cscale, anrm, n, 1_${ik}$, w, n, ierr ) do i = 1, n bwork( i ) = select( w( i ) ) end do ! reorder eigenvalues, transform schur vectors, and compute ! reciprocal condition numbers ! (cworkspace: if sense is not 'n', need 2*sdim*(n-sdim) ! otherwise, need none ) ! (rworkspace: none) call stdlib${ii}$_ztrsen( sense, jobvs, bwork, n, a, lda, vs, ldvs, w, sdim,rconde, & rcondv, work( iwrk ), lwork-iwrk+1,icond ) if( .not.wantsn )maxwrk = max( maxwrk, 2_${ik}$*sdim*( n-sdim ) ) if( icond==-14_${ik}$ ) then ! not enough complex workspace info = -15_${ik}$ end if end if if( wantvs ) then ! undo balancing ! (cworkspace: none) ! (rworkspace: need n) call stdlib${ii}$_zgebak( 'P', 'R', n, ilo, ihi, rwork( ibal ), n, vs, ldvs,ierr ) end if if( scalea ) then ! undo scaling for the schur form of a call stdlib${ii}$_zlascl( 'U', 0_${ik}$, 0_${ik}$, cscale, anrm, n, n, a, lda, ierr ) call stdlib${ii}$_zcopy( n, a, lda+1, w, 1_${ik}$ ) if( ( wantsv .or. wantsb ) .and. info==0_${ik}$ ) then dum( 1_${ik}$ ) = rcondv call stdlib${ii}$_dlascl( 'G', 0_${ik}$, 0_${ik}$, cscale, anrm, 1_${ik}$, 1_${ik}$, dum, 1_${ik}$, ierr ) rcondv = dum( 1_${ik}$ ) end if end if work( 1_${ik}$ ) = maxwrk return end subroutine stdlib${ii}$_zgeesx #:for ck,ct,ci in CMPLX_KINDS_TYPES #:if not ck in ["sp","dp"] module subroutine stdlib${ii}$_${ci}$geesx( jobvs, sort, select, sense, n, a, lda, sdim, w,vs, ldvs, rconde, & !! ZGEESX: computes for an N-by-N complex nonsymmetric matrix A, the !! eigenvalues, the Schur form T, and, optionally, the matrix of Schur !! vectors Z. This gives the Schur factorization A = Z*T*(Z**H). !! Optionally, it also orders the eigenvalues on the diagonal of the !! Schur form so that selected eigenvalues are at the top left; !! computes a reciprocal condition number for the average of the !! selected eigenvalues (RCONDE); and computes a reciprocal condition !! number for the right invariant subspace corresponding to the !! selected eigenvalues (RCONDV). The leading columns of Z form an !! orthonormal basis for this invariant subspace. !! For further explanation of the reciprocal condition numbers RCONDE !! and RCONDV, see Section 4.10_${ck}$ of the LAPACK Users' Guide (where !! these quantities are called s and sep respectively). !! A complex matrix is in Schur form if it is upper triangular. rcondv, work, lwork, rwork,bwork, info ) ! -- lapack driver routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_${ck}$, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments character, intent(in) :: jobvs, sense, sort integer(${ik}$), intent(out) :: info, sdim integer(${ik}$), intent(in) :: lda, ldvs, lwork, n real(${ck}$), intent(out) :: rconde, rcondv ! Array Arguments logical(lk), intent(out) :: bwork(*) real(${ck}$), intent(out) :: rwork(*) complex(${ck}$), intent(inout) :: a(lda,*) complex(${ck}$), intent(out) :: vs(ldvs,*), w(*), work(*) ! Function Arguments procedure(stdlib_select_${ci}$) :: select ! ===================================================================== ! Local Scalars logical(lk) :: lquery, scalea, wantsb, wantse, wantsn, wantst, wantsv, wantvs integer(${ik}$) :: hswork, i, ibal, icond, ierr, ieval, ihi, ilo, itau, iwrk, lwrk, & maxwrk, minwrk real(${ck}$) :: anrm, bignum, cscale, eps, smlnum ! Local Arrays real(${ck}$) :: dum(1_${ik}$) ! Intrinsic Functions ! Executable Statements ! test the input arguments info = 0_${ik}$ wantvs = stdlib_lsame( jobvs, 'V' ) wantst = stdlib_lsame( sort, 'S' ) wantsn = stdlib_lsame( sense, 'N' ) wantse = stdlib_lsame( sense, 'E' ) wantsv = stdlib_lsame( sense, 'V' ) wantsb = stdlib_lsame( sense, 'B' ) lquery = ( lwork==-1_${ik}$ ) if( ( .not.wantvs ) .and. ( .not.stdlib_lsame( jobvs, 'N' ) ) ) then info = -1_${ik}$ else if( ( .not.wantst ) .and. ( .not.stdlib_lsame( sort, 'N' ) ) ) then info = -2_${ik}$ else if( .not.( wantsn .or. wantse .or. wantsv .or. wantsb ) .or.( .not.wantst .and. & .not.wantsn ) ) then info = -4_${ik}$ else if( n<0_${ik}$ ) then info = -5_${ik}$ else if( lda<max( 1_${ik}$, n ) ) then info = -7_${ik}$ else if( ldvs<1_${ik}$ .or. ( wantvs .and. ldvs<n ) ) then info = -11_${ik}$ end if ! compute workspace ! (note: comments in the code beginning "workspace:" describe the ! minimal amount of real workspace needed at that point in the ! code, as well as the preferred amount for good performance. ! cworkspace refers to complex workspace, and rworkspace to real ! workspace. nb refers to the optimal block size for the ! immediately following subroutine, as returned by stdlib${ii}$_ilaenv. ! hswork refers to the workspace preferred by stdlib${ii}$_${ci}$hseqr, as ! calculated below. hswork is computed assuming ilo=1 and ihi=n, ! the worst case. ! if sense = 'e', 'v' or 'b', then the amount of workspace needed ! depends on sdim, which is computed by the routine stdlib${ii}$_${ci}$trsen later ! in the code.) if( info==0_${ik}$ ) then if( n==0_${ik}$ ) then minwrk = 1_${ik}$ lwrk = 1_${ik}$ else maxwrk = n + n*stdlib${ii}$_ilaenv( 1_${ik}$, 'ZGEHRD', ' ', n, 1_${ik}$, n, 0_${ik}$ ) minwrk = 2_${ik}$*n call stdlib${ii}$_${ci}$hseqr( 'S', jobvs, n, 1_${ik}$, n, a, lda, w, vs, ldvs,work, -1_${ik}$, ieval ) hswork = real( work( 1_${ik}$ ),KIND=${ck}$) if( .not.wantvs ) then maxwrk = max( maxwrk, hswork ) else maxwrk = max( maxwrk, n + ( n - 1_${ik}$ )*stdlib${ii}$_ilaenv( 1_${ik}$, 'ZUNGHR',' ', n, 1_${ik}$, n, -& 1_${ik}$ ) ) maxwrk = max( maxwrk, hswork ) end if lwrk = maxwrk if( .not.wantsn )lwrk = max( lwrk, ( n*n )/2_${ik}$ ) end if work( 1_${ik}$ ) = lwrk if( lwork<minwrk .and. .not.lquery ) then info = -15_${ik}$ end if end if if( info/=0_${ik}$ ) then call stdlib${ii}$_xerbla( 'ZGEESX', -info ) return else if( lquery ) then return end if ! quick return if possible if( n==0_${ik}$ ) then sdim = 0_${ik}$ return end if ! get machine constants eps = stdlib${ii}$_${c2ri(ci)}$lamch( 'P' ) smlnum = stdlib${ii}$_${c2ri(ci)}$lamch( 'S' ) bignum = one / smlnum call stdlib${ii}$_${c2ri(ci)}$labad( smlnum, bignum ) smlnum = sqrt( smlnum ) / eps bignum = one / smlnum ! scale a if max element outside range [smlnum,bignum] anrm = stdlib${ii}$_${ci}$lange( 'M', n, n, a, lda, dum ) scalea = .false. if( anrm>zero .and. anrm<smlnum ) then scalea = .true. cscale = smlnum else if( anrm>bignum ) then scalea = .true. cscale = bignum end if if( scalea )call stdlib${ii}$_${ci}$lascl( 'G', 0_${ik}$, 0_${ik}$, anrm, cscale, n, n, a, lda, ierr ) ! permute the matrix to make it more nearly triangular ! (cworkspace: none) ! (rworkspace: need n) ibal = 1_${ik}$ call stdlib${ii}$_${ci}$gebal( 'P', n, a, lda, ilo, ihi, rwork( ibal ), ierr ) ! reduce to upper hessenberg form ! (cworkspace: need 2*n, prefer n+n*nb) ! (rworkspace: none) itau = 1_${ik}$ iwrk = n + itau call stdlib${ii}$_${ci}$gehrd( n, ilo, ihi, a, lda, work( itau ), work( iwrk ),lwork-iwrk+1, ierr & ) if( wantvs ) then ! copy householder vectors to vs call stdlib${ii}$_${ci}$lacpy( 'L', n, n, a, lda, vs, ldvs ) ! generate unitary matrix in vs ! (cworkspace: need 2*n-1, prefer n+(n-1)*nb) ! (rworkspace: none) call stdlib${ii}$_${ci}$unghr( n, ilo, ihi, vs, ldvs, work( itau ), work( iwrk ),lwork-iwrk+1, & ierr ) end if sdim = 0_${ik}$ ! perform qr iteration, accumulating schur vectors in vs if desired ! (cworkspace: need 1, prefer hswork (see comments) ) ! (rworkspace: none) iwrk = itau call stdlib${ii}$_${ci}$hseqr( 'S', jobvs, n, ilo, ihi, a, lda, w, vs, ldvs,work( iwrk ), lwork-& iwrk+1, ieval ) if( ieval>0_${ik}$ )info = ieval ! sort eigenvalues if desired if( wantst .and. info==0_${ik}$ ) then if( scalea )call stdlib${ii}$_${ci}$lascl( 'G', 0_${ik}$, 0_${ik}$, cscale, anrm, n, 1_${ik}$, w, n, ierr ) do i = 1, n bwork( i ) = select( w( i ) ) end do ! reorder eigenvalues, transform schur vectors, and compute ! reciprocal condition numbers ! (cworkspace: if sense is not 'n', need 2*sdim*(n-sdim) ! otherwise, need none ) ! (rworkspace: none) call stdlib${ii}$_${ci}$trsen( sense, jobvs, bwork, n, a, lda, vs, ldvs, w, sdim,rconde, & rcondv, work( iwrk ), lwork-iwrk+1,icond ) if( .not.wantsn )maxwrk = max( maxwrk, 2_${ik}$*sdim*( n-sdim ) ) if( icond==-14_${ik}$ ) then ! not enough complex workspace info = -15_${ik}$ end if end if if( wantvs ) then ! undo balancing ! (cworkspace: none) ! (rworkspace: need n) call stdlib${ii}$_${ci}$gebak( 'P', 'R', n, ilo, ihi, rwork( ibal ), n, vs, ldvs,ierr ) end if if( scalea ) then ! undo scaling for the schur form of a call stdlib${ii}$_${ci}$lascl( 'U', 0_${ik}$, 0_${ik}$, cscale, anrm, n, n, a, lda, ierr ) call stdlib${ii}$_${ci}$copy( n, a, lda+1, w, 1_${ik}$ ) if( ( wantsv .or. wantsb ) .and. info==0_${ik}$ ) then dum( 1_${ik}$ ) = rcondv call stdlib${ii}$_${c2ri(ci)}$lascl( 'G', 0_${ik}$, 0_${ik}$, cscale, anrm, 1_${ik}$, 1_${ik}$, dum, 1_${ik}$, ierr ) rcondv = dum( 1_${ik}$ ) end if end if work( 1_${ik}$ ) = maxwrk return end subroutine stdlib${ii}$_${ci}$geesx #:endif #:endfor module subroutine stdlib${ii}$_sggev3( jobvl, jobvr, n, a, lda, b, ldb, alphar,alphai, beta, vl, ldvl, vr,& !! SGGEV3 computes for a pair of N-by-N real nonsymmetric matrices (A,B) !! the generalized eigenvalues, and optionally, the left and/or right !! generalized eigenvectors. !! A generalized eigenvalue for a pair of matrices (A,B) is a scalar !! lambda or a ratio alpha/beta = lambda, such that A - lambda*B is !! singular. It is usually represented as the pair (alpha,beta), as !! there is a reasonable interpretation for beta=0, and even for both !! being zero. !! The right eigenvector v(j) corresponding to the eigenvalue lambda(j) !! of (A,B) satisfies !! A * v(j) = lambda(j) * B * v(j). !! The left eigenvector u(j) corresponding to the eigenvalue lambda(j) !! of (A,B) satisfies !! u(j)**H * A = lambda(j) * u(j)**H * B . !! where u(j)**H is the conjugate-transpose of u(j). ldvr, work, lwork,info ) ! -- lapack driver routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_sp, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments character, intent(in) :: jobvl, jobvr integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: lda, ldb, ldvl, ldvr, lwork, n ! Array Arguments real(sp), intent(inout) :: a(lda,*), b(ldb,*) real(sp), intent(out) :: alphai(*), alphar(*), beta(*), vl(ldvl,*), vr(ldvr,*), work(*) ! ===================================================================== ! Local Scalars logical(lk) :: ilascl, ilbscl, ilv, ilvl, ilvr, lquery character :: chtemp integer(${ik}$) :: icols, ierr, ihi, ijobvl, ijobvr, ileft, ilo, in, iright, irows, itau, & iwrk, jc, jr, lwkopt real(sp) :: anrm, anrmto, bignum, bnrm, bnrmto, eps, smlnum, temp ! Local Arrays logical(lk) :: ldumma(1_${ik}$) ! Intrinsic Functions ! Executable Statements ! decode the input arguments if( stdlib_lsame( jobvl, 'N' ) ) then ijobvl = 1_${ik}$ ilvl = .false. else if( stdlib_lsame( jobvl, 'V' ) ) then ijobvl = 2_${ik}$ ilvl = .true. else ijobvl = -1_${ik}$ ilvl = .false. end if if( stdlib_lsame( jobvr, 'N' ) ) then ijobvr = 1_${ik}$ ilvr = .false. else if( stdlib_lsame( jobvr, 'V' ) ) then ijobvr = 2_${ik}$ ilvr = .true. else ijobvr = -1_${ik}$ ilvr = .false. end if ilv = ilvl .or. ilvr ! test the input arguments info = 0_${ik}$ lquery = ( lwork==-1_${ik}$ ) if( ijobvl<=0_${ik}$ ) then info = -1_${ik}$ else if( ijobvr<=0_${ik}$ ) then info = -2_${ik}$ else if( n<0_${ik}$ ) then info = -3_${ik}$ else if( lda<max( 1_${ik}$, n ) ) then info = -5_${ik}$ else if( ldb<max( 1_${ik}$, n ) ) then info = -7_${ik}$ else if( ldvl<1_${ik}$ .or. ( ilvl .and. ldvl<n ) ) then info = -12_${ik}$ else if( ldvr<1_${ik}$ .or. ( ilvr .and. ldvr<n ) ) then info = -14_${ik}$ else if( lwork<max( 1_${ik}$, 8_${ik}$*n ) .and. .not.lquery ) then info = -16_${ik}$ end if ! compute workspace if( info==0_${ik}$ ) then call stdlib${ii}$_sgeqrf( n, n, b, ldb, work, work, -1_${ik}$, ierr ) lwkopt = max( 1_${ik}$, 8_${ik}$*n, 3_${ik}$*n+int( work( 1_${ik}$ ),KIND=${ik}$) ) call stdlib${ii}$_sormqr( 'L', 'T', n, n, n, b, ldb, work, a, lda, work,-1_${ik}$, ierr ) lwkopt = max( lwkopt, 3_${ik}$*n+int( work( 1_${ik}$ ),KIND=${ik}$) ) call stdlib${ii}$_sgghd3( jobvl, jobvr, n, 1_${ik}$, n, a, lda, b, ldb, vl, ldvl,vr, ldvr, work, & -1_${ik}$, ierr ) lwkopt = max( lwkopt, 3_${ik}$*n+int( work( 1_${ik}$ ),KIND=${ik}$) ) if( ilvl ) then call stdlib${ii}$_sorgqr( n, n, n, vl, ldvl, work, work, -1_${ik}$, ierr ) lwkopt = max( lwkopt, 3_${ik}$*n+int( work( 1_${ik}$ ),KIND=${ik}$) ) call stdlib${ii}$_slaqz0( 'S', jobvl, jobvr, n, 1_${ik}$, n, a, lda, b, ldb,alphar, alphai, & beta, vl, ldvl, vr, ldvr,work, -1_${ik}$, 0_${ik}$, ierr ) lwkopt = max( lwkopt, 2_${ik}$*n+int( work( 1_${ik}$ ),KIND=${ik}$) ) else call stdlib${ii}$_slaqz0( 'E', jobvl, jobvr, n, 1_${ik}$, n, a, lda, b, ldb,alphar, alphai, & beta, vl, ldvl, vr, ldvr,work, -1_${ik}$, 0_${ik}$, ierr ) lwkopt = max( lwkopt, 2_${ik}$*n+int( work( 1_${ik}$ ),KIND=${ik}$) ) end if work( 1_${ik}$ ) = real( lwkopt,KIND=sp) end if if( info/=0_${ik}$ ) then call stdlib${ii}$_xerbla( 'SGGEV3 ', -info ) return else if( lquery ) then return end if ! quick return if possible if( n==0 )return ! get machine constants eps = stdlib${ii}$_slamch( 'P' ) smlnum = stdlib${ii}$_slamch( 'S' ) bignum = one / smlnum call stdlib${ii}$_slabad( smlnum, bignum ) smlnum = sqrt( smlnum ) / eps bignum = one / smlnum ! scale a if max element outside range [smlnum,bignum] anrm = stdlib${ii}$_slange( 'M', n, n, a, lda, work ) ilascl = .false. if( anrm>zero .and. anrm<smlnum ) then anrmto = smlnum ilascl = .true. else if( anrm>bignum ) then anrmto = bignum ilascl = .true. end if if( ilascl )call stdlib${ii}$_slascl( 'G', 0_${ik}$, 0_${ik}$, anrm, anrmto, n, n, a, lda, ierr ) ! scale b if max element outside range [smlnum,bignum] bnrm = stdlib${ii}$_slange( 'M', n, n, b, ldb, work ) ilbscl = .false. if( bnrm>zero .and. bnrm<smlnum ) then bnrmto = smlnum ilbscl = .true. else if( bnrm>bignum ) then bnrmto = bignum ilbscl = .true. end if if( ilbscl )call stdlib${ii}$_slascl( 'G', 0_${ik}$, 0_${ik}$, bnrm, bnrmto, n, n, b, ldb, ierr ) ! permute the matrices a, b to isolate eigenvalues if possible ileft = 1_${ik}$ iright = n + 1_${ik}$ iwrk = iright + n call stdlib${ii}$_sggbal( 'P', n, a, lda, b, ldb, ilo, ihi, work( ileft ),work( iright ), & work( iwrk ), ierr ) ! reduce b to triangular form (qr decomposition of b) irows = ihi + 1_${ik}$ - ilo if( ilv ) then icols = n + 1_${ik}$ - ilo else icols = irows end if itau = iwrk iwrk = itau + irows call stdlib${ii}$_sgeqrf( irows, icols, b( ilo, ilo ), ldb, work( itau ),work( iwrk ), lwork+& 1_${ik}$-iwrk, ierr ) ! apply the orthogonal transformation to matrix a call stdlib${ii}$_sormqr( 'L', 'T', irows, icols, irows, b( ilo, ilo ), ldb,work( itau ), a( & ilo, ilo ), lda, work( iwrk ),lwork+1-iwrk, ierr ) ! initialize vl if( ilvl ) then call stdlib${ii}$_slaset( 'FULL', n, n, zero, one, vl, ldvl ) if( irows>1_${ik}$ ) then call stdlib${ii}$_slacpy( 'L', irows-1, irows-1, b( ilo+1, ilo ), ldb,vl( ilo+1, ilo ),& ldvl ) end if call stdlib${ii}$_sorgqr( irows, irows, irows, vl( ilo, ilo ), ldvl,work( itau ), work( & iwrk ), lwork+1-iwrk, ierr ) end if ! initialize vr if( ilvr )call stdlib${ii}$_slaset( 'FULL', n, n, zero, one, vr, ldvr ) ! reduce to generalized hessenberg form if( ilv ) then ! eigenvectors requested -- work on whole matrix. call stdlib${ii}$_sgghd3( jobvl, jobvr, n, ilo, ihi, a, lda, b, ldb, vl,ldvl, vr, ldvr, & work( iwrk ), lwork+1-iwrk, ierr ) else call stdlib${ii}$_sgghd3( 'N', 'N', irows, 1_${ik}$, irows, a( ilo, ilo ), lda,b( ilo, ilo ), & ldb, vl, ldvl, vr, ldvr,work( iwrk ), lwork+1-iwrk, ierr ) end if ! perform qz algorithm (compute eigenvalues, and optionally, the ! schur forms and schur vectors) iwrk = itau if( ilv ) then chtemp = 'S' else chtemp = 'E' end if call stdlib${ii}$_slaqz0( chtemp, jobvl, jobvr, n, ilo, ihi, a, lda, b, ldb,alphar, alphai, & beta, vl, ldvl, vr, ldvr,work( iwrk ), lwork+1-iwrk, 0_${ik}$, ierr ) if( ierr/=0_${ik}$ ) then if( ierr>0_${ik}$ .and. ierr<=n ) then info = ierr else if( ierr>n .and. ierr<=2_${ik}$*n ) then info = ierr - n else info = n + 1_${ik}$ end if go to 110 end if ! compute eigenvectors if( ilv ) then if( ilvl ) then if( ilvr ) then chtemp = 'B' else chtemp = 'L' end if else chtemp = 'R' end if call stdlib${ii}$_stgevc( chtemp, 'B', ldumma, n, a, lda, b, ldb, vl, ldvl,vr, ldvr, n, & in, work( iwrk ), ierr ) if( ierr/=0_${ik}$ ) then info = n + 2_${ik}$ go to 110 end if ! undo balancing on vl and vr and normalization if( ilvl ) then call stdlib${ii}$_sggbak( 'P', 'L', n, ilo, ihi, work( ileft ),work( iright ), n, vl, & ldvl, ierr ) loop_50: do jc = 1, n if( alphai( jc )<zero )cycle loop_50 temp = zero if( alphai( jc )==zero ) then do jr = 1, n temp = max( temp, abs( vl( jr, jc ) ) ) end do else do jr = 1, n temp = max( temp, abs( vl( jr, jc ) )+abs( vl( jr, jc+1 ) ) ) end do end if if( temp<smlnum )cycle loop_50 temp = one / temp if( alphai( jc )==zero ) then do jr = 1, n vl( jr, jc ) = vl( jr, jc )*temp end do else do jr = 1, n vl( jr, jc ) = vl( jr, jc )*temp vl( jr, jc+1 ) = vl( jr, jc+1 )*temp end do end if end do loop_50 end if if( ilvr ) then call stdlib${ii}$_sggbak( 'P', 'R', n, ilo, ihi, work( ileft ),work( iright ), n, vr, & ldvr, ierr ) loop_100: do jc = 1, n if( alphai( jc )<zero )cycle loop_100 temp = zero if( alphai( jc )==zero ) then do jr = 1, n temp = max( temp, abs( vr( jr, jc ) ) ) end do else do jr = 1, n temp = max( temp, abs( vr( jr, jc ) )+abs( vr( jr, jc+1 ) ) ) end do end if if( temp<smlnum )cycle loop_100 temp = one / temp if( alphai( jc )==zero ) then do jr = 1, n vr( jr, jc ) = vr( jr, jc )*temp end do else do jr = 1, n vr( jr, jc ) = vr( jr, jc )*temp vr( jr, jc+1 ) = vr( jr, jc+1 )*temp end do end if end do loop_100 end if ! end of eigenvector calculation end if ! undo scaling if necessary 110 continue if( ilascl ) then call stdlib${ii}$_slascl( 'G', 0_${ik}$, 0_${ik}$, anrmto, anrm, n, 1_${ik}$, alphar, n, ierr ) call stdlib${ii}$_slascl( 'G', 0_${ik}$, 0_${ik}$, anrmto, anrm, n, 1_${ik}$, alphai, n, ierr ) end if if( ilbscl ) then call stdlib${ii}$_slascl( 'G', 0_${ik}$, 0_${ik}$, bnrmto, bnrm, n, 1_${ik}$, beta, n, ierr ) end if work( 1_${ik}$ ) = real( lwkopt,KIND=sp) return end subroutine stdlib${ii}$_sggev3 module subroutine stdlib${ii}$_dggev3( jobvl, jobvr, n, a, lda, b, ldb, alphar,alphai, beta, vl, ldvl, vr,& !! DGGEV3 computes for a pair of N-by-N real nonsymmetric matrices (A,B) !! the generalized eigenvalues, and optionally, the left and/or right !! generalized eigenvectors. !! A generalized eigenvalue for a pair of matrices (A,B) is a scalar !! lambda or a ratio alpha/beta = lambda, such that A - lambda*B is !! singular. It is usually represented as the pair (alpha,beta), as !! there is a reasonable interpretation for beta=0, and even for both !! being zero. !! The right eigenvector v(j) corresponding to the eigenvalue lambda(j) !! of (A,B) satisfies !! A * v(j) = lambda(j) * B * v(j). !! The left eigenvector u(j) corresponding to the eigenvalue lambda(j) !! of (A,B) satisfies !! u(j)**H * A = lambda(j) * u(j)**H * B . !! where u(j)**H is the conjugate-transpose of u(j). ldvr, work, lwork,info ) ! -- lapack driver routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_dp, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments character, intent(in) :: jobvl, jobvr integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: lda, ldb, ldvl, ldvr, lwork, n ! Array Arguments real(dp), intent(inout) :: a(lda,*), b(ldb,*) real(dp), intent(out) :: alphai(*), alphar(*), beta(*), vl(ldvl,*), vr(ldvr,*), work(*) ! ===================================================================== ! Local Scalars logical(lk) :: ilascl, ilbscl, ilv, ilvl, ilvr, lquery character :: chtemp integer(${ik}$) :: icols, ierr, ihi, ijobvl, ijobvr, ileft, ilo, in, iright, irows, itau, & iwrk, jc, jr, lwkopt real(dp) :: anrm, anrmto, bignum, bnrm, bnrmto, eps, smlnum, temp ! Local Arrays logical(lk) :: ldumma(1_${ik}$) ! Intrinsic Functions ! Executable Statements ! decode the input arguments if( stdlib_lsame( jobvl, 'N' ) ) then ijobvl = 1_${ik}$ ilvl = .false. else if( stdlib_lsame( jobvl, 'V' ) ) then ijobvl = 2_${ik}$ ilvl = .true. else ijobvl = -1_${ik}$ ilvl = .false. end if if( stdlib_lsame( jobvr, 'N' ) ) then ijobvr = 1_${ik}$ ilvr = .false. else if( stdlib_lsame( jobvr, 'V' ) ) then ijobvr = 2_${ik}$ ilvr = .true. else ijobvr = -1_${ik}$ ilvr = .false. end if ilv = ilvl .or. ilvr ! test the input arguments info = 0_${ik}$ lquery = ( lwork==-1_${ik}$ ) if( ijobvl<=0_${ik}$ ) then info = -1_${ik}$ else if( ijobvr<=0_${ik}$ ) then info = -2_${ik}$ else if( n<0_${ik}$ ) then info = -3_${ik}$ else if( lda<max( 1_${ik}$, n ) ) then info = -5_${ik}$ else if( ldb<max( 1_${ik}$, n ) ) then info = -7_${ik}$ else if( ldvl<1_${ik}$ .or. ( ilvl .and. ldvl<n ) ) then info = -12_${ik}$ else if( ldvr<1_${ik}$ .or. ( ilvr .and. ldvr<n ) ) then info = -14_${ik}$ else if( lwork<max( 1_${ik}$, 8_${ik}$*n ) .and. .not.lquery ) then info = -16_${ik}$ end if ! compute workspace if( info==0_${ik}$ ) then call stdlib${ii}$_dgeqrf( n, n, b, ldb, work, work, -1_${ik}$, ierr ) lwkopt = max(1_${ik}$, 8_${ik}$*n, 3_${ik}$*n+int( work( 1_${ik}$ ),KIND=${ik}$) ) call stdlib${ii}$_dormqr( 'L', 'T', n, n, n, b, ldb, work, a, lda, work, -1_${ik}$,ierr ) lwkopt = max( lwkopt, 3_${ik}$*n+int( work ( 1_${ik}$ ),KIND=${ik}$) ) if( ilvl ) then call stdlib${ii}$_dorgqr( n, n, n, vl, ldvl, work, work, -1_${ik}$, ierr ) lwkopt = max( lwkopt, 3_${ik}$*n+int( work ( 1_${ik}$ ),KIND=${ik}$) ) end if if( ilv ) then call stdlib${ii}$_dgghd3( jobvl, jobvr, n, 1_${ik}$, n, a, lda, b, ldb, vl,ldvl, vr, ldvr, & work, -1_${ik}$, ierr ) lwkopt = max( lwkopt, 3_${ik}$*n+int( work ( 1_${ik}$ ),KIND=${ik}$) ) call stdlib${ii}$_dlaqz0( 'S', jobvl, jobvr, n, 1_${ik}$, n, a, lda, b, ldb,alphar, alphai, & beta, vl, ldvl, vr, ldvr,work, -1_${ik}$, 0_${ik}$, ierr ) lwkopt = max( lwkopt, 2_${ik}$*n+int( work ( 1_${ik}$ ),KIND=${ik}$) ) else call stdlib${ii}$_dgghd3( 'N', 'N', n, 1_${ik}$, n, a, lda, b, ldb, vl, ldvl,vr, ldvr, work, -& 1_${ik}$, ierr ) lwkopt = max( lwkopt, 3_${ik}$*n+int( work ( 1_${ik}$ ),KIND=${ik}$) ) call stdlib${ii}$_dlaqz0( 'E', jobvl, jobvr, n, 1_${ik}$, n, a, lda, b, ldb,alphar, alphai, & beta, vl, ldvl, vr, ldvr,work, -1_${ik}$, 0_${ik}$, ierr ) lwkopt = max( lwkopt, 2_${ik}$*n+int( work ( 1_${ik}$ ),KIND=${ik}$) ) end if work( 1_${ik}$ ) = lwkopt end if if( info/=0_${ik}$ ) then call stdlib${ii}$_xerbla( 'DGGEV3 ', -info ) return else if( lquery ) then return end if ! quick return if possible if( n==0 )return ! get machine constants eps = stdlib${ii}$_dlamch( 'P' ) smlnum = stdlib${ii}$_dlamch( 'S' ) bignum = one / smlnum call stdlib${ii}$_dlabad( smlnum, bignum ) smlnum = sqrt( smlnum ) / eps bignum = one / smlnum ! scale a if max element outside range [smlnum,bignum] anrm = stdlib${ii}$_dlange( 'M', n, n, a, lda, work ) ilascl = .false. if( anrm>zero .and. anrm<smlnum ) then anrmto = smlnum ilascl = .true. else if( anrm>bignum ) then anrmto = bignum ilascl = .true. end if if( ilascl )call stdlib${ii}$_dlascl( 'G', 0_${ik}$, 0_${ik}$, anrm, anrmto, n, n, a, lda, ierr ) ! scale b if max element outside range [smlnum,bignum] bnrm = stdlib${ii}$_dlange( 'M', n, n, b, ldb, work ) ilbscl = .false. if( bnrm>zero .and. bnrm<smlnum ) then bnrmto = smlnum ilbscl = .true. else if( bnrm>bignum ) then bnrmto = bignum ilbscl = .true. end if if( ilbscl )call stdlib${ii}$_dlascl( 'G', 0_${ik}$, 0_${ik}$, bnrm, bnrmto, n, n, b, ldb, ierr ) ! permute the matrices a, b to isolate eigenvalues if possible ileft = 1_${ik}$ iright = n + 1_${ik}$ iwrk = iright + n call stdlib${ii}$_dggbal( 'P', n, a, lda, b, ldb, ilo, ihi, work( ileft ),work( iright ), & work( iwrk ), ierr ) ! reduce b to triangular form (qr decomposition of b) irows = ihi + 1_${ik}$ - ilo if( ilv ) then icols = n + 1_${ik}$ - ilo else icols = irows end if itau = iwrk iwrk = itau + irows call stdlib${ii}$_dgeqrf( irows, icols, b( ilo, ilo ), ldb, work( itau ),work( iwrk ), lwork+& 1_${ik}$-iwrk, ierr ) ! apply the orthogonal transformation to matrix a call stdlib${ii}$_dormqr( 'L', 'T', irows, icols, irows, b( ilo, ilo ), ldb,work( itau ), a( & ilo, ilo ), lda, work( iwrk ),lwork+1-iwrk, ierr ) ! initialize vl if( ilvl ) then call stdlib${ii}$_dlaset( 'FULL', n, n, zero, one, vl, ldvl ) if( irows>1_${ik}$ ) then call stdlib${ii}$_dlacpy( 'L', irows-1, irows-1, b( ilo+1, ilo ), ldb,vl( ilo+1, ilo ),& ldvl ) end if call stdlib${ii}$_dorgqr( irows, irows, irows, vl( ilo, ilo ), ldvl,work( itau ), work( & iwrk ), lwork+1-iwrk, ierr ) end if ! initialize vr if( ilvr )call stdlib${ii}$_dlaset( 'FULL', n, n, zero, one, vr, ldvr ) ! reduce to generalized hessenberg form if( ilv ) then ! eigenvectors requested -- work on whole matrix. call stdlib${ii}$_dgghd3( jobvl, jobvr, n, ilo, ihi, a, lda, b, ldb, vl,ldvl, vr, ldvr, & work( iwrk ), lwork+1-iwrk, ierr ) else call stdlib${ii}$_dgghd3( 'N', 'N', irows, 1_${ik}$, irows, a( ilo, ilo ), lda,b( ilo, ilo ), & ldb, vl, ldvl, vr, ldvr,work( iwrk ), lwork+1-iwrk, ierr ) end if ! perform qz algorithm (compute eigenvalues, and optionally, the ! schur forms and schur vectors) iwrk = itau if( ilv ) then chtemp = 'S' else chtemp = 'E' end if call stdlib${ii}$_dlaqz0( chtemp, jobvl, jobvr, n, ilo, ihi, a, lda, b, ldb,alphar, alphai, & beta, vl, ldvl, vr, ldvr,work( iwrk ), lwork+1-iwrk, 0_${ik}$, ierr ) if( ierr/=0_${ik}$ ) then if( ierr>0_${ik}$ .and. ierr<=n ) then info = ierr else if( ierr>n .and. ierr<=2_${ik}$*n ) then info = ierr - n else info = n + 1_${ik}$ end if go to 110 end if ! compute eigenvectors if( ilv ) then if( ilvl ) then if( ilvr ) then chtemp = 'B' else chtemp = 'L' end if else chtemp = 'R' end if call stdlib${ii}$_dtgevc( chtemp, 'B', ldumma, n, a, lda, b, ldb, vl, ldvl,vr, ldvr, n, & in, work( iwrk ), ierr ) if( ierr/=0_${ik}$ ) then info = n + 2_${ik}$ go to 110 end if ! undo balancing on vl and vr and normalization if( ilvl ) then call stdlib${ii}$_dggbak( 'P', 'L', n, ilo, ihi, work( ileft ),work( iright ), n, vl, & ldvl, ierr ) loop_50: do jc = 1, n if( alphai( jc )<zero )cycle loop_50 temp = zero if( alphai( jc )==zero ) then do jr = 1, n temp = max( temp, abs( vl( jr, jc ) ) ) end do else do jr = 1, n temp = max( temp, abs( vl( jr, jc ) )+abs( vl( jr, jc+1 ) ) ) end do end if if( temp<smlnum )cycle loop_50 temp = one / temp if( alphai( jc )==zero ) then do jr = 1, n vl( jr, jc ) = vl( jr, jc )*temp end do else do jr = 1, n vl( jr, jc ) = vl( jr, jc )*temp vl( jr, jc+1 ) = vl( jr, jc+1 )*temp end do end if end do loop_50 end if if( ilvr ) then call stdlib${ii}$_dggbak( 'P', 'R', n, ilo, ihi, work( ileft ),work( iright ), n, vr, & ldvr, ierr ) loop_100: do jc = 1, n if( alphai( jc )<zero )cycle loop_100 temp = zero if( alphai( jc )==zero ) then do jr = 1, n temp = max( temp, abs( vr( jr, jc ) ) ) end do else do jr = 1, n temp = max( temp, abs( vr( jr, jc ) )+abs( vr( jr, jc+1 ) ) ) end do end if if( temp<smlnum )cycle loop_100 temp = one / temp if( alphai( jc )==zero ) then do jr = 1, n vr( jr, jc ) = vr( jr, jc )*temp end do else do jr = 1, n vr( jr, jc ) = vr( jr, jc )*temp vr( jr, jc+1 ) = vr( jr, jc+1 )*temp end do end if end do loop_100 end if ! end of eigenvector calculation end if ! undo scaling if necessary 110 continue if( ilascl ) then call stdlib${ii}$_dlascl( 'G', 0_${ik}$, 0_${ik}$, anrmto, anrm, n, 1_${ik}$, alphar, n, ierr ) call stdlib${ii}$_dlascl( 'G', 0_${ik}$, 0_${ik}$, anrmto, anrm, n, 1_${ik}$, alphai, n, ierr ) end if if( ilbscl ) then call stdlib${ii}$_dlascl( 'G', 0_${ik}$, 0_${ik}$, bnrmto, bnrm, n, 1_${ik}$, beta, n, ierr ) end if work( 1_${ik}$ ) = lwkopt return end subroutine stdlib${ii}$_dggev3 #:for rk,rt,ri in REAL_KINDS_TYPES #:if not rk in ["sp","dp"] module subroutine stdlib${ii}$_${ri}$ggev3( jobvl, jobvr, n, a, lda, b, ldb, alphar,alphai, beta, vl, ldvl, vr,& !! DGGEV3: computes for a pair of N-by-N real nonsymmetric matrices (A,B) !! the generalized eigenvalues, and optionally, the left and/or right !! generalized eigenvectors. !! A generalized eigenvalue for a pair of matrices (A,B) is a scalar !! lambda or a ratio alpha/beta = lambda, such that A - lambda*B is !! singular. It is usually represented as the pair (alpha,beta), as !! there is a reasonable interpretation for beta=0, and even for both !! being zero. !! The right eigenvector v(j) corresponding to the eigenvalue lambda(j) !! of (A,B) satisfies !! A * v(j) = lambda(j) * B * v(j). !! The left eigenvector u(j) corresponding to the eigenvalue lambda(j) !! of (A,B) satisfies !! u(j)**H * A = lambda(j) * u(j)**H * B . !! where u(j)**H is the conjugate-transpose of u(j). ldvr, work, lwork,info ) ! -- lapack driver routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_${rk}$, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments character, intent(in) :: jobvl, jobvr integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: lda, ldb, ldvl, ldvr, lwork, n ! Array Arguments real(${rk}$), intent(inout) :: a(lda,*), b(ldb,*) real(${rk}$), intent(out) :: alphai(*), alphar(*), beta(*), vl(ldvl,*), vr(ldvr,*), work(*) ! ===================================================================== ! Local Scalars logical(lk) :: ilascl, ilbscl, ilv, ilvl, ilvr, lquery character :: chtemp integer(${ik}$) :: icols, ierr, ihi, ijobvl, ijobvr, ileft, ilo, in, iright, irows, itau, & iwrk, jc, jr, lwkopt real(${rk}$) :: anrm, anrmto, bignum, bnrm, bnrmto, eps, smlnum, temp ! Local Arrays logical(lk) :: ldumma(1_${ik}$) ! Intrinsic Functions ! Executable Statements ! decode the input arguments if( stdlib_lsame( jobvl, 'N' ) ) then ijobvl = 1_${ik}$ ilvl = .false. else if( stdlib_lsame( jobvl, 'V' ) ) then ijobvl = 2_${ik}$ ilvl = .true. else ijobvl = -1_${ik}$ ilvl = .false. end if if( stdlib_lsame( jobvr, 'N' ) ) then ijobvr = 1_${ik}$ ilvr = .false. else if( stdlib_lsame( jobvr, 'V' ) ) then ijobvr = 2_${ik}$ ilvr = .true. else ijobvr = -1_${ik}$ ilvr = .false. end if ilv = ilvl .or. ilvr ! test the input arguments info = 0_${ik}$ lquery = ( lwork==-1_${ik}$ ) if( ijobvl<=0_${ik}$ ) then info = -1_${ik}$ else if( ijobvr<=0_${ik}$ ) then info = -2_${ik}$ else if( n<0_${ik}$ ) then info = -3_${ik}$ else if( lda<max( 1_${ik}$, n ) ) then info = -5_${ik}$ else if( ldb<max( 1_${ik}$, n ) ) then info = -7_${ik}$ else if( ldvl<1_${ik}$ .or. ( ilvl .and. ldvl<n ) ) then info = -12_${ik}$ else if( ldvr<1_${ik}$ .or. ( ilvr .and. ldvr<n ) ) then info = -14_${ik}$ else if( lwork<max( 1_${ik}$, 8_${ik}$*n ) .and. .not.lquery ) then info = -16_${ik}$ end if ! compute workspace if( info==0_${ik}$ ) then call stdlib${ii}$_${ri}$geqrf( n, n, b, ldb, work, work, -1_${ik}$, ierr ) lwkopt = max(1_${ik}$, 8_${ik}$*n, 3_${ik}$*n+int( work( 1_${ik}$ ),KIND=${ik}$) ) call stdlib${ii}$_${ri}$ormqr( 'L', 'T', n, n, n, b, ldb, work, a, lda, work, -1_${ik}$,ierr ) lwkopt = max( lwkopt, 3_${ik}$*n+int( work ( 1_${ik}$ ),KIND=${ik}$) ) if( ilvl ) then call stdlib${ii}$_${ri}$orgqr( n, n, n, vl, ldvl, work, work, -1_${ik}$, ierr ) lwkopt = max( lwkopt, 3_${ik}$*n+int( work ( 1_${ik}$ ),KIND=${ik}$) ) end if if( ilv ) then call stdlib${ii}$_${ri}$gghd3( jobvl, jobvr, n, 1_${ik}$, n, a, lda, b, ldb, vl,ldvl, vr, ldvr, & work, -1_${ik}$, ierr ) lwkopt = max( lwkopt, 3_${ik}$*n+int( work ( 1_${ik}$ ),KIND=${ik}$) ) call stdlib${ii}$_${ri}$laqz0( 'S', jobvl, jobvr, n, 1_${ik}$, n, a, lda, b, ldb,alphar, alphai, & beta, vl, ldvl, vr, ldvr,work, -1_${ik}$, 0_${ik}$, ierr ) lwkopt = max( lwkopt, 2_${ik}$*n+int( work ( 1_${ik}$ ),KIND=${ik}$) ) else call stdlib${ii}$_${ri}$gghd3( 'N', 'N', n, 1_${ik}$, n, a, lda, b, ldb, vl, ldvl,vr, ldvr, work, -& 1_${ik}$, ierr ) lwkopt = max( lwkopt, 3_${ik}$*n+int( work ( 1_${ik}$ ),KIND=${ik}$) ) call stdlib${ii}$_${ri}$laqz0( 'E', jobvl, jobvr, n, 1_${ik}$, n, a, lda, b, ldb,alphar, alphai, & beta, vl, ldvl, vr, ldvr,work, -1_${ik}$, 0_${ik}$, ierr ) lwkopt = max( lwkopt, 2_${ik}$*n+int( work ( 1_${ik}$ ),KIND=${ik}$) ) end if work( 1_${ik}$ ) = lwkopt end if if( info/=0_${ik}$ ) then call stdlib${ii}$_xerbla( 'DGGEV3 ', -info ) return else if( lquery ) then return end if ! quick return if possible if( n==0 )return ! get machine constants eps = stdlib${ii}$_${ri}$lamch( 'P' ) smlnum = stdlib${ii}$_${ri}$lamch( 'S' ) bignum = one / smlnum call stdlib${ii}$_${ri}$labad( smlnum, bignum ) smlnum = sqrt( smlnum ) / eps bignum = one / smlnum ! scale a if max element outside range [smlnum,bignum] anrm = stdlib${ii}$_${ri}$lange( 'M', n, n, a, lda, work ) ilascl = .false. if( anrm>zero .and. anrm<smlnum ) then anrmto = smlnum ilascl = .true. else if( anrm>bignum ) then anrmto = bignum ilascl = .true. end if if( ilascl )call stdlib${ii}$_${ri}$lascl( 'G', 0_${ik}$, 0_${ik}$, anrm, anrmto, n, n, a, lda, ierr ) ! scale b if max element outside range [smlnum,bignum] bnrm = stdlib${ii}$_${ri}$lange( 'M', n, n, b, ldb, work ) ilbscl = .false. if( bnrm>zero .and. bnrm<smlnum ) then bnrmto = smlnum ilbscl = .true. else if( bnrm>bignum ) then bnrmto = bignum ilbscl = .true. end if if( ilbscl )call stdlib${ii}$_${ri}$lascl( 'G', 0_${ik}$, 0_${ik}$, bnrm, bnrmto, n, n, b, ldb, ierr ) ! permute the matrices a, b to isolate eigenvalues if possible ileft = 1_${ik}$ iright = n + 1_${ik}$ iwrk = iright + n call stdlib${ii}$_${ri}$ggbal( 'P', n, a, lda, b, ldb, ilo, ihi, work( ileft ),work( iright ), & work( iwrk ), ierr ) ! reduce b to triangular form (qr decomposition of b) irows = ihi + 1_${ik}$ - ilo if( ilv ) then icols = n + 1_${ik}$ - ilo else icols = irows end if itau = iwrk iwrk = itau + irows call stdlib${ii}$_${ri}$geqrf( irows, icols, b( ilo, ilo ), ldb, work( itau ),work( iwrk ), lwork+& 1_${ik}$-iwrk, ierr ) ! apply the orthogonal transformation to matrix a call stdlib${ii}$_${ri}$ormqr( 'L', 'T', irows, icols, irows, b( ilo, ilo ), ldb,work( itau ), a( & ilo, ilo ), lda, work( iwrk ),lwork+1-iwrk, ierr ) ! initialize vl if( ilvl ) then call stdlib${ii}$_${ri}$laset( 'FULL', n, n, zero, one, vl, ldvl ) if( irows>1_${ik}$ ) then call stdlib${ii}$_${ri}$lacpy( 'L', irows-1, irows-1, b( ilo+1, ilo ), ldb,vl( ilo+1, ilo ),& ldvl ) end if call stdlib${ii}$_${ri}$orgqr( irows, irows, irows, vl( ilo, ilo ), ldvl,work( itau ), work( & iwrk ), lwork+1-iwrk, ierr ) end if ! initialize vr if( ilvr )call stdlib${ii}$_${ri}$laset( 'FULL', n, n, zero, one, vr, ldvr ) ! reduce to generalized hessenberg form if( ilv ) then ! eigenvectors requested -- work on whole matrix. call stdlib${ii}$_${ri}$gghd3( jobvl, jobvr, n, ilo, ihi, a, lda, b, ldb, vl,ldvl, vr, ldvr, & work( iwrk ), lwork+1-iwrk, ierr ) else call stdlib${ii}$_${ri}$gghd3( 'N', 'N', irows, 1_${ik}$, irows, a( ilo, ilo ), lda,b( ilo, ilo ), & ldb, vl, ldvl, vr, ldvr,work( iwrk ), lwork+1-iwrk, ierr ) end if ! perform qz algorithm (compute eigenvalues, and optionally, the ! schur forms and schur vectors) iwrk = itau if( ilv ) then chtemp = 'S' else chtemp = 'E' end if call stdlib${ii}$_${ri}$laqz0( chtemp, jobvl, jobvr, n, ilo, ihi, a, lda, b, ldb,alphar, alphai, & beta, vl, ldvl, vr, ldvr,work( iwrk ), lwork+1-iwrk, 0_${ik}$, ierr ) if( ierr/=0_${ik}$ ) then if( ierr>0_${ik}$ .and. ierr<=n ) then info = ierr else if( ierr>n .and. ierr<=2_${ik}$*n ) then info = ierr - n else info = n + 1_${ik}$ end if go to 110 end if ! compute eigenvectors if( ilv ) then if( ilvl ) then if( ilvr ) then chtemp = 'B' else chtemp = 'L' end if else chtemp = 'R' end if call stdlib${ii}$_${ri}$tgevc( chtemp, 'B', ldumma, n, a, lda, b, ldb, vl, ldvl,vr, ldvr, n, & in, work( iwrk ), ierr ) if( ierr/=0_${ik}$ ) then info = n + 2_${ik}$ go to 110 end if ! undo balancing on vl and vr and normalization if( ilvl ) then call stdlib${ii}$_${ri}$ggbak( 'P', 'L', n, ilo, ihi, work( ileft ),work( iright ), n, vl, & ldvl, ierr ) loop_50: do jc = 1, n if( alphai( jc )<zero )cycle loop_50 temp = zero if( alphai( jc )==zero ) then do jr = 1, n temp = max( temp, abs( vl( jr, jc ) ) ) end do else do jr = 1, n temp = max( temp, abs( vl( jr, jc ) )+abs( vl( jr, jc+1 ) ) ) end do end if if( temp<smlnum )cycle loop_50 temp = one / temp if( alphai( jc )==zero ) then do jr = 1, n vl( jr, jc ) = vl( jr, jc )*temp end do else do jr = 1, n vl( jr, jc ) = vl( jr, jc )*temp vl( jr, jc+1 ) = vl( jr, jc+1 )*temp end do end if end do loop_50 end if if( ilvr ) then call stdlib${ii}$_${ri}$ggbak( 'P', 'R', n, ilo, ihi, work( ileft ),work( iright ), n, vr, & ldvr, ierr ) loop_100: do jc = 1, n if( alphai( jc )<zero )cycle loop_100 temp = zero if( alphai( jc )==zero ) then do jr = 1, n temp = max( temp, abs( vr( jr, jc ) ) ) end do else do jr = 1, n temp = max( temp, abs( vr( jr, jc ) )+abs( vr( jr, jc+1 ) ) ) end do end if if( temp<smlnum )cycle loop_100 temp = one / temp if( alphai( jc )==zero ) then do jr = 1, n vr( jr, jc ) = vr( jr, jc )*temp end do else do jr = 1, n vr( jr, jc ) = vr( jr, jc )*temp vr( jr, jc+1 ) = vr( jr, jc+1 )*temp end do end if end do loop_100 end if ! end of eigenvector calculation end if ! undo scaling if necessary 110 continue if( ilascl ) then call stdlib${ii}$_${ri}$lascl( 'G', 0_${ik}$, 0_${ik}$, anrmto, anrm, n, 1_${ik}$, alphar, n, ierr ) call stdlib${ii}$_${ri}$lascl( 'G', 0_${ik}$, 0_${ik}$, anrmto, anrm, n, 1_${ik}$, alphai, n, ierr ) end if if( ilbscl ) then call stdlib${ii}$_${ri}$lascl( 'G', 0_${ik}$, 0_${ik}$, bnrmto, bnrm, n, 1_${ik}$, beta, n, ierr ) end if work( 1_${ik}$ ) = lwkopt return end subroutine stdlib${ii}$_${ri}$ggev3 #:endif #:endfor module subroutine stdlib${ii}$_cggev3( jobvl, jobvr, n, a, lda, b, ldb, alpha, beta,vl, ldvl, vr, ldvr, & !! CGGEV3 computes for a pair of N-by-N complex nonsymmetric matrices !! (A,B), the generalized eigenvalues, and optionally, the left and/or !! right generalized eigenvectors. !! A generalized eigenvalue for a pair of matrices (A,B) is a scalar !! lambda or a ratio alpha/beta = lambda, such that A - lambda*B is !! singular. It is usually represented as the pair (alpha,beta), as !! there is a reasonable interpretation for beta=0, and even for both !! being zero. !! The right generalized eigenvector v(j) corresponding to the !! generalized eigenvalue lambda(j) of (A,B) satisfies !! A * v(j) = lambda(j) * B * v(j). !! The left generalized eigenvector u(j) corresponding to the !! generalized eigenvalues lambda(j) of (A,B) satisfies !! u(j)**H * A = lambda(j) * u(j)**H * B !! where u(j)**H is the conjugate-transpose of u(j). work, lwork, rwork, info ) ! -- lapack driver routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_sp, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments character, intent(in) :: jobvl, jobvr integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: lda, ldb, ldvl, ldvr, lwork, n ! Array Arguments real(sp), intent(out) :: rwork(*) complex(sp), intent(inout) :: a(lda,*), b(ldb,*) complex(sp), intent(out) :: alpha(*), beta(*), vl(ldvl,*), vr(ldvr,*), work(*) ! ===================================================================== ! Local Scalars logical(lk) :: ilascl, ilbscl, ilv, ilvl, ilvr, lquery character :: chtemp integer(${ik}$) :: icols, ierr, ihi, ijobvl, ijobvr, ileft, ilo, in, iright, irows, irwrk,& itau, iwrk, jc, jr, lwkopt real(sp) :: anrm, anrmto, bignum, bnrm, bnrmto, eps, smlnum, temp complex(sp) :: x ! Local Arrays logical(lk) :: ldumma(1_${ik}$) ! Intrinsic Functions ! Statement Functions real(sp) :: abs1 ! Statement Function Definitions abs1( x ) = abs( real( x,KIND=sp) ) + abs( aimag( x ) ) ! Executable Statements ! decode the input arguments if( stdlib_lsame( jobvl, 'N' ) ) then ijobvl = 1_${ik}$ ilvl = .false. else if( stdlib_lsame( jobvl, 'V' ) ) then ijobvl = 2_${ik}$ ilvl = .true. else ijobvl = -1_${ik}$ ilvl = .false. end if if( stdlib_lsame( jobvr, 'N' ) ) then ijobvr = 1_${ik}$ ilvr = .false. else if( stdlib_lsame( jobvr, 'V' ) ) then ijobvr = 2_${ik}$ ilvr = .true. else ijobvr = -1_${ik}$ ilvr = .false. end if ilv = ilvl .or. ilvr ! test the input arguments info = 0_${ik}$ lquery = ( lwork==-1_${ik}$ ) if( ijobvl<=0_${ik}$ ) then info = -1_${ik}$ else if( ijobvr<=0_${ik}$ ) then info = -2_${ik}$ else if( n<0_${ik}$ ) then info = -3_${ik}$ else if( lda<max( 1_${ik}$, n ) ) then info = -5_${ik}$ else if( ldb<max( 1_${ik}$, n ) ) then info = -7_${ik}$ else if( ldvl<1_${ik}$ .or. ( ilvl .and. ldvl<n ) ) then info = -11_${ik}$ else if( ldvr<1_${ik}$ .or. ( ilvr .and. ldvr<n ) ) then info = -13_${ik}$ else if( lwork<max( 1_${ik}$, 2_${ik}$*n ) .and. .not.lquery ) then info = -15_${ik}$ end if ! compute workspace if( info==0_${ik}$ ) then call stdlib${ii}$_cgeqrf( n, n, b, ldb, work, work, -1_${ik}$, ierr ) lwkopt = max( n, n+int( work( 1_${ik}$ ),KIND=${ik}$) ) call stdlib${ii}$_cunmqr( 'L', 'C', n, n, n, b, ldb, work, a, lda, work,-1_${ik}$, ierr ) lwkopt = max( lwkopt, n+int( work( 1_${ik}$ ),KIND=${ik}$) ) if( ilvl ) then call stdlib${ii}$_cungqr( n, n, n, vl, ldvl, work, work, -1_${ik}$, ierr ) lwkopt = max( lwkopt, n+int( work( 1_${ik}$ ),KIND=${ik}$) ) end if if( ilv ) then call stdlib${ii}$_cgghd3( jobvl, jobvr, n, 1_${ik}$, n, a, lda, b, ldb, vl,ldvl, vr, ldvr, & work, -1_${ik}$, ierr ) lwkopt = max( lwkopt, n+int( work( 1_${ik}$ ),KIND=${ik}$) ) call stdlib${ii}$_claqz0( 'S', jobvl, jobvr, n, 1_${ik}$, n, a, lda, b, ldb,alpha, beta, vl, & ldvl, vr, ldvr, work, -1_${ik}$,rwork, 0_${ik}$, ierr ) lwkopt = max( lwkopt, n+int( work( 1_${ik}$ ),KIND=${ik}$) ) else call stdlib${ii}$_cgghd3( 'N', 'N', n, 1_${ik}$, n, a, lda, b, ldb, vl, ldvl,vr, ldvr, work, -& 1_${ik}$, ierr ) lwkopt = max( lwkopt, n+int( work( 1_${ik}$ ),KIND=${ik}$) ) call stdlib${ii}$_claqz0( 'E', jobvl, jobvr, n, 1_${ik}$, n, a, lda, b, ldb,alpha, beta, vl, & ldvl, vr, ldvr, work, -1_${ik}$,rwork, 0_${ik}$, ierr ) lwkopt = max( lwkopt, n+int( work( 1_${ik}$ ),KIND=${ik}$) ) end if work( 1_${ik}$ ) = cmplx( lwkopt,KIND=sp) end if if( info/=0_${ik}$ ) then call stdlib${ii}$_xerbla( 'CGGEV3 ', -info ) return else if( lquery ) then return end if ! quick return if possible if( n==0 )return ! get machine constants eps = stdlib${ii}$_slamch( 'E' )*stdlib${ii}$_slamch( 'B' ) smlnum = stdlib${ii}$_slamch( 'S' ) bignum = one / smlnum call stdlib${ii}$_slabad( smlnum, bignum ) smlnum = sqrt( smlnum ) / eps bignum = one / smlnum ! scale a if max element outside range [smlnum,bignum] anrm = stdlib${ii}$_clange( 'M', n, n, a, lda, rwork ) ilascl = .false. if( anrm>zero .and. anrm<smlnum ) then anrmto = smlnum ilascl = .true. else if( anrm>bignum ) then anrmto = bignum ilascl = .true. end if if( ilascl )call stdlib${ii}$_clascl( 'G', 0_${ik}$, 0_${ik}$, anrm, anrmto, n, n, a, lda, ierr ) ! scale b if max element outside range [smlnum,bignum] bnrm = stdlib${ii}$_clange( 'M', n, n, b, ldb, rwork ) ilbscl = .false. if( bnrm>zero .and. bnrm<smlnum ) then bnrmto = smlnum ilbscl = .true. else if( bnrm>bignum ) then bnrmto = bignum ilbscl = .true. end if if( ilbscl )call stdlib${ii}$_clascl( 'G', 0_${ik}$, 0_${ik}$, bnrm, bnrmto, n, n, b, ldb, ierr ) ! permute the matrices a, b to isolate eigenvalues if possible ileft = 1_${ik}$ iright = n + 1_${ik}$ irwrk = iright + n call stdlib${ii}$_cggbal( 'P', n, a, lda, b, ldb, ilo, ihi, rwork( ileft ),rwork( iright ), & rwork( irwrk ), ierr ) ! reduce b to triangular form (qr decomposition of b) irows = ihi + 1_${ik}$ - ilo if( ilv ) then icols = n + 1_${ik}$ - ilo else icols = irows end if itau = 1_${ik}$ iwrk = itau + irows call stdlib${ii}$_cgeqrf( irows, icols, b( ilo, ilo ), ldb, work( itau ),work( iwrk ), lwork+& 1_${ik}$-iwrk, ierr ) ! apply the orthogonal transformation to matrix a call stdlib${ii}$_cunmqr( 'L', 'C', irows, icols, irows, b( ilo, ilo ), ldb,work( itau ), a( & ilo, ilo ), lda, work( iwrk ),lwork+1-iwrk, ierr ) ! initialize vl if( ilvl ) then call stdlib${ii}$_claset( 'FULL', n, n, czero, cone, vl, ldvl ) if( irows>1_${ik}$ ) then call stdlib${ii}$_clacpy( 'L', irows-1, irows-1, b( ilo+1, ilo ), ldb,vl( ilo+1, ilo ),& ldvl ) end if call stdlib${ii}$_cungqr( irows, irows, irows, vl( ilo, ilo ), ldvl,work( itau ), work( & iwrk ), lwork+1-iwrk, ierr ) end if ! initialize vr if( ilvr )call stdlib${ii}$_claset( 'FULL', n, n, czero, cone, vr, ldvr ) ! reduce to generalized hessenberg form if( ilv ) then ! eigenvectors requested -- work on whole matrix. call stdlib${ii}$_cgghd3( jobvl, jobvr, n, ilo, ihi, a, lda, b, ldb, vl,ldvl, vr, ldvr, & work( iwrk ), lwork+1-iwrk,ierr ) else call stdlib${ii}$_cgghd3( 'N', 'N', irows, 1_${ik}$, irows, a( ilo, ilo ), lda,b( ilo, ilo ), & ldb, vl, ldvl, vr, ldvr,work( iwrk ), lwork+1-iwrk, ierr ) end if ! perform qz algorithm (compute eigenvalues, and optionally, the ! schur form and schur vectors) iwrk = itau if( ilv ) then chtemp = 'S' else chtemp = 'E' end if call stdlib${ii}$_claqz0( chtemp, jobvl, jobvr, n, ilo, ihi, a, lda, b, ldb,alpha, beta, vl, & ldvl, vr, ldvr, work( iwrk ),lwork+1-iwrk, rwork( irwrk ), 0_${ik}$, ierr ) if( ierr/=0_${ik}$ ) then if( ierr>0_${ik}$ .and. ierr<=n ) then info = ierr else if( ierr>n .and. ierr<=2_${ik}$*n ) then info = ierr - n else info = n + 1_${ik}$ end if go to 70 end if ! compute eigenvectors if( ilv ) then if( ilvl ) then if( ilvr ) then chtemp = 'B' else chtemp = 'L' end if else chtemp = 'R' end if call stdlib${ii}$_ctgevc( chtemp, 'B', ldumma, n, a, lda, b, ldb, vl, ldvl,vr, ldvr, n, & in, work( iwrk ), rwork( irwrk ),ierr ) if( ierr/=0_${ik}$ ) then info = n + 2_${ik}$ go to 70 end if ! undo balancing on vl and vr and normalization if( ilvl ) then call stdlib${ii}$_cggbak( 'P', 'L', n, ilo, ihi, rwork( ileft ),rwork( iright ), n, vl,& ldvl, ierr ) loop_30: do jc = 1, n temp = zero do jr = 1, n temp = max( temp, abs1( vl( jr, jc ) ) ) end do if( temp<smlnum )cycle loop_30 temp = one / temp do jr = 1, n vl( jr, jc ) = vl( jr, jc )*temp end do end do loop_30 end if if( ilvr ) then call stdlib${ii}$_cggbak( 'P', 'R', n, ilo, ihi, rwork( ileft ),rwork( iright ), n, vr,& ldvr, ierr ) loop_60: do jc = 1, n temp = zero do jr = 1, n temp = max( temp, abs1( vr( jr, jc ) ) ) end do if( temp<smlnum )cycle loop_60 temp = one / temp do jr = 1, n vr( jr, jc ) = vr( jr, jc )*temp end do end do loop_60 end if end if ! undo scaling if necessary 70 continue if( ilascl )call stdlib${ii}$_clascl( 'G', 0_${ik}$, 0_${ik}$, anrmto, anrm, n, 1_${ik}$, alpha, n, ierr ) if( ilbscl )call stdlib${ii}$_clascl( 'G', 0_${ik}$, 0_${ik}$, bnrmto, bnrm, n, 1_${ik}$, beta, n, ierr ) work( 1_${ik}$ ) = cmplx( lwkopt,KIND=sp) return end subroutine stdlib${ii}$_cggev3 module subroutine stdlib${ii}$_zggev3( jobvl, jobvr, n, a, lda, b, ldb, alpha, beta,vl, ldvl, vr, ldvr, & !! ZGGEV3 computes for a pair of N-by-N complex nonsymmetric matrices !! (A,B), the generalized eigenvalues, and optionally, the left and/or !! right generalized eigenvectors. !! A generalized eigenvalue for a pair of matrices (A,B) is a scalar !! lambda or a ratio alpha/beta = lambda, such that A - lambda*B is !! singular. It is usually represented as the pair (alpha,beta), as !! there is a reasonable interpretation for beta=0, and even for both !! being zero. !! The right generalized eigenvector v(j) corresponding to the !! generalized eigenvalue lambda(j) of (A,B) satisfies !! A * v(j) = lambda(j) * B * v(j). !! The left generalized eigenvector u(j) corresponding to the !! generalized eigenvalues lambda(j) of (A,B) satisfies !! u(j)**H * A = lambda(j) * u(j)**H * B !! where u(j)**H is the conjugate-transpose of u(j). work, lwork, rwork, info ) ! -- lapack driver routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_dp, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments character, intent(in) :: jobvl, jobvr integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: lda, ldb, ldvl, ldvr, lwork, n ! Array Arguments real(dp), intent(out) :: rwork(*) complex(dp), intent(inout) :: a(lda,*), b(ldb,*) complex(dp), intent(out) :: alpha(*), beta(*), vl(ldvl,*), vr(ldvr,*), work(*) ! ===================================================================== ! Local Scalars logical(lk) :: ilascl, ilbscl, ilv, ilvl, ilvr, lquery character :: chtemp integer(${ik}$) :: icols, ierr, ihi, ijobvl, ijobvr, ileft, ilo, in, iright, irows, irwrk,& itau, iwrk, jc, jr, lwkopt real(dp) :: anrm, anrmto, bignum, bnrm, bnrmto, eps, smlnum, temp complex(dp) :: x ! Local Arrays logical(lk) :: ldumma(1_${ik}$) ! Intrinsic Functions ! Statement Functions real(dp) :: abs1 ! Statement Function Definitions abs1( x ) = abs( real( x,KIND=dp) ) + abs( aimag( x ) ) ! Executable Statements ! decode the input arguments if( stdlib_lsame( jobvl, 'N' ) ) then ijobvl = 1_${ik}$ ilvl = .false. else if( stdlib_lsame( jobvl, 'V' ) ) then ijobvl = 2_${ik}$ ilvl = .true. else ijobvl = -1_${ik}$ ilvl = .false. end if if( stdlib_lsame( jobvr, 'N' ) ) then ijobvr = 1_${ik}$ ilvr = .false. else if( stdlib_lsame( jobvr, 'V' ) ) then ijobvr = 2_${ik}$ ilvr = .true. else ijobvr = -1_${ik}$ ilvr = .false. end if ilv = ilvl .or. ilvr ! test the input arguments info = 0_${ik}$ lquery = ( lwork==-1_${ik}$ ) if( ijobvl<=0_${ik}$ ) then info = -1_${ik}$ else if( ijobvr<=0_${ik}$ ) then info = -2_${ik}$ else if( n<0_${ik}$ ) then info = -3_${ik}$ else if( lda<max( 1_${ik}$, n ) ) then info = -5_${ik}$ else if( ldb<max( 1_${ik}$, n ) ) then info = -7_${ik}$ else if( ldvl<1_${ik}$ .or. ( ilvl .and. ldvl<n ) ) then info = -11_${ik}$ else if( ldvr<1_${ik}$ .or. ( ilvr .and. ldvr<n ) ) then info = -13_${ik}$ else if( lwork<max( 1_${ik}$, 2_${ik}$*n ) .and. .not.lquery ) then info = -15_${ik}$ end if ! compute workspace if( info==0_${ik}$ ) then call stdlib${ii}$_zgeqrf( n, n, b, ldb, work, work, -1_${ik}$, ierr ) lwkopt = max( 1_${ik}$, n+int( work( 1_${ik}$ ),KIND=${ik}$) ) call stdlib${ii}$_zunmqr( 'L', 'C', n, n, n, b, ldb, work, a, lda, work,-1_${ik}$, ierr ) lwkopt = max( lwkopt, n+int( work( 1_${ik}$ ),KIND=${ik}$) ) if( ilvl ) then call stdlib${ii}$_zungqr( n, n, n, vl, ldvl, work, work, -1_${ik}$, ierr ) lwkopt = max( lwkopt, n+int( work( 1_${ik}$ ),KIND=${ik}$) ) end if if( ilv ) then call stdlib${ii}$_zgghd3( jobvl, jobvr, n, 1_${ik}$, n, a, lda, b, ldb, vl,ldvl, vr, ldvr, & work, -1_${ik}$, ierr ) lwkopt = max( lwkopt, n+int( work( 1_${ik}$ ),KIND=${ik}$) ) call stdlib${ii}$_zlaqz0( 'S', jobvl, jobvr, n, 1_${ik}$, n, a, lda, b, ldb,alpha, beta, vl, & ldvl, vr, ldvr, work, -1_${ik}$,rwork, 0_${ik}$, ierr ) lwkopt = max( lwkopt, n+int( work( 1_${ik}$ ),KIND=${ik}$) ) else call stdlib${ii}$_zgghd3( jobvl, jobvr, n, 1_${ik}$, n, a, lda, b, ldb, vl,ldvl, vr, ldvr, & work, -1_${ik}$, ierr ) lwkopt = max( lwkopt, n+int( work( 1_${ik}$ ),KIND=${ik}$) ) call stdlib${ii}$_zlaqz0( 'E', jobvl, jobvr, n, 1_${ik}$, n, a, lda, b, ldb,alpha, beta, vl, & ldvl, vr, ldvr, work, -1_${ik}$,rwork, 0_${ik}$, ierr ) lwkopt = max( lwkopt, n+int( work( 1_${ik}$ ),KIND=${ik}$) ) end if work( 1_${ik}$ ) = cmplx( lwkopt,KIND=dp) end if if( info/=0_${ik}$ ) then call stdlib${ii}$_xerbla( 'ZGGEV3 ', -info ) return else if( lquery ) then return end if ! quick return if possible if( n==0 )return ! get machine constants eps = stdlib${ii}$_dlamch( 'E' )*stdlib${ii}$_dlamch( 'B' ) smlnum = stdlib${ii}$_dlamch( 'S' ) bignum = one / smlnum call stdlib${ii}$_dlabad( smlnum, bignum ) smlnum = sqrt( smlnum ) / eps bignum = one / smlnum ! scale a if max element outside range [smlnum,bignum] anrm = stdlib${ii}$_zlange( 'M', n, n, a, lda, rwork ) ilascl = .false. if( anrm>zero .and. anrm<smlnum ) then anrmto = smlnum ilascl = .true. else if( anrm>bignum ) then anrmto = bignum ilascl = .true. end if if( ilascl )call stdlib${ii}$_zlascl( 'G', 0_${ik}$, 0_${ik}$, anrm, anrmto, n, n, a, lda, ierr ) ! scale b if max element outside range [smlnum,bignum] bnrm = stdlib${ii}$_zlange( 'M', n, n, b, ldb, rwork ) ilbscl = .false. if( bnrm>zero .and. bnrm<smlnum ) then bnrmto = smlnum ilbscl = .true. else if( bnrm>bignum ) then bnrmto = bignum ilbscl = .true. end if if( ilbscl )call stdlib${ii}$_zlascl( 'G', 0_${ik}$, 0_${ik}$, bnrm, bnrmto, n, n, b, ldb, ierr ) ! permute the matrices a, b to isolate eigenvalues if possible ileft = 1_${ik}$ iright = n + 1_${ik}$ irwrk = iright + n call stdlib${ii}$_zggbal( 'P', n, a, lda, b, ldb, ilo, ihi, rwork( ileft ),rwork( iright ), & rwork( irwrk ), ierr ) ! reduce b to triangular form (qr decomposition of b) irows = ihi + 1_${ik}$ - ilo if( ilv ) then icols = n + 1_${ik}$ - ilo else icols = irows end if itau = 1_${ik}$ iwrk = itau + irows call stdlib${ii}$_zgeqrf( irows, icols, b( ilo, ilo ), ldb, work( itau ),work( iwrk ), lwork+& 1_${ik}$-iwrk, ierr ) ! apply the orthogonal transformation to matrix a call stdlib${ii}$_zunmqr( 'L', 'C', irows, icols, irows, b( ilo, ilo ), ldb,work( itau ), a( & ilo, ilo ), lda, work( iwrk ),lwork+1-iwrk, ierr ) ! initialize vl if( ilvl ) then call stdlib${ii}$_zlaset( 'FULL', n, n, czero, cone, vl, ldvl ) if( irows>1_${ik}$ ) then call stdlib${ii}$_zlacpy( 'L', irows-1, irows-1, b( ilo+1, ilo ), ldb,vl( ilo+1, ilo ),& ldvl ) end if call stdlib${ii}$_zungqr( irows, irows, irows, vl( ilo, ilo ), ldvl,work( itau ), work( & iwrk ), lwork+1-iwrk, ierr ) end if ! initialize vr if( ilvr )call stdlib${ii}$_zlaset( 'FULL', n, n, czero, cone, vr, ldvr ) ! reduce to generalized hessenberg form if( ilv ) then ! eigenvectors requested -- work on whole matrix. call stdlib${ii}$_zgghd3( jobvl, jobvr, n, ilo, ihi, a, lda, b, ldb, vl,ldvl, vr, ldvr, & work( iwrk ), lwork+1-iwrk, ierr ) else call stdlib${ii}$_zgghd3( 'N', 'N', irows, 1_${ik}$, irows, a( ilo, ilo ), lda,b( ilo, ilo ), & ldb, vl, ldvl, vr, ldvr,work( iwrk ), lwork+1-iwrk, ierr ) end if ! perform qz algorithm (compute eigenvalues, and optionally, the ! schur form and schur vectors) iwrk = itau if( ilv ) then chtemp = 'S' else chtemp = 'E' end if call stdlib${ii}$_zlaqz0( chtemp, jobvl, jobvr, n, ilo, ihi, a, lda, b, ldb,alpha, beta, vl, & ldvl, vr, ldvr, work( iwrk ),lwork+1-iwrk, rwork( irwrk ), 0_${ik}$, ierr ) if( ierr/=0_${ik}$ ) then if( ierr>0_${ik}$ .and. ierr<=n ) then info = ierr else if( ierr>n .and. ierr<=2_${ik}$*n ) then info = ierr - n else info = n + 1_${ik}$ end if go to 70 end if ! compute eigenvectors if( ilv ) then if( ilvl ) then if( ilvr ) then chtemp = 'B' else chtemp = 'L' end if else chtemp = 'R' end if call stdlib${ii}$_ztgevc( chtemp, 'B', ldumma, n, a, lda, b, ldb, vl, ldvl,vr, ldvr, n, & in, work( iwrk ), rwork( irwrk ),ierr ) if( ierr/=0_${ik}$ ) then info = n + 2_${ik}$ go to 70 end if ! undo balancing on vl and vr and normalization if( ilvl ) then call stdlib${ii}$_zggbak( 'P', 'L', n, ilo, ihi, rwork( ileft ),rwork( iright ), n, vl,& ldvl, ierr ) loop_30: do jc = 1, n temp = zero do jr = 1, n temp = max( temp, abs1( vl( jr, jc ) ) ) end do if( temp<smlnum )cycle loop_30 temp = one / temp do jr = 1, n vl( jr, jc ) = vl( jr, jc )*temp end do end do loop_30 end if if( ilvr ) then call stdlib${ii}$_zggbak( 'P', 'R', n, ilo, ihi, rwork( ileft ),rwork( iright ), n, vr,& ldvr, ierr ) loop_60: do jc = 1, n temp = zero do jr = 1, n temp = max( temp, abs1( vr( jr, jc ) ) ) end do if( temp<smlnum )cycle loop_60 temp = one / temp do jr = 1, n vr( jr, jc ) = vr( jr, jc )*temp end do end do loop_60 end if end if ! undo scaling if necessary 70 continue if( ilascl )call stdlib${ii}$_zlascl( 'G', 0_${ik}$, 0_${ik}$, anrmto, anrm, n, 1_${ik}$, alpha, n, ierr ) if( ilbscl )call stdlib${ii}$_zlascl( 'G', 0_${ik}$, 0_${ik}$, bnrmto, bnrm, n, 1_${ik}$, beta, n, ierr ) work( 1_${ik}$ ) = cmplx( lwkopt,KIND=dp) return end subroutine stdlib${ii}$_zggev3 #:for ck,ct,ci in CMPLX_KINDS_TYPES #:if not ck in ["sp","dp"] module subroutine stdlib${ii}$_${ci}$ggev3( jobvl, jobvr, n, a, lda, b, ldb, alpha, beta,vl, ldvl, vr, ldvr, & !! ZGGEV3: computes for a pair of N-by-N complex nonsymmetric matrices !! (A,B), the generalized eigenvalues, and optionally, the left and/or !! right generalized eigenvectors. !! A generalized eigenvalue for a pair of matrices (A,B) is a scalar !! lambda or a ratio alpha/beta = lambda, such that A - lambda*B is !! singular. It is usually represented as the pair (alpha,beta), as !! there is a reasonable interpretation for beta=0, and even for both !! being zero. !! The right generalized eigenvector v(j) corresponding to the !! generalized eigenvalue lambda(j) of (A,B) satisfies !! A * v(j) = lambda(j) * B * v(j). !! The left generalized eigenvector u(j) corresponding to the !! generalized eigenvalues lambda(j) of (A,B) satisfies !! u(j)**H * A = lambda(j) * u(j)**H * B !! where u(j)**H is the conjugate-transpose of u(j). work, lwork, rwork, info ) ! -- lapack driver routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_${ck}$, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments character, intent(in) :: jobvl, jobvr integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: lda, ldb, ldvl, ldvr, lwork, n ! Array Arguments real(${ck}$), intent(out) :: rwork(*) complex(${ck}$), intent(inout) :: a(lda,*), b(ldb,*) complex(${ck}$), intent(out) :: alpha(*), beta(*), vl(ldvl,*), vr(ldvr,*), work(*) ! ===================================================================== ! Local Scalars logical(lk) :: ilascl, ilbscl, ilv, ilvl, ilvr, lquery character :: chtemp integer(${ik}$) :: icols, ierr, ihi, ijobvl, ijobvr, ileft, ilo, in, iright, irows, irwrk,& itau, iwrk, jc, jr, lwkopt real(${ck}$) :: anrm, anrmto, bignum, bnrm, bnrmto, eps, smlnum, temp complex(${ck}$) :: x ! Local Arrays logical(lk) :: ldumma(1_${ik}$) ! Intrinsic Functions ! Statement Functions real(${ck}$) :: abs1 ! Statement Function Definitions abs1( x ) = abs( real( x,KIND=${ck}$) ) + abs( aimag( x ) ) ! Executable Statements ! decode the input arguments if( stdlib_lsame( jobvl, 'N' ) ) then ijobvl = 1_${ik}$ ilvl = .false. else if( stdlib_lsame( jobvl, 'V' ) ) then ijobvl = 2_${ik}$ ilvl = .true. else ijobvl = -1_${ik}$ ilvl = .false. end if if( stdlib_lsame( jobvr, 'N' ) ) then ijobvr = 1_${ik}$ ilvr = .false. else if( stdlib_lsame( jobvr, 'V' ) ) then ijobvr = 2_${ik}$ ilvr = .true. else ijobvr = -1_${ik}$ ilvr = .false. end if ilv = ilvl .or. ilvr ! test the input arguments info = 0_${ik}$ lquery = ( lwork==-1_${ik}$ ) if( ijobvl<=0_${ik}$ ) then info = -1_${ik}$ else if( ijobvr<=0_${ik}$ ) then info = -2_${ik}$ else if( n<0_${ik}$ ) then info = -3_${ik}$ else if( lda<max( 1_${ik}$, n ) ) then info = -5_${ik}$ else if( ldb<max( 1_${ik}$, n ) ) then info = -7_${ik}$ else if( ldvl<1_${ik}$ .or. ( ilvl .and. ldvl<n ) ) then info = -11_${ik}$ else if( ldvr<1_${ik}$ .or. ( ilvr .and. ldvr<n ) ) then info = -13_${ik}$ else if( lwork<max( 1_${ik}$, 2_${ik}$*n ) .and. .not.lquery ) then info = -15_${ik}$ end if ! compute workspace if( info==0_${ik}$ ) then call stdlib${ii}$_${ci}$geqrf( n, n, b, ldb, work, work, -1_${ik}$, ierr ) lwkopt = max( 1_${ik}$, n+int( work( 1_${ik}$ ),KIND=${ik}$) ) call stdlib${ii}$_${ci}$unmqr( 'L', 'C', n, n, n, b, ldb, work, a, lda, work,-1_${ik}$, ierr ) lwkopt = max( lwkopt, n+int( work( 1_${ik}$ ),KIND=${ik}$) ) if( ilvl ) then call stdlib${ii}$_${ci}$ungqr( n, n, n, vl, ldvl, work, work, -1_${ik}$, ierr ) lwkopt = max( lwkopt, n+int( work( 1_${ik}$ ),KIND=${ik}$) ) end if if( ilv ) then call stdlib${ii}$_${ci}$gghd3( jobvl, jobvr, n, 1_${ik}$, n, a, lda, b, ldb, vl,ldvl, vr, ldvr, & work, -1_${ik}$, ierr ) lwkopt = max( lwkopt, n+int( work( 1_${ik}$ ),KIND=${ik}$) ) call stdlib${ii}$_${ci}$laqz0( 'S', jobvl, jobvr, n, 1_${ik}$, n, a, lda, b, ldb,alpha, beta, vl, & ldvl, vr, ldvr, work, -1_${ik}$,rwork, 0_${ik}$, ierr ) lwkopt = max( lwkopt, n+int( work( 1_${ik}$ ),KIND=${ik}$) ) else call stdlib${ii}$_${ci}$gghd3( jobvl, jobvr, n, 1_${ik}$, n, a, lda, b, ldb, vl,ldvl, vr, ldvr, & work, -1_${ik}$, ierr ) lwkopt = max( lwkopt, n+int( work( 1_${ik}$ ),KIND=${ik}$) ) call stdlib${ii}$_${ci}$laqz0( 'E', jobvl, jobvr, n, 1_${ik}$, n, a, lda, b, ldb,alpha, beta, vl, & ldvl, vr, ldvr, work, -1_${ik}$,rwork, 0_${ik}$, ierr ) lwkopt = max( lwkopt, n+int( work( 1_${ik}$ ),KIND=${ik}$) ) end if work( 1_${ik}$ ) = cmplx( lwkopt,KIND=${ck}$) end if if( info/=0_${ik}$ ) then call stdlib${ii}$_xerbla( 'ZGGEV3 ', -info ) return else if( lquery ) then return end if ! quick return if possible if( n==0 )return ! get machine constants eps = stdlib${ii}$_${c2ri(ci)}$lamch( 'E' )*stdlib${ii}$_${c2ri(ci)}$lamch( 'B' ) smlnum = stdlib${ii}$_${c2ri(ci)}$lamch( 'S' ) bignum = one / smlnum call stdlib${ii}$_${c2ri(ci)}$labad( smlnum, bignum ) smlnum = sqrt( smlnum ) / eps bignum = one / smlnum ! scale a if max element outside range [smlnum,bignum] anrm = stdlib${ii}$_${ci}$lange( 'M', n, n, a, lda, rwork ) ilascl = .false. if( anrm>zero .and. anrm<smlnum ) then anrmto = smlnum ilascl = .true. else if( anrm>bignum ) then anrmto = bignum ilascl = .true. end if if( ilascl )call stdlib${ii}$_${ci}$lascl( 'G', 0_${ik}$, 0_${ik}$, anrm, anrmto, n, n, a, lda, ierr ) ! scale b if max element outside range [smlnum,bignum] bnrm = stdlib${ii}$_${ci}$lange( 'M', n, n, b, ldb, rwork ) ilbscl = .false. if( bnrm>zero .and. bnrm<smlnum ) then bnrmto = smlnum ilbscl = .true. else if( bnrm>bignum ) then bnrmto = bignum ilbscl = .true. end if if( ilbscl )call stdlib${ii}$_${ci}$lascl( 'G', 0_${ik}$, 0_${ik}$, bnrm, bnrmto, n, n, b, ldb, ierr ) ! permute the matrices a, b to isolate eigenvalues if possible ileft = 1_${ik}$ iright = n + 1_${ik}$ irwrk = iright + n call stdlib${ii}$_${ci}$ggbal( 'P', n, a, lda, b, ldb, ilo, ihi, rwork( ileft ),rwork( iright ), & rwork( irwrk ), ierr ) ! reduce b to triangular form (qr decomposition of b) irows = ihi + 1_${ik}$ - ilo if( ilv ) then icols = n + 1_${ik}$ - ilo else icols = irows end if itau = 1_${ik}$ iwrk = itau + irows call stdlib${ii}$_${ci}$geqrf( irows, icols, b( ilo, ilo ), ldb, work( itau ),work( iwrk ), lwork+& 1_${ik}$-iwrk, ierr ) ! apply the orthogonal transformation to matrix a call stdlib${ii}$_${ci}$unmqr( 'L', 'C', irows, icols, irows, b( ilo, ilo ), ldb,work( itau ), a( & ilo, ilo ), lda, work( iwrk ),lwork+1-iwrk, ierr ) ! initialize vl if( ilvl ) then call stdlib${ii}$_${ci}$laset( 'FULL', n, n, czero, cone, vl, ldvl ) if( irows>1_${ik}$ ) then call stdlib${ii}$_${ci}$lacpy( 'L', irows-1, irows-1, b( ilo+1, ilo ), ldb,vl( ilo+1, ilo ),& ldvl ) end if call stdlib${ii}$_${ci}$ungqr( irows, irows, irows, vl( ilo, ilo ), ldvl,work( itau ), work( & iwrk ), lwork+1-iwrk, ierr ) end if ! initialize vr if( ilvr )call stdlib${ii}$_${ci}$laset( 'FULL', n, n, czero, cone, vr, ldvr ) ! reduce to generalized hessenberg form if( ilv ) then ! eigenvectors requested -- work on whole matrix. call stdlib${ii}$_${ci}$gghd3( jobvl, jobvr, n, ilo, ihi, a, lda, b, ldb, vl,ldvl, vr, ldvr, & work( iwrk ), lwork+1-iwrk, ierr ) else call stdlib${ii}$_${ci}$gghd3( 'N', 'N', irows, 1_${ik}$, irows, a( ilo, ilo ), lda,b( ilo, ilo ), & ldb, vl, ldvl, vr, ldvr,work( iwrk ), lwork+1-iwrk, ierr ) end if ! perform qz algorithm (compute eigenvalues, and optionally, the ! schur form and schur vectors) iwrk = itau if( ilv ) then chtemp = 'S' else chtemp = 'E' end if call stdlib${ii}$_${ci}$laqz0( chtemp, jobvl, jobvr, n, ilo, ihi, a, lda, b, ldb,alpha, beta, vl, & ldvl, vr, ldvr, work( iwrk ),lwork+1-iwrk, rwork( irwrk ), 0_${ik}$, ierr ) if( ierr/=0_${ik}$ ) then if( ierr>0_${ik}$ .and. ierr<=n ) then info = ierr else if( ierr>n .and. ierr<=2_${ik}$*n ) then info = ierr - n else info = n + 1_${ik}$ end if go to 70 end if ! compute eigenvectors if( ilv ) then if( ilvl ) then if( ilvr ) then chtemp = 'B' else chtemp = 'L' end if else chtemp = 'R' end if call stdlib${ii}$_${ci}$tgevc( chtemp, 'B', ldumma, n, a, lda, b, ldb, vl, ldvl,vr, ldvr, n, & in, work( iwrk ), rwork( irwrk ),ierr ) if( ierr/=0_${ik}$ ) then info = n + 2_${ik}$ go to 70 end if ! undo balancing on vl and vr and normalization if( ilvl ) then call stdlib${ii}$_${ci}$ggbak( 'P', 'L', n, ilo, ihi, rwork( ileft ),rwork( iright ), n, vl,& ldvl, ierr ) loop_30: do jc = 1, n temp = zero do jr = 1, n temp = max( temp, abs1( vl( jr, jc ) ) ) end do if( temp<smlnum )cycle loop_30 temp = one / temp do jr = 1, n vl( jr, jc ) = vl( jr, jc )*temp end do end do loop_30 end if if( ilvr ) then call stdlib${ii}$_${ci}$ggbak( 'P', 'R', n, ilo, ihi, rwork( ileft ),rwork( iright ), n, vr,& ldvr, ierr ) loop_60: do jc = 1, n temp = zero do jr = 1, n temp = max( temp, abs1( vr( jr, jc ) ) ) end do if( temp<smlnum )cycle loop_60 temp = one / temp do jr = 1, n vr( jr, jc ) = vr( jr, jc )*temp end do end do loop_60 end if end if ! undo scaling if necessary 70 continue if( ilascl )call stdlib${ii}$_${ci}$lascl( 'G', 0_${ik}$, 0_${ik}$, anrmto, anrm, n, 1_${ik}$, alpha, n, ierr ) if( ilbscl )call stdlib${ii}$_${ci}$lascl( 'G', 0_${ik}$, 0_${ik}$, bnrmto, bnrm, n, 1_${ik}$, beta, n, ierr ) work( 1_${ik}$ ) = cmplx( lwkopt,KIND=${ck}$) return end subroutine stdlib${ii}$_${ci}$ggev3 #:endif #:endfor module subroutine stdlib${ii}$_sggev( jobvl, jobvr, n, a, lda, b, ldb, alphar, alphai,beta, vl, ldvl, vr, & !! SGGEV computes for a pair of N-by-N real nonsymmetric matrices (A,B) !! the generalized eigenvalues, and optionally, the left and/or right !! generalized eigenvectors. !! A generalized eigenvalue for a pair of matrices (A,B) is a scalar !! lambda or a ratio alpha/beta = lambda, such that A - lambda*B is !! singular. It is usually represented as the pair (alpha,beta), as !! there is a reasonable interpretation for beta=0, and even for both !! being zero. !! The right eigenvector v(j) corresponding to the eigenvalue lambda(j) !! of (A,B) satisfies !! A * v(j) = lambda(j) * B * v(j). !! The left eigenvector u(j) corresponding to the eigenvalue lambda(j) !! of (A,B) satisfies !! u(j)**H * A = lambda(j) * u(j)**H * B . !! where u(j)**H is the conjugate-transpose of u(j). ldvr, work, lwork, info ) ! -- lapack driver routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_sp, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments character, intent(in) :: jobvl, jobvr integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: lda, ldb, ldvl, ldvr, lwork, n ! Array Arguments real(sp), intent(inout) :: a(lda,*), b(ldb,*) real(sp), intent(out) :: alphai(*), alphar(*), beta(*), vl(ldvl,*), vr(ldvr,*), work(*) ! ===================================================================== ! Local Scalars logical(lk) :: ilascl, ilbscl, ilv, ilvl, ilvr, lquery character :: chtemp integer(${ik}$) :: icols, ierr, ihi, ijobvl, ijobvr, ileft, ilo, in, iright, irows, itau, & iwrk, jc, jr, maxwrk, minwrk real(sp) :: anrm, anrmto, bignum, bnrm, bnrmto, eps, smlnum, temp ! Local Arrays logical(lk) :: ldumma(1_${ik}$) ! Intrinsic Functions ! Executable Statements ! decode the input arguments if( stdlib_lsame( jobvl, 'N' ) ) then ijobvl = 1_${ik}$ ilvl = .false. else if( stdlib_lsame( jobvl, 'V' ) ) then ijobvl = 2_${ik}$ ilvl = .true. else ijobvl = -1_${ik}$ ilvl = .false. end if if( stdlib_lsame( jobvr, 'N' ) ) then ijobvr = 1_${ik}$ ilvr = .false. else if( stdlib_lsame( jobvr, 'V' ) ) then ijobvr = 2_${ik}$ ilvr = .true. else ijobvr = -1_${ik}$ ilvr = .false. end if ilv = ilvl .or. ilvr ! test the input arguments info = 0_${ik}$ lquery = ( lwork==-1_${ik}$ ) if( ijobvl<=0_${ik}$ ) then info = -1_${ik}$ else if( ijobvr<=0_${ik}$ ) then info = -2_${ik}$ else if( n<0_${ik}$ ) then info = -3_${ik}$ else if( lda<max( 1_${ik}$, n ) ) then info = -5_${ik}$ else if( ldb<max( 1_${ik}$, n ) ) then info = -7_${ik}$ else if( ldvl<1_${ik}$ .or. ( ilvl .and. ldvl<n ) ) then info = -12_${ik}$ else if( ldvr<1_${ik}$ .or. ( ilvr .and. ldvr<n ) ) then info = -14_${ik}$ end if ! compute workspace ! (note: comments in the code beginning "workspace:" describe the ! minimal amount of workspace needed at that point in the code, ! as well as the preferred amount for good performance. ! nb refers to the optimal block size for the immediately ! following subroutine, as returned by stdlib${ii}$_ilaenv. the workspace is ! computed assuming ilo = 1 and ihi = n, the worst case.) if( info==0_${ik}$ ) then minwrk = max( 1_${ik}$, 8_${ik}$*n ) maxwrk = max( 1_${ik}$, n*( 7_${ik}$ +stdlib${ii}$_ilaenv( 1_${ik}$, 'SGEQRF', ' ', n, 1_${ik}$, n, 0_${ik}$ ) ) ) maxwrk = max( maxwrk, n*( 7_${ik}$ +stdlib${ii}$_ilaenv( 1_${ik}$, 'SORMQR', ' ', n, 1_${ik}$, n, 0_${ik}$ ) ) ) if( ilvl ) then maxwrk = max( maxwrk, n*( 7_${ik}$ +stdlib${ii}$_ilaenv( 1_${ik}$, 'SORGQR', ' ', n, 1_${ik}$, n, -1_${ik}$ ) ) ) end if work( 1_${ik}$ ) = maxwrk if( lwork<minwrk .and. .not.lquery )info = -16_${ik}$ end if if( info/=0_${ik}$ ) then call stdlib${ii}$_xerbla( 'SGGEV ', -info ) return else if( lquery ) then return end if ! quick return if possible if( n==0 )return ! get machine constants eps = stdlib${ii}$_slamch( 'P' ) smlnum = stdlib${ii}$_slamch( 'S' ) bignum = one / smlnum call stdlib${ii}$_slabad( smlnum, bignum ) smlnum = sqrt( smlnum ) / eps bignum = one / smlnum ! scale a if max element outside range [smlnum,bignum] anrm = stdlib${ii}$_slange( 'M', n, n, a, lda, work ) ilascl = .false. if( anrm>zero .and. anrm<smlnum ) then anrmto = smlnum ilascl = .true. else if( anrm>bignum ) then anrmto = bignum ilascl = .true. end if if( ilascl )call stdlib${ii}$_slascl( 'G', 0_${ik}$, 0_${ik}$, anrm, anrmto, n, n, a, lda, ierr ) ! scale b if max element outside range [smlnum,bignum] bnrm = stdlib${ii}$_slange( 'M', n, n, b, ldb, work ) ilbscl = .false. if( bnrm>zero .and. bnrm<smlnum ) then bnrmto = smlnum ilbscl = .true. else if( bnrm>bignum ) then bnrmto = bignum ilbscl = .true. end if if( ilbscl )call stdlib${ii}$_slascl( 'G', 0_${ik}$, 0_${ik}$, bnrm, bnrmto, n, n, b, ldb, ierr ) ! permute the matrices a, b to isolate eigenvalues if possible ! (workspace: need 6*n) ileft = 1_${ik}$ iright = n + 1_${ik}$ iwrk = iright + n call stdlib${ii}$_sggbal( 'P', n, a, lda, b, ldb, ilo, ihi, work( ileft ),work( iright ), & work( iwrk ), ierr ) ! reduce b to triangular form (qr decomposition of b) ! (workspace: need n, prefer n*nb) irows = ihi + 1_${ik}$ - ilo if( ilv ) then icols = n + 1_${ik}$ - ilo else icols = irows end if itau = iwrk iwrk = itau + irows call stdlib${ii}$_sgeqrf( irows, icols, b( ilo, ilo ), ldb, work( itau ),work( iwrk ), lwork+& 1_${ik}$-iwrk, ierr ) ! apply the orthogonal transformation to matrix a ! (workspace: need n, prefer n*nb) call stdlib${ii}$_sormqr( 'L', 'T', irows, icols, irows, b( ilo, ilo ), ldb,work( itau ), a( & ilo, ilo ), lda, work( iwrk ),lwork+1-iwrk, ierr ) ! initialize vl ! (workspace: need n, prefer n*nb) if( ilvl ) then call stdlib${ii}$_slaset( 'FULL', n, n, zero, one, vl, ldvl ) if( irows>1_${ik}$ ) then call stdlib${ii}$_slacpy( 'L', irows-1, irows-1, b( ilo+1, ilo ), ldb,vl( ilo+1, ilo ),& ldvl ) end if call stdlib${ii}$_sorgqr( irows, irows, irows, vl( ilo, ilo ), ldvl,work( itau ), work( & iwrk ), lwork+1-iwrk, ierr ) end if ! initialize vr if( ilvr )call stdlib${ii}$_slaset( 'FULL', n, n, zero, one, vr, ldvr ) ! reduce to generalized hessenberg form ! (workspace: none needed) if( ilv ) then ! eigenvectors requested -- work on whole matrix. call stdlib${ii}$_sgghrd( jobvl, jobvr, n, ilo, ihi, a, lda, b, ldb, vl,ldvl, vr, ldvr, & ierr ) else call stdlib${ii}$_sgghrd( 'N', 'N', irows, 1_${ik}$, irows, a( ilo, ilo ), lda,b( ilo, ilo ), & ldb, vl, ldvl, vr, ldvr, ierr ) end if ! perform qz algorithm (compute eigenvalues, and optionally, the ! schur forms and schur vectors) ! (workspace: need n) iwrk = itau if( ilv ) then chtemp = 'S' else chtemp = 'E' end if call stdlib${ii}$_shgeqz( chtemp, jobvl, jobvr, n, ilo, ihi, a, lda, b, ldb,alphar, alphai, & beta, vl, ldvl, vr, ldvr,work( iwrk ), lwork+1-iwrk, ierr ) if( ierr/=0_${ik}$ ) then if( ierr>0_${ik}$ .and. ierr<=n ) then info = ierr else if( ierr>n .and. ierr<=2_${ik}$*n ) then info = ierr - n else info = n + 1_${ik}$ end if go to 110 end if ! compute eigenvectors ! (workspace: need 6*n) if( ilv ) then if( ilvl ) then if( ilvr ) then chtemp = 'B' else chtemp = 'L' end if else chtemp = 'R' end if call stdlib${ii}$_stgevc( chtemp, 'B', ldumma, n, a, lda, b, ldb, vl, ldvl,vr, ldvr, n, & in, work( iwrk ), ierr ) if( ierr/=0_${ik}$ ) then info = n + 2_${ik}$ go to 110 end if ! undo balancing on vl and vr and normalization ! (workspace: none needed) if( ilvl ) then call stdlib${ii}$_sggbak( 'P', 'L', n, ilo, ihi, work( ileft ),work( iright ), n, vl, & ldvl, ierr ) loop_50: do jc = 1, n if( alphai( jc )<zero )cycle loop_50 temp = zero if( alphai( jc )==zero ) then do jr = 1, n temp = max( temp, abs( vl( jr, jc ) ) ) end do else do jr = 1, n temp = max( temp, abs( vl( jr, jc ) )+abs( vl( jr, jc+1 ) ) ) end do end if if( temp<smlnum )cycle loop_50 temp = one / temp if( alphai( jc )==zero ) then do jr = 1, n vl( jr, jc ) = vl( jr, jc )*temp end do else do jr = 1, n vl( jr, jc ) = vl( jr, jc )*temp vl( jr, jc+1 ) = vl( jr, jc+1 )*temp end do end if end do loop_50 end if if( ilvr ) then call stdlib${ii}$_sggbak( 'P', 'R', n, ilo, ihi, work( ileft ),work( iright ), n, vr, & ldvr, ierr ) loop_100: do jc = 1, n if( alphai( jc )<zero )cycle loop_100 temp = zero if( alphai( jc )==zero ) then do jr = 1, n temp = max( temp, abs( vr( jr, jc ) ) ) end do else do jr = 1, n temp = max( temp, abs( vr( jr, jc ) )+abs( vr( jr, jc+1 ) ) ) end do end if if( temp<smlnum )cycle loop_100 temp = one / temp if( alphai( jc )==zero ) then do jr = 1, n vr( jr, jc ) = vr( jr, jc )*temp end do else do jr = 1, n vr( jr, jc ) = vr( jr, jc )*temp vr( jr, jc+1 ) = vr( jr, jc+1 )*temp end do end if end do loop_100 end if ! end of eigenvector calculation end if ! undo scaling if necessary 110 continue if( ilascl ) then call stdlib${ii}$_slascl( 'G', 0_${ik}$, 0_${ik}$, anrmto, anrm, n, 1_${ik}$, alphar, n, ierr ) call stdlib${ii}$_slascl( 'G', 0_${ik}$, 0_${ik}$, anrmto, anrm, n, 1_${ik}$, alphai, n, ierr ) end if if( ilbscl ) then call stdlib${ii}$_slascl( 'G', 0_${ik}$, 0_${ik}$, bnrmto, bnrm, n, 1_${ik}$, beta, n, ierr ) end if work( 1_${ik}$ ) = maxwrk return end subroutine stdlib${ii}$_sggev module subroutine stdlib${ii}$_dggev( jobvl, jobvr, n, a, lda, b, ldb, alphar, alphai,beta, vl, ldvl, vr, & !! DGGEV computes for a pair of N-by-N real nonsymmetric matrices (A,B) !! the generalized eigenvalues, and optionally, the left and/or right !! generalized eigenvectors. !! A generalized eigenvalue for a pair of matrices (A,B) is a scalar !! lambda or a ratio alpha/beta = lambda, such that A - lambda*B is !! singular. It is usually represented as the pair (alpha,beta), as !! there is a reasonable interpretation for beta=0, and even for both !! being zero. !! The right eigenvector v(j) corresponding to the eigenvalue lambda(j) !! of (A,B) satisfies !! A * v(j) = lambda(j) * B * v(j). !! The left eigenvector u(j) corresponding to the eigenvalue lambda(j) !! of (A,B) satisfies !! u(j)**H * A = lambda(j) * u(j)**H * B . !! where u(j)**H is the conjugate-transpose of u(j). ldvr, work, lwork, info ) ! -- lapack driver routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_dp, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments character, intent(in) :: jobvl, jobvr integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: lda, ldb, ldvl, ldvr, lwork, n ! Array Arguments real(dp), intent(inout) :: a(lda,*), b(ldb,*) real(dp), intent(out) :: alphai(*), alphar(*), beta(*), vl(ldvl,*), vr(ldvr,*), work(*) ! ===================================================================== ! Local Scalars logical(lk) :: ilascl, ilbscl, ilv, ilvl, ilvr, lquery character :: chtemp integer(${ik}$) :: icols, ierr, ihi, ijobvl, ijobvr, ileft, ilo, in, iright, irows, itau, & iwrk, jc, jr, maxwrk, minwrk real(dp) :: anrm, anrmto, bignum, bnrm, bnrmto, eps, smlnum, temp ! Local Arrays logical(lk) :: ldumma(1_${ik}$) ! Intrinsic Functions ! Executable Statements ! decode the input arguments if( stdlib_lsame( jobvl, 'N' ) ) then ijobvl = 1_${ik}$ ilvl = .false. else if( stdlib_lsame( jobvl, 'V' ) ) then ijobvl = 2_${ik}$ ilvl = .true. else ijobvl = -1_${ik}$ ilvl = .false. end if if( stdlib_lsame( jobvr, 'N' ) ) then ijobvr = 1_${ik}$ ilvr = .false. else if( stdlib_lsame( jobvr, 'V' ) ) then ijobvr = 2_${ik}$ ilvr = .true. else ijobvr = -1_${ik}$ ilvr = .false. end if ilv = ilvl .or. ilvr ! test the input arguments info = 0_${ik}$ lquery = ( lwork==-1_${ik}$ ) if( ijobvl<=0_${ik}$ ) then info = -1_${ik}$ else if( ijobvr<=0_${ik}$ ) then info = -2_${ik}$ else if( n<0_${ik}$ ) then info = -3_${ik}$ else if( lda<max( 1_${ik}$, n ) ) then info = -5_${ik}$ else if( ldb<max( 1_${ik}$, n ) ) then info = -7_${ik}$ else if( ldvl<1_${ik}$ .or. ( ilvl .and. ldvl<n ) ) then info = -12_${ik}$ else if( ldvr<1_${ik}$ .or. ( ilvr .and. ldvr<n ) ) then info = -14_${ik}$ end if ! compute workspace ! (note: comments in the code beginning "workspace:" describe the ! minimal amount of workspace needed at that point in the code, ! as well as the preferred amount for good performance. ! nb refers to the optimal block size for the immediately ! following subroutine, as returned by stdlib${ii}$_ilaenv. the workspace is ! computed assuming ilo = 1 and ihi = n, the worst case.) if( info==0_${ik}$ ) then minwrk = max( 1_${ik}$, 8_${ik}$*n ) maxwrk = max( 1_${ik}$, n*( 7_${ik}$ +stdlib${ii}$_ilaenv( 1_${ik}$, 'DGEQRF', ' ', n, 1_${ik}$, n, 0_${ik}$ ) ) ) maxwrk = max( maxwrk, n*( 7_${ik}$ +stdlib${ii}$_ilaenv( 1_${ik}$, 'DORMQR', ' ', n, 1_${ik}$, n, 0_${ik}$ ) ) ) if( ilvl ) then maxwrk = max( maxwrk, n*( 7_${ik}$ +stdlib${ii}$_ilaenv( 1_${ik}$, 'DORGQR', ' ', n, 1_${ik}$, n, -1_${ik}$ ) ) ) end if work( 1_${ik}$ ) = maxwrk if( lwork<minwrk .and. .not.lquery )info = -16_${ik}$ end if if( info/=0_${ik}$ ) then call stdlib${ii}$_xerbla( 'DGGEV ', -info ) return else if( lquery ) then return end if ! quick return if possible if( n==0 )return ! get machine constants eps = stdlib${ii}$_dlamch( 'P' ) smlnum = stdlib${ii}$_dlamch( 'S' ) bignum = one / smlnum call stdlib${ii}$_dlabad( smlnum, bignum ) smlnum = sqrt( smlnum ) / eps bignum = one / smlnum ! scale a if max element outside range [smlnum,bignum] anrm = stdlib${ii}$_dlange( 'M', n, n, a, lda, work ) ilascl = .false. if( anrm>zero .and. anrm<smlnum ) then anrmto = smlnum ilascl = .true. else if( anrm>bignum ) then anrmto = bignum ilascl = .true. end if if( ilascl )call stdlib${ii}$_dlascl( 'G', 0_${ik}$, 0_${ik}$, anrm, anrmto, n, n, a, lda, ierr ) ! scale b if max element outside range [smlnum,bignum] bnrm = stdlib${ii}$_dlange( 'M', n, n, b, ldb, work ) ilbscl = .false. if( bnrm>zero .and. bnrm<smlnum ) then bnrmto = smlnum ilbscl = .true. else if( bnrm>bignum ) then bnrmto = bignum ilbscl = .true. end if if( ilbscl )call stdlib${ii}$_dlascl( 'G', 0_${ik}$, 0_${ik}$, bnrm, bnrmto, n, n, b, ldb, ierr ) ! permute the matrices a, b to isolate eigenvalues if possible ! (workspace: need 6*n) ileft = 1_${ik}$ iright = n + 1_${ik}$ iwrk = iright + n call stdlib${ii}$_dggbal( 'P', n, a, lda, b, ldb, ilo, ihi, work( ileft ),work( iright ), & work( iwrk ), ierr ) ! reduce b to triangular form (qr decomposition of b) ! (workspace: need n, prefer n*nb) irows = ihi + 1_${ik}$ - ilo if( ilv ) then icols = n + 1_${ik}$ - ilo else icols = irows end if itau = iwrk iwrk = itau + irows call stdlib${ii}$_dgeqrf( irows, icols, b( ilo, ilo ), ldb, work( itau ),work( iwrk ), lwork+& 1_${ik}$-iwrk, ierr ) ! apply the orthogonal transformation to matrix a ! (workspace: need n, prefer n*nb) call stdlib${ii}$_dormqr( 'L', 'T', irows, icols, irows, b( ilo, ilo ), ldb,work( itau ), a( & ilo, ilo ), lda, work( iwrk ),lwork+1-iwrk, ierr ) ! initialize vl ! (workspace: need n, prefer n*nb) if( ilvl ) then call stdlib${ii}$_dlaset( 'FULL', n, n, zero, one, vl, ldvl ) if( irows>1_${ik}$ ) then call stdlib${ii}$_dlacpy( 'L', irows-1, irows-1, b( ilo+1, ilo ), ldb,vl( ilo+1, ilo ),& ldvl ) end if call stdlib${ii}$_dorgqr( irows, irows, irows, vl( ilo, ilo ), ldvl,work( itau ), work( & iwrk ), lwork+1-iwrk, ierr ) end if ! initialize vr if( ilvr )call stdlib${ii}$_dlaset( 'FULL', n, n, zero, one, vr, ldvr ) ! reduce to generalized hessenberg form ! (workspace: none needed) if( ilv ) then ! eigenvectors requested -- work on whole matrix. call stdlib${ii}$_dgghrd( jobvl, jobvr, n, ilo, ihi, a, lda, b, ldb, vl,ldvl, vr, ldvr, & ierr ) else call stdlib${ii}$_dgghrd( 'N', 'N', irows, 1_${ik}$, irows, a( ilo, ilo ), lda,b( ilo, ilo ), & ldb, vl, ldvl, vr, ldvr, ierr ) end if ! perform qz algorithm (compute eigenvalues, and optionally, the ! schur forms and schur vectors) ! (workspace: need n) iwrk = itau if( ilv ) then chtemp = 'S' else chtemp = 'E' end if call stdlib${ii}$_dhgeqz( chtemp, jobvl, jobvr, n, ilo, ihi, a, lda, b, ldb,alphar, alphai, & beta, vl, ldvl, vr, ldvr,work( iwrk ), lwork+1-iwrk, ierr ) if( ierr/=0_${ik}$ ) then if( ierr>0_${ik}$ .and. ierr<=n ) then info = ierr else if( ierr>n .and. ierr<=2_${ik}$*n ) then info = ierr - n else info = n + 1_${ik}$ end if go to 110 end if ! compute eigenvectors ! (workspace: need 6*n) if( ilv ) then if( ilvl ) then if( ilvr ) then chtemp = 'B' else chtemp = 'L' end if else chtemp = 'R' end if call stdlib${ii}$_dtgevc( chtemp, 'B', ldumma, n, a, lda, b, ldb, vl, ldvl,vr, ldvr, n, & in, work( iwrk ), ierr ) if( ierr/=0_${ik}$ ) then info = n + 2_${ik}$ go to 110 end if ! undo balancing on vl and vr and normalization ! (workspace: none needed) if( ilvl ) then call stdlib${ii}$_dggbak( 'P', 'L', n, ilo, ihi, work( ileft ),work( iright ), n, vl, & ldvl, ierr ) loop_50: do jc = 1, n if( alphai( jc )<zero )cycle loop_50 temp = zero if( alphai( jc )==zero ) then do jr = 1, n temp = max( temp, abs( vl( jr, jc ) ) ) end do else do jr = 1, n temp = max( temp, abs( vl( jr, jc ) )+abs( vl( jr, jc+1 ) ) ) end do end if if( temp<smlnum )cycle loop_50 temp = one / temp if( alphai( jc )==zero ) then do jr = 1, n vl( jr, jc ) = vl( jr, jc )*temp end do else do jr = 1, n vl( jr, jc ) = vl( jr, jc )*temp vl( jr, jc+1 ) = vl( jr, jc+1 )*temp end do end if end do loop_50 end if if( ilvr ) then call stdlib${ii}$_dggbak( 'P', 'R', n, ilo, ihi, work( ileft ),work( iright ), n, vr, & ldvr, ierr ) loop_100: do jc = 1, n if( alphai( jc )<zero )cycle loop_100 temp = zero if( alphai( jc )==zero ) then do jr = 1, n temp = max( temp, abs( vr( jr, jc ) ) ) end do else do jr = 1, n temp = max( temp, abs( vr( jr, jc ) )+abs( vr( jr, jc+1 ) ) ) end do end if if( temp<smlnum )cycle loop_100 temp = one / temp if( alphai( jc )==zero ) then do jr = 1, n vr( jr, jc ) = vr( jr, jc )*temp end do else do jr = 1, n vr( jr, jc ) = vr( jr, jc )*temp vr( jr, jc+1 ) = vr( jr, jc+1 )*temp end do end if end do loop_100 end if ! end of eigenvector calculation end if ! undo scaling if necessary 110 continue if( ilascl ) then call stdlib${ii}$_dlascl( 'G', 0_${ik}$, 0_${ik}$, anrmto, anrm, n, 1_${ik}$, alphar, n, ierr ) call stdlib${ii}$_dlascl( 'G', 0_${ik}$, 0_${ik}$, anrmto, anrm, n, 1_${ik}$, alphai, n, ierr ) end if if( ilbscl ) then call stdlib${ii}$_dlascl( 'G', 0_${ik}$, 0_${ik}$, bnrmto, bnrm, n, 1_${ik}$, beta, n, ierr ) end if work( 1_${ik}$ ) = maxwrk return end subroutine stdlib${ii}$_dggev #:for rk,rt,ri in REAL_KINDS_TYPES #:if not rk in ["sp","dp"] module subroutine stdlib${ii}$_${ri}$ggev( jobvl, jobvr, n, a, lda, b, ldb, alphar, alphai,beta, vl, ldvl, vr, & !! DGGEV: computes for a pair of N-by-N real nonsymmetric matrices (A,B) !! the generalized eigenvalues, and optionally, the left and/or right !! generalized eigenvectors. !! A generalized eigenvalue for a pair of matrices (A,B) is a scalar !! lambda or a ratio alpha/beta = lambda, such that A - lambda*B is !! singular. It is usually represented as the pair (alpha,beta), as !! there is a reasonable interpretation for beta=0, and even for both !! being zero. !! The right eigenvector v(j) corresponding to the eigenvalue lambda(j) !! of (A,B) satisfies !! A * v(j) = lambda(j) * B * v(j). !! The left eigenvector u(j) corresponding to the eigenvalue lambda(j) !! of (A,B) satisfies !! u(j)**H * A = lambda(j) * u(j)**H * B . !! where u(j)**H is the conjugate-transpose of u(j). ldvr, work, lwork, info ) ! -- lapack driver routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_${rk}$, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments character, intent(in) :: jobvl, jobvr integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: lda, ldb, ldvl, ldvr, lwork, n ! Array Arguments real(${rk}$), intent(inout) :: a(lda,*), b(ldb,*) real(${rk}$), intent(out) :: alphai(*), alphar(*), beta(*), vl(ldvl,*), vr(ldvr,*), work(*) ! ===================================================================== ! Local Scalars logical(lk) :: ilascl, ilbscl, ilv, ilvl, ilvr, lquery character :: chtemp integer(${ik}$) :: icols, ierr, ihi, ijobvl, ijobvr, ileft, ilo, in, iright, irows, itau, & iwrk, jc, jr, maxwrk, minwrk real(${rk}$) :: anrm, anrmto, bignum, bnrm, bnrmto, eps, smlnum, temp ! Local Arrays logical(lk) :: ldumma(1_${ik}$) ! Intrinsic Functions ! Executable Statements ! decode the input arguments if( stdlib_lsame( jobvl, 'N' ) ) then ijobvl = 1_${ik}$ ilvl = .false. else if( stdlib_lsame( jobvl, 'V' ) ) then ijobvl = 2_${ik}$ ilvl = .true. else ijobvl = -1_${ik}$ ilvl = .false. end if if( stdlib_lsame( jobvr, 'N' ) ) then ijobvr = 1_${ik}$ ilvr = .false. else if( stdlib_lsame( jobvr, 'V' ) ) then ijobvr = 2_${ik}$ ilvr = .true. else ijobvr = -1_${ik}$ ilvr = .false. end if ilv = ilvl .or. ilvr ! test the input arguments info = 0_${ik}$ lquery = ( lwork==-1_${ik}$ ) if( ijobvl<=0_${ik}$ ) then info = -1_${ik}$ else if( ijobvr<=0_${ik}$ ) then info = -2_${ik}$ else if( n<0_${ik}$ ) then info = -3_${ik}$ else if( lda<max( 1_${ik}$, n ) ) then info = -5_${ik}$ else if( ldb<max( 1_${ik}$, n ) ) then info = -7_${ik}$ else if( ldvl<1_${ik}$ .or. ( ilvl .and. ldvl<n ) ) then info = -12_${ik}$ else if( ldvr<1_${ik}$ .or. ( ilvr .and. ldvr<n ) ) then info = -14_${ik}$ end if ! compute workspace ! (note: comments in the code beginning "workspace:" describe the ! minimal amount of workspace needed at that point in the code, ! as well as the preferred amount for good performance. ! nb refers to the optimal block size for the immediately ! following subroutine, as returned by stdlib${ii}$_ilaenv. the workspace is ! computed assuming ilo = 1 and ihi = n, the worst case.) if( info==0_${ik}$ ) then minwrk = max( 1_${ik}$, 8_${ik}$*n ) maxwrk = max( 1_${ik}$, n*( 7_${ik}$ +stdlib${ii}$_ilaenv( 1_${ik}$, 'DGEQRF', ' ', n, 1_${ik}$, n, 0_${ik}$ ) ) ) maxwrk = max( maxwrk, n*( 7_${ik}$ +stdlib${ii}$_ilaenv( 1_${ik}$, 'DORMQR', ' ', n, 1_${ik}$, n, 0_${ik}$ ) ) ) if( ilvl ) then maxwrk = max( maxwrk, n*( 7_${ik}$ +stdlib${ii}$_ilaenv( 1_${ik}$, 'DORGQR', ' ', n, 1_${ik}$, n, -1_${ik}$ ) ) ) end if work( 1_${ik}$ ) = maxwrk if( lwork<minwrk .and. .not.lquery )info = -16_${ik}$ end if if( info/=0_${ik}$ ) then call stdlib${ii}$_xerbla( 'DGGEV ', -info ) return else if( lquery ) then return end if ! quick return if possible if( n==0 )return ! get machine constants eps = stdlib${ii}$_${ri}$lamch( 'P' ) smlnum = stdlib${ii}$_${ri}$lamch( 'S' ) bignum = one / smlnum call stdlib${ii}$_${ri}$labad( smlnum, bignum ) smlnum = sqrt( smlnum ) / eps bignum = one / smlnum ! scale a if max element outside range [smlnum,bignum] anrm = stdlib${ii}$_${ri}$lange( 'M', n, n, a, lda, work ) ilascl = .false. if( anrm>zero .and. anrm<smlnum ) then anrmto = smlnum ilascl = .true. else if( anrm>bignum ) then anrmto = bignum ilascl = .true. end if if( ilascl )call stdlib${ii}$_${ri}$lascl( 'G', 0_${ik}$, 0_${ik}$, anrm, anrmto, n, n, a, lda, ierr ) ! scale b if max element outside range [smlnum,bignum] bnrm = stdlib${ii}$_${ri}$lange( 'M', n, n, b, ldb, work ) ilbscl = .false. if( bnrm>zero .and. bnrm<smlnum ) then bnrmto = smlnum ilbscl = .true. else if( bnrm>bignum ) then bnrmto = bignum ilbscl = .true. end if if( ilbscl )call stdlib${ii}$_${ri}$lascl( 'G', 0_${ik}$, 0_${ik}$, bnrm, bnrmto, n, n, b, ldb, ierr ) ! permute the matrices a, b to isolate eigenvalues if possible ! (workspace: need 6*n) ileft = 1_${ik}$ iright = n + 1_${ik}$ iwrk = iright + n call stdlib${ii}$_${ri}$ggbal( 'P', n, a, lda, b, ldb, ilo, ihi, work( ileft ),work( iright ), & work( iwrk ), ierr ) ! reduce b to triangular form (qr decomposition of b) ! (workspace: need n, prefer n*nb) irows = ihi + 1_${ik}$ - ilo if( ilv ) then icols = n + 1_${ik}$ - ilo else icols = irows end if itau = iwrk iwrk = itau + irows call stdlib${ii}$_${ri}$geqrf( irows, icols, b( ilo, ilo ), ldb, work( itau ),work( iwrk ), lwork+& 1_${ik}$-iwrk, ierr ) ! apply the orthogonal transformation to matrix a ! (workspace: need n, prefer n*nb) call stdlib${ii}$_${ri}$ormqr( 'L', 'T', irows, icols, irows, b( ilo, ilo ), ldb,work( itau ), a( & ilo, ilo ), lda, work( iwrk ),lwork+1-iwrk, ierr ) ! initialize vl ! (workspace: need n, prefer n*nb) if( ilvl ) then call stdlib${ii}$_${ri}$laset( 'FULL', n, n, zero, one, vl, ldvl ) if( irows>1_${ik}$ ) then call stdlib${ii}$_${ri}$lacpy( 'L', irows-1, irows-1, b( ilo+1, ilo ), ldb,vl( ilo+1, ilo ),& ldvl ) end if call stdlib${ii}$_${ri}$orgqr( irows, irows, irows, vl( ilo, ilo ), ldvl,work( itau ), work( & iwrk ), lwork+1-iwrk, ierr ) end if ! initialize vr if( ilvr )call stdlib${ii}$_${ri}$laset( 'FULL', n, n, zero, one, vr, ldvr ) ! reduce to generalized hessenberg form ! (workspace: none needed) if( ilv ) then ! eigenvectors requested -- work on whole matrix. call stdlib${ii}$_${ri}$gghrd( jobvl, jobvr, n, ilo, ihi, a, lda, b, ldb, vl,ldvl, vr, ldvr, & ierr ) else call stdlib${ii}$_${ri}$gghrd( 'N', 'N', irows, 1_${ik}$, irows, a( ilo, ilo ), lda,b( ilo, ilo ), & ldb, vl, ldvl, vr, ldvr, ierr ) end if ! perform qz algorithm (compute eigenvalues, and optionally, the ! schur forms and schur vectors) ! (workspace: need n) iwrk = itau if( ilv ) then chtemp = 'S' else chtemp = 'E' end if call stdlib${ii}$_${ri}$hgeqz( chtemp, jobvl, jobvr, n, ilo, ihi, a, lda, b, ldb,alphar, alphai, & beta, vl, ldvl, vr, ldvr,work( iwrk ), lwork+1-iwrk, ierr ) if( ierr/=0_${ik}$ ) then if( ierr>0_${ik}$ .and. ierr<=n ) then info = ierr else if( ierr>n .and. ierr<=2_${ik}$*n ) then info = ierr - n else info = n + 1_${ik}$ end if go to 110 end if ! compute eigenvectors ! (workspace: need 6*n) if( ilv ) then if( ilvl ) then if( ilvr ) then chtemp = 'B' else chtemp = 'L' end if else chtemp = 'R' end if call stdlib${ii}$_${ri}$tgevc( chtemp, 'B', ldumma, n, a, lda, b, ldb, vl, ldvl,vr, ldvr, n, & in, work( iwrk ), ierr ) if( ierr/=0_${ik}$ ) then info = n + 2_${ik}$ go to 110 end if ! undo balancing on vl and vr and normalization ! (workspace: none needed) if( ilvl ) then call stdlib${ii}$_${ri}$ggbak( 'P', 'L', n, ilo, ihi, work( ileft ),work( iright ), n, vl, & ldvl, ierr ) loop_50: do jc = 1, n if( alphai( jc )<zero )cycle loop_50 temp = zero if( alphai( jc )==zero ) then do jr = 1, n temp = max( temp, abs( vl( jr, jc ) ) ) end do else do jr = 1, n temp = max( temp, abs( vl( jr, jc ) )+abs( vl( jr, jc+1 ) ) ) end do end if if( temp<smlnum )cycle loop_50 temp = one / temp if( alphai( jc )==zero ) then do jr = 1, n vl( jr, jc ) = vl( jr, jc )*temp end do else do jr = 1, n vl( jr, jc ) = vl( jr, jc )*temp vl( jr, jc+1 ) = vl( jr, jc+1 )*temp end do end if end do loop_50 end if if( ilvr ) then call stdlib${ii}$_${ri}$ggbak( 'P', 'R', n, ilo, ihi, work( ileft ),work( iright ), n, vr, & ldvr, ierr ) loop_100: do jc = 1, n if( alphai( jc )<zero )cycle loop_100 temp = zero if( alphai( jc )==zero ) then do jr = 1, n temp = max( temp, abs( vr( jr, jc ) ) ) end do else do jr = 1, n temp = max( temp, abs( vr( jr, jc ) )+abs( vr( jr, jc+1 ) ) ) end do end if if( temp<smlnum )cycle loop_100 temp = one / temp if( alphai( jc )==zero ) then do jr = 1, n vr( jr, jc ) = vr( jr, jc )*temp end do else do jr = 1, n vr( jr, jc ) = vr( jr, jc )*temp vr( jr, jc+1 ) = vr( jr, jc+1 )*temp end do end if end do loop_100 end if ! end of eigenvector calculation end if ! undo scaling if necessary 110 continue if( ilascl ) then call stdlib${ii}$_${ri}$lascl( 'G', 0_${ik}$, 0_${ik}$, anrmto, anrm, n, 1_${ik}$, alphar, n, ierr ) call stdlib${ii}$_${ri}$lascl( 'G', 0_${ik}$, 0_${ik}$, anrmto, anrm, n, 1_${ik}$, alphai, n, ierr ) end if if( ilbscl ) then call stdlib${ii}$_${ri}$lascl( 'G', 0_${ik}$, 0_${ik}$, bnrmto, bnrm, n, 1_${ik}$, beta, n, ierr ) end if work( 1_${ik}$ ) = maxwrk return end subroutine stdlib${ii}$_${ri}$ggev #:endif #:endfor module subroutine stdlib${ii}$_cggev( jobvl, jobvr, n, a, lda, b, ldb, alpha, beta,vl, ldvl, vr, ldvr, & !! CGGEV computes for a pair of N-by-N complex nonsymmetric matrices !! (A,B), the generalized eigenvalues, and optionally, the left and/or !! right generalized eigenvectors. !! A generalized eigenvalue for a pair of matrices (A,B) is a scalar !! lambda or a ratio alpha/beta = lambda, such that A - lambda*B is !! singular. It is usually represented as the pair (alpha,beta), as !! there is a reasonable interpretation for beta=0, and even for both !! being zero. !! The right generalized eigenvector v(j) corresponding to the !! generalized eigenvalue lambda(j) of (A,B) satisfies !! A * v(j) = lambda(j) * B * v(j). !! The left generalized eigenvector u(j) corresponding to the !! generalized eigenvalues lambda(j) of (A,B) satisfies !! u(j)**H * A = lambda(j) * u(j)**H * B !! where u(j)**H is the conjugate-transpose of u(j). work, lwork, rwork, info ) ! -- lapack driver routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_sp, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments character, intent(in) :: jobvl, jobvr integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: lda, ldb, ldvl, ldvr, lwork, n ! Array Arguments real(sp), intent(out) :: rwork(*) complex(sp), intent(inout) :: a(lda,*), b(ldb,*) complex(sp), intent(out) :: alpha(*), beta(*), vl(ldvl,*), vr(ldvr,*), work(*) ! ===================================================================== ! Local Scalars logical(lk) :: ilascl, ilbscl, ilv, ilvl, ilvr, lquery character :: chtemp integer(${ik}$) :: icols, ierr, ihi, ijobvl, ijobvr, ileft, ilo, in, iright, irows, irwrk,& itau, iwrk, jc, jr, lwkmin, lwkopt real(sp) :: anrm, anrmto, bignum, bnrm, bnrmto, eps, smlnum, temp complex(sp) :: x ! Local Arrays logical(lk) :: ldumma(1_${ik}$) ! Intrinsic Functions ! Statement Functions real(sp) :: abs1 ! Statement Function Definitions abs1( x ) = abs( real( x,KIND=sp) ) + abs( aimag( x ) ) ! Executable Statements ! decode the input arguments if( stdlib_lsame( jobvl, 'N' ) ) then ijobvl = 1_${ik}$ ilvl = .false. else if( stdlib_lsame( jobvl, 'V' ) ) then ijobvl = 2_${ik}$ ilvl = .true. else ijobvl = -1_${ik}$ ilvl = .false. end if if( stdlib_lsame( jobvr, 'N' ) ) then ijobvr = 1_${ik}$ ilvr = .false. else if( stdlib_lsame( jobvr, 'V' ) ) then ijobvr = 2_${ik}$ ilvr = .true. else ijobvr = -1_${ik}$ ilvr = .false. end if ilv = ilvl .or. ilvr ! test the input arguments info = 0_${ik}$ lquery = ( lwork==-1_${ik}$ ) if( ijobvl<=0_${ik}$ ) then info = -1_${ik}$ else if( ijobvr<=0_${ik}$ ) then info = -2_${ik}$ else if( n<0_${ik}$ ) then info = -3_${ik}$ else if( lda<max( 1_${ik}$, n ) ) then info = -5_${ik}$ else if( ldb<max( 1_${ik}$, n ) ) then info = -7_${ik}$ else if( ldvl<1_${ik}$ .or. ( ilvl .and. ldvl<n ) ) then info = -11_${ik}$ else if( ldvr<1_${ik}$ .or. ( ilvr .and. ldvr<n ) ) then info = -13_${ik}$ end if ! compute workspace ! (note: comments in the code beginning "workspace:" describe the ! minimal amount of workspace needed at that point in the code, ! as well as the preferred amount for good performance. ! nb refers to the optimal block size for the immediately ! following subroutine, as returned by stdlib${ii}$_ilaenv. the workspace is ! computed assuming ilo = 1 and ihi = n, the worst case.) if( info==0_${ik}$ ) then lwkmin = max( 1_${ik}$, 2_${ik}$*n ) lwkopt = max( 1_${ik}$, n + n*stdlib${ii}$_ilaenv( 1_${ik}$, 'CGEQRF', ' ', n, 1_${ik}$, n, 0_${ik}$ ) ) lwkopt = max( lwkopt, n +n*stdlib${ii}$_ilaenv( 1_${ik}$, 'CUNMQR', ' ', n, 1_${ik}$, n, 0_${ik}$ ) ) if( ilvl ) then lwkopt = max( lwkopt, n +n*stdlib${ii}$_ilaenv( 1_${ik}$, 'CUNGQR', ' ', n, 1_${ik}$, n, -1_${ik}$ ) ) end if work( 1_${ik}$ ) = lwkopt if( lwork<lwkmin .and. .not.lquery )info = -15_${ik}$ end if if( info/=0_${ik}$ ) then call stdlib${ii}$_xerbla( 'CGGEV ', -info ) return else if( lquery ) then return end if ! quick return if possible if( n==0 )return ! get machine constants eps = stdlib${ii}$_slamch( 'E' )*stdlib${ii}$_slamch( 'B' ) smlnum = stdlib${ii}$_slamch( 'S' ) bignum = one / smlnum call stdlib${ii}$_slabad( smlnum, bignum ) smlnum = sqrt( smlnum ) / eps bignum = one / smlnum ! scale a if max element outside range [smlnum,bignum] anrm = stdlib${ii}$_clange( 'M', n, n, a, lda, rwork ) ilascl = .false. if( anrm>zero .and. anrm<smlnum ) then anrmto = smlnum ilascl = .true. else if( anrm>bignum ) then anrmto = bignum ilascl = .true. end if if( ilascl )call stdlib${ii}$_clascl( 'G', 0_${ik}$, 0_${ik}$, anrm, anrmto, n, n, a, lda, ierr ) ! scale b if max element outside range [smlnum,bignum] bnrm = stdlib${ii}$_clange( 'M', n, n, b, ldb, rwork ) ilbscl = .false. if( bnrm>zero .and. bnrm<smlnum ) then bnrmto = smlnum ilbscl = .true. else if( bnrm>bignum ) then bnrmto = bignum ilbscl = .true. end if if( ilbscl )call stdlib${ii}$_clascl( 'G', 0_${ik}$, 0_${ik}$, bnrm, bnrmto, n, n, b, ldb, ierr ) ! permute the matrices a, b to isolate eigenvalues if possible ! (real workspace: need 6*n) ileft = 1_${ik}$ iright = n + 1_${ik}$ irwrk = iright + n call stdlib${ii}$_cggbal( 'P', n, a, lda, b, ldb, ilo, ihi, rwork( ileft ),rwork( iright ), & rwork( irwrk ), ierr ) ! reduce b to triangular form (qr decomposition of b) ! (complex workspace: need n, prefer n*nb) irows = ihi + 1_${ik}$ - ilo if( ilv ) then icols = n + 1_${ik}$ - ilo else icols = irows end if itau = 1_${ik}$ iwrk = itau + irows call stdlib${ii}$_cgeqrf( irows, icols, b( ilo, ilo ), ldb, work( itau ),work( iwrk ), lwork+& 1_${ik}$-iwrk, ierr ) ! apply the orthogonal transformation to matrix a ! (complex workspace: need n, prefer n*nb) call stdlib${ii}$_cunmqr( 'L', 'C', irows, icols, irows, b( ilo, ilo ), ldb,work( itau ), a( & ilo, ilo ), lda, work( iwrk ),lwork+1-iwrk, ierr ) ! initialize vl ! (complex workspace: need n, prefer n*nb) if( ilvl ) then call stdlib${ii}$_claset( 'FULL', n, n, czero, cone, vl, ldvl ) if( irows>1_${ik}$ ) then call stdlib${ii}$_clacpy( 'L', irows-1, irows-1, b( ilo+1, ilo ), ldb,vl( ilo+1, ilo ),& ldvl ) end if call stdlib${ii}$_cungqr( irows, irows, irows, vl( ilo, ilo ), ldvl,work( itau ), work( & iwrk ), lwork+1-iwrk, ierr ) end if ! initialize vr if( ilvr )call stdlib${ii}$_claset( 'FULL', n, n, czero, cone, vr, ldvr ) ! reduce to generalized hessenberg form if( ilv ) then ! eigenvectors requested -- work on whole matrix. call stdlib${ii}$_cgghrd( jobvl, jobvr, n, ilo, ihi, a, lda, b, ldb, vl,ldvl, vr, ldvr, & ierr ) else call stdlib${ii}$_cgghrd( 'N', 'N', irows, 1_${ik}$, irows, a( ilo, ilo ), lda,b( ilo, ilo ), & ldb, vl, ldvl, vr, ldvr, ierr ) end if ! perform qz algorithm (compute eigenvalues, and optionally, the ! schur form and schur vectors) ! (complex workspace: need n) ! (real workspace: need n) iwrk = itau if( ilv ) then chtemp = 'S' else chtemp = 'E' end if call stdlib${ii}$_chgeqz( chtemp, jobvl, jobvr, n, ilo, ihi, a, lda, b, ldb,alpha, beta, vl, & ldvl, vr, ldvr, work( iwrk ),lwork+1-iwrk, rwork( irwrk ), ierr ) if( ierr/=0_${ik}$ ) then if( ierr>0_${ik}$ .and. ierr<=n ) then info = ierr else if( ierr>n .and. ierr<=2_${ik}$*n ) then info = ierr - n else info = n + 1_${ik}$ end if go to 70 end if ! compute eigenvectors ! (real workspace: need 2*n) ! (complex workspace: need 2*n) if( ilv ) then if( ilvl ) then if( ilvr ) then chtemp = 'B' else chtemp = 'L' end if else chtemp = 'R' end if call stdlib${ii}$_ctgevc( chtemp, 'B', ldumma, n, a, lda, b, ldb, vl, ldvl,vr, ldvr, n, & in, work( iwrk ), rwork( irwrk ),ierr ) if( ierr/=0_${ik}$ ) then info = n + 2_${ik}$ go to 70 end if ! undo balancing on vl and vr and normalization ! (workspace: none needed) if( ilvl ) then call stdlib${ii}$_cggbak( 'P', 'L', n, ilo, ihi, rwork( ileft ),rwork( iright ), n, vl,& ldvl, ierr ) loop_30: do jc = 1, n temp = zero do jr = 1, n temp = max( temp, abs1( vl( jr, jc ) ) ) end do if( temp<smlnum )cycle loop_30 temp = one / temp do jr = 1, n vl( jr, jc ) = vl( jr, jc )*temp end do end do loop_30 end if if( ilvr ) then call stdlib${ii}$_cggbak( 'P', 'R', n, ilo, ihi, rwork( ileft ),rwork( iright ), n, vr,& ldvr, ierr ) loop_60: do jc = 1, n temp = zero do jr = 1, n temp = max( temp, abs1( vr( jr, jc ) ) ) end do if( temp<smlnum )cycle loop_60 temp = one / temp do jr = 1, n vr( jr, jc ) = vr( jr, jc )*temp end do end do loop_60 end if end if ! undo scaling if necessary 70 continue if( ilascl )call stdlib${ii}$_clascl( 'G', 0_${ik}$, 0_${ik}$, anrmto, anrm, n, 1_${ik}$, alpha, n, ierr ) if( ilbscl )call stdlib${ii}$_clascl( 'G', 0_${ik}$, 0_${ik}$, bnrmto, bnrm, n, 1_${ik}$, beta, n, ierr ) work( 1_${ik}$ ) = lwkopt return end subroutine stdlib${ii}$_cggev module subroutine stdlib${ii}$_zggev( jobvl, jobvr, n, a, lda, b, ldb, alpha, beta,vl, ldvl, vr, ldvr, & !! ZGGEV computes for a pair of N-by-N complex nonsymmetric matrices !! (A,B), the generalized eigenvalues, and optionally, the left and/or !! right generalized eigenvectors. !! A generalized eigenvalue for a pair of matrices (A,B) is a scalar !! lambda or a ratio alpha/beta = lambda, such that A - lambda*B is !! singular. It is usually represented as the pair (alpha,beta), as !! there is a reasonable interpretation for beta=0, and even for both !! being zero. !! The right generalized eigenvector v(j) corresponding to the !! generalized eigenvalue lambda(j) of (A,B) satisfies !! A * v(j) = lambda(j) * B * v(j). !! The left generalized eigenvector u(j) corresponding to the !! generalized eigenvalues lambda(j) of (A,B) satisfies !! u(j)**H * A = lambda(j) * u(j)**H * B !! where u(j)**H is the conjugate-transpose of u(j). work, lwork, rwork, info ) ! -- lapack driver routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_dp, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments character, intent(in) :: jobvl, jobvr integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: lda, ldb, ldvl, ldvr, lwork, n ! Array Arguments real(dp), intent(out) :: rwork(*) complex(dp), intent(inout) :: a(lda,*), b(ldb,*) complex(dp), intent(out) :: alpha(*), beta(*), vl(ldvl,*), vr(ldvr,*), work(*) ! ===================================================================== ! Local Scalars logical(lk) :: ilascl, ilbscl, ilv, ilvl, ilvr, lquery character :: chtemp integer(${ik}$) :: icols, ierr, ihi, ijobvl, ijobvr, ileft, ilo, in, iright, irows, irwrk,& itau, iwrk, jc, jr, lwkmin, lwkopt real(dp) :: anrm, anrmto, bignum, bnrm, bnrmto, eps, smlnum, temp complex(dp) :: x ! Local Arrays logical(lk) :: ldumma(1_${ik}$) ! Intrinsic Functions ! Statement Functions real(dp) :: abs1 ! Statement Function Definitions abs1( x ) = abs( real( x,KIND=dp) ) + abs( aimag( x ) ) ! Executable Statements ! decode the input arguments if( stdlib_lsame( jobvl, 'N' ) ) then ijobvl = 1_${ik}$ ilvl = .false. else if( stdlib_lsame( jobvl, 'V' ) ) then ijobvl = 2_${ik}$ ilvl = .true. else ijobvl = -1_${ik}$ ilvl = .false. end if if( stdlib_lsame( jobvr, 'N' ) ) then ijobvr = 1_${ik}$ ilvr = .false. else if( stdlib_lsame( jobvr, 'V' ) ) then ijobvr = 2_${ik}$ ilvr = .true. else ijobvr = -1_${ik}$ ilvr = .false. end if ilv = ilvl .or. ilvr ! test the input arguments info = 0_${ik}$ lquery = ( lwork==-1_${ik}$ ) if( ijobvl<=0_${ik}$ ) then info = -1_${ik}$ else if( ijobvr<=0_${ik}$ ) then info = -2_${ik}$ else if( n<0_${ik}$ ) then info = -3_${ik}$ else if( lda<max( 1_${ik}$, n ) ) then info = -5_${ik}$ else if( ldb<max( 1_${ik}$, n ) ) then info = -7_${ik}$ else if( ldvl<1_${ik}$ .or. ( ilvl .and. ldvl<n ) ) then info = -11_${ik}$ else if( ldvr<1_${ik}$ .or. ( ilvr .and. ldvr<n ) ) then info = -13_${ik}$ end if ! compute workspace ! (note: comments in the code beginning "workspace:" describe the ! minimal amount of workspace needed at that point in the code, ! as well as the preferred amount for good performance. ! nb refers to the optimal block size for the immediately ! following subroutine, as returned by stdlib${ii}$_ilaenv. the workspace is ! computed assuming ilo = 1 and ihi = n, the worst case.) if( info==0_${ik}$ ) then lwkmin = max( 1_${ik}$, 2_${ik}$*n ) lwkopt = max( 1_${ik}$, n + n*stdlib${ii}$_ilaenv( 1_${ik}$, 'ZGEQRF', ' ', n, 1_${ik}$, n, 0_${ik}$ ) ) lwkopt = max( lwkopt, n +n*stdlib${ii}$_ilaenv( 1_${ik}$, 'ZUNMQR', ' ', n, 1_${ik}$, n, 0_${ik}$ ) ) if( ilvl ) then lwkopt = max( lwkopt, n +n*stdlib${ii}$_ilaenv( 1_${ik}$, 'ZUNGQR', ' ', n, 1_${ik}$, n, -1_${ik}$ ) ) end if work( 1_${ik}$ ) = lwkopt if( lwork<lwkmin .and. .not.lquery )info = -15_${ik}$ end if if( info/=0_${ik}$ ) then call stdlib${ii}$_xerbla( 'ZGGEV ', -info ) return else if( lquery ) then return end if ! quick return if possible if( n==0 )return ! get machine constants eps = stdlib${ii}$_dlamch( 'E' )*stdlib${ii}$_dlamch( 'B' ) smlnum = stdlib${ii}$_dlamch( 'S' ) bignum = one / smlnum call stdlib${ii}$_dlabad( smlnum, bignum ) smlnum = sqrt( smlnum ) / eps bignum = one / smlnum ! scale a if max element outside range [smlnum,bignum] anrm = stdlib${ii}$_zlange( 'M', n, n, a, lda, rwork ) ilascl = .false. if( anrm>zero .and. anrm<smlnum ) then anrmto = smlnum ilascl = .true. else if( anrm>bignum ) then anrmto = bignum ilascl = .true. end if if( ilascl )call stdlib${ii}$_zlascl( 'G', 0_${ik}$, 0_${ik}$, anrm, anrmto, n, n, a, lda, ierr ) ! scale b if max element outside range [smlnum,bignum] bnrm = stdlib${ii}$_zlange( 'M', n, n, b, ldb, rwork ) ilbscl = .false. if( bnrm>zero .and. bnrm<smlnum ) then bnrmto = smlnum ilbscl = .true. else if( bnrm>bignum ) then bnrmto = bignum ilbscl = .true. end if if( ilbscl )call stdlib${ii}$_zlascl( 'G', 0_${ik}$, 0_${ik}$, bnrm, bnrmto, n, n, b, ldb, ierr ) ! permute the matrices a, b to isolate eigenvalues if possible ! (real workspace: need 6*n) ileft = 1_${ik}$ iright = n + 1_${ik}$ irwrk = iright + n call stdlib${ii}$_zggbal( 'P', n, a, lda, b, ldb, ilo, ihi, rwork( ileft ),rwork( iright ), & rwork( irwrk ), ierr ) ! reduce b to triangular form (qr decomposition of b) ! (complex workspace: need n, prefer n*nb) irows = ihi + 1_${ik}$ - ilo if( ilv ) then icols = n + 1_${ik}$ - ilo else icols = irows end if itau = 1_${ik}$ iwrk = itau + irows call stdlib${ii}$_zgeqrf( irows, icols, b( ilo, ilo ), ldb, work( itau ),work( iwrk ), lwork+& 1_${ik}$-iwrk, ierr ) ! apply the orthogonal transformation to matrix a ! (complex workspace: need n, prefer n*nb) call stdlib${ii}$_zunmqr( 'L', 'C', irows, icols, irows, b( ilo, ilo ), ldb,work( itau ), a( & ilo, ilo ), lda, work( iwrk ),lwork+1-iwrk, ierr ) ! initialize vl ! (complex workspace: need n, prefer n*nb) if( ilvl ) then call stdlib${ii}$_zlaset( 'FULL', n, n, czero, cone, vl, ldvl ) if( irows>1_${ik}$ ) then call stdlib${ii}$_zlacpy( 'L', irows-1, irows-1, b( ilo+1, ilo ), ldb,vl( ilo+1, ilo ),& ldvl ) end if call stdlib${ii}$_zungqr( irows, irows, irows, vl( ilo, ilo ), ldvl,work( itau ), work( & iwrk ), lwork+1-iwrk, ierr ) end if ! initialize vr if( ilvr )call stdlib${ii}$_zlaset( 'FULL', n, n, czero, cone, vr, ldvr ) ! reduce to generalized hessenberg form if( ilv ) then ! eigenvectors requested -- work on whole matrix. call stdlib${ii}$_zgghrd( jobvl, jobvr, n, ilo, ihi, a, lda, b, ldb, vl,ldvl, vr, ldvr, & ierr ) else call stdlib${ii}$_zgghrd( 'N', 'N', irows, 1_${ik}$, irows, a( ilo, ilo ), lda,b( ilo, ilo ), & ldb, vl, ldvl, vr, ldvr, ierr ) end if ! perform qz algorithm (compute eigenvalues, and optionally, the ! schur form and schur vectors) ! (complex workspace: need n) ! (real workspace: need n) iwrk = itau if( ilv ) then chtemp = 'S' else chtemp = 'E' end if call stdlib${ii}$_zhgeqz( chtemp, jobvl, jobvr, n, ilo, ihi, a, lda, b, ldb,alpha, beta, vl, & ldvl, vr, ldvr, work( iwrk ),lwork+1-iwrk, rwork( irwrk ), ierr ) if( ierr/=0_${ik}$ ) then if( ierr>0_${ik}$ .and. ierr<=n ) then info = ierr else if( ierr>n .and. ierr<=2_${ik}$*n ) then info = ierr - n else info = n + 1_${ik}$ end if go to 70 end if ! compute eigenvectors ! (real workspace: need 2*n) ! (complex workspace: need 2*n) if( ilv ) then if( ilvl ) then if( ilvr ) then chtemp = 'B' else chtemp = 'L' end if else chtemp = 'R' end if call stdlib${ii}$_ztgevc( chtemp, 'B', ldumma, n, a, lda, b, ldb, vl, ldvl,vr, ldvr, n, & in, work( iwrk ), rwork( irwrk ),ierr ) if( ierr/=0_${ik}$ ) then info = n + 2_${ik}$ go to 70 end if ! undo balancing on vl and vr and normalization ! (workspace: none needed) if( ilvl ) then call stdlib${ii}$_zggbak( 'P', 'L', n, ilo, ihi, rwork( ileft ),rwork( iright ), n, vl,& ldvl, ierr ) loop_30: do jc = 1, n temp = zero do jr = 1, n temp = max( temp, abs1( vl( jr, jc ) ) ) end do if( temp<smlnum )cycle loop_30 temp = one / temp do jr = 1, n vl( jr, jc ) = vl( jr, jc )*temp end do end do loop_30 end if if( ilvr ) then call stdlib${ii}$_zggbak( 'P', 'R', n, ilo, ihi, rwork( ileft ),rwork( iright ), n, vr,& ldvr, ierr ) loop_60: do jc = 1, n temp = zero do jr = 1, n temp = max( temp, abs1( vr( jr, jc ) ) ) end do if( temp<smlnum )cycle loop_60 temp = one / temp do jr = 1, n vr( jr, jc ) = vr( jr, jc )*temp end do end do loop_60 end if end if ! undo scaling if necessary 70 continue if( ilascl )call stdlib${ii}$_zlascl( 'G', 0_${ik}$, 0_${ik}$, anrmto, anrm, n, 1_${ik}$, alpha, n, ierr ) if( ilbscl )call stdlib${ii}$_zlascl( 'G', 0_${ik}$, 0_${ik}$, bnrmto, bnrm, n, 1_${ik}$, beta, n, ierr ) work( 1_${ik}$ ) = lwkopt return end subroutine stdlib${ii}$_zggev #:for ck,ct,ci in CMPLX_KINDS_TYPES #:if not ck in ["sp","dp"] module subroutine stdlib${ii}$_${ci}$ggev( jobvl, jobvr, n, a, lda, b, ldb, alpha, beta,vl, ldvl, vr, ldvr, & !! ZGGEV: computes for a pair of N-by-N complex nonsymmetric matrices !! (A,B), the generalized eigenvalues, and optionally, the left and/or !! right generalized eigenvectors. !! A generalized eigenvalue for a pair of matrices (A,B) is a scalar !! lambda or a ratio alpha/beta = lambda, such that A - lambda*B is !! singular. It is usually represented as the pair (alpha,beta), as !! there is a reasonable interpretation for beta=0, and even for both !! being zero. !! The right generalized eigenvector v(j) corresponding to the !! generalized eigenvalue lambda(j) of (A,B) satisfies !! A * v(j) = lambda(j) * B * v(j). !! The left generalized eigenvector u(j) corresponding to the !! generalized eigenvalues lambda(j) of (A,B) satisfies !! u(j)**H * A = lambda(j) * u(j)**H * B !! where u(j)**H is the conjugate-transpose of u(j). work, lwork, rwork, info ) ! -- lapack driver routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_${ck}$, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments character, intent(in) :: jobvl, jobvr integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: lda, ldb, ldvl, ldvr, lwork, n ! Array Arguments real(${ck}$), intent(out) :: rwork(*) complex(${ck}$), intent(inout) :: a(lda,*), b(ldb,*) complex(${ck}$), intent(out) :: alpha(*), beta(*), vl(ldvl,*), vr(ldvr,*), work(*) ! ===================================================================== ! Local Scalars logical(lk) :: ilascl, ilbscl, ilv, ilvl, ilvr, lquery character :: chtemp integer(${ik}$) :: icols, ierr, ihi, ijobvl, ijobvr, ileft, ilo, in, iright, irows, irwrk,& itau, iwrk, jc, jr, lwkmin, lwkopt real(${ck}$) :: anrm, anrmto, bignum, bnrm, bnrmto, eps, smlnum, temp complex(${ck}$) :: x ! Local Arrays logical(lk) :: ldumma(1_${ik}$) ! Intrinsic Functions ! Statement Functions real(${ck}$) :: abs1 ! Statement Function Definitions abs1( x ) = abs( real( x,KIND=${ck}$) ) + abs( aimag( x ) ) ! Executable Statements ! decode the input arguments if( stdlib_lsame( jobvl, 'N' ) ) then ijobvl = 1_${ik}$ ilvl = .false. else if( stdlib_lsame( jobvl, 'V' ) ) then ijobvl = 2_${ik}$ ilvl = .true. else ijobvl = -1_${ik}$ ilvl = .false. end if if( stdlib_lsame( jobvr, 'N' ) ) then ijobvr = 1_${ik}$ ilvr = .false. else if( stdlib_lsame( jobvr, 'V' ) ) then ijobvr = 2_${ik}$ ilvr = .true. else ijobvr = -1_${ik}$ ilvr = .false. end if ilv = ilvl .or. ilvr ! test the input arguments info = 0_${ik}$ lquery = ( lwork==-1_${ik}$ ) if( ijobvl<=0_${ik}$ ) then info = -1_${ik}$ else if( ijobvr<=0_${ik}$ ) then info = -2_${ik}$ else if( n<0_${ik}$ ) then info = -3_${ik}$ else if( lda<max( 1_${ik}$, n ) ) then info = -5_${ik}$ else if( ldb<max( 1_${ik}$, n ) ) then info = -7_${ik}$ else if( ldvl<1_${ik}$ .or. ( ilvl .and. ldvl<n ) ) then info = -11_${ik}$ else if( ldvr<1_${ik}$ .or. ( ilvr .and. ldvr<n ) ) then info = -13_${ik}$ end if ! compute workspace ! (note: comments in the code beginning "workspace:" describe the ! minimal amount of workspace needed at that point in the code, ! as well as the preferred amount for good performance. ! nb refers to the optimal block size for the immediately ! following subroutine, as returned by stdlib${ii}$_ilaenv. the workspace is ! computed assuming ilo = 1 and ihi = n, the worst case.) if( info==0_${ik}$ ) then lwkmin = max( 1_${ik}$, 2_${ik}$*n ) lwkopt = max( 1_${ik}$, n + n*stdlib${ii}$_ilaenv( 1_${ik}$, 'ZGEQRF', ' ', n, 1_${ik}$, n, 0_${ik}$ ) ) lwkopt = max( lwkopt, n +n*stdlib${ii}$_ilaenv( 1_${ik}$, 'ZUNMQR', ' ', n, 1_${ik}$, n, 0_${ik}$ ) ) if( ilvl ) then lwkopt = max( lwkopt, n +n*stdlib${ii}$_ilaenv( 1_${ik}$, 'ZUNGQR', ' ', n, 1_${ik}$, n, -1_${ik}$ ) ) end if work( 1_${ik}$ ) = lwkopt if( lwork<lwkmin .and. .not.lquery )info = -15_${ik}$ end if if( info/=0_${ik}$ ) then call stdlib${ii}$_xerbla( 'ZGGEV ', -info ) return else if( lquery ) then return end if ! quick return if possible if( n==0 )return ! get machine constants eps = stdlib${ii}$_${c2ri(ci)}$lamch( 'E' )*stdlib${ii}$_${c2ri(ci)}$lamch( 'B' ) smlnum = stdlib${ii}$_${c2ri(ci)}$lamch( 'S' ) bignum = one / smlnum call stdlib${ii}$_${c2ri(ci)}$labad( smlnum, bignum ) smlnum = sqrt( smlnum ) / eps bignum = one / smlnum ! scale a if max element outside range [smlnum,bignum] anrm = stdlib${ii}$_${ci}$lange( 'M', n, n, a, lda, rwork ) ilascl = .false. if( anrm>zero .and. anrm<smlnum ) then anrmto = smlnum ilascl = .true. else if( anrm>bignum ) then anrmto = bignum ilascl = .true. end if if( ilascl )call stdlib${ii}$_${ci}$lascl( 'G', 0_${ik}$, 0_${ik}$, anrm, anrmto, n, n, a, lda, ierr ) ! scale b if max element outside range [smlnum,bignum] bnrm = stdlib${ii}$_${ci}$lange( 'M', n, n, b, ldb, rwork ) ilbscl = .false. if( bnrm>zero .and. bnrm<smlnum ) then bnrmto = smlnum ilbscl = .true. else if( bnrm>bignum ) then bnrmto = bignum ilbscl = .true. end if if( ilbscl )call stdlib${ii}$_${ci}$lascl( 'G', 0_${ik}$, 0_${ik}$, bnrm, bnrmto, n, n, b, ldb, ierr ) ! permute the matrices a, b to isolate eigenvalues if possible ! (real workspace: need 6*n) ileft = 1_${ik}$ iright = n + 1_${ik}$ irwrk = iright + n call stdlib${ii}$_${ci}$ggbal( 'P', n, a, lda, b, ldb, ilo, ihi, rwork( ileft ),rwork( iright ), & rwork( irwrk ), ierr ) ! reduce b to triangular form (qr decomposition of b) ! (complex workspace: need n, prefer n*nb) irows = ihi + 1_${ik}$ - ilo if( ilv ) then icols = n + 1_${ik}$ - ilo else icols = irows end if itau = 1_${ik}$ iwrk = itau + irows call stdlib${ii}$_${ci}$geqrf( irows, icols, b( ilo, ilo ), ldb, work( itau ),work( iwrk ), lwork+& 1_${ik}$-iwrk, ierr ) ! apply the orthogonal transformation to matrix a ! (complex workspace: need n, prefer n*nb) call stdlib${ii}$_${ci}$unmqr( 'L', 'C', irows, icols, irows, b( ilo, ilo ), ldb,work( itau ), a( & ilo, ilo ), lda, work( iwrk ),lwork+1-iwrk, ierr ) ! initialize vl ! (complex workspace: need n, prefer n*nb) if( ilvl ) then call stdlib${ii}$_${ci}$laset( 'FULL', n, n, czero, cone, vl, ldvl ) if( irows>1_${ik}$ ) then call stdlib${ii}$_${ci}$lacpy( 'L', irows-1, irows-1, b( ilo+1, ilo ), ldb,vl( ilo+1, ilo ),& ldvl ) end if call stdlib${ii}$_${ci}$ungqr( irows, irows, irows, vl( ilo, ilo ), ldvl,work( itau ), work( & iwrk ), lwork+1-iwrk, ierr ) end if ! initialize vr if( ilvr )call stdlib${ii}$_${ci}$laset( 'FULL', n, n, czero, cone, vr, ldvr ) ! reduce to generalized hessenberg form if( ilv ) then ! eigenvectors requested -- work on whole matrix. call stdlib${ii}$_${ci}$gghrd( jobvl, jobvr, n, ilo, ihi, a, lda, b, ldb, vl,ldvl, vr, ldvr, & ierr ) else call stdlib${ii}$_${ci}$gghrd( 'N', 'N', irows, 1_${ik}$, irows, a( ilo, ilo ), lda,b( ilo, ilo ), & ldb, vl, ldvl, vr, ldvr, ierr ) end if ! perform qz algorithm (compute eigenvalues, and optionally, the ! schur form and schur vectors) ! (complex workspace: need n) ! (real workspace: need n) iwrk = itau if( ilv ) then chtemp = 'S' else chtemp = 'E' end if call stdlib${ii}$_${ci}$hgeqz( chtemp, jobvl, jobvr, n, ilo, ihi, a, lda, b, ldb,alpha, beta, vl, & ldvl, vr, ldvr, work( iwrk ),lwork+1-iwrk, rwork( irwrk ), ierr ) if( ierr/=0_${ik}$ ) then if( ierr>0_${ik}$ .and. ierr<=n ) then info = ierr else if( ierr>n .and. ierr<=2_${ik}$*n ) then info = ierr - n else info = n + 1_${ik}$ end if go to 70 end if ! compute eigenvectors ! (real workspace: need 2*n) ! (complex workspace: need 2*n) if( ilv ) then if( ilvl ) then if( ilvr ) then chtemp = 'B' else chtemp = 'L' end if else chtemp = 'R' end if call stdlib${ii}$_${ci}$tgevc( chtemp, 'B', ldumma, n, a, lda, b, ldb, vl, ldvl,vr, ldvr, n, & in, work( iwrk ), rwork( irwrk ),ierr ) if( ierr/=0_${ik}$ ) then info = n + 2_${ik}$ go to 70 end if ! undo balancing on vl and vr and normalization ! (workspace: none needed) if( ilvl ) then call stdlib${ii}$_${ci}$ggbak( 'P', 'L', n, ilo, ihi, rwork( ileft ),rwork( iright ), n, vl,& ldvl, ierr ) loop_30: do jc = 1, n temp = zero do jr = 1, n temp = max( temp, abs1( vl( jr, jc ) ) ) end do if( temp<smlnum )cycle loop_30 temp = one / temp do jr = 1, n vl( jr, jc ) = vl( jr, jc )*temp end do end do loop_30 end if if( ilvr ) then call stdlib${ii}$_${ci}$ggbak( 'P', 'R', n, ilo, ihi, rwork( ileft ),rwork( iright ), n, vr,& ldvr, ierr ) loop_60: do jc = 1, n temp = zero do jr = 1, n temp = max( temp, abs1( vr( jr, jc ) ) ) end do if( temp<smlnum )cycle loop_60 temp = one / temp do jr = 1, n vr( jr, jc ) = vr( jr, jc )*temp end do end do loop_60 end if end if ! undo scaling if necessary 70 continue if( ilascl )call stdlib${ii}$_${ci}$lascl( 'G', 0_${ik}$, 0_${ik}$, anrmto, anrm, n, 1_${ik}$, alpha, n, ierr ) if( ilbscl )call stdlib${ii}$_${ci}$lascl( 'G', 0_${ik}$, 0_${ik}$, bnrmto, bnrm, n, 1_${ik}$, beta, n, ierr ) work( 1_${ik}$ ) = lwkopt return end subroutine stdlib${ii}$_${ci}$ggev #:endif #:endfor module subroutine stdlib${ii}$_sggevx( balanc, jobvl, jobvr, sense, n, a, lda, b, ldb,alphar, alphai, & !! SGGEVX computes for a pair of N-by-N real nonsymmetric matrices (A,B) !! the generalized eigenvalues, and optionally, the left and/or right !! generalized eigenvectors. !! Optionally also, it computes a balancing transformation to improve !! the conditioning of the eigenvalues and eigenvectors (ILO, IHI, !! LSCALE, RSCALE, ABNRM, and BBNRM), reciprocal condition numbers for !! the eigenvalues (RCONDE), and reciprocal condition numbers for the !! right eigenvectors (RCONDV). !! A generalized eigenvalue for a pair of matrices (A,B) is a scalar !! lambda or a ratio alpha/beta = lambda, such that A - lambda*B is !! singular. It is usually represented as the pair (alpha,beta), as !! there is a reasonable interpretation for beta=0, and even for both !! being zero. !! The right eigenvector v(j) corresponding to the eigenvalue lambda(j) !! of (A,B) satisfies !! A * v(j) = lambda(j) * B * v(j) . !! The left eigenvector u(j) corresponding to the eigenvalue lambda(j) !! of (A,B) satisfies !! u(j)**H * A = lambda(j) * u(j)**H * B. !! where u(j)**H is the conjugate-transpose of u(j). beta, vl, ldvl, vr, ldvr, ilo,ihi, lscale, rscale, abnrm, bbnrm, rconde,rcondv, work, lwork, & iwork, bwork, info ) ! -- lapack driver routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_sp, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments character, intent(in) :: balanc, jobvl, jobvr, sense integer(${ik}$), intent(out) :: ihi, ilo, info integer(${ik}$), intent(in) :: lda, ldb, ldvl, ldvr, lwork, n real(sp), intent(out) :: abnrm, bbnrm ! Array Arguments logical(lk), intent(out) :: bwork(*) integer(${ik}$), intent(out) :: iwork(*) real(sp), intent(inout) :: a(lda,*), b(ldb,*) real(sp), intent(out) :: alphai(*), alphar(*), beta(*), lscale(*), rconde(*), rcondv(*)& , rscale(*), vl(ldvl,*), vr(ldvr,*), work(*) ! ===================================================================== ! Local Scalars logical(lk) :: ilascl, ilbscl, ilv, ilvl, ilvr, lquery, noscl, pair, wantsb, wantse, & wantsn, wantsv character :: chtemp integer(${ik}$) :: i, icols, ierr, ijobvl, ijobvr, in, irows, itau, iwrk, iwrk1, j, jc, & jr, m, maxwrk, minwrk, mm real(sp) :: anrm, anrmto, bignum, bnrm, bnrmto, eps, smlnum, temp ! Local Arrays logical(lk) :: ldumma(1_${ik}$) ! Intrinsic Functions ! Executable Statements ! decode the input arguments if( stdlib_lsame( jobvl, 'N' ) ) then ijobvl = 1_${ik}$ ilvl = .false. else if( stdlib_lsame( jobvl, 'V' ) ) then ijobvl = 2_${ik}$ ilvl = .true. else ijobvl = -1_${ik}$ ilvl = .false. end if if( stdlib_lsame( jobvr, 'N' ) ) then ijobvr = 1_${ik}$ ilvr = .false. else if( stdlib_lsame( jobvr, 'V' ) ) then ijobvr = 2_${ik}$ ilvr = .true. else ijobvr = -1_${ik}$ ilvr = .false. end if ilv = ilvl .or. ilvr noscl = stdlib_lsame( balanc, 'N' ) .or. stdlib_lsame( balanc, 'P' ) wantsn = stdlib_lsame( sense, 'N' ) wantse = stdlib_lsame( sense, 'E' ) wantsv = stdlib_lsame( sense, 'V' ) wantsb = stdlib_lsame( sense, 'B' ) ! test the input arguments info = 0_${ik}$ lquery = ( lwork==-1_${ik}$ ) if( .not.( noscl .or. stdlib_lsame( balanc, 'S' ) .or.stdlib_lsame( balanc, 'B' ) ) ) & then info = -1_${ik}$ else if( ijobvl<=0_${ik}$ ) then info = -2_${ik}$ else if( ijobvr<=0_${ik}$ ) then info = -3_${ik}$ else if( .not.( wantsn .or. wantse .or. wantsb .or. wantsv ) )then info = -4_${ik}$ else if( n<0_${ik}$ ) then info = -5_${ik}$ else if( lda<max( 1_${ik}$, n ) ) then info = -7_${ik}$ else if( ldb<max( 1_${ik}$, n ) ) then info = -9_${ik}$ else if( ldvl<1_${ik}$ .or. ( ilvl .and. ldvl<n ) ) then info = -14_${ik}$ else if( ldvr<1_${ik}$ .or. ( ilvr .and. ldvr<n ) ) then info = -16_${ik}$ end if ! compute workspace ! (note: comments in the code beginning "workspace:" describe the ! minimal amount of workspace needed at that point in the code, ! as well as the preferred amount for good performance. ! nb refers to the optimal block size for the immediately ! following subroutine, as returned by stdlib${ii}$_ilaenv. the workspace is ! computed assuming ilo = 1 and ihi = n, the worst case.) if( info==0_${ik}$ ) then if( n==0_${ik}$ ) then minwrk = 1_${ik}$ maxwrk = 1_${ik}$ else if( noscl .and. .not.ilv ) then minwrk = 2_${ik}$*n else minwrk = 6_${ik}$*n end if if( wantse ) then minwrk = 10_${ik}$*n else if( wantsv .or. wantsb ) then minwrk = 2_${ik}$*n*( n + 4_${ik}$ ) + 16_${ik}$ end if maxwrk = minwrk maxwrk = max( maxwrk,n + n*stdlib${ii}$_ilaenv( 1_${ik}$, 'SGEQRF', ' ', n, 1_${ik}$, n, 0_${ik}$ ) ) maxwrk = max( maxwrk,n + n*stdlib${ii}$_ilaenv( 1_${ik}$, 'SORMQR', ' ', n, 1_${ik}$, n, 0_${ik}$ ) ) if( ilvl ) then maxwrk = max( maxwrk, n +n*stdlib${ii}$_ilaenv( 1_${ik}$, 'SORGQR', ' ', n, 1_${ik}$, n, 0_${ik}$ ) ) end if end if work( 1_${ik}$ ) = maxwrk if( lwork<minwrk .and. .not.lquery ) then info = -26_${ik}$ end if end if if( info/=0_${ik}$ ) then call stdlib${ii}$_xerbla( 'SGGEVX', -info ) return else if( lquery ) then return end if ! quick return if possible if( n==0 )return ! get machine constants eps = stdlib${ii}$_slamch( 'P' ) smlnum = stdlib${ii}$_slamch( 'S' ) bignum = one / smlnum call stdlib${ii}$_slabad( smlnum, bignum ) smlnum = sqrt( smlnum ) / eps bignum = one / smlnum ! scale a if max element outside range [smlnum,bignum] anrm = stdlib${ii}$_slange( 'M', n, n, a, lda, work ) ilascl = .false. if( anrm>zero .and. anrm<smlnum ) then anrmto = smlnum ilascl = .true. else if( anrm>bignum ) then anrmto = bignum ilascl = .true. end if if( ilascl )call stdlib${ii}$_slascl( 'G', 0_${ik}$, 0_${ik}$, anrm, anrmto, n, n, a, lda, ierr ) ! scale b if max element outside range [smlnum,bignum] bnrm = stdlib${ii}$_slange( 'M', n, n, b, ldb, work ) ilbscl = .false. if( bnrm>zero .and. bnrm<smlnum ) then bnrmto = smlnum ilbscl = .true. else if( bnrm>bignum ) then bnrmto = bignum ilbscl = .true. end if if( ilbscl )call stdlib${ii}$_slascl( 'G', 0_${ik}$, 0_${ik}$, bnrm, bnrmto, n, n, b, ldb, ierr ) ! permute and/or balance the matrix pair (a,b) ! (workspace: need 6*n if balanc = 's' or 'b', 1 otherwise) call stdlib${ii}$_sggbal( balanc, n, a, lda, b, ldb, ilo, ihi, lscale, rscale,work, ierr ) ! compute abnrm and bbnrm abnrm = stdlib${ii}$_slange( '1', n, n, a, lda, work( 1_${ik}$ ) ) if( ilascl ) then work( 1_${ik}$ ) = abnrm call stdlib${ii}$_slascl( 'G', 0_${ik}$, 0_${ik}$, anrmto, anrm, 1_${ik}$, 1_${ik}$, work( 1_${ik}$ ), 1_${ik}$,ierr ) abnrm = work( 1_${ik}$ ) end if bbnrm = stdlib${ii}$_slange( '1', n, n, b, ldb, work( 1_${ik}$ ) ) if( ilbscl ) then work( 1_${ik}$ ) = bbnrm call stdlib${ii}$_slascl( 'G', 0_${ik}$, 0_${ik}$, bnrmto, bnrm, 1_${ik}$, 1_${ik}$, work( 1_${ik}$ ), 1_${ik}$,ierr ) bbnrm = work( 1_${ik}$ ) end if ! reduce b to triangular form (qr decomposition of b) ! (workspace: need n, prefer n*nb ) irows = ihi + 1_${ik}$ - ilo if( ilv .or. .not.wantsn ) then icols = n + 1_${ik}$ - ilo else icols = irows end if itau = 1_${ik}$ iwrk = itau + irows call stdlib${ii}$_sgeqrf( irows, icols, b( ilo, ilo ), ldb, work( itau ),work( iwrk ), lwork+& 1_${ik}$-iwrk, ierr ) ! apply the orthogonal transformation to a ! (workspace: need n, prefer n*nb) call stdlib${ii}$_sormqr( 'L', 'T', irows, icols, irows, b( ilo, ilo ), ldb,work( itau ), a( & ilo, ilo ), lda, work( iwrk ),lwork+1-iwrk, ierr ) ! initialize vl and/or vr ! (workspace: need n, prefer n*nb) if( ilvl ) then call stdlib${ii}$_slaset( 'FULL', n, n, zero, one, vl, ldvl ) if( irows>1_${ik}$ ) then call stdlib${ii}$_slacpy( 'L', irows-1, irows-1, b( ilo+1, ilo ), ldb,vl( ilo+1, ilo ),& ldvl ) end if call stdlib${ii}$_sorgqr( irows, irows, irows, vl( ilo, ilo ), ldvl,work( itau ), work( & iwrk ), lwork+1-iwrk, ierr ) end if if( ilvr )call stdlib${ii}$_slaset( 'FULL', n, n, zero, one, vr, ldvr ) ! reduce to generalized hessenberg form ! (workspace: none needed) if( ilv .or. .not.wantsn ) then ! eigenvectors requested -- work on whole matrix. call stdlib${ii}$_sgghrd( jobvl, jobvr, n, ilo, ihi, a, lda, b, ldb, vl,ldvl, vr, ldvr, & ierr ) else call stdlib${ii}$_sgghrd( 'N', 'N', irows, 1_${ik}$, irows, a( ilo, ilo ), lda,b( ilo, ilo ), & ldb, vl, ldvl, vr, ldvr, ierr ) end if ! perform qz algorithm (compute eigenvalues, and optionally, the ! schur forms and schur vectors) ! (workspace: need n) if( ilv .or. .not.wantsn ) then chtemp = 'S' else chtemp = 'E' end if call stdlib${ii}$_shgeqz( chtemp, jobvl, jobvr, n, ilo, ihi, a, lda, b, ldb,alphar, alphai, & beta, vl, ldvl, vr, ldvr, work,lwork, ierr ) if( ierr/=0_${ik}$ ) then if( ierr>0_${ik}$ .and. ierr<=n ) then info = ierr else if( ierr>n .and. ierr<=2_${ik}$*n ) then info = ierr - n else info = n + 1_${ik}$ end if go to 130 end if ! compute eigenvectors and estimate condition numbers if desired ! (workspace: stdlib${ii}$_stgevc: need 6*n ! stdlib${ii}$_stgsna: need 2*n*(n+2)+16 if sense = 'v' or 'b', ! need n otherwise ) if( ilv .or. .not.wantsn ) then if( ilv ) then if( ilvl ) then if( ilvr ) then chtemp = 'B' else chtemp = 'L' end if else chtemp = 'R' end if call stdlib${ii}$_stgevc( chtemp, 'B', ldumma, n, a, lda, b, ldb, vl,ldvl, vr, ldvr, n,& in, work, ierr ) if( ierr/=0_${ik}$ ) then info = n + 2_${ik}$ go to 130 end if end if if( .not.wantsn ) then ! compute eigenvectors (stdlib${ii}$_stgevc) and estimate condition ! numbers (stdlib${ii}$_stgsna). note that the definition of the condition ! number is not invariant under transformation (u,v) to ! (q*u, z*v), where (u,v) are eigenvectors of the generalized ! schur form (s,t), q and z are orthogonal matrices. in order ! to avoid using extra 2*n*n workspace, we have to recalculate ! eigenvectors and estimate one condition numbers at a time. pair = .false. loop_20: do i = 1, n if( pair ) then pair = .false. cycle loop_20 end if mm = 1_${ik}$ if( i<n ) then if( a( i+1, i )/=zero ) then pair = .true. mm = 2_${ik}$ end if end if do j = 1, n bwork( j ) = .false. end do if( mm==1_${ik}$ ) then bwork( i ) = .true. else if( mm==2_${ik}$ ) then bwork( i ) = .true. bwork( i+1 ) = .true. end if iwrk = mm*n + 1_${ik}$ iwrk1 = iwrk + mm*n ! compute a pair of left and right eigenvectors. ! (compute workspace: need up to 4*n + 6*n) if( wantse .or. wantsb ) then call stdlib${ii}$_stgevc( 'B', 'S', bwork, n, a, lda, b, ldb,work( 1_${ik}$ ), n, work( & iwrk ), n, mm, m,work( iwrk1 ), ierr ) if( ierr/=0_${ik}$ ) then info = n + 2_${ik}$ go to 130 end if end if call stdlib${ii}$_stgsna( sense, 'S', bwork, n, a, lda, b, ldb,work( 1_${ik}$ ), n, work( & iwrk ), n, rconde( i ),rcondv( i ), mm, m, work( iwrk1 ),lwork-iwrk1+1, iwork,& ierr ) end do loop_20 end if end if ! undo balancing on vl and vr and normalization ! (workspace: none needed) if( ilvl ) then call stdlib${ii}$_sggbak( balanc, 'L', n, ilo, ihi, lscale, rscale, n, vl,ldvl, ierr ) loop_70: do jc = 1, n if( alphai( jc )<zero )cycle loop_70 temp = zero if( alphai( jc )==zero ) then do jr = 1, n temp = max( temp, abs( vl( jr, jc ) ) ) end do else do jr = 1, n temp = max( temp, abs( vl( jr, jc ) )+abs( vl( jr, jc+1 ) ) ) end do end if if( temp<smlnum )cycle loop_70 temp = one / temp if( alphai( jc )==zero ) then do jr = 1, n vl( jr, jc ) = vl( jr, jc )*temp end do else do jr = 1, n vl( jr, jc ) = vl( jr, jc )*temp vl( jr, jc+1 ) = vl( jr, jc+1 )*temp end do end if end do loop_70 end if if( ilvr ) then call stdlib${ii}$_sggbak( balanc, 'R', n, ilo, ihi, lscale, rscale, n, vr,ldvr, ierr ) loop_120: do jc = 1, n if( alphai( jc )<zero )cycle loop_120 temp = zero if( alphai( jc )==zero ) then do jr = 1, n temp = max( temp, abs( vr( jr, jc ) ) ) end do else do jr = 1, n temp = max( temp, abs( vr( jr, jc ) )+abs( vr( jr, jc+1 ) ) ) end do end if if( temp<smlnum )cycle loop_120 temp = one / temp if( alphai( jc )==zero ) then do jr = 1, n vr( jr, jc ) = vr( jr, jc )*temp end do else do jr = 1, n vr( jr, jc ) = vr( jr, jc )*temp vr( jr, jc+1 ) = vr( jr, jc+1 )*temp end do end if end do loop_120 end if ! undo scaling if necessary 130 continue if( ilascl ) then call stdlib${ii}$_slascl( 'G', 0_${ik}$, 0_${ik}$, anrmto, anrm, n, 1_${ik}$, alphar, n, ierr ) call stdlib${ii}$_slascl( 'G', 0_${ik}$, 0_${ik}$, anrmto, anrm, n, 1_${ik}$, alphai, n, ierr ) end if if( ilbscl ) then call stdlib${ii}$_slascl( 'G', 0_${ik}$, 0_${ik}$, bnrmto, bnrm, n, 1_${ik}$, beta, n, ierr ) end if work( 1_${ik}$ ) = maxwrk return end subroutine stdlib${ii}$_sggevx module subroutine stdlib${ii}$_dggevx( balanc, jobvl, jobvr, sense, n, a, lda, b, ldb,alphar, alphai, & !! DGGEVX computes for a pair of N-by-N real nonsymmetric matrices (A,B) !! the generalized eigenvalues, and optionally, the left and/or right !! generalized eigenvectors. !! Optionally also, it computes a balancing transformation to improve !! the conditioning of the eigenvalues and eigenvectors (ILO, IHI, !! LSCALE, RSCALE, ABNRM, and BBNRM), reciprocal condition numbers for !! the eigenvalues (RCONDE), and reciprocal condition numbers for the !! right eigenvectors (RCONDV). !! A generalized eigenvalue for a pair of matrices (A,B) is a scalar !! lambda or a ratio alpha/beta = lambda, such that A - lambda*B is !! singular. It is usually represented as the pair (alpha,beta), as !! there is a reasonable interpretation for beta=0, and even for both !! being zero. !! The right eigenvector v(j) corresponding to the eigenvalue lambda(j) !! of (A,B) satisfies !! A * v(j) = lambda(j) * B * v(j) . !! The left eigenvector u(j) corresponding to the eigenvalue lambda(j) !! of (A,B) satisfies !! u(j)**H * A = lambda(j) * u(j)**H * B. !! where u(j)**H is the conjugate-transpose of u(j). beta, vl, ldvl, vr, ldvr, ilo,ihi, lscale, rscale, abnrm, bbnrm, rconde,rcondv, work, lwork, & iwork, bwork, info ) ! -- lapack driver routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_dp, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments character, intent(in) :: balanc, jobvl, jobvr, sense integer(${ik}$), intent(out) :: ihi, ilo, info integer(${ik}$), intent(in) :: lda, ldb, ldvl, ldvr, lwork, n real(dp), intent(out) :: abnrm, bbnrm ! Array Arguments logical(lk), intent(out) :: bwork(*) integer(${ik}$), intent(out) :: iwork(*) real(dp), intent(inout) :: a(lda,*), b(ldb,*) real(dp), intent(out) :: alphai(*), alphar(*), beta(*), lscale(*), rconde(*), rcondv(*)& , rscale(*), vl(ldvl,*), vr(ldvr,*), work(*) ! ===================================================================== ! Local Scalars logical(lk) :: ilascl, ilbscl, ilv, ilvl, ilvr, lquery, noscl, pair, wantsb, wantse, & wantsn, wantsv character :: chtemp integer(${ik}$) :: i, icols, ierr, ijobvl, ijobvr, in, irows, itau, iwrk, iwrk1, j, jc, & jr, m, maxwrk, minwrk, mm real(dp) :: anrm, anrmto, bignum, bnrm, bnrmto, eps, smlnum, temp ! Local Arrays logical(lk) :: ldumma(1_${ik}$) ! Intrinsic Functions ! Executable Statements ! decode the input arguments if( stdlib_lsame( jobvl, 'N' ) ) then ijobvl = 1_${ik}$ ilvl = .false. else if( stdlib_lsame( jobvl, 'V' ) ) then ijobvl = 2_${ik}$ ilvl = .true. else ijobvl = -1_${ik}$ ilvl = .false. end if if( stdlib_lsame( jobvr, 'N' ) ) then ijobvr = 1_${ik}$ ilvr = .false. else if( stdlib_lsame( jobvr, 'V' ) ) then ijobvr = 2_${ik}$ ilvr = .true. else ijobvr = -1_${ik}$ ilvr = .false. end if ilv = ilvl .or. ilvr noscl = stdlib_lsame( balanc, 'N' ) .or. stdlib_lsame( balanc, 'P' ) wantsn = stdlib_lsame( sense, 'N' ) wantse = stdlib_lsame( sense, 'E' ) wantsv = stdlib_lsame( sense, 'V' ) wantsb = stdlib_lsame( sense, 'B' ) ! test the input arguments info = 0_${ik}$ lquery = ( lwork==-1_${ik}$ ) if( .not.( stdlib_lsame( balanc, 'N' ) .or. stdlib_lsame( balanc,'S' ) .or. & stdlib_lsame( balanc, 'P' ) .or. stdlib_lsame( balanc, 'B' ) ) )then info = -1_${ik}$ else if( ijobvl<=0_${ik}$ ) then info = -2_${ik}$ else if( ijobvr<=0_${ik}$ ) then info = -3_${ik}$ else if( .not.( wantsn .or. wantse .or. wantsb .or. wantsv ) )then info = -4_${ik}$ else if( n<0_${ik}$ ) then info = -5_${ik}$ else if( lda<max( 1_${ik}$, n ) ) then info = -7_${ik}$ else if( ldb<max( 1_${ik}$, n ) ) then info = -9_${ik}$ else if( ldvl<1_${ik}$ .or. ( ilvl .and. ldvl<n ) ) then info = -14_${ik}$ else if( ldvr<1_${ik}$ .or. ( ilvr .and. ldvr<n ) ) then info = -16_${ik}$ end if ! compute workspace ! (note: comments in the code beginning "workspace:" describe the ! minimal amount of workspace needed at that point in the code, ! as well as the preferred amount for good performance. ! nb refers to the optimal block size for the immediately ! following subroutine, as returned by stdlib${ii}$_ilaenv. the workspace is ! computed assuming ilo = 1 and ihi = n, the worst case.) if( info==0_${ik}$ ) then if( n==0_${ik}$ ) then minwrk = 1_${ik}$ maxwrk = 1_${ik}$ else if( noscl .and. .not.ilv ) then minwrk = 2_${ik}$*n else minwrk = 6_${ik}$*n end if if( wantse .or. wantsb ) then minwrk = 10_${ik}$*n end if if( wantsv .or. wantsb ) then minwrk = max( minwrk, 2_${ik}$*n*( n + 4_${ik}$ ) + 16_${ik}$ ) end if maxwrk = minwrk maxwrk = max( maxwrk,n + n*stdlib${ii}$_ilaenv( 1_${ik}$, 'DGEQRF', ' ', n, 1_${ik}$, n, 0_${ik}$ ) ) maxwrk = max( maxwrk,n + n*stdlib${ii}$_ilaenv( 1_${ik}$, 'DORMQR', ' ', n, 1_${ik}$, n, 0_${ik}$ ) ) if( ilvl ) then maxwrk = max( maxwrk, n +n*stdlib${ii}$_ilaenv( 1_${ik}$, 'DORGQR', ' ', n, 1_${ik}$, n, 0_${ik}$ ) ) end if end if work( 1_${ik}$ ) = maxwrk if( lwork<minwrk .and. .not.lquery ) then info = -26_${ik}$ end if end if if( info/=0_${ik}$ ) then call stdlib${ii}$_xerbla( 'DGGEVX', -info ) return else if( lquery ) then return end if ! quick return if possible if( n==0 )return ! get machine constants eps = stdlib${ii}$_dlamch( 'P' ) smlnum = stdlib${ii}$_dlamch( 'S' ) bignum = one / smlnum call stdlib${ii}$_dlabad( smlnum, bignum ) smlnum = sqrt( smlnum ) / eps bignum = one / smlnum ! scale a if max element outside range [smlnum,bignum] anrm = stdlib${ii}$_dlange( 'M', n, n, a, lda, work ) ilascl = .false. if( anrm>zero .and. anrm<smlnum ) then anrmto = smlnum ilascl = .true. else if( anrm>bignum ) then anrmto = bignum ilascl = .true. end if if( ilascl )call stdlib${ii}$_dlascl( 'G', 0_${ik}$, 0_${ik}$, anrm, anrmto, n, n, a, lda, ierr ) ! scale b if max element outside range [smlnum,bignum] bnrm = stdlib${ii}$_dlange( 'M', n, n, b, ldb, work ) ilbscl = .false. if( bnrm>zero .and. bnrm<smlnum ) then bnrmto = smlnum ilbscl = .true. else if( bnrm>bignum ) then bnrmto = bignum ilbscl = .true. end if if( ilbscl )call stdlib${ii}$_dlascl( 'G', 0_${ik}$, 0_${ik}$, bnrm, bnrmto, n, n, b, ldb, ierr ) ! permute and/or balance the matrix pair (a,b) ! (workspace: need 6*n if balanc = 's' or 'b', 1 otherwise) call stdlib${ii}$_dggbal( balanc, n, a, lda, b, ldb, ilo, ihi, lscale, rscale,work, ierr ) ! compute abnrm and bbnrm abnrm = stdlib${ii}$_dlange( '1', n, n, a, lda, work( 1_${ik}$ ) ) if( ilascl ) then work( 1_${ik}$ ) = abnrm call stdlib${ii}$_dlascl( 'G', 0_${ik}$, 0_${ik}$, anrmto, anrm, 1_${ik}$, 1_${ik}$, work( 1_${ik}$ ), 1_${ik}$,ierr ) abnrm = work( 1_${ik}$ ) end if bbnrm = stdlib${ii}$_dlange( '1', n, n, b, ldb, work( 1_${ik}$ ) ) if( ilbscl ) then work( 1_${ik}$ ) = bbnrm call stdlib${ii}$_dlascl( 'G', 0_${ik}$, 0_${ik}$, bnrmto, bnrm, 1_${ik}$, 1_${ik}$, work( 1_${ik}$ ), 1_${ik}$,ierr ) bbnrm = work( 1_${ik}$ ) end if ! reduce b to triangular form (qr decomposition of b) ! (workspace: need n, prefer n*nb ) irows = ihi + 1_${ik}$ - ilo if( ilv .or. .not.wantsn ) then icols = n + 1_${ik}$ - ilo else icols = irows end if itau = 1_${ik}$ iwrk = itau + irows call stdlib${ii}$_dgeqrf( irows, icols, b( ilo, ilo ), ldb, work( itau ),work( iwrk ), lwork+& 1_${ik}$-iwrk, ierr ) ! apply the orthogonal transformation to a ! (workspace: need n, prefer n*nb) call stdlib${ii}$_dormqr( 'L', 'T', irows, icols, irows, b( ilo, ilo ), ldb,work( itau ), a( & ilo, ilo ), lda, work( iwrk ),lwork+1-iwrk, ierr ) ! initialize vl and/or vr ! (workspace: need n, prefer n*nb) if( ilvl ) then call stdlib${ii}$_dlaset( 'FULL', n, n, zero, one, vl, ldvl ) if( irows>1_${ik}$ ) then call stdlib${ii}$_dlacpy( 'L', irows-1, irows-1, b( ilo+1, ilo ), ldb,vl( ilo+1, ilo ),& ldvl ) end if call stdlib${ii}$_dorgqr( irows, irows, irows, vl( ilo, ilo ), ldvl,work( itau ), work( & iwrk ), lwork+1-iwrk, ierr ) end if if( ilvr )call stdlib${ii}$_dlaset( 'FULL', n, n, zero, one, vr, ldvr ) ! reduce to generalized hessenberg form ! (workspace: none needed) if( ilv .or. .not.wantsn ) then ! eigenvectors requested -- work on whole matrix. call stdlib${ii}$_dgghrd( jobvl, jobvr, n, ilo, ihi, a, lda, b, ldb, vl,ldvl, vr, ldvr, & ierr ) else call stdlib${ii}$_dgghrd( 'N', 'N', irows, 1_${ik}$, irows, a( ilo, ilo ), lda,b( ilo, ilo ), & ldb, vl, ldvl, vr, ldvr, ierr ) end if ! perform qz algorithm (compute eigenvalues, and optionally, the ! schur forms and schur vectors) ! (workspace: need n) if( ilv .or. .not.wantsn ) then chtemp = 'S' else chtemp = 'E' end if call stdlib${ii}$_dhgeqz( chtemp, jobvl, jobvr, n, ilo, ihi, a, lda, b, ldb,alphar, alphai, & beta, vl, ldvl, vr, ldvr, work,lwork, ierr ) if( ierr/=0_${ik}$ ) then if( ierr>0_${ik}$ .and. ierr<=n ) then info = ierr else if( ierr>n .and. ierr<=2_${ik}$*n ) then info = ierr - n else info = n + 1_${ik}$ end if go to 130 end if ! compute eigenvectors and estimate condition numbers if desired ! (workspace: stdlib${ii}$_dtgevc: need 6*n ! stdlib${ii}$_dtgsna: need 2*n*(n+2)+16 if sense = 'v' or 'b', ! need n otherwise ) if( ilv .or. .not.wantsn ) then if( ilv ) then if( ilvl ) then if( ilvr ) then chtemp = 'B' else chtemp = 'L' end if else chtemp = 'R' end if call stdlib${ii}$_dtgevc( chtemp, 'B', ldumma, n, a, lda, b, ldb, vl,ldvl, vr, ldvr, n,& in, work, ierr ) if( ierr/=0_${ik}$ ) then info = n + 2_${ik}$ go to 130 end if end if if( .not.wantsn ) then ! compute eigenvectors (stdlib${ii}$_dtgevc) and estimate condition ! numbers (stdlib${ii}$_dtgsna). note that the definition of the condition ! number is not invariant under transformation (u,v) to ! (q*u, z*v), where (u,v) are eigenvectors of the generalized ! schur form (s,t), q and z are orthogonal matrices. in order ! to avoid using extra 2*n*n workspace, we have to recalculate ! eigenvectors and estimate one condition numbers at a time. pair = .false. loop_20: do i = 1, n if( pair ) then pair = .false. cycle loop_20 end if mm = 1_${ik}$ if( i<n ) then if( a( i+1, i )/=zero ) then pair = .true. mm = 2_${ik}$ end if end if do j = 1, n bwork( j ) = .false. end do if( mm==1_${ik}$ ) then bwork( i ) = .true. else if( mm==2_${ik}$ ) then bwork( i ) = .true. bwork( i+1 ) = .true. end if iwrk = mm*n + 1_${ik}$ iwrk1 = iwrk + mm*n ! compute a pair of left and right eigenvectors. ! (compute workspace: need up to 4*n + 6*n) if( wantse .or. wantsb ) then call stdlib${ii}$_dtgevc( 'B', 'S', bwork, n, a, lda, b, ldb,work( 1_${ik}$ ), n, work( & iwrk ), n, mm, m,work( iwrk1 ), ierr ) if( ierr/=0_${ik}$ ) then info = n + 2_${ik}$ go to 130 end if end if call stdlib${ii}$_dtgsna( sense, 'S', bwork, n, a, lda, b, ldb,work( 1_${ik}$ ), n, work( & iwrk ), n, rconde( i ),rcondv( i ), mm, m, work( iwrk1 ),lwork-iwrk1+1, iwork,& ierr ) end do loop_20 end if end if ! undo balancing on vl and vr and normalization ! (workspace: none needed) if( ilvl ) then call stdlib${ii}$_dggbak( balanc, 'L', n, ilo, ihi, lscale, rscale, n, vl,ldvl, ierr ) loop_70: do jc = 1, n if( alphai( jc )<zero )cycle loop_70 temp = zero if( alphai( jc )==zero ) then do jr = 1, n temp = max( temp, abs( vl( jr, jc ) ) ) end do else do jr = 1, n temp = max( temp, abs( vl( jr, jc ) )+abs( vl( jr, jc+1 ) ) ) end do end if if( temp<smlnum )cycle loop_70 temp = one / temp if( alphai( jc )==zero ) then do jr = 1, n vl( jr, jc ) = vl( jr, jc )*temp end do else do jr = 1, n vl( jr, jc ) = vl( jr, jc )*temp vl( jr, jc+1 ) = vl( jr, jc+1 )*temp end do end if end do loop_70 end if if( ilvr ) then call stdlib${ii}$_dggbak( balanc, 'R', n, ilo, ihi, lscale, rscale, n, vr,ldvr, ierr ) loop_120: do jc = 1, n if( alphai( jc )<zero )cycle loop_120 temp = zero if( alphai( jc )==zero ) then do jr = 1, n temp = max( temp, abs( vr( jr, jc ) ) ) end do else do jr = 1, n temp = max( temp, abs( vr( jr, jc ) )+abs( vr( jr, jc+1 ) ) ) end do end if if( temp<smlnum )cycle loop_120 temp = one / temp if( alphai( jc )==zero ) then do jr = 1, n vr( jr, jc ) = vr( jr, jc )*temp end do else do jr = 1, n vr( jr, jc ) = vr( jr, jc )*temp vr( jr, jc+1 ) = vr( jr, jc+1 )*temp end do end if end do loop_120 end if ! undo scaling if necessary 130 continue if( ilascl ) then call stdlib${ii}$_dlascl( 'G', 0_${ik}$, 0_${ik}$, anrmto, anrm, n, 1_${ik}$, alphar, n, ierr ) call stdlib${ii}$_dlascl( 'G', 0_${ik}$, 0_${ik}$, anrmto, anrm, n, 1_${ik}$, alphai, n, ierr ) end if if( ilbscl ) then call stdlib${ii}$_dlascl( 'G', 0_${ik}$, 0_${ik}$, bnrmto, bnrm, n, 1_${ik}$, beta, n, ierr ) end if work( 1_${ik}$ ) = maxwrk return end subroutine stdlib${ii}$_dggevx #:for rk,rt,ri in REAL_KINDS_TYPES #:if not rk in ["sp","dp"] module subroutine stdlib${ii}$_${ri}$ggevx( balanc, jobvl, jobvr, sense, n, a, lda, b, ldb,alphar, alphai, & !! DGGEVX: computes for a pair of N-by-N real nonsymmetric matrices (A,B) !! the generalized eigenvalues, and optionally, the left and/or right !! generalized eigenvectors. !! Optionally also, it computes a balancing transformation to improve !! the conditioning of the eigenvalues and eigenvectors (ILO, IHI, !! LSCALE, RSCALE, ABNRM, and BBNRM), reciprocal condition numbers for !! the eigenvalues (RCONDE), and reciprocal condition numbers for the !! right eigenvectors (RCONDV). !! A generalized eigenvalue for a pair of matrices (A,B) is a scalar !! lambda or a ratio alpha/beta = lambda, such that A - lambda*B is !! singular. It is usually represented as the pair (alpha,beta), as !! there is a reasonable interpretation for beta=0, and even for both !! being zero. !! The right eigenvector v(j) corresponding to the eigenvalue lambda(j) !! of (A,B) satisfies !! A * v(j) = lambda(j) * B * v(j) . !! The left eigenvector u(j) corresponding to the eigenvalue lambda(j) !! of (A,B) satisfies !! u(j)**H * A = lambda(j) * u(j)**H * B. !! where u(j)**H is the conjugate-transpose of u(j). beta, vl, ldvl, vr, ldvr, ilo,ihi, lscale, rscale, abnrm, bbnrm, rconde,rcondv, work, lwork, & iwork, bwork, info ) ! -- lapack driver routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_${rk}$, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments character, intent(in) :: balanc, jobvl, jobvr, sense integer(${ik}$), intent(out) :: ihi, ilo, info integer(${ik}$), intent(in) :: lda, ldb, ldvl, ldvr, lwork, n real(${rk}$), intent(out) :: abnrm, bbnrm ! Array Arguments logical(lk), intent(out) :: bwork(*) integer(${ik}$), intent(out) :: iwork(*) real(${rk}$), intent(inout) :: a(lda,*), b(ldb,*) real(${rk}$), intent(out) :: alphai(*), alphar(*), beta(*), lscale(*), rconde(*), rcondv(*)& , rscale(*), vl(ldvl,*), vr(ldvr,*), work(*) ! ===================================================================== ! Local Scalars logical(lk) :: ilascl, ilbscl, ilv, ilvl, ilvr, lquery, noscl, pair, wantsb, wantse, & wantsn, wantsv character :: chtemp integer(${ik}$) :: i, icols, ierr, ijobvl, ijobvr, in, irows, itau, iwrk, iwrk1, j, jc, & jr, m, maxwrk, minwrk, mm real(${rk}$) :: anrm, anrmto, bignum, bnrm, bnrmto, eps, smlnum, temp ! Local Arrays logical(lk) :: ldumma(1_${ik}$) ! Intrinsic Functions ! Executable Statements ! decode the input arguments if( stdlib_lsame( jobvl, 'N' ) ) then ijobvl = 1_${ik}$ ilvl = .false. else if( stdlib_lsame( jobvl, 'V' ) ) then ijobvl = 2_${ik}$ ilvl = .true. else ijobvl = -1_${ik}$ ilvl = .false. end if if( stdlib_lsame( jobvr, 'N' ) ) then ijobvr = 1_${ik}$ ilvr = .false. else if( stdlib_lsame( jobvr, 'V' ) ) then ijobvr = 2_${ik}$ ilvr = .true. else ijobvr = -1_${ik}$ ilvr = .false. end if ilv = ilvl .or. ilvr noscl = stdlib_lsame( balanc, 'N' ) .or. stdlib_lsame( balanc, 'P' ) wantsn = stdlib_lsame( sense, 'N' ) wantse = stdlib_lsame( sense, 'E' ) wantsv = stdlib_lsame( sense, 'V' ) wantsb = stdlib_lsame( sense, 'B' ) ! test the input arguments info = 0_${ik}$ lquery = ( lwork==-1_${ik}$ ) if( .not.( stdlib_lsame( balanc, 'N' ) .or. stdlib_lsame( balanc,'S' ) .or. & stdlib_lsame( balanc, 'P' ) .or. stdlib_lsame( balanc, 'B' ) ) )then info = -1_${ik}$ else if( ijobvl<=0_${ik}$ ) then info = -2_${ik}$ else if( ijobvr<=0_${ik}$ ) then info = -3_${ik}$ else if( .not.( wantsn .or. wantse .or. wantsb .or. wantsv ) )then info = -4_${ik}$ else if( n<0_${ik}$ ) then info = -5_${ik}$ else if( lda<max( 1_${ik}$, n ) ) then info = -7_${ik}$ else if( ldb<max( 1_${ik}$, n ) ) then info = -9_${ik}$ else if( ldvl<1_${ik}$ .or. ( ilvl .and. ldvl<n ) ) then info = -14_${ik}$ else if( ldvr<1_${ik}$ .or. ( ilvr .and. ldvr<n ) ) then info = -16_${ik}$ end if ! compute workspace ! (note: comments in the code beginning "workspace:" describe the ! minimal amount of workspace needed at that point in the code, ! as well as the preferred amount for good performance. ! nb refers to the optimal block size for the immediately ! following subroutine, as returned by stdlib${ii}$_ilaenv. the workspace is ! computed assuming ilo = 1 and ihi = n, the worst case.) if( info==0_${ik}$ ) then if( n==0_${ik}$ ) then minwrk = 1_${ik}$ maxwrk = 1_${ik}$ else if( noscl .and. .not.ilv ) then minwrk = 2_${ik}$*n else minwrk = 6_${ik}$*n end if if( wantse .or. wantsb ) then minwrk = 10_${ik}$*n end if if( wantsv .or. wantsb ) then minwrk = max( minwrk, 2_${ik}$*n*( n + 4_${ik}$ ) + 16_${ik}$ ) end if maxwrk = minwrk maxwrk = max( maxwrk,n + n*stdlib${ii}$_ilaenv( 1_${ik}$, 'DGEQRF', ' ', n, 1_${ik}$, n, 0_${ik}$ ) ) maxwrk = max( maxwrk,n + n*stdlib${ii}$_ilaenv( 1_${ik}$, 'DORMQR', ' ', n, 1_${ik}$, n, 0_${ik}$ ) ) if( ilvl ) then maxwrk = max( maxwrk, n +n*stdlib${ii}$_ilaenv( 1_${ik}$, 'DORGQR', ' ', n, 1_${ik}$, n, 0_${ik}$ ) ) end if end if work( 1_${ik}$ ) = maxwrk if( lwork<minwrk .and. .not.lquery ) then info = -26_${ik}$ end if end if if( info/=0_${ik}$ ) then call stdlib${ii}$_xerbla( 'DGGEVX', -info ) return else if( lquery ) then return end if ! quick return if possible if( n==0 )return ! get machine constants eps = stdlib${ii}$_${ri}$lamch( 'P' ) smlnum = stdlib${ii}$_${ri}$lamch( 'S' ) bignum = one / smlnum call stdlib${ii}$_${ri}$labad( smlnum, bignum ) smlnum = sqrt( smlnum ) / eps bignum = one / smlnum ! scale a if max element outside range [smlnum,bignum] anrm = stdlib${ii}$_${ri}$lange( 'M', n, n, a, lda, work ) ilascl = .false. if( anrm>zero .and. anrm<smlnum ) then anrmto = smlnum ilascl = .true. else if( anrm>bignum ) then anrmto = bignum ilascl = .true. end if if( ilascl )call stdlib${ii}$_${ri}$lascl( 'G', 0_${ik}$, 0_${ik}$, anrm, anrmto, n, n, a, lda, ierr ) ! scale b if max element outside range [smlnum,bignum] bnrm = stdlib${ii}$_${ri}$lange( 'M', n, n, b, ldb, work ) ilbscl = .false. if( bnrm>zero .and. bnrm<smlnum ) then bnrmto = smlnum ilbscl = .true. else if( bnrm>bignum ) then bnrmto = bignum ilbscl = .true. end if if( ilbscl )call stdlib${ii}$_${ri}$lascl( 'G', 0_${ik}$, 0_${ik}$, bnrm, bnrmto, n, n, b, ldb, ierr ) ! permute and/or balance the matrix pair (a,b) ! (workspace: need 6*n if balanc = 's' or 'b', 1 otherwise) call stdlib${ii}$_${ri}$ggbal( balanc, n, a, lda, b, ldb, ilo, ihi, lscale, rscale,work, ierr ) ! compute abnrm and bbnrm abnrm = stdlib${ii}$_${ri}$lange( '1', n, n, a, lda, work( 1_${ik}$ ) ) if( ilascl ) then work( 1_${ik}$ ) = abnrm call stdlib${ii}$_${ri}$lascl( 'G', 0_${ik}$, 0_${ik}$, anrmto, anrm, 1_${ik}$, 1_${ik}$, work( 1_${ik}$ ), 1_${ik}$,ierr ) abnrm = work( 1_${ik}$ ) end if bbnrm = stdlib${ii}$_${ri}$lange( '1', n, n, b, ldb, work( 1_${ik}$ ) ) if( ilbscl ) then work( 1_${ik}$ ) = bbnrm call stdlib${ii}$_${ri}$lascl( 'G', 0_${ik}$, 0_${ik}$, bnrmto, bnrm, 1_${ik}$, 1_${ik}$, work( 1_${ik}$ ), 1_${ik}$,ierr ) bbnrm = work( 1_${ik}$ ) end if ! reduce b to triangular form (qr decomposition of b) ! (workspace: need n, prefer n*nb ) irows = ihi + 1_${ik}$ - ilo if( ilv .or. .not.wantsn ) then icols = n + 1_${ik}$ - ilo else icols = irows end if itau = 1_${ik}$ iwrk = itau + irows call stdlib${ii}$_${ri}$geqrf( irows, icols, b( ilo, ilo ), ldb, work( itau ),work( iwrk ), lwork+& 1_${ik}$-iwrk, ierr ) ! apply the orthogonal transformation to a ! (workspace: need n, prefer n*nb) call stdlib${ii}$_${ri}$ormqr( 'L', 'T', irows, icols, irows, b( ilo, ilo ), ldb,work( itau ), a( & ilo, ilo ), lda, work( iwrk ),lwork+1-iwrk, ierr ) ! initialize vl and/or vr ! (workspace: need n, prefer n*nb) if( ilvl ) then call stdlib${ii}$_${ri}$laset( 'FULL', n, n, zero, one, vl, ldvl ) if( irows>1_${ik}$ ) then call stdlib${ii}$_${ri}$lacpy( 'L', irows-1, irows-1, b( ilo+1, ilo ), ldb,vl( ilo+1, ilo ),& ldvl ) end if call stdlib${ii}$_${ri}$orgqr( irows, irows, irows, vl( ilo, ilo ), ldvl,work( itau ), work( & iwrk ), lwork+1-iwrk, ierr ) end if if( ilvr )call stdlib${ii}$_${ri}$laset( 'FULL', n, n, zero, one, vr, ldvr ) ! reduce to generalized hessenberg form ! (workspace: none needed) if( ilv .or. .not.wantsn ) then ! eigenvectors requested -- work on whole matrix. call stdlib${ii}$_${ri}$gghrd( jobvl, jobvr, n, ilo, ihi, a, lda, b, ldb, vl,ldvl, vr, ldvr, & ierr ) else call stdlib${ii}$_${ri}$gghrd( 'N', 'N', irows, 1_${ik}$, irows, a( ilo, ilo ), lda,b( ilo, ilo ), & ldb, vl, ldvl, vr, ldvr, ierr ) end if ! perform qz algorithm (compute eigenvalues, and optionally, the ! schur forms and schur vectors) ! (workspace: need n) if( ilv .or. .not.wantsn ) then chtemp = 'S' else chtemp = 'E' end if call stdlib${ii}$_${ri}$hgeqz( chtemp, jobvl, jobvr, n, ilo, ihi, a, lda, b, ldb,alphar, alphai, & beta, vl, ldvl, vr, ldvr, work,lwork, ierr ) if( ierr/=0_${ik}$ ) then if( ierr>0_${ik}$ .and. ierr<=n ) then info = ierr else if( ierr>n .and. ierr<=2_${ik}$*n ) then info = ierr - n else info = n + 1_${ik}$ end if go to 130 end if ! compute eigenvectors and estimate condition numbers if desired ! (workspace: stdlib${ii}$_${ri}$tgevc: need 6*n ! stdlib${ii}$_${ri}$tgsna: need 2*n*(n+2)+16 if sense = 'v' or 'b', ! need n otherwise ) if( ilv .or. .not.wantsn ) then if( ilv ) then if( ilvl ) then if( ilvr ) then chtemp = 'B' else chtemp = 'L' end if else chtemp = 'R' end if call stdlib${ii}$_${ri}$tgevc( chtemp, 'B', ldumma, n, a, lda, b, ldb, vl,ldvl, vr, ldvr, n,& in, work, ierr ) if( ierr/=0_${ik}$ ) then info = n + 2_${ik}$ go to 130 end if end if if( .not.wantsn ) then ! compute eigenvectors (stdlib${ii}$_${ri}$tgevc) and estimate condition ! numbers (stdlib${ii}$_${ri}$tgsna). note that the definition of the condition ! number is not invariant under transformation (u,v) to ! (q*u, z*v), where (u,v) are eigenvectors of the generalized ! schur form (s,t), q and z are orthogonal matrices. in order ! to avoid using extra 2*n*n workspace, we have to recalculate ! eigenvectors and estimate one condition numbers at a time. pair = .false. loop_20: do i = 1, n if( pair ) then pair = .false. cycle loop_20 end if mm = 1_${ik}$ if( i<n ) then if( a( i+1, i )/=zero ) then pair = .true. mm = 2_${ik}$ end if end if do j = 1, n bwork( j ) = .false. end do if( mm==1_${ik}$ ) then bwork( i ) = .true. else if( mm==2_${ik}$ ) then bwork( i ) = .true. bwork( i+1 ) = .true. end if iwrk = mm*n + 1_${ik}$ iwrk1 = iwrk + mm*n ! compute a pair of left and right eigenvectors. ! (compute workspace: need up to 4*n + 6*n) if( wantse .or. wantsb ) then call stdlib${ii}$_${ri}$tgevc( 'B', 'S', bwork, n, a, lda, b, ldb,work( 1_${ik}$ ), n, work( & iwrk ), n, mm, m,work( iwrk1 ), ierr ) if( ierr/=0_${ik}$ ) then info = n + 2_${ik}$ go to 130 end if end if call stdlib${ii}$_${ri}$tgsna( sense, 'S', bwork, n, a, lda, b, ldb,work( 1_${ik}$ ), n, work( & iwrk ), n, rconde( i ),rcondv( i ), mm, m, work( iwrk1 ),lwork-iwrk1+1, iwork,& ierr ) end do loop_20 end if end if ! undo balancing on vl and vr and normalization ! (workspace: none needed) if( ilvl ) then call stdlib${ii}$_${ri}$ggbak( balanc, 'L', n, ilo, ihi, lscale, rscale, n, vl,ldvl, ierr ) loop_70: do jc = 1, n if( alphai( jc )<zero )cycle loop_70 temp = zero if( alphai( jc )==zero ) then do jr = 1, n temp = max( temp, abs( vl( jr, jc ) ) ) end do else do jr = 1, n temp = max( temp, abs( vl( jr, jc ) )+abs( vl( jr, jc+1 ) ) ) end do end if if( temp<smlnum )cycle loop_70 temp = one / temp if( alphai( jc )==zero ) then do jr = 1, n vl( jr, jc ) = vl( jr, jc )*temp end do else do jr = 1, n vl( jr, jc ) = vl( jr, jc )*temp vl( jr, jc+1 ) = vl( jr, jc+1 )*temp end do end if end do loop_70 end if if( ilvr ) then call stdlib${ii}$_${ri}$ggbak( balanc, 'R', n, ilo, ihi, lscale, rscale, n, vr,ldvr, ierr ) loop_120: do jc = 1, n if( alphai( jc )<zero )cycle loop_120 temp = zero if( alphai( jc )==zero ) then do jr = 1, n temp = max( temp, abs( vr( jr, jc ) ) ) end do else do jr = 1, n temp = max( temp, abs( vr( jr, jc ) )+abs( vr( jr, jc+1 ) ) ) end do end if if( temp<smlnum )cycle loop_120 temp = one / temp if( alphai( jc )==zero ) then do jr = 1, n vr( jr, jc ) = vr( jr, jc )*temp end do else do jr = 1, n vr( jr, jc ) = vr( jr, jc )*temp vr( jr, jc+1 ) = vr( jr, jc+1 )*temp end do end if end do loop_120 end if ! undo scaling if necessary 130 continue if( ilascl ) then call stdlib${ii}$_${ri}$lascl( 'G', 0_${ik}$, 0_${ik}$, anrmto, anrm, n, 1_${ik}$, alphar, n, ierr ) call stdlib${ii}$_${ri}$lascl( 'G', 0_${ik}$, 0_${ik}$, anrmto, anrm, n, 1_${ik}$, alphai, n, ierr ) end if if( ilbscl ) then call stdlib${ii}$_${ri}$lascl( 'G', 0_${ik}$, 0_${ik}$, bnrmto, bnrm, n, 1_${ik}$, beta, n, ierr ) end if work( 1_${ik}$ ) = maxwrk return end subroutine stdlib${ii}$_${ri}$ggevx #:endif #:endfor module subroutine stdlib${ii}$_cggevx( balanc, jobvl, jobvr, sense, n, a, lda, b, ldb,alpha, beta, vl, & !! CGGEVX computes for a pair of N-by-N complex nonsymmetric matrices !! (A,B) the generalized eigenvalues, and optionally, the left and/or !! right generalized eigenvectors. !! Optionally, it also computes a balancing transformation to improve !! the conditioning of the eigenvalues and eigenvectors (ILO, IHI, !! LSCALE, RSCALE, ABNRM, and BBNRM), reciprocal condition numbers for !! the eigenvalues (RCONDE), and reciprocal condition numbers for the !! right eigenvectors (RCONDV). !! A generalized eigenvalue for a pair of matrices (A,B) is a scalar !! lambda or a ratio alpha/beta = lambda, such that A - lambda*B is !! singular. It is usually represented as the pair (alpha,beta), as !! there is a reasonable interpretation for beta=0, and even for both !! being zero. !! The right eigenvector v(j) corresponding to the eigenvalue lambda(j) !! of (A,B) satisfies !! A * v(j) = lambda(j) * B * v(j) . !! The left eigenvector u(j) corresponding to the eigenvalue lambda(j) !! of (A,B) satisfies !! u(j)**H * A = lambda(j) * u(j)**H * B. !! where u(j)**H is the conjugate-transpose of u(j). ldvl, vr, ldvr, ilo, ihi,lscale, rscale, abnrm, bbnrm, rconde, rcondv,work, lwork, rwork, & iwork, bwork, info ) ! -- lapack driver routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_sp, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments character, intent(in) :: balanc, jobvl, jobvr, sense integer(${ik}$), intent(out) :: ihi, ilo, info integer(${ik}$), intent(in) :: lda, ldb, ldvl, ldvr, lwork, n real(sp), intent(out) :: abnrm, bbnrm ! Array Arguments logical(lk), intent(out) :: bwork(*) integer(${ik}$), intent(out) :: iwork(*) real(sp), intent(out) :: lscale(*), rconde(*), rcondv(*), rscale(*), rwork(*) complex(sp), intent(inout) :: a(lda,*), b(ldb,*) complex(sp), intent(out) :: alpha(*), beta(*), vl(ldvl,*), vr(ldvr,*), work(*) ! ===================================================================== ! Local Scalars logical(lk) :: ilascl, ilbscl, ilv, ilvl, ilvr, lquery, noscl, wantsb, wantse, wantsn, & wantsv character :: chtemp integer(${ik}$) :: i, icols, ierr, ijobvl, ijobvr, in, irows, itau, iwrk, iwrk1, j, jc, & jr, m, maxwrk, minwrk real(sp) :: anrm, anrmto, bignum, bnrm, bnrmto, eps, smlnum, temp complex(sp) :: x ! Local Arrays logical(lk) :: ldumma(1_${ik}$) ! Intrinsic Functions ! Statement Functions real(sp) :: abs1 ! Statement Function Definitions abs1( x ) = abs( real( x,KIND=sp) ) + abs( aimag( x ) ) ! Executable Statements ! decode the input arguments if( stdlib_lsame( jobvl, 'N' ) ) then ijobvl = 1_${ik}$ ilvl = .false. else if( stdlib_lsame( jobvl, 'V' ) ) then ijobvl = 2_${ik}$ ilvl = .true. else ijobvl = -1_${ik}$ ilvl = .false. end if if( stdlib_lsame( jobvr, 'N' ) ) then ijobvr = 1_${ik}$ ilvr = .false. else if( stdlib_lsame( jobvr, 'V' ) ) then ijobvr = 2_${ik}$ ilvr = .true. else ijobvr = -1_${ik}$ ilvr = .false. end if ilv = ilvl .or. ilvr noscl = stdlib_lsame( balanc, 'N' ) .or. stdlib_lsame( balanc, 'P' ) wantsn = stdlib_lsame( sense, 'N' ) wantse = stdlib_lsame( sense, 'E' ) wantsv = stdlib_lsame( sense, 'V' ) wantsb = stdlib_lsame( sense, 'B' ) ! test the input arguments info = 0_${ik}$ lquery = ( lwork==-1_${ik}$ ) if( .not.( noscl .or. stdlib_lsame( balanc,'S' ) .or.stdlib_lsame( balanc, 'B' ) ) ) & then info = -1_${ik}$ else if( ijobvl<=0_${ik}$ ) then info = -2_${ik}$ else if( ijobvr<=0_${ik}$ ) then info = -3_${ik}$ else if( .not.( wantsn .or. wantse .or. wantsb .or. wantsv ) )then info = -4_${ik}$ else if( n<0_${ik}$ ) then info = -5_${ik}$ else if( lda<max( 1_${ik}$, n ) ) then info = -7_${ik}$ else if( ldb<max( 1_${ik}$, n ) ) then info = -9_${ik}$ else if( ldvl<1_${ik}$ .or. ( ilvl .and. ldvl<n ) ) then info = -13_${ik}$ else if( ldvr<1_${ik}$ .or. ( ilvr .and. ldvr<n ) ) then info = -15_${ik}$ end if ! compute workspace ! (note: comments in the code beginning "workspace:" describe the ! minimal amount of workspace needed at that point in the code, ! as well as the preferred amount for good performance. ! nb refers to the optimal block size for the immediately ! following subroutine, as returned by stdlib${ii}$_ilaenv. the workspace is ! computed assuming ilo = 1 and ihi = n, the worst case.) if( info==0_${ik}$ ) then if( n==0_${ik}$ ) then minwrk = 1_${ik}$ maxwrk = 1_${ik}$ else minwrk = 2_${ik}$*n if( wantse ) then minwrk = 4_${ik}$*n else if( wantsv .or. wantsb ) then minwrk = 2_${ik}$*n*( n + 1_${ik}$) end if maxwrk = minwrk maxwrk = max( maxwrk,n + n*stdlib${ii}$_ilaenv( 1_${ik}$, 'CGEQRF', ' ', n, 1_${ik}$, n, 0_${ik}$ ) ) maxwrk = max( maxwrk,n + n*stdlib${ii}$_ilaenv( 1_${ik}$, 'CUNMQR', ' ', n, 1_${ik}$, n, 0_${ik}$ ) ) if( ilvl ) then maxwrk = max( maxwrk, n +n*stdlib${ii}$_ilaenv( 1_${ik}$, 'CUNGQR', ' ', n, 1_${ik}$, n, 0_${ik}$ ) ) end if end if work( 1_${ik}$ ) = maxwrk if( lwork<minwrk .and. .not.lquery ) then info = -25_${ik}$ end if end if if( info/=0_${ik}$ ) then call stdlib${ii}$_xerbla( 'CGGEVX', -info ) return else if( lquery ) then return end if ! quick return if possible if( n==0 )return ! get machine constants eps = stdlib${ii}$_slamch( 'P' ) smlnum = stdlib${ii}$_slamch( 'S' ) bignum = one / smlnum call stdlib${ii}$_slabad( smlnum, bignum ) smlnum = sqrt( smlnum ) / eps bignum = one / smlnum ! scale a if max element outside range [smlnum,bignum] anrm = stdlib${ii}$_clange( 'M', n, n, a, lda, rwork ) ilascl = .false. if( anrm>zero .and. anrm<smlnum ) then anrmto = smlnum ilascl = .true. else if( anrm>bignum ) then anrmto = bignum ilascl = .true. end if if( ilascl )call stdlib${ii}$_clascl( 'G', 0_${ik}$, 0_${ik}$, anrm, anrmto, n, n, a, lda, ierr ) ! scale b if max element outside range [smlnum,bignum] bnrm = stdlib${ii}$_clange( 'M', n, n, b, ldb, rwork ) ilbscl = .false. if( bnrm>zero .and. bnrm<smlnum ) then bnrmto = smlnum ilbscl = .true. else if( bnrm>bignum ) then bnrmto = bignum ilbscl = .true. end if if( ilbscl )call stdlib${ii}$_clascl( 'G', 0_${ik}$, 0_${ik}$, bnrm, bnrmto, n, n, b, ldb, ierr ) ! permute and/or balance the matrix pair (a,b) ! (real workspace: need 6*n if balanc = 's' or 'b', 1 otherwise) call stdlib${ii}$_cggbal( balanc, n, a, lda, b, ldb, ilo, ihi, lscale, rscale,rwork, ierr ) ! compute abnrm and bbnrm abnrm = stdlib${ii}$_clange( '1', n, n, a, lda, rwork( 1_${ik}$ ) ) if( ilascl ) then rwork( 1_${ik}$ ) = abnrm call stdlib${ii}$_slascl( 'G', 0_${ik}$, 0_${ik}$, anrmto, anrm, 1_${ik}$, 1_${ik}$, rwork( 1_${ik}$ ), 1_${ik}$,ierr ) abnrm = rwork( 1_${ik}$ ) end if bbnrm = stdlib${ii}$_clange( '1', n, n, b, ldb, rwork( 1_${ik}$ ) ) if( ilbscl ) then rwork( 1_${ik}$ ) = bbnrm call stdlib${ii}$_slascl( 'G', 0_${ik}$, 0_${ik}$, bnrmto, bnrm, 1_${ik}$, 1_${ik}$, rwork( 1_${ik}$ ), 1_${ik}$,ierr ) bbnrm = rwork( 1_${ik}$ ) end if ! reduce b to triangular form (qr decomposition of b) ! (complex workspace: need n, prefer n*nb ) irows = ihi + 1_${ik}$ - ilo if( ilv .or. .not.wantsn ) then icols = n + 1_${ik}$ - ilo else icols = irows end if itau = 1_${ik}$ iwrk = itau + irows call stdlib${ii}$_cgeqrf( irows, icols, b( ilo, ilo ), ldb, work( itau ),work( iwrk ), lwork+& 1_${ik}$-iwrk, ierr ) ! apply the unitary transformation to a ! (complex workspace: need n, prefer n*nb) call stdlib${ii}$_cunmqr( 'L', 'C', irows, icols, irows, b( ilo, ilo ), ldb,work( itau ), a( & ilo, ilo ), lda, work( iwrk ),lwork+1-iwrk, ierr ) ! initialize vl and/or vr ! (workspace: need n, prefer n*nb) if( ilvl ) then call stdlib${ii}$_claset( 'FULL', n, n, czero, cone, vl, ldvl ) if( irows>1_${ik}$ ) then call stdlib${ii}$_clacpy( 'L', irows-1, irows-1, b( ilo+1, ilo ), ldb,vl( ilo+1, ilo ),& ldvl ) end if call stdlib${ii}$_cungqr( irows, irows, irows, vl( ilo, ilo ), ldvl,work( itau ), work( & iwrk ), lwork+1-iwrk, ierr ) end if if( ilvr )call stdlib${ii}$_claset( 'FULL', n, n, czero, cone, vr, ldvr ) ! reduce to generalized hessenberg form ! (workspace: none needed) if( ilv .or. .not.wantsn ) then ! eigenvectors requested -- work on whole matrix. call stdlib${ii}$_cgghrd( jobvl, jobvr, n, ilo, ihi, a, lda, b, ldb, vl,ldvl, vr, ldvr, & ierr ) else call stdlib${ii}$_cgghrd( 'N', 'N', irows, 1_${ik}$, irows, a( ilo, ilo ), lda,b( ilo, ilo ), & ldb, vl, ldvl, vr, ldvr, ierr ) end if ! perform qz algorithm (compute eigenvalues, and optionally, the ! schur forms and schur vectors) ! (complex workspace: need n) ! (real workspace: need n) iwrk = itau if( ilv .or. .not.wantsn ) then chtemp = 'S' else chtemp = 'E' end if call stdlib${ii}$_chgeqz( chtemp, jobvl, jobvr, n, ilo, ihi, a, lda, b, ldb,alpha, beta, vl, & ldvl, vr, ldvr, work( iwrk ),lwork+1-iwrk, rwork, ierr ) if( ierr/=0_${ik}$ ) then if( ierr>0_${ik}$ .and. ierr<=n ) then info = ierr else if( ierr>n .and. ierr<=2_${ik}$*n ) then info = ierr - n else info = n + 1_${ik}$ end if go to 90 end if ! compute eigenvectors and estimate condition numbers if desired ! stdlib${ii}$_ctgevc: (complex workspace: need 2*n ) ! (real workspace: need 2*n ) ! stdlib${ii}$_ctgsna: (complex workspace: need 2*n*n if sense='v' or 'b') ! (integer workspace: need n+2 ) if( ilv .or. .not.wantsn ) then if( ilv ) then if( ilvl ) then if( ilvr ) then chtemp = 'B' else chtemp = 'L' end if else chtemp = 'R' end if call stdlib${ii}$_ctgevc( chtemp, 'B', ldumma, n, a, lda, b, ldb, vl,ldvl, vr, ldvr, n,& in, work( iwrk ), rwork,ierr ) if( ierr/=0_${ik}$ ) then info = n + 2_${ik}$ go to 90 end if end if if( .not.wantsn ) then ! compute eigenvectors (stdlib${ii}$_ctgevc) and estimate condition ! numbers (stdlib${ii}$_ctgsna). note that the definition of the condition ! number is not invariant under transformation (u,v) to ! (q*u, z*v), where (u,v) are eigenvectors of the generalized ! schur form (s,t), q and z are orthogonal matrices. in order ! to avoid using extra 2*n*n workspace, we have to ! re-calculate eigenvectors and estimate the condition numbers ! one at a time. do i = 1, n do j = 1, n bwork( j ) = .false. end do bwork( i ) = .true. iwrk = n + 1_${ik}$ iwrk1 = iwrk + n if( wantse .or. wantsb ) then call stdlib${ii}$_ctgevc( 'B', 'S', bwork, n, a, lda, b, ldb,work( 1_${ik}$ ), n, work( & iwrk ), n, 1_${ik}$, m,work( iwrk1 ), rwork, ierr ) if( ierr/=0_${ik}$ ) then info = n + 2_${ik}$ go to 90 end if end if call stdlib${ii}$_ctgsna( sense, 'S', bwork, n, a, lda, b, ldb,work( 1_${ik}$ ), n, work( & iwrk ), n, rconde( i ),rcondv( i ), 1_${ik}$, m, work( iwrk1 ),lwork-iwrk1+1, iwork, & ierr ) end do end if end if ! undo balancing on vl and vr and normalization ! (workspace: none needed) if( ilvl ) then call stdlib${ii}$_cggbak( balanc, 'L', n, ilo, ihi, lscale, rscale, n, vl,ldvl, ierr ) loop_50: do jc = 1, n temp = zero do jr = 1, n temp = max( temp, abs1( vl( jr, jc ) ) ) end do if( temp<smlnum )cycle loop_50 temp = one / temp do jr = 1, n vl( jr, jc ) = vl( jr, jc )*temp end do end do loop_50 end if if( ilvr ) then call stdlib${ii}$_cggbak( balanc, 'R', n, ilo, ihi, lscale, rscale, n, vr,ldvr, ierr ) loop_80: do jc = 1, n temp = zero do jr = 1, n temp = max( temp, abs1( vr( jr, jc ) ) ) end do if( temp<smlnum )cycle loop_80 temp = one / temp do jr = 1, n vr( jr, jc ) = vr( jr, jc )*temp end do end do loop_80 end if ! undo scaling if necessary 90 continue if( ilascl )call stdlib${ii}$_clascl( 'G', 0_${ik}$, 0_${ik}$, anrmto, anrm, n, 1_${ik}$, alpha, n, ierr ) if( ilbscl )call stdlib${ii}$_clascl( 'G', 0_${ik}$, 0_${ik}$, bnrmto, bnrm, n, 1_${ik}$, beta, n, ierr ) work( 1_${ik}$ ) = maxwrk return end subroutine stdlib${ii}$_cggevx module subroutine stdlib${ii}$_zggevx( balanc, jobvl, jobvr, sense, n, a, lda, b, ldb,alpha, beta, vl, & !! ZGGEVX computes for a pair of N-by-N complex nonsymmetric matrices !! (A,B) the generalized eigenvalues, and optionally, the left and/or !! right generalized eigenvectors. !! Optionally, it also computes a balancing transformation to improve !! the conditioning of the eigenvalues and eigenvectors (ILO, IHI, !! LSCALE, RSCALE, ABNRM, and BBNRM), reciprocal condition numbers for !! the eigenvalues (RCONDE), and reciprocal condition numbers for the !! right eigenvectors (RCONDV). !! A generalized eigenvalue for a pair of matrices (A,B) is a scalar !! lambda or a ratio alpha/beta = lambda, such that A - lambda*B is !! singular. It is usually represented as the pair (alpha,beta), as !! there is a reasonable interpretation for beta=0, and even for both !! being zero. !! The right eigenvector v(j) corresponding to the eigenvalue lambda(j) !! of (A,B) satisfies !! A * v(j) = lambda(j) * B * v(j) . !! The left eigenvector u(j) corresponding to the eigenvalue lambda(j) !! of (A,B) satisfies !! u(j)**H * A = lambda(j) * u(j)**H * B. !! where u(j)**H is the conjugate-transpose of u(j). ldvl, vr, ldvr, ilo, ihi,lscale, rscale, abnrm, bbnrm, rconde, rcondv,work, lwork, rwork, & iwork, bwork, info ) ! -- lapack driver routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_dp, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments character, intent(in) :: balanc, jobvl, jobvr, sense integer(${ik}$), intent(out) :: ihi, ilo, info integer(${ik}$), intent(in) :: lda, ldb, ldvl, ldvr, lwork, n real(dp), intent(out) :: abnrm, bbnrm ! Array Arguments logical(lk), intent(out) :: bwork(*) integer(${ik}$), intent(out) :: iwork(*) real(dp), intent(out) :: lscale(*), rconde(*), rcondv(*), rscale(*), rwork(*) complex(dp), intent(inout) :: a(lda,*), b(ldb,*) complex(dp), intent(out) :: alpha(*), beta(*), vl(ldvl,*), vr(ldvr,*), work(*) ! ===================================================================== ! Local Scalars logical(lk) :: ilascl, ilbscl, ilv, ilvl, ilvr, lquery, noscl, wantsb, wantse, wantsn, & wantsv character :: chtemp integer(${ik}$) :: i, icols, ierr, ijobvl, ijobvr, in, irows, itau, iwrk, iwrk1, j, jc, & jr, m, maxwrk, minwrk real(dp) :: anrm, anrmto, bignum, bnrm, bnrmto, eps, smlnum, temp complex(dp) :: x ! Local Arrays logical(lk) :: ldumma(1_${ik}$) ! Intrinsic Functions ! Statement Functions real(dp) :: abs1 ! Statement Function Definitions abs1( x ) = abs( real( x,KIND=dp) ) + abs( aimag( x ) ) ! Executable Statements ! decode the input arguments if( stdlib_lsame( jobvl, 'N' ) ) then ijobvl = 1_${ik}$ ilvl = .false. else if( stdlib_lsame( jobvl, 'V' ) ) then ijobvl = 2_${ik}$ ilvl = .true. else ijobvl = -1_${ik}$ ilvl = .false. end if if( stdlib_lsame( jobvr, 'N' ) ) then ijobvr = 1_${ik}$ ilvr = .false. else if( stdlib_lsame( jobvr, 'V' ) ) then ijobvr = 2_${ik}$ ilvr = .true. else ijobvr = -1_${ik}$ ilvr = .false. end if ilv = ilvl .or. ilvr noscl = stdlib_lsame( balanc, 'N' ) .or. stdlib_lsame( balanc, 'P' ) wantsn = stdlib_lsame( sense, 'N' ) wantse = stdlib_lsame( sense, 'E' ) wantsv = stdlib_lsame( sense, 'V' ) wantsb = stdlib_lsame( sense, 'B' ) ! test the input arguments info = 0_${ik}$ lquery = ( lwork==-1_${ik}$ ) if( .not.( noscl .or. stdlib_lsame( balanc,'S' ) .or.stdlib_lsame( balanc, 'B' ) ) ) & then info = -1_${ik}$ else if( ijobvl<=0_${ik}$ ) then info = -2_${ik}$ else if( ijobvr<=0_${ik}$ ) then info = -3_${ik}$ else if( .not.( wantsn .or. wantse .or. wantsb .or. wantsv ) )then info = -4_${ik}$ else if( n<0_${ik}$ ) then info = -5_${ik}$ else if( lda<max( 1_${ik}$, n ) ) then info = -7_${ik}$ else if( ldb<max( 1_${ik}$, n ) ) then info = -9_${ik}$ else if( ldvl<1_${ik}$ .or. ( ilvl .and. ldvl<n ) ) then info = -13_${ik}$ else if( ldvr<1_${ik}$ .or. ( ilvr .and. ldvr<n ) ) then info = -15_${ik}$ end if ! compute workspace ! (note: comments in the code beginning "workspace:" describe the ! minimal amount of workspace needed at that point in the code, ! as well as the preferred amount for good performance. ! nb refers to the optimal block size for the immediately ! following subroutine, as returned by stdlib${ii}$_ilaenv. the workspace is ! computed assuming ilo = 1 and ihi = n, the worst case.) if( info==0_${ik}$ ) then if( n==0_${ik}$ ) then minwrk = 1_${ik}$ maxwrk = 1_${ik}$ else minwrk = 2_${ik}$*n if( wantse ) then minwrk = 4_${ik}$*n else if( wantsv .or. wantsb ) then minwrk = 2_${ik}$*n*( n + 1_${ik}$) end if maxwrk = minwrk maxwrk = max( maxwrk,n + n*stdlib${ii}$_ilaenv( 1_${ik}$, 'ZGEQRF', ' ', n, 1_${ik}$, n, 0_${ik}$ ) ) maxwrk = max( maxwrk,n + n*stdlib${ii}$_ilaenv( 1_${ik}$, 'ZUNMQR', ' ', n, 1_${ik}$, n, 0_${ik}$ ) ) if( ilvl ) then maxwrk = max( maxwrk, n +n*stdlib${ii}$_ilaenv( 1_${ik}$, 'ZUNGQR', ' ', n, 1_${ik}$, n, 0_${ik}$ ) ) end if end if work( 1_${ik}$ ) = maxwrk if( lwork<minwrk .and. .not.lquery ) then info = -25_${ik}$ end if end if if( info/=0_${ik}$ ) then call stdlib${ii}$_xerbla( 'ZGGEVX', -info ) return else if( lquery ) then return end if ! quick return if possible if( n==0 )return ! get machine constants eps = stdlib${ii}$_dlamch( 'P' ) smlnum = stdlib${ii}$_dlamch( 'S' ) bignum = one / smlnum call stdlib${ii}$_dlabad( smlnum, bignum ) smlnum = sqrt( smlnum ) / eps bignum = one / smlnum ! scale a if max element outside range [smlnum,bignum] anrm = stdlib${ii}$_zlange( 'M', n, n, a, lda, rwork ) ilascl = .false. if( anrm>zero .and. anrm<smlnum ) then anrmto = smlnum ilascl = .true. else if( anrm>bignum ) then anrmto = bignum ilascl = .true. end if if( ilascl )call stdlib${ii}$_zlascl( 'G', 0_${ik}$, 0_${ik}$, anrm, anrmto, n, n, a, lda, ierr ) ! scale b if max element outside range [smlnum,bignum] bnrm = stdlib${ii}$_zlange( 'M', n, n, b, ldb, rwork ) ilbscl = .false. if( bnrm>zero .and. bnrm<smlnum ) then bnrmto = smlnum ilbscl = .true. else if( bnrm>bignum ) then bnrmto = bignum ilbscl = .true. end if if( ilbscl )call stdlib${ii}$_zlascl( 'G', 0_${ik}$, 0_${ik}$, bnrm, bnrmto, n, n, b, ldb, ierr ) ! permute and/or balance the matrix pair (a,b) ! (real workspace: need 6*n if balanc = 's' or 'b', 1 otherwise) call stdlib${ii}$_zggbal( balanc, n, a, lda, b, ldb, ilo, ihi, lscale, rscale,rwork, ierr ) ! compute abnrm and bbnrm abnrm = stdlib${ii}$_zlange( '1', n, n, a, lda, rwork( 1_${ik}$ ) ) if( ilascl ) then rwork( 1_${ik}$ ) = abnrm call stdlib${ii}$_dlascl( 'G', 0_${ik}$, 0_${ik}$, anrmto, anrm, 1_${ik}$, 1_${ik}$, rwork( 1_${ik}$ ), 1_${ik}$,ierr ) abnrm = rwork( 1_${ik}$ ) end if bbnrm = stdlib${ii}$_zlange( '1', n, n, b, ldb, rwork( 1_${ik}$ ) ) if( ilbscl ) then rwork( 1_${ik}$ ) = bbnrm call stdlib${ii}$_dlascl( 'G', 0_${ik}$, 0_${ik}$, bnrmto, bnrm, 1_${ik}$, 1_${ik}$, rwork( 1_${ik}$ ), 1_${ik}$,ierr ) bbnrm = rwork( 1_${ik}$ ) end if ! reduce b to triangular form (qr decomposition of b) ! (complex workspace: need n, prefer n*nb ) irows = ihi + 1_${ik}$ - ilo if( ilv .or. .not.wantsn ) then icols = n + 1_${ik}$ - ilo else icols = irows end if itau = 1_${ik}$ iwrk = itau + irows call stdlib${ii}$_zgeqrf( irows, icols, b( ilo, ilo ), ldb, work( itau ),work( iwrk ), lwork+& 1_${ik}$-iwrk, ierr ) ! apply the unitary transformation to a ! (complex workspace: need n, prefer n*nb) call stdlib${ii}$_zunmqr( 'L', 'C', irows, icols, irows, b( ilo, ilo ), ldb,work( itau ), a( & ilo, ilo ), lda, work( iwrk ),lwork+1-iwrk, ierr ) ! initialize vl and/or vr ! (workspace: need n, prefer n*nb) if( ilvl ) then call stdlib${ii}$_zlaset( 'FULL', n, n, czero, cone, vl, ldvl ) if( irows>1_${ik}$ ) then call stdlib${ii}$_zlacpy( 'L', irows-1, irows-1, b( ilo+1, ilo ), ldb,vl( ilo+1, ilo ),& ldvl ) end if call stdlib${ii}$_zungqr( irows, irows, irows, vl( ilo, ilo ), ldvl,work( itau ), work( & iwrk ), lwork+1-iwrk, ierr ) end if if( ilvr )call stdlib${ii}$_zlaset( 'FULL', n, n, czero, cone, vr, ldvr ) ! reduce to generalized hessenberg form ! (workspace: none needed) if( ilv .or. .not.wantsn ) then ! eigenvectors requested -- work on whole matrix. call stdlib${ii}$_zgghrd( jobvl, jobvr, n, ilo, ihi, a, lda, b, ldb, vl,ldvl, vr, ldvr, & ierr ) else call stdlib${ii}$_zgghrd( 'N', 'N', irows, 1_${ik}$, irows, a( ilo, ilo ), lda,b( ilo, ilo ), & ldb, vl, ldvl, vr, ldvr, ierr ) end if ! perform qz algorithm (compute eigenvalues, and optionally, the ! schur forms and schur vectors) ! (complex workspace: need n) ! (real workspace: need n) iwrk = itau if( ilv .or. .not.wantsn ) then chtemp = 'S' else chtemp = 'E' end if call stdlib${ii}$_zhgeqz( chtemp, jobvl, jobvr, n, ilo, ihi, a, lda, b, ldb,alpha, beta, vl, & ldvl, vr, ldvr, work( iwrk ),lwork+1-iwrk, rwork, ierr ) if( ierr/=0_${ik}$ ) then if( ierr>0_${ik}$ .and. ierr<=n ) then info = ierr else if( ierr>n .and. ierr<=2_${ik}$*n ) then info = ierr - n else info = n + 1_${ik}$ end if go to 90 end if ! compute eigenvectors and estimate condition numbers if desired ! stdlib${ii}$_ztgevc: (complex workspace: need 2*n ) ! (real workspace: need 2*n ) ! stdlib${ii}$_ztgsna: (complex workspace: need 2*n*n if sense='v' or 'b') ! (integer workspace: need n+2 ) if( ilv .or. .not.wantsn ) then if( ilv ) then if( ilvl ) then if( ilvr ) then chtemp = 'B' else chtemp = 'L' end if else chtemp = 'R' end if call stdlib${ii}$_ztgevc( chtemp, 'B', ldumma, n, a, lda, b, ldb, vl,ldvl, vr, ldvr, n,& in, work( iwrk ), rwork,ierr ) if( ierr/=0_${ik}$ ) then info = n + 2_${ik}$ go to 90 end if end if if( .not.wantsn ) then ! compute eigenvectors (stdlib${ii}$_ztgevc) and estimate condition ! numbers (stdlib${ii}$_ztgsna). note that the definition of the condition ! number is not invariant under transformation (u,v) to ! (q*u, z*v), where (u,v) are eigenvectors of the generalized ! schur form (s,t), q and z are orthogonal matrices. in order ! to avoid using extra 2*n*n workspace, we have to ! re-calculate eigenvectors and estimate the condition numbers ! one at a time. do i = 1, n do j = 1, n bwork( j ) = .false. end do bwork( i ) = .true. iwrk = n + 1_${ik}$ iwrk1 = iwrk + n if( wantse .or. wantsb ) then call stdlib${ii}$_ztgevc( 'B', 'S', bwork, n, a, lda, b, ldb,work( 1_${ik}$ ), n, work( & iwrk ), n, 1_${ik}$, m,work( iwrk1 ), rwork, ierr ) if( ierr/=0_${ik}$ ) then info = n + 2_${ik}$ go to 90 end if end if call stdlib${ii}$_ztgsna( sense, 'S', bwork, n, a, lda, b, ldb,work( 1_${ik}$ ), n, work( & iwrk ), n, rconde( i ),rcondv( i ), 1_${ik}$, m, work( iwrk1 ),lwork-iwrk1+1, iwork, & ierr ) end do end if end if ! undo balancing on vl and vr and normalization ! (workspace: none needed) if( ilvl ) then call stdlib${ii}$_zggbak( balanc, 'L', n, ilo, ihi, lscale, rscale, n, vl,ldvl, ierr ) loop_50: do jc = 1, n temp = zero do jr = 1, n temp = max( temp, abs1( vl( jr, jc ) ) ) end do if( temp<smlnum )cycle loop_50 temp = one / temp do jr = 1, n vl( jr, jc ) = vl( jr, jc )*temp end do end do loop_50 end if if( ilvr ) then call stdlib${ii}$_zggbak( balanc, 'R', n, ilo, ihi, lscale, rscale, n, vr,ldvr, ierr ) loop_80: do jc = 1, n temp = zero do jr = 1, n temp = max( temp, abs1( vr( jr, jc ) ) ) end do if( temp<smlnum )cycle loop_80 temp = one / temp do jr = 1, n vr( jr, jc ) = vr( jr, jc )*temp end do end do loop_80 end if ! undo scaling if necessary 90 continue if( ilascl )call stdlib${ii}$_zlascl( 'G', 0_${ik}$, 0_${ik}$, anrmto, anrm, n, 1_${ik}$, alpha, n, ierr ) if( ilbscl )call stdlib${ii}$_zlascl( 'G', 0_${ik}$, 0_${ik}$, bnrmto, bnrm, n, 1_${ik}$, beta, n, ierr ) work( 1_${ik}$ ) = maxwrk return end subroutine stdlib${ii}$_zggevx #:for ck,ct,ci in CMPLX_KINDS_TYPES #:if not ck in ["sp","dp"] module subroutine stdlib${ii}$_${ci}$ggevx( balanc, jobvl, jobvr, sense, n, a, lda, b, ldb,alpha, beta, vl, & !! ZGGEVX: computes for a pair of N-by-N complex nonsymmetric matrices !! (A,B) the generalized eigenvalues, and optionally, the left and/or !! right generalized eigenvectors. !! Optionally, it also computes a balancing transformation to improve !! the conditioning of the eigenvalues and eigenvectors (ILO, IHI, !! LSCALE, RSCALE, ABNRM, and BBNRM), reciprocal condition numbers for !! the eigenvalues (RCONDE), and reciprocal condition numbers for the !! right eigenvectors (RCONDV). !! A generalized eigenvalue for a pair of matrices (A,B) is a scalar !! lambda or a ratio alpha/beta = lambda, such that A - lambda*B is !! singular. It is usually represented as the pair (alpha,beta), as !! there is a reasonable interpretation for beta=0, and even for both !! being zero. !! The right eigenvector v(j) corresponding to the eigenvalue lambda(j) !! of (A,B) satisfies !! A * v(j) = lambda(j) * B * v(j) . !! The left eigenvector u(j) corresponding to the eigenvalue lambda(j) !! of (A,B) satisfies !! u(j)**H * A = lambda(j) * u(j)**H * B. !! where u(j)**H is the conjugate-transpose of u(j). ldvl, vr, ldvr, ilo, ihi,lscale, rscale, abnrm, bbnrm, rconde, rcondv,work, lwork, rwork, & iwork, bwork, info ) ! -- lapack driver routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_${ck}$, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments character, intent(in) :: balanc, jobvl, jobvr, sense integer(${ik}$), intent(out) :: ihi, ilo, info integer(${ik}$), intent(in) :: lda, ldb, ldvl, ldvr, lwork, n real(${ck}$), intent(out) :: abnrm, bbnrm ! Array Arguments logical(lk), intent(out) :: bwork(*) integer(${ik}$), intent(out) :: iwork(*) real(${ck}$), intent(out) :: lscale(*), rconde(*), rcondv(*), rscale(*), rwork(*) complex(${ck}$), intent(inout) :: a(lda,*), b(ldb,*) complex(${ck}$), intent(out) :: alpha(*), beta(*), vl(ldvl,*), vr(ldvr,*), work(*) ! ===================================================================== ! Local Scalars logical(lk) :: ilascl, ilbscl, ilv, ilvl, ilvr, lquery, noscl, wantsb, wantse, wantsn, & wantsv character :: chtemp integer(${ik}$) :: i, icols, ierr, ijobvl, ijobvr, in, irows, itau, iwrk, iwrk1, j, jc, & jr, m, maxwrk, minwrk real(${ck}$) :: anrm, anrmto, bignum, bnrm, bnrmto, eps, smlnum, temp complex(${ck}$) :: x ! Local Arrays logical(lk) :: ldumma(1_${ik}$) ! Intrinsic Functions ! Statement Functions real(${ck}$) :: abs1 ! Statement Function Definitions abs1( x ) = abs( real( x,KIND=${ck}$) ) + abs( aimag( x ) ) ! Executable Statements ! decode the input arguments if( stdlib_lsame( jobvl, 'N' ) ) then ijobvl = 1_${ik}$ ilvl = .false. else if( stdlib_lsame( jobvl, 'V' ) ) then ijobvl = 2_${ik}$ ilvl = .true. else ijobvl = -1_${ik}$ ilvl = .false. end if if( stdlib_lsame( jobvr, 'N' ) ) then ijobvr = 1_${ik}$ ilvr = .false. else if( stdlib_lsame( jobvr, 'V' ) ) then ijobvr = 2_${ik}$ ilvr = .true. else ijobvr = -1_${ik}$ ilvr = .false. end if ilv = ilvl .or. ilvr noscl = stdlib_lsame( balanc, 'N' ) .or. stdlib_lsame( balanc, 'P' ) wantsn = stdlib_lsame( sense, 'N' ) wantse = stdlib_lsame( sense, 'E' ) wantsv = stdlib_lsame( sense, 'V' ) wantsb = stdlib_lsame( sense, 'B' ) ! test the input arguments info = 0_${ik}$ lquery = ( lwork==-1_${ik}$ ) if( .not.( noscl .or. stdlib_lsame( balanc,'S' ) .or.stdlib_lsame( balanc, 'B' ) ) ) & then info = -1_${ik}$ else if( ijobvl<=0_${ik}$ ) then info = -2_${ik}$ else if( ijobvr<=0_${ik}$ ) then info = -3_${ik}$ else if( .not.( wantsn .or. wantse .or. wantsb .or. wantsv ) )then info = -4_${ik}$ else if( n<0_${ik}$ ) then info = -5_${ik}$ else if( lda<max( 1_${ik}$, n ) ) then info = -7_${ik}$ else if( ldb<max( 1_${ik}$, n ) ) then info = -9_${ik}$ else if( ldvl<1_${ik}$ .or. ( ilvl .and. ldvl<n ) ) then info = -13_${ik}$ else if( ldvr<1_${ik}$ .or. ( ilvr .and. ldvr<n ) ) then info = -15_${ik}$ end if ! compute workspace ! (note: comments in the code beginning "workspace:" describe the ! minimal amount of workspace needed at that point in the code, ! as well as the preferred amount for good performance. ! nb refers to the optimal block size for the immediately ! following subroutine, as returned by stdlib${ii}$_ilaenv. the workspace is ! computed assuming ilo = 1 and ihi = n, the worst case.) if( info==0_${ik}$ ) then if( n==0_${ik}$ ) then minwrk = 1_${ik}$ maxwrk = 1_${ik}$ else minwrk = 2_${ik}$*n if( wantse ) then minwrk = 4_${ik}$*n else if( wantsv .or. wantsb ) then minwrk = 2_${ik}$*n*( n + 1_${ik}$) end if maxwrk = minwrk maxwrk = max( maxwrk,n + n*stdlib${ii}$_ilaenv( 1_${ik}$, 'ZGEQRF', ' ', n, 1_${ik}$, n, 0_${ik}$ ) ) maxwrk = max( maxwrk,n + n*stdlib${ii}$_ilaenv( 1_${ik}$, 'ZUNMQR', ' ', n, 1_${ik}$, n, 0_${ik}$ ) ) if( ilvl ) then maxwrk = max( maxwrk, n +n*stdlib${ii}$_ilaenv( 1_${ik}$, 'ZUNGQR', ' ', n, 1_${ik}$, n, 0_${ik}$ ) ) end if end if work( 1_${ik}$ ) = maxwrk if( lwork<minwrk .and. .not.lquery ) then info = -25_${ik}$ end if end if if( info/=0_${ik}$ ) then call stdlib${ii}$_xerbla( 'ZGGEVX', -info ) return else if( lquery ) then return end if ! quick return if possible if( n==0 )return ! get machine constants eps = stdlib${ii}$_${c2ri(ci)}$lamch( 'P' ) smlnum = stdlib${ii}$_${c2ri(ci)}$lamch( 'S' ) bignum = one / smlnum call stdlib${ii}$_${c2ri(ci)}$labad( smlnum, bignum ) smlnum = sqrt( smlnum ) / eps bignum = one / smlnum ! scale a if max element outside range [smlnum,bignum] anrm = stdlib${ii}$_${ci}$lange( 'M', n, n, a, lda, rwork ) ilascl = .false. if( anrm>zero .and. anrm<smlnum ) then anrmto = smlnum ilascl = .true. else if( anrm>bignum ) then anrmto = bignum ilascl = .true. end if if( ilascl )call stdlib${ii}$_${ci}$lascl( 'G', 0_${ik}$, 0_${ik}$, anrm, anrmto, n, n, a, lda, ierr ) ! scale b if max element outside range [smlnum,bignum] bnrm = stdlib${ii}$_${ci}$lange( 'M', n, n, b, ldb, rwork ) ilbscl = .false. if( bnrm>zero .and. bnrm<smlnum ) then bnrmto = smlnum ilbscl = .true. else if( bnrm>bignum ) then bnrmto = bignum ilbscl = .true. end if if( ilbscl )call stdlib${ii}$_${ci}$lascl( 'G', 0_${ik}$, 0_${ik}$, bnrm, bnrmto, n, n, b, ldb, ierr ) ! permute and/or balance the matrix pair (a,b) ! (real workspace: need 6*n if balanc = 's' or 'b', 1 otherwise) call stdlib${ii}$_${ci}$ggbal( balanc, n, a, lda, b, ldb, ilo, ihi, lscale, rscale,rwork, ierr ) ! compute abnrm and bbnrm abnrm = stdlib${ii}$_${ci}$lange( '1', n, n, a, lda, rwork( 1_${ik}$ ) ) if( ilascl ) then rwork( 1_${ik}$ ) = abnrm call stdlib${ii}$_${c2ri(ci)}$lascl( 'G', 0_${ik}$, 0_${ik}$, anrmto, anrm, 1_${ik}$, 1_${ik}$, rwork( 1_${ik}$ ), 1_${ik}$,ierr ) abnrm = rwork( 1_${ik}$ ) end if bbnrm = stdlib${ii}$_${ci}$lange( '1', n, n, b, ldb, rwork( 1_${ik}$ ) ) if( ilbscl ) then rwork( 1_${ik}$ ) = bbnrm call stdlib${ii}$_${c2ri(ci)}$lascl( 'G', 0_${ik}$, 0_${ik}$, bnrmto, bnrm, 1_${ik}$, 1_${ik}$, rwork( 1_${ik}$ ), 1_${ik}$,ierr ) bbnrm = rwork( 1_${ik}$ ) end if ! reduce b to triangular form (qr decomposition of b) ! (complex workspace: need n, prefer n*nb ) irows = ihi + 1_${ik}$ - ilo if( ilv .or. .not.wantsn ) then icols = n + 1_${ik}$ - ilo else icols = irows end if itau = 1_${ik}$ iwrk = itau + irows call stdlib${ii}$_${ci}$geqrf( irows, icols, b( ilo, ilo ), ldb, work( itau ),work( iwrk ), lwork+& 1_${ik}$-iwrk, ierr ) ! apply the unitary transformation to a ! (complex workspace: need n, prefer n*nb) call stdlib${ii}$_${ci}$unmqr( 'L', 'C', irows, icols, irows, b( ilo, ilo ), ldb,work( itau ), a( & ilo, ilo ), lda, work( iwrk ),lwork+1-iwrk, ierr ) ! initialize vl and/or vr ! (workspace: need n, prefer n*nb) if( ilvl ) then call stdlib${ii}$_${ci}$laset( 'FULL', n, n, czero, cone, vl, ldvl ) if( irows>1_${ik}$ ) then call stdlib${ii}$_${ci}$lacpy( 'L', irows-1, irows-1, b( ilo+1, ilo ), ldb,vl( ilo+1, ilo ),& ldvl ) end if call stdlib${ii}$_${ci}$ungqr( irows, irows, irows, vl( ilo, ilo ), ldvl,work( itau ), work( & iwrk ), lwork+1-iwrk, ierr ) end if if( ilvr )call stdlib${ii}$_${ci}$laset( 'FULL', n, n, czero, cone, vr, ldvr ) ! reduce to generalized hessenberg form ! (workspace: none needed) if( ilv .or. .not.wantsn ) then ! eigenvectors requested -- work on whole matrix. call stdlib${ii}$_${ci}$gghrd( jobvl, jobvr, n, ilo, ihi, a, lda, b, ldb, vl,ldvl, vr, ldvr, & ierr ) else call stdlib${ii}$_${ci}$gghrd( 'N', 'N', irows, 1_${ik}$, irows, a( ilo, ilo ), lda,b( ilo, ilo ), & ldb, vl, ldvl, vr, ldvr, ierr ) end if ! perform qz algorithm (compute eigenvalues, and optionally, the ! schur forms and schur vectors) ! (complex workspace: need n) ! (real workspace: need n) iwrk = itau if( ilv .or. .not.wantsn ) then chtemp = 'S' else chtemp = 'E' end if call stdlib${ii}$_${ci}$hgeqz( chtemp, jobvl, jobvr, n, ilo, ihi, a, lda, b, ldb,alpha, beta, vl, & ldvl, vr, ldvr, work( iwrk ),lwork+1-iwrk, rwork, ierr ) if( ierr/=0_${ik}$ ) then if( ierr>0_${ik}$ .and. ierr<=n ) then info = ierr else if( ierr>n .and. ierr<=2_${ik}$*n ) then info = ierr - n else info = n + 1_${ik}$ end if go to 90 end if ! compute eigenvectors and estimate condition numbers if desired ! stdlib${ii}$_${ci}$tgevc: (complex workspace: need 2*n ) ! (real workspace: need 2*n ) ! stdlib${ii}$_${ci}$tgsna: (complex workspace: need 2*n*n if sense='v' or 'b') ! (integer workspace: need n+2 ) if( ilv .or. .not.wantsn ) then if( ilv ) then if( ilvl ) then if( ilvr ) then chtemp = 'B' else chtemp = 'L' end if else chtemp = 'R' end if call stdlib${ii}$_${ci}$tgevc( chtemp, 'B', ldumma, n, a, lda, b, ldb, vl,ldvl, vr, ldvr, n,& in, work( iwrk ), rwork,ierr ) if( ierr/=0_${ik}$ ) then info = n + 2_${ik}$ go to 90 end if end if if( .not.wantsn ) then ! compute eigenvectors (stdlib${ii}$_${ci}$tgevc) and estimate condition ! numbers (stdlib${ii}$_${ci}$tgsna). note that the definition of the condition ! number is not invariant under transformation (u,v) to ! (q*u, z*v), where (u,v) are eigenvectors of the generalized ! schur form (s,t), q and z are orthogonal matrices. in order ! to avoid using extra 2*n*n workspace, we have to ! re-calculate eigenvectors and estimate the condition numbers ! one at a time. do i = 1, n do j = 1, n bwork( j ) = .false. end do bwork( i ) = .true. iwrk = n + 1_${ik}$ iwrk1 = iwrk + n if( wantse .or. wantsb ) then call stdlib${ii}$_${ci}$tgevc( 'B', 'S', bwork, n, a, lda, b, ldb,work( 1_${ik}$ ), n, work( & iwrk ), n, 1_${ik}$, m,work( iwrk1 ), rwork, ierr ) if( ierr/=0_${ik}$ ) then info = n + 2_${ik}$ go to 90 end if end if call stdlib${ii}$_${ci}$tgsna( sense, 'S', bwork, n, a, lda, b, ldb,work( 1_${ik}$ ), n, work( & iwrk ), n, rconde( i ),rcondv( i ), 1_${ik}$, m, work( iwrk1 ),lwork-iwrk1+1, iwork, & ierr ) end do end if end if ! undo balancing on vl and vr and normalization ! (workspace: none needed) if( ilvl ) then call stdlib${ii}$_${ci}$ggbak( balanc, 'L', n, ilo, ihi, lscale, rscale, n, vl,ldvl, ierr ) loop_50: do jc = 1, n temp = zero do jr = 1, n temp = max( temp, abs1( vl( jr, jc ) ) ) end do if( temp<smlnum )cycle loop_50 temp = one / temp do jr = 1, n vl( jr, jc ) = vl( jr, jc )*temp end do end do loop_50 end if if( ilvr ) then call stdlib${ii}$_${ci}$ggbak( balanc, 'R', n, ilo, ihi, lscale, rscale, n, vr,ldvr, ierr ) loop_80: do jc = 1, n temp = zero do jr = 1, n temp = max( temp, abs1( vr( jr, jc ) ) ) end do if( temp<smlnum )cycle loop_80 temp = one / temp do jr = 1, n vr( jr, jc ) = vr( jr, jc )*temp end do end do loop_80 end if ! undo scaling if necessary 90 continue if( ilascl )call stdlib${ii}$_${ci}$lascl( 'G', 0_${ik}$, 0_${ik}$, anrmto, anrm, n, 1_${ik}$, alpha, n, ierr ) if( ilbscl )call stdlib${ii}$_${ci}$lascl( 'G', 0_${ik}$, 0_${ik}$, bnrmto, bnrm, n, 1_${ik}$, beta, n, ierr ) work( 1_${ik}$ ) = maxwrk return end subroutine stdlib${ii}$_${ci}$ggevx #:endif #:endfor module subroutine stdlib${ii}$_sgges3( jobvsl, jobvsr, sort, selctg, n, a, lda, b,ldb, sdim, alphar, & !! SGGES3 computes for a pair of N-by-N real nonsymmetric matrices (A,B), !! the generalized eigenvalues, the generalized real Schur form (S,T), !! optionally, the left and/or right matrices of Schur vectors (VSL and !! VSR). This gives the generalized Schur factorization !! (A,B) = ( (VSL)*S*(VSR)**T, (VSL)*T*(VSR)**T ) !! Optionally, it also orders the eigenvalues so that a selected cluster !! of eigenvalues appears in the leading diagonal blocks of the upper !! quasi-triangular matrix S and the upper triangular matrix T.The !! leading columns of VSL and VSR then form an orthonormal basis for the !! corresponding left and right eigenspaces (deflating subspaces). !! (If only the generalized eigenvalues are needed, use the driver !! SGGEV instead, which is faster.) !! A generalized eigenvalue for a pair of matrices (A,B) is a scalar w !! or a ratio alpha/beta = w, such that A - w*B is singular. It is !! usually represented as the pair (alpha,beta), as there is a !! reasonable interpretation for beta=0 or both being zero. !! A pair of matrices (S,T) is in generalized real Schur form if T is !! upper triangular with non-negative diagonal and S is block upper !! triangular with 1-by-1 and 2-by-2 blocks. 1-by-1 blocks correspond !! to real generalized eigenvalues, while 2-by-2 blocks of S will be !! "standardized" by making the corresponding elements of T have the !! form: !! [ a 0 ] !! [ 0 b ] !! and the pair of corresponding 2-by-2 blocks in S and T will have a !! complex conjugate pair of generalized eigenvalues. alphai, beta, vsl, ldvsl,vsr, ldvsr, work, lwork, bwork, info ) ! -- lapack driver routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_sp, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments character, intent(in) :: jobvsl, jobvsr, sort integer(${ik}$), intent(out) :: info, sdim integer(${ik}$), intent(in) :: lda, ldb, ldvsl, ldvsr, lwork, n ! Array Arguments logical(lk), intent(out) :: bwork(*) real(sp), intent(inout) :: a(lda,*), b(ldb,*) real(sp), intent(out) :: alphai(*), alphar(*), beta(*), vsl(ldvsl,*), vsr(ldvsr,*), & work(*) ! Function Arguments procedure(stdlib_selctg_s) :: selctg ! ===================================================================== ! Local Scalars logical(lk) :: cursl, ilascl, ilbscl, ilvsl, ilvsr, lastsl, lquery, lst2sl, & wantst integer(${ik}$) :: i, icols, ierr, ihi, ijobvl, ijobvr, ileft, ilo, ip, iright, irows, & itau, iwrk, lwkopt real(sp) :: anrm, anrmto, bignum, bnrm, bnrmto, eps, pvsl, pvsr, safmax, safmin, & smlnum ! Local Arrays integer(${ik}$) :: idum(1_${ik}$) real(sp) :: dif(2_${ik}$) ! Intrinsic Functions ! Executable Statements ! decode the input arguments if( stdlib_lsame( jobvsl, 'N' ) ) then ijobvl = 1_${ik}$ ilvsl = .false. else if( stdlib_lsame( jobvsl, 'V' ) ) then ijobvl = 2_${ik}$ ilvsl = .true. else ijobvl = -1_${ik}$ ilvsl = .false. end if if( stdlib_lsame( jobvsr, 'N' ) ) then ijobvr = 1_${ik}$ ilvsr = .false. else if( stdlib_lsame( jobvsr, 'V' ) ) then ijobvr = 2_${ik}$ ilvsr = .true. else ijobvr = -1_${ik}$ ilvsr = .false. end if wantst = stdlib_lsame( sort, 'S' ) ! test the input arguments info = 0_${ik}$ lquery = ( lwork==-1_${ik}$ ) if( ijobvl<=0_${ik}$ ) then info = -1_${ik}$ else if( ijobvr<=0_${ik}$ ) then info = -2_${ik}$ else if( ( .not.wantst ) .and. ( .not.stdlib_lsame( sort, 'N' ) ) ) then info = -3_${ik}$ else if( n<0_${ik}$ ) then info = -5_${ik}$ else if( lda<max( 1_${ik}$, n ) ) then info = -7_${ik}$ else if( ldb<max( 1_${ik}$, n ) ) then info = -9_${ik}$ else if( ldvsl<1_${ik}$ .or. ( ilvsl .and. ldvsl<n ) ) then info = -15_${ik}$ else if( ldvsr<1_${ik}$ .or. ( ilvsr .and. ldvsr<n ) ) then info = -17_${ik}$ else if( lwork<6_${ik}$*n+16 .and. .not.lquery ) then info = -19_${ik}$ end if ! compute workspace if( info==0_${ik}$ ) then call stdlib${ii}$_sgeqrf( n, n, b, ldb, work, work, -1_${ik}$, ierr ) lwkopt = max( 6_${ik}$*n+16, 3_${ik}$*n+int( work( 1_${ik}$ ),KIND=${ik}$) ) call stdlib${ii}$_sormqr( 'L', 'T', n, n, n, b, ldb, work, a, lda, work,-1_${ik}$, ierr ) lwkopt = max( lwkopt, 3_${ik}$*n+int( work( 1_${ik}$ ),KIND=${ik}$) ) if( ilvsl ) then call stdlib${ii}$_sorgqr( n, n, n, vsl, ldvsl, work, work, -1_${ik}$, ierr ) lwkopt = max( lwkopt, 3_${ik}$*n+int( work( 1_${ik}$ ),KIND=${ik}$) ) end if call stdlib${ii}$_sgghd3( jobvsl, jobvsr, n, 1_${ik}$, n, a, lda, b, ldb, vsl,ldvsl, vsr, ldvsr, & work, -1_${ik}$, ierr ) lwkopt = max( lwkopt, 3_${ik}$*n+int( work( 1_${ik}$ ),KIND=${ik}$) ) call stdlib${ii}$_slaqz0( 'S', jobvsl, jobvsr, n, 1_${ik}$, n, a, lda, b, ldb,alphar, alphai, & beta, vsl, ldvsl, vsr, ldvsr,work, -1_${ik}$, 0_${ik}$, ierr ) lwkopt = max( lwkopt, 2_${ik}$*n+int( work( 1_${ik}$ ),KIND=${ik}$) ) if( wantst ) then call stdlib${ii}$_stgsen( 0_${ik}$, ilvsl, ilvsr, bwork, n, a, lda, b, ldb,alphar, alphai, & beta, vsl, ldvsl, vsr, ldvsr,sdim, pvsl, pvsr, dif, work, -1_${ik}$, idum, 1_${ik}$,ierr ) lwkopt = max( lwkopt, 2_${ik}$*n+int( work( 1_${ik}$ ),KIND=${ik}$) ) end if work( 1_${ik}$ ) = lwkopt end if if( info/=0_${ik}$ ) then call stdlib${ii}$_xerbla( 'SGGES3 ', -info ) return else if( lquery ) then return end if ! quick return if possible if( n==0_${ik}$ ) then sdim = 0_${ik}$ return end if ! get machine constants eps = stdlib${ii}$_slamch( 'P' ) safmin = stdlib${ii}$_slamch( 'S' ) safmax = one / safmin call stdlib${ii}$_slabad( safmin, safmax ) smlnum = sqrt( safmin ) / eps bignum = one / smlnum ! scale a if max element outside range [smlnum,bignum] anrm = stdlib${ii}$_slange( 'M', n, n, a, lda, work ) ilascl = .false. if( anrm>zero .and. anrm<smlnum ) then anrmto = smlnum ilascl = .true. else if( anrm>bignum ) then anrmto = bignum ilascl = .true. end if if( ilascl )call stdlib${ii}$_slascl( 'G', 0_${ik}$, 0_${ik}$, anrm, anrmto, n, n, a, lda, ierr ) ! scale b if max element outside range [smlnum,bignum] bnrm = stdlib${ii}$_slange( 'M', n, n, b, ldb, work ) ilbscl = .false. if( bnrm>zero .and. bnrm<smlnum ) then bnrmto = smlnum ilbscl = .true. else if( bnrm>bignum ) then bnrmto = bignum ilbscl = .true. end if if( ilbscl )call stdlib${ii}$_slascl( 'G', 0_${ik}$, 0_${ik}$, bnrm, bnrmto, n, n, b, ldb, ierr ) ! permute the matrix to make it more nearly triangular ileft = 1_${ik}$ iright = n + 1_${ik}$ iwrk = iright + n call stdlib${ii}$_sggbal( 'P', n, a, lda, b, ldb, ilo, ihi, work( ileft ),work( iright ), & work( iwrk ), ierr ) ! reduce b to triangular form (qr decomposition of b) irows = ihi + 1_${ik}$ - ilo icols = n + 1_${ik}$ - ilo itau = iwrk iwrk = itau + irows call stdlib${ii}$_sgeqrf( irows, icols, b( ilo, ilo ), ldb, work( itau ),work( iwrk ), lwork+& 1_${ik}$-iwrk, ierr ) ! apply the orthogonal transformation to matrix a call stdlib${ii}$_sormqr( 'L', 'T', irows, icols, irows, b( ilo, ilo ), ldb,work( itau ), a( & ilo, ilo ), lda, work( iwrk ),lwork+1-iwrk, ierr ) ! initialize vsl if( ilvsl ) then call stdlib${ii}$_slaset( 'FULL', n, n, zero, one, vsl, ldvsl ) if( irows>1_${ik}$ ) then call stdlib${ii}$_slacpy( 'L', irows-1, irows-1, b( ilo+1, ilo ), ldb,vsl( ilo+1, ilo )& , ldvsl ) end if call stdlib${ii}$_sorgqr( irows, irows, irows, vsl( ilo, ilo ), ldvsl,work( itau ), work( & iwrk ), lwork+1-iwrk, ierr ) end if ! initialize vsr if( ilvsr )call stdlib${ii}$_slaset( 'FULL', n, n, zero, one, vsr, ldvsr ) ! reduce to generalized hessenberg form call stdlib${ii}$_sgghd3( jobvsl, jobvsr, n, ilo, ihi, a, lda, b, ldb, vsl,ldvsl, vsr, ldvsr,& work( iwrk ), lwork+1-iwrk, ierr ) ! perform qz algorithm, computing schur vectors if desired iwrk = itau call stdlib${ii}$_slaqz0( 'S', jobvsl, jobvsr, n, ilo, ihi, a, lda, b, ldb,alphar, alphai, & beta, vsl, ldvsl, vsr, ldvsr,work( iwrk ), lwork+1-iwrk, 0_${ik}$, ierr ) if( ierr/=0_${ik}$ ) then if( ierr>0_${ik}$ .and. ierr<=n ) then info = ierr else if( ierr>n .and. ierr<=2_${ik}$*n ) then info = ierr - n else info = n + 1_${ik}$ end if go to 40 end if ! sort eigenvalues alpha/beta if desired sdim = 0_${ik}$ if( wantst ) then ! undo scaling on eigenvalues before selctging if( ilascl ) then call stdlib${ii}$_slascl( 'G', 0_${ik}$, 0_${ik}$, anrmto, anrm, n, 1_${ik}$, alphar, n,ierr ) call stdlib${ii}$_slascl( 'G', 0_${ik}$, 0_${ik}$, anrmto, anrm, n, 1_${ik}$, alphai, n,ierr ) end if if( ilbscl )call stdlib${ii}$_slascl( 'G', 0_${ik}$, 0_${ik}$, bnrmto, bnrm, n, 1_${ik}$, beta, n, ierr ) ! select eigenvalues do i = 1, n bwork( i ) = selctg( alphar( i ), alphai( i ), beta( i ) ) end do call stdlib${ii}$_stgsen( 0_${ik}$, ilvsl, ilvsr, bwork, n, a, lda, b, ldb, alphar,alphai, beta, & vsl, ldvsl, vsr, ldvsr, sdim, pvsl,pvsr, dif, work( iwrk ), lwork-iwrk+1, idum, 1_${ik}$,& ierr ) if( ierr==1_${ik}$ )info = n + 3_${ik}$ end if ! apply back-permutation to vsl and vsr if( ilvsl )call stdlib${ii}$_sggbak( 'P', 'L', n, ilo, ihi, work( ileft ),work( iright ), n, & vsl, ldvsl, ierr ) if( ilvsr )call stdlib${ii}$_sggbak( 'P', 'R', n, ilo, ihi, work( ileft ),work( iright ), n, & vsr, ldvsr, ierr ) ! check if unscaling would cause over/underflow, if so, rescale ! (alphar(i),alphai(i),beta(i)) so beta(i) is on the order of ! b(i,i) and alphar(i) and alphai(i) are on the order of a(i,i) if( ilascl )then do i = 1, n if( alphai( i )/=zero ) then if( ( alphar( i )/safmax )>( anrmto/anrm ) .or.( safmin/alphar( i ) )>( & anrm/anrmto ) ) then work( 1_${ik}$ ) = abs( a( i, i )/alphar( i ) ) beta( i ) = beta( i )*work( 1_${ik}$ ) alphar( i ) = alphar( i )*work( 1_${ik}$ ) alphai( i ) = alphai( i )*work( 1_${ik}$ ) else if( ( alphai( i )/safmax )>( anrmto/anrm ) .or.( safmin/alphai( i ) )>( & anrm/anrmto ) ) then work( 1_${ik}$ ) = abs( a( i, i+1 )/alphai( i ) ) beta( i ) = beta( i )*work( 1_${ik}$ ) alphar( i ) = alphar( i )*work( 1_${ik}$ ) alphai( i ) = alphai( i )*work( 1_${ik}$ ) end if end if end do end if if( ilbscl )then do i = 1, n if( alphai( i )/=zero ) then if( ( beta( i )/safmax )>( bnrmto/bnrm ) .or.( safmin/beta( i ) )>( & bnrm/bnrmto ) ) then work( 1_${ik}$ ) = abs(b( i, i )/beta( i )) beta( i ) = beta( i )*work( 1_${ik}$ ) alphar( i ) = alphar( i )*work( 1_${ik}$ ) alphai( i ) = alphai( i )*work( 1_${ik}$ ) end if end if end do end if ! undo scaling if( ilascl ) then call stdlib${ii}$_slascl( 'H', 0_${ik}$, 0_${ik}$, anrmto, anrm, n, n, a, lda, ierr ) call stdlib${ii}$_slascl( 'G', 0_${ik}$, 0_${ik}$, anrmto, anrm, n, 1_${ik}$, alphar, n, ierr ) call stdlib${ii}$_slascl( 'G', 0_${ik}$, 0_${ik}$, anrmto, anrm, n, 1_${ik}$, alphai, n, ierr ) end if if( ilbscl ) then call stdlib${ii}$_slascl( 'U', 0_${ik}$, 0_${ik}$, bnrmto, bnrm, n, n, b, ldb, ierr ) call stdlib${ii}$_slascl( 'G', 0_${ik}$, 0_${ik}$, bnrmto, bnrm, n, 1_${ik}$, beta, n, ierr ) end if if( wantst ) then ! check if reordering is correct lastsl = .true. lst2sl = .true. sdim = 0_${ik}$ ip = 0_${ik}$ do i = 1, n cursl = selctg( alphar( i ), alphai( i ), beta( i ) ) if( alphai( i )==zero ) then if( cursl )sdim = sdim + 1_${ik}$ ip = 0_${ik}$ if( cursl .and. .not.lastsl )info = n + 2_${ik}$ else if( ip==1_${ik}$ ) then ! last eigenvalue of conjugate pair cursl = cursl .or. lastsl lastsl = cursl if( cursl )sdim = sdim + 2_${ik}$ ip = -1_${ik}$ if( cursl .and. .not.lst2sl )info = n + 2_${ik}$ else ! first eigenvalue of conjugate pair ip = 1_${ik}$ end if end if lst2sl = lastsl lastsl = cursl end do end if 40 continue work( 1_${ik}$ ) = lwkopt return end subroutine stdlib${ii}$_sgges3 module subroutine stdlib${ii}$_dgges3( jobvsl, jobvsr, sort, selctg, n, a, lda, b,ldb, sdim, alphar, & !! DGGES3 computes for a pair of N-by-N real nonsymmetric matrices (A,B), !! the generalized eigenvalues, the generalized real Schur form (S,T), !! optionally, the left and/or right matrices of Schur vectors (VSL and !! VSR). This gives the generalized Schur factorization !! (A,B) = ( (VSL)*S*(VSR)**T, (VSL)*T*(VSR)**T ) !! Optionally, it also orders the eigenvalues so that a selected cluster !! of eigenvalues appears in the leading diagonal blocks of the upper !! quasi-triangular matrix S and the upper triangular matrix T.The !! leading columns of VSL and VSR then form an orthonormal basis for the !! corresponding left and right eigenspaces (deflating subspaces). !! (If only the generalized eigenvalues are needed, use the driver !! DGGEV instead, which is faster.) !! A generalized eigenvalue for a pair of matrices (A,B) is a scalar w !! or a ratio alpha/beta = w, such that A - w*B is singular. It is !! usually represented as the pair (alpha,beta), as there is a !! reasonable interpretation for beta=0 or both being zero. !! A pair of matrices (S,T) is in generalized real Schur form if T is !! upper triangular with non-negative diagonal and S is block upper !! triangular with 1-by-1 and 2-by-2 blocks. 1-by-1 blocks correspond !! to real generalized eigenvalues, while 2-by-2 blocks of S will be !! "standardized" by making the corresponding elements of T have the !! form: !! [ a 0 ] !! [ 0 b ] !! and the pair of corresponding 2-by-2 blocks in S and T will have a !! complex conjugate pair of generalized eigenvalues. alphai, beta, vsl, ldvsl,vsr, ldvsr, work, lwork, bwork, info ) ! -- lapack driver routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_dp, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments character, intent(in) :: jobvsl, jobvsr, sort integer(${ik}$), intent(out) :: info, sdim integer(${ik}$), intent(in) :: lda, ldb, ldvsl, ldvsr, lwork, n ! Array Arguments logical(lk), intent(out) :: bwork(*) real(dp), intent(inout) :: a(lda,*), b(ldb,*) real(dp), intent(out) :: alphai(*), alphar(*), beta(*), vsl(ldvsl,*), vsr(ldvsr,*), & work(*) ! Function Arguments procedure(stdlib_selctg_d) :: selctg ! ===================================================================== ! Local Scalars logical(lk) :: cursl, ilascl, ilbscl, ilvsl, ilvsr, lastsl, lquery, lst2sl, & wantst integer(${ik}$) :: i, icols, ierr, ihi, ijobvl, ijobvr, ileft, ilo, ip, iright, irows, & itau, iwrk, lwkopt real(dp) :: anrm, anrmto, bignum, bnrm, bnrmto, eps, pvsl, pvsr, safmax, safmin, & smlnum ! Local Arrays integer(${ik}$) :: idum(1_${ik}$) real(dp) :: dif(2_${ik}$) ! Intrinsic Functions ! Executable Statements ! decode the input arguments if( stdlib_lsame( jobvsl, 'N' ) ) then ijobvl = 1_${ik}$ ilvsl = .false. else if( stdlib_lsame( jobvsl, 'V' ) ) then ijobvl = 2_${ik}$ ilvsl = .true. else ijobvl = -1_${ik}$ ilvsl = .false. end if if( stdlib_lsame( jobvsr, 'N' ) ) then ijobvr = 1_${ik}$ ilvsr = .false. else if( stdlib_lsame( jobvsr, 'V' ) ) then ijobvr = 2_${ik}$ ilvsr = .true. else ijobvr = -1_${ik}$ ilvsr = .false. end if wantst = stdlib_lsame( sort, 'S' ) ! test the input arguments info = 0_${ik}$ lquery = ( lwork==-1_${ik}$ ) if( ijobvl<=0_${ik}$ ) then info = -1_${ik}$ else if( ijobvr<=0_${ik}$ ) then info = -2_${ik}$ else if( ( .not.wantst ) .and. ( .not.stdlib_lsame( sort, 'N' ) ) ) then info = -3_${ik}$ else if( n<0_${ik}$ ) then info = -5_${ik}$ else if( lda<max( 1_${ik}$, n ) ) then info = -7_${ik}$ else if( ldb<max( 1_${ik}$, n ) ) then info = -9_${ik}$ else if( ldvsl<1_${ik}$ .or. ( ilvsl .and. ldvsl<n ) ) then info = -15_${ik}$ else if( ldvsr<1_${ik}$ .or. ( ilvsr .and. ldvsr<n ) ) then info = -17_${ik}$ else if( lwork<6_${ik}$*n+16 .and. .not.lquery ) then info = -19_${ik}$ end if ! compute workspace if( info==0_${ik}$ ) then call stdlib${ii}$_dgeqrf( n, n, b, ldb, work, work, -1_${ik}$, ierr ) lwkopt = max( 6_${ik}$*n+16, 3_${ik}$*n+int( work ( 1_${ik}$ ),KIND=${ik}$) ) call stdlib${ii}$_dormqr( 'L', 'T', n, n, n, b, ldb, work, a, lda, work,-1_${ik}$, ierr ) lwkopt = max( lwkopt, 3_${ik}$*n+int( work ( 1_${ik}$ ),KIND=${ik}$) ) if( ilvsl ) then call stdlib${ii}$_dorgqr( n, n, n, vsl, ldvsl, work, work, -1_${ik}$, ierr ) lwkopt = max( lwkopt, 3_${ik}$*n+int( work ( 1_${ik}$ ),KIND=${ik}$) ) end if call stdlib${ii}$_dgghd3( jobvsl, jobvsr, n, 1_${ik}$, n, a, lda, b, ldb, vsl,ldvsl, vsr, ldvsr, & work, -1_${ik}$, ierr ) lwkopt = max( lwkopt, 3_${ik}$*n+int( work ( 1_${ik}$ ),KIND=${ik}$) ) call stdlib${ii}$_dlaqz0( 'S', jobvsl, jobvsr, n, 1_${ik}$, n, a, lda, b, ldb,alphar, alphai, & beta, vsl, ldvsl, vsr, ldvsr,work, -1_${ik}$, 0_${ik}$, ierr ) lwkopt = max( lwkopt, 2_${ik}$*n+int( work ( 1_${ik}$ ),KIND=${ik}$) ) if( wantst ) then call stdlib${ii}$_dtgsen( 0_${ik}$, ilvsl, ilvsr, bwork, n, a, lda, b, ldb,alphar, alphai, & beta, vsl, ldvsl, vsr, ldvsr,sdim, pvsl, pvsr, dif, work, -1_${ik}$, idum, 1_${ik}$,ierr ) lwkopt = max( lwkopt, 2_${ik}$*n+int( work ( 1_${ik}$ ),KIND=${ik}$) ) end if work( 1_${ik}$ ) = lwkopt end if if( info/=0_${ik}$ ) then call stdlib${ii}$_xerbla( 'DGGES3 ', -info ) return else if( lquery ) then return end if ! quick return if possible if( n==0_${ik}$ ) then sdim = 0_${ik}$ return end if ! get machine constants eps = stdlib${ii}$_dlamch( 'P' ) safmin = stdlib${ii}$_dlamch( 'S' ) safmax = one / safmin call stdlib${ii}$_dlabad( safmin, safmax ) smlnum = sqrt( safmin ) / eps bignum = one / smlnum ! scale a if max element outside range [smlnum,bignum] anrm = stdlib${ii}$_dlange( 'M', n, n, a, lda, work ) ilascl = .false. if( anrm>zero .and. anrm<smlnum ) then anrmto = smlnum ilascl = .true. else if( anrm>bignum ) then anrmto = bignum ilascl = .true. end if if( ilascl )call stdlib${ii}$_dlascl( 'G', 0_${ik}$, 0_${ik}$, anrm, anrmto, n, n, a, lda, ierr ) ! scale b if max element outside range [smlnum,bignum] bnrm = stdlib${ii}$_dlange( 'M', n, n, b, ldb, work ) ilbscl = .false. if( bnrm>zero .and. bnrm<smlnum ) then bnrmto = smlnum ilbscl = .true. else if( bnrm>bignum ) then bnrmto = bignum ilbscl = .true. end if if( ilbscl )call stdlib${ii}$_dlascl( 'G', 0_${ik}$, 0_${ik}$, bnrm, bnrmto, n, n, b, ldb, ierr ) ! permute the matrix to make it more nearly triangular ileft = 1_${ik}$ iright = n + 1_${ik}$ iwrk = iright + n call stdlib${ii}$_dggbal( 'P', n, a, lda, b, ldb, ilo, ihi, work( ileft ),work( iright ), & work( iwrk ), ierr ) ! reduce b to triangular form (qr decomposition of b) irows = ihi + 1_${ik}$ - ilo icols = n + 1_${ik}$ - ilo itau = iwrk iwrk = itau + irows call stdlib${ii}$_dgeqrf( irows, icols, b( ilo, ilo ), ldb, work( itau ),work( iwrk ), lwork+& 1_${ik}$-iwrk, ierr ) ! apply the orthogonal transformation to matrix a call stdlib${ii}$_dormqr( 'L', 'T', irows, icols, irows, b( ilo, ilo ), ldb,work( itau ), a( & ilo, ilo ), lda, work( iwrk ),lwork+1-iwrk, ierr ) ! initialize vsl if( ilvsl ) then call stdlib${ii}$_dlaset( 'FULL', n, n, zero, one, vsl, ldvsl ) if( irows>1_${ik}$ ) then call stdlib${ii}$_dlacpy( 'L', irows-1, irows-1, b( ilo+1, ilo ), ldb,vsl( ilo+1, ilo )& , ldvsl ) end if call stdlib${ii}$_dorgqr( irows, irows, irows, vsl( ilo, ilo ), ldvsl,work( itau ), work( & iwrk ), lwork+1-iwrk, ierr ) end if ! initialize vsr if( ilvsr )call stdlib${ii}$_dlaset( 'FULL', n, n, zero, one, vsr, ldvsr ) ! reduce to generalized hessenberg form call stdlib${ii}$_dgghd3( jobvsl, jobvsr, n, ilo, ihi, a, lda, b, ldb, vsl,ldvsl, vsr, ldvsr,& work( iwrk ), lwork+1-iwrk,ierr ) ! perform qz algorithm, computing schur vectors if desired iwrk = itau call stdlib${ii}$_dlaqz0( 'S', jobvsl, jobvsr, n, ilo, ihi, a, lda, b, ldb,alphar, alphai, & beta, vsl, ldvsl, vsr, ldvsr,work( iwrk ), lwork+1-iwrk, 0_${ik}$, ierr ) if( ierr/=0_${ik}$ ) then if( ierr>0_${ik}$ .and. ierr<=n ) then info = ierr else if( ierr>n .and. ierr<=2_${ik}$*n ) then info = ierr - n else info = n + 1_${ik}$ end if go to 50 end if ! sort eigenvalues alpha/beta if desired sdim = 0_${ik}$ if( wantst ) then ! undo scaling on eigenvalues before selctging if( ilascl ) then call stdlib${ii}$_dlascl( 'G', 0_${ik}$, 0_${ik}$, anrmto, anrm, n, 1_${ik}$, alphar, n,ierr ) call stdlib${ii}$_dlascl( 'G', 0_${ik}$, 0_${ik}$, anrmto, anrm, n, 1_${ik}$, alphai, n,ierr ) end if if( ilbscl )call stdlib${ii}$_dlascl( 'G', 0_${ik}$, 0_${ik}$, bnrmto, bnrm, n, 1_${ik}$, beta, n, ierr ) ! select eigenvalues do i = 1, n bwork( i ) = selctg( alphar( i ), alphai( i ), beta( i ) ) end do call stdlib${ii}$_dtgsen( 0_${ik}$, ilvsl, ilvsr, bwork, n, a, lda, b, ldb, alphar,alphai, beta, & vsl, ldvsl, vsr, ldvsr, sdim, pvsl,pvsr, dif, work( iwrk ), lwork-iwrk+1, idum, 1_${ik}$,& ierr ) if( ierr==1_${ik}$ )info = n + 3_${ik}$ end if ! apply back-permutation to vsl and vsr if( ilvsl )call stdlib${ii}$_dggbak( 'P', 'L', n, ilo, ihi, work( ileft ),work( iright ), n, & vsl, ldvsl, ierr ) if( ilvsr )call stdlib${ii}$_dggbak( 'P', 'R', n, ilo, ihi, work( ileft ),work( iright ), n, & vsr, ldvsr, ierr ) ! check if unscaling would cause over/underflow, if so, rescale ! (alphar(i),alphai(i),beta(i)) so beta(i) is on the order of ! b(i,i) and alphar(i) and alphai(i) are on the order of a(i,i) if( ilascl ) then do i = 1, n if( alphai( i )/=zero ) then if( ( alphar( i ) / safmax )>( anrmto / anrm ) .or.( safmin / alphar( i ) )>( & anrm / anrmto ) ) then work( 1_${ik}$ ) = abs( a( i, i ) / alphar( i ) ) beta( i ) = beta( i )*work( 1_${ik}$ ) alphar( i ) = alphar( i )*work( 1_${ik}$ ) alphai( i ) = alphai( i )*work( 1_${ik}$ ) else if( ( alphai( i ) / safmax )>( anrmto / anrm ) .or.( safmin / alphai( i )& )>( anrm / anrmto ) )then work( 1_${ik}$ ) = abs( a( i, i+1 ) / alphai( i ) ) beta( i ) = beta( i )*work( 1_${ik}$ ) alphar( i ) = alphar( i )*work( 1_${ik}$ ) alphai( i ) = alphai( i )*work( 1_${ik}$ ) end if end if end do end if if( ilbscl ) then do i = 1, n if( alphai( i )/=zero ) then if( ( beta( i ) / safmax )>( bnrmto / bnrm ) .or.( safmin / beta( i ) )>( & bnrm / bnrmto ) ) then work( 1_${ik}$ ) = abs( b( i, i ) / beta( i ) ) beta( i ) = beta( i )*work( 1_${ik}$ ) alphar( i ) = alphar( i )*work( 1_${ik}$ ) alphai( i ) = alphai( i )*work( 1_${ik}$ ) end if end if end do end if ! undo scaling if( ilascl ) then call stdlib${ii}$_dlascl( 'H', 0_${ik}$, 0_${ik}$, anrmto, anrm, n, n, a, lda, ierr ) call stdlib${ii}$_dlascl( 'G', 0_${ik}$, 0_${ik}$, anrmto, anrm, n, 1_${ik}$, alphar, n, ierr ) call stdlib${ii}$_dlascl( 'G', 0_${ik}$, 0_${ik}$, anrmto, anrm, n, 1_${ik}$, alphai, n, ierr ) end if if( ilbscl ) then call stdlib${ii}$_dlascl( 'U', 0_${ik}$, 0_${ik}$, bnrmto, bnrm, n, n, b, ldb, ierr ) call stdlib${ii}$_dlascl( 'G', 0_${ik}$, 0_${ik}$, bnrmto, bnrm, n, 1_${ik}$, beta, n, ierr ) end if if( wantst ) then ! check if reordering is correct lastsl = .true. lst2sl = .true. sdim = 0_${ik}$ ip = 0_${ik}$ do i = 1, n cursl = selctg( alphar( i ), alphai( i ), beta( i ) ) if( alphai( i )==zero ) then if( cursl )sdim = sdim + 1_${ik}$ ip = 0_${ik}$ if( cursl .and. .not.lastsl )info = n + 2_${ik}$ else if( ip==1_${ik}$ ) then ! last eigenvalue of conjugate pair cursl = cursl .or. lastsl lastsl = cursl if( cursl )sdim = sdim + 2_${ik}$ ip = -1_${ik}$ if( cursl .and. .not.lst2sl )info = n + 2_${ik}$ else ! first eigenvalue of conjugate pair ip = 1_${ik}$ end if end if lst2sl = lastsl lastsl = cursl end do end if 50 continue work( 1_${ik}$ ) = lwkopt return end subroutine stdlib${ii}$_dgges3 #:for rk,rt,ri in REAL_KINDS_TYPES #:if not rk in ["sp","dp"] module subroutine stdlib${ii}$_${ri}$gges3( jobvsl, jobvsr, sort, selctg, n, a, lda, b,ldb, sdim, alphar, & !! DGGES3: computes for a pair of N-by-N real nonsymmetric matrices (A,B), !! the generalized eigenvalues, the generalized real Schur form (S,T), !! optionally, the left and/or right matrices of Schur vectors (VSL and !! VSR). This gives the generalized Schur factorization !! (A,B) = ( (VSL)*S*(VSR)**T, (VSL)*T*(VSR)**T ) !! Optionally, it also orders the eigenvalues so that a selected cluster !! of eigenvalues appears in the leading diagonal blocks of the upper !! quasi-triangular matrix S and the upper triangular matrix T.The !! leading columns of VSL and VSR then form an orthonormal basis for the !! corresponding left and right eigenspaces (deflating subspaces). !! (If only the generalized eigenvalues are needed, use the driver !! DGGEV instead, which is faster.) !! A generalized eigenvalue for a pair of matrices (A,B) is a scalar w !! or a ratio alpha/beta = w, such that A - w*B is singular. It is !! usually represented as the pair (alpha,beta), as there is a !! reasonable interpretation for beta=0 or both being zero. !! A pair of matrices (S,T) is in generalized real Schur form if T is !! upper triangular with non-negative diagonal and S is block upper !! triangular with 1-by-1 and 2-by-2 blocks. 1-by-1 blocks correspond !! to real generalized eigenvalues, while 2-by-2 blocks of S will be !! "standardized" by making the corresponding elements of T have the !! form: !! [ a 0 ] !! [ 0 b ] !! and the pair of corresponding 2-by-2 blocks in S and T will have a !! complex conjugate pair of generalized eigenvalues. alphai, beta, vsl, ldvsl,vsr, ldvsr, work, lwork, bwork, info ) ! -- lapack driver routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_${rk}$, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments character, intent(in) :: jobvsl, jobvsr, sort integer(${ik}$), intent(out) :: info, sdim integer(${ik}$), intent(in) :: lda, ldb, ldvsl, ldvsr, lwork, n ! Array Arguments logical(lk), intent(out) :: bwork(*) real(${rk}$), intent(inout) :: a(lda,*), b(ldb,*) real(${rk}$), intent(out) :: alphai(*), alphar(*), beta(*), vsl(ldvsl,*), vsr(ldvsr,*), & work(*) ! Function Arguments procedure(stdlib_selctg_${ri}$) :: selctg ! ===================================================================== ! Local Scalars logical(lk) :: cursl, ilascl, ilbscl, ilvsl, ilvsr, lastsl, lquery, lst2sl, & wantst integer(${ik}$) :: i, icols, ierr, ihi, ijobvl, ijobvr, ileft, ilo, ip, iright, irows, & itau, iwrk, lwkopt real(${rk}$) :: anrm, anrmto, bignum, bnrm, bnrmto, eps, pvsl, pvsr, safmax, safmin, & smlnum ! Local Arrays integer(${ik}$) :: idum(1_${ik}$) real(${rk}$) :: dif(2_${ik}$) ! Intrinsic Functions ! Executable Statements ! decode the input arguments if( stdlib_lsame( jobvsl, 'N' ) ) then ijobvl = 1_${ik}$ ilvsl = .false. else if( stdlib_lsame( jobvsl, 'V' ) ) then ijobvl = 2_${ik}$ ilvsl = .true. else ijobvl = -1_${ik}$ ilvsl = .false. end if if( stdlib_lsame( jobvsr, 'N' ) ) then ijobvr = 1_${ik}$ ilvsr = .false. else if( stdlib_lsame( jobvsr, 'V' ) ) then ijobvr = 2_${ik}$ ilvsr = .true. else ijobvr = -1_${ik}$ ilvsr = .false. end if wantst = stdlib_lsame( sort, 'S' ) ! test the input arguments info = 0_${ik}$ lquery = ( lwork==-1_${ik}$ ) if( ijobvl<=0_${ik}$ ) then info = -1_${ik}$ else if( ijobvr<=0_${ik}$ ) then info = -2_${ik}$ else if( ( .not.wantst ) .and. ( .not.stdlib_lsame( sort, 'N' ) ) ) then info = -3_${ik}$ else if( n<0_${ik}$ ) then info = -5_${ik}$ else if( lda<max( 1_${ik}$, n ) ) then info = -7_${ik}$ else if( ldb<max( 1_${ik}$, n ) ) then info = -9_${ik}$ else if( ldvsl<1_${ik}$ .or. ( ilvsl .and. ldvsl<n ) ) then info = -15_${ik}$ else if( ldvsr<1_${ik}$ .or. ( ilvsr .and. ldvsr<n ) ) then info = -17_${ik}$ else if( lwork<6_${ik}$*n+16 .and. .not.lquery ) then info = -19_${ik}$ end if ! compute workspace if( info==0_${ik}$ ) then call stdlib${ii}$_${ri}$geqrf( n, n, b, ldb, work, work, -1_${ik}$, ierr ) lwkopt = max( 6_${ik}$*n+16, 3_${ik}$*n+int( work ( 1_${ik}$ ),KIND=${ik}$) ) call stdlib${ii}$_${ri}$ormqr( 'L', 'T', n, n, n, b, ldb, work, a, lda, work,-1_${ik}$, ierr ) lwkopt = max( lwkopt, 3_${ik}$*n+int( work ( 1_${ik}$ ),KIND=${ik}$) ) if( ilvsl ) then call stdlib${ii}$_${ri}$orgqr( n, n, n, vsl, ldvsl, work, work, -1_${ik}$, ierr ) lwkopt = max( lwkopt, 3_${ik}$*n+int( work ( 1_${ik}$ ),KIND=${ik}$) ) end if call stdlib${ii}$_${ri}$gghd3( jobvsl, jobvsr, n, 1_${ik}$, n, a, lda, b, ldb, vsl,ldvsl, vsr, ldvsr, & work, -1_${ik}$, ierr ) lwkopt = max( lwkopt, 3_${ik}$*n+int( work ( 1_${ik}$ ),KIND=${ik}$) ) call stdlib${ii}$_${ri}$laqz0( 'S', jobvsl, jobvsr, n, 1_${ik}$, n, a, lda, b, ldb,alphar, alphai, & beta, vsl, ldvsl, vsr, ldvsr,work, -1_${ik}$, 0_${ik}$, ierr ) lwkopt = max( lwkopt, 2_${ik}$*n+int( work ( 1_${ik}$ ),KIND=${ik}$) ) if( wantst ) then call stdlib${ii}$_${ri}$tgsen( 0_${ik}$, ilvsl, ilvsr, bwork, n, a, lda, b, ldb,alphar, alphai, & beta, vsl, ldvsl, vsr, ldvsr,sdim, pvsl, pvsr, dif, work, -1_${ik}$, idum, 1_${ik}$,ierr ) lwkopt = max( lwkopt, 2_${ik}$*n+int( work ( 1_${ik}$ ),KIND=${ik}$) ) end if work( 1_${ik}$ ) = lwkopt end if if( info/=0_${ik}$ ) then call stdlib${ii}$_xerbla( 'DGGES3 ', -info ) return else if( lquery ) then return end if ! quick return if possible if( n==0_${ik}$ ) then sdim = 0_${ik}$ return end if ! get machine constants eps = stdlib${ii}$_${ri}$lamch( 'P' ) safmin = stdlib${ii}$_${ri}$lamch( 'S' ) safmax = one / safmin call stdlib${ii}$_${ri}$labad( safmin, safmax ) smlnum = sqrt( safmin ) / eps bignum = one / smlnum ! scale a if max element outside range [smlnum,bignum] anrm = stdlib${ii}$_${ri}$lange( 'M', n, n, a, lda, work ) ilascl = .false. if( anrm>zero .and. anrm<smlnum ) then anrmto = smlnum ilascl = .true. else if( anrm>bignum ) then anrmto = bignum ilascl = .true. end if if( ilascl )call stdlib${ii}$_${ri}$lascl( 'G', 0_${ik}$, 0_${ik}$, anrm, anrmto, n, n, a, lda, ierr ) ! scale b if max element outside range [smlnum,bignum] bnrm = stdlib${ii}$_${ri}$lange( 'M', n, n, b, ldb, work ) ilbscl = .false. if( bnrm>zero .and. bnrm<smlnum ) then bnrmto = smlnum ilbscl = .true. else if( bnrm>bignum ) then bnrmto = bignum ilbscl = .true. end if if( ilbscl )call stdlib${ii}$_${ri}$lascl( 'G', 0_${ik}$, 0_${ik}$, bnrm, bnrmto, n, n, b, ldb, ierr ) ! permute the matrix to make it more nearly triangular ileft = 1_${ik}$ iright = n + 1_${ik}$ iwrk = iright + n call stdlib${ii}$_${ri}$ggbal( 'P', n, a, lda, b, ldb, ilo, ihi, work( ileft ),work( iright ), & work( iwrk ), ierr ) ! reduce b to triangular form (qr decomposition of b) irows = ihi + 1_${ik}$ - ilo icols = n + 1_${ik}$ - ilo itau = iwrk iwrk = itau + irows call stdlib${ii}$_${ri}$geqrf( irows, icols, b( ilo, ilo ), ldb, work( itau ),work( iwrk ), lwork+& 1_${ik}$-iwrk, ierr ) ! apply the orthogonal transformation to matrix a call stdlib${ii}$_${ri}$ormqr( 'L', 'T', irows, icols, irows, b( ilo, ilo ), ldb,work( itau ), a( & ilo, ilo ), lda, work( iwrk ),lwork+1-iwrk, ierr ) ! initialize vsl if( ilvsl ) then call stdlib${ii}$_${ri}$laset( 'FULL', n, n, zero, one, vsl, ldvsl ) if( irows>1_${ik}$ ) then call stdlib${ii}$_${ri}$lacpy( 'L', irows-1, irows-1, b( ilo+1, ilo ), ldb,vsl( ilo+1, ilo )& , ldvsl ) end if call stdlib${ii}$_${ri}$orgqr( irows, irows, irows, vsl( ilo, ilo ), ldvsl,work( itau ), work( & iwrk ), lwork+1-iwrk, ierr ) end if ! initialize vsr if( ilvsr )call stdlib${ii}$_${ri}$laset( 'FULL', n, n, zero, one, vsr, ldvsr ) ! reduce to generalized hessenberg form call stdlib${ii}$_${ri}$gghd3( jobvsl, jobvsr, n, ilo, ihi, a, lda, b, ldb, vsl,ldvsl, vsr, ldvsr,& work( iwrk ), lwork+1-iwrk,ierr ) ! perform qz algorithm, computing schur vectors if desired iwrk = itau call stdlib${ii}$_${ri}$laqz0( 'S', jobvsl, jobvsr, n, ilo, ihi, a, lda, b, ldb,alphar, alphai, & beta, vsl, ldvsl, vsr, ldvsr,work( iwrk ), lwork+1-iwrk, 0_${ik}$, ierr ) if( ierr/=0_${ik}$ ) then if( ierr>0_${ik}$ .and. ierr<=n ) then info = ierr else if( ierr>n .and. ierr<=2_${ik}$*n ) then info = ierr - n else info = n + 1_${ik}$ end if go to 50 end if ! sort eigenvalues alpha/beta if desired sdim = 0_${ik}$ if( wantst ) then ! undo scaling on eigenvalues before selctging if( ilascl ) then call stdlib${ii}$_${ri}$lascl( 'G', 0_${ik}$, 0_${ik}$, anrmto, anrm, n, 1_${ik}$, alphar, n,ierr ) call stdlib${ii}$_${ri}$lascl( 'G', 0_${ik}$, 0_${ik}$, anrmto, anrm, n, 1_${ik}$, alphai, n,ierr ) end if if( ilbscl )call stdlib${ii}$_${ri}$lascl( 'G', 0_${ik}$, 0_${ik}$, bnrmto, bnrm, n, 1_${ik}$, beta, n, ierr ) ! select eigenvalues do i = 1, n bwork( i ) = selctg( alphar( i ), alphai( i ), beta( i ) ) end do call stdlib${ii}$_${ri}$tgsen( 0_${ik}$, ilvsl, ilvsr, bwork, n, a, lda, b, ldb, alphar,alphai, beta, & vsl, ldvsl, vsr, ldvsr, sdim, pvsl,pvsr, dif, work( iwrk ), lwork-iwrk+1, idum, 1_${ik}$,& ierr ) if( ierr==1_${ik}$ )info = n + 3_${ik}$ end if ! apply back-permutation to vsl and vsr if( ilvsl )call stdlib${ii}$_${ri}$ggbak( 'P', 'L', n, ilo, ihi, work( ileft ),work( iright ), n, & vsl, ldvsl, ierr ) if( ilvsr )call stdlib${ii}$_${ri}$ggbak( 'P', 'R', n, ilo, ihi, work( ileft ),work( iright ), n, & vsr, ldvsr, ierr ) ! check if unscaling would cause over/underflow, if so, rescale ! (alphar(i),alphai(i),beta(i)) so beta(i) is on the order of ! b(i,i) and alphar(i) and alphai(i) are on the order of a(i,i) if( ilascl ) then do i = 1, n if( alphai( i )/=zero ) then if( ( alphar( i ) / safmax )>( anrmto / anrm ) .or.( safmin / alphar( i ) )>( & anrm / anrmto ) ) then work( 1_${ik}$ ) = abs( a( i, i ) / alphar( i ) ) beta( i ) = beta( i )*work( 1_${ik}$ ) alphar( i ) = alphar( i )*work( 1_${ik}$ ) alphai( i ) = alphai( i )*work( 1_${ik}$ ) else if( ( alphai( i ) / safmax )>( anrmto / anrm ) .or.( safmin / alphai( i )& )>( anrm / anrmto ) )then work( 1_${ik}$ ) = abs( a( i, i+1 ) / alphai( i ) ) beta( i ) = beta( i )*work( 1_${ik}$ ) alphar( i ) = alphar( i )*work( 1_${ik}$ ) alphai( i ) = alphai( i )*work( 1_${ik}$ ) end if end if end do end if if( ilbscl ) then do i = 1, n if( alphai( i )/=zero ) then if( ( beta( i ) / safmax )>( bnrmto / bnrm ) .or.( safmin / beta( i ) )>( & bnrm / bnrmto ) ) then work( 1_${ik}$ ) = abs( b( i, i ) / beta( i ) ) beta( i ) = beta( i )*work( 1_${ik}$ ) alphar( i ) = alphar( i )*work( 1_${ik}$ ) alphai( i ) = alphai( i )*work( 1_${ik}$ ) end if end if end do end if ! undo scaling if( ilascl ) then call stdlib${ii}$_${ri}$lascl( 'H', 0_${ik}$, 0_${ik}$, anrmto, anrm, n, n, a, lda, ierr ) call stdlib${ii}$_${ri}$lascl( 'G', 0_${ik}$, 0_${ik}$, anrmto, anrm, n, 1_${ik}$, alphar, n, ierr ) call stdlib${ii}$_${ri}$lascl( 'G', 0_${ik}$, 0_${ik}$, anrmto, anrm, n, 1_${ik}$, alphai, n, ierr ) end if if( ilbscl ) then call stdlib${ii}$_${ri}$lascl( 'U', 0_${ik}$, 0_${ik}$, bnrmto, bnrm, n, n, b, ldb, ierr ) call stdlib${ii}$_${ri}$lascl( 'G', 0_${ik}$, 0_${ik}$, bnrmto, bnrm, n, 1_${ik}$, beta, n, ierr ) end if if( wantst ) then ! check if reordering is correct lastsl = .true. lst2sl = .true. sdim = 0_${ik}$ ip = 0_${ik}$ do i = 1, n cursl = selctg( alphar( i ), alphai( i ), beta( i ) ) if( alphai( i )==zero ) then if( cursl )sdim = sdim + 1_${ik}$ ip = 0_${ik}$ if( cursl .and. .not.lastsl )info = n + 2_${ik}$ else if( ip==1_${ik}$ ) then ! last eigenvalue of conjugate pair cursl = cursl .or. lastsl lastsl = cursl if( cursl )sdim = sdim + 2_${ik}$ ip = -1_${ik}$ if( cursl .and. .not.lst2sl )info = n + 2_${ik}$ else ! first eigenvalue of conjugate pair ip = 1_${ik}$ end if end if lst2sl = lastsl lastsl = cursl end do end if 50 continue work( 1_${ik}$ ) = lwkopt return end subroutine stdlib${ii}$_${ri}$gges3 #:endif #:endfor module subroutine stdlib${ii}$_cgges3( jobvsl, jobvsr, sort, selctg, n, a, lda, b,ldb, sdim, alpha, beta, & !! CGGES3 computes for a pair of N-by-N complex nonsymmetric matrices !! (A,B), the generalized eigenvalues, the generalized complex Schur !! form (S, T), and optionally left and/or right Schur vectors (VSL !! and VSR). This gives the generalized Schur factorization !! (A,B) = ( (VSL)*S*(VSR)**H, (VSL)*T*(VSR)**H ) !! where (VSR)**H is the conjugate-transpose of VSR. !! Optionally, it also orders the eigenvalues so that a selected cluster !! of eigenvalues appears in the leading diagonal blocks of the upper !! triangular matrix S and the upper triangular matrix T. The leading !! columns of VSL and VSR then form an unitary basis for the !! corresponding left and right eigenspaces (deflating subspaces). !! (If only the generalized eigenvalues are needed, use the driver !! CGGEV instead, which is faster.) !! A generalized eigenvalue for a pair of matrices (A,B) is a scalar w !! or a ratio alpha/beta = w, such that A - w*B is singular. It is !! usually represented as the pair (alpha,beta), as there is a !! reasonable interpretation for beta=0, and even for both being zero. !! A pair of matrices (S,T) is in generalized complex Schur form if S !! and T are upper triangular and, in addition, the diagonal elements !! of T are non-negative real numbers. vsl, ldvsl, vsr, ldvsr,work, lwork, rwork, bwork, info ) ! -- lapack driver routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_sp, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments character, intent(in) :: jobvsl, jobvsr, sort integer(${ik}$), intent(out) :: info, sdim integer(${ik}$), intent(in) :: lda, ldb, ldvsl, ldvsr, lwork, n ! Array Arguments logical(lk), intent(out) :: bwork(*) real(sp), intent(out) :: rwork(*) complex(sp), intent(inout) :: a(lda,*), b(ldb,*) complex(sp), intent(out) :: alpha(*), beta(*), vsl(ldvsl,*), vsr(ldvsr,*), work(*) ! Function Arguments procedure(stdlib_selctg_c) :: selctg ! ===================================================================== ! Local Scalars logical(lk) :: cursl, ilascl, ilbscl, ilvsl, ilvsr, lastsl, lquery, wantst integer(${ik}$) :: i, icols, ierr, ihi, ijobvl, ijobvr, ileft, ilo, iright, irows, irwrk, & itau, iwrk, lwkopt real(sp) :: anrm, anrmto, bignum, bnrm, bnrmto, eps, pvsl, pvsr, smlnum ! Local Arrays integer(${ik}$) :: idum(1_${ik}$) real(sp) :: dif(2_${ik}$) ! Intrinsic Functions ! Executable Statements ! decode the input arguments if( stdlib_lsame( jobvsl, 'N' ) ) then ijobvl = 1_${ik}$ ilvsl = .false. else if( stdlib_lsame( jobvsl, 'V' ) ) then ijobvl = 2_${ik}$ ilvsl = .true. else ijobvl = -1_${ik}$ ilvsl = .false. end if if( stdlib_lsame( jobvsr, 'N' ) ) then ijobvr = 1_${ik}$ ilvsr = .false. else if( stdlib_lsame( jobvsr, 'V' ) ) then ijobvr = 2_${ik}$ ilvsr = .true. else ijobvr = -1_${ik}$ ilvsr = .false. end if wantst = stdlib_lsame( sort, 'S' ) ! test the input arguments info = 0_${ik}$ lquery = ( lwork==-1_${ik}$ ) if( ijobvl<=0_${ik}$ ) then info = -1_${ik}$ else if( ijobvr<=0_${ik}$ ) then info = -2_${ik}$ else if( ( .not.wantst ) .and. ( .not.stdlib_lsame( sort, 'N' ) ) ) then info = -3_${ik}$ else if( n<0_${ik}$ ) then info = -5_${ik}$ else if( lda<max( 1_${ik}$, n ) ) then info = -7_${ik}$ else if( ldb<max( 1_${ik}$, n ) ) then info = -9_${ik}$ else if( ldvsl<1_${ik}$ .or. ( ilvsl .and. ldvsl<n ) ) then info = -14_${ik}$ else if( ldvsr<1_${ik}$ .or. ( ilvsr .and. ldvsr<n ) ) then info = -16_${ik}$ else if( lwork<max( 1_${ik}$, 2_${ik}$*n ) .and. .not.lquery ) then info = -18_${ik}$ end if ! compute workspace if( info==0_${ik}$ ) then call stdlib${ii}$_cgeqrf( n, n, b, ldb, work, work, -1_${ik}$, ierr ) lwkopt = max( 1_${ik}$, n + int( work( 1_${ik}$ ),KIND=${ik}$) ) call stdlib${ii}$_cunmqr( 'L', 'C', n, n, n, b, ldb, work, a, lda, work,-1_${ik}$, ierr ) lwkopt = max( lwkopt, n + int( work( 1_${ik}$ ),KIND=${ik}$) ) if( ilvsl ) then call stdlib${ii}$_cungqr( n, n, n, vsl, ldvsl, work, work, -1_${ik}$,ierr ) lwkopt = max( lwkopt, n + int( work( 1_${ik}$ ),KIND=${ik}$) ) end if call stdlib${ii}$_cgghd3( jobvsl, jobvsr, n, 1_${ik}$, n, a, lda, b, ldb, vsl,ldvsl, vsr, ldvsr, & work, -1_${ik}$, ierr ) lwkopt = max( lwkopt, n + int( work( 1_${ik}$ ),KIND=${ik}$) ) call stdlib${ii}$_claqz0( 'S', jobvsl, jobvsr, n, 1_${ik}$, n, a, lda, b, ldb,alpha, beta, vsl, & ldvsl, vsr, ldvsr, work, -1_${ik}$,rwork, 0_${ik}$, ierr ) lwkopt = max( lwkopt, int( work( 1_${ik}$ ),KIND=${ik}$) ) if( wantst ) then call stdlib${ii}$_ctgsen( 0_${ik}$, ilvsl, ilvsr, bwork, n, a, lda, b, ldb,alpha, beta, vsl, & ldvsl, vsr, ldvsr, sdim,pvsl, pvsr, dif, work, -1_${ik}$, idum, 1_${ik}$, ierr ) lwkopt = max( lwkopt, int( work( 1_${ik}$ ),KIND=${ik}$) ) end if work( 1_${ik}$ ) = cmplx( lwkopt,KIND=sp) end if if( info/=0_${ik}$ ) then call stdlib${ii}$_xerbla( 'CGGES3 ', -info ) return else if( lquery ) then return end if ! quick return if possible if( n==0_${ik}$ ) then sdim = 0_${ik}$ return end if ! get machine constants eps = stdlib${ii}$_slamch( 'P' ) smlnum = stdlib${ii}$_slamch( 'S' ) bignum = one / smlnum call stdlib${ii}$_slabad( smlnum, bignum ) smlnum = sqrt( smlnum ) / eps bignum = one / smlnum ! scale a if max element outside range [smlnum,bignum] anrm = stdlib${ii}$_clange( 'M', n, n, a, lda, rwork ) ilascl = .false. if( anrm>zero .and. anrm<smlnum ) then anrmto = smlnum ilascl = .true. else if( anrm>bignum ) then anrmto = bignum ilascl = .true. end if if( ilascl )call stdlib${ii}$_clascl( 'G', 0_${ik}$, 0_${ik}$, anrm, anrmto, n, n, a, lda, ierr ) ! scale b if max element outside range [smlnum,bignum] bnrm = stdlib${ii}$_clange( 'M', n, n, b, ldb, rwork ) ilbscl = .false. if( bnrm>zero .and. bnrm<smlnum ) then bnrmto = smlnum ilbscl = .true. else if( bnrm>bignum ) then bnrmto = bignum ilbscl = .true. end if if( ilbscl )call stdlib${ii}$_clascl( 'G', 0_${ik}$, 0_${ik}$, bnrm, bnrmto, n, n, b, ldb, ierr ) ! permute the matrix to make it more nearly triangular ileft = 1_${ik}$ iright = n + 1_${ik}$ irwrk = iright + n call stdlib${ii}$_cggbal( 'P', n, a, lda, b, ldb, ilo, ihi, rwork( ileft ),rwork( iright ), & rwork( irwrk ), ierr ) ! reduce b to triangular form (qr decomposition of b) irows = ihi + 1_${ik}$ - ilo icols = n + 1_${ik}$ - ilo itau = 1_${ik}$ iwrk = itau + irows call stdlib${ii}$_cgeqrf( irows, icols, b( ilo, ilo ), ldb, work( itau ),work( iwrk ), lwork+& 1_${ik}$-iwrk, ierr ) ! apply the orthogonal transformation to matrix a call stdlib${ii}$_cunmqr( 'L', 'C', irows, icols, irows, b( ilo, ilo ), ldb,work( itau ), a( & ilo, ilo ), lda, work( iwrk ),lwork+1-iwrk, ierr ) ! initialize vsl if( ilvsl ) then call stdlib${ii}$_claset( 'FULL', n, n, czero, cone, vsl, ldvsl ) if( irows>1_${ik}$ ) then call stdlib${ii}$_clacpy( 'L', irows-1, irows-1, b( ilo+1, ilo ), ldb,vsl( ilo+1, ilo )& , ldvsl ) end if call stdlib${ii}$_cungqr( irows, irows, irows, vsl( ilo, ilo ), ldvsl,work( itau ), work( & iwrk ), lwork+1-iwrk, ierr ) end if ! initialize vsr if( ilvsr )call stdlib${ii}$_claset( 'FULL', n, n, czero, cone, vsr, ldvsr ) ! reduce to generalized hessenberg form call stdlib${ii}$_cgghd3( jobvsl, jobvsr, n, ilo, ihi, a, lda, b, ldb, vsl,ldvsl, vsr, ldvsr,& work( iwrk ), lwork+1-iwrk, ierr ) sdim = 0_${ik}$ ! perform qz algorithm, computing schur vectors if desired iwrk = itau call stdlib${ii}$_claqz0( 'S', jobvsl, jobvsr, n, ilo, ihi, a, lda, b, ldb,alpha, beta, vsl, & ldvsl, vsr, ldvsr, work( iwrk ),lwork+1-iwrk, rwork( irwrk ), 0_${ik}$, ierr ) if( ierr/=0_${ik}$ ) then if( ierr>0_${ik}$ .and. ierr<=n ) then info = ierr else if( ierr>n .and. ierr<=2_${ik}$*n ) then info = ierr - n else info = n + 1_${ik}$ end if go to 30 end if ! sort eigenvalues alpha/beta if desired if( wantst ) then ! undo scaling on eigenvalues before selecting if( ilascl )call stdlib${ii}$_clascl( 'G', 0_${ik}$, 0_${ik}$, anrm, anrmto, n, 1_${ik}$, alpha, n, ierr ) if( ilbscl )call stdlib${ii}$_clascl( 'G', 0_${ik}$, 0_${ik}$, bnrm, bnrmto, n, 1_${ik}$, beta, n, ierr ) ! select eigenvalues do i = 1, n bwork( i ) = selctg( alpha( i ), beta( i ) ) end do call stdlib${ii}$_ctgsen( 0_${ik}$, ilvsl, ilvsr, bwork, n, a, lda, b, ldb, alpha,beta, vsl, & ldvsl, vsr, ldvsr, sdim, pvsl, pvsr,dif, work( iwrk ), lwork-iwrk+1, idum, 1_${ik}$, ierr ) if( ierr==1_${ik}$ )info = n + 3_${ik}$ end if ! apply back-permutation to vsl and vsr if( ilvsl )call stdlib${ii}$_cggbak( 'P', 'L', n, ilo, ihi, rwork( ileft ),rwork( iright ), & n, vsl, ldvsl, ierr ) if( ilvsr )call stdlib${ii}$_cggbak( 'P', 'R', n, ilo, ihi, rwork( ileft ),rwork( iright ), & n, vsr, ldvsr, ierr ) ! undo scaling if( ilascl )