#:include "common.fypp" submodule(stdlib_lapack_eig_svd_lsq) stdlib_lapack_eigv_std_driver implicit none contains #:for ik,it,ii in LINALG_INT_KINDS_TYPES module subroutine stdlib${ii}$_ssyev( jobz, uplo, n, a, lda, w, work, lwork, info ) !! SSYEV computes all eigenvalues and, optionally, eigenvectors of a !! real symmetric matrix A. ! -- 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) :: jobz, uplo integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: lda, lwork, n ! Array Arguments real(sp), intent(inout) :: a(lda,*) real(sp), intent(out) :: w(*), work(*) ! ===================================================================== ! Local Scalars logical(lk) :: lower, lquery, wantz integer(${ik}$) :: iinfo, imax, inde, indtau, indwrk, iscale, llwork, lwkopt, nb real(sp) :: anrm, bignum, eps, rmax, rmin, safmin, sigma, smlnum ! Intrinsic Functions ! Executable Statements ! test the input parameters. wantz = stdlib_lsame( jobz, 'V' ) lower = stdlib_lsame( uplo, 'L' ) lquery = ( lwork==-1_${ik}$ ) info = 0_${ik}$ if( .not.( wantz .or. stdlib_lsame( jobz, 'N' ) ) ) then info = -1_${ik}$ else if( .not.( lower .or. stdlib_lsame( uplo, 'U' ) ) ) then info = -2_${ik}$ else if( n<0_${ik}$ ) then info = -3_${ik}$ else if( lda<max( 1_${ik}$, n ) ) then info = -5_${ik}$ end if if( info==0_${ik}$ ) then nb = stdlib${ii}$_ilaenv( 1_${ik}$, 'SSYTRD', uplo, n, -1_${ik}$, -1_${ik}$, -1_${ik}$ ) lwkopt = max( 1_${ik}$, ( nb+2 )*n ) work( 1_${ik}$ ) = lwkopt if( lwork<max( 1_${ik}$, 3_${ik}$*n-1 ) .and. .not.lquery )info = -8_${ik}$ end if if( info/=0_${ik}$ ) then call stdlib${ii}$_xerbla( 'SSYEV ', -info ) return else if( lquery ) then return end if ! quick return if possible if( n==0_${ik}$ ) then return end if if( n==1_${ik}$ ) then w( 1_${ik}$ ) = a( 1_${ik}$, 1_${ik}$ ) work( 1_${ik}$ ) = 2_${ik}$ if( wantz )a( 1_${ik}$, 1_${ik}$ ) = one return end if ! get machine constants. safmin = stdlib${ii}$_slamch( 'SAFE MINIMUM' ) eps = stdlib${ii}$_slamch( 'PRECISION' ) smlnum = safmin / eps bignum = one / smlnum rmin = sqrt( smlnum ) rmax = sqrt( bignum ) ! scale matrix to allowable range, if necessary. anrm = stdlib${ii}$_slansy( 'M', uplo, n, a, lda, work ) iscale = 0_${ik}$ if( anrm>zero .and. anrm<rmin ) then iscale = 1_${ik}$ sigma = rmin / anrm else if( anrm>rmax ) then iscale = 1_${ik}$ sigma = rmax / anrm end if if( iscale==1_${ik}$ )call stdlib${ii}$_slascl( uplo, 0_${ik}$, 0_${ik}$, one, sigma, n, n, a, lda, info ) ! call stdlib${ii}$_ssytrd to reduce symmetric matrix to tridiagonal form. inde = 1_${ik}$ indtau = inde + n indwrk = indtau + n llwork = lwork - indwrk + 1_${ik}$ call stdlib${ii}$_ssytrd( uplo, n, a, lda, w, work( inde ), work( indtau ),work( indwrk ), & llwork, iinfo ) ! for eigenvalues only, call stdlib${ii}$_ssterf. for eigenvectors, first call ! stdlib${ii}$_sorgtr to generate the orthogonal matrix, then call stdlib${ii}$_ssteqr. if( .not.wantz ) then call stdlib${ii}$_ssterf( n, w, work( inde ), info ) else call stdlib${ii}$_sorgtr( uplo, n, a, lda, work( indtau ), work( indwrk ),llwork, iinfo ) call stdlib${ii}$_ssteqr( jobz, n, w, work( inde ), a, lda, work( indtau ),info ) end if ! if matrix was scaled, then rescale eigenvalues appropriately. if( iscale==1_${ik}$ ) then if( info==0_${ik}$ ) then imax = n else imax = info - 1_${ik}$ end if call stdlib${ii}$_sscal( imax, one / sigma, w, 1_${ik}$ ) end if ! set work(1) to optimal workspace size. work( 1_${ik}$ ) = lwkopt return end subroutine stdlib${ii}$_ssyev module subroutine stdlib${ii}$_dsyev( jobz, uplo, n, a, lda, w, work, lwork, info ) !! DSYEV computes all eigenvalues and, optionally, eigenvectors of a !! real symmetric matrix A. ! -- 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) :: jobz, uplo integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: lda, lwork, n ! Array Arguments real(dp), intent(inout) :: a(lda,*) real(dp), intent(out) :: w(*), work(*) ! ===================================================================== ! Local Scalars logical(lk) :: lower, lquery, wantz integer(${ik}$) :: iinfo, imax, inde, indtau, indwrk, iscale, llwork, lwkopt, nb real(dp) :: anrm, bignum, eps, rmax, rmin, safmin, sigma, smlnum ! Intrinsic Functions ! Executable Statements ! test the input parameters. wantz = stdlib_lsame( jobz, 'V' ) lower = stdlib_lsame( uplo, 'L' ) lquery = ( lwork==-1_${ik}$ ) info = 0_${ik}$ if( .not.( wantz .or. stdlib_lsame( jobz, 'N' ) ) ) then info = -1_${ik}$ else if( .not.( lower .or. stdlib_lsame( uplo, 'U' ) ) ) then info = -2_${ik}$ else if( n<0_${ik}$ ) then info = -3_${ik}$ else if( lda<max( 1_${ik}$, n ) ) then info = -5_${ik}$ end if if( info==0_${ik}$ ) then nb = stdlib${ii}$_ilaenv( 1_${ik}$, 'DSYTRD', uplo, n, -1_${ik}$, -1_${ik}$, -1_${ik}$ ) lwkopt = max( 1_${ik}$, ( nb+2 )*n ) work( 1_${ik}$ ) = lwkopt if( lwork<max( 1_${ik}$, 3_${ik}$*n-1 ) .and. .not.lquery )info = -8_${ik}$ end if if( info/=0_${ik}$ ) then call stdlib${ii}$_xerbla( 'DSYEV ', -info ) return else if( lquery ) then return end if ! quick return if possible if( n==0_${ik}$ ) then return end if if( n==1_${ik}$ ) then w( 1_${ik}$ ) = a( 1_${ik}$, 1_${ik}$ ) work( 1_${ik}$ ) = 2_${ik}$ if( wantz )a( 1_${ik}$, 1_${ik}$ ) = one return end if ! get machine constants. safmin = stdlib${ii}$_dlamch( 'SAFE MINIMUM' ) eps = stdlib${ii}$_dlamch( 'PRECISION' ) smlnum = safmin / eps bignum = one / smlnum rmin = sqrt( smlnum ) rmax = sqrt( bignum ) ! scale matrix to allowable range, if necessary. anrm = stdlib${ii}$_dlansy( 'M', uplo, n, a, lda, work ) iscale = 0_${ik}$ if( anrm>zero .and. anrm<rmin ) then iscale = 1_${ik}$ sigma = rmin / anrm else if( anrm>rmax ) then iscale = 1_${ik}$ sigma = rmax / anrm end if if( iscale==1_${ik}$ )call stdlib${ii}$_dlascl( uplo, 0_${ik}$, 0_${ik}$, one, sigma, n, n, a, lda, info ) ! call stdlib${ii}$_dsytrd to reduce symmetric matrix to tridiagonal form. inde = 1_${ik}$ indtau = inde + n indwrk = indtau + n llwork = lwork - indwrk + 1_${ik}$ call stdlib${ii}$_dsytrd( uplo, n, a, lda, w, work( inde ), work( indtau ),work( indwrk ), & llwork, iinfo ) ! for eigenvalues only, call stdlib${ii}$_dsterf. for eigenvectors, first call ! stdlib${ii}$_dorgtr to generate the orthogonal matrix, then call stdlib${ii}$_dsteqr. if( .not.wantz ) then call stdlib${ii}$_dsterf( n, w, work( inde ), info ) else call stdlib${ii}$_dorgtr( uplo, n, a, lda, work( indtau ), work( indwrk ),llwork, iinfo ) call stdlib${ii}$_dsteqr( jobz, n, w, work( inde ), a, lda, work( indtau ),info ) end if ! if matrix was scaled, then rescale eigenvalues appropriately. if( iscale==1_${ik}$ ) then if( info==0_${ik}$ ) then imax = n else imax = info - 1_${ik}$ end if call stdlib${ii}$_dscal( imax, one / sigma, w, 1_${ik}$ ) end if ! set work(1) to optimal workspace size. work( 1_${ik}$ ) = lwkopt return end subroutine stdlib${ii}$_dsyev #:for rk,rt,ri in REAL_KINDS_TYPES #:if not rk in ["sp","dp"] module subroutine stdlib${ii}$_${ri}$syev( jobz, uplo, n, a, lda, w, work, lwork, info ) !! DSYEV: computes all eigenvalues and, optionally, eigenvectors of a !! real symmetric matrix A. ! -- 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) :: jobz, uplo integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: lda, lwork, n ! Array Arguments real(${rk}$), intent(inout) :: a(lda,*) real(${rk}$), intent(out) :: w(*), work(*) ! ===================================================================== ! Local Scalars logical(lk) :: lower, lquery, wantz integer(${ik}$) :: iinfo, imax, inde, indtau, indwrk, iscale, llwork, lwkopt, nb real(${rk}$) :: anrm, bignum, eps, rmax, rmin, safmin, sigma, smlnum ! Intrinsic Functions ! Executable Statements ! test the input parameters. wantz = stdlib_lsame( jobz, 'V' ) lower = stdlib_lsame( uplo, 'L' ) lquery = ( lwork==-1_${ik}$ ) info = 0_${ik}$ if( .not.( wantz .or. stdlib_lsame( jobz, 'N' ) ) ) then info = -1_${ik}$ else if( .not.( lower .or. stdlib_lsame( uplo, 'U' ) ) ) then info = -2_${ik}$ else if( n<0_${ik}$ ) then info = -3_${ik}$ else if( lda<max( 1_${ik}$, n ) ) then info = -5_${ik}$ end if if( info==0_${ik}$ ) then nb = stdlib${ii}$_ilaenv( 1_${ik}$, 'DSYTRD', uplo, n, -1_${ik}$, -1_${ik}$, -1_${ik}$ ) lwkopt = max( 1_${ik}$, ( nb+2 )*n ) work( 1_${ik}$ ) = lwkopt if( lwork<max( 1_${ik}$, 3_${ik}$*n-1 ) .and. .not.lquery )info = -8_${ik}$ end if if( info/=0_${ik}$ ) then call stdlib${ii}$_xerbla( 'DSYEV ', -info ) return else if( lquery ) then return end if ! quick return if possible if( n==0_${ik}$ ) then return end if if( n==1_${ik}$ ) then w( 1_${ik}$ ) = a( 1_${ik}$, 1_${ik}$ ) work( 1_${ik}$ ) = 2_${ik}$ if( wantz )a( 1_${ik}$, 1_${ik}$ ) = one return end if ! get machine constants. safmin = stdlib${ii}$_${ri}$lamch( 'SAFE MINIMUM' ) eps = stdlib${ii}$_${ri}$lamch( 'PRECISION' ) smlnum = safmin / eps bignum = one / smlnum rmin = sqrt( smlnum ) rmax = sqrt( bignum ) ! scale matrix to allowable range, if necessary. anrm = stdlib${ii}$_${ri}$lansy( 'M', uplo, n, a, lda, work ) iscale = 0_${ik}$ if( anrm>zero .and. anrm<rmin ) then iscale = 1_${ik}$ sigma = rmin / anrm else if( anrm>rmax ) then iscale = 1_${ik}$ sigma = rmax / anrm end if if( iscale==1_${ik}$ )call stdlib${ii}$_${ri}$lascl( uplo, 0_${ik}$, 0_${ik}$, one, sigma, n, n, a, lda, info ) ! call stdlib${ii}$_${ri}$sytrd to reduce symmetric matrix to tridiagonal form. inde = 1_${ik}$ indtau = inde + n indwrk = indtau + n llwork = lwork - indwrk + 1_${ik}$ call stdlib${ii}$_${ri}$sytrd( uplo, n, a, lda, w, work( inde ), work( indtau ),work( indwrk ), & llwork, iinfo ) ! for eigenvalues only, call stdlib${ii}$_${ri}$sterf. for eigenvectors, first call ! stdlib${ii}$_${ri}$orgtr to generate the orthogonal matrix, then call stdlib${ii}$_${ri}$steqr. if( .not.wantz ) then call stdlib${ii}$_${ri}$sterf( n, w, work( inde ), info ) else call stdlib${ii}$_${ri}$orgtr( uplo, n, a, lda, work( indtau ), work( indwrk ),llwork, iinfo ) call stdlib${ii}$_${ri}$steqr( jobz, n, w, work( inde ), a, lda, work( indtau ),info ) end if ! if matrix was scaled, then rescale eigenvalues appropriately. if( iscale==1_${ik}$ ) then if( info==0_${ik}$ ) then imax = n else imax = info - 1_${ik}$ end if call stdlib${ii}$_${ri}$scal( imax, one / sigma, w, 1_${ik}$ ) end if ! set work(1) to optimal workspace size. work( 1_${ik}$ ) = lwkopt return end subroutine stdlib${ii}$_${ri}$syev #:endif #:endfor module subroutine stdlib${ii}$_ssyevd( jobz, uplo, n, a, lda, w, work, lwork, iwork,liwork, info ) !! SSYEVD computes all eigenvalues and, optionally, eigenvectors of a !! real symmetric matrix A. If eigenvectors are desired, it uses a !! divide and conquer algorithm. !! The divide and conquer algorithm makes very mild assumptions about !! floating point arithmetic. It will work on machines with a guard !! digit in add/subtract, or on those binary machines without guard !! digits which subtract like the Cray X-MP, Cray Y-MP, Cray C-90, or !! Cray-2. It could conceivably fail on hexadecimal or decimal machines !! without guard digits, but we know of none. !! Because of large use of BLAS of level 3, SSYEVD needs N**2 more !! workspace than SSYEVX. ! -- 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) :: jobz, uplo integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: lda, liwork, lwork, n ! Array Arguments integer(${ik}$), intent(out) :: iwork(*) real(sp), intent(inout) :: a(lda,*) real(sp), intent(out) :: w(*), work(*) ! ===================================================================== ! Local Scalars logical(lk) :: lower, lquery, wantz integer(${ik}$) :: iinfo, inde, indtau, indwk2, indwrk, iscale, liopt, liwmin, llwork, & llwrk2, lopt, lwmin real(sp) :: anrm, bignum, eps, rmax, rmin, safmin, sigma, smlnum ! Intrinsic Functions ! Executable Statements ! test the input parameters. wantz = stdlib_lsame( jobz, 'V' ) lower = stdlib_lsame( uplo, 'L' ) lquery = ( lwork==-1_${ik}$ .or. liwork==-1_${ik}$ ) info = 0_${ik}$ if( .not.( wantz .or. stdlib_lsame( jobz, 'N' ) ) ) then info = -1_${ik}$ else if( .not.( lower .or. stdlib_lsame( uplo, 'U' ) ) ) then info = -2_${ik}$ else if( n<0_${ik}$ ) then info = -3_${ik}$ else if( lda<max( 1_${ik}$, n ) ) then info = -5_${ik}$ end if if( info==0_${ik}$ ) then if( n<=1_${ik}$ ) then liwmin = 1_${ik}$ lwmin = 1_${ik}$ lopt = lwmin liopt = liwmin else if( wantz ) then liwmin = 3_${ik}$ + 5_${ik}$*n lwmin = 1_${ik}$ + 6_${ik}$*n + 2_${ik}$*n**2_${ik}$ else liwmin = 1_${ik}$ lwmin = 2_${ik}$*n + 1_${ik}$ end if lopt = max( lwmin, 2_${ik}$*n +stdlib${ii}$_ilaenv( 1_${ik}$, 'SSYTRD', uplo, n, -1_${ik}$, -1_${ik}$, -1_${ik}$ ) ) liopt = liwmin end if work( 1_${ik}$ ) = lopt iwork( 1_${ik}$ ) = liopt if( lwork<lwmin .and. .not.lquery ) then info = -8_${ik}$ else if( liwork<liwmin .and. .not.lquery ) then info = -10_${ik}$ end if end if if( info/=0_${ik}$ ) then call stdlib${ii}$_xerbla( 'SSYEVD', -info ) return else if( lquery ) then return end if ! quick return if possible if( n==0 )return if( n==1_${ik}$ ) then w( 1_${ik}$ ) = a( 1_${ik}$, 1_${ik}$ ) if( wantz )a( 1_${ik}$, 1_${ik}$ ) = one return end if ! get machine constants. safmin = stdlib${ii}$_slamch( 'SAFE MINIMUM' ) eps = stdlib${ii}$_slamch( 'PRECISION' ) smlnum = safmin / eps bignum = one / smlnum rmin = sqrt( smlnum ) rmax = sqrt( bignum ) ! scale matrix to allowable range, if necessary. anrm = stdlib${ii}$_slansy( 'M', uplo, n, a, lda, work ) iscale = 0_${ik}$ if( anrm>zero .and. anrm<rmin ) then iscale = 1_${ik}$ sigma = rmin / anrm else if( anrm>rmax ) then iscale = 1_${ik}$ sigma = rmax / anrm end if if( iscale==1_${ik}$ )call stdlib${ii}$_slascl( uplo, 0_${ik}$, 0_${ik}$, one, sigma, n, n, a, lda, info ) ! call stdlib${ii}$_ssytrd to reduce symmetric matrix to tridiagonal form. inde = 1_${ik}$ indtau = inde + n indwrk = indtau + n llwork = lwork - indwrk + 1_${ik}$ indwk2 = indwrk + n*n llwrk2 = lwork - indwk2 + 1_${ik}$ call stdlib${ii}$_ssytrd( uplo, n, a, lda, w, work( inde ), work( indtau ),work( indwrk ), & llwork, iinfo ) ! for eigenvalues only, call stdlib${ii}$_ssterf. for eigenvectors, first call ! stdlib${ii}$_sstedc to generate the eigenvector matrix, work(indwrk), of the ! tridiagonal matrix, then call stdlib${ii}$_sormtr to multiply it by the ! householder transformations stored in a. if( .not.wantz ) then call stdlib${ii}$_ssterf( n, w, work( inde ), info ) else call stdlib${ii}$_sstedc( 'I', n, w, work( inde ), work( indwrk ), n,work( indwk2 ), & llwrk2, iwork, liwork, info ) call stdlib${ii}$_sormtr( 'L', uplo, 'N', n, n, a, lda, work( indtau ),work( indwrk ), n, & work( indwk2 ), llwrk2, iinfo ) call stdlib${ii}$_slacpy( 'A', n, n, work( indwrk ), n, a, lda ) end if ! if matrix was scaled, then rescale eigenvalues appropriately. if( iscale==1_${ik}$ )call stdlib${ii}$_sscal( n, one / sigma, w, 1_${ik}$ ) work( 1_${ik}$ ) = lopt iwork( 1_${ik}$ ) = liopt return end subroutine stdlib${ii}$_ssyevd module subroutine stdlib${ii}$_dsyevd( jobz, uplo, n, a, lda, w, work, lwork, iwork,liwork, info ) !! DSYEVD computes all eigenvalues and, optionally, eigenvectors of a !! real symmetric matrix A. If eigenvectors are desired, it uses a !! divide and conquer algorithm. !! The divide and conquer algorithm makes very mild assumptions about !! floating point arithmetic. It will work on machines with a guard !! digit in add/subtract, or on those binary machines without guard !! digits which subtract like the Cray X-MP, Cray Y-MP, Cray C-90, or !! Cray-2. It could conceivably fail on hexadecimal or decimal machines !! without guard digits, but we know of none. !! Because of large use of BLAS of level 3, DSYEVD needs N**2 more !! workspace than DSYEVX. ! -- 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) :: jobz, uplo integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: lda, liwork, lwork, n ! Array Arguments integer(${ik}$), intent(out) :: iwork(*) real(dp), intent(inout) :: a(lda,*) real(dp), intent(out) :: w(*), work(*) ! ===================================================================== ! Local Scalars logical(lk) :: lower, lquery, wantz integer(${ik}$) :: iinfo, inde, indtau, indwk2, indwrk, iscale, liopt, liwmin, llwork, & llwrk2, lopt, lwmin real(dp) :: anrm, bignum, eps, rmax, rmin, safmin, sigma, smlnum ! Intrinsic Functions ! Executable Statements ! test the input parameters. wantz = stdlib_lsame( jobz, 'V' ) lower = stdlib_lsame( uplo, 'L' ) lquery = ( lwork==-1_${ik}$ .or. liwork==-1_${ik}$ ) info = 0_${ik}$ if( .not.( wantz .or. stdlib_lsame( jobz, 'N' ) ) ) then info = -1_${ik}$ else if( .not.( lower .or. stdlib_lsame( uplo, 'U' ) ) ) then info = -2_${ik}$ else if( n<0_${ik}$ ) then info = -3_${ik}$ else if( lda<max( 1_${ik}$, n ) ) then info = -5_${ik}$ end if if( info==0_${ik}$ ) then if( n<=1_${ik}$ ) then liwmin = 1_${ik}$ lwmin = 1_${ik}$ lopt = lwmin liopt = liwmin else if( wantz ) then liwmin = 3_${ik}$ + 5_${ik}$*n lwmin = 1_${ik}$ + 6_${ik}$*n + 2_${ik}$*n**2_${ik}$ else liwmin = 1_${ik}$ lwmin = 2_${ik}$*n + 1_${ik}$ end if lopt = max( lwmin, 2_${ik}$*n +stdlib${ii}$_ilaenv( 1_${ik}$, 'DSYTRD', uplo, n, -1_${ik}$, -1_${ik}$, -1_${ik}$ ) ) liopt = liwmin end if work( 1_${ik}$ ) = lopt iwork( 1_${ik}$ ) = liopt if( lwork<lwmin .and. .not.lquery ) then info = -8_${ik}$ else if( liwork<liwmin .and. .not.lquery ) then info = -10_${ik}$ end if end if if( info/=0_${ik}$ ) then call stdlib${ii}$_xerbla( 'DSYEVD', -info ) return else if( lquery ) then return end if ! quick return if possible if( n==0 )return if( n==1_${ik}$ ) then w( 1_${ik}$ ) = a( 1_${ik}$, 1_${ik}$ ) if( wantz )a( 1_${ik}$, 1_${ik}$ ) = one return end if ! get machine constants. safmin = stdlib${ii}$_dlamch( 'SAFE MINIMUM' ) eps = stdlib${ii}$_dlamch( 'PRECISION' ) smlnum = safmin / eps bignum = one / smlnum rmin = sqrt( smlnum ) rmax = sqrt( bignum ) ! scale matrix to allowable range, if necessary. anrm = stdlib${ii}$_dlansy( 'M', uplo, n, a, lda, work ) iscale = 0_${ik}$ if( anrm>zero .and. anrm<rmin ) then iscale = 1_${ik}$ sigma = rmin / anrm else if( anrm>rmax ) then iscale = 1_${ik}$ sigma = rmax / anrm end if if( iscale==1_${ik}$ )call stdlib${ii}$_dlascl( uplo, 0_${ik}$, 0_${ik}$, one, sigma, n, n, a, lda, info ) ! call stdlib${ii}$_dsytrd to reduce symmetric matrix to tridiagonal form. inde = 1_${ik}$ indtau = inde + n indwrk = indtau + n llwork = lwork - indwrk + 1_${ik}$ indwk2 = indwrk + n*n llwrk2 = lwork - indwk2 + 1_${ik}$ call stdlib${ii}$_dsytrd( uplo, n, a, lda, w, work( inde ), work( indtau ),work( indwrk ), & llwork, iinfo ) ! for eigenvalues only, call stdlib${ii}$_dsterf. for eigenvectors, first call ! stdlib${ii}$_dstedc to generate the eigenvector matrix, work(indwrk), of the ! tridiagonal matrix, then call stdlib${ii}$_dormtr to multiply it by the ! householder transformations stored in a. if( .not.wantz ) then call stdlib${ii}$_dsterf( n, w, work( inde ), info ) else call stdlib${ii}$_dstedc( 'I', n, w, work( inde ), work( indwrk ), n,work( indwk2 ), & llwrk2, iwork, liwork, info ) call stdlib${ii}$_dormtr( 'L', uplo, 'N', n, n, a, lda, work( indtau ),work( indwrk ), n, & work( indwk2 ), llwrk2, iinfo ) call stdlib${ii}$_dlacpy( 'A', n, n, work( indwrk ), n, a, lda ) end if ! if matrix was scaled, then rescale eigenvalues appropriately. if( iscale==1_${ik}$ )call stdlib${ii}$_dscal( n, one / sigma, w, 1_${ik}$ ) work( 1_${ik}$ ) = lopt iwork( 1_${ik}$ ) = liopt return end subroutine stdlib${ii}$_dsyevd #:for rk,rt,ri in REAL_KINDS_TYPES #:if not rk in ["sp","dp"] module subroutine stdlib${ii}$_${ri}$syevd( jobz, uplo, n, a, lda, w, work, lwork, iwork,liwork, info ) !! DSYEVD: computes all eigenvalues and, optionally, eigenvectors of a !! real symmetric matrix A. If eigenvectors are desired, it uses a !! divide and conquer algorithm. !! The divide and conquer algorithm makes very mild assumptions about !! floating point arithmetic. It will work on machines with a guard !! digit in add/subtract, or on those binary machines without guard !! digits which subtract like the Cray X-MP, Cray Y-MP, Cray C-90, or !! Cray-2. It could conceivably fail on hexadecimal or decimal machines !! without guard digits, but we know of none. !! Because of large use of BLAS of level 3, DSYEVD needs N**2 more !! workspace than DSYEVX. ! -- 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) :: jobz, uplo integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: lda, liwork, lwork, n ! Array Arguments integer(${ik}$), intent(out) :: iwork(*) real(${rk}$), intent(inout) :: a(lda,*) real(${rk}$), intent(out) :: w(*), work(*) ! ===================================================================== ! Local Scalars logical(lk) :: lower, lquery, wantz integer(${ik}$) :: iinfo, inde, indtau, indwk2, indwrk, iscale, liopt, liwmin, llwork, & llwrk2, lopt, lwmin real(${rk}$) :: anrm, bignum, eps, rmax, rmin, safmin, sigma, smlnum ! Intrinsic Functions ! Executable Statements ! test the input parameters. wantz = stdlib_lsame( jobz, 'V' ) lower = stdlib_lsame( uplo, 'L' ) lquery = ( lwork==-1_${ik}$ .or. liwork==-1_${ik}$ ) info = 0_${ik}$ if( .not.( wantz .or. stdlib_lsame( jobz, 'N' ) ) ) then info = -1_${ik}$ else if( .not.( lower .or. stdlib_lsame( uplo, 'U' ) ) ) then info = -2_${ik}$ else if( n<0_${ik}$ ) then info = -3_${ik}$ else if( lda<max( 1_${ik}$, n ) ) then info = -5_${ik}$ end if if( info==0_${ik}$ ) then if( n<=1_${ik}$ ) then liwmin = 1_${ik}$ lwmin = 1_${ik}$ lopt = lwmin liopt = liwmin else if( wantz ) then liwmin = 3_${ik}$ + 5_${ik}$*n lwmin = 1_${ik}$ + 6_${ik}$*n + 2_${ik}$*n**2_${ik}$ else liwmin = 1_${ik}$ lwmin = 2_${ik}$*n + 1_${ik}$ end if lopt = max( lwmin, 2_${ik}$*n +stdlib${ii}$_ilaenv( 1_${ik}$, 'DSYTRD', uplo, n, -1_${ik}$, -1_${ik}$, -1_${ik}$ ) ) liopt = liwmin end if work( 1_${ik}$ ) = lopt iwork( 1_${ik}$ ) = liopt if( lwork<lwmin .and. .not.lquery ) then info = -8_${ik}$ else if( liwork<liwmin .and. .not.lquery ) then info = -10_${ik}$ end if end if if( info/=0_${ik}$ ) then call stdlib${ii}$_xerbla( 'DSYEVD', -info ) return else if( lquery ) then return end if ! quick return if possible if( n==0 )return if( n==1_${ik}$ ) then w( 1_${ik}$ ) = a( 1_${ik}$, 1_${ik}$ ) if( wantz )a( 1_${ik}$, 1_${ik}$ ) = one return end if ! get machine constants. safmin = stdlib${ii}$_${ri}$lamch( 'SAFE MINIMUM' ) eps = stdlib${ii}$_${ri}$lamch( 'PRECISION' ) smlnum = safmin / eps bignum = one / smlnum rmin = sqrt( smlnum ) rmax = sqrt( bignum ) ! scale matrix to allowable range, if necessary. anrm = stdlib${ii}$_${ri}$lansy( 'M', uplo, n, a, lda, work ) iscale = 0_${ik}$ if( anrm>zero .and. anrm<rmin ) then iscale = 1_${ik}$ sigma = rmin / anrm else if( anrm>rmax ) then iscale = 1_${ik}$ sigma = rmax / anrm end if if( iscale==1_${ik}$ )call stdlib${ii}$_${ri}$lascl( uplo, 0_${ik}$, 0_${ik}$, one, sigma, n, n, a, lda, info ) ! call stdlib${ii}$_${ri}$sytrd to reduce symmetric matrix to tridiagonal form. inde = 1_${ik}$ indtau = inde + n indwrk = indtau + n llwork = lwork - indwrk + 1_${ik}$ indwk2 = indwrk + n*n llwrk2 = lwork - indwk2 + 1_${ik}$ call stdlib${ii}$_${ri}$sytrd( uplo, n, a, lda, w, work( inde ), work( indtau ),work( indwrk ), & llwork, iinfo ) ! for eigenvalues only, call stdlib${ii}$_${ri}$sterf. for eigenvectors, first call ! stdlib${ii}$_${ri}$stedc to generate the eigenvector matrix, work(indwrk), of the ! tridiagonal matrix, then call stdlib${ii}$_${ri}$ormtr to multiply it by the ! householder transformations stored in a. if( .not.wantz ) then call stdlib${ii}$_${ri}$sterf( n, w, work( inde ), info ) else call stdlib${ii}$_${ri}$stedc( 'I', n, w, work( inde ), work( indwrk ), n,work( indwk2 ), & llwrk2, iwork, liwork, info ) call stdlib${ii}$_${ri}$ormtr( 'L', uplo, 'N', n, n, a, lda, work( indtau ),work( indwrk ), n, & work( indwk2 ), llwrk2, iinfo ) call stdlib${ii}$_${ri}$lacpy( 'A', n, n, work( indwrk ), n, a, lda ) end if ! if matrix was scaled, then rescale eigenvalues appropriately. if( iscale==1_${ik}$ )call stdlib${ii}$_${ri}$scal( n, one / sigma, w, 1_${ik}$ ) work( 1_${ik}$ ) = lopt iwork( 1_${ik}$ ) = liopt return end subroutine stdlib${ii}$_${ri}$syevd #:endif #:endfor module subroutine stdlib${ii}$_ssyevr( jobz, range, uplo, n, a, lda, vl, vu, il, iu,abstol, m, w, z, ldz, & !! SSYEVR computes selected eigenvalues and, optionally, eigenvectors !! of a real symmetric matrix A. Eigenvalues and eigenvectors can be !! selected by specifying either a range of values or a range of !! indices for the desired eigenvalues. !! SSYEVR first reduces the matrix A to tridiagonal form T with a call !! to SSYTRD. Then, whenever possible, SSYEVR calls SSTEMR to compute !! the eigenspectrum using Relatively Robust Representations. SSTEMR !! computes eigenvalues by the dqds algorithm, while orthogonal !! eigenvectors are computed from various "good" L D L^T representations !! (also known as Relatively Robust Representations). Gram-Schmidt !! orthogonalization is avoided as far as possible. More specifically, !! the various steps of the algorithm are as follows. !! For each unreduced block (submatrix) of T, !! (a) Compute T - sigma I = L D L^T, so that L and D !! define all the wanted eigenvalues to high relative accuracy. !! This means that small relative changes in the entries of D and L !! cause only small relative changes in the eigenvalues and !! eigenvectors. The standard (unfactored) representation of the !! tridiagonal matrix T does not have this property in general. !! (b) Compute the eigenvalues to suitable accuracy. !! If the eigenvectors are desired, the algorithm attains full !! accuracy of the computed eigenvalues only right before !! the corresponding vectors have to be computed, see steps c) and d). !! (c) For each cluster of close eigenvalues, select a new !! shift close to the cluster, find a new factorization, and refine !! the shifted eigenvalues to suitable accuracy. !! (d) For each eigenvalue with a large enough relative separation compute !! the corresponding eigenvector by forming a rank revealing twisted !! factorization. Go back to (c) for any clusters that remain. !! The desired accuracy of the output can be specified by the input !! parameter ABSTOL. !! For more details, see SSTEMR's documentation and: !! - Inderjit S. Dhillon and Beresford N. Parlett: "Multiple representations !! to compute orthogonal eigenvectors of symmetric tridiagonal matrices," !! Linear Algebra and its Applications, 387(1), pp. 1-28, August 2004. !! - Inderjit Dhillon and Beresford Parlett: "Orthogonal Eigenvectors and !! Relative Gaps," SIAM Journal on Matrix Analysis and Applications, Vol. 25, !! 2004. Also LAPACK Working Note 154. !! - Inderjit Dhillon: "A new O(n^2) algorithm for the symmetric !! tridiagonal eigenvalue/eigenvector problem", !! Computer Science Division Technical Report No. UCB/CSD-97-971, !! UC Berkeley, May 1997. !! Note 1 : SSYEVR calls SSTEMR when the full spectrum is requested !! on machines which conform to the ieee-754 floating point standard. !! SSYEVR calls SSTEBZ and SSTEIN on non-ieee machines and !! when partial spectrum requests are made. !! Normal execution of SSTEMR may create NaNs and infinities and !! hence may abort due to a floating point exception in environments !! which do not handle NaNs and infinities in the ieee standard default !! manner. isuppz, work, lwork,iwork, liwork, 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) :: jobz, range, uplo integer(${ik}$), intent(in) :: il, iu, lda, ldz, liwork, lwork, n integer(${ik}$), intent(out) :: info, m real(sp), intent(in) :: abstol, vl, vu ! Array Arguments integer(${ik}$), intent(out) :: isuppz(*), iwork(*) real(sp), intent(inout) :: a(lda,*) real(sp), intent(out) :: w(*), work(*), z(ldz,*) ! ===================================================================== ! Local Scalars logical(lk) :: alleig, indeig, lower, lquery, test, valeig, wantz, tryrac character :: order integer(${ik}$) :: i, ieeeok, iinfo, imax, indd, inddd, inde, indee, indibl, indifl, & indisp, indiwo, indtau, indwk, indwkn, iscale, j, jj, liwmin, llwork, llwrkn, lwkopt, & lwmin, nb, nsplit real(sp) :: abstll, anrm, bignum, eps, rmax, rmin, safmin, sigma, smlnum, tmp1, vll, & vuu ! Intrinsic Functions ! Executable Statements ! test the input parameters. ieeeok = stdlib${ii}$_ilaenv( 10_${ik}$, 'SSYEVR', 'N', 1_${ik}$, 2_${ik}$, 3_${ik}$, 4_${ik}$ ) lower = stdlib_lsame( uplo, 'L' ) wantz = stdlib_lsame( jobz, 'V' ) alleig = stdlib_lsame( range, 'A' ) valeig = stdlib_lsame( range, 'V' ) indeig = stdlib_lsame( range, 'I' ) lquery = ( ( lwork==-1_${ik}$ ) .or. ( liwork==-1_${ik}$ ) ) lwmin = max( 1_${ik}$, 26_${ik}$*n ) liwmin = max( 1_${ik}$, 10_${ik}$*n ) info = 0_${ik}$ if( .not.( wantz .or. stdlib_lsame( jobz, 'N' ) ) ) then info = -1_${ik}$ else if( .not.( alleig .or. valeig .or. indeig ) ) then info = -2_${ik}$ else if( .not.( lower .or. stdlib_lsame( uplo, 'U' ) ) ) then info = -3_${ik}$ else if( n<0_${ik}$ ) then info = -4_${ik}$ else if( lda<max( 1_${ik}$, n ) ) then info = -6_${ik}$ else if( valeig ) then if( n>0_${ik}$ .and. vu<=vl )info = -8_${ik}$ else if( indeig ) then if( il<1_${ik}$ .or. il>max( 1_${ik}$, n ) ) then info = -9_${ik}$ else if( iu<min( n, il ) .or. iu>n ) then info = -10_${ik}$ end if end if end if if( info==0_${ik}$ ) then if( ldz<1_${ik}$ .or. ( wantz .and. ldz<n ) ) then info = -15_${ik}$ end if end if if( info==0_${ik}$ ) then nb = stdlib${ii}$_ilaenv( 1_${ik}$, 'SSYTRD', uplo, n, -1_${ik}$, -1_${ik}$, -1_${ik}$ ) nb = max( nb, stdlib${ii}$_ilaenv( 1_${ik}$, 'SORMTR', uplo, n, -1_${ik}$, -1_${ik}$, -1_${ik}$ ) ) lwkopt = max( ( nb+1 )*n, lwmin ) work( 1_${ik}$ ) = lwkopt iwork( 1_${ik}$ ) = liwmin if( lwork<lwmin .and. .not.lquery ) then info = -18_${ik}$ else if( liwork<liwmin .and. .not.lquery ) then info = -20_${ik}$ end if end if if( info/=0_${ik}$ ) then call stdlib${ii}$_xerbla( 'SSYEVR', -info ) return else if( lquery ) then return end if ! quick return if possible m = 0_${ik}$ if( n==0_${ik}$ ) then work( 1_${ik}$ ) = 1_${ik}$ return end if if( n==1_${ik}$ ) then work( 1_${ik}$ ) = 26_${ik}$ if( alleig .or. indeig ) then m = 1_${ik}$ w( 1_${ik}$ ) = a( 1_${ik}$, 1_${ik}$ ) else if( vl<a( 1_${ik}$, 1_${ik}$ ) .and. vu>=a( 1_${ik}$, 1_${ik}$ ) ) then m = 1_${ik}$ w( 1_${ik}$ ) = a( 1_${ik}$, 1_${ik}$ ) end if end if if( wantz ) then z( 1_${ik}$, 1_${ik}$ ) = one isuppz( 1_${ik}$ ) = 1_${ik}$ isuppz( 2_${ik}$ ) = 1_${ik}$ end if return end if ! get machine constants. safmin = stdlib${ii}$_slamch( 'SAFE MINIMUM' ) eps = stdlib${ii}$_slamch( 'PRECISION' ) smlnum = safmin / eps bignum = one / smlnum rmin = sqrt( smlnum ) rmax = min( sqrt( bignum ), one / sqrt( sqrt( safmin ) ) ) ! scale matrix to allowable range, if necessary. iscale = 0_${ik}$ abstll = abstol if (valeig) then vll = vl vuu = vu end if anrm = stdlib${ii}$_slansy( 'M', uplo, n, a, lda, work ) if( anrm>zero .and. anrm<rmin ) then iscale = 1_${ik}$ sigma = rmin / anrm else if( anrm>rmax ) then iscale = 1_${ik}$ sigma = rmax / anrm end if if( iscale==1_${ik}$ ) then if( lower ) then do j = 1, n call stdlib${ii}$_sscal( n-j+1, sigma, a( j, j ), 1_${ik}$ ) end do else do j = 1, n call stdlib${ii}$_sscal( j, sigma, a( 1_${ik}$, j ), 1_${ik}$ ) end do end if if( abstol>0_${ik}$ )abstll = abstol*sigma if( valeig ) then vll = vl*sigma vuu = vu*sigma end if end if ! initialize indices into workspaces. note: the iwork indices are ! used only if stdlib${ii}$_ssterf or stdlib${ii}$_sstemr fail. ! work(indtau:indtau+n-1) stores the scalar factors of the ! elementary reflectors used in stdlib${ii}$_ssytrd. indtau = 1_${ik}$ ! work(indd:indd+n-1) stores the tridiagonal's diagonal entries. indd = indtau + n ! work(inde:inde+n-1) stores the off-diagonal entries of the ! tridiagonal matrix from stdlib${ii}$_ssytrd. inde = indd + n ! work(inddd:inddd+n-1) is a copy of the diagonal entries over ! -written by stdlib${ii}$_sstemr (the stdlib${ii}$_ssterf path copies the diagonal to w). inddd = inde + n ! work(indee:indee+n-1) is a copy of the off-diagonal entries over ! -written while computing the eigenvalues in stdlib${ii}$_ssterf and stdlib${ii}$_sstemr. indee = inddd + n ! indwk is the starting offset of the left-over workspace, and ! llwork is the remaining workspace size. indwk = indee + n llwork = lwork - indwk + 1_${ik}$ ! iwork(indibl:indibl+m-1) corresponds to iblock in stdlib${ii}$_sstebz and ! stores the block indices of each of the m<=n eigenvalues. indibl = 1_${ik}$ ! iwork(indisp:indisp+nsplit-1) corresponds to isplit in stdlib${ii}$_sstebz and ! stores the starting and finishing indices of each block. indisp = indibl + n ! iwork(indifl:indifl+n-1) stores the indices of eigenvectors ! that corresponding to eigenvectors that fail to converge in ! stdlib${ii}$_sstein. this information is discarded; if any fail, the driver ! returns info > 0. indifl = indisp + n ! indiwo is the offset of the remaining integer workspace. indiwo = indifl + n ! call stdlib${ii}$_ssytrd to reduce symmetric matrix to tridiagonal form. call stdlib${ii}$_ssytrd( uplo, n, a, lda, work( indd ), work( inde ),work( indtau ), work( & indwk ), llwork, iinfo ) ! if all eigenvalues are desired ! then call stdlib${ii}$_ssterf or stdlib${ii}$_sstemr and stdlib${ii}$_sormtr. test = .false. if( indeig ) then if( il==1_${ik}$ .and. iu==n ) then test = .true. end if end if if( ( alleig.or.test ) .and. ( ieeeok==1_${ik}$ ) ) then if( .not.wantz ) then call stdlib${ii}$_scopy( n, work( indd ), 1_${ik}$, w, 1_${ik}$ ) call stdlib${ii}$_scopy( n-1, work( inde ), 1_${ik}$, work( indee ), 1_${ik}$ ) call stdlib${ii}$_ssterf( n, w, work( indee ), info ) else call stdlib${ii}$_scopy( n-1, work( inde ), 1_${ik}$, work( indee ), 1_${ik}$ ) call stdlib${ii}$_scopy( n, work( indd ), 1_${ik}$, work( inddd ), 1_${ik}$ ) if (abstol <= two*n*eps) then tryrac = .true. else tryrac = .false. end if call stdlib${ii}$_sstemr( jobz, 'A', n, work( inddd ), work( indee ),vl, vu, il, iu, m,& w, z, ldz, n, isuppz,tryrac, work( indwk ), lwork, iwork, liwork,info ) ! apply orthogonal matrix used in reduction to tridiagonal ! form to eigenvectors returned by stdlib${ii}$_sstemr. if( wantz .and. info==0_${ik}$ ) then indwkn = inde llwrkn = lwork - indwkn + 1_${ik}$ call stdlib${ii}$_sormtr( 'L', uplo, 'N', n, m, a, lda,work( indtau ), z, ldz, work(& indwkn ),llwrkn, iinfo ) end if end if if( info==0_${ik}$ ) then ! everything worked. skip stdlib${ii}$_sstebz/stdlib${ii}$_sstein. iwork(:) are ! undefined. m = n go to 30 end if info = 0_${ik}$ end if ! otherwise, call stdlib${ii}$_sstebz and, if eigenvectors are desired, stdlib${ii}$_sstein. ! also call stdlib${ii}$_sstebz and stdlib${ii}$_sstein if stdlib${ii}$_sstemr fails. if( wantz ) then order = 'B' else order = 'E' end if call stdlib${ii}$_sstebz( range, order, n, vll, vuu, il, iu, abstll,work( indd ), work( inde & ), m, nsplit, w,iwork( indibl ), iwork( indisp ), work( indwk ),iwork( indiwo ), info ) if( wantz ) then call stdlib${ii}$_sstein( n, work( indd ), work( inde ), m, w,iwork( indibl ), iwork( & indisp ), z, ldz,work( indwk ), iwork( indiwo ), iwork( indifl ),info ) ! apply orthogonal matrix used in reduction to tridiagonal ! form to eigenvectors returned by stdlib${ii}$_sstein. indwkn = inde llwrkn = lwork - indwkn + 1_${ik}$ call stdlib${ii}$_sormtr( 'L', uplo, 'N', n, m, a, lda, work( indtau ), z,ldz, work( & indwkn ), llwrkn, iinfo ) end if ! if matrix was scaled, then rescale eigenvalues appropriately. ! jump here if stdlib${ii}$_sstemr/stdlib${ii}$_sstein succeeded. 30 continue if( iscale==1_${ik}$ ) then if( info==0_${ik}$ ) then imax = m else imax = info - 1_${ik}$ end if call stdlib${ii}$_sscal( imax, one / sigma, w, 1_${ik}$ ) end if ! if eigenvalues are not in order, then sort them, along with ! eigenvectors. note: we do not sort the ifail portion of iwork. ! it may not be initialized (if stdlib${ii}$_sstemr/stdlib${ii}$_sstein succeeded), and we do ! not return this detailed information to the user. if( wantz ) then do j = 1, m - 1 i = 0_${ik}$ tmp1 = w( j ) do jj = j + 1, m if( w( jj )<tmp1 ) then i = jj tmp1 = w( jj ) end if end do if( i/=0_${ik}$ ) then w( i ) = w( j ) w( j ) = tmp1 call stdlib${ii}$_sswap( n, z( 1_${ik}$, i ), 1_${ik}$, z( 1_${ik}$, j ), 1_${ik}$ ) end if end do end if ! set work(1) to optimal workspace size. work( 1_${ik}$ ) = lwkopt iwork( 1_${ik}$ ) = liwmin return end subroutine stdlib${ii}$_ssyevr module subroutine stdlib${ii}$_dsyevr( jobz, range, uplo, n, a, lda, vl, vu, il, iu,abstol, m, w, z, ldz, & !! DSYEVR computes selected eigenvalues and, optionally, eigenvectors !! of a real symmetric matrix A. Eigenvalues and eigenvectors can be !! selected by specifying either a range of values or a range of !! indices for the desired eigenvalues. !! DSYEVR first reduces the matrix A to tridiagonal form T with a call !! to DSYTRD. Then, whenever possible, DSYEVR calls DSTEMR to compute !! the eigenspectrum using Relatively Robust Representations. DSTEMR !! computes eigenvalues by the dqds algorithm, while orthogonal !! eigenvectors are computed from various "good" L D L^T representations !! (also known as Relatively Robust Representations). Gram-Schmidt !! orthogonalization is avoided as far as possible. More specifically, !! the various steps of the algorithm are as follows. !! For each unreduced block (submatrix) of T, !! (a) Compute T - sigma I = L D L^T, so that L and D !! define all the wanted eigenvalues to high relative accuracy. !! This means that small relative changes in the entries of D and L !! cause only small relative changes in the eigenvalues and !! eigenvectors. The standard (unfactored) representation of the !! tridiagonal matrix T does not have this property in general. !! (b) Compute the eigenvalues to suitable accuracy. !! If the eigenvectors are desired, the algorithm attains full !! accuracy of the computed eigenvalues only right before !! the corresponding vectors have to be computed, see steps c) and d). !! (c) For each cluster of close eigenvalues, select a new !! shift close to the cluster, find a new factorization, and refine !! the shifted eigenvalues to suitable accuracy. !! (d) For each eigenvalue with a large enough relative separation compute !! the corresponding eigenvector by forming a rank revealing twisted !! factorization. Go back to (c) for any clusters that remain. !! The desired accuracy of the output can be specified by the input !! parameter ABSTOL. !! For more details, see DSTEMR's documentation and: !! - Inderjit S. Dhillon and Beresford N. Parlett: "Multiple representations !! to compute orthogonal eigenvectors of symmetric tridiagonal matrices," !! Linear Algebra and its Applications, 387(1), pp. 1-28, August 2004. !! - Inderjit Dhillon and Beresford Parlett: "Orthogonal Eigenvectors and !! Relative Gaps," SIAM Journal on Matrix Analysis and Applications, Vol. 25, !! 2004. Also LAPACK Working Note 154. !! - Inderjit Dhillon: "A new O(n^2) algorithm for the symmetric !! tridiagonal eigenvalue/eigenvector problem", !! Computer Science Division Technical Report No. UCB/CSD-97-971, !! UC Berkeley, May 1997. !! Note 1 : DSYEVR calls DSTEMR when the full spectrum is requested !! on machines which conform to the ieee-754 floating point standard. !! DSYEVR calls DSTEBZ and DSTEIN on non-ieee machines and !! when partial spectrum requests are made. !! Normal execution of DSTEMR may create NaNs and infinities and !! hence may abort due to a floating point exception in environments !! which do not handle NaNs and infinities in the ieee standard default !! manner. isuppz, work, lwork,iwork, liwork, 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) :: jobz, range, uplo integer(${ik}$), intent(in) :: il, iu, lda, ldz, liwork, lwork, n integer(${ik}$), intent(out) :: info, m real(dp), intent(in) :: abstol, vl, vu ! Array Arguments integer(${ik}$), intent(out) :: isuppz(*), iwork(*) real(dp), intent(inout) :: a(lda,*) real(dp), intent(out) :: w(*), work(*), z(ldz,*) ! ===================================================================== ! Local Scalars logical(lk) :: alleig, indeig, lower, lquery, valeig, wantz, tryrac character :: order integer(${ik}$) :: i, ieeeok, iinfo, imax, indd, inddd, inde, indee, indibl, indifl, & indisp, indiwo, indtau, indwk, indwkn, iscale, j, jj, liwmin, llwork, llwrkn, lwkopt, & lwmin, nb, nsplit real(dp) :: abstll, anrm, bignum, eps, rmax, rmin, safmin, sigma, smlnum, tmp1, vll, & vuu ! Intrinsic Functions ! Executable Statements ! test the input parameters. ieeeok = stdlib${ii}$_ilaenv( 10_${ik}$, 'DSYEVR', 'N', 1_${ik}$, 2_${ik}$, 3_${ik}$, 4_${ik}$ ) lower = stdlib_lsame( uplo, 'L' ) wantz = stdlib_lsame( jobz, 'V' ) alleig = stdlib_lsame( range, 'A' ) valeig = stdlib_lsame( range, 'V' ) indeig = stdlib_lsame( range, 'I' ) lquery = ( ( lwork==-1_${ik}$ ) .or. ( liwork==-1_${ik}$ ) ) lwmin = max( 1_${ik}$, 26_${ik}$*n ) liwmin = max( 1_${ik}$, 10_${ik}$*n ) info = 0_${ik}$ if( .not.( wantz .or. stdlib_lsame( jobz, 'N' ) ) ) then info = -1_${ik}$ else if( .not.( alleig .or. valeig .or. indeig ) ) then info = -2_${ik}$ else if( .not.( lower .or. stdlib_lsame( uplo, 'U' ) ) ) then info = -3_${ik}$ else if( n<0_${ik}$ ) then info = -4_${ik}$ else if( lda<max( 1_${ik}$, n ) ) then info = -6_${ik}$ else if( valeig ) then if( n>0_${ik}$ .and. vu<=vl )info = -8_${ik}$ else if( indeig ) then if( il<1_${ik}$ .or. il>max( 1_${ik}$, n ) ) then info = -9_${ik}$ else if( iu<min( n, il ) .or. iu>n ) then info = -10_${ik}$ end if end if end if if( info==0_${ik}$ ) then if( ldz<1_${ik}$ .or. ( wantz .and. ldz<n ) ) then info = -15_${ik}$ else if( lwork<lwmin .and. .not.lquery ) then info = -18_${ik}$ else if( liwork<liwmin .and. .not.lquery ) then info = -20_${ik}$ end if end if if( info==0_${ik}$ ) then nb = stdlib${ii}$_ilaenv( 1_${ik}$, 'DSYTRD', uplo, n, -1_${ik}$, -1_${ik}$, -1_${ik}$ ) nb = max( nb, stdlib${ii}$_ilaenv( 1_${ik}$, 'DORMTR', uplo, n, -1_${ik}$, -1_${ik}$, -1_${ik}$ ) ) lwkopt = max( ( nb+1 )*n, lwmin ) work( 1_${ik}$ ) = lwkopt iwork( 1_${ik}$ ) = liwmin end if if( info/=0_${ik}$ ) then call stdlib${ii}$_xerbla( 'DSYEVR', -info ) return else if( lquery ) then return end if ! quick return if possible m = 0_${ik}$ if( n==0_${ik}$ ) then work( 1_${ik}$ ) = 1_${ik}$ return end if if( n==1_${ik}$ ) then work( 1_${ik}$ ) = 7_${ik}$ if( alleig .or. indeig ) then m = 1_${ik}$ w( 1_${ik}$ ) = a( 1_${ik}$, 1_${ik}$ ) else if( vl<a( 1_${ik}$, 1_${ik}$ ) .and. vu>=a( 1_${ik}$, 1_${ik}$ ) ) then m = 1_${ik}$ w( 1_${ik}$ ) = a( 1_${ik}$, 1_${ik}$ ) end if end if if( wantz ) then z( 1_${ik}$, 1_${ik}$ ) = one isuppz( 1_${ik}$ ) = 1_${ik}$ isuppz( 2_${ik}$ ) = 1_${ik}$ end if return end if ! get machine constants. safmin = stdlib${ii}$_dlamch( 'SAFE MINIMUM' ) eps = stdlib${ii}$_dlamch( 'PRECISION' ) smlnum = safmin / eps bignum = one / smlnum rmin = sqrt( smlnum ) rmax = min( sqrt( bignum ), one / sqrt( sqrt( safmin ) ) ) ! scale matrix to allowable range, if necessary. iscale = 0_${ik}$ abstll = abstol if (valeig) then vll = vl vuu = vu end if anrm = stdlib${ii}$_dlansy( 'M', uplo, n, a, lda, work ) if( anrm>zero .and. anrm<rmin ) then iscale = 1_${ik}$ sigma = rmin / anrm else if( anrm>rmax ) then iscale = 1_${ik}$ sigma = rmax / anrm end if if( iscale==1_${ik}$ ) then if( lower ) then do j = 1, n call stdlib${ii}$_dscal( n-j+1, sigma, a( j, j ), 1_${ik}$ ) end do else do j = 1, n call stdlib${ii}$_dscal( j, sigma, a( 1_${ik}$, j ), 1_${ik}$ ) end do end if if( abstol>0_${ik}$ )abstll = abstol*sigma if( valeig ) then vll = vl*sigma vuu = vu*sigma end if end if ! initialize indices into workspaces. note: the iwork indices are ! used only if stdlib${ii}$_dsterf or stdlib${ii}$_dstemr fail. ! work(indtau:indtau+n-1) stores the scalar factors of the ! elementary reflectors used in stdlib${ii}$_dsytrd. indtau = 1_${ik}$ ! work(indd:indd+n-1) stores the tridiagonal's diagonal entries. indd = indtau + n ! work(inde:inde+n-1) stores the off-diagonal entries of the ! tridiagonal matrix from stdlib${ii}$_dsytrd. inde = indd + n ! work(inddd:inddd+n-1) is a copy of the diagonal entries over ! -written by stdlib${ii}$_dstemr (the stdlib${ii}$_dsterf path copies the diagonal to w). inddd = inde + n ! work(indee:indee+n-1) is a copy of the off-diagonal entries over ! -written while computing the eigenvalues in stdlib${ii}$_dsterf and stdlib${ii}$_dstemr. indee = inddd + n ! indwk is the starting offset of the left-over workspace, and ! llwork is the remaining workspace size. indwk = indee + n llwork = lwork - indwk + 1_${ik}$ ! iwork(indibl:indibl+m-1) corresponds to iblock in stdlib${ii}$_dstebz and ! stores the block indices of each of the m<=n eigenvalues. indibl = 1_${ik}$ ! iwork(indisp:indisp+nsplit-1) corresponds to isplit in stdlib${ii}$_dstebz and ! stores the starting and finishing indices of each block. indisp = indibl + n ! iwork(indifl:indifl+n-1) stores the indices of eigenvectors ! that corresponding to eigenvectors that fail to converge in ! stdlib${ii}$_dstein. this information is discarded; if any fail, the driver ! returns info > 0. indifl = indisp + n ! indiwo is the offset of the remaining integer workspace. indiwo = indifl + n ! call stdlib${ii}$_dsytrd to reduce symmetric matrix to tridiagonal form. call stdlib${ii}$_dsytrd( uplo, n, a, lda, work( indd ), work( inde ),work( indtau ), work( & indwk ), llwork, iinfo ) ! if all eigenvalues are desired ! then call stdlib${ii}$_dsterf or stdlib${ii}$_dstemr and stdlib${ii}$_dormtr. if( ( alleig .or. ( indeig .and. il==1_${ik}$ .and. iu==n ) ) .and.ieeeok==1_${ik}$ ) then if( .not.wantz ) then call stdlib${ii}$_dcopy( n, work( indd ), 1_${ik}$, w, 1_${ik}$ ) call stdlib${ii}$_dcopy( n-1, work( inde ), 1_${ik}$, work( indee ), 1_${ik}$ ) call stdlib${ii}$_dsterf( n, w, work( indee ), info ) else call stdlib${ii}$_dcopy( n-1, work( inde ), 1_${ik}$, work( indee ), 1_${ik}$ ) call stdlib${ii}$_dcopy( n, work( indd ), 1_${ik}$, work( inddd ), 1_${ik}$ ) if (abstol <= two*n*eps) then tryrac = .true. else tryrac = .false. end if call stdlib${ii}$_dstemr( jobz, 'A', n, work( inddd ), work( indee ),vl, vu, il, iu, m,& w, z, ldz, n, isuppz,tryrac, work( indwk ), lwork, iwork, liwork,info ) ! apply orthogonal matrix used in reduction to tridiagonal ! form to eigenvectors returned by stdlib${ii}$_dstemr. if( wantz .and. info==0_${ik}$ ) then indwkn = inde llwrkn = lwork - indwkn + 1_${ik}$ call stdlib${ii}$_dormtr( 'L', uplo, 'N', n, m, a, lda,work( indtau ), z, ldz, work(& indwkn ),llwrkn, iinfo ) end if end if if( info==0_${ik}$ ) then ! everything worked. skip stdlib${ii}$_dstebz/stdlib${ii}$_dstein. iwork(:) are ! undefined. m = n go to 30 end if info = 0_${ik}$ end if ! otherwise, call stdlib${ii}$_dstebz and, if eigenvectors are desired, stdlib${ii}$_dstein. ! also call stdlib${ii}$_dstebz and stdlib${ii}$_dstein if stdlib${ii}$_dstemr fails. if( wantz ) then order = 'B' else order = 'E' end if call stdlib${ii}$_dstebz( range, order, n, vll, vuu, il, iu, abstll,work( indd ), work( inde & ), m, nsplit, w,iwork( indibl ), iwork( indisp ), work( indwk ),iwork( indiwo ), info ) if( wantz ) then call stdlib${ii}$_dstein( n, work( indd ), work( inde ), m, w,iwork( indibl ), iwork( & indisp ), z, ldz,work( indwk ), iwork( indiwo ), iwork( indifl ),info ) ! apply orthogonal matrix used in reduction to tridiagonal ! form to eigenvectors returned by stdlib${ii}$_dstein. indwkn = inde llwrkn = lwork - indwkn + 1_${ik}$ call stdlib${ii}$_dormtr( 'L', uplo, 'N', n, m, a, lda, work( indtau ), z,ldz, work( & indwkn ), llwrkn, iinfo ) end if ! if matrix was scaled, then rescale eigenvalues appropriately. ! jump here if stdlib${ii}$_dstemr/stdlib${ii}$_dstein succeeded. 30 continue if( iscale==1_${ik}$ ) then if( info==0_${ik}$ ) then imax = m else imax = info - 1_${ik}$ end if call stdlib${ii}$_dscal( imax, one / sigma, w, 1_${ik}$ ) end if ! if eigenvalues are not in order, then sort them, along with ! eigenvectors. note: we do not sort the ifail portion of iwork. ! it may not be initialized (if stdlib${ii}$_dstemr/stdlib${ii}$_dstein succeeded), and we do ! not return this detailed information to the user. if( wantz ) then do j = 1, m - 1 i = 0_${ik}$ tmp1 = w( j ) do jj = j + 1, m if( w( jj )<tmp1 ) then i = jj tmp1 = w( jj ) end if end do if( i/=0_${ik}$ ) then w( i ) = w( j ) w( j ) = tmp1 call stdlib${ii}$_dswap( n, z( 1_${ik}$, i ), 1_${ik}$, z( 1_${ik}$, j ), 1_${ik}$ ) end if end do end if ! set work(1) to optimal workspace size. work( 1_${ik}$ ) = lwkopt iwork( 1_${ik}$ ) = liwmin return end subroutine stdlib${ii}$_dsyevr #:for rk,rt,ri in REAL_KINDS_TYPES #:if not rk in ["sp","dp"] module subroutine stdlib${ii}$_${ri}$syevr( jobz, range, uplo, n, a, lda, vl, vu, il, iu,abstol, m, w, z, ldz, & !! DSYEVR: computes selected eigenvalues and, optionally, eigenvectors !! of a real symmetric matrix A. Eigenvalues and eigenvectors can be !! selected by specifying either a range of values or a range of !! indices for the desired eigenvalues. !! DSYEVR first reduces the matrix A to tridiagonal form T with a call !! to DSYTRD. Then, whenever possible, DSYEVR calls DSTEMR to compute !! the eigenspectrum using Relatively Robust Representations. DSTEMR !! computes eigenvalues by the dqds algorithm, while orthogonal !! eigenvectors are computed from various "good" L D L^T representations !! (also known as Relatively Robust Representations). Gram-Schmidt !! orthogonalization is avoided as far as possible. More specifically, !! the various steps of the algorithm are as follows. !! For each unreduced block (submatrix) of T, !! (a) Compute T - sigma I = L D L^T, so that L and D !! define all the wanted eigenvalues to high relative accuracy. !! This means that small relative changes in the entries of D and L !! cause only small relative changes in the eigenvalues and !! eigenvectors. The standard (unfactored) representation of the !! tridiagonal matrix T does not have this property in general. !! (b) Compute the eigenvalues to suitable accuracy. !! If the eigenvectors are desired, the algorithm attains full !! accuracy of the computed eigenvalues only right before !! the corresponding vectors have to be computed, see steps c) and d). !! (c) For each cluster of close eigenvalues, select a new !! shift close to the cluster, find a new factorization, and refine !! the shifted eigenvalues to suitable accuracy. !! (d) For each eigenvalue with a large enough relative separation compute !! the corresponding eigenvector by forming a rank revealing twisted !! factorization. Go back to (c) for any clusters that remain. !! The desired accuracy of the output can be specified by the input !! parameter ABSTOL. !! For more details, see DSTEMR's documentation and: !! - Inderjit S. Dhillon and Beresford N. Parlett: "Multiple representations !! to compute orthogonal eigenvectors of symmetric tridiagonal matrices," !! Linear Algebra and its Applications, 387(1), pp. 1-28, August 2004. !! - Inderjit Dhillon and Beresford Parlett: "Orthogonal Eigenvectors and !! Relative Gaps," SIAM Journal on Matrix Analysis and Applications, Vol. 25, !! 2004. Also LAPACK Working Note 154. !! - Inderjit Dhillon: "A new O(n^2) algorithm for the symmetric !! tridiagonal eigenvalue/eigenvector problem", !! Computer Science Division Technical Report No. UCB/CSD-97-971, !! UC Berkeley, May 1997. !! Note 1 : DSYEVR calls DSTEMR when the full spectrum is requested !! on machines which conform to the ieee-754 floating point standard. !! DSYEVR calls DSTEBZ and DSTEIN on non-ieee machines and !! when partial spectrum requests are made. !! Normal execution of DSTEMR may create NaNs and infinities and !! hence may abort due to a floating point exception in environments !! which do not handle NaNs and infinities in the ieee standard default !! manner. isuppz, work, lwork,iwork, liwork, 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) :: jobz, range, uplo integer(${ik}$), intent(in) :: il, iu, lda, ldz, liwork, lwork, n integer(${ik}$), intent(out) :: info, m real(${rk}$), intent(in) :: abstol, vl, vu ! Array Arguments integer(${ik}$), intent(out) :: isuppz(*), iwork(*) real(${rk}$), intent(inout) :: a(lda,*) real(${rk}$), intent(out) :: w(*), work(*), z(ldz,*) ! ===================================================================== ! Local Scalars logical(lk) :: alleig, indeig, lower, lquery, valeig, wantz, tryrac character :: order integer(${ik}$) :: i, ieeeok, iinfo, imax, indd, inddd, inde, indee, indibl, indifl, & indisp, indiwo, indtau, indwk, indwkn, iscale, j, jj, liwmin, llwork, llwrkn, lwkopt, & lwmin, nb, nsplit real(${rk}$) :: abstll, anrm, bignum, eps, rmax, rmin, safmin, sigma, smlnum, tmp1, vll, & vuu ! Intrinsic Functions ! Executable Statements ! test the input parameters. ieeeok = stdlib${ii}$_ilaenv( 10_${ik}$, 'DSYEVR', 'N', 1_${ik}$, 2_${ik}$, 3_${ik}$, 4_${ik}$ ) lower = stdlib_lsame( uplo, 'L' ) wantz = stdlib_lsame( jobz, 'V' ) alleig = stdlib_lsame( range, 'A' ) valeig = stdlib_lsame( range, 'V' ) indeig = stdlib_lsame( range, 'I' ) lquery = ( ( lwork==-1_${ik}$ ) .or. ( liwork==-1_${ik}$ ) ) lwmin = max( 1_${ik}$, 26_${ik}$*n ) liwmin = max( 1_${ik}$, 10_${ik}$*n ) info = 0_${ik}$ if( .not.( wantz .or. stdlib_lsame( jobz, 'N' ) ) ) then info = -1_${ik}$ else if( .not.( alleig .or. valeig .or. indeig ) ) then info = -2_${ik}$ else if( .not.( lower .or. stdlib_lsame( uplo, 'U' ) ) ) then info = -3_${ik}$ else if( n<0_${ik}$ ) then info = -4_${ik}$ else if( lda<max( 1_${ik}$, n ) ) then info = -6_${ik}$ else if( valeig ) then if( n>0_${ik}$ .and. vu<=vl )info = -8_${ik}$ else if( indeig ) then if( il<1_${ik}$ .or. il>max( 1_${ik}$, n ) ) then info = -9_${ik}$ else if( iu<min( n, il ) .or. iu>n ) then info = -10_${ik}$ end if end if end if if( info==0_${ik}$ ) then if( ldz<1_${ik}$ .or. ( wantz .and. ldz<n ) ) then info = -15_${ik}$ else if( lwork<lwmin .and. .not.lquery ) then info = -18_${ik}$ else if( liwork<liwmin .and. .not.lquery ) then info = -20_${ik}$ end if end if if( info==0_${ik}$ ) then nb = stdlib${ii}$_ilaenv( 1_${ik}$, 'DSYTRD', uplo, n, -1_${ik}$, -1_${ik}$, -1_${ik}$ ) nb = max( nb, stdlib${ii}$_ilaenv( 1_${ik}$, 'DORMTR', uplo, n, -1_${ik}$, -1_${ik}$, -1_${ik}$ ) ) lwkopt = max( ( nb+1 )*n, lwmin ) work( 1_${ik}$ ) = lwkopt iwork( 1_${ik}$ ) = liwmin end if if( info/=0_${ik}$ ) then call stdlib${ii}$_xerbla( 'DSYEVR', -info ) return else if( lquery ) then return end if ! quick return if possible m = 0_${ik}$ if( n==0_${ik}$ ) then work( 1_${ik}$ ) = 1_${ik}$ return end if if( n==1_${ik}$ ) then work( 1_${ik}$ ) = 7_${ik}$ if( alleig .or. indeig ) then m = 1_${ik}$ w( 1_${ik}$ ) = a( 1_${ik}$, 1_${ik}$ ) else if( vl<a( 1_${ik}$, 1_${ik}$ ) .and. vu>=a( 1_${ik}$, 1_${ik}$ ) ) then m = 1_${ik}$ w( 1_${ik}$ ) = a( 1_${ik}$, 1_${ik}$ ) end if end if if( wantz ) then z( 1_${ik}$, 1_${ik}$ ) = one isuppz( 1_${ik}$ ) = 1_${ik}$ isuppz( 2_${ik}$ ) = 1_${ik}$ end if return end if ! get machine constants. safmin = stdlib${ii}$_${ri}$lamch( 'SAFE MINIMUM' ) eps = stdlib${ii}$_${ri}$lamch( 'PRECISION' ) smlnum = safmin / eps bignum = one / smlnum rmin = sqrt( smlnum ) rmax = min( sqrt( bignum ), one / sqrt( sqrt( safmin ) ) ) ! scale matrix to allowable range, if necessary. iscale = 0_${ik}$ abstll = abstol if (valeig) then vll = vl vuu = vu end if anrm = stdlib${ii}$_${ri}$lansy( 'M', uplo, n, a, lda, work ) if( anrm>zero .and. anrm<rmin ) then iscale = 1_${ik}$ sigma = rmin / anrm else if( anrm>rmax ) then iscale = 1_${ik}$ sigma = rmax / anrm end if if( iscale==1_${ik}$ ) then if( lower ) then do j = 1, n call stdlib${ii}$_${ri}$scal( n-j+1, sigma, a( j, j ), 1_${ik}$ ) end do else do j = 1, n call stdlib${ii}$_${ri}$scal( j, sigma, a( 1_${ik}$, j ), 1_${ik}$ ) end do end if if( abstol>0_${ik}$ )abstll = abstol*sigma if( valeig ) then vll = vl*sigma vuu = vu*sigma end if end if ! initialize indices into workspaces. note: the iwork indices are ! used only if stdlib${ii}$_${ri}$sterf or stdlib${ii}$_${ri}$stemr fail. ! work(indtau:indtau+n-1) stores the scalar factors of the ! elementary reflectors used in stdlib${ii}$_${ri}$sytrd. indtau = 1_${ik}$ ! work(indd:indd+n-1) stores the tridiagonal's diagonal entries. indd = indtau + n ! work(inde:inde+n-1) stores the off-diagonal entries of the ! tridiagonal matrix from stdlib${ii}$_${ri}$sytrd. inde = indd + n ! work(inddd:inddd+n-1) is a copy of the diagonal entries over ! -written by stdlib${ii}$_${ri}$stemr (the stdlib${ii}$_${ri}$sterf path copies the diagonal to w). inddd = inde + n ! work(indee:indee+n-1) is a copy of the off-diagonal entries over ! -written while computing the eigenvalues in stdlib${ii}$_${ri}$sterf and stdlib${ii}$_${ri}$stemr. indee = inddd + n ! indwk is the starting offset of the left-over workspace, and ! llwork is the remaining workspace size. indwk = indee + n llwork = lwork - indwk + 1_${ik}$ ! iwork(indibl:indibl+m-1) corresponds to iblock in stdlib${ii}$_${ri}$stebz and ! stores the block indices of each of the m<=n eigenvalues. indibl = 1_${ik}$ ! iwork(indisp:indisp+nsplit-1) corresponds to isplit in stdlib${ii}$_${ri}$stebz and ! stores the starting and finishing indices of each block. indisp = indibl + n ! iwork(indifl:indifl+n-1) stores the indices of eigenvectors ! that corresponding to eigenvectors that fail to converge in ! stdlib${ii}$_${ri}$stein. this information is discarded; if any fail, the driver ! returns info > 0. indifl = indisp + n ! indiwo is the offset of the remaining integer workspace. indiwo = indifl + n ! call stdlib${ii}$_${ri}$sytrd to reduce symmetric matrix to tridiagonal form. call stdlib${ii}$_${ri}$sytrd( uplo, n, a, lda, work( indd ), work( inde ),work( indtau ), work( & indwk ), llwork, iinfo ) ! if all eigenvalues are desired ! then call stdlib${ii}$_${ri}$sterf or stdlib${ii}$_${ri}$stemr and stdlib${ii}$_${ri}$ormtr. if( ( alleig .or. ( indeig .and. il==1_${ik}$ .and. iu==n ) ) .and.ieeeok==1_${ik}$ ) then if( .not.wantz ) then call stdlib${ii}$_${ri}$copy( n, work( indd ), 1_${ik}$, w, 1_${ik}$ ) call stdlib${ii}$_${ri}$copy( n-1, work( inde ), 1_${ik}$, work( indee ), 1_${ik}$ ) call stdlib${ii}$_${ri}$sterf( n, w, work( indee ), info ) else call stdlib${ii}$_${ri}$copy( n-1, work( inde ), 1_${ik}$, work( indee ), 1_${ik}$ ) call stdlib${ii}$_${ri}$copy( n, work( indd ), 1_${ik}$, work( inddd ), 1_${ik}$ ) if (abstol <= two*n*eps) then tryrac = .true. else tryrac = .false. end if call stdlib${ii}$_${ri}$stemr( jobz, 'A', n, work( inddd ), work( indee ),vl, vu, il, iu, m,& w, z, ldz, n, isuppz,tryrac, work( indwk ), lwork, iwork, liwork,info ) ! apply orthogonal matrix used in reduction to tridiagonal ! form to eigenvectors returned by stdlib${ii}$_${ri}$stemr. if( wantz .and. info==0_${ik}$ ) then indwkn = inde llwrkn = lwork - indwkn + 1_${ik}$ call stdlib${ii}$_${ri}$ormtr( 'L', uplo, 'N', n, m, a, lda,work( indtau ), z, ldz, work(& indwkn ),llwrkn, iinfo ) end if end if if( info==0_${ik}$ ) then ! everything worked. skip stdlib${ii}$_${ri}$stebz/stdlib${ii}$_${ri}$stein. iwork(:) are ! undefined. m = n go to 30 end if info = 0_${ik}$ end if ! otherwise, call stdlib${ii}$_${ri}$stebz and, if eigenvectors are desired, stdlib${ii}$_${ri}$stein. ! also call stdlib${ii}$_${ri}$stebz and stdlib${ii}$_${ri}$stein if stdlib${ii}$_${ri}$stemr fails. if( wantz ) then order = 'B' else order = 'E' end if call stdlib${ii}$_${ri}$stebz( range, order, n, vll, vuu, il, iu, abstll,work( indd ), work( inde & ), m, nsplit, w,iwork( indibl ), iwork( indisp ), work( indwk ),iwork( indiwo ), info ) if( wantz ) then call stdlib${ii}$_${ri}$stein( n, work( indd ), work( inde ), m, w,iwork( indibl ), iwork( & indisp ), z, ldz,work( indwk ), iwork( indiwo ), iwork( indifl ),info ) ! apply orthogonal matrix used in reduction to tridiagonal ! form to eigenvectors returned by stdlib${ii}$_${ri}$stein. indwkn = inde llwrkn = lwork - indwkn + 1_${ik}$ call stdlib${ii}$_${ri}$ormtr( 'L', uplo, 'N', n, m, a, lda, work( indtau ), z,ldz, work( & indwkn ), llwrkn, iinfo ) end if ! if matrix was scaled, then rescale eigenvalues appropriately. ! jump here if stdlib${ii}$_${ri}$stemr/stdlib${ii}$_${ri}$stein succeeded. 30 continue if( iscale==1_${ik}$ ) then if( info==0_${ik}$ ) then imax = m else imax = info - 1_${ik}$ end if call stdlib${ii}$_${ri}$scal( imax, one / sigma, w, 1_${ik}$ ) end if ! if eigenvalues are not in order, then sort them, along with ! eigenvectors. note: we do not sort the ifail portion of iwork. ! it may not be initialized (if stdlib${ii}$_${ri}$stemr/stdlib${ii}$_${ri}$stein succeeded), and we do ! not return this detailed information to the user. if( wantz ) then do j = 1, m - 1 i = 0_${ik}$ tmp1 = w( j ) do jj = j + 1, m if( w( jj )<tmp1 ) then i = jj tmp1 = w( jj ) end if end do if( i/=0_${ik}$ ) then w( i ) = w( j ) w( j ) = tmp1 call stdlib${ii}$_${ri}$swap( n, z( 1_${ik}$, i ), 1_${ik}$, z( 1_${ik}$, j ), 1_${ik}$ ) end if end do end if ! set work(1) to optimal workspace size. work( 1_${ik}$ ) = lwkopt iwork( 1_${ik}$ ) = liwmin return end subroutine stdlib${ii}$_${ri}$syevr #:endif #:endfor module subroutine stdlib${ii}$_ssyevx( jobz, range, uplo, n, a, lda, vl, vu, il, iu,abstol, m, w, z, ldz, & !! SSYEVX computes selected eigenvalues and, optionally, eigenvectors !! of a real symmetric matrix A. Eigenvalues and eigenvectors can be !! selected by specifying either a range of values or a range of indices !! for the desired eigenvalues. work, lwork, iwork,ifail, 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) :: jobz, range, uplo integer(${ik}$), intent(in) :: il, iu, lda, ldz, lwork, n integer(${ik}$), intent(out) :: info, m real(sp), intent(in) :: abstol, vl, vu ! Array Arguments integer(${ik}$), intent(out) :: ifail(*), iwork(*) real(sp), intent(inout) :: a(lda,*) real(sp), intent(out) :: w(*), work(*), z(ldz,*) ! ===================================================================== ! Local Scalars logical(lk) :: alleig, indeig, lower, lquery, test, valeig, wantz character :: order integer(${ik}$) :: i, iinfo, imax, indd, inde, indee, indibl, indisp, indiwo, indtau, & indwkn, indwrk, iscale, itmp1, j, jj, llwork, llwrkn, lwkmin, lwkopt, nb, & nsplit real(sp) :: abstll, anrm, bignum, eps, rmax, rmin, safmin, sigma, smlnum, tmp1, vll, & vuu ! Intrinsic Functions ! Executable Statements ! test the input parameters. lower = stdlib_lsame( uplo, 'L' ) wantz = stdlib_lsame( jobz, 'V' ) alleig = stdlib_lsame( range, 'A' ) valeig = stdlib_lsame( range, 'V' ) indeig = stdlib_lsame( range, 'I' ) lquery = ( lwork==-1_${ik}$ ) info = 0_${ik}$ if( .not.( wantz .or. stdlib_lsame( jobz, 'N' ) ) ) then info = -1_${ik}$ else if( .not.( alleig .or. valeig .or. indeig ) ) then info = -2_${ik}$ else if( .not.( lower .or. stdlib_lsame( uplo, 'U' ) ) ) then info = -3_${ik}$ else if( n<0_${ik}$ ) then info = -4_${ik}$ else if( lda<max( 1_${ik}$, n ) ) then info = -6_${ik}$ else if( valeig ) then if( n>0_${ik}$ .and. vu<=vl )info = -8_${ik}$ else if( indeig ) then if( il<1_${ik}$ .or. il>max( 1_${ik}$, n ) ) then info = -9_${ik}$ else if( iu<min( n, il ) .or. iu>n ) then info = -10_${ik}$ end if end if end if if( info==0_${ik}$ ) then if( ldz<1_${ik}$ .or. ( wantz .and. ldz<n ) ) then info = -15_${ik}$ end if end if if( info==0_${ik}$ ) then if( n<=1_${ik}$ ) then lwkmin = 1_${ik}$ work( 1_${ik}$ ) = lwkmin else lwkmin = 8_${ik}$*n nb = stdlib${ii}$_ilaenv( 1_${ik}$, 'SSYTRD', uplo, n, -1_${ik}$, -1_${ik}$, -1_${ik}$ ) nb = max( nb, stdlib${ii}$_ilaenv( 1_${ik}$, 'SORMTR', uplo, n, -1_${ik}$, -1_${ik}$, -1_${ik}$ ) ) lwkopt = max( lwkmin, ( nb + 3_${ik}$ )*n ) work( 1_${ik}$ ) = lwkopt end if if( lwork<lwkmin .and. .not.lquery )info = -17_${ik}$ end if if( info/=0_${ik}$ ) then call stdlib${ii}$_xerbla( 'SSYEVX', -info ) return else if( lquery ) then return end if ! quick return if possible m = 0_${ik}$ if( n==0_${ik}$ ) then return end if if( n==1_${ik}$ ) then if( alleig .or. indeig ) then m = 1_${ik}$ w( 1_${ik}$ ) = a( 1_${ik}$, 1_${ik}$ ) else if( vl<a( 1_${ik}$, 1_${ik}$ ) .and. vu>=a( 1_${ik}$, 1_${ik}$ ) ) then m = 1_${ik}$ w( 1_${ik}$ ) = a( 1_${ik}$, 1_${ik}$ ) end if end if if( wantz )z( 1_${ik}$, 1_${ik}$ ) = one return end if ! get machine constants. safmin = stdlib${ii}$_slamch( 'SAFE MINIMUM' ) eps = stdlib${ii}$_slamch( 'PRECISION' ) smlnum = safmin / eps bignum = one / smlnum rmin = sqrt( smlnum ) rmax = min( sqrt( bignum ), one / sqrt( sqrt( safmin ) ) ) ! scale matrix to allowable range, if necessary. iscale = 0_${ik}$ abstll = abstol if( valeig ) then vll = vl vuu = vu end if anrm = stdlib${ii}$_slansy( 'M', uplo, n, a, lda, work ) if( anrm>zero .and. anrm<rmin ) then iscale = 1_${ik}$ sigma = rmin / anrm else if( anrm>rmax ) then iscale = 1_${ik}$ sigma = rmax / anrm end if if( iscale==1_${ik}$ ) then if( lower ) then do j = 1, n call stdlib${ii}$_sscal( n-j+1, sigma, a( j, j ), 1_${ik}$ ) end do else do j = 1, n call stdlib${ii}$_sscal( j, sigma, a( 1_${ik}$, j ), 1_${ik}$ ) end do end if if( abstol>0_${ik}$ )abstll = abstol*sigma if( valeig ) then vll = vl*sigma vuu = vu*sigma end if end if ! call stdlib${ii}$_ssytrd to reduce symmetric matrix to tridiagonal form. indtau = 1_${ik}$ inde = indtau + n indd = inde + n indwrk = indd + n llwork = lwork - indwrk + 1_${ik}$ call stdlib${ii}$_ssytrd( uplo, n, a, lda, work( indd ), work( inde ),work( indtau ), work( & indwrk ), llwork, iinfo ) ! if all eigenvalues are desired and abstol is less than or equal to ! zero, then call stdlib${ii}$_ssterf or stdlib${ii}$_sorgtr and stdlib${ii}$_ssteqr. if this fails for ! some eigenvalue, then try stdlib${ii}$_sstebz. test = .false. if( indeig ) then if( il==1_${ik}$ .and. iu==n ) then test = .true. end if end if if( ( alleig .or. test ) .and. ( abstol<=zero ) ) then call stdlib${ii}$_scopy( n, work( indd ), 1_${ik}$, w, 1_${ik}$ ) indee = indwrk + 2_${ik}$*n if( .not.wantz ) then call stdlib${ii}$_scopy( n-1, work( inde ), 1_${ik}$, work( indee ), 1_${ik}$ ) call stdlib${ii}$_ssterf( n, w, work( indee ), info ) else call stdlib${ii}$_slacpy( 'A', n, n, a, lda, z, ldz ) call stdlib${ii}$_sorgtr( uplo, n, z, ldz, work( indtau ),work( indwrk ), llwork, & iinfo ) call stdlib${ii}$_scopy( n-1, work( inde ), 1_${ik}$, work( indee ), 1_${ik}$ ) call stdlib${ii}$_ssteqr( jobz, n, w, work( indee ), z, ldz,work( indwrk ), info ) if( info==0_${ik}$ ) then do i = 1, n ifail( i ) = 0_${ik}$ end do end if end if if( info==0_${ik}$ ) then m = n go to 40 end if info = 0_${ik}$ end if ! otherwise, call stdlib${ii}$_sstebz and, if eigenvectors are desired, stdlib${ii}$_sstein. if( wantz ) then order = 'B' else order = 'E' end if indibl = 1_${ik}$ indisp = indibl + n indiwo = indisp + n call stdlib${ii}$_sstebz( range, order, n, vll, vuu, il, iu, abstll,work( indd ), work( inde & ), m, nsplit, w,iwork( indibl ), iwork( indisp ), work( indwrk ),iwork( indiwo ), info & ) if( wantz ) then call stdlib${ii}$_sstein( n, work( indd ), work( inde ), m, w,iwork( indibl ), iwork( & indisp ), z, ldz,work( indwrk ), iwork( indiwo ), ifail, info ) ! apply orthogonal matrix used in reduction to tridiagonal ! form to eigenvectors returned by stdlib${ii}$_sstein. indwkn = inde llwrkn = lwork - indwkn + 1_${ik}$ call stdlib${ii}$_sormtr( 'L', uplo, 'N', n, m, a, lda, work( indtau ), z,ldz, work( & indwkn ), llwrkn, iinfo ) end if ! if matrix was scaled, then rescale eigenvalues appropriately. 40 continue if( iscale==1_${ik}$ ) then if( info==0_${ik}$ ) then imax = m else imax = info - 1_${ik}$ end if call stdlib${ii}$_sscal( imax, one / sigma, w, 1_${ik}$ ) end if ! if eigenvalues are not in order, then sort them, along with ! eigenvectors. if( wantz ) then do j = 1, m - 1 i = 0_${ik}$ tmp1 = w( j ) do jj = j + 1, m if( w( jj )<tmp1 ) then i = jj tmp1 = w( jj ) end if end do if( i/=0_${ik}$ ) then itmp1 = iwork( indibl+i-1 ) w( i ) = w( j ) iwork( indibl+i-1 ) = iwork( indibl+j-1 ) w( j ) = tmp1 iwork( indibl+j-1 ) = itmp1 call stdlib${ii}$_sswap( n, z( 1_${ik}$, i ), 1_${ik}$, z( 1_${ik}$, j ), 1_${ik}$ ) if( info/=0_${ik}$ ) then itmp1 = ifail( i ) ifail( i ) = ifail( j ) ifail( j ) = itmp1 end if end if end do end if ! set work(1) to optimal workspace size. work( 1_${ik}$ ) = lwkopt return end subroutine stdlib${ii}$_ssyevx module subroutine stdlib${ii}$_dsyevx( jobz, range, uplo, n, a, lda, vl, vu, il, iu,abstol, m, w, z, ldz, & !! DSYEVX computes selected eigenvalues and, optionally, eigenvectors !! of a real symmetric matrix A. Eigenvalues and eigenvectors can be !! selected by specifying either a range of values or a range of indices !! for the desired eigenvalues. work, lwork, iwork,ifail, 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) :: jobz, range, uplo integer(${ik}$), intent(in) :: il, iu, lda, ldz, lwork, n integer(${ik}$), intent(out) :: info, m real(dp), intent(in) :: abstol, vl, vu ! Array Arguments integer(${ik}$), intent(out) :: ifail(*), iwork(*) real(dp), intent(inout) :: a(lda,*) real(dp), intent(out) :: w(*), work(*), z(ldz,*) ! ===================================================================== ! Local Scalars logical(lk) :: alleig, indeig, lower, lquery, test, valeig, wantz character :: order integer(${ik}$) :: i, iinfo, imax, indd, inde, indee, indibl, indisp, indiwo, indtau, & indwkn, indwrk, iscale, itmp1, j, jj, llwork, llwrkn, lwkmin, lwkopt, nb, & nsplit real(dp) :: abstll, anrm, bignum, eps, rmax, rmin, safmin, sigma, smlnum, tmp1, vll, & vuu ! Intrinsic Functions ! Executable Statements ! test the input parameters. lower = stdlib_lsame( uplo, 'L' ) wantz = stdlib_lsame( jobz, 'V' ) alleig = stdlib_lsame( range, 'A' ) valeig = stdlib_lsame( range, 'V' ) indeig = stdlib_lsame( range, 'I' ) lquery = ( lwork==-1_${ik}$ ) info = 0_${ik}$ if( .not.( wantz .or. stdlib_lsame( jobz, 'N' ) ) ) then info = -1_${ik}$ else if( .not.( alleig .or. valeig .or. indeig ) ) then info = -2_${ik}$ else if( .not.( lower .or. stdlib_lsame( uplo, 'U' ) ) ) then info = -3_${ik}$ else if( n<0_${ik}$ ) then info = -4_${ik}$ else if( lda<max( 1_${ik}$, n ) ) then info = -6_${ik}$ else if( valeig ) then if( n>0_${ik}$ .and. vu<=vl )info = -8_${ik}$ else if( indeig ) then if( il<1_${ik}$ .or. il>max( 1_${ik}$, n ) ) then info = -9_${ik}$ else if( iu<min( n, il ) .or. iu>n ) then info = -10_${ik}$ end if end if end if if( info==0_${ik}$ ) then if( ldz<1_${ik}$ .or. ( wantz .and. ldz<n ) ) then info = -15_${ik}$ end if end if if( info==0_${ik}$ ) then if( n<=1_${ik}$ ) then lwkmin = 1_${ik}$ work( 1_${ik}$ ) = lwkmin else lwkmin = 8_${ik}$*n nb = stdlib${ii}$_ilaenv( 1_${ik}$, 'DSYTRD', uplo, n, -1_${ik}$, -1_${ik}$, -1_${ik}$ ) nb = max( nb, stdlib${ii}$_ilaenv( 1_${ik}$, 'DORMTR', uplo, n, -1_${ik}$, -1_${ik}$, -1_${ik}$ ) ) lwkopt = max( lwkmin, ( nb + 3_${ik}$ )*n ) work( 1_${ik}$ ) = lwkopt end if if( lwork<lwkmin .and. .not.lquery )info = -17_${ik}$ end if if( info/=0_${ik}$ ) then call stdlib${ii}$_xerbla( 'DSYEVX', -info ) return else if( lquery ) then return end if ! quick return if possible m = 0_${ik}$ if( n==0_${ik}$ ) then return end if if( n==1_${ik}$ ) then if( alleig .or. indeig ) then m = 1_${ik}$ w( 1_${ik}$ ) = a( 1_${ik}$, 1_${ik}$ ) else if( vl<a( 1_${ik}$, 1_${ik}$ ) .and. vu>=a( 1_${ik}$, 1_${ik}$ ) ) then m = 1_${ik}$ w( 1_${ik}$ ) = a( 1_${ik}$, 1_${ik}$ ) end if end if if( wantz )z( 1_${ik}$, 1_${ik}$ ) = one return end if ! get machine constants. safmin = stdlib${ii}$_dlamch( 'SAFE MINIMUM' ) eps = stdlib${ii}$_dlamch( 'PRECISION' ) smlnum = safmin / eps bignum = one / smlnum rmin = sqrt( smlnum ) rmax = min( sqrt( bignum ), one / sqrt( sqrt( safmin ) ) ) ! scale matrix to allowable range, if necessary. iscale = 0_${ik}$ abstll = abstol if( valeig ) then vll = vl vuu = vu end if anrm = stdlib${ii}$_dlansy( 'M', uplo, n, a, lda, work ) if( anrm>zero .and. anrm<rmin ) then iscale = 1_${ik}$ sigma = rmin / anrm else if( anrm>rmax ) then iscale = 1_${ik}$ sigma = rmax / anrm end if if( iscale==1_${ik}$ ) then if( lower ) then do j = 1, n call stdlib${ii}$_dscal( n-j+1, sigma, a( j, j ), 1_${ik}$ ) end do else do j = 1, n call stdlib${ii}$_dscal( j, sigma, a( 1_${ik}$, j ), 1_${ik}$ ) end do end if if( abstol>0_${ik}$ )abstll = abstol*sigma if( valeig ) then vll = vl*sigma vuu = vu*sigma end if end if ! call stdlib${ii}$_dsytrd to reduce symmetric matrix to tridiagonal form. indtau = 1_${ik}$ inde = indtau + n indd = inde + n indwrk = indd + n llwork = lwork - indwrk + 1_${ik}$ call stdlib${ii}$_dsytrd( uplo, n, a, lda, work( indd ), work( inde ),work( indtau ), work( & indwrk ), llwork, iinfo ) ! if all eigenvalues are desired and abstol is less than or equal to ! zero, then call stdlib${ii}$_dsterf or stdlib${ii}$_dorgtr and stdlib${ii}$_ssteqr. if this fails for ! some eigenvalue, then try stdlib${ii}$_dstebz. test = .false. if( indeig ) then if( il==1_${ik}$ .and. iu==n ) then test = .true. end if end if if( ( alleig .or. test ) .and. ( abstol<=zero ) ) then call stdlib${ii}$_dcopy( n, work( indd ), 1_${ik}$, w, 1_${ik}$ ) indee = indwrk + 2_${ik}$*n if( .not.wantz ) then call stdlib${ii}$_dcopy( n-1, work( inde ), 1_${ik}$, work( indee ), 1_${ik}$ ) call stdlib${ii}$_dsterf( n, w, work( indee ), info ) else call stdlib${ii}$_dlacpy( 'A', n, n, a, lda, z, ldz ) call stdlib${ii}$_dorgtr( uplo, n, z, ldz, work( indtau ),work( indwrk ), llwork, & iinfo ) call stdlib${ii}$_dcopy( n-1, work( inde ), 1_${ik}$, work( indee ), 1_${ik}$ ) call stdlib${ii}$_dsteqr( jobz, n, w, work( indee ), z, ldz,work( indwrk ), info ) if( info==0_${ik}$ ) then do i = 1, n ifail( i ) = 0_${ik}$ end do end if end if if( info==0_${ik}$ ) then m = n go to 40 end if info = 0_${ik}$ end if ! otherwise, call stdlib${ii}$_dstebz and, if eigenvectors are desired, stdlib${ii}$_sstein. if( wantz ) then order = 'B' else order = 'E' end if indibl = 1_${ik}$ indisp = indibl + n indiwo = indisp + n call stdlib${ii}$_dstebz( range, order, n, vll, vuu, il, iu, abstll,work( indd ), work( inde & ), m, nsplit, w,iwork( indibl ), iwork( indisp ), work( indwrk ),iwork( indiwo ), info & ) if( wantz ) then call stdlib${ii}$_dstein( n, work( indd ), work( inde ), m, w,iwork( indibl ), iwork( & indisp ), z, ldz,work( indwrk ), iwork( indiwo ), ifail, info ) ! apply orthogonal matrix used in reduction to tridiagonal ! form to eigenvectors returned by stdlib${ii}$_dstein. indwkn = inde llwrkn = lwork - indwkn + 1_${ik}$ call stdlib${ii}$_dormtr( 'L', uplo, 'N', n, m, a, lda, work( indtau ), z,ldz, work( & indwkn ), llwrkn, iinfo ) end if ! if matrix was scaled, then rescale eigenvalues appropriately. 40 continue if( iscale==1_${ik}$ ) then if( info==0_${ik}$ ) then imax = m else imax = info - 1_${ik}$ end if call stdlib${ii}$_dscal( imax, one / sigma, w, 1_${ik}$ ) end if ! if eigenvalues are not in order, then sort them, along with ! eigenvectors. if( wantz ) then do j = 1, m - 1 i = 0_${ik}$ tmp1 = w( j ) do jj = j + 1, m if( w( jj )<tmp1 ) then i = jj tmp1 = w( jj ) end if end do if( i/=0_${ik}$ ) then itmp1 = iwork( indibl+i-1 ) w( i ) = w( j ) iwork( indibl+i-1 ) = iwork( indibl+j-1 ) w( j ) = tmp1 iwork( indibl+j-1 ) = itmp1 call stdlib${ii}$_dswap( n, z( 1_${ik}$, i ), 1_${ik}$, z( 1_${ik}$, j ), 1_${ik}$ ) if( info/=0_${ik}$ ) then itmp1 = ifail( i ) ifail( i ) = ifail( j ) ifail( j ) = itmp1 end if end if end do end if ! set work(1) to optimal workspace size. work( 1_${ik}$ ) = lwkopt return end subroutine stdlib${ii}$_dsyevx #:for rk,rt,ri in REAL_KINDS_TYPES #:if not rk in ["sp","dp"] module subroutine stdlib${ii}$_${ri}$syevx( jobz, range, uplo, n, a, lda, vl, vu, il, iu,abstol, m, w, z, ldz, & !! DSYEVX: computes selected eigenvalues and, optionally, eigenvectors !! of a real symmetric matrix A. Eigenvalues and eigenvectors can be !! selected by specifying either a range of values or a range of indices !! for the desired eigenvalues. work, lwork, iwork,ifail, 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) :: jobz, range, uplo integer(${ik}$), intent(in) :: il, iu, lda, ldz, lwork, n integer(${ik}$), intent(out) :: info, m real(${rk}$), intent(in) :: abstol, vl, vu ! Array Arguments integer(${ik}$), intent(out) :: ifail(*), iwork(*) real(${rk}$), intent(inout) :: a(lda,*) real(${rk}$), intent(out) :: w(*), work(*), z(ldz,*) ! ===================================================================== ! Local Scalars logical(lk) :: alleig, indeig, lower, lquery, test, valeig, wantz character :: order integer(${ik}$) :: i, iinfo, imax, indd, inde, indee, indibl, indisp, indiwo, indtau, & indwkn, indwrk, iscale, itmp1, j, jj, llwork, llwrkn, lwkmin, lwkopt, nb, & nsplit real(${rk}$) :: abstll, anrm, bignum, eps, rmax, rmin, safmin, sigma, smlnum, tmp1, vll, & vuu ! Intrinsic Functions ! Executable Statements ! test the input parameters. lower = stdlib_lsame( uplo, 'L' ) wantz = stdlib_lsame( jobz, 'V' ) alleig = stdlib_lsame( range, 'A' ) valeig = stdlib_lsame( range, 'V' ) indeig = stdlib_lsame( range, 'I' ) lquery = ( lwork==-1_${ik}$ ) info = 0_${ik}$ if( .not.( wantz .or. stdlib_lsame( jobz, 'N' ) ) ) then info = -1_${ik}$ else if( .not.( alleig .or. valeig .or. indeig ) ) then info = -2_${ik}$ else if( .not.( lower .or. stdlib_lsame( uplo, 'U' ) ) ) then info = -3_${ik}$ else if( n<0_${ik}$ ) then info = -4_${ik}$ else if( lda<max( 1_${ik}$, n ) ) then info = -6_${ik}$ else if( valeig ) then if( n>0_${ik}$ .and. vu<=vl )info = -8_${ik}$ else if( indeig ) then if( il<1_${ik}$ .or. il>max( 1_${ik}$, n ) ) then info = -9_${ik}$ else if( iu<min( n, il ) .or. iu>n ) then info = -10_${ik}$ end if end if end if if( info==0_${ik}$ ) then if( ldz<1_${ik}$ .or. ( wantz .and. ldz<n ) ) then info = -15_${ik}$ end if end if if( info==0_${ik}$ ) then if( n<=1_${ik}$ ) then lwkmin = 1_${ik}$ work( 1_${ik}$ ) = lwkmin else lwkmin = 8_${ik}$*n nb = stdlib${ii}$_ilaenv( 1_${ik}$, 'DSYTRD', uplo, n, -1_${ik}$, -1_${ik}$, -1_${ik}$ ) nb = max( nb, stdlib${ii}$_ilaenv( 1_${ik}$, 'DORMTR', uplo, n, -1_${ik}$, -1_${ik}$, -1_${ik}$ ) ) lwkopt = max( lwkmin, ( nb + 3_${ik}$ )*n ) work( 1_${ik}$ ) = lwkopt end if if( lwork<lwkmin .and. .not.lquery )info = -17_${ik}$ end if if( info/=0_${ik}$ ) then call stdlib${ii}$_xerbla( 'DSYEVX', -info ) return else if( lquery ) then return end if ! quick return if possible m = 0_${ik}$ if( n==0_${ik}$ ) then return end if if( n==1_${ik}$ ) then if( alleig .or. indeig ) then m = 1_${ik}$ w( 1_${ik}$ ) = a( 1_${ik}$, 1_${ik}$ ) else if( vl<a( 1_${ik}$, 1_${ik}$ ) .and. vu>=a( 1_${ik}$, 1_${ik}$ ) ) then m = 1_${ik}$ w( 1_${ik}$ ) = a( 1_${ik}$, 1_${ik}$ ) end if end if if( wantz )z( 1_${ik}$, 1_${ik}$ ) = one return end if ! get machine constants. safmin = stdlib${ii}$_${ri}$lamch( 'SAFE MINIMUM' ) eps = stdlib${ii}$_${ri}$lamch( 'PRECISION' ) smlnum = safmin / eps bignum = one / smlnum rmin = sqrt( smlnum ) rmax = min( sqrt( bignum ), one / sqrt( sqrt( safmin ) ) ) ! scale matrix to allowable range, if necessary. iscale = 0_${ik}$ abstll = abstol if( valeig ) then vll = vl vuu = vu end if anrm = stdlib${ii}$_${ri}$lansy( 'M', uplo, n, a, lda, work ) if( anrm>zero .and. anrm<rmin ) then iscale = 1_${ik}$ sigma = rmin / anrm else if( anrm>rmax ) then iscale = 1_${ik}$ sigma = rmax / anrm end if if( iscale==1_${ik}$ ) then if( lower ) then do j = 1, n call stdlib${ii}$_${ri}$scal( n-j+1, sigma, a( j, j ), 1_${ik}$ ) end do else do j = 1, n call stdlib${ii}$_${ri}$scal( j, sigma, a( 1_${ik}$, j ), 1_${ik}$ ) end do end if if( abstol>0_${ik}$ )abstll = abstol*sigma if( valeig ) then vll = vl*sigma vuu = vu*sigma end if end if ! call stdlib${ii}$_${ri}$sytrd to reduce symmetric matrix to tridiagonal form. indtau = 1_${ik}$ inde = indtau + n indd = inde + n indwrk = indd + n llwork = lwork - indwrk + 1_${ik}$ call stdlib${ii}$_${ri}$sytrd( uplo, n, a, lda, work( indd ), work( inde ),work( indtau ), work( & indwrk ), llwork, iinfo ) ! if all eigenvalues are desired and abstol is less than or equal to ! zero, then call stdlib${ii}$_${ri}$sterf or stdlib${ii}$_${ri}$orgtr and stdlib${ii}$_dsteqr. if this fails for ! some eigenvalue, then try stdlib${ii}$_${ri}$stebz. test = .false. if( indeig ) then if( il==1_${ik}$ .and. iu==n ) then test = .true. end if end if if( ( alleig .or. test ) .and. ( abstol<=zero ) ) then call stdlib${ii}$_${ri}$copy( n, work( indd ), 1_${ik}$, w, 1_${ik}$ ) indee = indwrk + 2_${ik}$*n if( .not.wantz ) then call stdlib${ii}$_${ri}$copy( n-1, work( inde ), 1_${ik}$, work( indee ), 1_${ik}$ ) call stdlib${ii}$_${ri}$sterf( n, w, work( indee ), info ) else call stdlib${ii}$_${ri}$lacpy( 'A', n, n, a, lda, z, ldz ) call stdlib${ii}$_${ri}$orgtr( uplo, n, z, ldz, work( indtau ),work( indwrk ), llwork, & iinfo ) call stdlib${ii}$_${ri}$copy( n-1, work( inde ), 1_${ik}$, work( indee ), 1_${ik}$ ) call stdlib${ii}$_${ri}$steqr( jobz, n, w, work( indee ), z, ldz,work( indwrk ), info ) if( info==0_${ik}$ ) then do i = 1, n ifail( i ) = 0_${ik}$ end do end if end if if( info==0_${ik}$ ) then m = n go to 40 end if info = 0_${ik}$ end if ! otherwise, call stdlib${ii}$_${ri}$stebz and, if eigenvectors are desired, stdlib${ii}$_dstein. if( wantz ) then order = 'B' else order = 'E' end if indibl = 1_${ik}$ indisp = indibl + n indiwo = indisp + n call stdlib${ii}$_${ri}$stebz( range, order, n, vll, vuu, il, iu, abstll,work( indd ), work( inde & ), m, nsplit, w,iwork( indibl ), iwork( indisp ), work( indwrk ),iwork( indiwo ), info & ) if( wantz ) then call stdlib${ii}$_${ri}$stein( n, work( indd ), work( inde ), m, w,iwork( indibl ), iwork( & indisp ), z, ldz,work( indwrk ), iwork( indiwo ), ifail, info ) ! apply orthogonal matrix used in reduction to tridiagonal ! form to eigenvectors returned by stdlib${ii}$_${ri}$stein. indwkn = inde llwrkn = lwork - indwkn + 1_${ik}$ call stdlib${ii}$_${ri}$ormtr( 'L', uplo, 'N', n, m, a, lda, work( indtau ), z,ldz, work( & indwkn ), llwrkn, iinfo ) end if ! if matrix was scaled, then rescale eigenvalues appropriately. 40 continue if( iscale==1_${ik}$ ) then if( info==0_${ik}$ ) then imax = m else imax = info - 1_${ik}$ end if call stdlib${ii}$_${ri}$scal( imax, one / sigma, w, 1_${ik}$ ) end if ! if eigenvalues are not in order, then sort them, along with ! eigenvectors. if( wantz ) then do j = 1, m - 1 i = 0_${ik}$ tmp1 = w( j ) do jj = j + 1, m if( w( jj )<tmp1 ) then i = jj tmp1 = w( jj ) end if end do if( i/=0_${ik}$ ) then itmp1 = iwork( indibl+i-1 ) w( i ) = w( j ) iwork( indibl+i-1 ) = iwork( indibl+j-1 ) w( j ) = tmp1 iwork( indibl+j-1 ) = itmp1 call stdlib${ii}$_${ri}$swap( n, z( 1_${ik}$, i ), 1_${ik}$, z( 1_${ik}$, j ), 1_${ik}$ ) if( info/=0_${ik}$ ) then itmp1 = ifail( i ) ifail( i ) = ifail( j ) ifail( j ) = itmp1 end if end if end do end if ! set work(1) to optimal workspace size. work( 1_${ik}$ ) = lwkopt return end subroutine stdlib${ii}$_${ri}$syevx #:endif #:endfor module subroutine stdlib${ii}$_sspev( jobz, uplo, n, ap, w, z, ldz, work, info ) !! SSPEV computes all the eigenvalues and, optionally, eigenvectors of a !! real symmetric matrix A in packed storage. ! -- 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) :: jobz, uplo integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: ldz, n ! Array Arguments real(sp), intent(inout) :: ap(*) real(sp), intent(out) :: w(*), work(*), z(ldz,*) ! ===================================================================== ! Local Scalars logical(lk) :: wantz integer(${ik}$) :: iinfo, imax, inde, indtau, indwrk, iscale real(sp) :: anrm, bignum, eps, rmax, rmin, safmin, sigma, smlnum ! Intrinsic Functions ! Executable Statements ! test the input parameters. wantz = stdlib_lsame( jobz, 'V' ) info = 0_${ik}$ if( .not.( wantz .or. stdlib_lsame( jobz, 'N' ) ) ) then info = -1_${ik}$ else if( .not.( stdlib_lsame( uplo, 'U' ) .or. stdlib_lsame( uplo, 'L' ) ) )& then info = -2_${ik}$ else if( n<0_${ik}$ ) then info = -3_${ik}$ else if( ldz<1_${ik}$ .or. ( wantz .and. ldz<n ) ) then info = -7_${ik}$ end if if( info/=0_${ik}$ ) then call stdlib${ii}$_xerbla( 'SSPEV ', -info ) return end if ! quick return if possible if( n==0 )return if( n==1_${ik}$ ) then w( 1_${ik}$ ) = ap( 1_${ik}$ ) if( wantz )z( 1_${ik}$, 1_${ik}$ ) = one return end if ! get machine constants. safmin = stdlib${ii}$_slamch( 'SAFE MINIMUM' ) eps = stdlib${ii}$_slamch( 'PRECISION' ) smlnum = safmin / eps bignum = one / smlnum rmin = sqrt( smlnum ) rmax = sqrt( bignum ) ! scale matrix to allowable range, if necessary. anrm = stdlib${ii}$_slansp( 'M', uplo, n, ap, work ) iscale = 0_${ik}$ if( anrm>zero .and. anrm<rmin ) then iscale = 1_${ik}$ sigma = rmin / anrm else if( anrm>rmax ) then iscale = 1_${ik}$ sigma = rmax / anrm end if if( iscale==1_${ik}$ ) then call stdlib${ii}$_sscal( ( n*( n+1 ) ) / 2_${ik}$, sigma, ap, 1_${ik}$ ) end if ! call stdlib${ii}$_ssptrd to reduce symmetric packed matrix to tridiagonal form. inde = 1_${ik}$ indtau = inde + n call stdlib${ii}$_ssptrd( uplo, n, ap, w, work( inde ), work( indtau ), iinfo ) ! for eigenvalues only, call stdlib${ii}$_ssterf. for eigenvectors, first call ! stdlib${ii}$_sopgtr to generate the orthogonal matrix, then call stdlib${ii}$_ssteqr. if( .not.wantz ) then call stdlib${ii}$_ssterf( n, w, work( inde ), info ) else indwrk = indtau + n call stdlib${ii}$_sopgtr( uplo, n, ap, work( indtau ), z, ldz,work( indwrk ), iinfo ) call stdlib${ii}$_ssteqr( jobz, n, w, work( inde ), z, ldz, work( indtau ),info ) end if ! if matrix was scaled, then rescale eigenvalues appropriately. if( iscale==1_${ik}$ ) then if( info==0_${ik}$ ) then imax = n else imax = info - 1_${ik}$ end if call stdlib${ii}$_sscal( imax, one / sigma, w, 1_${ik}$ ) end if return end subroutine stdlib${ii}$_sspev module subroutine stdlib${ii}$_dspev( jobz, uplo, n, ap, w, z, ldz, work, info ) !! DSPEV computes all the eigenvalues and, optionally, eigenvectors of a !! real symmetric matrix A in packed storage. ! -- 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) :: jobz, uplo integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: ldz, n ! Array Arguments real(dp), intent(inout) :: ap(*) real(dp), intent(out) :: w(*), work(*), z(ldz,*) ! ===================================================================== ! Local Scalars logical(lk) :: wantz integer(${ik}$) :: iinfo, imax, inde, indtau, indwrk, iscale real(dp) :: anrm, bignum, eps, rmax, rmin, safmin, sigma, smlnum ! Intrinsic Functions ! Executable Statements ! test the input parameters. wantz = stdlib_lsame( jobz, 'V' ) info = 0_${ik}$ if( .not.( wantz .or. stdlib_lsame( jobz, 'N' ) ) ) then info = -1_${ik}$ else if( .not.( stdlib_lsame( uplo, 'U' ) .or. stdlib_lsame( uplo, 'L' ) ) )& then info = -2_${ik}$ else if( n<0_${ik}$ ) then info = -3_${ik}$ else if( ldz<1_${ik}$ .or. ( wantz .and. ldz<n ) ) then info = -7_${ik}$ end if if( info/=0_${ik}$ ) then call stdlib${ii}$_xerbla( 'DSPEV ', -info ) return end if ! quick return if possible if( n==0 )return if( n==1_${ik}$ ) then w( 1_${ik}$ ) = ap( 1_${ik}$ ) if( wantz )z( 1_${ik}$, 1_${ik}$ ) = one return end if ! get machine constants. safmin = stdlib${ii}$_dlamch( 'SAFE MINIMUM' ) eps = stdlib${ii}$_dlamch( 'PRECISION' ) smlnum = safmin / eps bignum = one / smlnum rmin = sqrt( smlnum ) rmax = sqrt( bignum ) ! scale matrix to allowable range, if necessary. anrm = stdlib${ii}$_dlansp( 'M', uplo, n, ap, work ) iscale = 0_${ik}$ if( anrm>zero .and. anrm<rmin ) then iscale = 1_${ik}$ sigma = rmin / anrm else if( anrm>rmax ) then iscale = 1_${ik}$ sigma = rmax / anrm end if if( iscale==1_${ik}$ ) then call stdlib${ii}$_dscal( ( n*( n+1 ) ) / 2_${ik}$, sigma, ap, 1_${ik}$ ) end if ! call stdlib${ii}$_dsptrd to reduce symmetric packed matrix to tridiagonal form. inde = 1_${ik}$ indtau = inde + n call stdlib${ii}$_dsptrd( uplo, n, ap, w, work( inde ), work( indtau ), iinfo ) ! for eigenvalues only, call stdlib${ii}$_dsterf. for eigenvectors, first call ! stdlib${ii}$_dopgtr to generate the orthogonal matrix, then call stdlib${ii}$_dsteqr. if( .not.wantz ) then call stdlib${ii}$_dsterf( n, w, work( inde ), info ) else indwrk = indtau + n call stdlib${ii}$_dopgtr( uplo, n, ap, work( indtau ), z, ldz,work( indwrk ), iinfo ) call stdlib${ii}$_dsteqr( jobz, n, w, work( inde ), z, ldz, work( indtau ),info ) end if ! if matrix was scaled, then rescale eigenvalues appropriately. if( iscale==1_${ik}$ ) then if( info==0_${ik}$ ) then imax = n else imax = info - 1_${ik}$ end if call stdlib${ii}$_dscal( imax, one / sigma, w, 1_${ik}$ ) end if return end subroutine stdlib${ii}$_dspev #:for rk,rt,ri in REAL_KINDS_TYPES #:if not rk in ["sp","dp"] module subroutine stdlib${ii}$_${ri}$spev( jobz, uplo, n, ap, w, z, ldz, work, info ) !! DSPEV: computes all the eigenvalues and, optionally, eigenvectors of a !! real symmetric matrix A in packed storage. ! -- 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) :: jobz, uplo integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: ldz, n ! Array Arguments real(${rk}$), intent(inout) :: ap(*) real(${rk}$), intent(out) :: w(*), work(*), z(ldz,*) ! ===================================================================== ! Local Scalars logical(lk) :: wantz integer(${ik}$) :: iinfo, imax, inde, indtau, indwrk, iscale real(${rk}$) :: anrm, bignum, eps, rmax, rmin, safmin, sigma, smlnum ! Intrinsic Functions ! Executable Statements ! test the input parameters. wantz = stdlib_lsame( jobz, 'V' ) info = 0_${ik}$ if( .not.( wantz .or. stdlib_lsame( jobz, 'N' ) ) ) then info = -1_${ik}$ else if( .not.( stdlib_lsame( uplo, 'U' ) .or. stdlib_lsame( uplo, 'L' ) ) )& then info = -2_${ik}$ else if( n<0_${ik}$ ) then info = -3_${ik}$ else if( ldz<1_${ik}$ .or. ( wantz .and. ldz<n ) ) then info = -7_${ik}$ end if if( info/=0_${ik}$ ) then call stdlib${ii}$_xerbla( 'DSPEV ', -info ) return end if ! quick return if possible if( n==0 )return if( n==1_${ik}$ ) then w( 1_${ik}$ ) = ap( 1_${ik}$ ) if( wantz )z( 1_${ik}$, 1_${ik}$ ) = one return end if ! get machine constants. safmin = stdlib${ii}$_${ri}$lamch( 'SAFE MINIMUM' ) eps = stdlib${ii}$_${ri}$lamch( 'PRECISION' ) smlnum = safmin / eps bignum = one / smlnum rmin = sqrt( smlnum ) rmax = sqrt( bignum ) ! scale matrix to allowable range, if necessary. anrm = stdlib${ii}$_${ri}$lansp( 'M', uplo, n, ap, work ) iscale = 0_${ik}$ if( anrm>zero .and. anrm<rmin ) then iscale = 1_${ik}$ sigma = rmin / anrm else if( anrm>rmax ) then iscale = 1_${ik}$ sigma = rmax / anrm end if if( iscale==1_${ik}$ ) then call stdlib${ii}$_${ri}$scal( ( n*( n+1 ) ) / 2_${ik}$, sigma, ap, 1_${ik}$ ) end if ! call stdlib${ii}$_${ri}$sptrd to reduce symmetric packed matrix to tridiagonal form. inde = 1_${ik}$ indtau = inde + n call stdlib${ii}$_${ri}$sptrd( uplo, n, ap, w, work( inde ), work( indtau ), iinfo ) ! for eigenvalues only, call stdlib${ii}$_${ri}$sterf. for eigenvectors, first call ! stdlib${ii}$_${ri}$opgtr to generate the orthogonal matrix, then call stdlib${ii}$_${ri}$steqr. if( .not.wantz ) then call stdlib${ii}$_${ri}$sterf( n, w, work( inde ), info ) else indwrk = indtau + n call stdlib${ii}$_${ri}$opgtr( uplo, n, ap, work( indtau ), z, ldz,work( indwrk ), iinfo ) call stdlib${ii}$_${ri}$steqr( jobz, n, w, work( inde ), z, ldz, work( indtau ),info ) end if ! if matrix was scaled, then rescale eigenvalues appropriately. if( iscale==1_${ik}$ ) then if( info==0_${ik}$ ) then imax = n else imax = info - 1_${ik}$ end if call stdlib${ii}$_${ri}$scal( imax, one / sigma, w, 1_${ik}$ ) end if return end subroutine stdlib${ii}$_${ri}$spev #:endif #:endfor module subroutine stdlib${ii}$_sspevd( jobz, uplo, n, ap, w, z, ldz, work, lwork,iwork, liwork, info ) !! SSPEVD computes all the eigenvalues and, optionally, eigenvectors !! of a real symmetric matrix A in packed storage. If eigenvectors are !! desired, it uses a divide and conquer algorithm. !! The divide and conquer algorithm makes very mild assumptions about !! floating point arithmetic. It will work on machines with a guard !! digit in add/subtract, or on those binary machines without guard !! digits which subtract like the Cray X-MP, Cray Y-MP, Cray C-90, or !! Cray-2. It could conceivably fail on hexadecimal or decimal machines !! without guard digits, but we know of none. ! -- 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) :: jobz, uplo integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: ldz, liwork, lwork, n ! Array Arguments integer(${ik}$), intent(out) :: iwork(*) real(sp), intent(inout) :: ap(*) real(sp), intent(out) :: w(*), work(*), z(ldz,*) ! ===================================================================== ! Local Scalars logical(lk) :: lquery, wantz integer(${ik}$) :: iinfo, inde, indtau, indwrk, iscale, liwmin, llwork, lwmin real(sp) :: anrm, bignum, eps, rmax, rmin, safmin, sigma, smlnum ! Intrinsic Functions ! Executable Statements ! test the input parameters. wantz = stdlib_lsame( jobz, 'V' ) lquery = ( lwork==-1_${ik}$ .or. liwork==-1_${ik}$ ) info = 0_${ik}$ if( .not.( wantz .or. stdlib_lsame( jobz, 'N' ) ) ) then info = -1_${ik}$ else if( .not.( stdlib_lsame( uplo, 'U' ) .or. stdlib_lsame( uplo, 'L' ) ) )& then info = -2_${ik}$ else if( n<0_${ik}$ ) then info = -3_${ik}$ else if( ldz<1_${ik}$ .or. ( wantz .and. ldz<n ) ) then info = -7_${ik}$ end if if( info==0_${ik}$ ) then if( n<=1_${ik}$ ) then liwmin = 1_${ik}$ lwmin = 1_${ik}$ else if( wantz ) then liwmin = 3_${ik}$ + 5_${ik}$*n lwmin = 1_${ik}$ + 6_${ik}$*n + n**2_${ik}$ else liwmin = 1_${ik}$ lwmin = 2_${ik}$*n end if end if iwork( 1_${ik}$ ) = liwmin work( 1_${ik}$ ) = lwmin if( lwork<lwmin .and. .not.lquery ) then info = -9_${ik}$ else if( liwork<liwmin .and. .not.lquery ) then info = -11_${ik}$ end if end if if( info/=0_${ik}$ ) then call stdlib${ii}$_xerbla( 'SSPEVD', -info ) return else if( lquery ) then return end if ! quick return if possible if( n==0 )return if( n==1_${ik}$ ) then w( 1_${ik}$ ) = ap( 1_${ik}$ ) if( wantz )z( 1_${ik}$, 1_${ik}$ ) = one return end if ! get machine constants. safmin = stdlib${ii}$_slamch( 'SAFE MINIMUM' ) eps = stdlib${ii}$_slamch( 'PRECISION' ) smlnum = safmin / eps bignum = one / smlnum rmin = sqrt( smlnum ) rmax = sqrt( bignum ) ! scale matrix to allowable range, if necessary. anrm = stdlib${ii}$_slansp( 'M', uplo, n, ap, work ) iscale = 0_${ik}$ if( anrm>zero .and. anrm<rmin ) then iscale = 1_${ik}$ sigma = rmin / anrm else if( anrm>rmax ) then iscale = 1_${ik}$ sigma = rmax / anrm end if if( iscale==1_${ik}$ ) then call stdlib${ii}$_sscal( ( n*( n+1 ) ) / 2_${ik}$, sigma, ap, 1_${ik}$ ) end if ! call stdlib${ii}$_ssptrd to reduce symmetric packed matrix to tridiagonal form. inde = 1_${ik}$ indtau = inde + n call stdlib${ii}$_ssptrd( uplo, n, ap, w, work( inde ), work( indtau ), iinfo ) ! for eigenvalues only, call stdlib${ii}$_ssterf. for eigenvectors, first call ! stdlib${ii}$_sstedc to generate the eigenvector matrix, work(indwrk), of the ! tridiagonal matrix, then call stdlib${ii}$_sopmtr to multiply it by the ! householder transformations represented in ap. if( .not.wantz ) then call stdlib${ii}$_ssterf( n, w, work( inde ), info ) else indwrk = indtau + n llwork = lwork - indwrk + 1_${ik}$ call stdlib${ii}$_sstedc( 'I', n, w, work( inde ), z, ldz, work( indwrk ),llwork, iwork, & liwork, info ) call stdlib${ii}$_sopmtr( 'L', uplo, 'N', n, n, ap, work( indtau ), z, ldz,work( indwrk ),& iinfo ) end if ! if matrix was scaled, then rescale eigenvalues appropriately. if( iscale==1_${ik}$ )call stdlib${ii}$_sscal( n, one / sigma, w, 1_${ik}$ ) work( 1_${ik}$ ) = lwmin iwork( 1_${ik}$ ) = liwmin return end subroutine stdlib${ii}$_sspevd module subroutine stdlib${ii}$_dspevd( jobz, uplo, n, ap, w, z, ldz, work, lwork,iwork, liwork, info ) !! DSPEVD computes all the eigenvalues and, optionally, eigenvectors !! of a real symmetric matrix A in packed storage. If eigenvectors are !! desired, it uses a divide and conquer algorithm. !! The divide and conquer algorithm makes very mild assumptions about !! floating point arithmetic. It will work on machines with a guard !! digit in add/subtract, or on those binary machines without guard !! digits which subtract like the Cray X-MP, Cray Y-MP, Cray C-90, or !! Cray-2. It could conceivably fail on hexadecimal or decimal machines !! without guard digits, but we know of none. ! -- 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) :: jobz, uplo integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: ldz, liwork, lwork, n ! Array Arguments integer(${ik}$), intent(out) :: iwork(*) real(dp), intent(inout) :: ap(*) real(dp), intent(out) :: w(*), work(*), z(ldz,*) ! ===================================================================== ! Local Scalars logical(lk) :: lquery, wantz integer(${ik}$) :: iinfo, inde, indtau, indwrk, iscale, liwmin, llwork, lwmin real(dp) :: anrm, bignum, eps, rmax, rmin, safmin, sigma, smlnum ! Intrinsic Functions ! Executable Statements ! test the input parameters. wantz = stdlib_lsame( jobz, 'V' ) lquery = ( lwork==-1_${ik}$ .or. liwork==-1_${ik}$ ) info = 0_${ik}$ if( .not.( wantz .or. stdlib_lsame( jobz, 'N' ) ) ) then info = -1_${ik}$ else if( .not.( stdlib_lsame( uplo, 'U' ) .or. stdlib_lsame( uplo, 'L' ) ) )& then info = -2_${ik}$ else if( n<0_${ik}$ ) then info = -3_${ik}$ else if( ldz<1_${ik}$ .or. ( wantz .and. ldz<n ) ) then info = -7_${ik}$ end if if( info==0_${ik}$ ) then if( n<=1_${ik}$ ) then liwmin = 1_${ik}$ lwmin = 1_${ik}$ else if( wantz ) then liwmin = 3_${ik}$ + 5_${ik}$*n lwmin = 1_${ik}$ + 6_${ik}$*n + n**2_${ik}$ else liwmin = 1_${ik}$ lwmin = 2_${ik}$*n end if end if iwork( 1_${ik}$ ) = liwmin work( 1_${ik}$ ) = lwmin if( lwork<lwmin .and. .not.lquery ) then info = -9_${ik}$ else if( liwork<liwmin .and. .not.lquery ) then info = -11_${ik}$ end if end if if( info/=0_${ik}$ ) then call stdlib${ii}$_xerbla( 'DSPEVD', -info ) return else if( lquery ) then return end if ! quick return if possible if( n==0 )return if( n==1_${ik}$ ) then w( 1_${ik}$ ) = ap( 1_${ik}$ ) if( wantz )z( 1_${ik}$, 1_${ik}$ ) = one return end if ! get machine constants. safmin = stdlib${ii}$_dlamch( 'SAFE MINIMUM' ) eps = stdlib${ii}$_dlamch( 'PRECISION' ) smlnum = safmin / eps bignum = one / smlnum rmin = sqrt( smlnum ) rmax = sqrt( bignum ) ! scale matrix to allowable range, if necessary. anrm = stdlib${ii}$_dlansp( 'M', uplo, n, ap, work ) iscale = 0_${ik}$ if( anrm>zero .and. anrm<rmin ) then iscale = 1_${ik}$ sigma = rmin / anrm else if( anrm>rmax ) then iscale = 1_${ik}$ sigma = rmax / anrm end if if( iscale==1_${ik}$ ) then call stdlib${ii}$_dscal( ( n*( n+1 ) ) / 2_${ik}$, sigma, ap, 1_${ik}$ ) end if ! call stdlib${ii}$_dsptrd to reduce symmetric packed matrix to tridiagonal form. inde = 1_${ik}$ indtau = inde + n call stdlib${ii}$_dsptrd( uplo, n, ap, w, work( inde ), work( indtau ), iinfo ) ! for eigenvalues only, call stdlib${ii}$_dsterf. for eigenvectors, first call ! stdlib${ii}$_dstedc to generate the eigenvector matrix, work(indwrk), of the ! tridiagonal matrix, then call stdlib${ii}$_dopmtr to multiply it by the ! householder transformations represented in ap. if( .not.wantz ) then call stdlib${ii}$_dsterf( n, w, work( inde ), info ) else indwrk = indtau + n llwork = lwork - indwrk + 1_${ik}$ call stdlib${ii}$_dstedc( 'I', n, w, work( inde ), z, ldz, work( indwrk ),llwork, iwork, & liwork, info ) call stdlib${ii}$_dopmtr( 'L', uplo, 'N', n, n, ap, work( indtau ), z, ldz,work( indwrk ),& iinfo ) end if ! if matrix was scaled, then rescale eigenvalues appropriately. if( iscale==1_${ik}$ )call stdlib${ii}$_dscal( n, one / sigma, w, 1_${ik}$ ) work( 1_${ik}$ ) = lwmin iwork( 1_${ik}$ ) = liwmin return end subroutine stdlib${ii}$_dspevd #:for rk,rt,ri in REAL_KINDS_TYPES #:if not rk in ["sp","dp"] module subroutine stdlib${ii}$_${ri}$spevd( jobz, uplo, n, ap, w, z, ldz, work, lwork,iwork, liwork, info ) !! DSPEVD: computes all the eigenvalues and, optionally, eigenvectors !! of a real symmetric matrix A in packed storage. If eigenvectors are !! desired, it uses a divide and conquer algorithm. !! The divide and conquer algorithm makes very mild assumptions about !! floating point arithmetic. It will work on machines with a guard !! digit in add/subtract, or on those binary machines without guard !! digits which subtract like the Cray X-MP, Cray Y-MP, Cray C-90, or !! Cray-2. It could conceivably fail on hexadecimal or decimal machines !! without guard digits, but we know of none. ! -- 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) :: jobz, uplo integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: ldz, liwork, lwork, n ! Array Arguments integer(${ik}$), intent(out) :: iwork(*) real(${rk}$), intent(inout) :: ap(*) real(${rk}$), intent(out) :: w(*), work(*), z(ldz,*) ! ===================================================================== ! Local Scalars logical(lk) :: lquery, wantz integer(${ik}$) :: iinfo, inde, indtau, indwrk, iscale, liwmin, llwork, lwmin real(${rk}$) :: anrm, bignum, eps, rmax, rmin, safmin, sigma, smlnum ! Intrinsic Functions ! Executable Statements ! test the input parameters. wantz = stdlib_lsame( jobz, 'V' ) lquery = ( lwork==-1_${ik}$ .or. liwork==-1_${ik}$ ) info = 0_${ik}$ if( .not.( wantz .or. stdlib_lsame( jobz, 'N' ) ) ) then info = -1_${ik}$ else if( .not.( stdlib_lsame( uplo, 'U' ) .or. stdlib_lsame( uplo, 'L' ) ) )& then info = -2_${ik}$ else if( n<0_${ik}$ ) then info = -3_${ik}$ else if( ldz<1_${ik}$ .or. ( wantz .and. ldz<n ) ) then info = -7_${ik}$ end if if( info==0_${ik}$ ) then if( n<=1_${ik}$ ) then liwmin = 1_${ik}$ lwmin = 1_${ik}$ else if( wantz ) then liwmin = 3_${ik}$ + 5_${ik}$*n lwmin = 1_${ik}$ + 6_${ik}$*n + n**2_${ik}$ else liwmin = 1_${ik}$ lwmin = 2_${ik}$*n end if end if iwork( 1_${ik}$ ) = liwmin work( 1_${ik}$ ) = lwmin if( lwork<lwmin .and. .not.lquery ) then info = -9_${ik}$ else if( liwork<liwmin .and. .not.lquery ) then info = -11_${ik}$ end if end if if( info/=0_${ik}$ ) then call stdlib${ii}$_xerbla( 'DSPEVD', -info ) return else if( lquery ) then return end if ! quick return if possible if( n==0 )return if( n==1_${ik}$ ) then w( 1_${ik}$ ) = ap( 1_${ik}$ ) if( wantz )z( 1_${ik}$, 1_${ik}$ ) = one return end if ! get machine constants. safmin = stdlib${ii}$_${ri}$lamch( 'SAFE MINIMUM' ) eps = stdlib${ii}$_${ri}$lamch( 'PRECISION' ) smlnum = safmin / eps bignum = one / smlnum rmin = sqrt( smlnum ) rmax = sqrt( bignum ) ! scale matrix to allowable range, if necessary. anrm = stdlib${ii}$_${ri}$lansp( 'M', uplo, n, ap, work ) iscale = 0_${ik}$ if( anrm>zero .and. anrm<rmin ) then iscale = 1_${ik}$ sigma = rmin / anrm else if( anrm>rmax ) then iscale = 1_${ik}$ sigma = rmax / anrm end if if( iscale==1_${ik}$ ) then call stdlib${ii}$_${ri}$scal( ( n*( n+1 ) ) / 2_${ik}$, sigma, ap, 1_${ik}$ ) end if ! call stdlib${ii}$_${ri}$sptrd to reduce symmetric packed matrix to tridiagonal form. inde = 1_${ik}$ indtau = inde + n call stdlib${ii}$_${ri}$sptrd( uplo, n, ap, w, work( inde ), work( indtau ), iinfo ) ! for eigenvalues only, call stdlib${ii}$_${ri}$sterf. for eigenvectors, first call ! stdlib${ii}$_${ri}$stedc to generate the eigenvector matrix, work(indwrk), of the ! tridiagonal matrix, then call stdlib${ii}$_${ri}$opmtr to multiply it by the ! householder transformations represented in ap. if( .not.wantz ) then call stdlib${ii}$_${ri}$sterf( n, w, work( inde ), info ) else indwrk = indtau + n llwork = lwork - indwrk + 1_${ik}$ call stdlib${ii}$_${ri}$stedc( 'I', n, w, work( inde ), z, ldz, work( indwrk ),llwork, iwork, & liwork, info ) call stdlib${ii}$_${ri}$opmtr( 'L', uplo, 'N', n, n, ap, work( indtau ), z, ldz,work( indwrk ),& iinfo ) end if ! if matrix was scaled, then rescale eigenvalues appropriately. if( iscale==1_${ik}$ )call stdlib${ii}$_${ri}$scal( n, one / sigma, w, 1_${ik}$ ) work( 1_${ik}$ ) = lwmin iwork( 1_${ik}$ ) = liwmin return end subroutine stdlib${ii}$_${ri}$spevd #:endif #:endfor module subroutine stdlib${ii}$_sspevx( jobz, range, uplo, n, ap, vl, vu, il, iu,abstol, m, w, z, ldz, & !! SSPEVX computes selected eigenvalues and, optionally, eigenvectors !! of a real symmetric matrix A in packed storage. Eigenvalues/vectors !! can be selected by specifying either a range of values or a range of !! indices for the desired eigenvalues. work, iwork, ifail,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) :: jobz, range, uplo integer(${ik}$), intent(in) :: il, iu, ldz, n integer(${ik}$), intent(out) :: info, m real(sp), intent(in) :: abstol, vl, vu ! Array Arguments integer(${ik}$), intent(out) :: ifail(*), iwork(*) real(sp), intent(inout) :: ap(*) real(sp), intent(out) :: w(*), work(*), z(ldz,*) ! ===================================================================== ! Local Scalars logical(lk) :: alleig, indeig, test, valeig, wantz character :: order integer(${ik}$) :: i, iinfo, imax, indd, inde, indee, indibl, indisp, indiwo, indtau, & indwrk, iscale, itmp1, j, jj, nsplit real(sp) :: abstll, anrm, bignum, eps, rmax, rmin, safmin, sigma, smlnum, tmp1, vll, & vuu ! Intrinsic Functions ! Executable Statements ! test the input parameters. wantz = stdlib_lsame( jobz, 'V' ) alleig = stdlib_lsame( range, 'A' ) valeig = stdlib_lsame( range, 'V' ) indeig = stdlib_lsame( range, 'I' ) info = 0_${ik}$ if( .not.( wantz .or. stdlib_lsame( jobz, 'N' ) ) ) then info = -1_${ik}$ else if( .not.( alleig .or. valeig .or. indeig ) ) then info = -2_${ik}$ else if( .not.( stdlib_lsame( uplo, 'L' ) .or. stdlib_lsame( uplo, 'U' ) ) )& then info = -3_${ik}$ else if( n<0_${ik}$ ) then info = -4_${ik}$ else if( valeig ) then if( n>0_${ik}$ .and. vu<=vl )info = -7_${ik}$ else if( indeig ) then if( il<1_${ik}$ .or. il>max( 1_${ik}$, n ) ) then info = -8_${ik}$ else if( iu<min( n, il ) .or. iu>n ) then info = -9_${ik}$ end if end if end if if( info==0_${ik}$ ) then if( ldz<1_${ik}$ .or. ( wantz .and. ldz<n ) )info = -14_${ik}$ end if if( info/=0_${ik}$ ) then call stdlib${ii}$_xerbla( 'SSPEVX', -info ) return end if ! quick return if possible m = 0_${ik}$ if( n==0 )return if( n==1_${ik}$ ) then if( alleig .or. indeig ) then m = 1_${ik}$ w( 1_${ik}$ ) = ap( 1_${ik}$ ) else if( vl<ap( 1_${ik}$ ) .and. vu>=ap( 1_${ik}$ ) ) then m = 1_${ik}$ w( 1_${ik}$ ) = ap( 1_${ik}$ ) end if end if if( wantz )z( 1_${ik}$, 1_${ik}$ ) = one return end if ! get machine constants. safmin = stdlib${ii}$_slamch( 'SAFE MINIMUM' ) eps = stdlib${ii}$_slamch( 'PRECISION' ) smlnum = safmin / eps bignum = one / smlnum rmin = sqrt( smlnum ) rmax = min( sqrt( bignum ), one / sqrt( sqrt( safmin ) ) ) ! scale matrix to allowable range, if necessary. iscale = 0_${ik}$ abstll = abstol if ( valeig ) then vll = vl vuu = vu else vll = zero vuu = zero endif anrm = stdlib${ii}$_slansp( 'M', uplo, n, ap, work ) if( anrm>zero .and. anrm<rmin ) then iscale = 1_${ik}$ sigma = rmin / anrm else if( anrm>rmax ) then iscale = 1_${ik}$ sigma = rmax / anrm end if if( iscale==1_${ik}$ ) then call stdlib${ii}$_sscal( ( n*( n+1 ) ) / 2_${ik}$, sigma, ap, 1_${ik}$ ) if( abstol>0_${ik}$ )abstll = abstol*sigma if( valeig ) then vll = vl*sigma vuu = vu*sigma end if end if ! call stdlib${ii}$_ssptrd to reduce symmetric packed matrix to tridiagonal form. indtau = 1_${ik}$ inde = indtau + n indd = inde + n indwrk = indd + n call stdlib${ii}$_ssptrd( uplo, n, ap, work( indd ), work( inde ),work( indtau ), iinfo ) ! if all eigenvalues are desired and abstol is less than or equal ! to zero, then call stdlib${ii}$_ssterf or stdlib${ii}$_sopgtr and stdlib${ii}$_ssteqr. if this fails ! for some eigenvalue, then try stdlib${ii}$_sstebz. test = .false. if (indeig) then if (il==1_${ik}$ .and. iu==n) then test = .true. end if end if if ((alleig .or. test) .and. (abstol<=zero)) then call stdlib${ii}$_scopy( n, work( indd ), 1_${ik}$, w, 1_${ik}$ ) indee = indwrk + 2_${ik}$*n if( .not.wantz ) then call stdlib${ii}$_scopy( n-1, work( inde ), 1_${ik}$, work( indee ), 1_${ik}$ ) call stdlib${ii}$_ssterf( n, w, work( indee ), info ) else call stdlib${ii}$_sopgtr( uplo, n, ap, work( indtau ), z, ldz,work( indwrk ), iinfo ) call stdlib${ii}$_scopy( n-1, work( inde ), 1_${ik}$, work( indee ), 1_${ik}$ ) call stdlib${ii}$_ssteqr( jobz, n, w, work( indee ), z, ldz,work( indwrk ), info ) if( info==0_${ik}$ ) then do i = 1, n ifail( i ) = 0_${ik}$ end do end if end if if( info==0_${ik}$ ) then m = n go to 20 end if info = 0_${ik}$ end if ! otherwise, call stdlib${ii}$_sstebz and, if eigenvectors are desired, stdlib${ii}$_sstein. if( wantz ) then order = 'B' else order = 'E' end if indibl = 1_${ik}$ indisp = indibl + n indiwo = indisp + n call stdlib${ii}$_sstebz( range, order, n, vll, vuu, il, iu, abstll,work( indd ), work( inde & ), m, nsplit, w,iwork( indibl ), iwork( indisp ), work( indwrk ),iwork( indiwo ), info & ) if( wantz ) then call stdlib${ii}$_sstein( n, work( indd ), work( inde ), m, w,iwork( indibl ), iwork( & indisp ), z, ldz,work( indwrk ), iwork( indiwo ), ifail, info ) ! apply orthogonal matrix used in reduction to tridiagonal ! form to eigenvectors returned by stdlib${ii}$_sstein. call stdlib${ii}$_sopmtr( 'L', uplo, 'N', n, m, ap, work( indtau ), z, ldz,work( indwrk ),& iinfo ) end if ! if matrix was scaled, then rescale eigenvalues appropriately. 20 continue if( iscale==1_${ik}$ ) then if( info==0_${ik}$ ) then imax = m else imax = info - 1_${ik}$ end if call stdlib${ii}$_sscal( imax, one / sigma, w, 1_${ik}$ ) end if ! if eigenvalues are not in order, then sort them, along with ! eigenvectors. if( wantz ) then do j = 1, m - 1 i = 0_${ik}$ tmp1 = w( j ) do jj = j + 1, m if( w( jj )<tmp1 ) then i = jj tmp1 = w( jj ) end if end do if( i/=0_${ik}$ ) then itmp1 = iwork( indibl+i-1 ) w( i ) = w( j ) iwork( indibl+i-1 ) = iwork( indibl+j-1 ) w( j ) = tmp1 iwork( indibl+j-1 ) = itmp1 call stdlib${ii}$_sswap( n, z( 1_${ik}$, i ), 1_${ik}$, z( 1_${ik}$, j ), 1_${ik}$ ) if( info/=0_${ik}$ ) then itmp1 = ifail( i ) ifail( i ) = ifail( j ) ifail( j ) = itmp1 end if end if end do end if return end subroutine stdlib${ii}$_sspevx module subroutine stdlib${ii}$_dspevx( jobz, range, uplo, n, ap, vl, vu, il, iu,abstol, m, w, z, ldz, & !! DSPEVX computes selected eigenvalues and, optionally, eigenvectors !! of a real symmetric matrix A in packed storage. Eigenvalues/vectors !! can be selected by specifying either a range of values or a range of !! indices for the desired eigenvalues. work, iwork, ifail,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) :: jobz, range, uplo integer(${ik}$), intent(in) :: il, iu, ldz, n integer(${ik}$), intent(out) :: info, m real(dp), intent(in) :: abstol, vl, vu ! Array Arguments integer(${ik}$), intent(out) :: ifail(*), iwork(*) real(dp), intent(inout) :: ap(*) real(dp), intent(out) :: w(*), work(*), z(ldz,*) ! ===================================================================== ! Local Scalars logical(lk) :: alleig, indeig, test, valeig, wantz character :: order integer(${ik}$) :: i, iinfo, imax, indd, inde, indee, indibl, indisp, indiwo, indtau, & indwrk, iscale, itmp1, j, jj, nsplit real(dp) :: abstll, anrm, bignum, eps, rmax, rmin, safmin, sigma, smlnum, tmp1, vll, & vuu ! Intrinsic Functions ! Executable Statements ! test the input parameters. wantz = stdlib_lsame( jobz, 'V' ) alleig = stdlib_lsame( range, 'A' ) valeig = stdlib_lsame( range, 'V' ) indeig = stdlib_lsame( range, 'I' ) info = 0_${ik}$ if( .not.( wantz .or. stdlib_lsame( jobz, 'N' ) ) ) then info = -1_${ik}$ else if( .not.( alleig .or. valeig .or. indeig ) ) then info = -2_${ik}$ else if( .not.( stdlib_lsame( uplo, 'L' ) .or. stdlib_lsame( uplo, 'U' ) ) )& then info = -3_${ik}$ else if( n<0_${ik}$ ) then info = -4_${ik}$ else if( valeig ) then if( n>0_${ik}$ .and. vu<=vl )info = -7_${ik}$ else if( indeig ) then if( il<1_${ik}$ .or. il>max( 1_${ik}$, n ) ) then info = -8_${ik}$ else if( iu<min( n, il ) .or. iu>n ) then info = -9_${ik}$ end if end if end if if( info==0_${ik}$ ) then if( ldz<1_${ik}$ .or. ( wantz .and. ldz<n ) )info = -14_${ik}$ end if if( info/=0_${ik}$ ) then call stdlib${ii}$_xerbla( 'DSPEVX', -info ) return end if ! quick return if possible m = 0_${ik}$ if( n==0 )return if( n==1_${ik}$ ) then if( alleig .or. indeig ) then m = 1_${ik}$ w( 1_${ik}$ ) = ap( 1_${ik}$ ) else if( vl<ap( 1_${ik}$ ) .and. vu>=ap( 1_${ik}$ ) ) then m = 1_${ik}$ w( 1_${ik}$ ) = ap( 1_${ik}$ ) end if end if if( wantz )z( 1_${ik}$, 1_${ik}$ ) = one return end if ! get machine constants. safmin = stdlib${ii}$_dlamch( 'SAFE MINIMUM' ) eps = stdlib${ii}$_dlamch( 'PRECISION' ) smlnum = safmin / eps bignum = one / smlnum rmin = sqrt( smlnum ) rmax = min( sqrt( bignum ), one / sqrt( sqrt( safmin ) ) ) ! scale matrix to allowable range, if necessary. iscale = 0_${ik}$ abstll = abstol if( valeig ) then vll = vl vuu = vu else vll = zero vuu = zero end if anrm = stdlib${ii}$_dlansp( 'M', uplo, n, ap, work ) if( anrm>zero .and. anrm<rmin ) then iscale = 1_${ik}$ sigma = rmin / anrm else if( anrm>rmax ) then iscale = 1_${ik}$ sigma = rmax / anrm end if if( iscale==1_${ik}$ ) then call stdlib${ii}$_dscal( ( n*( n+1 ) ) / 2_${ik}$, sigma, ap, 1_${ik}$ ) if( abstol>0_${ik}$ )abstll = abstol*sigma if( valeig ) then vll = vl*sigma vuu = vu*sigma end if end if ! call stdlib${ii}$_dsptrd to reduce symmetric packed matrix to tridiagonal form. indtau = 1_${ik}$ inde = indtau + n indd = inde + n indwrk = indd + n call stdlib${ii}$_dsptrd( uplo, n, ap, work( indd ), work( inde ),work( indtau ), iinfo ) ! if all eigenvalues are desired and abstol is less than or equal ! to zero, then call stdlib${ii}$_dsterf or stdlib${ii}$_dopgtr and stdlib${ii}$_ssteqr. if this fails ! for some eigenvalue, then try stdlib${ii}$_dstebz. test = .false. if (indeig) then if (il==1_${ik}$ .and. iu==n) then test = .true. end if end if if ((alleig .or. test) .and. (abstol<=zero)) then call stdlib${ii}$_dcopy( n, work( indd ), 1_${ik}$, w, 1_${ik}$ ) indee = indwrk + 2_${ik}$*n if( .not.wantz ) then call stdlib${ii}$_dcopy( n-1, work( inde ), 1_${ik}$, work( indee ), 1_${ik}$ ) call stdlib${ii}$_dsterf( n, w, work( indee ), info ) else call stdlib${ii}$_dopgtr( uplo, n, ap, work( indtau ), z, ldz,work( indwrk ), iinfo ) call stdlib${ii}$_dcopy( n-1, work( inde ), 1_${ik}$, work( indee ), 1_${ik}$ ) call stdlib${ii}$_dsteqr( jobz, n, w, work( indee ), z, ldz,work( indwrk ), info ) if( info==0_${ik}$ ) then do i = 1, n ifail( i ) = 0_${ik}$ end do end if end if if( info==0_${ik}$ ) then m = n go to 20 end if info = 0_${ik}$ end if ! otherwise, call stdlib${ii}$_dstebz and, if eigenvectors are desired, stdlib${ii}$_sstein. if( wantz ) then order = 'B' else order = 'E' end if indibl = 1_${ik}$ indisp = indibl + n indiwo = indisp + n call stdlib${ii}$_dstebz( range, order, n, vll, vuu, il, iu, abstll,work( indd ), work( inde & ), m, nsplit, w,iwork( indibl ), iwork( indisp ), work( indwrk ),iwork( indiwo ), info & ) if( wantz ) then call stdlib${ii}$_dstein( n, work( indd ), work( inde ), m, w,iwork( indibl ), iwork( & indisp ), z, ldz,work( indwrk ), iwork( indiwo ), ifail, info ) ! apply orthogonal matrix used in reduction to tridiagonal ! form to eigenvectors returned by stdlib${ii}$_dstein. call stdlib${ii}$_dopmtr( 'L', uplo, 'N', n, m, ap, work( indtau ), z, ldz,work( indwrk ),& iinfo ) end if ! if matrix was scaled, then rescale eigenvalues appropriately. 20 continue if( iscale==1_${ik}$ ) then if( info==0_${ik}$ ) then imax = m else imax = info - 1_${ik}$ end if call stdlib${ii}$_dscal( imax, one / sigma, w, 1_${ik}$ ) end if ! if eigenvalues are not in order, then sort them, along with ! eigenvectors. if( wantz ) then do j = 1, m - 1 i = 0_${ik}$ tmp1 = w( j ) do jj = j + 1, m if( w( jj )<tmp1 ) then i = jj tmp1 = w( jj ) end if end do if( i/=0_${ik}$ ) then itmp1 = iwork( indibl+i-1 ) w( i ) = w( j ) iwork( indibl+i-1 ) = iwork( indibl+j-1 ) w( j ) = tmp1 iwork( indibl+j-1 ) = itmp1 call stdlib${ii}$_dswap( n, z( 1_${ik}$, i ), 1_${ik}$, z( 1_${ik}$, j ), 1_${ik}$ ) if( info/=0_${ik}$ ) then itmp1 = ifail( i ) ifail( i ) = ifail( j ) ifail( j ) = itmp1 end if end if end do end if return end subroutine stdlib${ii}$_dspevx #:for rk,rt,ri in REAL_KINDS_TYPES #:if not rk in ["sp","dp"] module subroutine stdlib${ii}$_${ri}$spevx( jobz, range, uplo, n, ap, vl, vu, il, iu,abstol, m, w, z, ldz, & !! DSPEVX: computes selected eigenvalues and, optionally, eigenvectors !! of a real symmetric matrix A in packed storage. Eigenvalues/vectors !! can be selected by specifying either a range of values or a range of !! indices for the desired eigenvalues. work, iwork, ifail,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) :: jobz, range, uplo integer(${ik}$), intent(in) :: il, iu, ldz, n integer(${ik}$), intent(out) :: info, m real(${rk}$), intent(in) :: abstol, vl, vu ! Array Arguments integer(${ik}$), intent(out) :: ifail(*), iwork(*) real(${rk}$), intent(inout) :: ap(*) real(${rk}$), intent(out) :: w(*), work(*), z(ldz,*) ! ===================================================================== ! Local Scalars logical(lk) :: alleig, indeig, test, valeig, wantz character :: order integer(${ik}$) :: i, iinfo, imax, indd, inde, indee, indibl, indisp, indiwo, indtau, & indwrk, iscale, itmp1, j, jj, nsplit real(${rk}$) :: abstll, anrm, bignum, eps, rmax, rmin, safmin, sigma, smlnum, tmp1, vll, & vuu ! Intrinsic Functions ! Executable Statements ! test the input parameters. wantz = stdlib_lsame( jobz, 'V' ) alleig = stdlib_lsame( range, 'A' ) valeig = stdlib_lsame( range, 'V' ) indeig = stdlib_lsame( range, 'I' ) info = 0_${ik}$ if( .not.( wantz .or. stdlib_lsame( jobz, 'N' ) ) ) then info = -1_${ik}$ else if( .not.( alleig .or. valeig .or. indeig ) ) then info = -2_${ik}$ else if( .not.( stdlib_lsame( uplo, 'L' ) .or. stdlib_lsame( uplo, 'U' ) ) )& then info = -3_${ik}$ else if( n<0_${ik}$ ) then info = -4_${ik}$ else if( valeig ) then if( n>0_${ik}$ .and. vu<=vl )info = -7_${ik}$ else if( indeig ) then if( il<1_${ik}$ .or. il>max( 1_${ik}$, n ) ) then info = -8_${ik}$ else if( iu<min( n, il ) .or. iu>n ) then info = -9_${ik}$ end if end if end if if( info==0_${ik}$ ) then if( ldz<1_${ik}$ .or. ( wantz .and. ldz<n ) )info = -14_${ik}$ end if if( info/=0_${ik}$ ) then call stdlib${ii}$_xerbla( 'DSPEVX', -info ) return end if ! quick return if possible m = 0_${ik}$ if( n==0 )return if( n==1_${ik}$ ) then if( alleig .or. indeig ) then m = 1_${ik}$ w( 1_${ik}$ ) = ap( 1_${ik}$ ) else if( vl<ap( 1_${ik}$ ) .and. vu>=ap( 1_${ik}$ ) ) then m = 1_${ik}$ w( 1_${ik}$ ) = ap( 1_${ik}$ ) end if end if if( wantz )z( 1_${ik}$, 1_${ik}$ ) = one return end if ! get machine constants. safmin = stdlib${ii}$_${ri}$lamch( 'SAFE MINIMUM' ) eps = stdlib${ii}$_${ri}$lamch( 'PRECISION' ) smlnum = safmin / eps bignum = one / smlnum rmin = sqrt( smlnum ) rmax = min( sqrt( bignum ), one / sqrt( sqrt( safmin ) ) ) ! scale matrix to allowable range, if necessary. iscale = 0_${ik}$ abstll = abstol if( valeig ) then vll = vl vuu = vu else vll = zero vuu = zero end if anrm = stdlib${ii}$_${ri}$lansp( 'M', uplo, n, ap, work ) if( anrm>zero .and. anrm<rmin ) then iscale = 1_${ik}$ sigma = rmin / anrm else if( anrm>rmax ) then iscale = 1_${ik}$ sigma = rmax / anrm end if if( iscale==1_${ik}$ ) then call stdlib${ii}$_${ri}$scal( ( n*( n+1 ) ) / 2_${ik}$, sigma, ap, 1_${ik}$ ) if( abstol>0_${ik}$ )abstll = abstol*sigma if( valeig ) then vll = vl*sigma vuu = vu*sigma end if end if ! call stdlib${ii}$_${ri}$sptrd to reduce symmetric packed matrix to tridiagonal form. indtau = 1_${ik}$ inde = indtau + n indd = inde + n indwrk = indd + n call stdlib${ii}$_${ri}$sptrd( uplo, n, ap, work( indd ), work( inde ),work( indtau ), iinfo ) ! if all eigenvalues are desired and abstol is less than or equal ! to zero, then call stdlib${ii}$_${ri}$sterf or stdlib${ii}$_${ri}$opgtr and stdlib${ii}$_dsteqr. if this fails ! for some eigenvalue, then try stdlib${ii}$_${ri}$stebz. test = .false. if (indeig) then if (il==1_${ik}$ .and. iu==n) then test = .true. end if end if if ((alleig .or. test) .and. (abstol<=zero)) then call stdlib${ii}$_${ri}$copy( n, work( indd ), 1_${ik}$, w, 1_${ik}$ ) indee = indwrk + 2_${ik}$*n if( .not.wantz ) then call stdlib${ii}$_${ri}$copy( n-1, work( inde ), 1_${ik}$, work( indee ), 1_${ik}$ ) call stdlib${ii}$_${ri}$sterf( n, w, work( indee ), info ) else call stdlib${ii}$_${ri}$opgtr( uplo, n, ap, work( indtau ), z, ldz,work( indwrk ), iinfo ) call stdlib${ii}$_${ri}$copy( n-1, work( inde ), 1_${ik}$, work( indee ), 1_${ik}$ ) call stdlib${ii}$_${ri}$steqr( jobz, n, w, work( indee ), z, ldz,work( indwrk ), info ) if( info==0_${ik}$ ) then do i = 1, n ifail( i ) = 0_${ik}$ end do end if end if if( info==0_${ik}$ ) then m = n go to 20 end if info = 0_${ik}$ end if ! otherwise, call stdlib${ii}$_${ri}$stebz and, if eigenvectors are desired, stdlib${ii}$_dstein. if( wantz ) then order = 'B' else order = 'E' end if indibl = 1_${ik}$ indisp = indibl + n indiwo = indisp + n call stdlib${ii}$_${ri}$stebz( range, order, n, vll, vuu, il, iu, abstll,work( indd ), work( inde & ), m, nsplit, w,iwork( indibl ), iwork( indisp ), work( indwrk ),iwork( indiwo ), info & ) if( wantz ) then call stdlib${ii}$_${ri}$stein( n, work( indd ), work( inde ), m, w,iwork( indibl ), iwork( & indisp ), z, ldz,work( indwrk ), iwork( indiwo ), ifail, info ) ! apply orthogonal matrix used in reduction to tridiagonal ! form to eigenvectors returned by stdlib${ii}$_${ri}$stein. call stdlib${ii}$_${ri}$opmtr( 'L', uplo, 'N', n, m, ap, work( indtau ), z, ldz,work( indwrk ),& iinfo ) end if ! if matrix was scaled, then rescale eigenvalues appropriately. 20 continue if( iscale==1_${ik}$ ) then if( info==0_${ik}$ ) then imax = m else imax = info - 1_${ik}$ end if call stdlib${ii}$_${ri}$scal( imax, one / sigma, w, 1_${ik}$ ) end if ! if eigenvalues are not in order, then sort them, along with ! eigenvectors. if( wantz ) then do j = 1, m - 1 i = 0_${ik}$ tmp1 = w( j ) do jj = j + 1, m if( w( jj )<tmp1 ) then i = jj tmp1 = w( jj ) end if end do if( i/=0_${ik}$ ) then itmp1 = iwork( indibl+i-1 ) w( i ) = w( j ) iwork( indibl+i-1 ) = iwork( indibl+j-1 ) w( j ) = tmp1 iwork( indibl+j-1 ) = itmp1 call stdlib${ii}$_${ri}$swap( n, z( 1_${ik}$, i ), 1_${ik}$, z( 1_${ik}$, j ), 1_${ik}$ ) if( info/=0_${ik}$ ) then itmp1 = ifail( i ) ifail( i ) = ifail( j ) ifail( j ) = itmp1 end if end if end do end if return end subroutine stdlib${ii}$_${ri}$spevx #:endif #:endfor module subroutine stdlib${ii}$_ssbev( jobz, uplo, n, kd, ab, ldab, w, z, ldz, work,info ) !! SSBEV computes all the eigenvalues and, optionally, eigenvectors of !! a real symmetric band matrix A. ! -- 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) :: jobz, uplo integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: kd, ldab, ldz, n ! Array Arguments real(sp), intent(inout) :: ab(ldab,*) real(sp), intent(out) :: w(*), work(*), z(ldz,*) ! ===================================================================== ! Local Scalars logical(lk) :: lower, wantz integer(${ik}$) :: iinfo, imax, inde, indwrk, iscale real(sp) :: anrm, bignum, eps, rmax, rmin, safmin, sigma, smlnum ! Intrinsic Functions ! Executable Statements ! test the input parameters. wantz = stdlib_lsame( jobz, 'V' ) lower = stdlib_lsame( uplo, 'L' ) info = 0_${ik}$ if( .not.( wantz .or. stdlib_lsame( jobz, 'N' ) ) ) then info = -1_${ik}$ else if( .not.( lower .or. stdlib_lsame( uplo, 'U' ) ) ) then info = -2_${ik}$ else if( n<0_${ik}$ ) then info = -3_${ik}$ else if( kd<0_${ik}$ ) then info = -4_${ik}$ else if( ldab<kd+1 ) then info = -6_${ik}$ else if( ldz<1_${ik}$ .or. ( wantz .and. ldz<n ) ) then info = -9_${ik}$ end if if( info/=0_${ik}$ ) then call stdlib${ii}$_xerbla( 'SSBEV ', -info ) return end if ! quick return if possible if( n==0 )return if( n==1_${ik}$ ) then if( lower ) then w( 1_${ik}$ ) = ab( 1_${ik}$, 1_${ik}$ ) else w( 1_${ik}$ ) = ab( kd+1, 1_${ik}$ ) end if if( wantz )z( 1_${ik}$, 1_${ik}$ ) = one return end if ! get machine constants. safmin = stdlib${ii}$_slamch( 'SAFE MINIMUM' ) eps = stdlib${ii}$_slamch( 'PRECISION' ) smlnum = safmin / eps bignum = one / smlnum rmin = sqrt( smlnum ) rmax = sqrt( bignum ) ! scale matrix to allowable range, if necessary. anrm = stdlib${ii}$_slansb( 'M', uplo, n, kd, ab, ldab, work ) iscale = 0_${ik}$ if( anrm>zero .and. anrm<rmin ) then iscale = 1_${ik}$ sigma = rmin / anrm else if( anrm>rmax ) then iscale = 1_${ik}$ sigma = rmax / anrm end if if( iscale==1_${ik}$ ) then if( lower ) then call stdlib${ii}$_slascl( 'B', kd, kd, one, sigma, n, n, ab, ldab, info ) else call stdlib${ii}$_slascl( 'Q', kd, kd, one, sigma, n, n, ab, ldab, info ) end if end if ! call stdlib${ii}$_ssbtrd to reduce symmetric band matrix to tridiagonal form. inde = 1_${ik}$ indwrk = inde + n call stdlib${ii}$_ssbtrd( jobz, uplo, n, kd, ab, ldab, w, work( inde ), z, ldz,work( indwrk )& , iinfo ) ! for eigenvalues only, call stdlib${ii}$_ssterf. for eigenvectors, call stdlib${ii}$_ssteqr. if( .not.wantz ) then call stdlib${ii}$_ssterf( n, w, work( inde ), info ) else call stdlib${ii}$_ssteqr( jobz, n, w, work( inde ), z, ldz, work( indwrk ),info ) end if ! if matrix was scaled, then rescale eigenvalues appropriately. if( iscale==1_${ik}$ ) then if( info==0_${ik}$ ) then imax = n else imax = info - 1_${ik}$ end if call stdlib${ii}$_sscal( imax, one / sigma, w, 1_${ik}$ ) end if return end subroutine stdlib${ii}$_ssbev module subroutine stdlib${ii}$_dsbev( jobz, uplo, n, kd, ab, ldab, w, z, ldz, work,info ) !! DSBEV computes all the eigenvalues and, optionally, eigenvectors of !! a real symmetric band matrix A. ! -- 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) :: jobz, uplo integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: kd, ldab, ldz, n ! Array Arguments real(dp), intent(inout) :: ab(ldab,*) real(dp), intent(out) :: w(*), work(*), z(ldz,*) ! ===================================================================== ! Local Scalars logical(lk) :: lower, wantz integer(${ik}$) :: iinfo, imax, inde, indwrk, iscale real(dp) :: anrm, bignum, eps, rmax, rmin, safmin, sigma, smlnum ! Intrinsic Functions ! Executable Statements ! test the input parameters. wantz = stdlib_lsame( jobz, 'V' ) lower = stdlib_lsame( uplo, 'L' ) info = 0_${ik}$ if( .not.( wantz .or. stdlib_lsame( jobz, 'N' ) ) ) then info = -1_${ik}$ else if( .not.( lower .or. stdlib_lsame( uplo, 'U' ) ) ) then info = -2_${ik}$ else if( n<0_${ik}$ ) then info = -3_${ik}$ else if( kd<0_${ik}$ ) then info = -4_${ik}$ else if( ldab<kd+1 ) then info = -6_${ik}$ else if( ldz<1_${ik}$ .or. ( wantz .and. ldz<n ) ) then info = -9_${ik}$ end if if( info/=0_${ik}$ ) then call stdlib${ii}$_xerbla( 'DSBEV ', -info ) return end if ! quick return if possible if( n==0 )return if( n==1_${ik}$ ) then if( lower ) then w( 1_${ik}$ ) = ab( 1_${ik}$, 1_${ik}$ ) else w( 1_${ik}$ ) = ab( kd+1, 1_${ik}$ ) end if if( wantz )z( 1_${ik}$, 1_${ik}$ ) = one return end if ! get machine constants. safmin = stdlib${ii}$_dlamch( 'SAFE MINIMUM' ) eps = stdlib${ii}$_dlamch( 'PRECISION' ) smlnum = safmin / eps bignum = one / smlnum rmin = sqrt( smlnum ) rmax = sqrt( bignum ) ! scale matrix to allowable range, if necessary. anrm = stdlib${ii}$_dlansb( 'M', uplo, n, kd, ab, ldab, work ) iscale = 0_${ik}$ if( anrm>zero .and. anrm<rmin ) then iscale = 1_${ik}$ sigma = rmin / anrm else if( anrm>rmax ) then iscale = 1_${ik}$ sigma = rmax / anrm end if if( iscale==1_${ik}$ ) then if( lower ) then call stdlib${ii}$_dlascl( 'B', kd, kd, one, sigma, n, n, ab, ldab, info ) else call stdlib${ii}$_dlascl( 'Q', kd, kd, one, sigma, n, n, ab, ldab, info ) end if end if ! call stdlib${ii}$_dsbtrd to reduce symmetric band matrix to tridiagonal form. inde = 1_${ik}$ indwrk = inde + n call stdlib${ii}$_dsbtrd( jobz, uplo, n, kd, ab, ldab, w, work( inde ), z, ldz,work( indwrk )& , iinfo ) ! for eigenvalues only, call stdlib${ii}$_dsterf. for eigenvectors, call stdlib${ii}$_ssteqr. if( .not.wantz ) then call stdlib${ii}$_dsterf( n, w, work( inde ), info ) else call stdlib${ii}$_dsteqr( jobz, n, w, work( inde ), z, ldz, work( indwrk ),info ) end if ! if matrix was scaled, then rescale eigenvalues appropriately. if( iscale==1_${ik}$ ) then if( info==0_${ik}$ ) then imax = n else imax = info - 1_${ik}$ end if call stdlib${ii}$_dscal( imax, one / sigma, w, 1_${ik}$ ) end if return end subroutine stdlib${ii}$_dsbev #:for rk,rt,ri in REAL_KINDS_TYPES #:if not rk in ["sp","dp"] module subroutine stdlib${ii}$_${ri}$sbev( jobz, uplo, n, kd, ab, ldab, w, z, ldz, work,info ) !! DSBEV: computes all the eigenvalues and, optionally, eigenvectors of !! a real symmetric band matrix A. ! -- 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) :: jobz, uplo integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: kd, ldab, ldz, n ! Array Arguments real(${rk}$), intent(inout) :: ab(ldab,*) real(${rk}$), intent(out) :: w(*), work(*), z(ldz,*) ! ===================================================================== ! Local Scalars logical(lk) :: lower, wantz integer(${ik}$) :: iinfo, imax, inde, indwrk, iscale real(${rk}$) :: anrm, bignum, eps, rmax, rmin, safmin, sigma, smlnum ! Intrinsic Functions ! Executable Statements ! test the input parameters. wantz = stdlib_lsame( jobz, 'V' ) lower = stdlib_lsame( uplo, 'L' ) info = 0_${ik}$ if( .not.( wantz .or. stdlib_lsame( jobz, 'N' ) ) ) then info = -1_${ik}$ else if( .not.( lower .or. stdlib_lsame( uplo, 'U' ) ) ) then info = -2_${ik}$ else if( n<0_${ik}$ ) then info = -3_${ik}$ else if( kd<0_${ik}$ ) then info = -4_${ik}$ else if( ldab<kd+1 ) then info = -6_${ik}$ else if( ldz<1_${ik}$ .or. ( wantz .and. ldz<n ) ) then info = -9_${ik}$ end if if( info/=0_${ik}$ ) then call stdlib${ii}$_xerbla( 'DSBEV ', -info ) return end if ! quick return if possible if( n==0 )return if( n==1_${ik}$ ) then if( lower ) then w( 1_${ik}$ ) = ab( 1_${ik}$, 1_${ik}$ ) else w( 1_${ik}$ ) = ab( kd+1, 1_${ik}$ ) end if if( wantz )z( 1_${ik}$, 1_${ik}$ ) = one return end if ! get machine constants. safmin = stdlib${ii}$_${ri}$lamch( 'SAFE MINIMUM' ) eps = stdlib${ii}$_${ri}$lamch( 'PRECISION' ) smlnum = safmin / eps bignum = one / smlnum rmin = sqrt( smlnum ) rmax = sqrt( bignum ) ! scale matrix to allowable range, if necessary. anrm = stdlib${ii}$_${ri}$lansb( 'M', uplo, n, kd, ab, ldab, work ) iscale = 0_${ik}$ if( anrm>zero .and. anrm<rmin ) then iscale = 1_${ik}$ sigma = rmin / anrm else if( anrm>rmax ) then iscale = 1_${ik}$ sigma = rmax / anrm end if if( iscale==1_${ik}$ ) then if( lower ) then call stdlib${ii}$_${ri}$lascl( 'B', kd, kd, one, sigma, n, n, ab, ldab, info ) else call stdlib${ii}$_${ri}$lascl( 'Q', kd, kd, one, sigma, n, n, ab, ldab, info ) end if end if ! call stdlib${ii}$_${ri}$sbtrd to reduce symmetric band matrix to tridiagonal form. inde = 1_${ik}$ indwrk = inde + n call stdlib${ii}$_${ri}$sbtrd( jobz, uplo, n, kd, ab, ldab, w, work( inde ), z, ldz,work( indwrk )& , iinfo ) ! for eigenvalues only, call stdlib${ii}$_${ri}$sterf. for eigenvectors, call stdlib${ii}$_dsteqr. if( .not.wantz ) then call stdlib${ii}$_${ri}$sterf( n, w, work( inde ), info ) else call stdlib${ii}$_${ri}$steqr( jobz, n, w, work( inde ), z, ldz, work( indwrk ),info ) end if ! if matrix was scaled, then rescale eigenvalues appropriately. if( iscale==1_${ik}$ ) then if( info==0_${ik}$ ) then imax = n else imax = info - 1_${ik}$ end if call stdlib${ii}$_${ri}$scal( imax, one / sigma, w, 1_${ik}$ ) end if return end subroutine stdlib${ii}$_${ri}$sbev #:endif #:endfor module subroutine stdlib${ii}$_ssbevd( jobz, uplo, n, kd, ab, ldab, w, z, ldz, work,lwork, iwork, liwork, & !! SSBEVD computes all the eigenvalues and, optionally, eigenvectors of !! a real symmetric band matrix A. If eigenvectors are desired, it uses !! a divide and conquer algorithm. !! The divide and conquer algorithm makes very mild assumptions about !! floating point arithmetic. It will work on machines with a guard !! digit in add/subtract, or on those binary machines without guard !! digits which subtract like the Cray X-MP, Cray Y-MP, Cray C-90, or !! Cray-2. It could conceivably fail on hexadecimal or decimal machines !! without guard digits, but we know of none. 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) :: jobz, uplo integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: kd, ldab, ldz, liwork, lwork, n ! Array Arguments integer(${ik}$), intent(out) :: iwork(*) real(sp), intent(inout) :: ab(ldab,*) real(sp), intent(out) :: w(*), work(*), z(ldz,*) ! ===================================================================== ! Local Scalars logical(lk) :: lower, lquery, wantz integer(${ik}$) :: iinfo, inde, indwk2, indwrk, iscale, liwmin, llwrk2, lwmin real(sp) :: anrm, bignum, eps, rmax, rmin, safmin, sigma, smlnum ! Intrinsic Functions ! Executable Statements ! test the input parameters. wantz = stdlib_lsame( jobz, 'V' ) lower = stdlib_lsame( uplo, 'L' ) lquery = ( lwork==-1_${ik}$ .or. liwork==-1_${ik}$ ) info = 0_${ik}$ if( n<=1_${ik}$ ) then liwmin = 1_${ik}$ lwmin = 1_${ik}$ else if( wantz ) then liwmin = 3_${ik}$ + 5_${ik}$*n lwmin = 1_${ik}$ + 5_${ik}$*n + 2_${ik}$*n**2_${ik}$ else liwmin = 1_${ik}$ lwmin = 2_${ik}$*n end if end if if( .not.( wantz .or. stdlib_lsame( jobz, 'N' ) ) ) then info = -1_${ik}$ else if( .not.( lower .or. stdlib_lsame( uplo, 'U' ) ) ) then info = -2_${ik}$ else if( n<0_${ik}$ ) then info = -3_${ik}$ else if( kd<0_${ik}$ ) then info = -4_${ik}$ else if( ldab<kd+1 ) then info = -6_${ik}$ else if( ldz<1_${ik}$ .or. ( wantz .and. ldz<n ) ) then info = -9_${ik}$ end if if( info==0_${ik}$ ) then work( 1_${ik}$ ) = lwmin iwork( 1_${ik}$ ) = liwmin if( lwork<lwmin .and. .not.lquery ) then info = -11_${ik}$ else if( liwork<liwmin .and. .not.lquery ) then info = -13_${ik}$ end if end if if( info/=0_${ik}$ ) then call stdlib${ii}$_xerbla( 'SSBEVD', -info ) return else if( lquery ) then return end if ! quick return if possible if( n==0 )return if( n==1_${ik}$ ) then w( 1_${ik}$ ) = ab( 1_${ik}$, 1_${ik}$ ) if( wantz )z( 1_${ik}$, 1_${ik}$ ) = one return end if ! get machine constants. safmin = stdlib${ii}$_slamch( 'SAFE MINIMUM' ) eps = stdlib${ii}$_slamch( 'PRECISION' ) smlnum = safmin / eps bignum = one / smlnum rmin = sqrt( smlnum ) rmax = sqrt( bignum ) ! scale matrix to allowable range, if necessary. anrm = stdlib${ii}$_slansb( 'M', uplo, n, kd, ab, ldab, work ) iscale = 0_${ik}$ if( anrm>zero .and. anrm<rmin ) then iscale = 1_${ik}$ sigma = rmin / anrm else if( anrm>rmax ) then iscale = 1_${ik}$ sigma = rmax / anrm end if if( iscale==1_${ik}$ ) then if( lower ) then call stdlib${ii}$_slascl( 'B', kd, kd, one, sigma, n, n, ab, ldab, info ) else call stdlib${ii}$_slascl( 'Q', kd, kd, one, sigma, n, n, ab, ldab, info ) end if end if ! call stdlib${ii}$_ssbtrd to reduce symmetric band matrix to tridiagonal form. inde = 1_${ik}$ indwrk = inde + n indwk2 = indwrk + n*n llwrk2 = lwork - indwk2 + 1_${ik}$ call stdlib${ii}$_ssbtrd( jobz, uplo, n, kd, ab, ldab, w, work( inde ), z, ldz,work( indwrk )& , iinfo ) ! for eigenvalues only, call stdlib${ii}$_ssterf. for eigenvectors, call stdlib${ii}$_sstedc. if( .not.wantz ) then call stdlib${ii}$_ssterf( n, w, work( inde ), info ) else call stdlib${ii}$_sstedc( 'I', n, w, work( inde ), work( indwrk ), n,work( indwk2 ), & llwrk2, iwork, liwork, info ) call stdlib${ii}$_sgemm( 'N', 'N', n, n, n, one, z, ldz, work( indwrk ), n,zero, work( & indwk2 ), n ) call stdlib${ii}$_slacpy( 'A', n, n, work( indwk2 ), n, z, ldz ) end if ! if matrix was scaled, then rescale eigenvalues appropriately. if( iscale==1_${ik}$ )call stdlib${ii}$_sscal( n, one / sigma, w, 1_${ik}$ ) work( 1_${ik}$ ) = lwmin iwork( 1_${ik}$ ) = liwmin return end subroutine stdlib${ii}$_ssbevd module subroutine stdlib${ii}$_dsbevd( jobz, uplo, n, kd, ab, ldab, w, z, ldz, work,lwork, iwork, liwork, & !! DSBEVD computes all the eigenvalues and, optionally, eigenvectors of !! a real symmetric band matrix A. If eigenvectors are desired, it uses !! a divide and conquer algorithm. !! The divide and conquer algorithm makes very mild assumptions about !! floating point arithmetic. It will work on machines with a guard !! digit in add/subtract, or on those binary machines without guard !! digits which subtract like the Cray X-MP, Cray Y-MP, Cray C-90, or !! Cray-2. It could conceivably fail on hexadecimal or decimal machines !! without guard digits, but we know of none. 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) :: jobz, uplo integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: kd, ldab, ldz, liwork, lwork, n ! Array Arguments integer(${ik}$), intent(out) :: iwork(*) real(dp), intent(inout) :: ab(ldab,*) real(dp), intent(out) :: w(*), work(*), z(ldz,*) ! ===================================================================== ! Local Scalars logical(lk) :: lower, lquery, wantz integer(${ik}$) :: iinfo, inde, indwk2, indwrk, iscale, liwmin, llwrk2, lwmin real(dp) :: anrm, bignum, eps, rmax, rmin, safmin, sigma, smlnum ! Intrinsic Functions ! Executable Statements ! test the input parameters. wantz = stdlib_lsame( jobz, 'V' ) lower = stdlib_lsame( uplo, 'L' ) lquery = ( lwork==-1_${ik}$ .or. liwork==-1_${ik}$ ) info = 0_${ik}$ if( n<=1_${ik}$ ) then liwmin = 1_${ik}$ lwmin = 1_${ik}$ else if( wantz ) then liwmin = 3_${ik}$ + 5_${ik}$*n lwmin = 1_${ik}$ + 5_${ik}$*n + 2_${ik}$*n**2_${ik}$ else liwmin = 1_${ik}$ lwmin = 2_${ik}$*n end if end if if( .not.( wantz .or. stdlib_lsame( jobz, 'N' ) ) ) then info = -1_${ik}$ else if( .not.( lower .or. stdlib_lsame( uplo, 'U' ) ) ) then info = -2_${ik}$ else if( n<0_${ik}$ ) then info = -3_${ik}$ else if( kd<0_${ik}$ ) then info = -4_${ik}$ else if( ldab<kd+1 ) then info = -6_${ik}$ else if( ldz<1_${ik}$ .or. ( wantz .and. ldz<n ) ) then info = -9_${ik}$ end if if( info==0_${ik}$ ) then work( 1_${ik}$ ) = lwmin iwork( 1_${ik}$ ) = liwmin if( lwork<lwmin .and. .not.lquery ) then info = -11_${ik}$ else if( liwork<liwmin .and. .not.lquery ) then info = -13_${ik}$ end if end if if( info/=0_${ik}$ ) then call stdlib${ii}$_xerbla( 'DSBEVD', -info ) return else if( lquery ) then return end if ! quick return if possible if( n==0 )return if( n==1_${ik}$ ) then w( 1_${ik}$ ) = ab( 1_${ik}$, 1_${ik}$ ) if( wantz )z( 1_${ik}$, 1_${ik}$ ) = one return end if ! get machine constants. safmin = stdlib${ii}$_dlamch( 'SAFE MINIMUM' ) eps = stdlib${ii}$_dlamch( 'PRECISION' ) smlnum = safmin / eps bignum = one / smlnum rmin = sqrt( smlnum ) rmax = sqrt( bignum ) ! scale matrix to allowable range, if necessary. anrm = stdlib${ii}$_dlansb( 'M', uplo, n, kd, ab, ldab, work ) iscale = 0_${ik}$ if( anrm>zero .and. anrm<rmin ) then iscale = 1_${ik}$ sigma = rmin / anrm else if( anrm>rmax ) then iscale = 1_${ik}$ sigma = rmax / anrm end if if( iscale==1_${ik}$ ) then if( lower ) then call stdlib${ii}$_dlascl( 'B', kd, kd, one, sigma, n, n, ab, ldab, info ) else call stdlib${ii}$_dlascl( 'Q', kd, kd, one, sigma, n, n, ab, ldab, info ) end if end if ! call stdlib${ii}$_dsbtrd to reduce symmetric band matrix to tridiagonal form. inde = 1_${ik}$ indwrk = inde + n indwk2 = indwrk + n*n llwrk2 = lwork - indwk2 + 1_${ik}$ call stdlib${ii}$_dsbtrd( jobz, uplo, n, kd, ab, ldab, w, work( inde ), z, ldz,work( indwrk )& , iinfo ) ! for eigenvalues only, call stdlib${ii}$_dsterf. for eigenvectors, call stdlib${ii}$_sstedc. if( .not.wantz ) then call stdlib${ii}$_dsterf( n, w, work( inde ), info ) else call stdlib${ii}$_dstedc( 'I', n, w, work( inde ), work( indwrk ), n,work( indwk2 ), & llwrk2, iwork, liwork, info ) call stdlib${ii}$_dgemm( 'N', 'N', n, n, n, one, z, ldz, work( indwrk ), n,zero, work( & indwk2 ), n ) call stdlib${ii}$_dlacpy( 'A', n, n, work( indwk2 ), n, z, ldz ) end if ! if matrix was scaled, then rescale eigenvalues appropriately. if( iscale==1_${ik}$ )call stdlib${ii}$_dscal( n, one / sigma, w, 1_${ik}$ ) work( 1_${ik}$ ) = lwmin iwork( 1_${ik}$ ) = liwmin return end subroutine stdlib${ii}$_dsbevd #:for rk,rt,ri in REAL_KINDS_TYPES #:if not rk in ["sp","dp"] module subroutine stdlib${ii}$_${ri}$sbevd( jobz, uplo, n, kd, ab, ldab, w, z, ldz, work,lwork, iwork, liwork, & !! DSBEVD: computes all the eigenvalues and, optionally, eigenvectors of !! a real symmetric band matrix A. If eigenvectors are desired, it uses !! a divide and conquer algorithm. !! The divide and conquer algorithm makes very mild assumptions about !! floating point arithmetic. It will work on machines with a guard !! digit in add/subtract, or on those binary machines without guard !! digits which subtract like the Cray X-MP, Cray Y-MP, Cray C-90, or !! Cray-2. It could conceivably fail on hexadecimal or decimal machines !! without guard digits, but we know of none. 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) :: jobz, uplo integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: kd, ldab, ldz, liwork, lwork, n ! Array Arguments integer(${ik}$), intent(out) :: iwork(*) real(${rk}$), intent(inout) :: ab(ldab,*) real(${rk}$), intent(out) :: w(*), work(*), z(ldz,*) ! ===================================================================== ! Local Scalars logical(lk) :: lower, lquery, wantz integer(${ik}$) :: iinfo, inde, indwk2, indwrk, iscale, liwmin, llwrk2, lwmin real(${rk}$) :: anrm, bignum, eps, rmax, rmin, safmin, sigma, smlnum ! Intrinsic Functions ! Executable Statements ! test the input parameters. wantz = stdlib_lsame( jobz, 'V' ) lower = stdlib_lsame( uplo, 'L' ) lquery = ( lwork==-1_${ik}$ .or. liwork==-1_${ik}$ ) info = 0_${ik}$ if( n<=1_${ik}$ ) then liwmin = 1_${ik}$ lwmin = 1_${ik}$ else if( wantz ) then liwmin = 3_${ik}$ + 5_${ik}$*n lwmin = 1_${ik}$ + 5_${ik}$*n + 2_${ik}$*n**2_${ik}$ else liwmin = 1_${ik}$ lwmin = 2_${ik}$*n end if end if if( .not.( wantz .or. stdlib_lsame( jobz, 'N' ) ) ) then info = -1_${ik}$ else if( .not.( lower .or. stdlib_lsame( uplo, 'U' ) ) ) then info = -2_${ik}$ else if( n<0_${ik}$ ) then info = -3_${ik}$ else if( kd<0_${ik}$ ) then info = -4_${ik}$ else if( ldab<kd+1 ) then info = -6_${ik}$ else if( ldz<1_${ik}$ .or. ( wantz .and. ldz<n ) ) then info = -9_${ik}$ end if if( info==0_${ik}$ ) then work( 1_${ik}$ ) = lwmin iwork( 1_${ik}$ ) = liwmin if( lwork<lwmin .and. .not.lquery ) then info = -11_${ik}$ else if( liwork<liwmin .and. .not.lquery ) then info = -13_${ik}$ end if end if if( info/=0_${ik}$ ) then call stdlib${ii}$_xerbla( 'DSBEVD', -info ) return else if( lquery ) then return end if ! quick return if possible if( n==0 )return if( n==1_${ik}$ ) then w( 1_${ik}$ ) = ab( 1_${ik}$, 1_${ik}$ ) if( wantz )z( 1_${ik}$, 1_${ik}$ ) = one return end if ! get machine constants. safmin = stdlib${ii}$_${ri}$lamch( 'SAFE MINIMUM' ) eps = stdlib${ii}$_${ri}$lamch( 'PRECISION' ) smlnum = safmin / eps bignum = one / smlnum rmin = sqrt( smlnum ) rmax = sqrt( bignum ) ! scale matrix to allowable range, if necessary. anrm = stdlib${ii}$_${ri}$lansb( 'M', uplo, n, kd, ab, ldab, work ) iscale = 0_${ik}$ if( anrm>zero .and. anrm<rmin ) then iscale = 1_${ik}$ sigma = rmin / anrm else if( anrm>rmax ) then iscale = 1_${ik}$ sigma = rmax / anrm end if if( iscale==1_${ik}$ ) then if( lower ) then call stdlib${ii}$_${ri}$lascl( 'B', kd, kd, one, sigma, n, n, ab, ldab, info ) else call stdlib${ii}$_${ri}$lascl( 'Q', kd, kd, one, sigma, n, n, ab, ldab, info ) end if end if ! call stdlib${ii}$_${ri}$sbtrd to reduce symmetric band matrix to tridiagonal form. inde = 1_${ik}$ indwrk = inde + n indwk2 = indwrk + n*n llwrk2 = lwork - indwk2 + 1_${ik}$ call stdlib${ii}$_${ri}$sbtrd( jobz, uplo, n, kd, ab, ldab, w, work( inde ), z, ldz,work( indwrk )& , iinfo ) ! for eigenvalues only, call stdlib${ii}$_${ri}$sterf. for eigenvectors, call stdlib${ii}$_dstedc. if( .not.wantz ) then call stdlib${ii}$_${ri}$sterf( n, w, work( inde ), info ) else call stdlib${ii}$_${ri}$stedc( 'I', n, w, work( inde ), work( indwrk ), n,work( indwk2 ), & llwrk2, iwork, liwork, info ) call stdlib${ii}$_${ri}$gemm( 'N', 'N', n, n, n, one, z, ldz, work( indwrk ), n,zero, work( & indwk2 ), n ) call stdlib${ii}$_${ri}$lacpy( 'A', n, n, work( indwk2 ), n, z, ldz ) end if ! if matrix was scaled, then rescale eigenvalues appropriately. if( iscale==1_${ik}$ )call stdlib${ii}$_${ri}$scal( n, one / sigma, w, 1_${ik}$ ) work( 1_${ik}$ ) = lwmin iwork( 1_${ik}$ ) = liwmin return end subroutine stdlib${ii}$_${ri}$sbevd #:endif #:endfor module subroutine stdlib${ii}$_ssbevx( jobz, range, uplo, n, kd, ab, ldab, q, ldq, vl,vu, il, iu, abstol, & !! SSBEVX computes selected eigenvalues and, optionally, eigenvectors !! of a real symmetric band matrix A. Eigenvalues and eigenvectors can !! be selected by specifying either a range of values or a range of !! indices for the desired eigenvalues. m, w, z, ldz, work, iwork,ifail, 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) :: jobz, range, uplo integer(${ik}$), intent(in) :: il, iu, kd, ldab, ldq, ldz, n integer(${ik}$), intent(out) :: info, m real(sp), intent(in) :: abstol, vl, vu ! Array Arguments integer(${ik}$), intent(out) :: ifail(*), iwork(*) real(sp), intent(inout) :: ab(ldab,*) real(sp), intent(out) :: q(ldq,*), w(*), work(*), z(ldz,*) ! ===================================================================== ! Local Scalars logical(lk) :: alleig, indeig, lower, test, valeig, wantz character :: order integer(${ik}$) :: i, iinfo, imax, indd, inde, indee, indibl, indisp, indiwo, indwrk, & iscale, itmp1, j, jj, nsplit real(sp) :: abstll, anrm, bignum, eps, rmax, rmin, safmin, sigma, smlnum, tmp1, vll, & vuu ! Intrinsic Functions ! Executable Statements ! test the input parameters. wantz = stdlib_lsame( jobz, 'V' ) alleig = stdlib_lsame( range, 'A' ) valeig = stdlib_lsame( range, 'V' ) indeig = stdlib_lsame( range, 'I' ) lower = stdlib_lsame( uplo, 'L' ) info = 0_${ik}$ if( .not.( wantz .or. stdlib_lsame( jobz, 'N' ) ) ) then info = -1_${ik}$ else if( .not.( alleig .or. valeig .or. indeig ) ) then info = -2_${ik}$ else if( .not.( lower .or. stdlib_lsame( uplo, 'U' ) ) ) then info = -3_${ik}$ else if( n<0_${ik}$ ) then info = -4_${ik}$ else if( kd<0_${ik}$ ) then info = -5_${ik}$ else if( ldab<kd+1 ) then info = -7_${ik}$ else if( wantz .and. ldq<max( 1_${ik}$, n ) ) then info = -9_${ik}$ else if( valeig ) then if( n>0_${ik}$ .and. vu<=vl )info = -11_${ik}$ else if( indeig ) then if( il<1_${ik}$ .or. il>max( 1_${ik}$, n ) ) then info = -12_${ik}$ else if( iu<min( n, il ) .or. iu>n ) then info = -13_${ik}$ end if end if end if if( info==0_${ik}$ ) then if( ldz<1_${ik}$ .or. ( wantz .and. ldz<n ) )info = -18_${ik}$ end if if( info/=0_${ik}$ ) then call stdlib${ii}$_xerbla( 'SSBEVX', -info ) return end if ! quick return if possible m = 0_${ik}$ if( n==0 )return if( n==1_${ik}$ ) then m = 1_${ik}$ if( lower ) then tmp1 = ab( 1_${ik}$, 1_${ik}$ ) else tmp1 = ab( kd+1, 1_${ik}$ ) end if if( valeig ) then if( .not.( vl<tmp1 .and. vu>=tmp1 ) )m = 0_${ik}$ end if if( m==1_${ik}$ ) then w( 1_${ik}$ ) = tmp1 if( wantz )z( 1_${ik}$, 1_${ik}$ ) = one end if return end if ! get machine constants. safmin = stdlib${ii}$_slamch( 'SAFE MINIMUM' ) eps = stdlib${ii}$_slamch( 'PRECISION' ) smlnum = safmin / eps bignum = one / smlnum rmin = sqrt( smlnum ) rmax = min( sqrt( bignum ), one / sqrt( sqrt( safmin ) ) ) ! scale matrix to allowable range, if necessary. iscale = 0_${ik}$ abstll = abstol if ( valeig ) then vll = vl vuu = vu else vll = zero vuu = zero endif anrm = stdlib${ii}$_slansb( 'M', uplo, n, kd, ab, ldab, work ) if( anrm>zero .and. anrm<rmin ) then iscale = 1_${ik}$ sigma = rmin / anrm else if( anrm>rmax ) then iscale = 1_${ik}$ sigma = rmax / anrm end if if( iscale==1_${ik}$ ) then if( lower ) then call stdlib${ii}$_slascl( 'B', kd, kd, one, sigma, n, n, ab, ldab, info ) else call stdlib${ii}$_slascl( 'Q', kd, kd, one, sigma, n, n, ab, ldab, info ) end if if( abstol>0_${ik}$ )abstll = abstol*sigma if( valeig ) then vll = vl*sigma vuu = vu*sigma end if end if ! call stdlib${ii}$_ssbtrd to reduce symmetric band matrix to tridiagonal form. indd = 1_${ik}$ inde = indd + n indwrk = inde + n call stdlib${ii}$_ssbtrd( jobz, uplo, n, kd, ab, ldab, work( indd ),work( inde ), q, ldq, & work( indwrk ), iinfo ) ! if all eigenvalues are desired and abstol is less than or equal ! to zero, then call stdlib${ii}$_ssterf or stdlib${ii}$_ssteqr. if this fails for some ! eigenvalue, then try stdlib${ii}$_sstebz. test = .false. if (indeig) then if (il==1_${ik}$ .and. iu==n) then test = .true. end if end if if ((alleig .or. test) .and. (abstol<=zero)) then call stdlib${ii}$_scopy( n, work( indd ), 1_${ik}$, w, 1_${ik}$ ) indee = indwrk + 2_${ik}$*n if( .not.wantz ) then call stdlib${ii}$_scopy( n-1, work( inde ), 1_${ik}$, work( indee ), 1_${ik}$ ) call stdlib${ii}$_ssterf( n, w, work( indee ), info ) else call stdlib${ii}$_slacpy( 'A', n, n, q, ldq, z, ldz ) call stdlib${ii}$_scopy( n-1, work( inde ), 1_${ik}$, work( indee ), 1_${ik}$ ) call stdlib${ii}$_ssteqr( jobz, n, w, work( indee ), z, ldz,work( indwrk ), info ) if( info==0_${ik}$ ) then do i = 1, n ifail( i ) = 0_${ik}$ end do end if end if if( info==0_${ik}$ ) then m = n go to 30 end if info = 0_${ik}$ end if ! otherwise, call stdlib${ii}$_sstebz and, if eigenvectors are desired, stdlib${ii}$_sstein. if( wantz ) then order = 'B' else order = 'E' end if indibl = 1_${ik}$ indisp = indibl + n indiwo = indisp + n call stdlib${ii}$_sstebz( range, order, n, vll, vuu, il, iu, abstll,work( indd ), work( inde & ), m, nsplit, w,iwork( indibl ), iwork( indisp ), work( indwrk ),iwork( indiwo ), info & ) if( wantz ) then call stdlib${ii}$_sstein( n, work( indd ), work( inde ), m, w,iwork( indibl ), iwork( & indisp ), z, ldz,work( indwrk ), iwork( indiwo ), ifail, info ) ! apply orthogonal matrix used in reduction to tridiagonal ! form to eigenvectors returned by stdlib${ii}$_sstein. do j = 1, m call stdlib${ii}$_scopy( n, z( 1_${ik}$, j ), 1_${ik}$, work( 1_${ik}$ ), 1_${ik}$ ) call stdlib${ii}$_sgemv( 'N', n, n, one, q, ldq, work, 1_${ik}$, zero,z( 1_${ik}$, j ), 1_${ik}$ ) end do end if ! if matrix was scaled, then rescale eigenvalues appropriately. 30 continue if( iscale==1_${ik}$ ) then if( info==0_${ik}$ ) then imax = m else imax = info - 1_${ik}$ end if call stdlib${ii}$_sscal( imax, one / sigma, w, 1_${ik}$ ) end if ! if eigenvalues are not in order, then sort them, along with ! eigenvectors. if( wantz ) then do j = 1, m - 1 i = 0_${ik}$ tmp1 = w( j ) do jj = j + 1, m if( w( jj )<tmp1 ) then i = jj tmp1 = w( jj ) end if end do if( i/=0_${ik}$ ) then itmp1 = iwork( indibl+i-1 ) w( i ) = w( j ) iwork( indibl+i-1 ) = iwork( indibl+j-1 ) w( j ) = tmp1 iwork( indibl+j-1 ) = itmp1 call stdlib${ii}$_sswap( n, z( 1_${ik}$, i ), 1_${ik}$, z( 1_${ik}$, j ), 1_${ik}$ ) if( info/=0_${ik}$ ) then itmp1 = ifail( i ) ifail( i ) = ifail( j ) ifail( j ) = itmp1 end if end if end do end if return end subroutine stdlib${ii}$_ssbevx module subroutine stdlib${ii}$_dsbevx( jobz, range, uplo, n, kd, ab, ldab, q, ldq, vl,vu, il, iu, abstol, & !! DSBEVX computes selected eigenvalues and, optionally, eigenvectors !! of a real symmetric band matrix A. Eigenvalues and eigenvectors can !! be selected by specifying either a range of values or a range of !! indices for the desired eigenvalues. m, w, z, ldz, work, iwork,ifail, 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) :: jobz, range, uplo integer(${ik}$), intent(in) :: il, iu, kd, ldab, ldq, ldz, n integer(${ik}$), intent(out) :: info, m real(dp), intent(in) :: abstol, vl, vu ! Array Arguments integer(${ik}$), intent(out) :: ifail(*), iwork(*) real(dp), intent(inout) :: ab(ldab,*) real(dp), intent(out) :: q(ldq,*), w(*), work(*), z(ldz,*) ! ===================================================================== ! Local Scalars logical(lk) :: alleig, indeig, lower, test, valeig, wantz character :: order integer(${ik}$) :: i, iinfo, imax, indd, inde, indee, indibl, indisp, indiwo, indwrk, & iscale, itmp1, j, jj, nsplit real(dp) :: abstll, anrm, bignum, eps, rmax, rmin, safmin, sigma, smlnum, tmp1, vll, & vuu ! Intrinsic Functions ! Executable Statements ! test the input parameters. wantz = stdlib_lsame( jobz, 'V' ) alleig = stdlib_lsame( range, 'A' ) valeig = stdlib_lsame( range, 'V' ) indeig = stdlib_lsame( range, 'I' ) lower = stdlib_lsame( uplo, 'L' ) info = 0_${ik}$ if( .not.( wantz .or. stdlib_lsame( jobz, 'N' ) ) ) then info = -1_${ik}$ else if( .not.( alleig .or. valeig .or. indeig ) ) then info = -2_${ik}$ else if( .not.( lower .or. stdlib_lsame( uplo, 'U' ) ) ) then info = -3_${ik}$ else if( n<0_${ik}$ ) then info = -4_${ik}$ else if( kd<0_${ik}$ ) then info = -5_${ik}$ else if( ldab<kd+1 ) then info = -7_${ik}$ else if( wantz .and. ldq<max( 1_${ik}$, n ) ) then info = -9_${ik}$ else if( valeig ) then if( n>0_${ik}$ .and. vu<=vl )info = -11_${ik}$ else if( indeig ) then if( il<1_${ik}$ .or. il>max( 1_${ik}$, n ) ) then info = -12_${ik}$ else if( iu<min( n, il ) .or. iu>n ) then info = -13_${ik}$ end if end if end if if( info==0_${ik}$ ) then if( ldz<1_${ik}$ .or. ( wantz .and. ldz<n ) )info = -18_${ik}$ end if if( info/=0_${ik}$ ) then call stdlib${ii}$_xerbla( 'DSBEVX', -info ) return end if ! quick return if possible m = 0_${ik}$ if( n==0 )return if( n==1_${ik}$ ) then m = 1_${ik}$ if( lower ) then tmp1 = ab( 1_${ik}$, 1_${ik}$ ) else tmp1 = ab( kd+1, 1_${ik}$ ) end if if( valeig ) then if( .not.( vl<tmp1 .and. vu>=tmp1 ) )m = 0_${ik}$ end if if( m==1_${ik}$ ) then w( 1_${ik}$ ) = tmp1 if( wantz )z( 1_${ik}$, 1_${ik}$ ) = one end if return end if ! get machine constants. safmin = stdlib${ii}$_dlamch( 'SAFE MINIMUM' ) eps = stdlib${ii}$_dlamch( 'PRECISION' ) smlnum = safmin / eps bignum = one / smlnum rmin = sqrt( smlnum ) rmax = min( sqrt( bignum ), one / sqrt( sqrt( safmin ) ) ) ! scale matrix to allowable range, if necessary. iscale = 0_${ik}$ abstll = abstol if( valeig ) then vll = vl vuu = vu else vll = zero vuu = zero end if anrm = stdlib${ii}$_dlansb( 'M', uplo, n, kd, ab, ldab, work ) if( anrm>zero .and. anrm<rmin ) then iscale = 1_${ik}$ sigma = rmin / anrm else if( anrm>rmax ) then iscale = 1_${ik}$ sigma = rmax / anrm end if if( iscale==1_${ik}$ ) then if( lower ) then call stdlib${ii}$_dlascl( 'B', kd, kd, one, sigma, n, n, ab, ldab, info ) else call stdlib${ii}$_dlascl( 'Q', kd, kd, one, sigma, n, n, ab, ldab, info ) end if if( abstol>0_${ik}$ )abstll = abstol*sigma if( valeig ) then vll = vl*sigma vuu = vu*sigma end if end if ! call stdlib${ii}$_dsbtrd to reduce symmetric band matrix to tridiagonal form. indd = 1_${ik}$ inde = indd + n indwrk = inde + n call stdlib${ii}$_dsbtrd( jobz, uplo, n, kd, ab, ldab, work( indd ),work( inde ), q, ldq, & work( indwrk ), iinfo ) ! if all eigenvalues are desired and abstol is less than or equal ! to zero, then call stdlib${ii}$_dsterf or stdlib${ii}$_ssteqr. if this fails for some ! eigenvalue, then try stdlib${ii}$_dstebz. test = .false. if (indeig) then if (il==1_${ik}$ .and. iu==n) then test = .true. end if end if if ((alleig .or. test) .and. (abstol<=zero)) then call stdlib${ii}$_dcopy( n, work( indd ), 1_${ik}$, w, 1_${ik}$ ) indee = indwrk + 2_${ik}$*n if( .not.wantz ) then call stdlib${ii}$_dcopy( n-1, work( inde ), 1_${ik}$, work( indee ), 1_${ik}$ ) call stdlib${ii}$_dsterf( n, w, work( indee ), info ) else call stdlib${ii}$_dlacpy( 'A', n, n, q, ldq, z, ldz ) call stdlib${ii}$_dcopy( n-1, work( inde ), 1_${ik}$, work( indee ), 1_${ik}$ ) call stdlib${ii}$_dsteqr( jobz, n, w, work( indee ), z, ldz,work( indwrk ), info ) if( info==0_${ik}$ ) then do i = 1, n ifail( i ) = 0_${ik}$ end do end if end if if( info==0_${ik}$ ) then m = n go to 30 end if info = 0_${ik}$ end if ! otherwise, call stdlib${ii}$_dstebz and, if eigenvectors are desired, stdlib${ii}$_sstein. if( wantz ) then order = 'B' else order = 'E' end if indibl = 1_${ik}$ indisp = indibl + n indiwo = indisp + n call stdlib${ii}$_dstebz( range, order, n, vll, vuu, il, iu, abstll,work( indd ), work( inde & ), m, nsplit, w,iwork( indibl ), iwork( indisp ), work( indwrk ),iwork( indiwo ), info & ) if( wantz ) then call stdlib${ii}$_dstein( n, work( indd ), work( inde ), m, w,iwork( indibl ), iwork( & indisp ), z, ldz,work( indwrk ), iwork( indiwo ), ifail, info ) ! apply orthogonal matrix used in reduction to tridiagonal ! form to eigenvectors returned by stdlib${ii}$_dstein. do j = 1, m call stdlib${ii}$_dcopy( n, z( 1_${ik}$, j ), 1_${ik}$, work( 1_${ik}$ ), 1_${ik}$ ) call stdlib${ii}$_dgemv( 'N', n, n, one, q, ldq, work, 1_${ik}$, zero,z( 1_${ik}$, j ), 1_${ik}$ ) end do end if ! if matrix was scaled, then rescale eigenvalues appropriately. 30 continue if( iscale==1_${ik}$ ) then if( info==0_${ik}$ ) then imax = m else imax = info - 1_${ik}$ end if call stdlib${ii}$_dscal( imax, one / sigma, w, 1_${ik}$ ) end if ! if eigenvalues are not in order, then sort them, along with ! eigenvectors. if( wantz ) then do j = 1, m - 1 i = 0_${ik}$ tmp1 = w( j ) do jj = j + 1, m if( w( jj )<tmp1 ) then i = jj tmp1 = w( jj ) end if end do if( i/=0_${ik}$ ) then itmp1 = iwork( indibl+i-1 ) w( i ) = w( j ) iwork( indibl+i-1 ) = iwork( indibl+j-1 ) w( j ) = tmp1 iwork( indibl+j-1 ) = itmp1 call stdlib${ii}$_dswap( n, z( 1_${ik}$, i ), 1_${ik}$, z( 1_${ik}$, j ), 1_${ik}$ ) if( info/=0_${ik}$ ) then itmp1 = ifail( i ) ifail( i ) = ifail( j ) ifail( j ) = itmp1 end if end if end do end if return end subroutine stdlib${ii}$_dsbevx #:for rk,rt,ri in REAL_KINDS_TYPES #:if not rk in ["sp","dp"] module subroutine stdlib${ii}$_${ri}$sbevx( jobz, range, uplo, n, kd, ab, ldab, q, ldq, vl,vu, il, iu, abstol, & !! DSBEVX: computes selected eigenvalues and, optionally, eigenvectors !! of a real symmetric band matrix A. Eigenvalues and eigenvectors can !! be selected by specifying either a range of values or a range of !! indices for the desired eigenvalues. m, w, z, ldz, work, iwork,ifail, 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) :: jobz, range, uplo integer(${ik}$), intent(in) :: il, iu, kd, ldab, ldq, ldz, n integer(${ik}$), intent(out) :: info, m real(${rk}$), intent(in) :: abstol, vl, vu ! Array Arguments integer(${ik}$), intent(out) :: ifail(*), iwork(*) real(${rk}$), intent(inout) :: ab(ldab,*) real(${rk}$), intent(out) :: q(ldq,*), w(*), work(*), z(ldz,*) ! ===================================================================== ! Local Scalars logical(lk) :: alleig, indeig, lower, test, valeig, wantz character :: order integer(${ik}$) :: i, iinfo, imax, indd, inde, indee, indibl, indisp, indiwo, indwrk, & iscale, itmp1, j, jj, nsplit real(${rk}$) :: abstll, anrm, bignum, eps, rmax, rmin, safmin, sigma, smlnum, tmp1, vll, & vuu ! Intrinsic Functions ! Executable Statements ! test the input parameters. wantz = stdlib_lsame( jobz, 'V' ) alleig = stdlib_lsame( range, 'A' ) valeig = stdlib_lsame( range, 'V' ) indeig = stdlib_lsame( range, 'I' ) lower = stdlib_lsame( uplo, 'L' ) info = 0_${ik}$ if( .not.( wantz .or. stdlib_lsame( jobz, 'N' ) ) ) then info = -1_${ik}$ else if( .not.( alleig .or. valeig .or. indeig ) ) then info = -2_${ik}$ else if( .not.( lower .or. stdlib_lsame( uplo, 'U' ) ) ) then info = -3_${ik}$ else if( n<0_${ik}$ ) then info = -4_${ik}$ else if( kd<0_${ik}$ ) then info = -5_${ik}$ else if( ldab<kd+1 ) then info = -7_${ik}$ else if( wantz .and. ldq<max( 1_${ik}$, n ) ) then info = -9_${ik}$ else if( valeig ) then if( n>0_${ik}$ .and. vu<=vl )info = -11_${ik}$ else if( indeig ) then if( il<1_${ik}$ .or. il>max( 1_${ik}$, n ) ) then info = -12_${ik}$ else if( iu<min( n, il ) .or. iu>n ) then info = -13_${ik}$ end if end if end if if( info==0_${ik}$ ) then if( ldz<1_${ik}$ .or. ( wantz .and. ldz<n ) )info = -18_${ik}$ end if if( info/=0_${ik}$ ) then call stdlib${ii}$_xerbla( 'DSBEVX', -info ) return end if ! quick return if possible m = 0_${ik}$ if( n==0 )return if( n==1_${ik}$ ) then m = 1_${ik}$ if( lower ) then tmp1 = ab( 1_${ik}$, 1_${ik}$ ) else tmp1 = ab( kd+1, 1_${ik}$ ) end if if( valeig ) then if( .not.( vl<tmp1 .and. vu>=tmp1 ) )m = 0_${ik}$ end if if( m==1_${ik}$ ) then w( 1_${ik}$ ) = tmp1 if( wantz )z( 1_${ik}$, 1_${ik}$ ) = one end if return end if ! get machine constants. safmin = stdlib${ii}$_${ri}$lamch( 'SAFE MINIMUM' ) eps = stdlib${ii}$_${ri}$lamch( 'PRECISION' ) smlnum = safmin / eps bignum = one / smlnum rmin = sqrt( smlnum ) rmax = min( sqrt( bignum ), one / sqrt( sqrt( safmin ) ) ) ! scale matrix to allowable range, if necessary. iscale = 0_${ik}$ abstll = abstol if( valeig ) then vll = vl vuu = vu else vll = zero vuu = zero end if anrm = stdlib${ii}$_${ri}$lansb( 'M', uplo, n, kd, ab, ldab, work ) if( anrm>zero .and. anrm<rmin ) then iscale = 1_${ik}$ sigma = rmin / anrm else if( anrm>rmax ) then iscale = 1_${ik}$ sigma = rmax / anrm end if if( iscale==1_${ik}$ ) then if( lower ) then call stdlib${ii}$_${ri}$lascl( 'B', kd, kd, one, sigma, n, n, ab, ldab, info ) else call stdlib${ii}$_${ri}$lascl( 'Q', kd, kd, one, sigma, n, n, ab, ldab, info ) end if if( abstol>0_${ik}$ )abstll = abstol*sigma if( valeig ) then vll = vl*sigma vuu = vu*sigma end if end if ! call stdlib${ii}$_${ri}$sbtrd to reduce symmetric band matrix to tridiagonal form. indd = 1_${ik}$ inde = indd + n indwrk = inde + n call stdlib${ii}$_${ri}$sbtrd( jobz, uplo, n, kd, ab, ldab, work( indd ),work( inde ), q, ldq, & work( indwrk ), iinfo ) ! if all eigenvalues are desired and abstol is less than or equal ! to zero, then call stdlib${ii}$_${ri}$sterf or stdlib${ii}$_dsteqr. if this fails for some ! eigenvalue, then try stdlib${ii}$_${ri}$stebz. test = .false. if (indeig) then if (il==1_${ik}$ .and. iu==n) then test = .true. end if end if if ((alleig .or. test) .and. (abstol<=zero)) then call stdlib${ii}$_${ri}$copy( n, work( indd ), 1_${ik}$, w, 1_${ik}$ ) indee = indwrk + 2_${ik}$*n if( .not.wantz ) then call stdlib${ii}$_${ri}$copy( n-1, work( inde ), 1_${ik}$, work( indee ), 1_${ik}$ ) call stdlib${ii}$_${ri}$sterf( n, w, work( indee ), info ) else call stdlib${ii}$_${ri}$lacpy( 'A', n, n, q, ldq, z, ldz ) call stdlib${ii}$_${ri}$copy( n-1, work( inde ), 1_${ik}$, work( indee ), 1_${ik}$ ) call stdlib${ii}$_${ri}$steqr( jobz, n, w, work( indee ), z, ldz,work( indwrk ), info ) if( info==0_${ik}$ ) then do i = 1, n ifail( i ) = 0_${ik}$ end do end if end if if( info==0_${ik}$ ) then m = n go to 30 end if info = 0_${ik}$ end if ! otherwise, call stdlib${ii}$_${ri}$stebz and, if eigenvectors are desired, stdlib${ii}$_dstein. if( wantz ) then order = 'B' else order = 'E' end if indibl = 1_${ik}$ indisp = indibl + n indiwo = indisp + n call stdlib${ii}$_${ri}$stebz( range, order, n, vll, vuu, il, iu, abstll,work( indd ), work( inde & ), m, nsplit, w,iwork( indibl ), iwork( indisp ), work( indwrk ),iwork( indiwo ), info & ) if( wantz ) then call stdlib${ii}$_${ri}$stein( n, work( indd ), work( inde ), m, w,iwork( indibl ), iwork( & indisp ), z, ldz,work( indwrk ), iwork( indiwo ), ifail, info ) ! apply orthogonal matrix used in reduction to tridiagonal ! form to eigenvectors returned by stdlib${ii}$_${ri}$stein. do j = 1, m call stdlib${ii}$_${ri}$copy( n, z( 1_${ik}$, j ), 1_${ik}$, work( 1_${ik}$ ), 1_${ik}$ ) call stdlib${ii}$_${ri}$gemv( 'N', n, n, one, q, ldq, work, 1_${ik}$, zero,z( 1_${ik}$, j ), 1_${ik}$ ) end do end if ! if matrix was scaled, then rescale eigenvalues appropriately. 30 continue if( iscale==1_${ik}$ ) then if( info==0_${ik}$ ) then imax = m else imax = info - 1_${ik}$ end if call stdlib${ii}$_${ri}$scal( imax, one / sigma, w, 1_${ik}$ ) end if ! if eigenvalues are not in order, then sort them, along with ! eigenvectors. if( wantz ) then do j = 1, m - 1 i = 0_${ik}$ tmp1 = w( j ) do jj = j + 1, m if( w( jj )<tmp1 ) then i = jj tmp1 = w( jj ) end if end do if( i/=0_${ik}$ ) then itmp1 = iwork( indibl+i-1 ) w( i ) = w( j ) iwork( indibl+i-1 ) = iwork( indibl+j-1 ) w( j ) = tmp1 iwork( indibl+j-1 ) = itmp1 call stdlib${ii}$_${ri}$swap( n, z( 1_${ik}$, i ), 1_${ik}$, z( 1_${ik}$, j ), 1_${ik}$ ) if( info/=0_${ik}$ ) then itmp1 = ifail( i ) ifail( i ) = ifail( j ) ifail( j ) = itmp1 end if end if end do end if return end subroutine stdlib${ii}$_${ri}$sbevx #:endif #:endfor module subroutine stdlib${ii}$_cheev( jobz, uplo, n, a, lda, w, work, lwork, rwork,info ) !! CHEEV computes all eigenvalues and, optionally, eigenvectors of a !! complex Hermitian matrix A. ! -- 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) :: jobz, uplo integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: lda, lwork, n ! Array Arguments real(sp), intent(out) :: rwork(*), w(*) complex(sp), intent(inout) :: a(lda,*) complex(sp), intent(out) :: work(*) ! ===================================================================== ! Local Scalars logical(lk) :: lower, lquery, wantz integer(${ik}$) :: iinfo, imax, inde, indtau, indwrk, iscale, llwork, lwkopt, nb real(sp) :: anrm, bignum, eps, rmax, rmin, safmin, sigma, smlnum ! Intrinsic Functions ! Executable Statements ! test the input parameters. wantz = stdlib_lsame( jobz, 'V' ) lower = stdlib_lsame( uplo, 'L' ) lquery = ( lwork==-1_${ik}$ ) info = 0_${ik}$ if( .not.( wantz .or. stdlib_lsame( jobz, 'N' ) ) ) then info = -1_${ik}$ else if( .not.( lower .or. stdlib_lsame( uplo, 'U' ) ) ) then info = -2_${ik}$ else if( n<0_${ik}$ ) then info = -3_${ik}$ else if( lda<max( 1_${ik}$, n ) ) then info = -5_${ik}$ end if if( info==0_${ik}$ ) then nb = stdlib${ii}$_ilaenv( 1_${ik}$, 'CHETRD', uplo, n, -1_${ik}$, -1_${ik}$, -1_${ik}$ ) lwkopt = max( 1_${ik}$, ( nb+1 )*n ) work( 1_${ik}$ ) = lwkopt if( lwork<max( 1_${ik}$, 2_${ik}$*n-1 ) .and. .not.lquery )info = -8_${ik}$ end if if( info/=0_${ik}$ ) then call stdlib${ii}$_xerbla( 'CHEEV ', -info ) return else if( lquery ) then return end if ! quick return if possible if( n==0_${ik}$ ) then return end if if( n==1_${ik}$ ) then w( 1_${ik}$ ) = real( a( 1_${ik}$, 1_${ik}$ ),KIND=sp) work( 1_${ik}$ ) = 1_${ik}$ if( wantz )a( 1_${ik}$, 1_${ik}$ ) = cone return end if ! get machine constants. safmin = stdlib${ii}$_slamch( 'SAFE MINIMUM' ) eps = stdlib${ii}$_slamch( 'PRECISION' ) smlnum = safmin / eps bignum = one / smlnum rmin = sqrt( smlnum ) rmax = sqrt( bignum ) ! scale matrix to allowable range, if necessary. anrm = stdlib${ii}$_clanhe( 'M', uplo, n, a, lda, rwork ) iscale = 0_${ik}$ if( anrm>zero .and. anrm<rmin ) then iscale = 1_${ik}$ sigma = rmin / anrm else if( anrm>rmax ) then iscale = 1_${ik}$ sigma = rmax / anrm end if if( iscale==1_${ik}$ )call stdlib${ii}$_clascl( uplo, 0_${ik}$, 0_${ik}$, one, sigma, n, n, a, lda, info ) ! call stdlib${ii}$_chetrd to reduce hermitian matrix to tridiagonal form. inde = 1_${ik}$ indtau = 1_${ik}$ indwrk = indtau + n llwork = lwork - indwrk + 1_${ik}$ call stdlib${ii}$_chetrd( uplo, n, a, lda, w, rwork( inde ), work( indtau ),work( indwrk ), & llwork, iinfo ) ! for eigenvalues only, call stdlib${ii}$_ssterf. for eigenvectors, first call ! stdlib${ii}$_cungtr to generate the unitary matrix, then call stdlib${ii}$_csteqr. if( .not.wantz ) then call stdlib${ii}$_ssterf( n, w, rwork( inde ), info ) else call stdlib${ii}$_cungtr( uplo, n, a, lda, work( indtau ), work( indwrk ),llwork, iinfo ) indwrk = inde + n call stdlib${ii}$_csteqr( jobz, n, w, rwork( inde ), a, lda,rwork( indwrk ), info ) end if ! if matrix was scaled, then rescale eigenvalues appropriately. if( iscale==1_${ik}$ ) then if( info==0_${ik}$ ) then imax = n else imax = info - 1_${ik}$ end if call stdlib${ii}$_sscal( imax, one / sigma, w, 1_${ik}$ ) end if ! set work(1) to optimal complex workspace size. work( 1_${ik}$ ) = lwkopt return end subroutine stdlib${ii}$_cheev module subroutine stdlib${ii}$_zheev( jobz, uplo, n, a, lda, w, work, lwork, rwork,info ) !! ZHEEV computes all eigenvalues and, optionally, eigenvectors of a !! complex Hermitian matrix A. ! -- 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) :: jobz, uplo integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: lda, lwork, n ! Array Arguments real(dp), intent(out) :: rwork(*), w(*) complex(dp), intent(inout) :: a(lda,*) complex(dp), intent(out) :: work(*) ! ===================================================================== ! Local Scalars logical(lk) :: lower, lquery, wantz integer(${ik}$) :: iinfo, imax, inde, indtau, indwrk, iscale, llwork, lwkopt, nb real(dp) :: anrm, bignum, eps, rmax, rmin, safmin, sigma, smlnum ! Intrinsic Functions ! Executable Statements ! test the input parameters. wantz = stdlib_lsame( jobz, 'V' ) lower = stdlib_lsame( uplo, 'L' ) lquery = ( lwork==-1_${ik}$ ) info = 0_${ik}$ if( .not.( wantz .or. stdlib_lsame( jobz, 'N' ) ) ) then info = -1_${ik}$ else if( .not.( lower .or. stdlib_lsame( uplo, 'U' ) ) ) then info = -2_${ik}$ else if( n<0_${ik}$ ) then info = -3_${ik}$ else if( lda<max( 1_${ik}$, n ) ) then info = -5_${ik}$ end if if( info==0_${ik}$ ) then nb = stdlib${ii}$_ilaenv( 1_${ik}$, 'ZHETRD', uplo, n, -1_${ik}$, -1_${ik}$, -1_${ik}$ ) lwkopt = max( 1_${ik}$, ( nb+1 )*n ) work( 1_${ik}$ ) = lwkopt if( lwork<max( 1_${ik}$, 2_${ik}$*n-1 ) .and. .not.lquery )info = -8_${ik}$ end if if( info/=0_${ik}$ ) then call stdlib${ii}$_xerbla( 'ZHEEV ', -info ) return else if( lquery ) then return end if ! quick return if possible if( n==0_${ik}$ ) then return end if if( n==1_${ik}$ ) then w( 1_${ik}$ ) = real( a( 1_${ik}$, 1_${ik}$ ),KIND=dp) work( 1_${ik}$ ) = 1_${ik}$ if( wantz )a( 1_${ik}$, 1_${ik}$ ) = cone return end if ! get machine constants. safmin = stdlib${ii}$_dlamch( 'SAFE MINIMUM' ) eps = stdlib${ii}$_dlamch( 'PRECISION' ) smlnum = safmin / eps bignum = one / smlnum rmin = sqrt( smlnum ) rmax = sqrt( bignum ) ! scale matrix to allowable range, if necessary. anrm = stdlib${ii}$_zlanhe( 'M', uplo, n, a, lda, rwork ) iscale = 0_${ik}$ if( anrm>zero .and. anrm<rmin ) then iscale = 1_${ik}$ sigma = rmin / anrm else if( anrm>rmax ) then iscale = 1_${ik}$ sigma = rmax / anrm end if if( iscale==1_${ik}$ )call stdlib${ii}$_zlascl( uplo, 0_${ik}$, 0_${ik}$, one, sigma, n, n, a, lda, info ) ! call stdlib${ii}$_zhetrd to reduce hermitian matrix to tridiagonal form. inde = 1_${ik}$ indtau = 1_${ik}$ indwrk = indtau + n llwork = lwork - indwrk + 1_${ik}$ call stdlib${ii}$_zhetrd( uplo, n, a, lda, w, rwork( inde ), work( indtau ),work( indwrk ), & llwork, iinfo ) ! for eigenvalues only, call stdlib${ii}$_dsterf. for eigenvectors, first call ! stdlib${ii}$_zungtr to generate the unitary matrix, then call stdlib${ii}$_zsteqr. if( .not.wantz ) then call stdlib${ii}$_dsterf( n, w, rwork( inde ), info ) else call stdlib${ii}$_zungtr( uplo, n, a, lda, work( indtau ), work( indwrk ),llwork, iinfo ) indwrk = inde + n call stdlib${ii}$_zsteqr( jobz, n, w, rwork( inde ), a, lda,rwork( indwrk ), info ) end if ! if matrix was scaled, then rescale eigenvalues appropriately. if( iscale==1_${ik}$ ) then if( info==0_${ik}$ ) then imax = n else imax = info - 1_${ik}$ end if call stdlib${ii}$_dscal( imax, one / sigma, w, 1_${ik}$ ) end if ! set work(1) to optimal complex workspace size. work( 1_${ik}$ ) = lwkopt return end subroutine stdlib${ii}$_zheev #:for ck,ct,ci in CMPLX_KINDS_TYPES #:if not ck in ["sp","dp"] module subroutine stdlib${ii}$_${ci}$heev( jobz, uplo, n, a, lda, w, work, lwork, rwork,info ) !! ZHEEV: computes all eigenvalues and, optionally, eigenvectors of a !! complex Hermitian matrix A. ! -- 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) :: jobz, uplo integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: lda, lwork, n ! Array Arguments real(${ck}$), intent(out) :: rwork(*), w(*) complex(${ck}$), intent(inout) :: a(lda,*) complex(${ck}$), intent(out) :: work(*) ! ===================================================================== ! Local Scalars logical(lk) :: lower, lquery, wantz integer(${ik}$) :: iinfo, imax, inde, indtau, indwrk, iscale, llwork, lwkopt, nb real(${ck}$) :: anrm, bignum, eps, rmax, rmin, safmin, sigma, smlnum ! Intrinsic Functions ! Executable Statements ! test the input parameters. wantz = stdlib_lsame( jobz, 'V' ) lower = stdlib_lsame( uplo, 'L' ) lquery = ( lwork==-1_${ik}$ ) info = 0_${ik}$ if( .not.( wantz .or. stdlib_lsame( jobz, 'N' ) ) ) then info = -1_${ik}$ else if( .not.( lower .or. stdlib_lsame( uplo, 'U' ) ) ) then info = -2_${ik}$ else if( n<0_${ik}$ ) then info = -3_${ik}$ else if( lda<max( 1_${ik}$, n ) ) then info = -5_${ik}$ end if if( info==0_${ik}$ ) then nb = stdlib${ii}$_ilaenv( 1_${ik}$, 'ZHETRD', uplo, n, -1_${ik}$, -1_${ik}$, -1_${ik}$ ) lwkopt = max( 1_${ik}$, ( nb+1 )*n ) work( 1_${ik}$ ) = lwkopt if( lwork<max( 1_${ik}$, 2_${ik}$*n-1 ) .and. .not.lquery )info = -8_${ik}$ end if if( info/=0_${ik}$ ) then call stdlib${ii}$_xerbla( 'ZHEEV ', -info ) return else if( lquery ) then return end if ! quick return if possible if( n==0_${ik}$ ) then return end if if( n==1_${ik}$ ) then w( 1_${ik}$ ) = real( a( 1_${ik}$, 1_${ik}$ ),KIND=${ck}$) work( 1_${ik}$ ) = 1_${ik}$ if( wantz )a( 1_${ik}$, 1_${ik}$ ) = cone return end if ! get machine constants. safmin = stdlib${ii}$_${c2ri(ci)}$lamch( 'SAFE MINIMUM' ) eps = stdlib${ii}$_${c2ri(ci)}$lamch( 'PRECISION' ) smlnum = safmin / eps bignum = one / smlnum rmin = sqrt( smlnum ) rmax = sqrt( bignum ) ! scale matrix to allowable range, if necessary. anrm = stdlib${ii}$_${ci}$lanhe( 'M', uplo, n, a, lda, rwork ) iscale = 0_${ik}$ if( anrm>zero .and. anrm<rmin ) then iscale = 1_${ik}$ sigma = rmin / anrm else if( anrm>rmax ) then iscale = 1_${ik}$ sigma = rmax / anrm end if if( iscale==1_${ik}$ )call stdlib${ii}$_${ci}$lascl( uplo, 0_${ik}$, 0_${ik}$, one, sigma, n, n, a, lda, info ) ! call stdlib${ii}$_${ci}$hetrd to reduce hermitian matrix to tridiagonal form. inde = 1_${ik}$ indtau = 1_${ik}$ indwrk = indtau + n llwork = lwork - indwrk + 1_${ik}$ call stdlib${ii}$_${ci}$hetrd( uplo, n, a, lda, w, rwork( inde ), work( indtau ),work( indwrk ), & llwork, iinfo ) ! for eigenvalues only, call stdlib${ii}$_${c2ri(ci)}$sterf. for eigenvectors, first call ! stdlib${ii}$_${ci}$ungtr to generate the unitary matrix, then call stdlib${ii}$_${ci}$steqr. if( .not.wantz ) then call stdlib${ii}$_${c2ri(ci)}$sterf( n, w, rwork( inde ), info ) else call stdlib${ii}$_${ci}$ungtr( uplo, n, a, lda, work( indtau ), work( indwrk ),llwork, iinfo ) indwrk = inde + n call stdlib${ii}$_${ci}$steqr( jobz, n, w, rwork( inde ), a, lda,rwork( indwrk ), info ) end if ! if matrix was scaled, then rescale eigenvalues appropriately. if( iscale==1_${ik}$ ) then if( info==0_${ik}$ ) then imax = n else imax = info - 1_${ik}$ end if call stdlib${ii}$_${c2ri(ci)}$scal( imax, one / sigma, w, 1_${ik}$ ) end if ! set work(1) to optimal complex workspace size. work( 1_${ik}$ ) = lwkopt return end subroutine stdlib${ii}$_${ci}$heev #:endif #:endfor module subroutine stdlib${ii}$_cheevd( jobz, uplo, n, a, lda, w, work, lwork, rwork,lrwork, iwork, liwork,& !! CHEEVD computes all eigenvalues and, optionally, eigenvectors of a !! complex Hermitian matrix A. If eigenvectors are desired, it uses a !! divide and conquer algorithm. !! The divide and conquer algorithm makes very mild assumptions about !! floating point arithmetic. It will work on machines with a guard !! digit in add/subtract, or on those binary machines without guard !! digits which subtract like the Cray X-MP, Cray Y-MP, Cray C-90, or !! Cray-2. It could conceivably fail on hexadecimal or decimal machines !! without guard digits, but we know of none. 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) :: jobz, uplo integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: lda, liwork, lrwork, lwork, n ! Array Arguments integer(${ik}$), intent(out) :: iwork(*) real(sp), intent(out) :: rwork(*), w(*) complex(sp), intent(inout) :: a(lda,*) complex(sp), intent(out) :: work(*) ! ===================================================================== ! Local Scalars logical(lk) :: lower, lquery, wantz integer(${ik}$) :: iinfo, imax, inde, indrwk, indtau, indwk2, indwrk, iscale, liopt, & liwmin, llrwk, llwork, llwrk2, lopt, lropt, lrwmin, lwmin real(sp) :: anrm, bignum, eps, rmax, rmin, safmin, sigma, smlnum ! Intrinsic Functions ! Executable Statements ! test the input parameters. wantz = stdlib_lsame( jobz, 'V' ) lower = stdlib_lsame( uplo, 'L' ) lquery = ( lwork==-1_${ik}$ .or. lrwork==-1_${ik}$ .or. liwork==-1_${ik}$ ) info = 0_${ik}$ if( .not.( wantz .or. stdlib_lsame( jobz, 'N' ) ) ) then info = -1_${ik}$ else if( .not.( lower .or. stdlib_lsame( uplo, 'U' ) ) ) then info = -2_${ik}$ else if( n<0_${ik}$ ) then info = -3_${ik}$ else if( lda<max( 1_${ik}$, n ) ) then info = -5_${ik}$ end if if( info==0_${ik}$ ) then if( n<=1_${ik}$ ) then lwmin = 1_${ik}$ lrwmin = 1_${ik}$ liwmin = 1_${ik}$ lopt = lwmin lropt = lrwmin liopt = liwmin else if( wantz ) then lwmin = 2_${ik}$*n + n*n lrwmin = 1_${ik}$ + 5_${ik}$*n + 2_${ik}$*n**2_${ik}$ liwmin = 3_${ik}$ + 5_${ik}$*n else lwmin = n + 1_${ik}$ lrwmin = n liwmin = 1_${ik}$ end if lopt = max( lwmin, n +stdlib${ii}$_ilaenv( 1_${ik}$, 'CHETRD', uplo, n, -1_${ik}$, -1_${ik}$, -1_${ik}$ ) ) lropt = lrwmin liopt = liwmin end if work( 1_${ik}$ ) = lopt rwork( 1_${ik}$ ) = lropt iwork( 1_${ik}$ ) = liopt if( lwork<lwmin .and. .not.lquery ) then info = -8_${ik}$ else if( lrwork<lrwmin .and. .not.lquery ) then info = -10_${ik}$ else if( liwork<liwmin .and. .not.lquery ) then info = -12_${ik}$ end if end if if( info/=0_${ik}$ ) then call stdlib${ii}$_xerbla( 'CHEEVD', -info ) return else if( lquery ) then return end if ! quick return if possible if( n==0 )return if( n==1_${ik}$ ) then w( 1_${ik}$ ) = real( a( 1_${ik}$, 1_${ik}$ ),KIND=sp) if( wantz )a( 1_${ik}$, 1_${ik}$ ) = cone return end if ! get machine constants. safmin = stdlib${ii}$_slamch( 'SAFE MINIMUM' ) eps = stdlib${ii}$_slamch( 'PRECISION' ) smlnum = safmin / eps bignum = one / smlnum rmin = sqrt( smlnum ) rmax = sqrt( bignum ) ! scale matrix to allowable range, if necessary. anrm = stdlib${ii}$_clanhe( 'M', uplo, n, a, lda, rwork ) iscale = 0_${ik}$ if( anrm>zero .and. anrm<rmin ) then iscale = 1_${ik}$ sigma = rmin / anrm else if( anrm>rmax ) then iscale = 1_${ik}$ sigma = rmax / anrm end if if( iscale==1_${ik}$ )call stdlib${ii}$_clascl( uplo, 0_${ik}$, 0_${ik}$, one, sigma, n, n, a, lda, info ) ! call stdlib${ii}$_chetrd to reduce hermitian matrix to tridiagonal form. inde = 1_${ik}$ indtau = 1_${ik}$ indwrk = indtau + n indrwk = inde + n indwk2 = indwrk + n*n llwork = lwork - indwrk + 1_${ik}$ llwrk2 = lwork - indwk2 + 1_${ik}$ llrwk = lrwork - indrwk + 1_${ik}$ call stdlib${ii}$_chetrd( uplo, n, a, lda, w, rwork( inde ), work( indtau ),work( indwrk ), & llwork, iinfo ) ! for eigenvalues only, call stdlib${ii}$_ssterf. for eigenvectors, first call ! stdlib${ii}$_cstedc to generate the eigenvector matrix, work(indwrk), of the ! tridiagonal matrix, then call stdlib${ii}$_cunmtr to multiply it to the ! householder transformations represented as householder vectors in ! a. if( .not.wantz ) then call stdlib${ii}$_ssterf( n, w, rwork( inde ), info ) else call stdlib${ii}$_cstedc( 'I', n, w, rwork( inde ), work( indwrk ), n,work( indwk2 ), & llwrk2, rwork( indrwk ), llrwk,iwork, liwork, info ) call stdlib${ii}$_cunmtr( 'L', uplo, 'N', n, n, a, lda, work( indtau ),work( indwrk ), n, & work( indwk2 ), llwrk2, iinfo ) call stdlib${ii}$_clacpy( 'A', n, n, work( indwrk ), n, a, lda ) end if ! if matrix was scaled, then rescale eigenvalues appropriately. if( iscale==1_${ik}$ ) then if( info==0_${ik}$ ) then imax = n else imax = info - 1_${ik}$ end if call stdlib${ii}$_sscal( imax, one / sigma, w, 1_${ik}$ ) end if work( 1_${ik}$ ) = lopt rwork( 1_${ik}$ ) = lropt iwork( 1_${ik}$ ) = liopt return end subroutine stdlib${ii}$_cheevd module subroutine stdlib${ii}$_zheevd( jobz, uplo, n, a, lda, w, work, lwork, rwork,lrwork, iwork, liwork,& !! ZHEEVD computes all eigenvalues and, optionally, eigenvectors of a !! complex Hermitian matrix A. If eigenvectors are desired, it uses a !! divide and conquer algorithm. !! The divide and conquer algorithm makes very mild assumptions about !! floating point arithmetic. It will work on machines with a guard !! digit in add/subtract, or on those binary machines without guard !! digits which subtract like the Cray X-MP, Cray Y-MP, Cray C-90, or !! Cray-2. It could conceivably fail on hexadecimal or decimal machines !! without guard digits, but we know of none. 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) :: jobz, uplo integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: lda, liwork, lrwork, lwork, n ! Array Arguments integer(${ik}$), intent(out) :: iwork(*) real(dp), intent(out) :: rwork(*), w(*) complex(dp), intent(inout) :: a(lda,*) complex(dp), intent(out) :: work(*) ! ===================================================================== ! Local Scalars logical(lk) :: lower, lquery, wantz integer(${ik}$) :: iinfo, imax, inde, indrwk, indtau, indwk2, indwrk, iscale, liopt, & liwmin, llrwk, llwork, llwrk2, lopt, lropt, lrwmin, lwmin real(dp) :: anrm, bignum, eps, rmax, rmin, safmin, sigma, smlnum ! Intrinsic Functions ! Executable Statements ! test the input parameters. wantz = stdlib_lsame( jobz, 'V' ) lower = stdlib_lsame( uplo, 'L' ) lquery = ( lwork==-1_${ik}$ .or. lrwork==-1_${ik}$ .or. liwork==-1_${ik}$ ) info = 0_${ik}$ if( .not.( wantz .or. stdlib_lsame( jobz, 'N' ) ) ) then info = -1_${ik}$ else if( .not.( lower .or. stdlib_lsame( uplo, 'U' ) ) ) then info = -2_${ik}$ else if( n<0_${ik}$ ) then info = -3_${ik}$ else if( lda<max( 1_${ik}$, n ) ) then info = -5_${ik}$ end if if( info==0_${ik}$ ) then if( n<=1_${ik}$ ) then lwmin = 1_${ik}$ lrwmin = 1_${ik}$ liwmin = 1_${ik}$ lopt = lwmin lropt = lrwmin liopt = liwmin else if( wantz ) then lwmin = 2_${ik}$*n + n*n lrwmin = 1_${ik}$ + 5_${ik}$*n + 2_${ik}$*n**2_${ik}$ liwmin = 3_${ik}$ + 5_${ik}$*n else lwmin = n + 1_${ik}$ lrwmin = n liwmin = 1_${ik}$ end if lopt = max( lwmin, n +stdlib${ii}$_ilaenv( 1_${ik}$, 'ZHETRD', uplo, n, -1_${ik}$, -1_${ik}$, -1_${ik}$ ) ) lropt = lrwmin liopt = liwmin end if work( 1_${ik}$ ) = lopt rwork( 1_${ik}$ ) = lropt iwork( 1_${ik}$ ) = liopt if( lwork<lwmin .and. .not.lquery ) then info = -8_${ik}$ else if( lrwork<lrwmin .and. .not.lquery ) then info = -10_${ik}$ else if( liwork<liwmin .and. .not.lquery ) then info = -12_${ik}$ end if end if if( info/=0_${ik}$ ) then call stdlib${ii}$_xerbla( 'ZHEEVD', -info ) return else if( lquery ) then return end if ! quick return if possible if( n==0 )return if( n==1_${ik}$ ) then w( 1_${ik}$ ) = real( a( 1_${ik}$, 1_${ik}$ ),KIND=dp) if( wantz )a( 1_${ik}$, 1_${ik}$ ) = cone return end if ! get machine constants. safmin = stdlib${ii}$_dlamch( 'SAFE MINIMUM' ) eps = stdlib${ii}$_dlamch( 'PRECISION' ) smlnum = safmin / eps bignum = one / smlnum rmin = sqrt( smlnum ) rmax = sqrt( bignum ) ! scale matrix to allowable range, if necessary. anrm = stdlib${ii}$_zlanhe( 'M', uplo, n, a, lda, rwork ) iscale = 0_${ik}$ if( anrm>zero .and. anrm<rmin ) then iscale = 1_${ik}$ sigma = rmin / anrm else if( anrm>rmax ) then iscale = 1_${ik}$ sigma = rmax / anrm end if if( iscale==1_${ik}$ )call stdlib${ii}$_zlascl( uplo, 0_${ik}$, 0_${ik}$, one, sigma, n, n, a, lda, info ) ! call stdlib${ii}$_zhetrd to reduce hermitian matrix to tridiagonal form. inde = 1_${ik}$ indtau = 1_${ik}$ indwrk = indtau + n indrwk = inde + n indwk2 = indwrk + n*n llwork = lwork - indwrk + 1_${ik}$ llwrk2 = lwork - indwk2 + 1_${ik}$ llrwk = lrwork - indrwk + 1_${ik}$ call stdlib${ii}$_zhetrd( uplo, n, a, lda, w, rwork( inde ), work( indtau ),work( indwrk ), & llwork, iinfo ) ! for eigenvalues only, call stdlib${ii}$_dsterf. for eigenvectors, first call ! stdlib${ii}$_zstedc to generate the eigenvector matrix, work(indwrk), of the ! tridiagonal matrix, then call stdlib${ii}$_zunmtr to multiply it to the ! householder transformations represented as householder vectors in ! a. if( .not.wantz ) then call stdlib${ii}$_dsterf( n, w, rwork( inde ), info ) else call stdlib${ii}$_zstedc( 'I', n, w, rwork( inde ), work( indwrk ), n,work( indwk2 ), & llwrk2, rwork( indrwk ), llrwk,iwork, liwork, info ) call stdlib${ii}$_zunmtr( 'L', uplo, 'N', n, n, a, lda, work( indtau ),work( indwrk ), n, & work( indwk2 ), llwrk2, iinfo ) call stdlib${ii}$_zlacpy( 'A', n, n, work( indwrk ), n, a, lda ) end if ! if matrix was scaled, then rescale eigenvalues appropriately. if( iscale==1_${ik}$ ) then if( info==0_${ik}$ ) then imax = n else imax = info - 1_${ik}$ end if call stdlib${ii}$_dscal( imax, one / sigma, w, 1_${ik}$ ) end if work( 1_${ik}$ ) = lopt rwork( 1_${ik}$ ) = lropt iwork( 1_${ik}$ ) = liopt return end subroutine stdlib${ii}$_zheevd #:for ck,ct,ci in CMPLX_KINDS_TYPES #:if not ck in ["sp","dp"] module subroutine stdlib${ii}$_${ci}$heevd( jobz, uplo, n, a, lda, w, work, lwork, rwork,lrwork, iwork, liwork,& !! ZHEEVD: computes all eigenvalues and, optionally, eigenvectors of a !! complex Hermitian matrix A. If eigenvectors are desired, it uses a !! divide and conquer algorithm. !! The divide and conquer algorithm makes very mild assumptions about !! floating point arithmetic. It will work on machines with a guard !! digit in add/subtract, or on those binary machines without guard !! digits which subtract like the Cray X-MP, Cray Y-MP, Cray C-90, or !! Cray-2. It could conceivably fail on hexadecimal or decimal machines !! without guard digits, but we know of none. 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) :: jobz, uplo integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: lda, liwork, lrwork, lwork, n ! Array Arguments integer(${ik}$), intent(out) :: iwork(*) real(${ck}$), intent(out) :: rwork(*), w(*) complex(${ck}$), intent(inout) :: a(lda,*) complex(${ck}$), intent(out) :: work(*) ! ===================================================================== ! Local Scalars logical(lk) :: lower, lquery, wantz integer(${ik}$) :: iinfo, imax, inde, indrwk, indtau, indwk2, indwrk, iscale, liopt, & liwmin, llrwk, llwork, llwrk2, lopt, lropt, lrwmin, lwmin real(${ck}$) :: anrm, bignum, eps, rmax, rmin, safmin, sigma, smlnum ! Intrinsic Functions ! Executable Statements ! test the input parameters. wantz = stdlib_lsame( jobz, 'V' ) lower = stdlib_lsame( uplo, 'L' ) lquery = ( lwork==-1_${ik}$ .or. lrwork==-1_${ik}$ .or. liwork==-1_${ik}$ ) info = 0_${ik}$ if( .not.( wantz .or. stdlib_lsame( jobz, 'N' ) ) ) then info = -1_${ik}$ else if( .not.( lower .or. stdlib_lsame( uplo, 'U' ) ) ) then info = -2_${ik}$ else if( n<0_${ik}$ ) then info = -3_${ik}$ else if( lda<max( 1_${ik}$, n ) ) then info = -5_${ik}$ end if if( info==0_${ik}$ ) then if( n<=1_${ik}$ ) then lwmin = 1_${ik}$ lrwmin = 1_${ik}$ liwmin = 1_${ik}$ lopt = lwmin lropt = lrwmin liopt = liwmin else if( wantz ) then lwmin = 2_${ik}$*n + n*n lrwmin = 1_${ik}$ + 5_${ik}$*n + 2_${ik}$*n**2_${ik}$ liwmin = 3_${ik}$ + 5_${ik}$*n else lwmin = n + 1_${ik}$ lrwmin = n liwmin = 1_${ik}$ end if lopt = max( lwmin, n +stdlib${ii}$_ilaenv( 1_${ik}$, 'ZHETRD', uplo, n, -1_${ik}$, -1_${ik}$, -1_${ik}$ ) ) lropt = lrwmin liopt = liwmin end if work( 1_${ik}$ ) = lopt rwork( 1_${ik}$ ) = lropt iwork( 1_${ik}$ ) = liopt if( lwork<lwmin .and. .not.lquery ) then info = -8_${ik}$ else if( lrwork<lrwmin .and. .not.lquery ) then info = -10_${ik}$ else if( liwork<liwmin .and. .not.lquery ) then info = -12_${ik}$ end if end if if( info/=0_${ik}$ ) then call stdlib${ii}$_xerbla( 'ZHEEVD', -info ) return else if( lquery ) then return end if ! quick return if possible if( n==0 )return if( n==1_${ik}$ ) then w( 1_${ik}$ ) = real( a( 1_${ik}$, 1_${ik}$ ),KIND=${ck}$) if( wantz )a( 1_${ik}$, 1_${ik}$ ) = cone return end if ! get machine constants. safmin = stdlib${ii}$_${c2ri(ci)}$lamch( 'SAFE MINIMUM' ) eps = stdlib${ii}$_${c2ri(ci)}$lamch( 'PRECISION' ) smlnum = safmin / eps bignum = one / smlnum rmin = sqrt( smlnum ) rmax = sqrt( bignum ) ! scale matrix to allowable range, if necessary. anrm = stdlib${ii}$_${ci}$lanhe( 'M', uplo, n, a, lda, rwork ) iscale = 0_${ik}$ if( anrm>zero .and. anrm<rmin ) then iscale = 1_${ik}$ sigma = rmin / anrm else if( anrm>rmax ) then iscale = 1_${ik}$ sigma = rmax / anrm end if if( iscale==1_${ik}$ )call stdlib${ii}$_${ci}$lascl( uplo, 0_${ik}$, 0_${ik}$, one, sigma, n, n, a, lda, info ) ! call stdlib${ii}$_${ci}$hetrd to reduce hermitian matrix to tridiagonal form. inde = 1_${ik}$ indtau = 1_${ik}$ indwrk = indtau + n indrwk = inde + n indwk2 = indwrk + n*n llwork = lwork - indwrk + 1_${ik}$ llwrk2 = lwork - indwk2 + 1_${ik}$ llrwk = lrwork - indrwk + 1_${ik}$ call stdlib${ii}$_${ci}$hetrd( uplo, n, a, lda, w, rwork( inde ), work( indtau ),work( indwrk ), & llwork, iinfo ) ! for eigenvalues only, call stdlib${ii}$_${c2ri(ci)}$sterf. for eigenvectors, first call ! stdlib${ii}$_${ci}$stedc to generate the eigenvector matrix, work(indwrk), of the ! tridiagonal matrix, then call stdlib${ii}$_${ci}$unmtr to multiply it to the ! householder transformations represented as householder vectors in ! a. if( .not.wantz ) then call stdlib${ii}$_${c2ri(ci)}$sterf( n, w, rwork( inde ), info ) else call stdlib${ii}$_${ci}$stedc( 'I', n, w, rwork( inde ), work( indwrk ), n,work( indwk2 ), & llwrk2, rwork( indrwk ), llrwk,iwork, liwork, info ) call stdlib${ii}$_${ci}$unmtr( 'L', uplo, 'N', n, n, a, lda, work( indtau ),work( indwrk ), n, & work( indwk2 ), llwrk2, iinfo ) call stdlib${ii}$_${ci}$lacpy( 'A', n, n, work( indwrk ), n, a, lda ) end if ! if matrix was scaled, then rescale eigenvalues appropriately. if( iscale==1_${ik}$ ) then if( info==0_${ik}$ ) then imax = n else imax = info - 1_${ik}$ end if call stdlib${ii}$_${c2ri(ci)}$scal( imax, one / sigma, w, 1_${ik}$ ) end if work( 1_${ik}$ ) = lopt rwork( 1_${ik}$ ) = lropt iwork( 1_${ik}$ ) = liopt return end subroutine stdlib${ii}$_${ci}$heevd #:endif #:endfor module subroutine stdlib${ii}$_cheevr( jobz, range, uplo, n, a, lda, vl, vu, il, iu,abstol, m, w, z, ldz, & !! CHEEVR computes selected eigenvalues and, optionally, eigenvectors !! of a complex Hermitian matrix A. Eigenvalues and eigenvectors can !! be selected by specifying either a range of values or a range of !! indices for the desired eigenvalues. !! CHEEVR first reduces the matrix A to tridiagonal form T with a call !! to CHETRD. Then, whenever possible, CHEEVR calls CSTEMR to compute !! the eigenspectrum using Relatively Robust Representations. CSTEMR !! computes eigenvalues by the dqds algorithm, while orthogonal !! eigenvectors are computed from various "good" L D L^T representations !! (also known as Relatively Robust Representations). Gram-Schmidt !! orthogonalization is avoided as far as possible. More specifically, !! the various steps of the algorithm are as follows. !! For each unreduced block (submatrix) of T, !! (a) Compute T - sigma I = L D L^T, so that L and D !! define all the wanted eigenvalues to high relative accuracy. !! This means that small relative changes in the entries of D and L !! cause only small relative changes in the eigenvalues and !! eigenvectors. The standard (unfactored) representation of the !! tridiagonal matrix T does not have this property in general. !! (b) Compute the eigenvalues to suitable accuracy. !! If the eigenvectors are desired, the algorithm attains full !! accuracy of the computed eigenvalues only right before !! the corresponding vectors have to be computed, see steps c) and d). !! (c) For each cluster of close eigenvalues, select a new !! shift close to the cluster, find a new factorization, and refine !! the shifted eigenvalues to suitable accuracy. !! (d) For each eigenvalue with a large enough relative separation compute !! the corresponding eigenvector by forming a rank revealing twisted !! factorization. Go back to (c) for any clusters that remain. !! The desired accuracy of the output can be specified by the input !! parameter ABSTOL. !! For more details, see CSTEMR's documentation and: !! - Inderjit S. Dhillon and Beresford N. Parlett: "Multiple representations !! to compute orthogonal eigenvectors of symmetric tridiagonal matrices," !! Linear Algebra and its Applications, 387(1), pp. 1-28, August 2004. !! - Inderjit Dhillon and Beresford Parlett: "Orthogonal Eigenvectors and !! Relative Gaps," SIAM Journal on Matrix Analysis and Applications, Vol. 25, !! 2004. Also LAPACK Working Note 154. !! - Inderjit Dhillon: "A new O(n^2) algorithm for the symmetric !! tridiagonal eigenvalue/eigenvector problem", !! Computer Science Division Technical Report No. UCB/CSD-97-971, !! UC Berkeley, May 1997. !! Note 1 : CHEEVR calls CSTEMR when the full spectrum is requested !! on machines which conform to the ieee-754 floating point standard. !! CHEEVR calls SSTEBZ and CSTEIN on non-ieee machines and !! when partial spectrum requests are made. !! Normal execution of CSTEMR may create NaNs and infinities and !! hence may abort due to a floating point exception in environments !! which do not handle NaNs and infinities in the ieee standard default !! manner. isuppz, work, lwork,rwork, lrwork, iwork, liwork, 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) :: jobz, range, uplo integer(${ik}$), intent(in) :: il, iu, lda, ldz, liwork, lrwork, lwork, n integer(${ik}$), intent(out) :: info, m real(sp), intent(in) :: abstol, vl, vu ! Array Arguments integer(${ik}$), intent(out) :: isuppz(*), iwork(*) real(sp), intent(out) :: rwork(*), w(*) complex(sp), intent(inout) :: a(lda,*) complex(sp), intent(out) :: work(*), z(ldz,*) ! ===================================================================== ! Local Scalars logical(lk) :: alleig, indeig, lower, lquery, test, valeig, wantz, tryrac character :: order integer(${ik}$) :: i, ieeeok, iinfo, imax, indibl, indifl, indisp, indiwo, indrd, indrdd, & indre, indree, indrwk, indtau, indwk, indwkn, iscale, itmp1, j, jj, liwmin, llwork, & llrwork, llwrkn, lrwmin, lwkopt, lwmin, nb, nsplit real(sp) :: abstll, anrm, bignum, eps, rmax, rmin, safmin, sigma, smlnum, tmp1, vll, & vuu ! Intrinsic Functions ! Executable Statements ! test the input parameters. ieeeok = stdlib${ii}$_ilaenv( 10_${ik}$, 'CHEEVR', 'N', 1_${ik}$, 2_${ik}$, 3_${ik}$, 4_${ik}$ ) lower = stdlib_lsame( uplo, 'L' ) wantz = stdlib_lsame( jobz, 'V' ) alleig = stdlib_lsame( range, 'A' ) valeig = stdlib_lsame( range, 'V' ) indeig = stdlib_lsame( range, 'I' ) lquery = ( ( lwork==-1_${ik}$ ) .or. ( lrwork==-1_${ik}$ ) .or.( liwork==-1_${ik}$ ) ) lrwmin = max( 1_${ik}$, 24_${ik}$*n ) liwmin = max( 1_${ik}$, 10_${ik}$*n ) lwmin = max( 1_${ik}$, 2_${ik}$*n ) info = 0_${ik}$ if( .not.( wantz .or. stdlib_lsame( jobz, 'N' ) ) ) then info = -1_${ik}$ else if( .not.( alleig .or. valeig .or. indeig ) ) then info = -2_${ik}$ else if( .not.( lower .or. stdlib_lsame( uplo, 'U' ) ) ) then info = -3_${ik}$ else if( n<0_${ik}$ ) then info = -4_${ik}$ else if( lda<max( 1_${ik}$, n ) ) then info = -6_${ik}$ else if( valeig ) then if( n>0_${ik}$ .and. vu<=vl )info = -8_${ik}$ else if( indeig ) then if( il<1_${ik}$ .or. il>max( 1_${ik}$, n ) ) then info = -9_${ik}$ else if( iu<min( n, il ) .or. iu>n ) then info = -10_${ik}$ end if end if end if if( info==0_${ik}$ ) then if( ldz<1_${ik}$ .or. ( wantz .and. ldz<n ) ) then info = -15_${ik}$ end if end if if( info==0_${ik}$ ) then nb = stdlib${ii}$_ilaenv( 1_${ik}$, 'CHETRD', uplo, n, -1_${ik}$, -1_${ik}$, -1_${ik}$ ) nb = max( nb, stdlib${ii}$_ilaenv( 1_${ik}$, 'CUNMTR', uplo, n, -1_${ik}$, -1_${ik}$, -1_${ik}$ ) ) lwkopt = max( ( nb+1 )*n, lwmin ) work( 1_${ik}$ ) = lwkopt rwork( 1_${ik}$ ) = lrwmin iwork( 1_${ik}$ ) = liwmin if( lwork<lwmin .and. .not.lquery ) then info = -18_${ik}$ else if( lrwork<lrwmin .and. .not.lquery ) then info = -20_${ik}$ else if( liwork<liwmin .and. .not.lquery ) then info = -22_${ik}$ end if end if if( info/=0_${ik}$ ) then call stdlib${ii}$_xerbla( 'CHEEVR', -info ) return else if( lquery ) then return end if ! quick return if possible m = 0_${ik}$ if( n==0_${ik}$ ) then work( 1_${ik}$ ) = 1_${ik}$ return end if if( n==1_${ik}$ ) then work( 1_${ik}$ ) = 2_${ik}$ if( alleig .or. indeig ) then m = 1_${ik}$ w( 1_${ik}$ ) = real( a( 1_${ik}$, 1_${ik}$ ),KIND=sp) else if( vl<real( a( 1_${ik}$, 1_${ik}$ ),KIND=sp) .and. vu>=real( a( 1_${ik}$, 1_${ik}$ ),KIND=sp) )then m = 1_${ik}$ w( 1_${ik}$ ) = real( a( 1_${ik}$, 1_${ik}$ ),KIND=sp) end if end if if( wantz ) then z( 1_${ik}$, 1_${ik}$ ) = one isuppz( 1_${ik}$ ) = 1_${ik}$ isuppz( 2_${ik}$ ) = 1_${ik}$ end if return end if ! get machine constants. safmin = stdlib${ii}$_slamch( 'SAFE MINIMUM' ) eps = stdlib${ii}$_slamch( 'PRECISION' ) smlnum = safmin / eps bignum = one / smlnum rmin = sqrt( smlnum ) rmax = min( sqrt( bignum ), one / sqrt( sqrt( safmin ) ) ) ! scale matrix to allowable range, if necessary. iscale = 0_${ik}$ abstll = abstol if (valeig) then vll = vl vuu = vu end if anrm = stdlib${ii}$_clansy( 'M', uplo, n, a, lda, rwork ) if( anrm>zero .and. anrm<rmin ) then iscale = 1_${ik}$ sigma = rmin / anrm else if( anrm>rmax ) then iscale = 1_${ik}$ sigma = rmax / anrm end if if( iscale==1_${ik}$ ) then if( lower ) then do j = 1, n call stdlib${ii}$_csscal( n-j+1, sigma, a( j, j ), 1_${ik}$ ) end do else do j = 1, n call stdlib${ii}$_csscal( j, sigma, a( 1_${ik}$, j ), 1_${ik}$ ) end do end if if( abstol>0_${ik}$ )abstll = abstol*sigma if( valeig ) then vll = vl*sigma vuu = vu*sigma end if end if ! initialize indices into workspaces. note: the iwork indices are ! used only if stdlib${ii}$_ssterf or stdlib${ii}$_cstemr fail. ! work(indtau:indtau+n-1) stores the complex scalar factors of the ! elementary reflectors used in stdlib${ii}$_chetrd. indtau = 1_${ik}$ ! indwk is the starting offset of the remaining complex workspace, ! and llwork is the remaining complex workspace size. indwk = indtau + n llwork = lwork - indwk + 1_${ik}$ ! rwork(indrd:indrd+n-1) stores the real tridiagonal's diagonal ! entries. indrd = 1_${ik}$ ! rwork(indre:indre+n-1) stores the off-diagonal entries of the ! tridiagonal matrix from stdlib${ii}$_chetrd. indre = indrd + n ! rwork(indrdd:indrdd+n-1) is a copy of the diagonal entries over ! -written by stdlib${ii}$_cstemr (the stdlib${ii}$_ssterf path copies the diagonal to w). indrdd = indre + n ! rwork(indree:indree+n-1) is a copy of the off-diagonal entries over ! -written while computing the eigenvalues in stdlib${ii}$_ssterf and stdlib${ii}$_cstemr. indree = indrdd + n ! indrwk is the starting offset of the left-over real workspace, and ! llrwork is the remaining workspace size. indrwk = indree + n llrwork = lrwork - indrwk + 1_${ik}$ ! iwork(indibl:indibl+m-1) corresponds to iblock in stdlib${ii}$_sstebz and ! stores the block indices of each of the m<=n eigenvalues. indibl = 1_${ik}$ ! iwork(indisp:indisp+nsplit-1) corresponds to isplit in stdlib${ii}$_sstebz and ! stores the starting and finishing indices of each block. indisp = indibl + n ! iwork(indifl:indifl+n-1) stores the indices of eigenvectors ! that corresponding to eigenvectors that fail to converge in ! stdlib${ii}$_sstein. this information is discarded; if any fail, the driver ! returns info > 0. indifl = indisp + n ! indiwo is the offset of the remaining integer workspace. indiwo = indifl + n ! call stdlib${ii}$_chetrd to reduce hermitian matrix to tridiagonal form. call stdlib${ii}$_chetrd( uplo, n, a, lda, rwork( indrd ), rwork( indre ),work( indtau ), & work( indwk ), llwork, iinfo ) ! if all eigenvalues are desired ! then call stdlib${ii}$_ssterf or stdlib${ii}$_cstemr and stdlib${ii}$_cunmtr. test = .false. if( indeig ) then if( il==1_${ik}$ .and. iu==n ) then test = .true. end if end if if( ( alleig.or.test ) .and. ( ieeeok==1_${ik}$ ) ) then if( .not.wantz ) then call stdlib${ii}$_scopy( n, rwork( indrd ), 1_${ik}$, w, 1_${ik}$ ) call stdlib${ii}$_scopy( n-1, rwork( indre ), 1_${ik}$, rwork( indree ), 1_${ik}$ ) call stdlib${ii}$_ssterf( n, w, rwork( indree ), info ) else call stdlib${ii}$_scopy( n-1, rwork( indre ), 1_${ik}$, rwork( indree ), 1_${ik}$ ) call stdlib${ii}$_scopy( n, rwork( indrd ), 1_${ik}$, rwork( indrdd ), 1_${ik}$ ) if (abstol <= two*n*eps) then tryrac = .true. else tryrac = .false. end if call stdlib${ii}$_cstemr( jobz, 'A', n, rwork( indrdd ),rwork( indree ), vl, vu, il, & iu, m, w,z, ldz, n, isuppz, tryrac,rwork( indrwk ), llrwork,iwork, liwork, info ) ! apply unitary matrix used in reduction to tridiagonal ! form to eigenvectors returned by stdlib${ii}$_cstemr. if( wantz .and. info==0_${ik}$ ) then indwkn = indwk llwrkn = lwork - indwkn + 1_${ik}$ call stdlib${ii}$_cunmtr( 'L', uplo, 'N', n, m, a, lda,work( indtau ), z, ldz, work(& indwkn ),llwrkn, iinfo ) end if end if if( info==0_${ik}$ ) then m = n go to 30 end if info = 0_${ik}$ end if ! otherwise, call stdlib${ii}$_sstebz and, if eigenvectors are desired, stdlib${ii}$_cstein. ! also call stdlib${ii}$_sstebz and stdlib${ii}$_cstein if stdlib${ii}$_cstemr fails. if( wantz ) then order = 'B' else order = 'E' end if call stdlib${ii}$_sstebz( range, order, n, vll, vuu, il, iu, abstll,rwork( indrd ), rwork( & indre ), m, nsplit, w,iwork( indibl ), iwork( indisp ), rwork( indrwk ),iwork( indiwo )& , info ) if( wantz ) then call stdlib${ii}$_cstein( n, rwork( indrd ), rwork( indre ), m, w,iwork( indibl ), iwork( & indisp ), z, ldz,rwork( indrwk ), iwork( indiwo ), iwork( indifl ),info ) ! apply unitary matrix used in reduction to tridiagonal ! form to eigenvectors returned by stdlib${ii}$_cstein. indwkn = indwk llwrkn = lwork - indwkn + 1_${ik}$ call stdlib${ii}$_cunmtr( 'L', uplo, 'N', n, m, a, lda, work( indtau ), z,ldz, work( & indwkn ), llwrkn, iinfo ) end if ! if matrix was scaled, then rescale eigenvalues appropriately. 30 continue if( iscale==1_${ik}$ ) then if( info==0_${ik}$ ) then imax = m else imax = info - 1_${ik}$ end if call stdlib${ii}$_sscal( imax, one / sigma, w, 1_${ik}$ ) end if ! if eigenvalues are not in order, then sort them, along with ! eigenvectors. if( wantz ) then do j = 1, m - 1 i = 0_${ik}$ tmp1 = w( j ) do jj = j + 1, m if( w( jj )<tmp1 ) then i = jj tmp1 = w( jj ) end if end do if( i/=0_${ik}$ ) then itmp1 = iwork( indibl+i-1 ) w( i ) = w( j ) iwork( indibl+i-1 ) = iwork( indibl+j-1 ) w( j ) = tmp1 iwork( indibl+j-1 ) = itmp1 call stdlib${ii}$_cswap( n, z( 1_${ik}$, i ), 1_${ik}$, z( 1_${ik}$, j ), 1_${ik}$ ) end if end do end if ! set work(1) to optimal workspace size. work( 1_${ik}$ ) = lwkopt rwork( 1_${ik}$ ) = lrwmin iwork( 1_${ik}$ ) = liwmin return end subroutine stdlib${ii}$_cheevr module subroutine stdlib${ii}$_zheevr( jobz, range, uplo, n, a, lda, vl, vu, il, iu,abstol, m, w, z, ldz, & !! ZHEEVR computes selected eigenvalues and, optionally, eigenvectors !! of a complex Hermitian matrix A. Eigenvalues and eigenvectors can !! be selected by specifying either a range of values or a range of !! indices for the desired eigenvalues. !! ZHEEVR first reduces the matrix A to tridiagonal form T with a call !! to ZHETRD. Then, whenever possible, ZHEEVR calls ZSTEMR to compute !! eigenspectrum using Relatively Robust Representations. ZSTEMR !! computes eigenvalues by the dqds algorithm, while orthogonal !! eigenvectors are computed from various "good" L D L^T representations !! (also known as Relatively Robust Representations). Gram-Schmidt !! orthogonalization is avoided as far as possible. More specifically, !! the various steps of the algorithm are as follows. !! For each unreduced block (submatrix) of T, !! (a) Compute T - sigma I = L D L^T, so that L and D !! define all the wanted eigenvalues to high relative accuracy. !! This means that small relative changes in the entries of D and L !! cause only small relative changes in the eigenvalues and !! eigenvectors. The standard (unfactored) representation of the !! tridiagonal matrix T does not have this property in general. !! (b) Compute the eigenvalues to suitable accuracy. !! If the eigenvectors are desired, the algorithm attains full !! accuracy of the computed eigenvalues only right before !! the corresponding vectors have to be computed, see steps c) and d). !! (c) For each cluster of close eigenvalues, select a new !! shift close to the cluster, find a new factorization, and refine !! the shifted eigenvalues to suitable accuracy. !! (d) For each eigenvalue with a large enough relative separation compute !! the corresponding eigenvector by forming a rank revealing twisted !! factorization. Go back to (c) for any clusters that remain. !! The desired accuracy of the output can be specified by the input !! parameter ABSTOL. !! For more details, see ZSTEMR's documentation and: !! - Inderjit S. Dhillon and Beresford N. Parlett: "Multiple representations !! to compute orthogonal eigenvectors of symmetric tridiagonal matrices," !! Linear Algebra and its Applications, 387(1), pp. 1-28, August 2004. !! - Inderjit Dhillon and Beresford Parlett: "Orthogonal Eigenvectors and !! Relative Gaps," SIAM Journal on Matrix Analysis and Applications, Vol. 25, !! 2004. Also LAPACK Working Note 154. !! - Inderjit Dhillon: "A new O(n^2) algorithm for the symmetric !! tridiagonal eigenvalue/eigenvector problem", !! Computer Science Division Technical Report No. UCB/CSD-97-971, !! UC Berkeley, May 1997. !! Note 1 : ZHEEVR calls ZSTEMR when the full spectrum is requested !! on machines which conform to the ieee-754 floating point standard. !! ZHEEVR calls DSTEBZ and ZSTEIN on non-ieee machines and !! when partial spectrum requests are made. !! Normal execution of ZSTEMR may create NaNs and infinities and !! hence may abort due to a floating point exception in environments !! which do not handle NaNs and infinities in the ieee standard default !! manner. isuppz, work, lwork,rwork, lrwork, iwork, liwork, 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) :: jobz, range, uplo integer(${ik}$), intent(in) :: il, iu, lda, ldz, liwork, lrwork, lwork, n integer(${ik}$), intent(out) :: info, m real(dp), intent(in) :: abstol, vl, vu ! Array Arguments integer(${ik}$), intent(out) :: isuppz(*), iwork(*) real(dp), intent(out) :: rwork(*), w(*) complex(dp), intent(inout) :: a(lda,*) complex(dp), intent(out) :: work(*), z(ldz,*) ! ===================================================================== ! Local Scalars logical(lk) :: alleig, indeig, lower, lquery, test, valeig, wantz, tryrac character :: order integer(${ik}$) :: i, ieeeok, iinfo, imax, indibl, indifl, indisp, indiwo, indrd, indrdd, & indre, indree, indrwk, indtau, indwk, indwkn, iscale, itmp1, j, jj, liwmin, llwork, & llrwork, llwrkn, lrwmin, lwkopt, lwmin, nb, nsplit real(dp) :: abstll, anrm, bignum, eps, rmax, rmin, safmin, sigma, smlnum, tmp1, vll, & vuu ! Intrinsic Functions ! Executable Statements ! test the input parameters. ieeeok = stdlib${ii}$_ilaenv( 10_${ik}$, 'ZHEEVR', 'N', 1_${ik}$, 2_${ik}$, 3_${ik}$, 4_${ik}$ ) lower = stdlib_lsame( uplo, 'L' ) wantz = stdlib_lsame( jobz, 'V' ) alleig = stdlib_lsame( range, 'A' ) valeig = stdlib_lsame( range, 'V' ) indeig = stdlib_lsame( range, 'I' ) lquery = ( ( lwork==-1_${ik}$ ) .or. ( lrwork==-1_${ik}$ ) .or.( liwork==-1_${ik}$ ) ) lrwmin = max( 1_${ik}$, 24_${ik}$*n ) liwmin = max( 1_${ik}$, 10_${ik}$*n ) lwmin = max( 1_${ik}$, 2_${ik}$*n ) info = 0_${ik}$ if( .not.( wantz .or. stdlib_lsame( jobz, 'N' ) ) ) then info = -1_${ik}$ else if( .not.( alleig .or. valeig .or. indeig ) ) then info = -2_${ik}$ else if( .not.( lower .or. stdlib_lsame( uplo, 'U' ) ) ) then info = -3_${ik}$ else if( n<0_${ik}$ ) then info = -4_${ik}$ else if( lda<max( 1_${ik}$, n ) ) then info = -6_${ik}$ else if( valeig ) then if( n>0_${ik}$ .and. vu<=vl )info = -8_${ik}$ else if( indeig ) then if( il<1_${ik}$ .or. il>max( 1_${ik}$, n ) ) then info = -9_${ik}$ else if( iu<min( n, il ) .or. iu>n ) then info = -10_${ik}$ end if end if end if if( info==0_${ik}$ ) then if( ldz<1_${ik}$ .or. ( wantz .and. ldz<n ) ) then info = -15_${ik}$ end if end if if( info==0_${ik}$ ) then nb = stdlib${ii}$_ilaenv( 1_${ik}$, 'ZHETRD', uplo, n, -1_${ik}$, -1_${ik}$, -1_${ik}$ ) nb = max( nb, stdlib${ii}$_ilaenv( 1_${ik}$, 'ZUNMTR', uplo, n, -1_${ik}$, -1_${ik}$, -1_${ik}$ ) ) lwkopt = max( ( nb+1 )*n, lwmin ) work( 1_${ik}$ ) = lwkopt rwork( 1_${ik}$ ) = lrwmin iwork( 1_${ik}$ ) = liwmin if( lwork<lwmin .and. .not.lquery ) then info = -18_${ik}$ else if( lrwork<lrwmin .and. .not.lquery ) then info = -20_${ik}$ else if( liwork<liwmin .and. .not.lquery ) then info = -22_${ik}$ end if end if if( info/=0_${ik}$ ) then call stdlib${ii}$_xerbla( 'ZHEEVR', -info ) return else if( lquery ) then return end if ! quick return if possible m = 0_${ik}$ if( n==0_${ik}$ ) then work( 1_${ik}$ ) = 1_${ik}$ return end if if( n==1_${ik}$ ) then work( 1_${ik}$ ) = 2_${ik}$ if( alleig .or. indeig ) then m = 1_${ik}$ w( 1_${ik}$ ) = real( a( 1_${ik}$, 1_${ik}$ ),KIND=dp) else if( vl<real( a( 1_${ik}$, 1_${ik}$ ),KIND=dp) .and. vu>=real( a( 1_${ik}$, 1_${ik}$ ),KIND=dp) )then m = 1_${ik}$ w( 1_${ik}$ ) = real( a( 1_${ik}$, 1_${ik}$ ),KIND=dp) end if end if if( wantz ) then z( 1_${ik}$, 1_${ik}$ ) = one isuppz( 1_${ik}$ ) = 1_${ik}$ isuppz( 2_${ik}$ ) = 1_${ik}$ end if return end if ! get machine constants. safmin = stdlib${ii}$_dlamch( 'SAFE MINIMUM' ) eps = stdlib${ii}$_dlamch( 'PRECISION' ) smlnum = safmin / eps bignum = one / smlnum rmin = sqrt( smlnum ) rmax = min( sqrt( bignum ), one / sqrt( sqrt( safmin ) ) ) ! scale matrix to allowable range, if necessary. iscale = 0_${ik}$ abstll = abstol if (valeig) then vll = vl vuu = vu end if anrm = stdlib${ii}$_zlansy( 'M', uplo, n, a, lda, rwork ) if( anrm>zero .and. anrm<rmin ) then iscale = 1_${ik}$ sigma = rmin / anrm else if( anrm>rmax ) then iscale = 1_${ik}$ sigma = rmax / anrm end if if( iscale==1_${ik}$ ) then if( lower ) then do j = 1, n call stdlib${ii}$_zdscal( n-j+1, sigma, a( j, j ), 1_${ik}$ ) end do else do j = 1, n call stdlib${ii}$_zdscal( j, sigma, a( 1_${ik}$, j ), 1_${ik}$ ) end do end if if( abstol>0_${ik}$ )abstll = abstol*sigma if( valeig ) then vll = vl*sigma vuu = vu*sigma end if end if ! initialize indices into workspaces. note: the iwork indices are ! used only if stdlib${ii}$_dsterf or stdlib${ii}$_zstemr fail. ! work(indtau:indtau+n-1) stores the complex scalar factors of the ! elementary reflectors used in stdlib${ii}$_zhetrd. indtau = 1_${ik}$ ! indwk is the starting offset of the remaining complex workspace, ! and llwork is the remaining complex workspace size. indwk = indtau + n llwork = lwork - indwk + 1_${ik}$ ! rwork(indrd:indrd+n-1) stores the real tridiagonal's diagonal ! entries. indrd = 1_${ik}$ ! rwork(indre:indre+n-1) stores the off-diagonal entries of the ! tridiagonal matrix from stdlib${ii}$_zhetrd. indre = indrd + n ! rwork(indrdd:indrdd+n-1) is a copy of the diagonal entries over ! -written by stdlib${ii}$_zstemr (the stdlib${ii}$_dsterf path copies the diagonal to w). indrdd = indre + n ! rwork(indree:indree+n-1) is a copy of the off-diagonal entries over ! -written while computing the eigenvalues in stdlib${ii}$_dsterf and stdlib${ii}$_zstemr. indree = indrdd + n ! indrwk is the starting offset of the left-over real workspace, and ! llrwork is the remaining workspace size. indrwk = indree + n llrwork = lrwork - indrwk + 1_${ik}$ ! iwork(indibl:indibl+m-1) corresponds to iblock in stdlib${ii}$_dstebz and ! stores the block indices of each of the m<=n eigenvalues. indibl = 1_${ik}$ ! iwork(indisp:indisp+nsplit-1) corresponds to isplit in stdlib${ii}$_dstebz and ! stores the starting and finishing indices of each block. indisp = indibl + n ! iwork(indifl:indifl+n-1) stores the indices of eigenvectors ! that corresponding to eigenvectors that fail to converge in ! stdlib${ii}$_dstein. this information is discarded; if any fail, the driver ! returns info > 0. indifl = indisp + n ! indiwo is the offset of the remaining integer workspace. indiwo = indifl + n ! call stdlib${ii}$_zhetrd to reduce hermitian matrix to tridiagonal form. call stdlib${ii}$_zhetrd( uplo, n, a, lda, rwork( indrd ), rwork( indre ),work( indtau ), & work( indwk ), llwork, iinfo ) ! if all eigenvalues are desired ! then call stdlib${ii}$_dsterf or stdlib${ii}$_zstemr and stdlib${ii}$_zunmtr. test = .false. if( indeig ) then if( il==1_${ik}$ .and. iu==n ) then test = .true. end if end if if( ( alleig.or.test ) .and. ( ieeeok==1_${ik}$ ) ) then if( .not.wantz ) then call stdlib${ii}$_dcopy( n, rwork( indrd ), 1_${ik}$, w, 1_${ik}$ ) call stdlib${ii}$_dcopy( n-1, rwork( indre ), 1_${ik}$, rwork( indree ), 1_${ik}$ ) call stdlib${ii}$_dsterf( n, w, rwork( indree ), info ) else call stdlib${ii}$_dcopy( n-1, rwork( indre ), 1_${ik}$, rwork( indree ), 1_${ik}$ ) call stdlib${ii}$_dcopy( n, rwork( indrd ), 1_${ik}$, rwork( indrdd ), 1_${ik}$ ) if (abstol <= two*n*eps) then tryrac = .true. else tryrac = .false. end if call stdlib${ii}$_zstemr( jobz, 'A', n, rwork( indrdd ),rwork( indree ), vl, vu, il, & iu, m, w,z, ldz, n, isuppz, tryrac,rwork( indrwk ), llrwork,iwork, liwork, info ) ! apply unitary matrix used in reduction to tridiagonal ! form to eigenvectors returned by stdlib${ii}$_zstemr. if( wantz .and. info==0_${ik}$ ) then indwkn = indwk llwrkn = lwork - indwkn + 1_${ik}$ call stdlib${ii}$_zunmtr( 'L', uplo, 'N', n, m, a, lda,work( indtau ), z, ldz, work(& indwkn ),llwrkn, iinfo ) end if end if if( info==0_${ik}$ ) then m = n go to 30 end if info = 0_${ik}$ end if ! otherwise, call stdlib${ii}$_dstebz and, if eigenvectors are desired, stdlib${ii}$_zstein. ! also call stdlib${ii}$_dstebz and stdlib${ii}$_zstein if stdlib${ii}$_zstemr fails. if( wantz ) then order = 'B' else order = 'E' end if call stdlib${ii}$_dstebz( range, order, n, vll, vuu, il, iu, abstll,rwork( indrd ), rwork( & indre ), m, nsplit, w,iwork( indibl ), iwork( indisp ), rwork( indrwk ),iwork( indiwo )& , info ) if( wantz ) then call stdlib${ii}$_zstein( n, rwork( indrd ), rwork( indre ), m, w,iwork( indibl ), iwork( & indisp ), z, ldz,rwork( indrwk ), iwork( indiwo ), iwork( indifl ),info ) ! apply unitary matrix used in reduction to tridiagonal ! form to eigenvectors returned by stdlib${ii}$_zstein. indwkn = indwk llwrkn = lwork - indwkn + 1_${ik}$ call stdlib${ii}$_zunmtr( 'L', uplo, 'N', n, m, a, lda, work( indtau ), z,ldz, work( & indwkn ), llwrkn, iinfo ) end if ! if matrix was scaled, then rescale eigenvalues appropriately. 30 continue if( iscale==1_${ik}$ ) then if( info==0_${ik}$ ) then imax = m else imax = info - 1_${ik}$ end if call stdlib${ii}$_dscal( imax, one / sigma, w, 1_${ik}$ ) end if ! if eigenvalues are not in order, then sort them, along with ! eigenvectors. if( wantz ) then do j = 1, m - 1 i = 0_${ik}$ tmp1 = w( j ) do jj = j + 1, m if( w( jj )<tmp1 ) then i = jj tmp1 = w( jj ) end if end do if( i/=0_${ik}$ ) then itmp1 = iwork( indibl+i-1 ) w( i ) = w( j ) iwork( indibl+i-1 ) = iwork( indibl+j-1 ) w( j ) = tmp1 iwork( indibl+j-1 ) = itmp1 call stdlib${ii}$_zswap( n, z( 1_${ik}$, i ), 1_${ik}$, z( 1_${ik}$, j ), 1_${ik}$ ) end if end do end if ! set work(1) to optimal workspace size. work( 1_${ik}$ ) = lwkopt rwork( 1_${ik}$ ) = lrwmin iwork( 1_${ik}$ ) = liwmin return end subroutine stdlib${ii}$_zheevr #:for ck,ct,ci in CMPLX_KINDS_TYPES #:if not ck in ["sp","dp"] module subroutine stdlib${ii}$_${ci}$heevr( jobz, range, uplo, n, a, lda, vl, vu, il, iu,abstol, m, w, z, ldz, & !! ZHEEVR: computes selected eigenvalues and, optionally, eigenvectors !! of a complex Hermitian matrix A. Eigenvalues and eigenvectors can !! be selected by specifying either a range of values or a range of !! indices for the desired eigenvalues. !! ZHEEVR first reduces the matrix A to tridiagonal form T with a call !! to ZHETRD. Then, whenever possible, ZHEEVR calls ZSTEMR to compute !! eigenspectrum using Relatively Robust Representations. ZSTEMR !! computes eigenvalues by the dqds algorithm, while orthogonal !! eigenvectors are computed from various "good" L D L^T representations !! (also known as Relatively Robust Representations). Gram-Schmidt !! orthogonalization is avoided as far as possible. More specifically, !! the various steps of the algorithm are as follows. !! For each unreduced block (submatrix) of T, !! (a) Compute T - sigma I = L D L^T, so that L and D !! define all the wanted eigenvalues to high relative accuracy. !! This means that small relative changes in the entries of D and L !! cause only small relative changes in the eigenvalues and !! eigenvectors. The standard (unfactored) representation of the !! tridiagonal matrix T does not have this property in general. !! (b) Compute the eigenvalues to suitable accuracy. !! If the eigenvectors are desired, the algorithm attains full !! accuracy of the computed eigenvalues only right before !! the corresponding vectors have to be computed, see steps c) and d). !! (c) For each cluster of close eigenvalues, select a new !! shift close to the cluster, find a new factorization, and refine !! the shifted eigenvalues to suitable accuracy. !! (d) For each eigenvalue with a large enough relative separation compute !! the corresponding eigenvector by forming a rank revealing twisted !! factorization. Go back to (c) for any clusters that remain. !! The desired accuracy of the output can be specified by the input !! parameter ABSTOL. !! For more details, see ZSTEMR's documentation and: !! - Inderjit S. Dhillon and Beresford N. Parlett: "Multiple representations !! to compute orthogonal eigenvectors of symmetric tridiagonal matrices," !! Linear Algebra and its Applications, 387(1), pp. 1-28, August 2004. !! - Inderjit Dhillon and Beresford Parlett: "Orthogonal Eigenvectors and !! Relative Gaps," SIAM Journal on Matrix Analysis and Applications, Vol. 25, !! 2004. Also LAPACK Working Note 154. !! - Inderjit Dhillon: "A new O(n^2) algorithm for the symmetric !! tridiagonal eigenvalue/eigenvector problem", !! Computer Science Division Technical Report No. UCB/CSD-97-971, !! UC Berkeley, May 1997. !! Note 1 : ZHEEVR calls ZSTEMR when the full spectrum is requested !! on machines which conform to the ieee-754 floating point standard. !! ZHEEVR calls DSTEBZ and ZSTEIN on non-ieee machines and !! when partial spectrum requests are made. !! Normal execution of ZSTEMR may create NaNs and infinities and !! hence may abort due to a floating point exception in environments !! which do not handle NaNs and infinities in the ieee standard default !! manner. isuppz, work, lwork,rwork, lrwork, iwork, liwork, 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) :: jobz, range, uplo integer(${ik}$), intent(in) :: il, iu, lda, ldz, liwork, lrwork, lwork, n integer(${ik}$), intent(out) :: info, m real(${ck}$), intent(in) :: abstol, vl, vu ! Array Arguments integer(${ik}$), intent(out) :: isuppz(*), iwork(*) real(${ck}$), intent(out) :: rwork(*), w(*) complex(${ck}$), intent(inout) :: a(lda,*) complex(${ck}$), intent(out) :: work(*), z(ldz,*) ! ===================================================================== ! Local Scalars logical(lk) :: alleig, indeig, lower, lquery, test, valeig, wantz, tryrac character :: order integer(${ik}$) :: i, ieeeok, iinfo, imax, indibl, indifl, indisp, indiwo, indrd, indrdd, & indre, indree, indrwk, indtau, indwk, indwkn, iscale, itmp1, j, jj, liwmin, llwork, & llrwork, llwrkn, lrwmin, lwkopt, lwmin, nb, nsplit real(${ck}$) :: abstll, anrm, bignum, eps, rmax, rmin, safmin, sigma, smlnum, tmp1, vll, & vuu ! Intrinsic Functions ! Executable Statements ! test the input parameters. ieeeok = stdlib${ii}$_ilaenv( 10_${ik}$, 'ZHEEVR', 'N', 1_${ik}$, 2_${ik}$, 3_${ik}$, 4_${ik}$ ) lower = stdlib_lsame( uplo, 'L' ) wantz = stdlib_lsame( jobz, 'V' ) alleig = stdlib_lsame( range, 'A' ) valeig = stdlib_lsame( range, 'V' ) indeig = stdlib_lsame( range, 'I' ) lquery = ( ( lwork==-1_${ik}$ ) .or. ( lrwork==-1_${ik}$ ) .or.( liwork==-1_${ik}$ ) ) lrwmin = max( 1_${ik}$, 24_${ik}$*n ) liwmin = max( 1_${ik}$, 10_${ik}$*n ) lwmin = max( 1_${ik}$, 2_${ik}$*n ) info = 0_${ik}$ if( .not.( wantz .or. stdlib_lsame( jobz, 'N' ) ) ) then info = -1_${ik}$ else if( .not.( alleig .or. valeig .or. indeig ) ) then info = -2_${ik}$ else if( .not.( lower .or. stdlib_lsame( uplo, 'U' ) ) ) then info = -3_${ik}$ else if( n<0_${ik}$ ) then info = -4_${ik}$ else if( lda<max( 1_${ik}$, n ) ) then info = -6_${ik}$ else if( valeig ) then if( n>0_${ik}$ .and. vu<=vl )info = -8_${ik}$ else if( indeig ) then if( il<1_${ik}$ .or. il>max( 1_${ik}$, n ) ) then info = -9_${ik}$ else if( iu<min( n, il ) .or. iu>n ) then info = -10_${ik}$ end if end if end if if( info==0_${ik}$ ) then if( ldz<1_${ik}$ .or. ( wantz .and. ldz<n ) ) then info = -15_${ik}$ end if end if if( info==0_${ik}$ ) then nb = stdlib${ii}$_ilaenv( 1_${ik}$, 'ZHETRD', uplo, n, -1_${ik}$, -1_${ik}$, -1_${ik}$ ) nb = max( nb, stdlib${ii}$_ilaenv( 1_${ik}$, 'ZUNMTR', uplo, n, -1_${ik}$, -1_${ik}$, -1_${ik}$ ) ) lwkopt = max( ( nb+1 )*n, lwmin ) work( 1_${ik}$ ) = lwkopt rwork( 1_${ik}$ ) = lrwmin iwork( 1_${ik}$ ) = liwmin if( lwork<lwmin .and. .not.lquery ) then info = -18_${ik}$ else if( lrwork<lrwmin .and. .not.lquery ) then info = -20_${ik}$ else if( liwork<liwmin .and. .not.lquery ) then info = -22_${ik}$ end if end if if( info/=0_${ik}$ ) then call stdlib${ii}$_xerbla( 'ZHEEVR', -info ) return else if( lquery ) then return end if ! quick return if possible m = 0_${ik}$ if( n==0_${ik}$ ) then work( 1_${ik}$ ) = 1_${ik}$ return end if if( n==1_${ik}$ ) then work( 1_${ik}$ ) = 2_${ik}$ if( alleig .or. indeig ) then m = 1_${ik}$ w( 1_${ik}$ ) = real( a( 1_${ik}$, 1_${ik}$ ),KIND=${ck}$) else if( vl<real( a( 1_${ik}$, 1_${ik}$ ),KIND=${ck}$) .and. vu>=real( a( 1_${ik}$, 1_${ik}$ ),KIND=${ck}$) )then m = 1_${ik}$ w( 1_${ik}$ ) = real( a( 1_${ik}$, 1_${ik}$ ),KIND=${ck}$) end if end if if( wantz ) then z( 1_${ik}$, 1_${ik}$ ) = one isuppz( 1_${ik}$ ) = 1_${ik}$ isuppz( 2_${ik}$ ) = 1_${ik}$ end if return end if ! get machine constants. safmin = stdlib${ii}$_${c2ri(ci)}$lamch( 'SAFE MINIMUM' ) eps = stdlib${ii}$_${c2ri(ci)}$lamch( 'PRECISION' ) smlnum = safmin / eps bignum = one / smlnum rmin = sqrt( smlnum ) rmax = min( sqrt( bignum ), one / sqrt( sqrt( safmin ) ) ) ! scale matrix to allowable range, if necessary. iscale = 0_${ik}$ abstll = abstol if (valeig) then vll = vl vuu = vu end if anrm = stdlib${ii}$_${ci}$lansy( 'M', uplo, n, a, lda, rwork ) if( anrm>zero .and. anrm<rmin ) then iscale = 1_${ik}$ sigma = rmin / anrm else if( anrm>rmax ) then iscale = 1_${ik}$ sigma = rmax / anrm end if if( iscale==1_${ik}$ ) then if( lower ) then do j = 1, n call stdlib${ii}$_${ci}$dscal( n-j+1, sigma, a( j, j ), 1_${ik}$ ) end do else do j = 1, n call stdlib${ii}$_${ci}$dscal( j, sigma, a( 1_${ik}$, j ), 1_${ik}$ ) end do end if if( abstol>0_${ik}$ )abstll = abstol*sigma if( valeig ) then vll = vl*sigma vuu = vu*sigma end if end if ! initialize indices into workspaces. note: the iwork indices are ! used only if stdlib${ii}$_${c2ri(ci)}$sterf or stdlib${ii}$_${ci}$stemr fail. ! work(indtau:indtau+n-1) stores the complex scalar factors of the ! elementary reflectors used in stdlib${ii}$_${ci}$hetrd. indtau = 1_${ik}$ ! indwk is the starting offset of the remaining complex workspace, ! and llwork is the remaining complex workspace size. indwk = indtau + n llwork = lwork - indwk + 1_${ik}$ ! rwork(indrd:indrd+n-1) stores the real tridiagonal's diagonal ! entries. indrd = 1_${ik}$ ! rwork(indre:indre+n-1) stores the off-diagonal entries of the ! tridiagonal matrix from stdlib${ii}$_${ci}$hetrd. indre = indrd + n ! rwork(indrdd:indrdd+n-1) is a copy of the diagonal entries over ! -written by stdlib${ii}$_${ci}$stemr (the stdlib${ii}$_${c2ri(ci)}$sterf path copies the diagonal to w). indrdd = indre + n ! rwork(indree:indree+n-1) is a copy of the off-diagonal entries over ! -written while computing the eigenvalues in stdlib${ii}$_${c2ri(ci)}$sterf and stdlib${ii}$_${ci}$stemr. indree = indrdd + n ! indrwk is the starting offset of the left-over real workspace, and ! llrwork is the remaining workspace size. indrwk = indree + n llrwork = lrwork - indrwk + 1_${ik}$ ! iwork(indibl:indibl+m-1) corresponds to iblock in stdlib${ii}$_${c2ri(ci)}$stebz and ! stores the block indices of each of the m<=n eigenvalues. indibl = 1_${ik}$ ! iwork(indisp:indisp+nsplit-1) corresponds to isplit in stdlib${ii}$_${c2ri(ci)}$stebz and ! stores the starting and finishing indices of each block. indisp = indibl + n ! iwork(indifl:indifl+n-1) stores the indices of eigenvectors ! that corresponding to eigenvectors that fail to converge in ! stdlib${ii}$_${c2ri(ci)}$stein. this information is discarded; if any fail, the driver ! returns info > 0. indifl = indisp + n ! indiwo is the offset of the remaining integer workspace. indiwo = indifl + n ! call stdlib${ii}$_${ci}$hetrd to reduce hermitian matrix to tridiagonal form. call stdlib${ii}$_${ci}$hetrd( uplo, n, a, lda, rwork( indrd ), rwork( indre ),work( indtau ), & work( indwk ), llwork, iinfo ) ! if all eigenvalues are desired ! then call stdlib${ii}$_${c2ri(ci)}$sterf or stdlib${ii}$_${ci}$stemr and stdlib${ii}$_${ci}$unmtr. test = .false. if( indeig ) then if( il==1_${ik}$ .and. iu==n ) then test = .true. end if end if if( ( alleig.or.test ) .and. ( ieeeok==1_${ik}$ ) ) then if( .not.wantz ) then call stdlib${ii}$_${c2ri(ci)}$copy( n, rwork( indrd ), 1_${ik}$, w, 1_${ik}$ ) call stdlib${ii}$_${c2ri(ci)}$copy( n-1, rwork( indre ), 1_${ik}$, rwork( indree ), 1_${ik}$ ) call stdlib${ii}$_${c2ri(ci)}$sterf( n, w, rwork( indree ), info ) else call stdlib${ii}$_${c2ri(ci)}$copy( n-1, rwork( indre ), 1_${ik}$, rwork( indree ), 1_${ik}$ ) call stdlib${ii}$_${c2ri(ci)}$copy( n, rwork( indrd ), 1_${ik}$, rwork( indrdd ), 1_${ik}$ ) if (abstol <= two*n*eps) then tryrac = .true. else tryrac = .false. end if call stdlib${ii}$_${ci}$stemr( jobz, 'A', n, rwork( indrdd ),rwork( indree ), vl, vu, il, & iu, m, w,z, ldz, n, isuppz, tryrac,rwork( indrwk ), llrwork,iwork, liwork, info ) ! apply unitary matrix used in reduction to tridiagonal ! form to eigenvectors returned by stdlib${ii}$_${ci}$stemr. if( wantz .and. info==0_${ik}$ ) then indwkn = indwk llwrkn = lwork - indwkn + 1_${ik}$ call stdlib${ii}$_${ci}$unmtr( 'L', uplo, 'N', n, m, a, lda,work( indtau ), z, ldz, work(& indwkn ),llwrkn, iinfo ) end if end if if( info==0_${ik}$ ) then m = n go to 30 end if info = 0_${ik}$ end if ! otherwise, call stdlib${ii}$_${c2ri(ci)}$stebz and, if eigenvectors are desired, stdlib${ii}$_${ci}$stein. ! also call stdlib${ii}$_${c2ri(ci)}$stebz and stdlib${ii}$_${ci}$stein if stdlib${ii}$_${ci}$stemr fails. if( wantz ) then order = 'B' else order = 'E' end if call stdlib${ii}$_${c2ri(ci)}$stebz( range, order, n, vll, vuu, il, iu, abstll,rwork( indrd ), rwork( & indre ), m, nsplit, w,iwork( indibl ), iwork( indisp ), rwork( indrwk ),iwork( indiwo )& , info ) if( wantz ) then call stdlib${ii}$_${ci}$stein( n, rwork( indrd ), rwork( indre ), m, w,iwork( indibl ), iwork( & indisp ), z, ldz,rwork( indrwk ), iwork( indiwo ), iwork( indifl ),info ) ! apply unitary matrix used in reduction to tridiagonal ! form to eigenvectors returned by stdlib${ii}$_${ci}$stein. indwkn = indwk llwrkn = lwork - indwkn + 1_${ik}$ call stdlib${ii}$_${ci}$unmtr( 'L', uplo, 'N', n, m, a, lda, work( indtau ), z,ldz, work( & indwkn ), llwrkn, iinfo ) end if ! if matrix was scaled, then rescale eigenvalues appropriately. 30 continue if( iscale==1_${ik}$ ) then if( info==0_${ik}$ ) then imax = m else imax = info - 1_${ik}$ end if call stdlib${ii}$_${c2ri(ci)}$scal( imax, one / sigma, w, 1_${ik}$ ) end if ! if eigenvalues are not in order, then sort them, along with ! eigenvectors. if( wantz ) then do j = 1, m - 1 i = 0_${ik}$ tmp1 = w( j ) do jj = j + 1, m if( w( jj )<tmp1 ) then i = jj tmp1 = w( jj ) end if end do if( i/=0_${ik}$ ) then itmp1 = iwork( indibl+i-1 ) w( i ) = w( j ) iwork( indibl+i-1 ) = iwork( indibl+j-1 ) w( j ) = tmp1 iwork( indibl+j-1 ) = itmp1 call stdlib${ii}$_${ci}$swap( n, z( 1_${ik}$, i ), 1_${ik}$, z( 1_${ik}$, j ), 1_${ik}$ ) end if end do end if ! set work(1) to optimal workspace size. work( 1_${ik}$ ) = lwkopt rwork( 1_${ik}$ ) = lrwmin iwork( 1_${ik}$ ) = liwmin return end subroutine stdlib${ii}$_${ci}$heevr #:endif #:endfor module subroutine stdlib${ii}$_cheevx( jobz, range, uplo, n, a, lda, vl, vu, il, iu,abstol, m, w, z, ldz, & !! CHEEVX computes selected eigenvalues and, optionally, eigenvectors !! of a complex Hermitian matrix A. Eigenvalues and eigenvectors can !! be selected by specifying either a range of values or a range of !! indices for the desired eigenvalues. work, lwork, rwork,iwork, ifail, 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) :: jobz, range, uplo integer(${ik}$), intent(in) :: il, iu, lda, ldz, lwork, n integer(${ik}$), intent(out) :: info, m real(sp), intent(in) :: abstol, vl, vu ! Array Arguments integer(${ik}$), intent(out) :: ifail(*), iwork(*) real(sp), intent(out) :: rwork(*), w(*) complex(sp), intent(inout) :: a(lda,*) complex(sp), intent(out) :: work(*), z(ldz,*) ! ===================================================================== ! Local Scalars logical(lk) :: alleig, indeig, lower, lquery, test, valeig, wantz character :: order integer(${ik}$) :: i, iinfo, imax, indd, inde, indee, indibl, indisp, indiwk, indrwk, & indtau, indwrk, iscale, itmp1, j, jj, llwork, lwkmin, lwkopt, nb, nsplit real(sp) :: abstll, anrm, bignum, eps, rmax, rmin, safmin, sigma, smlnum, tmp1, vll, & vuu ! Intrinsic Functions ! Executable Statements ! test the input parameters. lower = stdlib_lsame( uplo, 'L' ) wantz = stdlib_lsame( jobz, 'V' ) alleig = stdlib_lsame( range, 'A' ) valeig = stdlib_lsame( range, 'V' ) indeig = stdlib_lsame( range, 'I' ) lquery = ( lwork==-1_${ik}$ ) info = 0_${ik}$ if( .not.( wantz .or. stdlib_lsame( jobz, 'N' ) ) ) then info = -1_${ik}$ else if( .not.( alleig .or. valeig .or. indeig ) ) then info = -2_${ik}$ else if( .not.( lower .or. stdlib_lsame( uplo, 'U' ) ) ) then info = -3_${ik}$ else if( n<0_${ik}$ ) then info = -4_${ik}$ else if( lda<max( 1_${ik}$, n ) ) then info = -6_${ik}$ else if( valeig ) then if( n>0_${ik}$ .and. vu<=vl )info = -8_${ik}$ else if( indeig ) then if( il<1_${ik}$ .or. il>max( 1_${ik}$, n ) ) then info = -9_${ik}$ else if( iu<min( n, il ) .or. iu>n ) then info = -10_${ik}$ end if end if end if if( info==0_${ik}$ ) then if( ldz<1_${ik}$ .or. ( wantz .and. ldz<n ) ) then info = -15_${ik}$ end if end if if( info==0_${ik}$ ) then if( n<=1_${ik}$ ) then lwkmin = 1_${ik}$ work( 1_${ik}$ ) = lwkmin else lwkmin = 2_${ik}$*n nb = stdlib${ii}$_ilaenv( 1_${ik}$, 'CHETRD', uplo, n, -1_${ik}$, -1_${ik}$, -1_${ik}$ ) nb = max( nb, stdlib${ii}$_ilaenv( 1_${ik}$, 'CUNMTR', uplo, n, -1_${ik}$, -1_${ik}$, -1_${ik}$ ) ) lwkopt = max( 1_${ik}$, ( nb + 1_${ik}$ )*n ) work( 1_${ik}$ ) = lwkopt end if if( lwork<lwkmin .and. .not.lquery )info = -17_${ik}$ end if if( info/=0_${ik}$ ) then call stdlib${ii}$_xerbla( 'CHEEVX', -info ) return else if( lquery ) then return end if ! quick return if possible m = 0_${ik}$ if( n==0_${ik}$ ) then return end if if( n==1_${ik}$ ) then if( alleig .or. indeig ) then m = 1_${ik}$ w( 1_${ik}$ ) = real( a( 1_${ik}$, 1_${ik}$ ),KIND=sp) else if( valeig ) then if( vl<real( a( 1_${ik}$, 1_${ik}$ ),KIND=sp) .and. vu>=real( a( 1_${ik}$, 1_${ik}$ ),KIND=sp) )then m = 1_${ik}$ w( 1_${ik}$ ) = real( a( 1_${ik}$, 1_${ik}$ ),KIND=sp) end if end if if( wantz )z( 1_${ik}$, 1_${ik}$ ) = cone return end if ! get machine constants. safmin = stdlib${ii}$_slamch( 'SAFE MINIMUM' ) eps = stdlib${ii}$_slamch( 'PRECISION' ) smlnum = safmin / eps bignum = one / smlnum rmin = sqrt( smlnum ) rmax = min( sqrt( bignum ), one / sqrt( sqrt( safmin ) ) ) ! scale matrix to allowable range, if necessary. iscale = 0_${ik}$ abstll = abstol if( valeig ) then vll = vl vuu = vu end if anrm = stdlib${ii}$_clanhe( 'M', uplo, n, a, lda, rwork ) if( anrm>zero .and. anrm<rmin ) then iscale = 1_${ik}$ sigma = rmin / anrm else if( anrm>rmax ) then iscale = 1_${ik}$ sigma = rmax / anrm end if if( iscale==1_${ik}$ ) then if( lower ) then do j = 1, n call stdlib${ii}$_csscal( n-j+1, sigma, a( j, j ), 1_${ik}$ ) end do else do j = 1, n call stdlib${ii}$_csscal( j, sigma, a( 1_${ik}$, j ), 1_${ik}$ ) end do end if if( abstol>0_${ik}$ )abstll = abstol*sigma if( valeig ) then vll = vl*sigma vuu = vu*sigma end if end if ! call stdlib${ii}$_chetrd to reduce hermitian matrix to tridiagonal form. indd = 1_${ik}$ inde = indd + n indrwk = inde + n indtau = 1_${ik}$ indwrk = indtau + n llwork = lwork - indwrk + 1_${ik}$ call stdlib${ii}$_chetrd( uplo, n, a, lda, rwork( indd ), rwork( inde ),work( indtau ), work(& indwrk ), llwork, iinfo ) ! if all eigenvalues are desired and abstol is less than or equal to ! zero, then call stdlib${ii}$_ssterf or stdlib${ii}$_cungtr and stdlib${ii}$_csteqr. if this fails for ! some eigenvalue, then try stdlib${ii}$_sstebz. test = .false. if( indeig ) then if( il==1_${ik}$ .and. iu==n ) then test = .true. end if end if if( ( alleig .or. test ) .and. ( abstol<=zero ) ) then call stdlib${ii}$_scopy( n, rwork( indd ), 1_${ik}$, w, 1_${ik}$ ) indee = indrwk + 2_${ik}$*n if( .not.wantz ) then call stdlib${ii}$_scopy( n-1, rwork( inde ), 1_${ik}$, rwork( indee ), 1_${ik}$ ) call stdlib${ii}$_ssterf( n, w, rwork( indee ), info ) else call stdlib${ii}$_clacpy( 'A', n, n, a, lda, z, ldz ) call stdlib${ii}$_cungtr( uplo, n, z, ldz, work( indtau ),work( indwrk ), llwork, & iinfo ) call stdlib${ii}$_scopy( n-1, rwork( inde ), 1_${ik}$, rwork( indee ), 1_${ik}$ ) call stdlib${ii}$_csteqr( jobz, n, w, rwork( indee ), z, ldz,rwork( indrwk ), info ) if( info==0_${ik}$ ) then do i = 1, n ifail( i ) = 0_${ik}$ end do end if end if if( info==0_${ik}$ ) then m = n go to 40 end if info = 0_${ik}$ end if ! otherwise, call stdlib${ii}$_sstebz and, if eigenvectors are desired, stdlib${ii}$_cstein. if( wantz ) then order = 'B' else order = 'E' end if indibl = 1_${ik}$ indisp = indibl + n indiwk = indisp + n call stdlib${ii}$_sstebz( range, order, n, vll, vuu, il, iu, abstll,rwork( indd ), rwork( & inde ), m, nsplit, w,iwork( indibl ), iwork( indisp ), rwork( indrwk ),iwork( indiwk ),& info ) if( wantz ) then call stdlib${ii}$_cstein( n, rwork( indd ), rwork( inde ), m, w,iwork( indibl ), iwork( & indisp ), z, ldz,rwork( indrwk ), iwork( indiwk ), ifail, info ) ! apply unitary matrix used in reduction to tridiagonal ! form to eigenvectors returned by stdlib${ii}$_cstein. call stdlib${ii}$_cunmtr( 'L', uplo, 'N', n, m, a, lda, work( indtau ), z,ldz, work( & indwrk ), llwork, iinfo ) end if ! if matrix was scaled, then rescale eigenvalues appropriately. 40 continue if( iscale==1_${ik}$ ) then if( info==0_${ik}$ ) then imax = m else imax = info - 1_${ik}$ end if call stdlib${ii}$_sscal( imax, one / sigma, w, 1_${ik}$ ) end if ! if eigenvalues are not in order, then sort them, along with ! eigenvectors. if( wantz ) then do j = 1, m - 1 i = 0_${ik}$ tmp1 = w( j ) do jj = j + 1, m if( w( jj )<tmp1 ) then i = jj tmp1 = w( jj ) end if end do if( i/=0_${ik}$ ) then itmp1 = iwork( indibl+i-1 ) w( i ) = w( j ) iwork( indibl+i-1 ) = iwork( indibl+j-1 ) w( j ) = tmp1 iwork( indibl+j-1 ) = itmp1 call stdlib${ii}$_cswap( n, z( 1_${ik}$, i ), 1_${ik}$, z( 1_${ik}$, j ), 1_${ik}$ ) if( info/=0_${ik}$ ) then itmp1 = ifail( i ) ifail( i ) = ifail( j ) ifail( j ) = itmp1 end if end if end do end if ! set work(1) to optimal complex workspace size. work( 1_${ik}$ ) = lwkopt return end subroutine stdlib${ii}$_cheevx module subroutine stdlib${ii}$_zheevx( jobz, range, uplo, n, a, lda, vl, vu, il, iu,abstol, m, w, z, ldz, & !! ZHEEVX computes selected eigenvalues and, optionally, eigenvectors !! of a complex Hermitian matrix A. Eigenvalues and eigenvectors can !! be selected by specifying either a range of values or a range of !! indices for the desired eigenvalues. work, lwork, rwork,iwork, ifail, 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) :: jobz, range, uplo integer(${ik}$), intent(in) :: il, iu, lda, ldz, lwork, n integer(${ik}$), intent(out) :: info, m real(dp), intent(in) :: abstol, vl, vu ! Array Arguments integer(${ik}$), intent(out) :: ifail(*), iwork(*) real(dp), intent(out) :: rwork(*), w(*) complex(dp), intent(inout) :: a(lda,*) complex(dp), intent(out) :: work(*), z(ldz,*) ! ===================================================================== ! Local Scalars logical(lk) :: alleig, indeig, lower, lquery, test, valeig, wantz character :: order integer(${ik}$) :: i, iinfo, imax, indd, inde, indee, indibl, indisp, indiwk, indrwk, & indtau, indwrk, iscale, itmp1, j, jj, llwork, lwkmin, lwkopt, nb, nsplit real(dp) :: abstll, anrm, bignum, eps, rmax, rmin, safmin, sigma, smlnum, tmp1, vll, & vuu ! Intrinsic Functions ! Executable Statements ! test the input parameters. lower = stdlib_lsame( uplo, 'L' ) wantz = stdlib_lsame( jobz, 'V' ) alleig = stdlib_lsame( range, 'A' ) valeig = stdlib_lsame( range, 'V' ) indeig = stdlib_lsame( range, 'I' ) lquery = ( lwork==-1_${ik}$ ) info = 0_${ik}$ if( .not.( wantz .or. stdlib_lsame( jobz, 'N' ) ) ) then info = -1_${ik}$ else if( .not.( alleig .or. valeig .or. indeig ) ) then info = -2_${ik}$ else if( .not.( lower .or. stdlib_lsame( uplo, 'U' ) ) ) then info = -3_${ik}$ else if( n<0_${ik}$ ) then info = -4_${ik}$ else if( lda<max( 1_${ik}$, n ) ) then info = -6_${ik}$ else if( valeig ) then if( n>0_${ik}$ .and. vu<=vl )info = -8_${ik}$ else if( indeig ) then if( il<1_${ik}$ .or. il>max( 1_${ik}$, n ) ) then info = -9_${ik}$ else if( iu<min( n, il ) .or. iu>n ) then info = -10_${ik}$ end if end if end if if( info==0_${ik}$ ) then if( ldz<1_${ik}$ .or. ( wantz .and. ldz<n ) ) then info = -15_${ik}$ end if end if if( info==0_${ik}$ ) then if( n<=1_${ik}$ ) then lwkmin = 1_${ik}$ work( 1_${ik}$ ) = lwkmin else lwkmin = 2_${ik}$*n nb = stdlib${ii}$_ilaenv( 1_${ik}$, 'ZHETRD', uplo, n, -1_${ik}$, -1_${ik}$, -1_${ik}$ ) nb = max( nb, stdlib${ii}$_ilaenv( 1_${ik}$, 'ZUNMTR', uplo, n, -1_${ik}$, -1_${ik}$, -1_${ik}$ ) ) lwkopt = max( 1_${ik}$, ( nb + 1_${ik}$ )*n ) work( 1_${ik}$ ) = lwkopt end if if( lwork<lwkmin .and. .not.lquery )info = -17_${ik}$ end if if( info/=0_${ik}$ ) then call stdlib${ii}$_xerbla( 'ZHEEVX', -info ) return else if( lquery ) then return end if ! quick return if possible m = 0_${ik}$ if( n==0_${ik}$ ) then return end if if( n==1_${ik}$ ) then if( alleig .or. indeig ) then m = 1_${ik}$ w( 1_${ik}$ ) = real( a( 1_${ik}$, 1_${ik}$ ),KIND=dp) else if( valeig ) then if( vl<real( a( 1_${ik}$, 1_${ik}$ ),KIND=dp) .and. vu>=real( a( 1_${ik}$, 1_${ik}$ ),KIND=dp) )then m = 1_${ik}$ w( 1_${ik}$ ) = real( a( 1_${ik}$, 1_${ik}$ ),KIND=dp) end if end if if( wantz )z( 1_${ik}$, 1_${ik}$ ) = cone return end if ! get machine constants. safmin = stdlib${ii}$_dlamch( 'SAFE MINIMUM' ) eps = stdlib${ii}$_dlamch( 'PRECISION' ) smlnum = safmin / eps bignum = one / smlnum rmin = sqrt( smlnum ) rmax = min( sqrt( bignum ), one / sqrt( sqrt( safmin ) ) ) ! scale matrix to allowable range, if necessary. iscale = 0_${ik}$ abstll = abstol if( valeig ) then vll = vl vuu = vu end if anrm = stdlib${ii}$_zlanhe( 'M', uplo, n, a, lda, rwork ) if( anrm>zero .and. anrm<rmin ) then iscale = 1_${ik}$ sigma = rmin / anrm else if( anrm>rmax ) then iscale = 1_${ik}$ sigma = rmax / anrm end if if( iscale==1_${ik}$ ) then if( lower ) then do j = 1, n call stdlib${ii}$_zdscal( n-j+1, sigma, a( j, j ), 1_${ik}$ ) end do else do j = 1, n call stdlib${ii}$_zdscal( j, sigma, a( 1_${ik}$, j ), 1_${ik}$ ) end do end if if( abstol>0_${ik}$ )abstll = abstol*sigma if( valeig ) then vll = vl*sigma vuu = vu*sigma end if end if ! call stdlib${ii}$_zhetrd to reduce hermitian matrix to tridiagonal form. indd = 1_${ik}$ inde = indd + n indrwk = inde + n indtau = 1_${ik}$ indwrk = indtau + n llwork = lwork - indwrk + 1_${ik}$ call stdlib${ii}$_zhetrd( uplo, n, a, lda, rwork( indd ), rwork( inde ),work( indtau ), work(& indwrk ), llwork, iinfo ) ! if all eigenvalues are desired and abstol is less than or equal to ! zero, then call stdlib${ii}$_dsterf or stdlib${ii}$_zungtr and stdlib${ii}$_zsteqr. if this fails for ! some eigenvalue, then try stdlib${ii}$_dstebz. test = .false. if( indeig ) then if( il==1_${ik}$ .and. iu==n ) then test = .true. end if end if if( ( alleig .or. test ) .and. ( abstol<=zero ) ) then call stdlib${ii}$_dcopy( n, rwork( indd ), 1_${ik}$, w, 1_${ik}$ ) indee = indrwk + 2_${ik}$*n if( .not.wantz ) then call stdlib${ii}$_dcopy( n-1, rwork( inde ), 1_${ik}$, rwork( indee ), 1_${ik}$ ) call stdlib${ii}$_dsterf( n, w, rwork( indee ), info ) else call stdlib${ii}$_zlacpy( 'A', n, n, a, lda, z, ldz ) call stdlib${ii}$_zungtr( uplo, n, z, ldz, work( indtau ),work( indwrk ), llwork, & iinfo ) call stdlib${ii}$_dcopy( n-1, rwork( inde ), 1_${ik}$, rwork( indee ), 1_${ik}$ ) call stdlib${ii}$_zsteqr( jobz, n, w, rwork( indee ), z, ldz,rwork( indrwk ), info ) if( info==0_${ik}$ ) then do i = 1, n ifail( i ) = 0_${ik}$ end do end if end if if( info==0_${ik}$ ) then m = n go to 40 end if info = 0_${ik}$ end if ! otherwise, call stdlib${ii}$_dstebz and, if eigenvectors are desired, stdlib${ii}$_zstein. if( wantz ) then order = 'B' else order = 'E' end if indibl = 1_${ik}$ indisp = indibl + n indiwk = indisp + n call stdlib${ii}$_dstebz( range, order, n, vll, vuu, il, iu, abstll,rwork( indd ), rwork( & inde ), m, nsplit, w,iwork( indibl ), iwork( indisp ), rwork( indrwk ),iwork( indiwk ),& info ) if( wantz ) then call stdlib${ii}$_zstein( n, rwork( indd ), rwork( inde ), m, w,iwork( indibl ), iwork( & indisp ), z, ldz,rwork( indrwk ), iwork( indiwk ), ifail, info ) ! apply unitary matrix used in reduction to tridiagonal ! form to eigenvectors returned by stdlib${ii}$_zstein. call stdlib${ii}$_zunmtr( 'L', uplo, 'N', n, m, a, lda, work( indtau ), z,ldz, work( & indwrk ), llwork, iinfo ) end if ! if matrix was scaled, then rescale eigenvalues appropriately. 40 continue if( iscale==1_${ik}$ ) then if( info==0_${ik}$ ) then imax = m else imax = info - 1_${ik}$ end if call stdlib${ii}$_dscal( imax, one / sigma, w, 1_${ik}$ ) end if ! if eigenvalues are not in order, then sort them, along with ! eigenvectors. if( wantz ) then do j = 1, m - 1 i = 0_${ik}$ tmp1 = w( j ) do jj = j + 1, m if( w( jj )<tmp1 ) then i = jj tmp1 = w( jj ) end if end do if( i/=0_${ik}$ ) then itmp1 = iwork( indibl+i-1 ) w( i ) = w( j ) iwork( indibl+i-1 ) = iwork( indibl+j-1 ) w( j ) = tmp1 iwork( indibl+j-1 ) = itmp1 call stdlib${ii}$_zswap( n, z( 1_${ik}$, i ), 1_${ik}$, z( 1_${ik}$, j ), 1_${ik}$ ) if( info/=0_${ik}$ ) then itmp1 = ifail( i ) ifail( i ) = ifail( j ) ifail( j ) = itmp1 end if end if end do end if ! set work(1) to optimal complex workspace size. work( 1_${ik}$ ) = lwkopt return end subroutine stdlib${ii}$_zheevx #:for ck,ct,ci in CMPLX_KINDS_TYPES #:if not ck in ["sp","dp"] module subroutine stdlib${ii}$_${ci}$heevx( jobz, range, uplo, n, a, lda, vl, vu, il, iu,abstol, m, w, z, ldz, & !! ZHEEVX: computes selected eigenvalues and, optionally, eigenvectors !! of a complex Hermitian matrix A. Eigenvalues and eigenvectors can !! be selected by specifying either a range of values or a range of !! indices for the desired eigenvalues. work, lwork, rwork,iwork, ifail, 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) :: jobz, range, uplo integer(${ik}$), intent(in) :: il, iu, lda, ldz, lwork, n integer(${ik}$), intent(out) :: info, m real(${ck}$), intent(in) :: abstol, vl, vu ! Array Arguments integer(${ik}$), intent(out) :: ifail(*), iwork(*) real(${ck}$), intent(out) :: rwork(*), w(*) complex(${ck}$), intent(inout) :: a(lda,*) complex(${ck}$), intent(out) :: work(*), z(ldz,*) ! ===================================================================== ! Local Scalars logical(lk) :: alleig, indeig, lower, lquery, test, valeig, wantz character :: order integer(${ik}$) :: i, iinfo, imax, indd, inde, indee, indibl, indisp, indiwk, indrwk, & indtau, indwrk, iscale, itmp1, j, jj, llwork, lwkmin, lwkopt, nb, nsplit real(${ck}$) :: abstll, anrm, bignum, eps, rmax, rmin, safmin, sigma, smlnum, tmp1, vll, & vuu ! Intrinsic Functions ! Executable Statements ! test the input parameters. lower = stdlib_lsame( uplo, 'L' ) wantz = stdlib_lsame( jobz, 'V' ) alleig = stdlib_lsame( range, 'A' ) valeig = stdlib_lsame( range, 'V' ) indeig = stdlib_lsame( range, 'I' ) lquery = ( lwork==-1_${ik}$ ) info = 0_${ik}$ if( .not.( wantz .or. stdlib_lsame( jobz, 'N' ) ) ) then info = -1_${ik}$ else if( .not.( alleig .or. valeig .or. indeig ) ) then info = -2_${ik}$ else if( .not.( lower .or. stdlib_lsame( uplo, 'U' ) ) ) then info = -3_${ik}$ else if( n<0_${ik}$ ) then info = -4_${ik}$ else if( lda<max( 1_${ik}$, n ) ) then info = -6_${ik}$ else if( valeig ) then if( n>0_${ik}$ .and. vu<=vl )info = -8_${ik}$ else if( indeig ) then if( il<1_${ik}$ .or. il>max( 1_${ik}$, n ) ) then info = -9_${ik}$ else if( iu<min( n, il ) .or. iu>n ) then info = -10_${ik}$ end if end if end if if( info==0_${ik}$ ) then if( ldz<1_${ik}$ .or. ( wantz .and. ldz<n ) ) then info = -15_${ik}$ end if end if if( info==0_${ik}$ ) then if( n<=1_${ik}$ ) then lwkmin = 1_${ik}$ work( 1_${ik}$ ) = lwkmin else lwkmin = 2_${ik}$*n nb = stdlib${ii}$_ilaenv( 1_${ik}$, 'ZHETRD', uplo, n, -1_${ik}$, -1_${ik}$, -1_${ik}$ ) nb = max( nb, stdlib${ii}$_ilaenv( 1_${ik}$, 'ZUNMTR', uplo, n, -1_${ik}$, -1_${ik}$, -1_${ik}$ ) ) lwkopt = max( 1_${ik}$, ( nb + 1_${ik}$ )*n ) work( 1_${ik}$ ) = lwkopt end if if( lwork<lwkmin .and. .not.lquery )info = -17_${ik}$ end if if( info/=0_${ik}$ ) then call stdlib${ii}$_xerbla( 'ZHEEVX', -info ) return else if( lquery ) then return end if ! quick return if possible m = 0_${ik}$ if( n==0_${ik}$ ) then return end if if( n==1_${ik}$ ) then if( alleig .or. indeig ) then m = 1_${ik}$ w( 1_${ik}$ ) = real( a( 1_${ik}$, 1_${ik}$ ),KIND=${ck}$) else if( valeig ) then if( vl<real( a( 1_${ik}$, 1_${ik}$ ),KIND=${ck}$) .and. vu>=real( a( 1_${ik}$, 1_${ik}$ ),KIND=${ck}$) )then m = 1_${ik}$ w( 1_${ik}$ ) = real( a( 1_${ik}$, 1_${ik}$ ),KIND=${ck}$) end if end if if( wantz )z( 1_${ik}$, 1_${ik}$ ) = cone return end if ! get machine constants. safmin = stdlib${ii}$_${c2ri(ci)}$lamch( 'SAFE MINIMUM' ) eps = stdlib${ii}$_${c2ri(ci)}$lamch( 'PRECISION' ) smlnum = safmin / eps bignum = one / smlnum rmin = sqrt( smlnum ) rmax = min( sqrt( bignum ), one / sqrt( sqrt( safmin ) ) ) ! scale matrix to allowable range, if necessary. iscale = 0_${ik}$ abstll = abstol if( valeig ) then vll = vl vuu = vu end if anrm = stdlib${ii}$_${ci}$lanhe( 'M', uplo, n, a, lda, rwork ) if( anrm>zero .and. anrm<rmin ) then iscale = 1_${ik}$ sigma = rmin / anrm else if( anrm>rmax ) then iscale = 1_${ik}$ sigma = rmax / anrm end if if( iscale==1_${ik}$ ) then if( lower ) then do j = 1, n call stdlib${ii}$_${ci}$dscal( n-j+1, sigma, a( j, j ), 1_${ik}$ ) end do else do j = 1, n call stdlib${ii}$_${ci}$dscal( j, sigma, a( 1_${ik}$, j ), 1_${ik}$ ) end do end if if( abstol>0_${ik}$ )abstll = abstol*sigma if( valeig ) then vll = vl*sigma vuu = vu*sigma end if end if ! call stdlib${ii}$_${ci}$hetrd to reduce hermitian matrix to tridiagonal form. indd = 1_${ik}$ inde = indd + n indrwk = inde + n indtau = 1_${ik}$ indwrk = indtau + n llwork = lwork - indwrk + 1_${ik}$ call stdlib${ii}$_${ci}$hetrd( uplo, n, a, lda, rwork( indd ), rwork( inde ),work( indtau ), work(& indwrk ), llwork, iinfo ) ! if all eigenvalues are desired and abstol is less than or equal to ! zero, then call stdlib${ii}$_${c2ri(ci)}$sterf or stdlib${ii}$_${ci}$ungtr and stdlib${ii}$_${ci}$steqr. if this fails for ! some eigenvalue, then try stdlib${ii}$_${c2ri(ci)}$stebz. test = .false. if( indeig ) then if( il==1_${ik}$ .and. iu==n ) then test = .true. end if end if if( ( alleig .or. test ) .and. ( abstol<=zero ) ) then call stdlib${ii}$_${c2ri(ci)}$copy( n, rwork( indd ), 1_${ik}$, w, 1_${ik}$ ) indee = indrwk + 2_${ik}$*n if( .not.wantz ) then call stdlib${ii}$_${c2ri(ci)}$copy( n-1, rwork( inde ), 1_${ik}$, rwork( indee ), 1_${ik}$ ) call stdlib${ii}$_${c2ri(ci)}$sterf( n, w, rwork( indee ), info ) else call stdlib${ii}$_${ci}$lacpy( 'A', n, n, a, lda, z, ldz ) call stdlib${ii}$_${ci}$ungtr( uplo, n, z, ldz, work( indtau ),work( indwrk ), llwork, & iinfo ) call stdlib${ii}$_${c2ri(ci)}$copy( n-1, rwork( inde ), 1_${ik}$, rwork( indee ), 1_${ik}$ ) call stdlib${ii}$_${ci}$steqr( jobz, n, w, rwork( indee ), z, ldz,rwork( indrwk ), info ) if( info==0_${ik}$ ) then do i = 1, n ifail( i ) = 0_${ik}$ end do end if end if if( info==0_${ik}$ ) then m = n go to 40 end if info = 0_${ik}$ end if ! otherwise, call stdlib${ii}$_${c2ri(ci)}$stebz and, if eigenvectors are desired, stdlib${ii}$_${ci}$stein. if( wantz ) then order = 'B' else order = 'E' end if indibl = 1_${ik}$ indisp = indibl + n indiwk = indisp + n call stdlib${ii}$_${c2ri(ci)}$stebz( range, order, n, vll, vuu, il, iu, abstll,rwork( indd ), rwork( & inde ), m, nsplit, w,iwork( indibl ), iwork( indisp ), rwork( indrwk ),iwork( indiwk ),& info ) if( wantz ) then call stdlib${ii}$_${ci}$stein( n, rwork( indd ), rwork( inde ), m, w,iwork( indibl ), iwork( & indisp ), z, ldz,rwork( indrwk ), iwork( indiwk ), ifail, info ) ! apply unitary matrix used in reduction to tridiagonal ! form to eigenvectors returned by stdlib${ii}$_${ci}$stein. call stdlib${ii}$_${ci}$unmtr( 'L', uplo, 'N', n, m, a, lda, work( indtau ), z,ldz, work( & indwrk ), llwork, iinfo ) end if ! if matrix was scaled, then rescale eigenvalues appropriately. 40 continue if( iscale==1_${ik}$ ) then if( info==0_${ik}$ ) then imax = m else imax = info - 1_${ik}$ end if call stdlib${ii}$_${c2ri(ci)}$scal( imax, one / sigma, w, 1_${ik}$ ) end if ! if eigenvalues are not in order, then sort them, along with ! eigenvectors. if( wantz ) then do j = 1, m - 1 i = 0_${ik}$ tmp1 = w( j ) do jj = j + 1, m if( w( jj )<tmp1 ) then i = jj tmp1 = w( jj ) end if end do if( i/=0_${ik}$ ) then itmp1 = iwork( indibl+i-1 ) w( i ) = w( j ) iwork( indibl+i-1 ) = iwork( indibl+j-1 ) w( j ) = tmp1 iwork( indibl+j-1 ) = itmp1 call stdlib${ii}$_${ci}$swap( n, z( 1_${ik}$, i ), 1_${ik}$, z( 1_${ik}$, j ), 1_${ik}$ ) if( info/=0_${ik}$ ) then itmp1 = ifail( i ) ifail( i ) = ifail( j ) ifail( j ) = itmp1 end if end if end do end if ! set work(1) to optimal complex workspace size. work( 1_${ik}$ ) = lwkopt return end subroutine stdlib${ii}$_${ci}$heevx #:endif #:endfor module subroutine stdlib${ii}$_chpev( jobz, uplo, n, ap, w, z, ldz, work, rwork,info ) !! CHPEV computes all the eigenvalues and, optionally, eigenvectors of a !! complex Hermitian matrix in packed storage. ! -- 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) :: jobz, uplo integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: ldz, n ! Array Arguments real(sp), intent(out) :: rwork(*), w(*) complex(sp), intent(inout) :: ap(*) complex(sp), intent(out) :: work(*), z(ldz,*) ! ===================================================================== ! Local Scalars logical(lk) :: wantz integer(${ik}$) :: iinfo, imax, inde, indrwk, indtau, indwrk, iscale real(sp) :: anrm, bignum, eps, rmax, rmin, safmin, sigma, smlnum ! Intrinsic Functions ! Executable Statements ! test the input parameters. wantz = stdlib_lsame( jobz, 'V' ) info = 0_${ik}$ if( .not.( wantz .or. stdlib_lsame( jobz, 'N' ) ) ) then info = -1_${ik}$ else if( .not.( stdlib_lsame( uplo, 'L' ) .or. stdlib_lsame( uplo, 'U' ) ) )& then info = -2_${ik}$ else if( n<0_${ik}$ ) then info = -3_${ik}$ else if( ldz<1_${ik}$ .or. ( wantz .and. ldz<n ) ) then info = -7_${ik}$ end if if( info/=0_${ik}$ ) then call stdlib${ii}$_xerbla( 'CHPEV ', -info ) return end if ! quick return if possible if( n==0 )return if( n==1_${ik}$ ) then w( 1_${ik}$ ) = real( ap( 1_${ik}$ ),KIND=sp) rwork( 1_${ik}$ ) = 1_${ik}$ if( wantz )z( 1_${ik}$, 1_${ik}$ ) = one return end if ! get machine constants. safmin = stdlib${ii}$_slamch( 'SAFE MINIMUM' ) eps = stdlib${ii}$_slamch( 'PRECISION' ) smlnum = safmin / eps bignum = one / smlnum rmin = sqrt( smlnum ) rmax = sqrt( bignum ) ! scale matrix to allowable range, if necessary. anrm = stdlib${ii}$_clanhp( 'M', uplo, n, ap, rwork ) iscale = 0_${ik}$ if( anrm>zero .and. anrm<rmin ) then iscale = 1_${ik}$ sigma = rmin / anrm else if( anrm>rmax ) then iscale = 1_${ik}$ sigma = rmax / anrm end if if( iscale==1_${ik}$ ) then call stdlib${ii}$_csscal( ( n*( n+1 ) ) / 2_${ik}$, sigma, ap, 1_${ik}$ ) end if ! call stdlib${ii}$_chptrd to reduce hermitian packed matrix to tridiagonal form. inde = 1_${ik}$ indtau = 1_${ik}$ call stdlib${ii}$_chptrd( uplo, n, ap, w, rwork( inde ), work( indtau ),iinfo ) ! for eigenvalues only, call stdlib${ii}$_ssterf. for eigenvectors, first call ! stdlib${ii}$_cupgtr to generate the orthogonal matrix, then call stdlib${ii}$_csteqr. if( .not.wantz ) then call stdlib${ii}$_ssterf( n, w, rwork( inde ), info ) else indwrk = indtau + n call stdlib${ii}$_cupgtr( uplo, n, ap, work( indtau ), z, ldz,work( indwrk ), iinfo ) indrwk = inde + n call stdlib${ii}$_csteqr( jobz, n, w, rwork( inde ), z, ldz,rwork( indrwk ), info ) end if ! if matrix was scaled, then rescale eigenvalues appropriately. if( iscale==1_${ik}$ ) then if( info==0_${ik}$ ) then imax = n else imax = info - 1_${ik}$ end if call stdlib${ii}$_sscal( imax, one / sigma, w, 1_${ik}$ ) end if return end subroutine stdlib${ii}$_chpev module subroutine stdlib${ii}$_zhpev( jobz, uplo, n, ap, w, z, ldz, work, rwork,info ) !! ZHPEV computes all the eigenvalues and, optionally, eigenvectors of a !! complex Hermitian matrix in packed storage. ! -- 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) :: jobz, uplo integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: ldz, n ! Array Arguments real(dp), intent(out) :: rwork(*), w(*) complex(dp), intent(inout) :: ap(*) complex(dp), intent(out) :: work(*), z(ldz,*) ! ===================================================================== ! Local Scalars logical(lk) :: wantz integer(${ik}$) :: iinfo, imax, inde, indrwk, indtau, indwrk, iscale real(dp) :: anrm, bignum, eps, rmax, rmin, safmin, sigma, smlnum ! Intrinsic Functions ! Executable Statements ! test the input parameters. wantz = stdlib_lsame( jobz, 'V' ) info = 0_${ik}$ if( .not.( wantz .or. stdlib_lsame( jobz, 'N' ) ) ) then info = -1_${ik}$ else if( .not.( stdlib_lsame( uplo, 'L' ) .or. stdlib_lsame( uplo, 'U' ) ) )& then info = -2_${ik}$ else if( n<0_${ik}$ ) then info = -3_${ik}$ else if( ldz<1_${ik}$ .or. ( wantz .and. ldz<n ) ) then info = -7_${ik}$ end if if( info/=0_${ik}$ ) then call stdlib${ii}$_xerbla( 'ZHPEV ', -info ) return end if ! quick return if possible if( n==0 )return if( n==1_${ik}$ ) then w( 1_${ik}$ ) = real( ap( 1_${ik}$ ),KIND=dp) rwork( 1_${ik}$ ) = 1_${ik}$ if( wantz )z( 1_${ik}$, 1_${ik}$ ) = one return end if ! get machine constants. safmin = stdlib${ii}$_dlamch( 'SAFE MINIMUM' ) eps = stdlib${ii}$_dlamch( 'PRECISION' ) smlnum = safmin / eps bignum = one / smlnum rmin = sqrt( smlnum ) rmax = sqrt( bignum ) ! scale matrix to allowable range, if necessary. anrm = stdlib${ii}$_zlanhp( 'M', uplo, n, ap, rwork ) iscale = 0_${ik}$ if( anrm>zero .and. anrm<rmin ) then iscale = 1_${ik}$ sigma = rmin / anrm else if( anrm>rmax ) then iscale = 1_${ik}$ sigma = rmax / anrm end if if( iscale==1_${ik}$ ) then call stdlib${ii}$_zdscal( ( n*( n+1 ) ) / 2_${ik}$, sigma, ap, 1_${ik}$ ) end if ! call stdlib${ii}$_zhptrd to reduce hermitian packed matrix to tridiagonal form. inde = 1_${ik}$ indtau = 1_${ik}$ call stdlib${ii}$_zhptrd( uplo, n, ap, w, rwork( inde ), work( indtau ),iinfo ) ! for eigenvalues only, call stdlib${ii}$_dsterf. for eigenvectors, first call ! stdlib${ii}$_zupgtr to generate the orthogonal matrix, then call stdlib${ii}$_zsteqr. if( .not.wantz ) then call stdlib${ii}$_dsterf( n, w, rwork( inde ), info ) else indwrk = indtau + n call stdlib${ii}$_zupgtr( uplo, n, ap, work( indtau ), z, ldz,work( indwrk ), iinfo ) indrwk = inde + n call stdlib${ii}$_zsteqr( jobz, n, w, rwork( inde ), z, ldz,rwork( indrwk ), info ) end if ! if matrix was scaled, then rescale eigenvalues appropriately. if( iscale==1_${ik}$ ) then if( info==0_${ik}$ ) then imax = n else imax = info - 1_${ik}$ end if call stdlib${ii}$_dscal( imax, one / sigma, w, 1_${ik}$ ) end if return end subroutine stdlib${ii}$_zhpev #:for ck,ct,ci in CMPLX_KINDS_TYPES #:if not ck in ["sp","dp"] module subroutine stdlib${ii}$_${ci}$hpev( jobz, uplo, n, ap, w, z, ldz, work, rwork,info ) !! ZHPEV: computes all the eigenvalues and, optionally, eigenvectors of a !! complex Hermitian matrix in packed storage. ! -- 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) :: jobz, uplo integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: ldz, n ! Array Arguments real(${ck}$), intent(out) :: rwork(*), w(*) complex(${ck}$), intent(inout) :: ap(*) complex(${ck}$), intent(out) :: work(*), z(ldz,*) ! ===================================================================== ! Local Scalars logical(lk) :: wantz integer(${ik}$) :: iinfo, imax, inde, indrwk, indtau, indwrk, iscale real(${ck}$) :: anrm, bignum, eps, rmax, rmin, safmin, sigma, smlnum ! Intrinsic Functions ! Executable Statements ! test the input parameters. wantz = stdlib_lsame( jobz, 'V' ) info = 0_${ik}$ if( .not.( wantz .or. stdlib_lsame( jobz, 'N' ) ) ) then info = -1_${ik}$ else if( .not.( stdlib_lsame( uplo, 'L' ) .or. stdlib_lsame( uplo, 'U' ) ) )& then info = -2_${ik}$ else if( n<0_${ik}$ ) then info = -3_${ik}$ else if( ldz<1_${ik}$ .or. ( wantz .and. ldz<n ) ) then info = -7_${ik}$ end if if( info/=0_${ik}$ ) then call stdlib${ii}$_xerbla( 'ZHPEV ', -info ) return end if ! quick return if possible if( n==0 )return if( n==1_${ik}$ ) then w( 1_${ik}$ ) = real( ap( 1_${ik}$ ),KIND=${ck}$) rwork( 1_${ik}$ ) = 1_${ik}$ if( wantz )z( 1_${ik}$, 1_${ik}$ ) = one return end if ! get machine constants. safmin = stdlib${ii}$_${c2ri(ci)}$lamch( 'SAFE MINIMUM' ) eps = stdlib${ii}$_${c2ri(ci)}$lamch( 'PRECISION' ) smlnum = safmin / eps bignum = one / smlnum rmin = sqrt( smlnum ) rmax = sqrt( bignum ) ! scale matrix to allowable range, if necessary. anrm = stdlib${ii}$_${ci}$lanhp( 'M', uplo, n, ap, rwork ) iscale = 0_${ik}$ if( anrm>zero .and. anrm<rmin ) then iscale = 1_${ik}$ sigma = rmin / anrm else if( anrm>rmax ) then iscale = 1_${ik}$ sigma = rmax / anrm end if if( iscale==1_${ik}$ ) then call stdlib${ii}$_${ci}$dscal( ( n*( n+1 ) ) / 2_${ik}$, sigma, ap, 1_${ik}$ ) end if ! call stdlib${ii}$_${ci}$hptrd to reduce hermitian packed matrix to tridiagonal form. inde = 1_${ik}$ indtau = 1_${ik}$ call stdlib${ii}$_${ci}$hptrd( uplo, n, ap, w, rwork( inde ), work( indtau ),iinfo ) ! for eigenvalues only, call stdlib${ii}$_${c2ri(ci)}$sterf. for eigenvectors, first call ! stdlib${ii}$_${ci}$upgtr to generate the orthogonal matrix, then call stdlib${ii}$_${ci}$steqr. if( .not.wantz ) then call stdlib${ii}$_${c2ri(ci)}$sterf( n, w, rwork( inde ), info ) else indwrk = indtau + n call stdlib${ii}$_${ci}$upgtr( uplo, n, ap, work( indtau ), z, ldz,work( indwrk ), iinfo ) indrwk = inde + n call stdlib${ii}$_${ci}$steqr( jobz, n, w, rwork( inde ), z, ldz,rwork( indrwk ), info ) end if ! if matrix was scaled, then rescale eigenvalues appropriately. if( iscale==1_${ik}$ ) then if( info==0_${ik}$ ) then imax = n else imax = info - 1_${ik}$ end if call stdlib${ii}$_${c2ri(ci)}$scal( imax, one / sigma, w, 1_${ik}$ ) end if return end subroutine stdlib${ii}$_${ci}$hpev #:endif #:endfor module subroutine stdlib${ii}$_chpevd( jobz, uplo, n, ap, w, z, ldz, work, lwork,rwork, lrwork, iwork, & !! CHPEVD computes all the eigenvalues and, optionally, eigenvectors of !! a complex Hermitian matrix A in packed storage. If eigenvectors are !! desired, it uses a divide and conquer algorithm. !! The divide and conquer algorithm makes very mild assumptions about !! floating point arithmetic. It will work on machines with a guard !! digit in add/subtract, or on those binary machines without guard !! digits which subtract like the Cray X-MP, Cray Y-MP, Cray C-90, or !! Cray-2. It could conceivably fail on hexadecimal or decimal machines !! without guard digits, but we know of none. liwork, 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) :: jobz, uplo integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: ldz, liwork, lrwork, lwork, n ! Array Arguments integer(${ik}$), intent(out) :: iwork(*) real(sp), intent(out) :: rwork(*), w(*) complex(sp), intent(inout) :: ap(*) complex(sp), intent(out) :: work(*), z(ldz,*) ! ===================================================================== ! Local Scalars logical(lk) :: lquery, wantz integer(${ik}$) :: iinfo, imax, inde, indrwk, indtau, indwrk, iscale, liwmin, llrwk, & llwrk, lrwmin, lwmin real(sp) :: anrm, bignum, eps, rmax, rmin, safmin, sigma, smlnum ! Intrinsic Functions ! Executable Statements ! test the input parameters. wantz = stdlib_lsame( jobz, 'V' ) lquery = ( lwork==-1_${ik}$ .or. lrwork==-1_${ik}$ .or. liwork==-1_${ik}$ ) info = 0_${ik}$ if( .not.( wantz .or. stdlib_lsame( jobz, 'N' ) ) ) then info = -1_${ik}$ else if( .not.( stdlib_lsame( uplo, 'L' ) .or. stdlib_lsame( uplo, 'U' ) ) )& then info = -2_${ik}$ else if( n<0_${ik}$ ) then info = -3_${ik}$ else if( ldz<1_${ik}$ .or. ( wantz .and. ldz<n ) ) then info = -7_${ik}$ end if if( info==0_${ik}$ ) then if( n<=1_${ik}$ ) then lwmin = 1_${ik}$ liwmin = 1_${ik}$ lrwmin = 1_${ik}$ else if( wantz ) then lwmin = 2_${ik}$*n lrwmin = 1_${ik}$ + 5_${ik}$*n + 2_${ik}$*n**2_${ik}$ liwmin = 3_${ik}$ + 5_${ik}$*n else lwmin = n lrwmin = n liwmin = 1_${ik}$ end if end if work( 1_${ik}$ ) = lwmin rwork( 1_${ik}$ ) = lrwmin iwork( 1_${ik}$ ) = liwmin if( lwork<lwmin .and. .not.lquery ) then info = -9_${ik}$ else if( lrwork<lrwmin .and. .not.lquery ) then info = -11_${ik}$ else if( liwork<liwmin .and. .not.lquery ) then info = -13_${ik}$ end if end if if( info/=0_${ik}$ ) then call stdlib${ii}$_xerbla( 'CHPEVD', -info ) return else if( lquery ) then return end if ! quick return if possible if( n==0 )return if( n==1_${ik}$ ) then w( 1_${ik}$ ) = real( ap( 1_${ik}$ ),KIND=sp) if( wantz )z( 1_${ik}$, 1_${ik}$ ) = cone return end if ! get machine constants. safmin = stdlib${ii}$_slamch( 'SAFE MINIMUM' ) eps = stdlib${ii}$_slamch( 'PRECISION' ) smlnum = safmin / eps bignum = one / smlnum rmin = sqrt( smlnum ) rmax = sqrt( bignum ) ! scale matrix to allowable range, if necessary. anrm = stdlib${ii}$_clanhp( 'M', uplo, n, ap, rwork ) iscale = 0_${ik}$ if( anrm>zero .and. anrm<rmin ) then iscale = 1_${ik}$ sigma = rmin / anrm else if( anrm>rmax ) then iscale = 1_${ik}$ sigma = rmax / anrm end if if( iscale==1_${ik}$ ) then call stdlib${ii}$_csscal( ( n*( n+1 ) ) / 2_${ik}$, sigma, ap, 1_${ik}$ ) end if ! call stdlib${ii}$_chptrd to reduce hermitian packed matrix to tridiagonal form. inde = 1_${ik}$ indtau = 1_${ik}$ indrwk = inde + n indwrk = indtau + n llwrk = lwork - indwrk + 1_${ik}$ llrwk = lrwork - indrwk + 1_${ik}$ call stdlib${ii}$_chptrd( uplo, n, ap, w, rwork( inde ), work( indtau ),iinfo ) ! for eigenvalues only, call stdlib${ii}$_ssterf. for eigenvectors, first call ! stdlib${ii}$_cupgtr to generate the orthogonal matrix, then call stdlib${ii}$_cstedc. if( .not.wantz ) then call stdlib${ii}$_ssterf( n, w, rwork( inde ), info ) else call stdlib${ii}$_cstedc( 'I', n, w, rwork( inde ), z, ldz, work( indwrk ),llwrk, rwork( & indrwk ), llrwk, iwork, liwork,info ) call stdlib${ii}$_cupmtr( 'L', uplo, 'N', n, n, ap, work( indtau ), z, ldz,work( indwrk ),& iinfo ) end if ! if matrix was scaled, then rescale eigenvalues appropriately. if( iscale==1_${ik}$ ) then if( info==0_${ik}$ ) then imax = n else imax = info - 1_${ik}$ end if call stdlib${ii}$_sscal( imax, one / sigma, w, 1_${ik}$ ) end if work( 1_${ik}$ ) = lwmin rwork( 1_${ik}$ ) = lrwmin iwork( 1_${ik}$ ) = liwmin return end subroutine stdlib${ii}$_chpevd module subroutine stdlib${ii}$_zhpevd( jobz, uplo, n, ap, w, z, ldz, work, lwork,rwork, lrwork, iwork, & !! ZHPEVD computes all the eigenvalues and, optionally, eigenvectors of !! a complex Hermitian matrix A in packed storage. If eigenvectors are !! desired, it uses a divide and conquer algorithm. !! The divide and conquer algorithm makes very mild assumptions about !! floating point arithmetic. It will work on machines with a guard !! digit in add/subtract, or on those binary machines without guard !! digits which subtract like the Cray X-MP, Cray Y-MP, Cray C-90, or !! Cray-2. It could conceivably fail on hexadecimal or decimal machines !! without guard digits, but we know of none. liwork, 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) :: jobz, uplo integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: ldz, liwork, lrwork, lwork, n ! Array Arguments integer(${ik}$), intent(out) :: iwork(*) real(dp), intent(out) :: rwork(*), w(*) complex(dp), intent(inout) :: ap(*) complex(dp), intent(out) :: work(*), z(ldz,*) ! ===================================================================== ! Local Scalars logical(lk) :: lquery, wantz integer(${ik}$) :: iinfo, imax, inde, indrwk, indtau, indwrk, iscale, liwmin, llrwk, & llwrk, lrwmin, lwmin real(dp) :: anrm, bignum, eps, rmax, rmin, safmin, sigma, smlnum ! Intrinsic Functions ! Executable Statements ! test the input parameters. wantz = stdlib_lsame( jobz, 'V' ) lquery = ( lwork==-1_${ik}$ .or. lrwork==-1_${ik}$ .or. liwork==-1_${ik}$ ) info = 0_${ik}$ if( .not.( wantz .or. stdlib_lsame( jobz, 'N' ) ) ) then info = -1_${ik}$ else if( .not.( stdlib_lsame( uplo, 'L' ) .or. stdlib_lsame( uplo, 'U' ) ) )& then info = -2_${ik}$ else if( n<0_${ik}$ ) then info = -3_${ik}$ else if( ldz<1_${ik}$ .or. ( wantz .and. ldz<n ) ) then info = -7_${ik}$ end if if( info==0_${ik}$ ) then if( n<=1_${ik}$ ) then lwmin = 1_${ik}$ liwmin = 1_${ik}$ lrwmin = 1_${ik}$ else if( wantz ) then lwmin = 2_${ik}$*n lrwmin = 1_${ik}$ + 5_${ik}$*n + 2_${ik}$*n**2_${ik}$ liwmin = 3_${ik}$ + 5_${ik}$*n else lwmin = n lrwmin = n liwmin = 1_${ik}$ end if end if work( 1_${ik}$ ) = lwmin rwork( 1_${ik}$ ) = lrwmin iwork( 1_${ik}$ ) = liwmin if( lwork<lwmin .and. .not.lquery ) then info = -9_${ik}$ else if( lrwork<lrwmin .and. .not.lquery ) then info = -11_${ik}$ else if( liwork<liwmin .and. .not.lquery ) then info = -13_${ik}$ end if end if if( info/=0_${ik}$ ) then call stdlib${ii}$_xerbla( 'ZHPEVD', -info ) return else if( lquery ) then return end if ! quick return if possible if( n==0 )return if( n==1_${ik}$ ) then w( 1_${ik}$ ) = real( ap( 1_${ik}$ ),KIND=dp) if( wantz )z( 1_${ik}$, 1_${ik}$ ) = cone return end if ! get machine constants. safmin = stdlib${ii}$_dlamch( 'SAFE MINIMUM' ) eps = stdlib${ii}$_dlamch( 'PRECISION' ) smlnum = safmin / eps bignum = one / smlnum rmin = sqrt( smlnum ) rmax = sqrt( bignum ) ! scale matrix to allowable range, if necessary. anrm = stdlib${ii}$_zlanhp( 'M', uplo, n, ap, rwork ) iscale = 0_${ik}$ if( anrm>zero .and. anrm<rmin ) then iscale = 1_${ik}$ sigma = rmin / anrm else if( anrm>rmax ) then iscale = 1_${ik}$ sigma = rmax / anrm end if if( iscale==1_${ik}$ ) then call stdlib${ii}$_zdscal( ( n*( n+1 ) ) / 2_${ik}$, sigma, ap, 1_${ik}$ ) end if ! call stdlib${ii}$_zhptrd to reduce hermitian packed matrix to tridiagonal form. inde = 1_${ik}$ indtau = 1_${ik}$ indrwk = inde + n indwrk = indtau + n llwrk = lwork - indwrk + 1_${ik}$ llrwk = lrwork - indrwk + 1_${ik}$ call stdlib${ii}$_zhptrd( uplo, n, ap, w, rwork( inde ), work( indtau ),iinfo ) ! for eigenvalues only, call stdlib${ii}$_dsterf. for eigenvectors, first call ! stdlib${ii}$_zupgtr to generate the orthogonal matrix, then call stdlib${ii}$_zstedc. if( .not.wantz ) then call stdlib${ii}$_dsterf( n, w, rwork( inde ), info ) else call stdlib${ii}$_zstedc( 'I', n, w, rwork( inde ), z, ldz, work( indwrk ),llwrk, rwork( & indrwk ), llrwk, iwork, liwork,info ) call stdlib${ii}$_zupmtr( 'L', uplo, 'N', n, n, ap, work( indtau ), z, ldz,work( indwrk ),& iinfo ) end if ! if matrix was scaled, then rescale eigenvalues appropriately. if( iscale==1_${ik}$ ) then if( info==0_${ik}$ ) then imax = n else imax = info - 1_${ik}$ end if call stdlib${ii}$_dscal( imax, one / sigma, w, 1_${ik}$ ) end if work( 1_${ik}$ ) = lwmin rwork( 1_${ik}$ ) = lrwmin iwork( 1_${ik}$ ) = liwmin return end subroutine stdlib${ii}$_zhpevd #:for ck,ct,ci in CMPLX_KINDS_TYPES #:if not ck in ["sp","dp"] module subroutine stdlib${ii}$_${ci}$hpevd( jobz, uplo, n, ap, w, z, ldz, work, lwork,rwork, lrwork, iwork, & !! ZHPEVD: computes all the eigenvalues and, optionally, eigenvectors of !! a complex Hermitian matrix A in packed storage. If eigenvectors are !! desired, it uses a divide and conquer algorithm. !! The divide and conquer algorithm makes very mild assumptions about !! floating point arithmetic. It will work on machines with a guard !! digit in add/subtract, or on those binary machines without guard !! digits which subtract like the Cray X-MP, Cray Y-MP, Cray C-90, or !! Cray-2. It could conceivably fail on hexadecimal or decimal machines !! without guard digits, but we know of none. liwork, 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) :: jobz, uplo integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: ldz, liwork, lrwork, lwork, n ! Array Arguments integer(${ik}$), intent(out) :: iwork(*) real(${ck}$), intent(out) :: rwork(*), w(*) complex(${ck}$), intent(inout) :: ap(*) complex(${ck}$), intent(out) :: work(*), z(ldz,*) ! ===================================================================== ! Local Scalars logical(lk) :: lquery, wantz integer(${ik}$) :: iinfo, imax, inde, indrwk, indtau, indwrk, iscale, liwmin, llrwk, & llwrk, lrwmin, lwmin real(${ck}$) :: anrm, bignum, eps, rmax, rmin, safmin, sigma, smlnum ! Intrinsic Functions ! Executable Statements ! test the input parameters. wantz = stdlib_lsame( jobz, 'V' ) lquery = ( lwork==-1_${ik}$ .or. lrwork==-1_${ik}$ .or. liwork==-1_${ik}$ ) info = 0_${ik}$ if( .not.( wantz .or. stdlib_lsame( jobz, 'N' ) ) ) then info = -1_${ik}$ else if( .not.( stdlib_lsame( uplo, 'L' ) .or. stdlib_lsame( uplo, 'U' ) ) )& then info = -2_${ik}$ else if( n<0_${ik}$ ) then info = -3_${ik}$ else if( ldz<1_${ik}$ .or. ( wantz .and. ldz<n ) ) then info = -7_${ik}$ end if if( info==0_${ik}$ ) then if( n<=1_${ik}$ ) then lwmin = 1_${ik}$ liwmin = 1_${ik}$ lrwmin = 1_${ik}$ else if( wantz ) then lwmin = 2_${ik}$*n lrwmin = 1_${ik}$ + 5_${ik}$*n + 2_${ik}$*n**2_${ik}$ liwmin = 3_${ik}$ + 5_${ik}$*n else lwmin = n lrwmin = n liwmin = 1_${ik}$ end if end if work( 1_${ik}$ ) = lwmin rwork( 1_${ik}$ ) = lrwmin iwork( 1_${ik}$ ) = liwmin if( lwork<lwmin .and. .not.lquery ) then info = -9_${ik}$ else if( lrwork<lrwmin .and. .not.lquery ) then info = -11_${ik}$ else if( liwork<liwmin .and. .not.lquery ) then info = -13_${ik}$ end if end if if( info/=0_${ik}$ ) then call stdlib${ii}$_xerbla( 'ZHPEVD', -info ) return else if( lquery ) then return end if ! quick return if possible if( n==0 )return if( n==1_${ik}$ ) then w( 1_${ik}$ ) = real( ap( 1_${ik}$ ),KIND=${ck}$) if( wantz )z( 1_${ik}$, 1_${ik}$ ) = cone return end if ! get machine constants. safmin = stdlib${ii}$_${c2ri(ci)}$lamch( 'SAFE MINIMUM' ) eps = stdlib${ii}$_${c2ri(ci)}$lamch( 'PRECISION' ) smlnum = safmin / eps bignum = one / smlnum rmin = sqrt( smlnum ) rmax = sqrt( bignum ) ! scale matrix to allowable range, if necessary. anrm = stdlib${ii}$_${ci}$lanhp( 'M', uplo, n, ap, rwork ) iscale = 0_${ik}$ if( anrm>zero .and. anrm<rmin ) then iscale = 1_${ik}$ sigma = rmin / anrm else if( anrm>rmax ) then iscale = 1_${ik}$ sigma = rmax / anrm end if if( iscale==1_${ik}$ ) then call stdlib${ii}$_${ci}$dscal( ( n*( n+1 ) ) / 2_${ik}$, sigma, ap, 1_${ik}$ ) end if ! call stdlib${ii}$_${ci}$hptrd to reduce hermitian packed matrix to tridiagonal form. inde = 1_${ik}$ indtau = 1_${ik}$ indrwk = inde + n indwrk = indtau + n llwrk = lwork - indwrk + 1_${ik}$ llrwk = lrwork - indrwk + 1_${ik}$ call stdlib${ii}$_${ci}$hptrd( uplo, n, ap, w, rwork( inde ), work( indtau ),iinfo ) ! for eigenvalues only, call stdlib${ii}$_${c2ri(ci)}$sterf. for eigenvectors, first call ! stdlib${ii}$_${ci}$upgtr to generate the orthogonal matrix, then call stdlib${ii}$_${ci}$stedc. if( .not.wantz ) then call stdlib${ii}$_${c2ri(ci)}$sterf( n, w, rwork( inde ), info ) else call stdlib${ii}$_${ci}$stedc( 'I', n, w, rwork( inde ), z, ldz, work( indwrk ),llwrk, rwork( & indrwk ), llrwk, iwork, liwork,info ) call stdlib${ii}$_${ci}$upmtr( 'L', uplo, 'N', n, n, ap, work( indtau ), z, ldz,work( indwrk ),& iinfo ) end if ! if matrix was scaled, then rescale eigenvalues appropriately. if( iscale==1_${ik}$ ) then if( info==0_${ik}$ ) then imax = n else imax = info - 1_${ik}$ end if call stdlib${ii}$_${c2ri(ci)}$scal( imax, one / sigma, w, 1_${ik}$ ) end if work( 1_${ik}$ ) = lwmin rwork( 1_${ik}$ ) = lrwmin iwork( 1_${ik}$ ) = liwmin return end subroutine stdlib${ii}$_${ci}$hpevd #:endif #:endfor module subroutine stdlib${ii}$_chpevx( jobz, range, uplo, n, ap, vl, vu, il, iu,abstol, m, w, z, ldz, & !! CHPEVX computes selected eigenvalues and, optionally, eigenvectors !! of a complex Hermitian matrix A in packed storage. !! Eigenvalues/vectors can be selected by specifying either a range of !! values or a range of indices for the desired eigenvalues. work, rwork, iwork,ifail, 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) :: jobz, range, uplo integer(${ik}$), intent(in) :: il, iu, ldz, n integer(${ik}$), intent(out) :: info, m real(sp), intent(in) :: abstol, vl, vu ! Array Arguments integer(${ik}$), intent(out) :: ifail(*), iwork(*) real(sp), intent(out) :: rwork(*), w(*) complex(sp), intent(inout) :: ap(*) complex(sp), intent(out) :: work(*), z(ldz,*) ! ===================================================================== ! Local Scalars logical(lk) :: alleig, indeig, test, valeig, wantz character :: order integer(${ik}$) :: i, iinfo, imax, indd, inde, indee, indibl, indisp, indiwk, indrwk, & indtau, indwrk, iscale, itmp1, j, jj, nsplit real(sp) :: abstll, anrm, bignum, eps, rmax, rmin, safmin, sigma, smlnum, tmp1, vll, & vuu ! Intrinsic Functions ! Executable Statements ! test the input parameters. wantz = stdlib_lsame( jobz, 'V' ) alleig = stdlib_lsame( range, 'A' ) valeig = stdlib_lsame( range, 'V' ) indeig = stdlib_lsame( range, 'I' ) info = 0_${ik}$ if( .not.( wantz .or. stdlib_lsame( jobz, 'N' ) ) ) then info = -1_${ik}$ else if( .not.( alleig .or. valeig .or. indeig ) ) then info = -2_${ik}$ else if( .not.( stdlib_lsame( uplo, 'L' ) .or. stdlib_lsame( uplo, 'U' ) ) )& then info = -3_${ik}$ else if( n<0_${ik}$ ) then info = -4_${ik}$ else if( valeig ) then if( n>0_${ik}$ .and. vu<=vl )info = -7_${ik}$ else if( indeig ) then if( il<1_${ik}$ .or. il>max( 1_${ik}$, n ) ) then info = -8_${ik}$ else if( iu<min( n, il ) .or. iu>n ) then info = -9_${ik}$ end if end if end if if( info==0_${ik}$ ) then if( ldz<1_${ik}$ .or. ( wantz .and. ldz<n ) )info = -14_${ik}$ end if if( info/=0_${ik}$ ) then call stdlib${ii}$_xerbla( 'CHPEVX', -info ) return end if ! quick return if possible m = 0_${ik}$ if( n==0 )return if( n==1_${ik}$ ) then if( alleig .or. indeig ) then m = 1_${ik}$ w( 1_${ik}$ ) = real( ap( 1_${ik}$ ),KIND=sp) else if( vl<real( ap( 1_${ik}$ ),KIND=sp) .and. vu>=real( ap( 1_${ik}$ ),KIND=sp) ) then m = 1_${ik}$ w( 1_${ik}$ ) = real( ap( 1_${ik}$ ),KIND=sp) end if end if if( wantz )z( 1_${ik}$, 1_${ik}$ ) = cone return end if ! get machine constants. safmin = stdlib${ii}$_slamch( 'SAFE MINIMUM' ) eps = stdlib${ii}$_slamch( 'PRECISION' ) smlnum = safmin / eps bignum = one / smlnum rmin = sqrt( smlnum ) rmax = min( sqrt( bignum ), one / sqrt( sqrt( safmin ) ) ) ! scale matrix to allowable range, if necessary. iscale = 0_${ik}$ abstll = abstol if ( valeig ) then vll = vl vuu = vu else vll = zero vuu = zero endif anrm = stdlib${ii}$_clanhp( 'M', uplo, n, ap, rwork ) if( anrm>zero .and. anrm<rmin ) then iscale = 1_${ik}$ sigma = rmin / anrm else if( anrm>rmax ) then iscale = 1_${ik}$ sigma = rmax / anrm end if if( iscale==1_${ik}$ ) then call stdlib${ii}$_csscal( ( n*( n+1 ) ) / 2_${ik}$, sigma, ap, 1_${ik}$ ) if( abstol>0_${ik}$ )abstll = abstol*sigma if( valeig ) then vll = vl*sigma vuu = vu*sigma end if end if ! call stdlib${ii}$_chptrd to reduce hermitian packed matrix to tridiagonal form. indd = 1_${ik}$ inde = indd + n indrwk = inde + n indtau = 1_${ik}$ indwrk = indtau + n call stdlib${ii}$_chptrd( uplo, n, ap, rwork( indd ), rwork( inde ),work( indtau ), iinfo ) ! if all eigenvalues are desired and abstol is less than or equal ! to zero, then call stdlib${ii}$_ssterf or stdlib${ii}$_cupgtr and stdlib${ii}$_csteqr. if this fails ! for some eigenvalue, then try stdlib${ii}$_sstebz. test = .false. if (indeig) then if (il==1_${ik}$ .and. iu==n) then test = .true. end if end if if ((alleig .or. test) .and. (abstol<=zero)) then call stdlib${ii}$_scopy( n, rwork( indd ), 1_${ik}$, w, 1_${ik}$ ) indee = indrwk + 2_${ik}$*n if( .not.wantz ) then call stdlib${ii}$_scopy( n-1, rwork( inde ), 1_${ik}$, rwork( indee ), 1_${ik}$ ) call stdlib${ii}$_ssterf( n, w, rwork( indee ), info ) else call stdlib${ii}$_cupgtr( uplo, n, ap, work( indtau ), z, ldz,work( indwrk ), iinfo ) call stdlib${ii}$_scopy( n-1, rwork( inde ), 1_${ik}$, rwork( indee ), 1_${ik}$ ) call stdlib${ii}$_csteqr( jobz, n, w, rwork( indee ), z, ldz,rwork( indrwk ), info ) if( info==0_${ik}$ ) then do i = 1, n ifail( i ) = 0_${ik}$ end do end if end if if( info==0_${ik}$ ) then m = n go to 20 end if info = 0_${ik}$ end if ! otherwise, call stdlib${ii}$_sstebz and, if eigenvectors are desired, stdlib${ii}$_cstein. if( wantz ) then order = 'B' else order = 'E' end if indibl = 1_${ik}$ indisp = indibl + n indiwk = indisp + n call stdlib${ii}$_sstebz( range, order, n, vll, vuu, il, iu, abstll,rwork( indd ), rwork( & inde ), m, nsplit, w,iwork( indibl ), iwork( indisp ), rwork( indrwk ),iwork( indiwk ),& info ) if( wantz ) then call stdlib${ii}$_cstein( n, rwork( indd ), rwork( inde ), m, w,iwork( indibl ), iwork( & indisp ), z, ldz,rwork( indrwk ), iwork( indiwk ), ifail, info ) ! apply unitary matrix used in reduction to tridiagonal ! form to eigenvectors returned by stdlib${ii}$_cstein. indwrk = indtau + n call stdlib${ii}$_cupmtr( 'L', uplo, 'N', n, m, ap, work( indtau ), z, ldz,work( indwrk ),& iinfo ) end if ! if matrix was scaled, then rescale eigenvalues appropriately. 20 continue if( iscale==1_${ik}$ ) then if( info==0_${ik}$ ) then imax = m else imax = info - 1_${ik}$ end if call stdlib${ii}$_sscal( imax, one / sigma, w, 1_${ik}$ ) end if ! if eigenvalues are not in order, then sort them, along with ! eigenvectors. if( wantz ) then do j = 1, m - 1 i = 0_${ik}$ tmp1 = w( j ) do jj = j + 1, m if( w( jj )<tmp1 ) then i = jj tmp1 = w( jj ) end if end do if( i/=0_${ik}$ ) then itmp1 = iwork( indibl+i-1 ) w( i ) = w( j ) iwork( indibl+i-1 ) = iwork( indibl+j-1 ) w( j ) = tmp1 iwork( indibl+j-1 ) = itmp1 call stdlib${ii}$_cswap( n, z( 1_${ik}$, i ), 1_${ik}$, z( 1_${ik}$, j ), 1_${ik}$ ) if( info/=0_${ik}$ ) then itmp1 = ifail( i ) ifail( i ) = ifail( j ) ifail( j ) = itmp1 end if end if end do end if return end subroutine stdlib${ii}$_chpevx module subroutine stdlib${ii}$_zhpevx( jobz, range, uplo, n, ap, vl, vu, il, iu,abstol, m, w, z, ldz, & !! ZHPEVX computes selected eigenvalues and, optionally, eigenvectors !! of a complex Hermitian matrix A in packed storage. !! Eigenvalues/vectors can be selected by specifying either a range of !! values or a range of indices for the desired eigenvalues. work, rwork, iwork,ifail, 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) :: jobz, range, uplo integer(${ik}$), intent(in) :: il, iu, ldz, n integer(${ik}$), intent(out) :: info, m real(dp), intent(in) :: abstol, vl, vu ! Array Arguments integer(${ik}$), intent(out) :: ifail(*), iwork(*) real(dp), intent(out) :: rwork(*), w(*) complex(dp), intent(inout) :: ap(*) complex(dp), intent(out) :: work(*), z(ldz,*) ! ===================================================================== ! Local Scalars logical(lk) :: alleig, indeig, test, valeig, wantz character :: order integer(${ik}$) :: i, iinfo, imax, indd, inde, indee, indibl, indisp, indiwk, indrwk, & indtau, indwrk, iscale, itmp1, j, jj, nsplit real(dp) :: abstll, anrm, bignum, eps, rmax, rmin, safmin, sigma, smlnum, tmp1, vll, & vuu ! Intrinsic Functions ! Executable Statements ! test the input parameters. wantz = stdlib_lsame( jobz, 'V' ) alleig = stdlib_lsame( range, 'A' ) valeig = stdlib_lsame( range, 'V' ) indeig = stdlib_lsame( range, 'I' ) info = 0_${ik}$ if( .not.( wantz .or. stdlib_lsame( jobz, 'N' ) ) ) then info = -1_${ik}$ else if( .not.( alleig .or. valeig .or. indeig ) ) then info = -2_${ik}$ else if( .not.( stdlib_lsame( uplo, 'L' ) .or. stdlib_lsame( uplo, 'U' ) ) )& then info = -3_${ik}$ else if( n<0_${ik}$ ) then info = -4_${ik}$ else if( valeig ) then if( n>0_${ik}$ .and. vu<=vl )info = -7_${ik}$ else if( indeig ) then if( il<1_${ik}$ .or. il>max( 1_${ik}$, n ) ) then info = -8_${ik}$ else if( iu<min( n, il ) .or. iu>n ) then info = -9_${ik}$ end if end if end if if( info==0_${ik}$ ) then if( ldz<1_${ik}$ .or. ( wantz .and. ldz<n ) )info = -14_${ik}$ end if if( info/=0_${ik}$ ) then call stdlib${ii}$_xerbla( 'ZHPEVX', -info ) return end if ! quick return if possible m = 0_${ik}$ if( n==0 )return if( n==1_${ik}$ ) then if( alleig .or. indeig ) then m = 1_${ik}$ w( 1_${ik}$ ) = real( ap( 1_${ik}$ ),KIND=dp) else if( vl<real( ap( 1_${ik}$ ),KIND=dp) .and. vu>=real( ap( 1_${ik}$ ),KIND=dp) ) then m = 1_${ik}$ w( 1_${ik}$ ) = real( ap( 1_${ik}$ ),KIND=dp) end if end if if( wantz )z( 1_${ik}$, 1_${ik}$ ) = cone return end if ! get machine constants. safmin = stdlib${ii}$_dlamch( 'SAFE MINIMUM' ) eps = stdlib${ii}$_dlamch( 'PRECISION' ) smlnum = safmin / eps bignum = one / smlnum rmin = sqrt( smlnum ) rmax = min( sqrt( bignum ), one / sqrt( sqrt( safmin ) ) ) ! scale matrix to allowable range, if necessary. iscale = 0_${ik}$ abstll = abstol if( valeig ) then vll = vl vuu = vu else vll = zero vuu = zero end if anrm = stdlib${ii}$_zlanhp( 'M', uplo, n, ap, rwork ) if( anrm>zero .and. anrm<rmin ) then iscale = 1_${ik}$ sigma = rmin / anrm else if( anrm>rmax ) then iscale = 1_${ik}$ sigma = rmax / anrm end if if( iscale==1_${ik}$ ) then call stdlib${ii}$_zdscal( ( n*( n+1 ) ) / 2_${ik}$, sigma, ap, 1_${ik}$ ) if( abstol>0_${ik}$ )abstll = abstol*sigma if( valeig ) then vll = vl*sigma vuu = vu*sigma end if end if ! call stdlib${ii}$_zhptrd to reduce hermitian packed matrix to tridiagonal form. indd = 1_${ik}$ inde = indd + n indrwk = inde + n indtau = 1_${ik}$ indwrk = indtau + n call stdlib${ii}$_zhptrd( uplo, n, ap, rwork( indd ), rwork( inde ),work( indtau ), iinfo ) ! if all eigenvalues are desired and abstol is less than or equal ! to zero, then call stdlib${ii}$_dsterf or stdlib${ii}$_zupgtr and stdlib${ii}$_zsteqr. if this fails ! for some eigenvalue, then try stdlib${ii}$_dstebz. test = .false. if (indeig) then if (il==1_${ik}$ .and. iu==n) then test = .true. end if end if if ((alleig .or. test) .and. (abstol<=zero)) then call stdlib${ii}$_dcopy( n, rwork( indd ), 1_${ik}$, w, 1_${ik}$ ) indee = indrwk + 2_${ik}$*n if( .not.wantz ) then call stdlib${ii}$_dcopy( n-1, rwork( inde ), 1_${ik}$, rwork( indee ), 1_${ik}$ ) call stdlib${ii}$_dsterf( n, w, rwork( indee ), info ) else call stdlib${ii}$_zupgtr( uplo, n, ap, work( indtau ), z, ldz,work( indwrk ), iinfo ) call stdlib${ii}$_dcopy( n-1, rwork( inde ), 1_${ik}$, rwork( indee ), 1_${ik}$ ) call stdlib${ii}$_zsteqr( jobz, n, w, rwork( indee ), z, ldz,rwork( indrwk ), info ) if( info==0_${ik}$ ) then do i = 1, n ifail( i ) = 0_${ik}$ end do end if end if if( info==0_${ik}$ ) then m = n go to 20 end if info = 0_${ik}$ end if ! otherwise, call stdlib${ii}$_dstebz and, if eigenvectors are desired, stdlib${ii}$_zstein. if( wantz ) then order = 'B' else order = 'E' end if indibl = 1_${ik}$ indisp = indibl + n indiwk = indisp + n call stdlib${ii}$_dstebz( range, order, n, vll, vuu, il, iu, abstll,rwork( indd ), rwork( & inde ), m, nsplit, w,iwork( indibl ), iwork( indisp ), rwork( indrwk ),iwork( indiwk ),& info ) if( wantz ) then call stdlib${ii}$_zstein( n, rwork( indd ), rwork( inde ), m, w,iwork( indibl ), iwork( & indisp ), z, ldz,rwork( indrwk ), iwork( indiwk ), ifail, info ) ! apply unitary matrix used in reduction to tridiagonal ! form to eigenvectors returned by stdlib${ii}$_zstein. indwrk = indtau + n call stdlib${ii}$_zupmtr( 'L', uplo, 'N', n, m, ap, work( indtau ), z, ldz,work( indwrk ),& iinfo ) end if ! if matrix was scaled, then rescale eigenvalues appropriately. 20 continue if( iscale==1_${ik}$ ) then if( info==0_${ik}$ ) then imax = m else imax = info - 1_${ik}$ end if call stdlib${ii}$_dscal( imax, one / sigma, w, 1_${ik}$ ) end if ! if eigenvalues are not in order, then sort them, along with ! eigenvectors. if( wantz ) then do j = 1, m - 1 i = 0_${ik}$ tmp1 = w( j ) do jj = j + 1, m if( w( jj )<tmp1 ) then i = jj tmp1 = w( jj ) end if end do if( i/=0_${ik}$ ) then itmp1 = iwork( indibl+i-1 ) w( i ) = w( j ) iwork( indibl+i-1 ) = iwork( indibl+j-1 ) w( j ) = tmp1 iwork( indibl+j-1 ) = itmp1 call stdlib${ii}$_zswap( n, z( 1_${ik}$, i ), 1_${ik}$, z( 1_${ik}$, j ), 1_${ik}$ ) if( info/=0_${ik}$ ) then itmp1 = ifail( i ) ifail( i ) = ifail( j ) ifail( j ) = itmp1 end if end if end do end if return end subroutine stdlib${ii}$_zhpevx #:for ck,ct,ci in CMPLX_KINDS_TYPES #:if not ck in ["sp","dp"] module subroutine stdlib${ii}$_${ci}$hpevx( jobz, range, uplo, n, ap, vl, vu, il, iu,abstol, m, w, z, ldz, & !! ZHPEVX: computes selected eigenvalues and, optionally, eigenvectors !! of a complex Hermitian matrix A in packed storage. !! Eigenvalues/vectors can be selected by specifying either a range of !! values or a range of indices for the desired eigenvalues. work, rwork, iwork,ifail, 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) :: jobz, range, uplo integer(${ik}$), intent(in) :: il, iu, ldz, n integer(${ik}$), intent(out) :: info, m real(${ck}$), intent(in) :: abstol, vl, vu ! Array Arguments integer(${ik}$), intent(out) :: ifail(*), iwork(*) real(${ck}$), intent(out) :: rwork(*), w(*) complex(${ck}$), intent(inout) :: ap(*) complex(${ck}$), intent(out) :: work(*), z(ldz,*) ! ===================================================================== ! Local Scalars logical(lk) :: alleig, indeig, test, valeig, wantz character :: order integer(${ik}$) :: i, iinfo, imax, indd, inde, indee, indibl, indisp, indiwk, indrwk, & indtau, indwrk, iscale, itmp1, j, jj, nsplit real(${ck}$) :: abstll, anrm, bignum, eps, rmax, rmin, safmin, sigma, smlnum, tmp1, vll, & vuu ! Intrinsic Functions ! Executable Statements ! test the input parameters. wantz = stdlib_lsame( jobz, 'V' ) alleig = stdlib_lsame( range, 'A' ) valeig = stdlib_lsame( range, 'V' ) indeig = stdlib_lsame( range, 'I' ) info = 0_${ik}$ if( .not.( wantz .or. stdlib_lsame( jobz, 'N' ) ) ) then info = -1_${ik}$ else if( .not.( alleig .or. valeig .or. indeig ) ) then info = -2_${ik}$ else if( .not.( stdlib_lsame( uplo, 'L' ) .or. stdlib_lsame( uplo, 'U' ) ) )& then info = -3_${ik}$ else if( n<0_${ik}$ ) then info = -4_${ik}$ else if( valeig ) then if( n>0_${ik}$ .and. vu<=vl )info = -7_${ik}$ else if( indeig ) then if( il<1_${ik}$ .or. il>max( 1_${ik}$, n ) ) then info = -8_${ik}$ else if( iu<min( n, il ) .or. iu>n ) then info = -9_${ik}$ end if end if end if if( info==0_${ik}$ ) then if( ldz<1_${ik}$ .or. ( wantz .and. ldz<n ) )info = -14_${ik}$ end if if( info/=0_${ik}$ ) then call stdlib${ii}$_xerbla( 'ZHPEVX', -info ) return end if ! quick return if possible m = 0_${ik}$ if( n==0 )return if( n==1_${ik}$ ) then if( alleig .or. indeig ) then m = 1_${ik}$ w( 1_${ik}$ ) = real( ap( 1_${ik}$ ),KIND=${ck}$) else if( vl<real( ap( 1_${ik}$ ),KIND=${ck}$) .and. vu>=real( ap( 1_${ik}$ ),KIND=${ck}$) ) then m = 1_${ik}$ w( 1_${ik}$ ) = real( ap( 1_${ik}$ ),KIND=${ck}$) end if end if if( wantz )z( 1_${ik}$, 1_${ik}$ ) = cone return end if ! get machine constants. safmin = stdlib${ii}$_${c2ri(ci)}$lamch( 'SAFE MINIMUM' ) eps = stdlib${ii}$_${c2ri(ci)}$lamch( 'PRECISION' ) smlnum = safmin / eps bignum = one / smlnum rmin = sqrt( smlnum ) rmax = min( sqrt( bignum ), one / sqrt( sqrt( safmin ) ) ) ! scale matrix to allowable range, if necessary. iscale = 0_${ik}$ abstll = abstol if( valeig ) then vll = vl vuu = vu else vll = zero vuu = zero end if anrm = stdlib${ii}$_${ci}$lanhp( 'M', uplo, n, ap, rwork ) if( anrm>zero .and. anrm<rmin ) then iscale = 1_${ik}$ sigma = rmin / anrm else if( anrm>rmax ) then iscale = 1_${ik}$ sigma = rmax / anrm end if if( iscale==1_${ik}$ ) then call stdlib${ii}$_${ci}$dscal( ( n*( n+1 ) ) / 2_${ik}$, sigma, ap, 1_${ik}$ ) if( abstol>0_${ik}$ )abstll = abstol*sigma if( valeig ) then vll = vl*sigma vuu = vu*sigma end if end if ! call stdlib${ii}$_${ci}$hptrd to reduce hermitian packed matrix to tridiagonal form. indd = 1_${ik}$ inde = indd + n indrwk = inde + n indtau = 1_${ik}$ indwrk = indtau + n call stdlib${ii}$_${ci}$hptrd( uplo, n, ap, rwork( indd ), rwork( inde ),work( indtau ), iinfo ) ! if all eigenvalues are desired and abstol is less than or equal ! to zero, then call stdlib${ii}$_${c2ri(ci)}$sterf or stdlib${ii}$_${ci}$upgtr and stdlib${ii}$_${ci}$steqr. if this fails ! for some eigenvalue, then try stdlib${ii}$_${c2ri(ci)}$stebz. test = .false. if (indeig) then if (il==1_${ik}$ .and. iu==n) then test = .true. end if end if if ((alleig .or. test) .and. (abstol<=zero)) then call stdlib${ii}$_${c2ri(ci)}$copy( n, rwork( indd ), 1_${ik}$, w, 1_${ik}$ ) indee = indrwk + 2_${ik}$*n if( .not.wantz ) then call stdlib${ii}$_${c2ri(ci)}$copy( n-1, rwork( inde ), 1_${ik}$, rwork( indee ), 1_${ik}$ ) call stdlib${ii}$_${c2ri(ci)}$sterf( n, w, rwork( indee ), info ) else call stdlib${ii}$_${ci}$upgtr( uplo, n, ap, work( indtau ), z, ldz,work( indwrk ), iinfo ) call stdlib${ii}$_${c2ri(ci)}$copy( n-1, rwork( inde ), 1_${ik}$, rwork( indee ), 1_${ik}$ ) call stdlib${ii}$_${ci}$steqr( jobz, n, w, rwork( indee ), z, ldz,rwork( indrwk ), info ) if( info==0_${ik}$ ) then do i = 1, n ifail( i ) = 0_${ik}$ end do end if end if if( info==0_${ik}$ ) then m = n go to 20 end if info = 0_${ik}$ end if ! otherwise, call stdlib${ii}$_${c2ri(ci)}$stebz and, if eigenvectors are desired, stdlib${ii}$_${ci}$stein. if( wantz ) then order = 'B' else order = 'E' end if indibl = 1_${ik}$ indisp = indibl + n indiwk = indisp + n call stdlib${ii}$_${c2ri(ci)}$stebz( range, order, n, vll, vuu, il, iu, abstll,rwork( indd ), rwork( & inde ), m, nsplit, w,iwork( indibl ), iwork( indisp ), rwork( indrwk ),iwork( indiwk ),& info ) if( wantz ) then call stdlib${ii}$_${ci}$stein( n, rwork( indd ), rwork( inde ), m, w,iwork( indibl ), iwork( & indisp ), z, ldz,rwork( indrwk ), iwork( indiwk ), ifail, info ) ! apply unitary matrix used in reduction to tridiagonal ! form to eigenvectors returned by stdlib${ii}$_${ci}$stein. indwrk = indtau + n call stdlib${ii}$_${ci}$upmtr( 'L', uplo, 'N', n, m, ap, work( indtau ), z, ldz,work( indwrk ),& iinfo ) end if ! if matrix was scaled, then rescale eigenvalues appropriately. 20 continue if( iscale==1_${ik}$ ) then if( info==0_${ik}$ ) then imax = m else imax = info - 1_${ik}$ end if call stdlib${ii}$_${c2ri(ci)}$scal( imax, one / sigma, w, 1_${ik}$ ) end if ! if eigenvalues are not in order, then sort them, along with ! eigenvectors. if( wantz ) then do j = 1, m - 1 i = 0_${ik}$ tmp1 = w( j ) do jj = j + 1, m if( w( jj )<tmp1 ) then i = jj tmp1 = w( jj ) end if end do if( i/=0_${ik}$ ) then itmp1 = iwork( indibl+i-1 ) w( i ) = w( j ) iwork( indibl+i-1 ) = iwork( indibl+j-1 ) w( j ) = tmp1 iwork( indibl+j-1 ) = itmp1 call stdlib${ii}$_${ci}$swap( n, z( 1_${ik}$, i ), 1_${ik}$, z( 1_${ik}$, j ), 1_${ik}$ ) if( info/=0_${ik}$ ) then itmp1 = ifail( i ) ifail( i ) = ifail( j ) ifail( j ) = itmp1 end if end if end do end if return end subroutine stdlib${ii}$_${ci}$hpevx #:endif #:endfor module subroutine stdlib${ii}$_chbev( jobz, uplo, n, kd, ab, ldab, w, z, ldz, work,rwork, info ) !! CHBEV computes all the eigenvalues and, optionally, eigenvectors of !! a complex Hermitian band matrix A. ! -- 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) :: jobz, uplo integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: kd, ldab, ldz, n ! Array Arguments real(sp), intent(out) :: rwork(*), w(*) complex(sp), intent(inout) :: ab(ldab,*) complex(sp), intent(out) :: work(*), z(ldz,*) ! ===================================================================== ! Local Scalars logical(lk) :: lower, wantz integer(${ik}$) :: iinfo, imax, inde, indrwk, iscale real(sp) :: anrm, bignum, eps, rmax, rmin, safmin, sigma, smlnum ! Intrinsic Functions ! Executable Statements ! test the input parameters. wantz = stdlib_lsame( jobz, 'V' ) lower = stdlib_lsame( uplo, 'L' ) info = 0_${ik}$ if( .not.( wantz .or. stdlib_lsame( jobz, 'N' ) ) ) then info = -1_${ik}$ else if( .not.( lower .or. stdlib_lsame( uplo, 'U' ) ) ) then info = -2_${ik}$ else if( n<0_${ik}$ ) then info = -3_${ik}$ else if( kd<0_${ik}$ ) then info = -4_${ik}$ else if( ldab<kd+1 ) then info = -6_${ik}$ else if( ldz<1_${ik}$ .or. ( wantz .and. ldz<n ) ) then info = -9_${ik}$ end if if( info/=0_${ik}$ ) then call stdlib${ii}$_xerbla( 'CHBEV ', -info ) return end if ! quick return if possible if( n==0 )return if( n==1_${ik}$ ) then if( lower ) then w( 1_${ik}$ ) = real( ab( 1_${ik}$, 1_${ik}$ ),KIND=sp) else w( 1_${ik}$ ) = real( ab( kd+1, 1_${ik}$ ),KIND=sp) end if if( wantz )z( 1_${ik}$, 1_${ik}$ ) = one return end if ! get machine constants. safmin = stdlib${ii}$_slamch( 'SAFE MINIMUM' ) eps = stdlib${ii}$_slamch( 'PRECISION' ) smlnum = safmin / eps bignum = one / smlnum rmin = sqrt( smlnum ) rmax = sqrt( bignum ) ! scale matrix to allowable range, if necessary. anrm = stdlib${ii}$_clanhb( 'M', uplo, n, kd, ab, ldab, rwork ) iscale = 0_${ik}$ if( anrm>zero .and. anrm<rmin ) then iscale = 1_${ik}$ sigma = rmin / anrm else if( anrm>rmax ) then iscale = 1_${ik}$ sigma = rmax / anrm end if if( iscale==1_${ik}$ ) then if( lower ) then call stdlib${ii}$_clascl( 'B', kd, kd, one, sigma, n, n, ab, ldab, info ) else call stdlib${ii}$_clascl( 'Q', kd, kd, one, sigma, n, n, ab, ldab, info ) end if end if ! call stdlib${ii}$_chbtrd to reduce hermitian band matrix to tridiagonal form. inde = 1_${ik}$ call stdlib${ii}$_chbtrd( jobz, uplo, n, kd, ab, ldab, w, rwork( inde ), z,ldz, work, iinfo ) ! for eigenvalues only, call stdlib${ii}$_ssterf. for eigenvectors, call stdlib${ii}$_csteqr. if( .not.wantz ) then call stdlib${ii}$_ssterf( n, w, rwork( inde ), info ) else indrwk = inde + n call stdlib${ii}$_csteqr( jobz, n, w, rwork( inde ), z, ldz,rwork( indrwk ), info ) end if ! if matrix was scaled, then rescale eigenvalues appropriately. if( iscale==1_${ik}$ ) then if( info==0_${ik}$ ) then imax = n else imax = info - 1_${ik}$ end if call stdlib${ii}$_sscal( imax, one / sigma, w, 1_${ik}$ ) end if return end subroutine stdlib${ii}$_chbev module subroutine stdlib${ii}$_zhbev( jobz, uplo, n, kd, ab, ldab, w, z, ldz, work,rwork, info ) !! ZHBEV computes all the eigenvalues and, optionally, eigenvectors of !! a complex Hermitian band matrix A. ! -- 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) :: jobz, uplo integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: kd, ldab, ldz, n ! Array Arguments real(dp), intent(out) :: rwork(*), w(*) complex(dp), intent(inout) :: ab(ldab,*) complex(dp), intent(out) :: work(*), z(ldz,*) ! ===================================================================== ! Local Scalars logical(lk) :: lower, wantz integer(${ik}$) :: iinfo, imax, inde, indrwk, iscale real(dp) :: anrm, bignum, eps, rmax, rmin, safmin, sigma, smlnum ! Intrinsic Functions ! Executable Statements ! test the input parameters. wantz = stdlib_lsame( jobz, 'V' ) lower = stdlib_lsame( uplo, 'L' ) info = 0_${ik}$ if( .not.( wantz .or. stdlib_lsame( jobz, 'N' ) ) ) then info = -1_${ik}$ else if( .not.( lower .or. stdlib_lsame( uplo, 'U' ) ) ) then info = -2_${ik}$ else if( n<0_${ik}$ ) then info = -3_${ik}$ else if( kd<0_${ik}$ ) then info = -4_${ik}$ else if( ldab<kd+1 ) then info = -6_${ik}$ else if( ldz<1_${ik}$ .or. ( wantz .and. ldz<n ) ) then info = -9_${ik}$ end if if( info/=0_${ik}$ ) then call stdlib${ii}$_xerbla( 'ZHBEV ', -info ) return end if ! quick return if possible if( n==0 )return if( n==1_${ik}$ ) then if( lower ) then w( 1_${ik}$ ) = real( ab( 1_${ik}$, 1_${ik}$ ),KIND=dp) else w( 1_${ik}$ ) = real( ab( kd+1, 1_${ik}$ ),KIND=dp) end if if( wantz )z( 1_${ik}$, 1_${ik}$ ) = one return end if ! get machine constants. safmin = stdlib${ii}$_dlamch( 'SAFE MINIMUM' ) eps = stdlib${ii}$_dlamch( 'PRECISION' ) smlnum = safmin / eps bignum = one / smlnum rmin = sqrt( smlnum ) rmax = sqrt( bignum ) ! scale matrix to allowable range, if necessary. anrm = stdlib${ii}$_zlanhb( 'M', uplo, n, kd, ab, ldab, rwork ) iscale = 0_${ik}$ if( anrm>zero .and. anrm<rmin ) then iscale = 1_${ik}$ sigma = rmin / anrm else if( anrm>rmax ) then iscale = 1_${ik}$ sigma = rmax / anrm end if if( iscale==1_${ik}$ ) then if( lower ) then call stdlib${ii}$_zlascl( 'B', kd, kd, one, sigma, n, n, ab, ldab, info ) else call stdlib${ii}$_zlascl( 'Q', kd, kd, one, sigma, n, n, ab, ldab, info ) end if end if ! call stdlib${ii}$_zhbtrd to reduce hermitian band matrix to tridiagonal form. inde = 1_${ik}$ call stdlib${ii}$_zhbtrd( jobz, uplo, n, kd, ab, ldab, w, rwork( inde ), z,ldz, work, iinfo ) ! for eigenvalues only, call stdlib${ii}$_dsterf. for eigenvectors, call stdlib${ii}$_zsteqr. if( .not.wantz ) then call stdlib${ii}$_dsterf( n, w, rwork( inde ), info ) else indrwk = inde + n call stdlib${ii}$_zsteqr( jobz, n, w, rwork( inde ), z, ldz,rwork( indrwk ), info ) end if ! if matrix was scaled, then rescale eigenvalues appropriately. if( iscale==1_${ik}$ ) then if( info==0_${ik}$ ) then imax = n else imax = info - 1_${ik}$ end if call stdlib${ii}$_dscal( imax, one / sigma, w, 1_${ik}$ ) end if return end subroutine stdlib${ii}$_zhbev #:for ck,ct,ci in CMPLX_KINDS_TYPES #:if not ck in ["sp","dp"] module subroutine stdlib${ii}$_${ci}$hbev( jobz, uplo, n, kd, ab, ldab, w, z, ldz, work,rwork, info ) !! ZHBEV: computes all the eigenvalues and, optionally, eigenvectors of !! a complex Hermitian band matrix A. ! -- 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) :: jobz, uplo integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: kd, ldab, ldz, n ! Array Arguments real(${ck}$), intent(out) :: rwork(*), w(*) complex(${ck}$), intent(inout) :: ab(ldab,*) complex(${ck}$), intent(out) :: work(*), z(ldz,*) ! ===================================================================== ! Local Scalars logical(lk) :: lower, wantz integer(${ik}$) :: iinfo, imax, inde, indrwk, iscale real(${ck}$) :: anrm, bignum, eps, rmax, rmin, safmin, sigma, smlnum ! Intrinsic Functions ! Executable Statements ! test the input parameters. wantz = stdlib_lsame( jobz, 'V' ) lower = stdlib_lsame( uplo, 'L' ) info = 0_${ik}$ if( .not.( wantz .or. stdlib_lsame( jobz, 'N' ) ) ) then info = -1_${ik}$ else if( .not.( lower .or. stdlib_lsame( uplo, 'U' ) ) ) then info = -2_${ik}$ else if( n<0_${ik}$ ) then info = -3_${ik}$ else if( kd<0_${ik}$ ) then info = -4_${ik}$ else if( ldab<kd+1 ) then info = -6_${ik}$ else if( ldz<1_${ik}$ .or. ( wantz .and. ldz<n ) ) then info = -9_${ik}$ end if if( info/=0_${ik}$ ) then call stdlib${ii}$_xerbla( 'ZHBEV ', -info ) return end if ! quick return if possible if( n==0 )return if( n==1_${ik}$ ) then if( lower ) then w( 1_${ik}$ ) = real( ab( 1_${ik}$, 1_${ik}$ ),KIND=${ck}$) else w( 1_${ik}$ ) = real( ab( kd+1, 1_${ik}$ ),KIND=${ck}$) end if if( wantz )z( 1_${ik}$, 1_${ik}$ ) = one return end if ! get machine constants. safmin = stdlib${ii}$_${c2ri(ci)}$lamch( 'SAFE MINIMUM' ) eps = stdlib${ii}$_${c2ri(ci)}$lamch( 'PRECISION' ) smlnum = safmin / eps bignum = one / smlnum rmin = sqrt( smlnum ) rmax = sqrt( bignum ) ! scale matrix to allowable range, if necessary. anrm = stdlib${ii}$_${ci}$lanhb( 'M', uplo, n, kd, ab, ldab, rwork ) iscale = 0_${ik}$ if( anrm>zero .and. anrm<rmin ) then iscale = 1_${ik}$ sigma = rmin / anrm else if( anrm>rmax ) then iscale = 1_${ik}$ sigma = rmax / anrm end if if( iscale==1_${ik}$ ) then if( lower ) then call stdlib${ii}$_${ci}$lascl( 'B', kd, kd, one, sigma, n, n, ab, ldab, info ) else call stdlib${ii}$_${ci}$lascl( 'Q', kd, kd, one, sigma, n, n, ab, ldab, info ) end if end if ! call stdlib${ii}$_${ci}$hbtrd to reduce hermitian band matrix to tridiagonal form. inde = 1_${ik}$ call stdlib${ii}$_${ci}$hbtrd( jobz, uplo, n, kd, ab, ldab, w, rwork( inde ), z,ldz, work, iinfo ) ! for eigenvalues only, call stdlib${ii}$_${c2ri(ci)}$sterf. for eigenvectors, call stdlib${ii}$_${ci}$steqr. if( .not.wantz ) then call stdlib${ii}$_${c2ri(ci)}$sterf( n, w, rwork( inde ), info ) else indrwk = inde + n call stdlib${ii}$_${ci}$steqr( jobz, n, w, rwork( inde ), z, ldz,rwork( indrwk ), info ) end if ! if matrix was scaled, then rescale eigenvalues appropriately. if( iscale==1_${ik}$ ) then if( info==0_${ik}$ ) then imax = n else imax = info - 1_${ik}$ end if call stdlib${ii}$_${c2ri(ci)}$scal( imax, one / sigma, w, 1_${ik}$ ) end if return end subroutine stdlib${ii}$_${ci}$hbev #:endif #:endfor module subroutine stdlib${ii}$_chbevd( jobz, uplo, n, kd, ab, ldab, w, z, ldz, work,lwork, rwork, lrwork, & !! CHBEVD computes all the eigenvalues and, optionally, eigenvectors of !! a complex Hermitian band matrix A. If eigenvectors are desired, it !! uses a divide and conquer algorithm. !! The divide and conquer algorithm makes very mild assumptions about !! floating point arithmetic. It will work on machines with a guard !! digit in add/subtract, or on those binary machines without guard !! digits which subtract like the Cray X-MP, Cray Y-MP, Cray C-90, or !! Cray-2. It could conceivably fail on hexadecimal or decimal machines !! without guard digits, but we know of none. iwork, liwork, 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) :: jobz, uplo integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: kd, ldab, ldz, liwork, lrwork, lwork, n ! Array Arguments integer(${ik}$), intent(out) :: iwork(*) real(sp), intent(out) :: rwork(*), w(*) complex(sp), intent(inout) :: ab(ldab,*) complex(sp), intent(out) :: work(*), z(ldz,*) ! ===================================================================== ! Local Scalars logical(lk) :: lower, lquery, wantz integer(${ik}$) :: iinfo, imax, inde, indwk2, indwrk, iscale, liwmin, llrwk, llwk2, & lrwmin, lwmin real(sp) :: anrm, bignum, eps, rmax, rmin, safmin, sigma, smlnum ! Intrinsic Functions ! Executable Statements ! test the input parameters. wantz = stdlib_lsame( jobz, 'V' ) lower = stdlib_lsame( uplo, 'L' ) lquery = ( lwork==-1_${ik}$ .or. liwork==-1_${ik}$ .or. lrwork==-1_${ik}$ ) info = 0_${ik}$ if( n<=1_${ik}$ ) then lwmin = 1_${ik}$ lrwmin = 1_${ik}$ liwmin = 1_${ik}$ else if( wantz ) then lwmin = 2_${ik}$*n**2_${ik}$ lrwmin = 1_${ik}$ + 5_${ik}$*n + 2_${ik}$*n**2_${ik}$ liwmin = 3_${ik}$ + 5_${ik}$*n else lwmin = n lrwmin = n liwmin = 1_${ik}$ end if end if if( .not.( wantz .or. stdlib_lsame( jobz, 'N' ) ) ) then info = -1_${ik}$ else if( .not.( lower .or. stdlib_lsame( uplo, 'U' ) ) ) then info = -2_${ik}$ else if( n<0_${ik}$ ) then info = -3_${ik}$ else if( kd<0_${ik}$ ) then info = -4_${ik}$ else if( ldab<kd+1 ) then info = -6_${ik}$ else if( ldz<1_${ik}$ .or. ( wantz .and. ldz<n ) ) then info = -9_${ik}$ end if if( info==0_${ik}$ ) then work( 1_${ik}$ ) = lwmin rwork( 1_${ik}$ ) = lrwmin iwork( 1_${ik}$ ) = liwmin if( lwork<lwmin .and. .not.lquery ) then info = -11_${ik}$ else if( lrwork<lrwmin .and. .not.lquery ) then info = -13_${ik}$ else if( liwork<liwmin .and. .not.lquery ) then info = -15_${ik}$ end if end if if( info/=0_${ik}$ ) then call stdlib${ii}$_xerbla( 'CHBEVD', -info ) return else if( lquery ) then return end if ! quick return if possible if( n==0 )return if( n==1_${ik}$ ) then w( 1_${ik}$ ) = real( ab( 1_${ik}$, 1_${ik}$ ),KIND=sp) if( wantz )z( 1_${ik}$, 1_${ik}$ ) = cone return end if ! get machine constants. safmin = stdlib${ii}$_slamch( 'SAFE MINIMUM' ) eps = stdlib${ii}$_slamch( 'PRECISION' ) smlnum = safmin / eps bignum = one / smlnum rmin = sqrt( smlnum ) rmax = sqrt( bignum ) ! scale matrix to allowable range, if necessary. anrm = stdlib${ii}$_clanhb( 'M', uplo, n, kd, ab, ldab, rwork ) iscale = 0_${ik}$ if( anrm>zero .and. anrm<rmin ) then iscale = 1_${ik}$ sigma = rmin / anrm else if( anrm>rmax ) then iscale = 1_${ik}$ sigma = rmax / anrm end if if( iscale==1_${ik}$ ) then if( lower ) then call stdlib${ii}$_clascl( 'B', kd, kd, one, sigma, n, n, ab, ldab, info ) else call stdlib${ii}$_clascl( 'Q', kd, kd, one, sigma, n, n, ab, ldab, info ) end if end if ! call stdlib${ii}$_chbtrd to reduce hermitian band matrix to tridiagonal form. inde = 1_${ik}$ indwrk = inde + n indwk2 = 1_${ik}$ + n*n llwk2 = lwork - indwk2 + 1_${ik}$ llrwk = lrwork - indwrk + 1_${ik}$ call stdlib${ii}$_chbtrd( jobz, uplo, n, kd, ab, ldab, w, rwork( inde ), z,ldz, work, iinfo ) ! for eigenvalues only, call stdlib${ii}$_ssterf. for eigenvectors, call stdlib${ii}$_cstedc. if( .not.wantz ) then call stdlib${ii}$_ssterf( n, w, rwork( inde ), info ) else call stdlib${ii}$_cstedc( 'I', n, w, rwork( inde ), work, n, work( indwk2 ),llwk2, rwork( & indwrk ), llrwk, iwork, liwork,info ) call stdlib${ii}$_cgemm( 'N', 'N', n, n, n, cone, z, ldz, work, n, czero,work( indwk2 ), & n ) call stdlib${ii}$_clacpy( 'A', n, n, work( indwk2 ), n, z, ldz ) end if ! if matrix was scaled, then rescale eigenvalues appropriately. if( iscale==1_${ik}$ ) then if( info==0_${ik}$ ) then imax = n else imax = info - 1_${ik}$ end if call stdlib${ii}$_sscal( imax, one / sigma, w, 1_${ik}$ ) end if work( 1_${ik}$ ) = lwmin rwork( 1_${ik}$ ) = lrwmin iwork( 1_${ik}$ ) = liwmin return end subroutine stdlib${ii}$_chbevd module subroutine stdlib${ii}$_zhbevd( jobz, uplo, n, kd, ab, ldab, w, z, ldz, work,lwork, rwork, lrwork, & !! ZHBEVD computes all the eigenvalues and, optionally, eigenvectors of !! a complex Hermitian band matrix A. If eigenvectors are desired, it !! uses a divide and conquer algorithm. !! The divide and conquer algorithm makes very mild assumptions about !! floating point arithmetic. It will work on machines with a guard !! digit in add/subtract, or on those binary machines without guard !! digits which subtract like the Cray X-MP, Cray Y-MP, Cray C-90, or !! Cray-2. It could conceivably fail on hexadecimal or decimal machines !! without guard digits, but we know of none. iwork, liwork, 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) :: jobz, uplo integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: kd, ldab, ldz, liwork, lrwork, lwork, n ! Array Arguments integer(${ik}$), intent(out) :: iwork(*) real(dp), intent(out) :: rwork(*), w(*) complex(dp), intent(inout) :: ab(ldab,*) complex(dp), intent(out) :: work(*), z(ldz,*) ! ===================================================================== ! Local Scalars logical(lk) :: lower, lquery, wantz integer(${ik}$) :: iinfo, imax, inde, indwk2, indwrk, iscale, liwmin, llrwk, llwk2, & lrwmin, lwmin real(dp) :: anrm, bignum, eps, rmax, rmin, safmin, sigma, smlnum ! Intrinsic Functions ! Executable Statements ! test the input parameters. wantz = stdlib_lsame( jobz, 'V' ) lower = stdlib_lsame( uplo, 'L' ) lquery = ( lwork==-1_${ik}$ .or. liwork==-1_${ik}$ .or. lrwork==-1_${ik}$ ) info = 0_${ik}$ if( n<=1_${ik}$ ) then lwmin = 1_${ik}$ lrwmin = 1_${ik}$ liwmin = 1_${ik}$ else if( wantz ) then lwmin = 2_${ik}$*n**2_${ik}$ lrwmin = 1_${ik}$ + 5_${ik}$*n + 2_${ik}$*n**2_${ik}$ liwmin = 3_${ik}$ + 5_${ik}$*n else lwmin = n lrwmin = n liwmin = 1_${ik}$ end if end if if( .not.( wantz .or. stdlib_lsame( jobz, 'N' ) ) ) then info = -1_${ik}$ else if( .not.( lower .or. stdlib_lsame( uplo, 'U' ) ) ) then info = -2_${ik}$ else if( n<0_${ik}$ ) then info = -3_${ik}$ else if( kd<0_${ik}$ ) then info = -4_${ik}$ else if( ldab<kd+1 ) then info = -6_${ik}$ else if( ldz<1_${ik}$ .or. ( wantz .and. ldz<n ) ) then info = -9_${ik}$ end if if( info==0_${ik}$ ) then work( 1_${ik}$ ) = lwmin rwork( 1_${ik}$ ) = lrwmin iwork( 1_${ik}$ ) = liwmin if( lwork<lwmin .and. .not.lquery ) then info = -11_${ik}$ else if( lrwork<lrwmin .and. .not.lquery ) then info = -13_${ik}$ else if( liwork<liwmin .and. .not.lquery ) then info = -15_${ik}$ end if end if if( info/=0_${ik}$ ) then call stdlib${ii}$_xerbla( 'ZHBEVD', -info ) return else if( lquery ) then return end if ! quick return if possible if( n==0 )return if( n==1_${ik}$ ) then w( 1_${ik}$ ) = real( ab( 1_${ik}$, 1_${ik}$ ),KIND=dp) if( wantz )z( 1_${ik}$, 1_${ik}$ ) = cone return end if ! get machine constants. safmin = stdlib${ii}$_dlamch( 'SAFE MINIMUM' ) eps = stdlib${ii}$_dlamch( 'PRECISION' ) smlnum = safmin / eps bignum = one / smlnum rmin = sqrt( smlnum ) rmax = sqrt( bignum ) ! scale matrix to allowable range, if necessary. anrm = stdlib${ii}$_zlanhb( 'M', uplo, n, kd, ab, ldab, rwork ) iscale = 0_${ik}$ if( anrm>zero .and. anrm<rmin ) then iscale = 1_${ik}$ sigma = rmin / anrm else if( anrm>rmax ) then iscale = 1_${ik}$ sigma = rmax / anrm end if if( iscale==1_${ik}$ ) then if( lower ) then call stdlib${ii}$_zlascl( 'B', kd, kd, one, sigma, n, n, ab, ldab, info ) else call stdlib${ii}$_zlascl( 'Q', kd, kd, one, sigma, n, n, ab, ldab, info ) end if end if ! call stdlib${ii}$_zhbtrd to reduce hermitian band matrix to tridiagonal form. inde = 1_${ik}$ indwrk = inde + n indwk2 = 1_${ik}$ + n*n llwk2 = lwork - indwk2 + 1_${ik}$ llrwk = lrwork - indwrk + 1_${ik}$ call stdlib${ii}$_zhbtrd( jobz, uplo, n, kd, ab, ldab, w, rwork( inde ), z,ldz, work, iinfo ) ! for eigenvalues only, call stdlib${ii}$_dsterf. for eigenvectors, call stdlib${ii}$_zstedc. if( .not.wantz ) then call stdlib${ii}$_dsterf( n, w, rwork( inde ), info ) else call stdlib${ii}$_zstedc( 'I', n, w, rwork( inde ), work, n, work( indwk2 ),llwk2, rwork( & indwrk ), llrwk, iwork, liwork,info ) call stdlib${ii}$_zgemm( 'N', 'N', n, n, n, cone, z, ldz, work, n, czero,work( indwk2 ), & n ) call stdlib${ii}$_zlacpy( 'A', n, n, work( indwk2 ), n, z, ldz ) end if ! if matrix was scaled, then rescale eigenvalues appropriately. if( iscale==1_${ik}$ ) then if( info==0_${ik}$ ) then imax = n else imax = info - 1_${ik}$ end if call stdlib${ii}$_dscal( imax, one / sigma, w, 1_${ik}$ ) end if work( 1_${ik}$ ) = lwmin rwork( 1_${ik}$ ) = lrwmin iwork( 1_${ik}$ ) = liwmin return end subroutine stdlib${ii}$_zhbevd #:for ck,ct,ci in CMPLX_KINDS_TYPES #:if not ck in ["sp","dp"] module subroutine stdlib${ii}$_${ci}$hbevd( jobz, uplo, n, kd, ab, ldab, w, z, ldz, work,lwork, rwork, lrwork, & !! ZHBEVD: computes all the eigenvalues and, optionally, eigenvectors of !! a complex Hermitian band matrix A. If eigenvectors are desired, it !! uses a divide and conquer algorithm. !! The divide and conquer algorithm makes very mild assumptions about !! floating point arithmetic. It will work on machines with a guard !! digit in add/subtract, or on those binary machines without guard !! digits which subtract like the Cray X-MP, Cray Y-MP, Cray C-90, or !! Cray-2. It could conceivably fail on hexadecimal or decimal machines !! without guard digits, but we know of none. iwork, liwork, 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) :: jobz, uplo integer(${ik}$), intent(out) :: info integer(${ik}$), intent(in) :: kd, ldab, ldz, liwork, lrwork, lwork, n ! Array Arguments integer(${ik}$), intent(out) :: iwork(*) real(${ck}$), intent(out) :: rwork(*), w(*) complex(${ck}$), intent(inout) :: ab(ldab,*) complex(${ck}$), intent(out) :: work(*), z(ldz,*) ! ===================================================================== ! Local Scalars logical(lk) :: lower, lquery, wantz integer(${ik}$) :: iinfo, imax, inde, indwk2, indwrk, iscale, liwmin, llrwk, llwk2, & lrwmin, lwmin real(${ck}$) :: anrm, bignum, eps, rmax, rmin, safmin, sigma, smlnum ! Intrinsic Functions ! Executable Statements ! test the input parameters. wantz = stdlib_lsame( jobz, 'V' ) lower = stdlib_lsame( uplo, 'L' ) lquery = ( lwork==-1_${ik}$ .or. liwork==-1_${ik}$ .or. lrwork==-1_${ik}$ ) info = 0_${ik}$ if( n<=1_${ik}$ ) then lwmin = 1_${ik}$ lrwmin = 1_${ik}$ liwmin = 1_${ik}$ else if( wantz ) then lwmin = 2_${ik}$*n**2_${ik}$ lrwmin = 1_${ik}$ + 5_${ik}$*n + 2_${ik}$*n**2_${ik}$ liwmin = 3_${ik}$ + 5_${ik}$*n else lwmin = n lrwmin = n liwmin = 1_${ik}$ end if end if if( .not.( wantz .or. stdlib_lsame( jobz, 'N' ) ) ) then info = -1_${ik}$ else if( .not.( lower .or. stdlib_lsame( uplo, 'U' ) ) ) then info = -2_${ik}$ else if( n<0_${ik}$ ) then info = -3_${ik}$ else if( kd<0_${ik}$ ) then info = -4_${ik}$ else if( ldab<kd+1 ) then info = -6_${ik}$ else if( ldz<1_${ik}$ .or. ( wantz .and. ldz<n ) ) then info = -9_${ik}$ end if if( info==0_${ik}$ ) then work( 1_${ik}$ ) = lwmin rwork( 1_${ik}$ ) = lrwmin iwork( 1_${ik}$ ) = liwmin if( lwork<lwmin .and. .not.lquery ) then info = -11_${ik}$ else if( lrwork<lrwmin .and. .not.lquery ) then info = -13_${ik}$ else if( liwork<liwmin .and. .not.lquery ) then info = -15_${ik}$ end if end if if( info/=0_${ik}$ ) then call stdlib${ii}$_xerbla( 'ZHBEVD', -info ) return else if( lquery ) then return end if ! quick return if possible if( n==0 )return if( n==1_${ik}$ ) then w( 1_${ik}$ ) = real( ab( 1_${ik}$, 1_${ik}$ ),KIND=${ck}$) if( wantz )z( 1_${ik}$, 1_${ik}$ ) = cone return end if ! get machine constants. safmin = stdlib${ii}$_${c2ri(ci)}$lamch( 'SAFE MINIMUM' ) eps = stdlib${ii}$_${c2ri(ci)}$lamch( 'PRECISION' ) smlnum = safmin / eps bignum = one / smlnum rmin = sqrt( smlnum ) rmax = sqrt( bignum ) ! scale matrix to allowable range, if necessary. anrm = stdlib${ii}$_${ci}$lanhb( 'M', uplo, n, kd, ab, ldab, rwork ) iscale = 0_${ik}$ if( anrm>zero .and. anrm<rmin ) then iscale = 1_${ik}$ sigma = rmin / anrm else if( anrm>rmax ) then iscale = 1_${ik}$ sigma = rmax / anrm end if if( iscale==1_${ik}$ ) then if( lower ) then call stdlib${ii}$_${ci}$lascl( 'B', kd, kd, one, sigma, n, n, ab, ldab, info ) else call stdlib${ii}$_${ci}$lascl( 'Q', kd, kd, one, sigma, n, n, ab, ldab, info ) end if end if ! call stdlib${ii}$_${ci}$hbtrd to reduce hermitian band matrix to tridiagonal form. inde = 1_${ik}$ indwrk = inde + n indwk2 = 1_${ik}$ + n*n llwk2 = lwork - indwk2 + 1_${ik}$ llrwk = lrwork - indwrk + 1_${ik}$ call stdlib${ii}$_${ci}$hbtrd( jobz, uplo, n, kd, ab, ldab, w, rwork( inde ), z,ldz, work, iinfo ) ! for eigenvalues only, call stdlib${ii}$_${c2ri(ci)}$sterf. for eigenvectors, call stdlib${ii}$_${ci}$stedc. if( .not.wantz ) then call stdlib${ii}$_${c2ri(ci)}$sterf( n, w, rwork( inde ), info ) else call stdlib${ii}$_${ci}$stedc( 'I', n, w, rwork( inde ), work, n, work( indwk2 ),llwk2, rwork( & indwrk ), llrwk, iwork, liwork,info ) call stdlib${ii}$_${ci}$gemm( 'N', 'N', n, n, n, cone, z, ldz, work, n, czero,work( indwk2 ), & n ) call stdlib${ii}$_${ci}$lacpy( 'A', n, n, work( indwk2 ), n, z, ldz ) end if ! if matrix was scaled, then rescale eigenvalues appropriately. if( iscale==1_${ik}$ ) then if( info==0_${ik}$ ) then imax = n else imax = info - 1_${ik}$ end if call stdlib${ii}$_${c2ri(ci)}$scal( imax, one / sigma, w, 1_${ik}$ ) end if work( 1_${ik}$ ) = lwmin rwork( 1_${ik}$ ) = lrwmin iwork( 1_${ik}$ ) = liwmin return end subroutine stdlib${ii}$_${ci}$hbevd #:endif #:endfor module subroutine stdlib${ii}$_chbevx( jobz, range, uplo, n, kd, ab, ldab, q, ldq, vl,vu, il, iu, abstol, & !! CHBEVX computes selected eigenvalues and, optionally, eigenvectors !! of a complex Hermitian band matrix A. Eigenvalues and eigenvectors !! can be selected by specifying either a range of values or a range of !! indices for the desired eigenvalues. m, w, z, ldz, work, rwork,iwork, ifail, 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) :: jobz, range, uplo integer(${ik}$), intent(in) :: il, iu, kd, ldab, ldq, ldz, n integer(${ik}$), intent(out) :: info, m real(sp), intent(in) :: abstol, vl, vu ! Array Arguments integer(${ik}$), intent(out) :: ifail(*), iwork(*) real(sp), intent(out) :: rwork(*), w(*) complex(sp), intent(inout) :: ab(ldab,*) complex(sp), intent(out) :: q(ldq,*), work(*), z(ldz,*) ! ===================================================================== ! Local Scalars logical(lk) :: alleig, indeig, lower, test, valeig, wantz character :: order integer(${ik}$) :: i, iinfo, imax, indd, inde, indee, indibl, indisp, indiwk, indrwk, & indwrk, iscale, itmp1, j, jj, nsplit real(sp) :: abstll, anrm, bignum, eps, rmax, rmin, safmin, sigma, smlnum, tmp1, vll, & vuu complex(sp) :: ctmp1 ! Intrinsic Functions ! Executable Statements ! test the input parameters. wantz = stdlib_lsame( jobz, 'V' ) alleig = stdlib_lsame( range, 'A' ) valeig = stdlib_lsame( range, 'V' ) indeig = stdlib_lsame( range, 'I' ) lower = stdlib_lsame( uplo, 'L' ) info = 0_${ik}$ if( .not.( wantz .or. stdlib_lsame( jobz, 'N' ) ) ) then info = -1_${ik}$ else if( .not.( alleig .or. valeig .or. indeig ) ) then info = -2_${ik}$ else if( .not.( lower .or. stdlib_lsame( uplo, 'U' ) ) ) then info = -3_${ik}$ else if( n<0_${ik}$ ) then info = -4_${ik}$ else if( kd<0_${ik}$ ) then info = -5_${ik}$ else if( ldab<kd+1 ) then info = -7_${ik}$ else if( wantz .and. ldq<max( 1_${ik}$, n ) ) then info = -9_${ik}$ else if( valeig ) then if( n>0_${ik}$ .and. vu<=vl )info = -11_${ik}$ else if( indeig ) then if( il<1_${ik}$ .or. il>max( 1_${ik}$, n ) ) then info = -12_${ik}$ else if( iu<min( n, il ) .or. iu>n ) then info = -13_${ik}$ end if end if end if if( info==0_${ik}$ ) then if( ldz<1_${ik}$ .or. ( wantz .and. ldz<n ) )info = -18_${ik}$ end if if( info/=0_${ik}$ ) then call stdlib${ii}$_xerbla( 'CHBEVX', -info ) return end if ! quick return if possible m = 0_${ik}$ if( n==0 )return if( n==1_${ik}$ ) then m = 1_${ik}$ if( lower ) then ctmp1 = ab( 1_${ik}$, 1_${ik}$ ) else ctmp1 = ab( kd+1, 1_${ik}$ ) end if tmp1 = real( ctmp1,KIND=sp) if( valeig ) then if( .not.( vl<tmp1 .and. vu>=tmp1 ) )m = 0_${ik}$ end if if( m==1_${ik}$ ) then w( 1_${ik}$ ) = real( ctmp1,KIND=sp) if( wantz )z( 1_${ik}$, 1_${ik}$ ) = cone end if return end if ! get machine constants. safmin = stdlib${ii}$_slamch( 'SAFE MINIMUM' ) eps = stdlib${ii}$_slamch( 'PRECISION' ) smlnum = safmin / eps bignum = one / smlnum rmin = sqrt( smlnum ) rmax = min( sqrt( bignum ), one / sqrt( sqrt( safmin ) ) ) ! scale matrix to allowable range, if necessary. iscale = 0_${ik}$ abstll = abstol if ( valeig ) then vll = vl vuu = vu else vll = zero vuu = zero endif anrm = stdlib${ii}$_clanhb( 'M', uplo, n, kd, ab, ldab, rwork ) if( anrm>zero .and. anrm<rmin ) then iscale = 1_${ik}$ sigma = rmin / anrm else if( anrm>rmax ) then iscale = 1_${ik}$ sigma = rmax / anrm end if if( iscale==1_${ik}$ ) then if( lower ) then call stdlib${ii}$_clascl( 'B', kd, kd, one, sigma, n, n, ab, ldab, info ) else call stdlib${ii}$_clascl( 'Q', kd, kd, one, sigma, n, n, ab, ldab, info ) end if if( abstol>0_${ik}$ )abstll = abstol*sigma if( valeig ) then vll = vl*sigma vuu = vu*sigma end if end if ! call stdlib${ii}$_chbtrd to reduce hermitian band matrix to tridiagonal form. indd = 1_${ik}$ inde = indd + n indrwk = inde + n indwrk = 1_${ik}$ call stdlib${ii}$_chbtrd( jobz, uplo, n, kd, ab, ldab, rwork( indd ),rwork( inde ), q, ldq, & work( indwrk ), iinfo ) ! if all eigenvalues are desired and abstol is less than or equal ! to zero, then call stdlib${ii}$_ssterf or stdlib${ii}$_csteqr. if this fails for some ! eigenvalue, then try stdlib${ii}$_sstebz. test = .false. if (indeig) then if (il==1_${ik}$ .and. iu==n) then test = .true. end if end if if ((alleig .or. test) .and. (abstol<=zero)) then call stdlib${ii}$_scopy( n, rwork( indd ), 1_${ik}$, w, 1_${ik}$ ) indee = indrwk + 2_${ik}$*n if( .not.wantz ) then call stdlib${ii}$_scopy( n-1, rwork( inde ), 1_${ik}$, rwork( indee ), 1_${ik}$ ) call stdlib${ii}$_ssterf( n, w, rwork( indee ), info ) else call stdlib${ii}$_clacpy( 'A', n, n, q, ldq, z, ldz ) call stdlib${ii}$_scopy( n-1, rwork( inde ), 1_${ik}$, rwork( indee ), 1_${ik}$ ) call stdlib${ii}$_csteqr( jobz, n, w, rwork( indee ), z, ldz,rwork( indrwk ), info ) if( info==0_${ik}$ ) then do i = 1, n ifail( i ) = 0_${ik}$ end do end if end if if( info==0_${ik}$ ) then m = n go to 30 end if info = 0_${ik}$ end if ! otherwise, call stdlib${ii}$_sstebz and, if eigenvectors are desired, stdlib${ii}$_cstein. if( wantz ) then order = 'B' else order = 'E' end if indibl = 1_${ik}$ indisp = indibl + n indiwk = indisp + n call stdlib${ii}$_sstebz( range, order, n, vll, vuu, il, iu, abstll,rwork( indd ), rwork( & inde ), m, nsplit, w,iwork( indibl ), iwork( indisp ), rwork( indrwk ),iwork( indiwk ),& info ) if( wantz ) then call stdlib${ii}$_cstein( n, rwork( indd ), rwork( inde ), m, w,iwork( indibl ), iwork( & indisp ), z, ldz,rwork( indrwk ), iwork( indiwk ), ifail, info ) ! apply unitary matrix used in reduction to tridiagonal ! form to eigenvectors returned by stdlib${ii}$_cstein. do j = 1, m call stdlib${ii}$_ccopy( n, z( 1_${ik}$, j ), 1_${ik}$, work( 1_${ik}$ ), 1_${ik}$ ) call stdlib${ii}$_cgemv( 'N', n, n, cone, q, ldq, work, 1_${ik}$, czero,z( 1_${ik}$, j ), 1_${ik}$ ) end do end if ! if matrix was scaled, then rescale eigenvalues appropriately. 30 continue if( iscale==1_${ik}$ ) then if( info==0_${ik}$ ) then imax = m else imax = info - 1_${ik}$ end if call stdlib${ii}$_sscal( imax, one / sigma, w, 1_${ik}$ ) end if ! if eigenvalues are not in order, then sort them, along with ! eigenvectors. if( wantz ) then do j = 1, m - 1 i = 0_${ik}$ tmp1 = w( j ) do jj = j + 1, m if( w( jj )<tmp1 ) then i = jj tmp1 = w( jj ) end if end do if( i/=0_${ik}$ ) then itmp1 = iwork( indibl+i-1 ) w( i ) = w( j ) iwork( indibl+i-1 ) = iwork( indibl+j-1 ) w( j ) = tmp1 iwork( indibl+j-1 ) = itmp1 call stdlib${ii}$_cswap( n, z( 1_${ik}$, i ), 1_${ik}$, z( 1_${ik}$, j ), 1_${ik}$ ) if( info/=0_${ik}$ ) then itmp1 = ifail( i ) ifail( i ) = ifail( j ) ifail( j ) = itmp1 end if end if end do end if return end subroutine stdlib${ii}$_chbevx module subroutine stdlib${ii}$_zhbevx( jobz, range, uplo, n, kd, ab, ldab, q, ldq, vl,vu, il, iu, abstol, & !! ZHBEVX computes selected eigenvalues and, optionally, eigenvectors !! of a complex Hermitian band matrix A. Eigenvalues and eigenvectors !! can be selected by specifying either a range of values or a range of !! indices for the desired eigenvalues. m, w, z, ldz, work, rwork,iwork, ifail, 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) :: jobz, range, uplo integer(${ik}$), intent(in) :: il, iu, kd, ldab, ldq, ldz, n integer(${ik}$), intent(out) :: info, m real(dp), intent(in) :: abstol, vl, vu ! Array Arguments integer(${ik}$), intent(out) :: ifail(*), iwork(*) real(dp), intent(out) :: rwork(*), w(*) complex(dp), intent(inout) :: ab(ldab,*) complex(dp), intent(out) :: q(ldq,*), work(*), z(ldz,*) ! ===================================================================== ! Local Scalars logical(lk) :: alleig, indeig, lower, test, valeig, wantz character :: order integer(${ik}$) :: i, iinfo, imax, indd, inde, indee, indibl, indisp, indiwk, indrwk, & indwrk, iscale, itmp1, j, jj, nsplit real(dp) :: abstll, anrm, bignum, eps, rmax, rmin, safmin, sigma, smlnum, tmp1, vll, & vuu complex(dp) :: ctmp1 ! Intrinsic Functions ! Executable Statements ! test the input parameters. wantz = stdlib_lsame( jobz, 'V' ) alleig = stdlib_lsame( range, 'A' ) valeig = stdlib_lsame( range, 'V' ) indeig = stdlib_lsame( range, 'I' ) lower = stdlib_lsame( uplo, 'L' ) info = 0_${ik}$ if( .not.( wantz .or. stdlib_lsame( jobz, 'N' ) ) ) then info = -1_${ik}$ else if( .not.( alleig .or. valeig .or. indeig ) ) then info = -2_${ik}$ else if( .not.( lower .or. stdlib_lsame( uplo, 'U' ) ) ) then info = -3_${ik}$ else if( n<0_${ik}$ ) then info = -4_${ik}$ else if( kd<0_${ik}$ ) then info = -5_${ik}$ else if( ldab<kd+1 ) then info = -7_${ik}$ else if( wantz .and. ldq<max( 1_${ik}$, n ) ) then info = -9_${ik}$ else if( valeig ) then if( n>0_${ik}$ .and. vu<=vl )info = -11_${ik}$ else if( indeig ) then if( il<1_${ik}$ .or. il>max( 1_${ik}$, n ) ) then info = -12_${ik}$ else if( iu<min( n, il ) .or. iu>n ) then info = -13_${ik}$ end if end if end if if( info==0_${ik}$ ) then if( ldz<1_${ik}$ .or. ( wantz .and. ldz<n ) )info = -18_${ik}$ end if if( info/=0_${ik}$ ) then call stdlib${ii}$_xerbla( 'ZHBEVX', -info ) return end if ! quick return if possible m = 0_${ik}$ if( n==0 )return if( n==1_${ik}$ ) then m = 1_${ik}$ if( lower ) then ctmp1 = ab( 1_${ik}$, 1_${ik}$ ) else ctmp1 = ab( kd+1, 1_${ik}$ ) end if tmp1 = real( ctmp1,KIND=dp) if( valeig ) then if( .not.( vl<tmp1 .and. vu>=tmp1 ) )m = 0_${ik}$ end if if( m==1_${ik}$ ) then w( 1_${ik}$ ) = real( ctmp1,KIND=dp) if( wantz )z( 1_${ik}$, 1_${ik}$ ) = cone end if return end if ! get machine constants. safmin = stdlib${ii}$_dlamch( 'SAFE MINIMUM' ) eps = stdlib${ii}$_dlamch( 'PRECISION' ) smlnum = safmin / eps bignum = one / smlnum rmin = sqrt( smlnum ) rmax = min( sqrt( bignum ), one / sqrt( sqrt( safmin ) ) ) ! scale matrix to allowable range, if necessary. iscale = 0_${ik}$ abstll = abstol if( valeig ) then vll = vl vuu = vu else vll = zero vuu = zero end if anrm = stdlib${ii}$_zlanhb( 'M', uplo, n, kd, ab, ldab, rwork ) if( anrm>zero .and. anrm<rmin ) then iscale = 1_${ik}$ sigma = rmin / anrm else if( anrm>rmax ) then iscale = 1_${ik}$ sigma = rmax / anrm end if if( iscale==1_${ik}$ ) then if( lower ) then call stdlib${ii}$_zlascl( 'B', kd, kd, one, sigma, n, n, ab, ldab, info ) else call stdlib${ii}$_zlascl( 'Q', kd, kd, one, sigma, n, n, ab, ldab, info ) end if if( abstol>0_${ik}$ )abstll = abstol*sigma if( valeig ) then vll = vl*sigma vuu = vu*sigma end if end if ! call stdlib${ii}$_zhbtrd to reduce hermitian band matrix to tridiagonal form. indd = 1_${ik}$ inde = indd + n indrwk = inde + n indwrk = 1_${ik}$ call stdlib${ii}$_zhbtrd( jobz, uplo, n, kd, ab, ldab, rwork( indd ),rwork( inde ), q, ldq, & work( indwrk ), iinfo ) ! if all eigenvalues are desired and abstol is less than or equal ! to zero, then call stdlib${ii}$_dsterf or stdlib${ii}$_zsteqr. if this fails for some ! eigenvalue, then try stdlib${ii}$_dstebz. test = .false. if (indeig) then if (il==1_${ik}$ .and. iu==n) then test = .true. end if end if if ((alleig .or. test) .and. (abstol<=zero)) then call stdlib${ii}$_dcopy( n, rwork( indd ), 1_${ik}$, w, 1_${ik}$ ) indee = indrwk + 2_${ik}$*n if( .not.wantz ) then call stdlib${ii}$_dcopy( n-1, rwork( inde ), 1_${ik}$, rwork( indee ), 1_${ik}$ ) call stdlib${ii}$_dsterf( n, w, rwork( indee ), info ) else call stdlib${ii}$_zlacpy( 'A', n, n, q, ldq, z, ldz ) call stdlib${ii}$_dcopy( n-1, rwork( inde ), 1_${ik}$, rwork( indee ), 1_${ik}$ ) call stdlib${ii}$_zsteqr( jobz, n, w, rwork( indee ), z, ldz,rwork( indrwk ), info ) if( info==0_${ik}$ ) then do i = 1, n ifail( i ) = 0_${ik}$ end do end if end if if( info==0_${ik}$ ) then m = n go to 30 end if info = 0_${ik}$ end if ! otherwise, call stdlib${ii}$_dstebz and, if eigenvectors are desired, stdlib${ii}$_zstein. if( wantz ) then order = 'B' else order = 'E' end if indibl = 1_${ik}$ indisp = indibl + n indiwk = indisp + n call stdlib${ii}$_dstebz( range, order, n, vll, vuu, il, iu, abstll,rwork( indd ), rwork( & inde ), m, nsplit, w,iwork( indibl ), iwork( indisp ), rwork( indrwk ),iwork( indiwk ),& info ) if( wantz ) then call stdlib${ii}$_zstein( n, rwork( indd ), rwork( inde ), m, w,iwork( indibl ), iwork( & indisp ), z, ldz,rwork( indrwk ), iwork( indiwk ), ifail, info ) ! apply unitary matrix used in reduction to tridiagonal ! form to eigenvectors returned by stdlib${ii}$_zstein. do j = 1, m call stdlib${ii}$_zcopy( n, z( 1_${ik}$, j ), 1_${ik}$, work( 1_${ik}$ ), 1_${ik}$ ) call stdlib${ii}$_zgemv( 'N', n, n, cone, q, ldq, work, 1_${ik}$, czero,z( 1_${ik}$, j ), 1_${ik}$ ) end do end if ! if matrix was scaled, then rescale eigenvalues appropriately. 30 continue if( iscale==1_${ik}$ ) then if( info==0_${ik}$ ) then imax = m else imax = info - 1_${ik}$ end if call stdlib${ii}$_dscal( imax, one / sigma, w, 1_${ik}$ ) end if ! if eigenvalues are not in order, then sort them, along with ! eigenvectors. if( wantz ) then do j = 1, m - 1 i = 0_${ik}$ tmp1 = w( j ) do jj = j + 1, m if( w( jj )<tmp1 ) then i = jj tmp1 = w( jj ) end if end do if( i/=0_${ik}$ ) then itmp1 = iwork( indibl+i-1 ) w( i ) = w( j ) iwork( indibl+i-1 ) = iwork( indibl+j-1 ) w( j ) = tmp1 iwork( indibl+j-1 ) = itmp1 call stdlib${ii}$_zswap( n, z( 1_${ik}$, i ), 1_${ik}$, z( 1_${ik}$, j ), 1_${ik}$ ) if( info/=0_${ik}$ ) then itmp1 = ifail( i ) ifail( i ) = ifail( j ) ifail( j ) = itmp1 end if end if end do end if return end subroutine stdlib${ii}$_zhbevx #:for ck,ct,ci in CMPLX_KINDS_TYPES #:if not ck in ["sp","dp"] module subroutine stdlib${ii}$_${ci}$hbevx( jobz, range, uplo, n, kd, ab, ldab, q, ldq, vl,vu, il, iu, abstol, & !! ZHBEVX: computes selected eigenvalues and, optionally, eigenvectors !! of a complex Hermitian band matrix A. Eigenvalues and eigenvectors !! can be selected by specifying either a range of values or a range of !! indices for the desired eigenvalues. m, w, z, ldz, work, rwork,iwork, ifail, 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) :: jobz, range, uplo integer(${ik}$), intent(in) :: il, iu, kd, ldab, ldq, ldz, n integer(${ik}$), intent(out) :: info, m real(${ck}$), intent(in) :: abstol, vl, vu ! Array Arguments integer(${ik}$), intent(out) :: ifail(*), iwork(*) real(${ck}$), intent(out) :: rwork(*), w(*) complex(${ck}$), intent(inout) :: ab(ldab,*) complex(${ck}$), intent(out) :: q(ldq,*), work(*), z(ldz,*) ! ===================================================================== ! Local Scalars logical(lk) :: alleig, indeig, lower, test, valeig, wantz character :: order integer(${ik}$) :: i, iinfo, imax, indd, inde, indee, indibl, indisp, indiwk, indrwk, & indwrk, iscale, itmp1, j, jj, nsplit real(${ck}$) :: abstll, anrm, bignum, eps, rmax, rmin, safmin, sigma, smlnum, tmp1, vll, & vuu complex(${ck}$) :: ctmp1 ! Intrinsic Functions ! Executable Statements ! test the input parameters. wantz = stdlib_lsame( jobz, 'V' ) alleig = stdlib_lsame( range, 'A' ) valeig = stdlib_lsame( range, 'V' ) indeig = stdlib_lsame( range, 'I' ) lower = stdlib_lsame( uplo, 'L' ) info = 0_${ik}$ if( .not.( wantz .or. stdlib_lsame( jobz, 'N' ) ) ) then info = -1_${ik}$ else if( .not.( alleig .or. valeig .or. indeig ) ) then info = -2_${ik}$ else if( .not.( lower .or. stdlib_lsame( uplo, 'U' ) ) ) then info = -3_${ik}$ else if( n<0_${ik}$ ) then info = -4_${ik}$ else if( kd<0_${ik}$ ) then info = -5_${ik}$ else if( ldab<kd+1 ) then info = -7_${ik}$ else if( wantz .and. ldq<max( 1_${ik}$, n ) ) then info = -9_${ik}$ else if( valeig ) then if( n>0_${ik}$ .and. vu<=vl )info = -11_${ik}$ else if( indeig ) then if( il<1_${ik}$ .or. il>max( 1_${ik}$, n ) ) then info = -12_${ik}$ else if( iu<min( n, il ) .or. iu>n ) then info = -13_${ik}$ end if end if end if if( info==0_${ik}$ ) then if( ldz<1_${ik}$ .or. ( wantz .and. ldz<n ) )info = -18_${ik}$ end if if( info/=0_${ik}$ ) then call stdlib${ii}$_xerbla( 'ZHBEVX', -info ) return end if ! quick return if possible m = 0_${ik}$ if( n==0 )return if( n==1_${ik}$ ) then m = 1_${ik}$ if( lower ) then ctmp1 = ab( 1_${ik}$, 1_${ik}$ ) else ctmp1 = ab( kd+1, 1_${ik}$ ) end if tmp1 = real( ctmp1,KIND=${ck}$) if( valeig ) then if( .not.( vl<tmp1 .and. vu>=tmp1 ) )m = 0_${ik}$ end if if( m==1_${ik}$ ) then w( 1_${ik}$ ) = real( ctmp1,KIND=${ck}$) if( wantz )z( 1_${ik}$, 1_${ik}$ ) = cone end if return end if ! get machine constants. safmin = stdlib${ii}$_${c2ri(ci)}$lamch( 'SAFE MINIMUM' ) eps = stdlib${ii}$_${c2ri(ci)}$lamch( 'PRECISION' ) smlnum = safmin / eps bignum = one / smlnum rmin = sqrt( smlnum ) rmax = min( sqrt( bignum ), one / sqrt( sqrt( safmin ) ) ) ! scale matrix to allowable range, if necessary. iscale = 0_${ik}$ abstll = abstol if( valeig ) then vll = vl vuu = vu else vll = zero vuu = zero end if anrm = stdlib${ii}$_${ci}$lanhb( 'M', uplo, n, kd, ab, ldab, rwork ) if( anrm>zero .and. anrm<rmin ) then iscale = 1_${ik}$ sigma = rmin / anrm else if( anrm>rmax ) then iscale = 1_${ik}$ sigma = rmax / anrm end if if( iscale==1_${ik}$ ) then if( lower ) then call stdlib${ii}$_${ci}$lascl( 'B', kd, kd, one, sigma, n, n, ab, ldab, info ) else call stdlib${ii}$_${ci}$lascl( 'Q', kd, kd, one, sigma, n, n, ab, ldab, info ) end if if( abstol>0_${ik}$ )abstll = abstol*sigma if( valeig ) then vll = vl*sigma vuu = vu*sigma end if end if ! call stdlib${ii}$_${ci}$hbtrd to reduce hermitian band matrix to tridiagonal form. indd = 1_${ik}$ inde = indd + n indrwk = inde + n indwrk = 1_${ik}$ call stdlib${ii}$_${ci}$hbtrd( jobz, uplo, n, kd, ab, ldab, rwork( indd ),rwork( inde ), q, ldq, & work( indwrk ), iinfo ) ! if all eigenvalues are desired and abstol is less than or equal ! to zero, then call stdlib${ii}$_${c2ri(ci)}$sterf or stdlib${ii}$_${ci}$steqr. if this fails for some ! eigenvalue, then try stdlib${ii}$_${c2ri(ci)}$stebz. test = .false. if (indeig) then if (il==1_${ik}$ .and. iu==n) then test = .true. end if end if if ((alleig .or. test) .and. (abstol<=zero)) then call stdlib${ii}$_${c2ri(ci)}$copy( n, rwork( indd ), 1_${ik}$, w, 1_${ik}$ ) indee = indrwk + 2_${ik}$*n if( .not.wantz ) then call stdlib${ii}$_${c2ri(ci)}$copy( n-1, rwork( inde ), 1_${ik}$, rwork( indee ), 1_${ik}$ ) call stdlib${ii}$_${c2ri(ci)}$sterf( n, w, rwork( indee ), info ) else call stdlib${ii}$_${ci}$lacpy( 'A', n, n, q, ldq, z, ldz ) call stdlib${ii}$_${c2ri(ci)}$copy( n-1, rwork( inde ), 1_${ik}$, rwork( indee ), 1_${ik}$ ) call stdlib${ii}$_${ci}$steqr( jobz, n, w, rwork( indee ), z, ldz,rwork( indrwk ), info ) if( info==0_${ik}$ ) then do i = 1, n ifail( i ) = 0_${ik}$ end do end if end if if( info==0_${ik}$ ) then m = n go to 30 end if info = 0_${ik}$ end if ! otherwise, call stdlib${ii}$_${c2ri(ci)}$stebz and, if eigenvectors are desired, stdlib${ii}$_${ci}$stein. if( wantz ) then order = 'B' else order = 'E' end if indibl = 1_${ik}$ indisp = indibl + n indiwk = indisp + n call stdlib${ii}$_${c2ri(ci)}$stebz( range, order, n, vll, vuu, il, iu, abstll,rwork( indd ), rwork( & inde ), m, nsplit, w,iwork( indibl ), iwork( indisp ), rwork( indrwk ),iwork( indiwk ),& info ) if( wantz ) then call stdlib${ii}$_${ci}$stein( n, rwork( indd ), rwork( inde ), m, w,iwork( indibl ), iwork( & indisp ), z, ldz,rwork( indrwk ), iwork( indiwk ), ifail, info ) ! apply unitary matrix used in reduction to tridiagonal ! form to eigenvectors returned by stdlib${ii}$_${ci}$stein. do j = 1, m call stdlib${ii}$_${ci}$copy( n, z( 1_${ik}$, j ), 1_${ik}$, work( 1_${ik}$ ), 1_${ik}$ ) call stdlib${ii}$_${ci}$gemv( 'N', n, n, cone, q, ldq, work, 1_${ik}$, czero,z( 1_${ik}$, j ), 1_${ik}$ ) end do end if ! if matrix was scaled, then rescale eigenvalues appropriately. 30 continue if( iscale==1_${ik}$ ) then if( info==0_${ik}$ ) then imax = m else imax = info - 1_${ik}$ end if call stdlib${ii}$_${c2ri(ci)}$scal( imax, one / sigma, w, 1_${ik}$ ) end if ! if eigenvalues are not in order, then sort them, along with ! eigenvectors. if( wantz ) then do j = 1, m - 1 i = 0_${ik}$ tmp1 = w( j ) do jj = j + 1, m if( w( jj )<tmp1 ) then i = jj tmp1 = w( jj ) end if end do if( i/=0_${ik}$ ) then itmp1 = iwork( indibl+i-1 ) w( i ) = w( j ) iwork( indibl+i-1 ) = iwork( indibl+j-1 ) w( j ) = tmp1 iwork( indibl+j-1 ) = itmp1 call stdlib${ii}$_${ci}$swap( n, z( 1_${ik}$, i ), 1_${ik}$, z( 1_${ik}$, j ), 1_${ik}$ ) if( info/=0_${ik}$ ) then itmp1 = ifail( i ) ifail( i ) = ifail( j ) ifail( j ) = itmp1 end if end if end do end if return end subroutine stdlib${ii}$_${ci}$hbevx #:endif #:endfor #:endfor end submodule stdlib_lapack_eigv_std_driver