pax_global_header00006660000000000000000000000064111125755320014514gustar00rootroot0000000000000052 comment=80c6bfe543bccd49b60de4037cf10ab043d96b1e symeig-1.5/000077500000000000000000000000001111257553200126565ustar00rootroot00000000000000symeig-1.5/COPYRIGHT000066400000000000000000000030111111257553200141440ustar00rootroot00000000000000 This file is part of the symeig python package. Copyright (c) 2003-2008, Pietro Berkes , Tiziano Zito Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. 3. The name of the authors may not be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. symeig-1.5/INSTALL000066400000000000000000000000131111257553200137010ustar00rootroot00000000000000See README.symeig-1.5/PKG-INFO000066400000000000000000000024771111257553200137650ustar00rootroot00000000000000Metadata-Version: 1.0 Name: symeig Version: 1.5 Summary: The symeig module contains a python wrapper for the LAPACK functions to solve the standard and generalized eigenvalue problems for symmetric and hermitian matrices. Home-page: http://mdp-toolkit.sourceforge.net/symeig.html Author: Pietro Berkes and Tiziano Zito Author-email: berkes@brandeis.edu, tiziano.zito@bccn-berlin.de License: BSD license Download-URL: http://sourceforge.net/project/showfiles.php?group_id=116959 Description: The symeig module contains a Python wrapper for the LAPACK functions to solve the standard and generalized eigenvalue problems for symmetric and hermitian matrices. Those specialized algorithms give an important speed-up with respect to the generic LAPACK eigenvalue problem solver used by NumPy (linalg.eig and linalg.eigh). The wrapper function symeig automatically selects the appropriate LAPACK routine. It is also possible to request only a subset of all eigenvalues, which consumes less memory and results sometimes in an additional speed-up, especially for large matrices. The symeig routine is integrated in the 0.7 release of SciPy. It is available there as scipy.linalg.eigh with a slightly different signature. Platform: Any symeig-1.5/README000066400000000000000000000150431111257553200135410ustar00rootroot00000000000000================================================================= SYMEIG Python Module ================================================================= Authors: Pietro Berkes and Tiziano Zito Email: berkes@brandeis.edu, tiziano.zito@bccn-berlin.de Homepage: http://mdp-toolkit.sourceforge.net/symeig.html Download: http://sourceforge.net/projects/mdp-toolkit Current release: 1.4 License: BSD (see COPYRIGHT file) Date: Wed Nov 19 2008 ================================================================= Semi-automatically generated by links from http://mdp-toolkit.sourceforge.net/symeig.html . Symeig - Symmetrical eigenvalue routines for NumPy The symeig module contains a Python wrapper for the LAPACK functions to solve the standard and generalized eigenvalue problems for symmetric and hermitian matrices. Those specialized algorithms give an important speed-up with respect to the generic LAPACK eigenvalue problem solver used by NumPy (linalg.eig and linalg.eigh). The wrapper function symeig automatically selects the appropriate LAPACK routine. It is also possible to request only a subset of all eigenvalues, which consumes less memory and results sometimes in an additional speed-up, especially for large matrices. The symeig routine is integrated in the 0.7 release of SciPy. It is available there as scipy.linalg.eigh with a slightly different signature. -------------------------------------------------------------------------- Installation * Requirements: * A complete LAPACK library, possibly complemented by ATLAS optimized routines * Python >= 2.4 * NumPy >= 1.0 * Download: Download symeig at SourceForge * Installation: Unpack the archive file and enter the project directory. To build the module type: python setup.py build To install it: python setup.py install If you want to use symeig without installing it on the system Python path: python setup.py install --prefix=/some_dir_in_your_PYTHONPATH/ * Testing: Check your installation in a Python shell as follows: >>> import symeig >>> symeig.test() -------------------------------------------------------------------------- Mantainers symeig has been written by Pietro Berkes and Tiziano Zito at the Institute for Theoretical Biology of the Humboldt University, Berlin. For comments, patches, feature requests, support requests, and bug reports please send a message to the MDP users mailing list. -------------------------------------------------------------------------- Documentation * symeig docstring: """Solve standard and generalized eigenvalue problem for symmetric and hermitian matrices. Syntax: w,Z = symeig(A) w = symeig(A,eigenvectors=0) w,Z = symeig(A,range=(lo,hi)) w,Z = symeig(A,B,range=(lo,hi)) Inputs: A -- An N x N real symmetric or complex hermitian matrix. B -- An N x N real symmetric or complex hermitian definite positive matrix. eigenvectors -- if set return eigenvalues and eigenvectors, otherwise only eigenvalues turbo -- (only for generalized eigenvalue problem and if range=None) if turbo = "on", use divide and conquer algorithm (faster but expensive in memory) range -- the tuple (lo,hi) represent the indexes of the smallest and largest (in ascending order) eigenvalues to be returned. 1 <= lo < hi <= N if range = None, returns all eigenvalues and eigenvectors. type -- (only for generalized eigenvalue problem) Specifies the problem type to be solved: type = 1: A*x = (lambda)*B*x = 2: A*B*x = (lambda)*x = 3: B*A*x = (lambda)*x overwrite -- if 'overwrite' is set, computations are done inplace, A and B are overwritten during calculation (you save memory but loose the matrices). If matrices are complex this argument is ignored. Outputs: w -- (selected) eigenvalues in ascending order. Z -- if range = None, Z contains the matrix of eigenvectors, normalized as follows: Z^H * A * Z = lambda and - type = 1 or 2: Z^H * B * Z = I - type = 3 : Z^H * B^(-1) * Z = I where ^H means conjugate transpose. if range, an N x M matrix containing the orthonormal eigenvectors of the matrix A corresponding to the selected eigenvalues, with the i-th column of Z holding the eigenvector associated with w[i]. The eigenvectors are normalized as above. """ * Wrapped LAPACK functions: symeig wraps the following LAPACK functions for standard and generalized symmetric eigenvalue problems: +----------------------------------------------------------+ | EVR routines | ssyevr.f | dsyevr.f | cheevr.f | zheevr.f | |--------------+----------+----------+----------+----------| | GV routines | ssygv.f | dsygv.f | chegv.f | zhegv.f | |--------------+----------+----------+----------+----------| | GVD routines | ssygvd.f | dsygvd.f | chegvd.f | zhegvd.f | |--------------+----------+----------+----------+----------| | GVX routines | ssygvx.f | dsygvx.f | chegvx.f | zhegvx.f | +----------------------------------------------------------+ -------------------------------------------------------------------------- SourceForge.net Logo Valid HTML 4.01! References Visible links . http://sourceforge.net/mail/?group_id=116959 . http://mdp-toolkit.sourceforge.net/symeig.html . http://numpy.scipy.org/ . http://www.scipy.org/ . http://www.netlib.org/lapack/ . http://math-atlas.sourceforge.net/ . http://www.python.org/ . http://numpy.scipy.org/ . http://sourceforge.net/project/showfiles.php?group_id=116959 . http://people.brandeis.edu/~berkes/ . http://itb.biologie.hu-berlin.de/~zito . http://itb.biologie.hu-berlin.de/ . http://www.hu-berlin.de/ . http://sourceforge.net/mail/?group_id=116959 . http://www.netlib.org/lapack/lug/node30.html . http://www.netlib.org/lapack/lug/node34.html . http://sourceforge.net/ . http://validator.w3.org/check?uri=referer;verbose=1 symeig-1.5/__init__.py000066400000000000000000000005431111257553200147710ustar00rootroot00000000000000from symeig import symeig, SymeigException, LeadingMinorException # import test functions: from test import test __version__ = '1.5' __authors__ = 'Pietro Berkes and Tiziano Zito' __copyright__ = '(c) 2003-2008 Pietro Berkes and Tiziano Zito' __license__ = 'BSD, see COPYRIGHT file for details' __contact__ = 'mdp-toolkit-users AT lists.sourceforge.net' symeig-1.5/froutines.pyf000066400000000000000000002216311111257553200154210ustar00rootroot00000000000000!%f90 -*- f90 -*- ! This file contains pyf files (f2py2 wrapper generator) ! for some LAPACK routines for symmetric, positive definite ! matrices ! ! - RRR routines for standard eigenvalue problem (evr) ! - Simple routines for generalized eigenvalue problem (gv) ! - Divide and conquer routines for generalized eigenvalue problem (gvd) ! - Expert routines for generalized eigenvalue problem (gvx) python module froutines ! in interface ! in :lapack_symeig ! ! RRR routines for standard eigenvalue problem ! subroutine ssyevr(jobz,range,uplo,n,a,lda,vl,vu,il,iu,abstol,m,w,z,ldz,isuppz,work,lwork,iwork,liwork,info) ! in :froutines:ssyevr.f ! Standard Eigenvalue Problem ! simple/expert driver: all eigenvectors or optionally selected eigenvalues ! algorithm: Relatively Robust Representation ! matrix storage ! Real - Single precision character intent(in) :: jobz='V' ! = 'N': Compute eigenvalues only; ! = 'V': Compute eigenvalues and eigenvectors. character intent(in) :: range='A' ! = 'A': all eigenvalues will be found. ! = 'V': all eigenvalues in the half-open interval (VL,VU] will be found. ! = 'I': the IL-th through IU-th eigenvalues will be found. character intent(in) :: uplo='L' ! = 'U': Upper triangles of A and B are stored; ! = 'L': Lower triangles of A and B are stored. integer intent(hide) :: n=shape(a,0) ! The order of the matrices A and B. real intent(in,copy),dimension(n,n) :: a ! (input/output) REAL array, dimension (LDA, N) ! On entry, the symmetric matrix A. If UPLO = 'U', the ! leading N-by-N upper triangular part of A contains the ! upper triangular part of the matrix A. If UPLO = 'L', ! the leading N-by-N lower triangular part of A contains ! the lower triangular part of the matrix A. ! On exit, the lower triangle (if UPLO='L') or the upper ! triangle (if UPLO='U') of A, including the diagonal, is ! destroyed. integer intent(hide),depend(n,a) :: lda=n ! The leading dimension of the array A. LDA >= max(1,N). real intent(hide) :: vl=0 ! If RANGE='V', the lower and upper bounds of the interval to real intent(hide) :: vu=1 ! be searched for eigenvalues. VL < VU. integer optional,intent(in) :: il=1 ! If RANGE='I', the indices (in ascending order) of the integer optional,intent(in),depend(n) :: iu=n ! smallest and largest eigenvalues to be returned. 1<=IL<=IU<= N real intent(hide) :: abstol=0. ! The absolute error tolerance for the eigenvalues. ! An approximate eigenvalue is accepted as converged ! when it is determined to lie in an interval [a,b] ! of width less than or equal to ! ABSTOL + EPS * max( |a|,|b| ) , ! where EPS is the machine precision. If ABSTOL is less than ! or equal to zero, then EPS*|T| will be used in its place, ! where |T| is the 1-norm of the tridiagonal matrix obtained ! by reducing A to tridiagonal form. integer intent(hide),depend(iu) :: m=iu-il+1 ! The total number of eigenvalues found. 0 <= M <= N. ! If RANGE = 'A', M = N, and if RANGE = 'I', M = IU-IL+1. real intent(out),dimension(n),depend(n) :: w ! If INFO = 0, the first M elements contain the selected ! eigenvalues in ascending order real intent(out),dimension(n,m),depend(n,m) :: z ! If JOBZ = 'V', then if INFO = 0, the first M columns of Z ! contain the orthonormal eigenvectors of the matrix A ! corresponding to the selected eigenvalues, with the i-th ! column of Z holding the eigenvector associated with W(i). ! If JOBZ = 'N', then Z is not referenced. ! Note: the user must ensure that at least max(1,M) columns are ! supplied in the array Z; if RANGE = 'V', the exact value of M ! is not known in advance and an upper bound must be used. integer intent(hide),check(shape(z,0)==ldz),depend(n,z) :: ldz=n ! The leading dimension of the array Z. integer intent(hide),dimension(2*m) :: isuppz ! fake variable integer intent(in),depend(n) :: lwork=26*n ! The length of the array WORK. LWORK >= max(1,26*N). ! For optimal efficiency, LWORK >= (NB+6)*N, ! where NB is the blocksize for SSYTRD and SORMTR returned by ILAENV. real intent(hide),dimension(lwork) :: work ! (workspace/output) REAL array, dimension (LWORK) ! On exit, if INFO = 0, WORK(1) returns the optimal LWORK. integer intent(hide),depend(n):: liwork=10*n ! The dimension of the array IWORK. LIWORK >= max(1,10*N). integer intent(hide),dimension(liwork) :: iwork ! (workspace/output) INTEGER array, dimension (LIWORK) integer intent(out) :: info ! = 0: successful exit ! < 0: if INFO = -i, the i-th argument had an illegal value ! > 0: Internal error end subroutine ssyevr ! !---------------------------------------------------------------------------------------------------------------------- ! subroutine dsyevr(jobz,range,uplo,n,a,lda,vl,vu,il,iu,abstol,m,w,z,ldz,isuppz,work,lwork,iwork,liwork,info) ! in :froutines:dsyevr.f ! Standard Eigenvalue Problem ! simple/expert driver: all eigenvectors or optionally selected eigenvalues ! algorithm: Relatively Robust Representation ! matrix storage ! Real - Double precision character intent(in) :: jobz='V' ! = 'N': Compute eigenvalues only; ! = 'V': Compute eigenvalues and eigenvectors. character intent(in) :: range='A' ! = 'A': all eigenvalues will be found. ! = 'V': all eigenvalues in the half-open interval (VL,VU] will be found. ! = 'I': the IL-th through IU-th eigenvalues will be found. character intent(in) :: uplo='L' ! = 'U': Upper triangles of A and B are stored; ! = 'L': Lower triangles of A and B are stored. integer intent(hide) :: n=shape(a,0) ! The order of the matrices A and B. double precision intent(in,copy),dimension(n,n) :: a ! (input/output) REAL/DOUBLE array, dimension (LDA, N) ! On entry, the symmetric matrix A. If UPLO = 'U', the ! leading N-by-N upper triangular part of A contains the ! upper triangular part of the matrix A. If UPLO = 'L', ! the leading N-by-N lower triangular part of A contains ! the lower triangular part of the matrix A. ! On exit, the lower triangle (if UPLO='L') or the upper ! triangle (if UPLO='U') of A, including the diagonal, is ! destroyed. integer intent(hide),depend(n,a) :: lda=n ! The leading dimension of the array A. LDA >= max(1,N). double precision intent(hide) :: vl=0 ! If RANGE='V', the lower and upper bounds of the interval to double precision intent(hide) :: vu=1 ! be searched for eigenvalues. VL < VU. integer optional,intent(in) :: il=1 ! If RANGE='I', the indices (in ascending order) of the integer optional,intent(in),depend(n) :: iu=n ! smallest and largest eigenvalues to be returned. 1<=IL<=IU<= N double precision intent(hide) :: abstol=0. ! The absolute error tolerance for the eigenvalues. ! An approximate eigenvalue is accepted as converged ! when it is determined to lie in an interval [a,b] ! of width less than or equal to ! ABSTOL + EPS * max( |a|,|b| ) , ! where EPS is the machine precision. If ABSTOL is less than ! or equal to zero, then EPS*|T| will be used in its place, ! where |T| is the 1-norm of the tridiagonal matrix obtained ! by reducing A to tridiagonal form. integer intent(hide),depend(iu) :: m=iu-il+1 ! The total number of eigenvalues found. 0 <= M <= N. ! If RANGE = 'A', M = N, and if RANGE = 'I', M = IU-IL+1. double precision intent(out),dimension(n),depend(n) :: w ! If INFO = 0, the first M elements contain the selected ! eigenvalues in ascending order double precision intent(out),dimension(n,m),depend(n,m) :: z ! If JOBZ = 'V', then if INFO = 0, the first M columns of Z ! contain the orthonormal eigenvectors of the matrix A ! corresponding to the selected eigenvalues, with the i-th ! column of Z holding the eigenvector associated with W(i). ! If JOBZ = 'N', then Z is not referenced. ! Note: the user must ensure that at least max(1,M) columns are ! supplied in the array Z; if RANGE = 'V', the exact value of M ! is not known in advance and an upper bound must be used. integer intent(hide),check(shape(z,0)==ldz),depend(n,z) :: ldz=n ! The leading dimension of the array Z. integer intent(hide),dimension(2*m) :: isuppz ! fake variable integer intent(in),depend(n) :: lwork=26*n ! The length of the array WORK. LWORK >= max(1,26*N). ! For optimal efficiency, LWORK >= (NB+6)*N, ! where NB is the blocksize for SSYTRD and SORMTR returned by ILAENV. double precision intent(hide),dimension(lwork) :: work ! (workspace/output) REAL/DOUBLE array, dimension (LWORK) ! On exit, if INFO = 0, WORK(1) returns the optimal LWORK. integer intent(hide),depend(n):: liwork=10*n ! The dimension of the array IWORK. LIWORK >= max(1,10*N). integer intent(hide),dimension(liwork) :: iwork ! (workspace/output) INTEGER array, dimension (LIWORK) integer intent(out) :: info ! = 0: successful exit ! < 0: if INFO = -i, the i-th argument had an illegal value ! > 0: Internal error end subroutine dsyevr ! !---------------------------------------------------------------------------------------------------------------------- ! subroutine cheevr(jobz,range,uplo,n,a,lda,vl,vu,il,iu,abstol,m,w,z,ldz,isuppz,work,lwork,rwork,lrwork,iwork,liwork,info) ! in :froutines:cheevr.f ! Standard Eigenvalue Problem ! simple/expert driver: all eigenvectors or optionally selected eigenvalues ! algorithm: Relatively Robust Representation ! matrix storage ! Complex - Single precision character intent(in) :: jobz='V' ! = 'N': Compute eigenvalues only; ! = 'V': Compute eigenvalues and eigenvectors. character intent(in) :: range='A' ! = 'A': all eigenvalues will be found. ! = 'V': all eigenvalues in the half-open interval (VL,VU] will be found. ! = 'I': the IL-th through IU-th eigenvalues will be found. character intent(in) :: uplo='L' ! = 'U': Upper triangles of A and B are stored; ! = 'L': Lower triangles of A and B are stored. integer intent(hide) :: n=shape(a,0) ! The order of the matrices A and B. complex intent(in,copy),dimension(n,n) :: a ! (input/output) COMPLEX array, dimension (LDA, N) ! On entry, the Hermitian matrix A. If UPLO = 'U', the ! leading N-by-N upper triangular part of A contains the ! upper triangular part of the matrix A. If UPLO = 'L', ! the leading N-by-N lower triangular part of A contains ! the lower triangular part of the matrix A. ! On exit, the lower triangle (if UPLO='L') or the upper ! triangle (if UPLO='U') of A, including the diagonal, is ! destroyed. integer intent(hide),depend(n,a) :: lda=n ! The leading dimension of the array A. LDA >= max(1,N). real intent(hide) :: vl=0 ! If RANGE='V', the lower and upper bounds of the interval to real intent(hide) :: vu=1 ! be searched for eigenvalues. VL < VU. integer optional,intent(in) :: il=1 ! If RANGE='I', the indices (in ascending order) of the integer optional,intent(in),depend(n) :: iu=n ! smallest and largest eigenvalues to be returned. 1<=IL<=IU<= N real intent(hide) :: abstol=0. ! The absolute error tolerance for the eigenvalues. ! An approximate eigenvalue is accepted as converged ! when it is determined to lie in an interval [a,b] ! of width less than or equal to ! ABSTOL + EPS * max( |a|,|b| ) , ! where EPS is the machine precision. If ABSTOL is less than ! or equal to zero, then EPS*|T| will be used in its place, ! where |T| is the 1-norm of the tridiagonal matrix obtained ! by reducing A to tridiagonal form. integer intent(hide),depend(iu) :: m=iu-il+1 ! The total number of eigenvalues found. 0 <= M <= N. ! If RANGE = 'A', M = N, and if RANGE = 'I', M = IU-IL+1. real intent(out),dimension(n),depend(n) :: w ! The first M elements contain the selected ! eigenvalues in ascending order complex intent(out),dimension(n,m),depend(n,m) :: z ! If JOBZ = 'V', then if INFO = 0, the first M columns of Z ! contain the orthonormal eigenvectors of the matrix A ! corresponding to the selected eigenvalues, with the i-th ! column of Z holding the eigenvector associated with W(i). ! If JOBZ = 'N', then Z is not referenced. ! Note: the user must ensure that at least max(1,M) columns are ! supplied in the array Z; if RANGE = 'V', the exact value of M ! is not known in advance and an upper bound must be used. integer intent(hide),check(shape(z,0)==ldz),depend(n,z) :: ldz=n ! The leading dimension of the array Z. integer intent(hide),dimension(2*m) :: isuppz ! fake variable integer intent(in),depend(n) :: lwork=2*n ! The length of the array WORK. LWORK >= max(1,2*N). ! For optimal efficiency, LWORK >= (NB+1)*N, ! where NB is the max of the blocksize for CHETRD and for ! CUNMTR as returned by ILAENV. complex intent(hide),dimension(lwork) :: work ! (workspace/output) COMPLEX array, dimension (LWORK) ! On exit, if INFO = 0, WORK(1) returns the optimal LWORK. integer intent(hide),depend(n) :: lrwork=24*n ! The length of the array RWORK. LRWORK >= max(1,24*N) real intent(hide),dimension(lrwork) :: rwork ! (workspace/output) REAL array, dimension (LRWORK) ! On exit, if INFO = 0, RWORK(1) returns the optimal ! (and minimal) LRWORK. integer intent(hide),depend(n):: liwork=10*n ! The dimension of the array IWORK. LIWORK >= max(1,10*N). integer intent(hide),dimension(liwork) :: iwork ! (workspace/output) INTEGER array, dimension (LIWORK) integer intent(out) :: info ! = 0: successful exit ! < 0: if INFO = -i, the i-th argument had an illegal value ! > 0: Internal error end subroutine cheevr ! !---------------------------------------------------------------------------------------------------------------------- ! subroutine zheevr(jobz,range,uplo,n,a,lda,vl,vu,il,iu,abstol,m,w,z,ldz,isuppz,work,lwork,rwork,lrwork,iwork,liwork,info) ! in :froutines:zheevr.f ! Standard Eigenvalue Problem ! simple/expert driver: all eigenvectors or optionally selected eigenvalues ! algorithm: Relatively Robust Representation ! matrix storage ! Complex - Double precision character intent(in) :: jobz='V' ! = 'N': Compute eigenvalues only; ! = 'V': Compute eigenvalues and eigenvectors. character intent(in) :: range='A' ! = 'A': all eigenvalues will be found. ! = 'V': all eigenvalues in the half-open interval (VL,VU] will be found. ! = 'I': the IL-th through IU-th eigenvalues will be found. character intent(in) :: uplo='L' ! = 'U': Upper triangles of A and B are stored; ! = 'L': Lower triangles of A and B are stored. integer intent(hide) :: n=shape(a,0) ! The order of the matrices A and B. complex*16 intent(in,copy),dimension(n,n) :: a ! (input/output) COMPLEX*16 array, dimension (LDA, N) ! On entry, the Hermitian matrix A. If UPLO = 'U', the ! leading N-by-N upper triangular part of A contains the ! upper triangular part of the matrix A. If UPLO = 'L', ! the leading N-by-N lower triangular part of A contains ! the lower triangular part of the matrix A. ! On exit, the lower triangle (if UPLO='L') or the upper ! triangle (if UPLO='U') of A, including the diagonal, is ! destroyed. integer intent(hide),depend(n,a) :: lda=n ! The leading dimension of the array A. LDA >= max(1,N). double precision intent(hide) :: vl=0 ! If RANGE='V', the lower and upper bounds of the interval to double precision intent(hide) :: vu=1 ! be searched for eigenvalues. VL < VU. integer optional,intent(in) :: il=1 ! If RANGE='I', the indices (in ascending order) of the integer optional,intent(in),depend(n) :: iu=n ! smallest and largest eigenvalues to be returned. 1<=IL<=IU<= N double precision intent(hide) :: abstol=0. ! The absolute error tolerance for the eigenvalues. ! An approximate eigenvalue is accepted as converged ! when it is determined to lie in an interval [a,b] ! of width less than or equal to ! ABSTOL + EPS * max( |a|,|b| ) , ! where EPS is the machine precision. If ABSTOL is less than ! or equal to zero, then EPS*|T| will be used in its place, ! where |T| is the 1-norm of the tridiagonal matrix obtained ! by reducing A to tridiagonal form. integer intent(hide),depend(iu) :: m=iu-il+1 ! The total number of eigenvalues found. 0 <= M <= N. ! If RANGE = 'A', M = N, and if RANGE = 'I', M = IU-IL+1. double precision intent(out),dimension(n),depend(n) :: w ! The first M elements contain the selected ! eigenvalues in ascending order complex*16 intent(out),dimension(n,m),depend(n,m) :: z ! If JOBZ = 'V', then if INFO = 0, the first M columns of Z ! contain the orthonormal eigenvectors of the matrix A ! corresponding to the selected eigenvalues, with the i-th ! column of Z holding the eigenvector associated with W(i). ! If JOBZ = 'N', then Z is not referenced. ! Note: the user must ensure that at least max(1,M) columns are ! supplied in the array Z; if RANGE = 'V', the exact value of M ! is not known in advance and an upper bound must be used. integer intent(hide),check(shape(z,0)==ldz),depend(n,z) :: ldz=n ! The leading dimension of the array Z. integer intent(hide),dimension(2*m) :: isuppz ! fake variable integer intent(in),depend(n) :: lwork=2*n ! The length of the array WORK. LWORK >= max(1,2*N). ! For optimal efficiency, LWORK >= (NB+1)*N, ! where NB is the max of the blocksize for CHETRD and for ! CUNMTR as returned by ILAENV. complex*16 intent(hide),dimension(lwork) :: work ! (workspace/output) COMPLEX*16 array, dimension (LWORK) ! On exit, if INFO = 0, WORK(1) returns the optimal LWORK. integer intent(hide),depend(n) :: lrwork=24*n ! The length of the array RWORK. LRWORK >= max(1,24*N) double precision intent(hide),dimension(lrwork) :: rwork ! (workspace/output) DOUBLE PRECISION array, dimension (LRWORK) ! On exit, if INFO = 0, RWORK(1) returns the optimal ! (and minimal) LRWORK. integer intent(hide),depend(n):: liwork=10*n ! The dimension of the array IWORK. LIWORK >= max(1,10*N). integer intent(hide),dimension(liwork) :: iwork ! (workspace/output) INTEGER array, dimension (LIWORK) integer intent(out) :: info ! = 0: successful exit ! < 0: if INFO = -i, the i-th argument had an illegal value ! > 0: Internal error end subroutine zheevr ! ! Simple routines for generalized eigenvalue problem ! subroutine ssygv(itype,jobz,uplo,n,a,lda,b,ldb,w,work,lwork,info) ! in :froutines:ssygv.f ! Generalized Eigenvalue Problem ! simple driver (all eigenvectors) ! algorithm: standard ! matrix storage ! Real - Single precision integer optional,intent(in) :: itype=1 ! Specifies the problem type to be solved: ! = 1: A*x = (lambda)*B*x ! = 2: A*B*x = (lambda)*x ! = 3: B*A*x = (lambda)*x character intent(in) :: jobz='V' ! = 'N': Compute eigenvalues only; ! = 'V': Compute eigenvalues and eigenvectors. character intent(in) :: uplo='L' ! = 'U': Upper triangles of A and B are stored; ! = 'L': Lower triangles of A and B are stored. integer intent(hide) :: n=shape(a,0) ! The order of the matrices A and B. real intent(in,copy,out),dimension(n,n) :: a ! On entry, the symmetric matrix A. If UPLO = 'U', the ! leading N-by-N upper triangular part of A contains the ! upper triangular part of the matrix A. If UPLO = 'L', ! the leading N-by-N lower triangular part of A contains ! the lower triangular part of the matrix A. ! On exit, if JOBZ = 'V', then if INFO = 0, A contains the ! matrix Z of eigenvectors. The eigenvectors are normalized ! as follows: ! if ITYPE = 1 or 2, Z**T*B*Z = I; ! if ITYPE = 3, Z**T*inv(B)*Z = I. ! If JOBZ = 'N', then on exit the upper triangle (if UPLO='U') ! or the lower triangle (if UPLO='L') of A, including the ! diagonal, is destroyed. integer intent(hide),depend(n,a) :: lda=n ! The leading dimension of the array A. LDA >= max(1,N). real intent(in,copy),dimension(n,n) :: b ! On entry, the symmetric matrix B. If UPLO = 'U', the ! leading N-by-N upper triangular part of A contains the ! upper triangular part of the matrix B. If UPLO = 'L', ! the leading N-by-N lower triangular part of A contains ! the lower triangular part of the matrix B. ! On exit, if INFO <= N, the part of B containing the matrix is ! overwritten by the triangular factor U or L from the Cholesky ! factorization B = U**T*U or B = L*L**T. integer intent(hide),depend(n,b) :: ldb=n ! The leading dimension of the array B. LDB >= max(1,N). real intent(out),dimension(n),depend(n) :: w ! If INFO = 0, the eigenvalues in ascending order. integer intent(hide) :: lwork=3*n-1 ! The length of the array WORK. LWORK >= max(1,3*N-1). ! For optimal efficiency, LWORK >= (NB+2)*N, ! where NB is the blocksize for SSYTRD returned by ILAENV. real intent(hide),dimension(lwork) :: work ! (workspace/output) REAL array, dimension (LWORK) ! On exit, if INFO = 0, WORK(1) returns the optimal LWORK. integer intent(out) :: info ! = 0: successful exit ! < 0: if INFO = -i, the i-th argument had an illegal value ! > 0: SPOTRF or SSYEV returned an error code: ! <= N: if INFO = i, SSYEV failed to converge; ! i off-diagonal elements of an intermediate ! tridiagonal form did not converge to zero. ! > N: if INFO = n + i, for 1 <= i <= n, then the leading ! minor of order i of B is not positive definite. ! The factorization of B could not be completed and ! no eigenvalues or eigenvectors were computed. end subroutine ssygv ! !---------------------------------------------------------------------------------------------------------------------- ! subroutine dsygv(itype,jobz,uplo,n,a,lda,b,ldb,w,work,lwork,info) ! in :froutines:dsygv.f ! Generalized Eigenvalue Problem ! simple driver (all eigenvectors) ! algorithm: standard ! matrix storage ! Real - Double precision integer optional,intent(in) :: itype=1 ! Specifies the problem type to be solved: ! = 1: A*x = (lambda)*B*x ! = 2: A*B*x = (lambda)*x ! = 3: B*A*x = (lambda)*x character intent(in) :: jobz='V' ! = 'N': Compute eigenvalues only; ! = 'V': Compute eigenvalues and eigenvectors. character intent(in) :: uplo='L' ! = 'U': Upper triangles of A and B are stored; ! = 'L': Lower triangles of A and B are stored. integer intent(hide) :: n=shape(a,0) ! The order of the matrices A and B. double precision intent(in,copy,out),dimension(n,n) :: a ! On entry, the symmetric matrix A. If UPLO = 'U', the ! leading N-by-N upper triangular part of A contains the ! upper triangular part of the matrix A. If UPLO = 'L', ! the leading N-by-N lower triangular part of A contains ! the lower triangular part of the matrix A. ! On exit, if JOBZ = 'V', then if INFO = 0, A contains the ! matrix Z of eigenvectors. The eigenvectors are normalized ! as follows: ! if ITYPE = 1 or 2, Z**T*B*Z = I; ! if ITYPE = 3, Z**T*inv(B)*Z = I. ! If JOBZ = 'N', then on exit the upper triangle (if UPLO='U') ! or the lower triangle (if UPLO='L') of A, including the ! diagonal, is destroyed. integer intent(hide),depend(n,a) :: lda=n ! The leading dimension of the array A. LDA >= max(1,N). double precision intent(in,copy),dimension(n,n) :: b ! On entry, the symmetric matrix B. If UPLO = 'U', the ! leading N-by-N upper triangular part of A contains the ! upper triangular part of the matrix B. If UPLO = 'L', ! the leading N-by-N lower triangular part of A contains ! the lower triangular part of the matrix B. ! On exit, if INFO <= N, the part of B containing the matrix is ! overwritten by the triangular factor U or L from the Cholesky ! factorization B = U**T*U or B = L*L**T. integer intent(hide),depend(n,b) :: ldb=n ! The leading dimension of the array B. LDB >= max(1,N). double precision intent(out),dimension(n),depend(n) :: w ! If INFO = 0, the eigenvalues in ascending order. integer intent(hide) :: lwork=3*n-1 ! The length of the array WORK. LWORK >= max(1,3*N-1). ! For optimal efficiency, LWORK >= (NB+2)*N, ! where NB is the blocksize for SSYTRD returned by ILAENV. double precision intent(hide),dimension(lwork) :: work ! (workspace/output) DOUBLE PRECISION array, dimension (LWORK) ! On exit, if INFO = 0, WORK(1) returns the optimal LWORK. integer intent(out) :: info ! = 0: successful exit ! < 0: if INFO = -i, the i-th argument had an illegal value ! > 0: SPOTRF or DSYEV returned an error code: ! <= N: if INFO = i, DSYEV failed to converge; ! i off-diagonal elements of an intermediate ! tridiagonal form did not converge to zero. ! > N: if INFO = n + i, for 1 <= i <= n, then the leading ! minor of order i of B is not positive definite. ! The factorization of B could not be completed and ! no eigenvalues or eigenvectors were computed. end subroutine dsygv ! !---------------------------------------------------------------------------------------------------------------------- ! subroutine chegv(itype,jobz,uplo,n,a,lda,b,ldb,w,work,lwork,rwork,info) ! in :froutines:chegv.f ! Generalized Eigenvalue Problem ! simple driver (all eigenvectors) ! algorithm: standard ! matrix storage ! Complex - Single precision integer optional,intent(in) :: itype=1 ! Specifies the problem type to be solved: ! = 1: A*x = (lambda)*B*x ! = 2: A*B*x = (lambda)*x ! = 3: B*A*x = (lambda)*x character intent(in) :: jobz='V' ! = 'N': Compute eigenvalues only; ! = 'V': Compute eigenvalues and eigenvectors. character intent(in) :: uplo='L' ! = 'U': Upper triangles of A and B are stored; ! = 'L': Lower triangles of A and B are stored. integer intent(hide) :: n=shape(a,0) ! The order of the matrices A and B. complex intent(in,copy,out),dimension(n,n) :: a ! On entry, the hermitian matrix A. If UPLO = 'U', the ! leading N-by-N upper triangular part of A contains the ! upper triangular part of the matrix A. If UPLO = 'L', ! the leading N-by-N lower triangular part of A contains ! the lower triangular part of the matrix A. ! On exit, if JOBZ = 'V', then if INFO = 0, A contains the ! matrix Z of eigenvectors. The eigenvectors are normalized ! as follows: ! if ITYPE = 1 or 2, Z**T*B*Z = I; ! if ITYPE = 3, Z**T*inv(B)*Z = I. ! If JOBZ = 'N', then on exit the upper triangle (if UPLO='U') ! or the lower triangle (if UPLO='L') of A, including the ! diagonal, is destroyed. integer intent(hide),depend(n,a) :: lda=n ! The leading dimension of the array A. LDA >= max(1,N). complex intent(in,copy),dimension(n,n) :: b ! On entry, the Hermitian positive definite matrix B. If UPLO = 'U', the ! leading N-by-N upper triangular part of B contains the ! upper triangular part of the matrix B. If UPLO = 'L', ! the leading N-by-N lower triangular part of B contains ! the lower triangular part of the matrix B. ! On exit, if INFO <= N, the part of B containing the matrix is ! overwritten by the triangular factor U or L from the Cholesky ! factorization B = U**H*U or B = L*L**H. integer intent(hide),depend(n,b) :: ldb=n ! The leading dimension of the array B. LDB >= max(1,N). real intent(out),dimension(n),depend(n) :: w ! If INFO = 0, the eigenvalues in ascending order. integer intent(hide) :: lwork=2*n-1 ! The length of the array WORK. LWORK >= max(1,2*N-1). ! For optimal efficiency, LWORK >= (NB+1)*N, ! where NB is the blocksize for CHETRD returned by ILAENV. complex intent(hide),dimension(lwork) :: work ! (workspace/output) COMPLEX array, dimension (LWORK) ! On exit, if INFO = 0, WORK(1) returns the optimal LWORK. real intent(hide),dimension(3*n-2) :: rwork ! (workspace) REAL array, dimension (max(1, 3*N-2)) integer intent(out) :: info ! = 0: successful exit ! < 0: if INFO = -i, the i-th argument had an illegal value ! > 0: SPOTRF or CHEEV returned an error code: ! <= N: if INFO = i, CHEEV failed to converge; ! i off-diagonal elements of an intermediate ! tridiagonal form did not converge to zero. ! > N: if INFO = n + i, for 1 <= i <= n, then the leading ! minor of order i of B is not positive definite. ! The factorization of B could not be completed and ! no eigenvalues or eigenvectors were computed. end subroutine chegv ! !---------------------------------------------------------------------------------------------------------------------- ! subroutine zhegv(itype,jobz,uplo,n,a,lda,b,ldb,w,work,lwork,rwork,info) ! in :froutines:chegv.f ! Generalized Eigenvalue Problem ! simple driver (all eigenvectors) ! algorithm: standard ! matrix storage ! Complex - Double precision integer optional,intent(in) :: itype=1 ! Specifies the problem type to be solved: ! = 1: A*x = (lambda)*B*x ! = 2: A*B*x = (lambda)*x ! = 3: B*A*x = (lambda)*x character intent(in) :: jobz='V' ! = 'N': Compute eigenvalues only; ! = 'V': Compute eigenvalues and eigenvectors. character intent(in) :: uplo='L' ! = 'U': Upper triangles of A and B are stored; ! = 'L': Lower triangles of A and B are stored. integer intent(hide) :: n=shape(a,0) ! The order of the matrices A and B. complex*16 intent(in,copy,out),dimension(n,n) :: a ! On entry, the hermitian matrix A. If UPLO = 'U', the ! leading N-by-N upper triangular part of A contains the ! upper triangular part of the matrix A. If UPLO = 'L', ! the leading N-by-N lower triangular part of A contains ! the lower triangular part of the matrix A. ! On exit, if JOBZ = 'V', then if INFO = 0, A contains the ! matrix Z of eigenvectors. The eigenvectors are normalized ! as follows: ! if ITYPE = 1 or 2, Z**H*B*Z = I; ! if ITYPE = 3, Z**H*inv(B)*Z = I. ! If JOBZ = 'N', then on exit the upper triangle (if UPLO='U') ! or the lower triangle (if UPLO='L') of A, including the ! diagonal, is destroyed. integer intent(hide),depend(n,a) :: lda=n ! The leading dimension of the array A. LDA >= max(1,N). complex*16 intent(in,copy),dimension(n,n) :: b ! On entry, the Hermitian positive definite matrix B. If UPLO = 'U', the ! leading N-by-N upper triangular part of B contains the ! upper triangular part of the matrix B. If UPLO = 'L', ! the leading N-by-N lower triangular part of B contains ! the lower triangular part of the matrix B. ! On exit, if INFO <= N, the part of B containing the matrix is ! overwritten by the triangular factor U or L from the Cholesky ! factorization B = U**H*U or B = L*L**H. integer intent(hide),depend(n,b) :: ldb=n ! The leading dimension of the array B. LDB >= max(1,N). double precision intent(out),dimension(n),depend(n) :: w ! If INFO = 0, the eigenvalues in ascending order. integer intent(hide) :: lwork=2*n-1 ! The length of the array WORK. LWORK >= max(1,2*N-1). ! For optimal efficiency, LWORK >= (NB+1)*N, ! where NB is the blocksize for CHETRD returned by ILAENV. complex*16 intent(hide),dimension(lwork) :: work ! (workspace/output) COMPLEX*16 array, dimension (LWORK) ! On exit, if INFO = 0, WORK(1) returns the optimal LWORK. double precision intent(hide),dimension(3*n-2) :: rwork ! (workspace) DOUBLE PRECISION array, dimension (max(1, 3*N-2)) integer intent(out) :: info ! = 0: successful exit ! < 0: if INFO = -i, the i-th argument had an illegal value ! > 0: SPOTRF or ZHEEV returned an error code: ! <= N: if INFO = i, ZHEEV failed to converge; ! i off-diagonal elements of an intermediate ! tridiagonal form did not converge to zero. ! > N: if INFO = n + i, for 1 <= i <= n, then the leading ! minor of order i of B is not positive definite. ! The factorization of B could not be completed and ! no eigenvalues or eigenvectors were computed. end subroutine zhegv ! ! Divide and conquer routines for generalized eigenvalue problem ! subroutine ssygvd(itype,jobz,uplo,n,a,lda,b,ldb,w,work,lwork,iwork,liwork,info) ! in :froutines:ssygvd.f ! Generalized Eigenvalue Problem ! simple driver (all eigenvectors) ! algorithm: divide and conquer ! matrix storage ! Real - Single precision integer optional,intent(in) :: itype=1 ! Specifies the problem type to be solved: ! = 1: A*x = (lambda)*B*x ! = 2: A*B*x = (lambda)*x ! = 3: B*A*x = (lambda)*x character intent(in) :: jobz='V' ! = 'N': Compute eigenvalues only; ! = 'V': Compute eigenvalues and eigenvectors. character intent(in) :: uplo='L' ! = 'U': Upper triangles of A and B are stored; ! = 'L': Lower triangles of A and B are stored. integer intent(hide) :: n=shape(a,0) ! The order of the matrices A and B. real intent(in,copy,out),dimension(n,n) :: a ! On entry, the symmetric matrix A. If UPLO = 'U', the ! leading N-by-N upper triangular part of A contains the ! upper triangular part of the matrix A. If UPLO = 'L', ! the leading N-by-N lower triangular part of A contains ! the lower triangular part of the matrix A. ! On exit, if JOBZ = 'V', then if INFO = 0, A contains the ! matrix Z of eigenvectors. The eigenvectors are normalized ! as follows: ! if ITYPE = 1 or 2, Z**T*B*Z = I; ! if ITYPE = 3, Z**T*inv(B)*Z = I. ! If JOBZ = 'N', then on exit the upper triangle (if UPLO='U') ! or the lower triangle (if UPLO='L') of A, including the ! diagonal, is destroyed. integer intent(hide),depend(n,a) :: lda=n ! The leading dimension of the array A. LDA >= max(1,N). real intent(in,copy),dimension(n,n) :: b ! On entry, the symmetric matrix B. If UPLO = 'U', the ! leading N-by-N upper triangular part of A contains the ! upper triangular part of the matrix B. If UPLO = 'L', ! the leading N-by-N lower triangular part of A contains ! the lower triangular part of the matrix B. ! On exit, if INFO <= N, the part of B containing the matrix is ! overwritten by the triangular factor U or L from the Cholesky ! factorization B = U**T*U or B = L*L**T. integer intent(hide),depend(n,b) :: ldb=n ! The leading dimension of the array B. LDB >= max(1,N). real intent(out),dimension(n),depend(n) :: w ! If INFO = 0, the eigenvalues in ascending order. integer intent(in),depend(n) :: lwork=1+6*n+2*n*n ! The dimension of the array WORK. real intent(hide),dimension(lwork) :: work ! REAL array, dimension (LWORK) ! On exit, if INFO = 0, WORK(1) returns the optimal LWORK. integer intent(hide),depend(n) :: liwork=3+5*n ! The dimension of the array IWORK. integer intent(hide),dimension(liwork) :: iwork ! (workspace/output) INTEGER array, dimension (LIWORK) ! On exit, if INFO = 0, IWORK(1) returns the optimal LIWORK. integer intent(out) :: info ! = 0: successful exit ! < 0: if INFO = -i, the i-th argument had an illegal value ! > 0: SPOTRF or SSYEVD returned an error code: ! <= N: if INFO = i, SSYEVD failed to converge; ! i off-diagonal elements of an intermediate ! tridiagonal form did not converge to zero; ! > N: if INFO = N + i, for 1 <= i <= N, then the leading ! minor of order i of B is not positive definite. ! The factorization of B could not be completed and ! no eigenvalues or eigenvectors were computed. end subroutine ssygvd ! !---------------------------------------------------------------------------------------------------------------------- ! subroutine dsygvd(itype,jobz,uplo,n,a,lda,b,ldb,w,work,lwork,iwork,liwork,info) ! in :froutines:ssygvd.f ! Generalized Eigenvalue Problem ! simple driver (all eigenvectors) ! algorithm: divide and conquer ! matrix storage ! Real - Double precision integer optional,intent(in) :: itype=1 ! Specifies the problem type to be solved: ! = 1: A*x = (lambda)*B*x ! = 2: A*B*x = (lambda)*x ! = 3: B*A*x = (lambda)*x character intent(in) :: jobz='V' ! = 'N': Compute eigenvalues only; ! = 'V': Compute eigenvalues and eigenvectors. character intent(in) :: uplo='L' ! = 'U': Upper triangles of A and B are stored; ! = 'L': Lower triangles of A and B are stored. integer intent(hide) :: n=shape(a,0) ! The order of the matrices A and B. double precision intent(in,copy,out),dimension(n,n) :: a ! On entry, the symmetric matrix A. If UPLO = 'U', the ! leading N-by-N upper triangular part of A contains the ! upper triangular part of the matrix A. If UPLO = 'L', ! the leading N-by-N lower triangular part of A contains ! the lower triangular part of the matrix A. ! On exit, if JOBZ = 'V', then if INFO = 0, A contains the ! matrix Z of eigenvectors. The eigenvectors are normalized ! as follows: ! if ITYPE = 1 or 2, Z**T*B*Z = I; ! if ITYPE = 3, Z**T*inv(B)*Z = I. ! If JOBZ = 'N', then on exit the upper triangle (if UPLO='U') ! or the lower triangle (if UPLO='L') of A, including the ! diagonal, is destroyed. integer intent(hide),depend(n,a) :: lda=n ! The leading dimension of the array A. LDA >= max(1,N). double precision intent(in,copy),dimension(n,n) :: b ! On entry, the symmetric matrix B. If UPLO = 'U', the ! leading N-by-N upper triangular part of A contains the ! upper triangular part of the matrix B. If UPLO = 'L', ! the leading N-by-N lower triangular part of A contains ! the lower triangular part of the matrix B. ! On exit, if INFO <= N, the part of B containing the matrix is ! overwritten by the triangular factor U or L from the Cholesky ! factorization B = U**T*U or B = L*L**T. integer intent(hide),depend(n,b) :: ldb=n ! The leading dimension of the array B. LDB >= max(1,N). double precision intent(out),dimension(n),depend(n) :: w ! If INFO = 0, the eigenvalues in ascending order. integer intent(in),depend(n) :: lwork=1+6*n+2*n*n ! The dimension of the array WORK. double precision intent(hide),dimension(lwork) :: work ! REAL array, dimension (LWORK) ! On exit, if INFO = 0, WORK(1) returns the optimal LWORK. integer intent(hide),depend(n) :: liwork=3+5*n ! The dimension of the array IWORK. integer intent(hide),dimension(liwork) :: iwork ! (workspace/output) INTEGER array, dimension (LIWORK) ! On exit, if INFO = 0, IWORK(1) returns the optimal LIWORK. integer intent(out) :: info ! = 0: successful exit ! < 0: if INFO = -i, the i-th argument had an illegal value ! > 0: SPOTRF or SSYEVD returned an error code: ! <= N: if INFO = i, SSYEVD failed to converge; ! i off-diagonal elements of an intermediate ! tridiagonal form did not converge to zero; ! > N: if INFO = N + i, for 1 <= i <= N, then the leading ! minor of order i of B is not positive definite. ! The factorization of B could not be completed and ! no eigenvalues or eigenvectors were computed. end subroutine dsygvd ! !---------------------------------------------------------------------------------------------------------------------- ! subroutine chegvd(itype,jobz,uplo,n,a,lda,b,ldb,w,work,lwork,rwork,lrwork,iwork,liwork,info) ! in :froutines:ssygvd.f ! Generalized Eigenvalue Problem ! simple driver (all eigenvectors) ! algorithm: divide and conquer ! matrix storage ! Complex - Single precision integer optional,intent(in) :: itype=1 ! Specifies the problem type to be solved: ! = 1: A*x = (lambda)*B*x ! = 2: A*B*x = (lambda)*x ! = 3: B*A*x = (lambda)*x character intent(in) :: jobz='V' ! = 'N': Compute eigenvalues only; ! = 'V': Compute eigenvalues and eigenvectors. character intent(in) :: uplo='L' ! = 'U': Upper triangles of A and B are stored; ! = 'L': Lower triangles of A and B are stored. integer intent(hide) :: n=shape(a,0) ! The order of the matrices A and B. complex intent(in,copy,out),dimension(n,n) :: a ! On entry, the symmetric matrix A. If UPLO = 'U', the ! leading N-by-N upper triangular part of A contains the ! upper triangular part of the matrix A. If UPLO = 'L', ! the leading N-by-N lower triangular part of A contains ! the lower triangular part of the matrix A. ! On exit, if JOBZ = 'V', then if INFO = 0, A contains the ! matrix Z of eigenvectors. The eigenvectors are normalized ! as follows: ! if ITYPE = 1 or 2, Z**T*B*Z = I; ! if ITYPE = 3, Z**T*inv(B)*Z = I. ! If JOBZ = 'N', then on exit the upper triangle (if UPLO='U') ! or the lower triangle (if UPLO='L') of A, including the ! diagonal, is destroyed. integer intent(hide),depend(n,a) :: lda=n ! The leading dimension of the array A. LDA >= max(1,N). complex intent(in,copy),dimension(n,n) :: b ! On entry, the symmetric matrix B. If UPLO = 'U', the ! leading N-by-N upper triangular part of A contains the ! upper triangular part of the matrix B. If UPLO = 'L', ! the leading N-by-N lower triangular part of A contains ! the lower triangular part of the matrix B. ! On exit, if INFO <= N, the part of B containing the matrix is ! overwritten by the triangular factor U or L from the Cholesky ! factorization B = U**T*U or B = L*L**T. integer intent(hide),depend(n,b) :: ldb=n ! The leading dimension of the array B. LDB >= max(1,N). real intent(out),dimension(n),depend(n) :: w ! If INFO = 0, the eigenvalues in ascending order. integer intent(in),depend(n) :: lwork=2*n+n*n ! The dimension of the array WORK. complex intent(hide),dimension(lwork) :: work ! REAL array, dimension (LWORK) ! On exit, if INFO = 0, WORK(1) returns the optimal LWORK. integer intent(hide),depend(n) :: lrwork=1+5*n+2*n*n ! The dimension of the array RWORK. real intent(hide),dimension(lrwork) :: rwork ! REAL array, dimension (LRWORK) ! On exit, if INFO = 0, WORK(1) returns the optimal LWORK. integer intent(hide),depend(n) :: liwork=3+5*n ! The dimension of the array IWORK. integer intent(hide),dimension(liwork) :: iwork ! (workspace/output) INTEGER array, dimension (LIWORK) ! On exit, if INFO = 0, IWORK(1) returns the optimal LIWORK. integer intent(out) :: info ! = 0: successful exit ! < 0: if INFO = -i, the i-th argument had an illegal value ! > 0: SPOTRF or SSYEVD returned an error code: ! <= N: if INFO = i, SSYEVD failed to converge; ! i off-diagonal elements of an intermediate ! tridiagonal form did not converge to zero; ! > N: if INFO = N + i, for 1 <= i <= N, then the leading ! minor of order i of B is not positive definite. ! The factorization of B could not be completed and ! no eigenvalues or eigenvectors were computed. end subroutine chegvd ! !---------------------------------------------------------------------------------------------------------------------- ! subroutine zhegvd(itype,jobz,uplo,n,a,lda,b,ldb,w,work,lwork,rwork,lrwork,iwork,liwork,info) ! in :froutines:ssygvd.f ! Generalized Eigenvalue Problem ! simple driver (all eigenvectors) ! algorithm: divide and conquer ! matrix storage ! Complex - Double precision integer optional,intent(in) :: itype=1 ! Specifies the problem type to be solved: ! = 1: A*x = (lambda)*B*x ! = 2: A*B*x = (lambda)*x ! = 3: B*A*x = (lambda)*x character intent(in) :: jobz='V' ! = 'N': Compute eigenvalues only; ! = 'V': Compute eigenvalues and eigenvectors. character intent(in) :: uplo='L' ! = 'U': Upper triangles of A and B are stored; ! = 'L': Lower triangles of A and B are stored. integer intent(hide) :: n=shape(a,0) ! The order of the matrices A and B. complex*16 intent(in,copy,out),dimension(n,n) :: a ! On entry, the symmetric matrix A. If UPLO = 'U', the ! leading N-by-N upper triangular part of A contains the ! upper triangular part of the matrix A. If UPLO = 'L', ! the leading N-by-N lower triangular part of A contains ! the lower triangular part of the matrix A. ! On exit, if JOBZ = 'V', then if INFO = 0, A contains the ! matrix Z of eigenvectors. The eigenvectors are normalized ! as follows: ! if ITYPE = 1 or 2, Z**T*B*Z = I; ! if ITYPE = 3, Z**T*inv(B)*Z = I. ! If JOBZ = 'N', then on exit the upper triangle (if UPLO='U') ! or the lower triangle (if UPLO='L') of A, including the ! diagonal, is destroyed. integer intent(hide),depend(n,a) :: lda=n ! The leading dimension of the array A. LDA >= max(1,N). complex*16 intent(in,copy),dimension(n,n) :: b ! On entry, the symmetric matrix B. If UPLO = 'U', the ! leading N-by-N upper triangular part of A contains the ! upper triangular part of the matrix B. If UPLO = 'L', ! the leading N-by-N lower triangular part of A contains ! the lower triangular part of the matrix B. ! On exit, if INFO <= N, the part of B containing the matrix is ! overwritten by the triangular factor U or L from the Cholesky ! factorization B = U**T*U or B = L*L**T. integer intent(hide),depend(n,b) :: ldb=n ! The leading dimension of the array B. LDB >= max(1,N). double precision intent(out),dimension(n),depend(n) :: w ! If INFO = 0, the eigenvalues in ascending order. integer intent(in),depend(n) :: lwork=2*n+n*n ! The dimension of the array WORK. complex*16 intent(hide),dimension(lwork) :: work ! REAL array, dimension (LWORK) ! On exit, if INFO = 0, WORK(1) returns the optimal LWORK. integer intent(hide),depend(n) :: lrwork=1+5*n+2*n*n ! The dimension of the array RWORK. double precision intent(hide),dimension(lrwork) :: rwork ! REAL array, dimension (LRWORK) ! On exit, if INFO = 0, WORK(1) returns the optimal LWORK. integer intent(hide),depend(n) :: liwork=3+5*n ! The dimension of the array IWORK. integer intent(hide),dimension(liwork) :: iwork ! (workspace/output) INTEGER array, dimension (LIWORK) ! On exit, if INFO = 0, IWORK(1) returns the optimal LIWORK. integer intent(out) :: info ! = 0: successful exit ! < 0: if INFO = -i, the i-th argument had an illegal value ! > 0: SPOTRF or SSYEVD returned an error code: ! <= N: if INFO = i, SSYEVD failed to converge; ! i off-diagonal elements of an intermediate ! tridiagonal form did not converge to zero; ! > N: if INFO = N + i, for 1 <= i <= N, then the leading ! minor of order i of B is not positive definite. ! The factorization of B could not be completed and ! no eigenvalues or eigenvectors were computed. end subroutine zhegvd! ! Expert routines for generalized eigenvalue problem ! subroutine ssygvx(itype,jobz,range,uplo,n,a,lda,b,ldb,vl,vu,il,iu,abstol,m,w,z,ldz,work,lwork,iwork,ifail,info) ! in :froutines:ssygvx.f ! Generalized Eigenvalue Problem ! expert driver (selected eigenvectors) ! algorithm: standard ! matrix storage ! Real - Single precision integer optional,intent(in) :: itype=1 ! Specifies the problem type to be solved: ! = 1: A*x = (lambda)*B*x ! = 2: A*B*x = (lambda)*x ! = 3: B*A*x = (lambda)*x character intent(in) :: jobz='V' ! = 'N': Compute eigenvalues only; ! = 'V': Compute eigenvalues and eigenvectors. character intent(hide) :: range='I' ! = 'A': all eigenvalues will be found. ! = 'V': all eigenvalues in the half-open interval (VL,VU] will be found. ! = 'I': the IL-th through IU-th eigenvalues will be found. character intent(in) :: uplo='L' ! = 'U': Upper triangles of A and B are stored; ! = 'L': Lower triangles of A and B are stored. integer intent(hide) :: n=shape(a,0) ! The order of the matrices A and B. real intent(in,copy),dimension(n,n) :: a ! On entry, the symmetric matrix A. If UPLO = 'U', the ! leading N-by-N upper triangular part of A contains the ! upper triangular part of the matrix A. If UPLO = 'L', ! the leading N-by-N lower triangular part of A contains ! the lower triangular part of the matrix A. ! On exit, the lower triangle (if UPLO='L') or the upper ! triangle (if UPLO='U') of A, including the diagonal, is ! destroyed. integer intent(hide),depend(n,a) :: lda=n ! The leading dimension of the array A. LDA >= max(1,N). real intent(in,copy),dimension(n,n) :: b ! On entry, the symmetric matrix B. If UPLO = 'U', the ! leading N-by-N upper triangular part of B contains the ! upper triangular part of the matrix B. If UPLO = 'L', ! the leading N-by-N lower triangular part of B contains ! the lower triangular part of the matrix B. ! On exit, if INFO <= N, the part of B containing the matrix is ! overwritten by the triangular factor U or L from the Cholesky ! factorization B = U**T*U or B = L*L**T. integer intent(hide),depend(n,b) :: ldb=n ! The leading dimension of the array B. LDB >= max(1,N). real intent(hide) :: vl=0. ! If RANGE='V', the lower and upper bounds of the interval to real intent(hide) :: vu=0. ! be searched for eigenvalues. VL < VU. Not referenced if RANGE = 'A' or 'I'. integer optional,intent(in) :: il=1 ! If RANGE='I', the indices (in ascending order) of the integer intent(in) :: iu ! smallest and largest eigenvalues to be returned. 1<=IL<=IU<= N real intent(hide) :: abstol=0. ! The absolute error tolerance for the eigenvalues. ! An approximate eigenvalue is accepted as converged ! when it is determined to lie in an interval [a,b] ! of width less than or equal to ! ABSTOL + EPS * max( |a|,|b| ) , ! where EPS is the machine precision. If ABSTOL is less than ! or equal to zero, then EPS*|T| will be used in its place, ! where |T| is the 1-norm of the tridiagonal matrix obtained ! by reducing A to tridiagonal form. ! Eigenvalues will be computed most accurately when ABSTOL is ! set to twice the underflow threshold 2*SLAMCH('S'), not zero. ! If this routine returns with INFO>0, indicating that some ! eigenvectors did not converge, try setting ABSTOL to 2*SLAMCH('S'). integer intent(hide),depend(iu) :: m=iu-il+1 ! The total number of eigenvalues found. 0 <= M <= N. ! If RANGE = 'A', M = N, and if RANGE = 'I', M = IU-IL+1. real intent(out),dimension(n),depend(n) :: w ! If INFO = 0, the first M elements contain the selected ! eigenvalues in ascending order real intent(out),dimension(n,m),depend(n,m) :: z ! If JOBZ = 'V', then if INFO = 0, the first M columns of Z ! contain the orthonormal eigenvectors of the matrix A ! corresponding to the selected eigenvalues, with the i-th ! column of Z holding the eigenvector associated with W(i). ! The eigenvectors are normalized as follows: ! if ITYPE = 1 or 2, Z**T*B*Z = I; ! if ITYPE = 3, Z**T*inv(B)*Z = I. ! If an eigenvector fails to converge, then that column of Z ! contains the latest approximation to the eigenvector, and the ! index of the eigenvector is returned in IFAIL. ! Note: the user must ensure that at least max(1,M) columns are ! supplied in the array Z; if RANGE = 'V', the exact value of M ! is not known in advance and an upper bound must be used. integer intent(hide),check(shape(z,0)==ldz),depend(n,z) :: ldz=n ! The leading dimension of the array Z. integer intent(in),depend(n) :: lwork=8*n ! The length of the array WORK. LWORK >= max(1,8*N). real intent(hide),dimension(lwork),depend(n,lwork) :: work ! (workspace) REAL array, dimension (LWORK) ! On exit, if INFO = 0, WORK(1) returns the optimal LWORK. integer intent(hide),dimension(5*n) :: iwork ! (workspace) INTEGER array, dimension (5*N) integer intent(out),dimension(n),depend(n) :: ifail ! If JOBZ = 'V', then if INFO = 0, the first M elements of ! IFAIL are zero. If INFO > 0, then IFAIL contains the ! indices of the eigenvectors that failed to converge. ! If JOBZ = 'N', then IFAIL is not referenced. integer intent(out) :: info ! = 0: successful exit ! < 0: if INFO = -i, the i-th argument had an illegal value ! > 0: SPOTRF or SSYEVX returned an error code: ! <= N: if INFO = i, SSYEVX failed to converge; ! i off-diagonal elements of an intermediate ! tridiagonal form did not converge to zero; ! > N: if INFO = N + i, for 1 <= i <= N, then the leading ! minor of order i of B is not positive definite. ! The factorization of B could not be completed and ! no eigenvalues or eigenvectors were computed. end subroutine ssygvx ! !---------------------------------------------------------------------------------------------------------------------- ! subroutine dsygvx(itype,jobz,range,uplo,n,a,lda,b,ldb,vl,vu,il,iu,abstol,m,w,z,ldz,work,lwork,iwork,ifail,info) ! in :froutines:ssygvx.f ! Generalized Eigenvalue Problem ! expert driver (selected eigenvectors) ! algorithm: standard ! matrix storage ! Real - Double precision integer optional,intent(in) :: itype=1 ! Specifies the problem type to be solved: ! = 1: A*x = (lambda)*B*x ! = 2: A*B*x = (lambda)*x ! = 3: B*A*x = (lambda)*x character intent(in) :: jobz='V' ! = 'N': Compute eigenvalues only; ! = 'V': Compute eigenvalues and eigenvectors. character intent(hide) :: range='I' ! = 'A': all eigenvalues will be found. ! = 'V': all eigenvalues in the half-open interval (VL,VU] will be found. ! = 'I': the IL-th through IU-th eigenvalues will be found. character intent(in) :: uplo='L' ! = 'U': Upper triangles of A and B are stored; ! = 'L': Lower triangles of A and B are stored. integer intent(hide) :: n=shape(a,0) ! The order of the matrices A and B. double precision intent(in,copy),dimension(n,n) :: a ! On entry, the symmetric matrix A. If UPLO = 'U', the ! leading N-by-N upper triangular part of A contains the ! upper triangular part of the matrix A. If UPLO = 'L', ! the leading N-by-N lower triangular part of A contains ! the lower triangular part of the matrix A. ! On exit, the lower triangle (if UPLO='L') or the upper ! triangle (if UPLO='U') of A, including the diagonal, is ! destroyed. integer intent(hide),depend(n,a) :: lda=n ! The leading dimension of the array A. LDA >= max(1,N). double precision intent(in,copy),dimension(n,n) :: b ! On entry, the symmetric matrix B. If UPLO = 'U', the ! leading N-by-N upper triangular part of B contains the ! upper triangular part of the matrix B. If UPLO = 'L', ! the leading N-by-N lower triangular part of B contains ! the lower triangular part of the matrix B. ! On exit, if INFO <= N, the part of B containing the matrix is ! overwritten by the triangular factor U or L from the Cholesky ! factorization B = U**T*U or B = L*L**T. integer intent(hide),depend(n,b) :: ldb=n ! The leading dimension of the array B. LDB >= max(1,N). double precision intent(hide) :: vl=0. ! If RANGE='V', the lower and upper bounds of the interval to double precision intent(hide) :: vu=0. ! be searched for eigenvalues. VL < VU. Not referenced if RANGE = 'A' or 'I'. integer optional,intent(in) :: il=1 ! If RANGE='I', the indices (in ascending order) of the integer intent(in) :: iu ! smallest and largest eigenvalues to be returned. 1<=IL<=IU<= N double precision intent(hide) :: abstol=0. ! The absolute error tolerance for the eigenvalues. ! An approximate eigenvalue is accepted as converged ! when it is determined to lie in an interval [a,b] ! of width less than or equal to ! ABSTOL + EPS * max( |a|,|b| ) , ! where EPS is the machine precision. If ABSTOL is less than ! or equal to zero, then EPS*|T| will be used in its place, ! where |T| is the 1-norm of the tridiagonal matrix obtained ! by reducing A to tridiagonal form. ! Eigenvalues will be computed most accurately when ABSTOL is ! set to twice the underflow threshold 2*SLAMCH('S'), not zero. ! If this routine returns with INFO>0, indicating that some ! eigenvectors did not converge, try setting ABSTOL to 2*SLAMCH('S'). integer intent(hide),depend(iu) :: m=iu-il+1 ! The total number of eigenvalues found. 0 <= M <= N. ! If RANGE = 'A', M = N, and if RANGE = 'I', M = IU-IL+1. double precision intent(out),dimension(n),depend(n) :: w ! If INFO = 0, the first M elements contain the selected ! eigenvalues in ascending order double precision intent(out),dimension(n,m),depend(n,m) :: z ! If JOBZ = 'V', then if INFO = 0, the first M columns of Z ! contain the orthonormal eigenvectors of the matrix A ! corresponding to the selected eigenvalues, with the i-th ! column of Z holding the eigenvector associated with W(i). ! The eigenvectors are normalized as follows: ! if ITYPE = 1 or 2, Z**T*B*Z = I; ! if ITYPE = 3, Z**T*inv(B)*Z = I. ! If an eigenvector fails to converge, then that column of Z ! contains the latest approximation to the eigenvector, and the ! index of the eigenvector is returned in IFAIL. ! Note: the user must ensure that at least max(1,M) columns are ! supplied in the array Z; if RANGE = 'V', the exact value of M ! is not known in advance and an upper bound must be used. integer intent(hide),check(shape(z,0)==ldz),depend(n,z) :: ldz=n ! The leading dimension of the array Z. integer intent(in),depend(n) :: lwork=8*n ! The length of the array WORK. LWORK >= max(1,8*N). double precision intent(hide),dimension(lwork),depend(n,lwork) :: work ! (workspace) REAL array, dimension (LWORK) ! On exit, if INFO = 0, WORK(1) returns the optimal LWORK. integer intent(hide),dimension(5*n) :: iwork ! (workspace) INTEGER array, dimension (5*N) integer intent(out),dimension(n),depend(n) :: ifail ! If JOBZ = 'V', then if INFO = 0, the first M elements of ! IFAIL are zero. If INFO > 0, then IFAIL contains the ! indices of the eigenvectors that failed to converge. ! If JOBZ = 'N', then IFAIL is not referenced. integer intent(out) :: info ! = 0: successful exit ! < 0: if INFO = -i, the i-th argument had an illegal value ! > 0: SPOTRF or SSYEVX returned an error code: ! <= N: if INFO = i, SSYEVX failed to converge; ! i off-diagonal elements of an intermediate ! tridiagonal form did not converge to zero; ! > N: if INFO = N + i, for 1 <= i <= N, then the leading ! minor of order i of B is not positive definite. ! The factorization of B could not be completed and ! no eigenvalues or eigenvectors were computed. end subroutine dsygvx ! !---------------------------------------------------------------------------------------------------------------------- ! subroutine chegvx(itype,jobz,range,uplo,n,a,lda,b,ldb,vl,vu,il,iu,abstol,m,w,z,ldz,work,lwork,rwork,iwork,ifail,info) ! in :froutines:ssygvx.f ! Generalized Eigenvalue Problem ! expert driver (selected eigenvectors) ! algorithm: standard ! matrix storage ! Complex - Single precision integer optional,intent(in) :: itype=1 ! Specifies the problem type to be solved: ! = 1: A*x = (lambda)*B*x ! = 2: A*B*x = (lambda)*x ! = 3: B*A*x = (lambda)*x character intent(in) :: jobz='V' ! = 'N': Compute eigenvalues only; ! = 'V': Compute eigenvalues and eigenvectors. character intent(hide) :: range='I' ! = 'A': all eigenvalues will be found. ! = 'V': all eigenvalues in the half-open interval (VL,VU] will be found. ! = 'I': the IL-th through IU-th eigenvalues will be found. character intent(in) :: uplo='L' ! = 'U': Upper triangles of A and B are stored; ! = 'L': Lower triangles of A and B are stored. integer intent(hide) :: n=shape(a,0) ! The order of the matrices A and B. complex intent(in,copy),dimension(n,n) :: a ! On entry, the symmetric matrix A. If UPLO = 'U', the ! leading N-by-N upper triangular part of A contains the ! upper triangular part of the matrix A. If UPLO = 'L', ! the leading N-by-N lower triangular part of A contains ! the lower triangular part of the matrix A. ! On exit, the lower triangle (if UPLO='L') or the upper ! triangle (if UPLO='U') of A, including the diagonal, is ! destroyed. integer intent(hide),depend(n,a) :: lda=n ! The leading dimension of the array A. LDA >= max(1,N). complex intent(in,copy),dimension(n,n) :: b ! On entry, the symmetric matrix B. If UPLO = 'U', the ! leading N-by-N upper triangular part of B contains the ! upper triangular part of the matrix B. If UPLO = 'L', ! the leading N-by-N lower triangular part of B contains ! the lower triangular part of the matrix B. ! On exit, if INFO <= N, the part of B containing the matrix is ! overwritten by the triangular factor U or L from the Cholesky ! factorization B = U**T*U or B = L*L**T. integer intent(hide),depend(n,b) :: ldb=n ! The leading dimension of the array B. LDB >= max(1,N). real intent(hide) :: vl=0. ! If RANGE='V', the lower and upper bounds of the interval to real intent(hide) :: vu=0. ! be searched for eigenvalues. VL < VU. Not referenced if RANGE = 'A' or 'I'. integer optional,intent(in) :: il=1 ! If RANGE='I', the indices (in ascending order) of the integer intent(in) :: iu ! smallest and largest eigenvalues to be returned. 1<=IL<=IU<= N real intent(hide) :: abstol=0. ! The absolute error tolerance for the eigenvalues. ! An approximate eigenvalue is accepted as converged ! when it is determined to lie in an interval [a,b] ! of width less than or equal to ! ABSTOL + EPS * max( |a|,|b| ) , ! where EPS is the machine precision. If ABSTOL is less than ! or equal to zero, then EPS*|T| will be used in its place, ! where |T| is the 1-norm of the tridiagonal matrix obtained ! by reducing A to tridiagonal form. ! Eigenvalues will be computed most accurately when ABSTOL is ! set to twice the underflow threshold 2*SLAMCH('S'), not zero. ! If this routine returns with INFO>0, indicating that some ! eigenvectors did not converge, try setting ABSTOL to 2*SLAMCH('S'). integer intent(hide),depend(iu) :: m=iu-il+1 ! The total number of eigenvalues found. 0 <= M <= N. ! If RANGE = 'A', M = N, and if RANGE = 'I', M = IU-IL+1. real intent(out),dimension(n),depend(n) :: w ! If INFO = 0, the first M elements contain the selected ! eigenvalues in ascending order complex intent(out),dimension(n,m),depend(n,m) :: z ! If JOBZ = 'V', then if INFO = 0, the first M columns of Z ! contain the orthonormal eigenvectors of the matrix A ! corresponding to the selected eigenvalues, with the i-th ! column of Z holding the eigenvector associated with W(i). ! The eigenvectors are normalized as follows: ! if ITYPE = 1 or 2, Z**T*B*Z = I; ! if ITYPE = 3, Z**T*inv(B)*Z = I. ! If an eigenvector fails to converge, then that column of Z ! contains the latest approximation to the eigenvector, and the ! index of the eigenvector is returned in IFAIL. ! Note: the user must ensure that at least max(1,M) columns are ! supplied in the array Z; if RANGE = 'V', the exact value of M ! is not known in advance and an upper bound must be used. integer intent(hide),check(shape(z,0)==ldz),depend(n,z) :: ldz=n ! The leading dimension of the array Z. integer intent(in),depend(n) :: lwork=2*n ! The length of the array WORK. LWORK >= max(1,2*N-1). complex intent(hide),dimension(lwork),depend(n,lwork) :: work ! (workspace) REAL array, dimension (LWORK) ! On exit, if INFO = 0, WORK(1) returns the optimal LWORK. real intent(hide),dimension(7*n) :: rwork ! (workspace) REAL array, dimension (5*N) integer intent(hide),dimension(5*n) :: iwork ! (workspace) INTEGER array, dimension (5*N) integer intent(out),dimension(n),depend(n) :: ifail ! If JOBZ = 'V', then if INFO = 0, the first M elements of ! IFAIL are zero. If INFO > 0, then IFAIL contains the ! indices of the eigenvectors that failed to converge. ! If JOBZ = 'N', then IFAIL is not referenced. integer intent(out) :: info ! = 0: successful exit ! < 0: if INFO = -i, the i-th argument had an illegal value ! > 0: SPOTRF or SSYEVX returned an error code: ! <= N: if INFO = i, SSYEVX failed to converge; ! i off-diagonal elements of an intermediate ! tridiagonal form did not converge to zero; ! > N: if INFO = N + i, for 1 <= i <= N, then the leading ! minor of order i of B is not positive definite. ! The factorization of B could not be completed and ! no eigenvalues or eigenvectors were computed. end subroutine chegvx ! !---------------------------------------------------------------------------------------------------------------------- ! subroutine zhegvx(itype,jobz,range,uplo,n,a,lda,b,ldb,vl,vu,il,iu,abstol,m,w,z,ldz,work,lwork,rwork,iwork,ifail,info) ! in :froutines:ssygvx.f ! Generalized Eigenvalue Problem ! expert driver (selected eigenvectors) ! algorithm: standard ! matrix storage ! Complex - Double precision integer optional,intent(in) :: itype=1 ! Specifies the problem type to be solved: ! = 1: A*x = (lambda)*B*x ! = 2: A*B*x = (lambda)*x ! = 3: B*A*x = (lambda)*x character intent(in) :: jobz='V' ! = 'N': Compute eigenvalues only; ! = 'V': Compute eigenvalues and eigenvectors. character intent(hide) :: range='I' ! = 'A': all eigenvalues will be found. ! = 'V': all eigenvalues in the half-open interval (VL,VU] will be found. ! = 'I': the IL-th through IU-th eigenvalues will be found. character intent(in) :: uplo='L' ! = 'U': Upper triangles of A and B are stored; ! = 'L': Lower triangles of A and B are stored. integer intent(hide) :: n=shape(a,0) ! The order of the matrices A and B. complex*16 intent(in,copy),dimension(n,n) :: a ! On entry, the symmetric matrix A. If UPLO = 'U', the ! leading N-by-N upper triangular part of A contains the ! upper triangular part of the matrix A. If UPLO = 'L', ! the leading N-by-N lower triangular part of A contains ! the lower triangular part of the matrix A. ! On exit, the lower triangle (if UPLO='L') or the upper ! triangle (if UPLO='U') of A, including the diagonal, is ! destroyed. integer intent(hide),depend(n,a) :: lda=n ! The leading dimension of the array A. LDA >= max(1,N). complex*16 intent(in,copy),dimension(n,n) :: b ! On entry, the symmetric matrix B. If UPLO = 'U', the ! leading N-by-N upper triangular part of B contains the ! upper triangular part of the matrix B. If UPLO = 'L', ! the leading N-by-N lower triangular part of B contains ! the lower triangular part of the matrix B. ! On exit, if INFO <= N, the part of B containing the matrix is ! overwritten by the triangular factor U or L from the Cholesky ! factorization B = U**T*U or B = L*L**T. integer intent(hide),depend(n,b) :: ldb=n ! The leading dimension of the array B. LDB >= max(1,N). double precision intent(hide) :: vl=0. ! If RANGE='V', the lower and upper bounds of the interval to double precision intent(hide) :: vu=0. ! be searched for eigenvalues. VL < VU. Not referenced if RANGE = 'A' or 'I'. integer optional,intent(in) :: il=1 ! If RANGE='I', the indices (in ascending order) of the integer intent(in) :: iu ! smallest and largest eigenvalues to be returned. 1<=IL<=IU<= N double precision intent(hide) :: abstol=0. ! The absolute error tolerance for the eigenvalues. ! An approximate eigenvalue is accepted as converged ! when it is determined to lie in an interval [a,b] ! of width less than or equal to ! ABSTOL + EPS * max( |a|,|b| ) , ! where EPS is the machine precision. If ABSTOL is less than ! or equal to zero, then EPS*|T| will be used in its place, ! where |T| is the 1-norm of the tridiagonal matrix obtained ! by reducing A to tridiagonal form. ! Eigenvalues will be computed most accurately when ABSTOL is ! set to twice the underflow threshold 2*SLAMCH('S'), not zero. ! If this routine returns with INFO>0, indicating that some ! eigenvectors did not converge, try setting ABSTOL to 2*SLAMCH('S'). integer intent(hide),depend(iu) :: m=iu-il+1 ! The total number of eigenvalues found. 0 <= M <= N. ! If RANGE = 'A', M = N, and if RANGE = 'I', M = IU-IL+1. double precision intent(out),dimension(n),depend(n) :: w ! If INFO = 0, the first M elements contain the selected ! eigenvalues in ascending order complex*16 intent(out),dimension(n,m),depend(n,m) :: z ! If JOBZ = 'V', then if INFO = 0, the first M columns of Z ! contain the orthonormal eigenvectors of the matrix A ! corresponding to the selected eigenvalues, with the i-th ! column of Z holding the eigenvector associated with W(i). ! The eigenvectors are normalized as follows: ! if ITYPE = 1 or 2, Z**T*B*Z = I; ! if ITYPE = 3, Z**T*inv(B)*Z = I. ! If an eigenvector fails to converge, then that column of Z ! contains the latest approximation to the eigenvector, and the ! index of the eigenvector is returned in IFAIL. ! Note: the user must ensure that at least max(1,M) columns are ! supplied in the array Z; if RANGE = 'V', the exact value of M ! is not known in advance and an upper bound must be used. integer intent(hide),check(shape(z,0)==ldz),depend(n,z) :: ldz=n ! The leading dimension of the array Z. integer intent(in),depend(n) :: lwork=2*n ! The length of the array WORK. LWORK >= max(1,2*N-1). complex*16 intent(hide),dimension(lwork),depend(n,lwork) :: work ! (workspace) REAL array, dimension (LWORK) ! On exit, if INFO = 0, WORK(1) returns the optimal LWORK. double precision intent(hide),dimension(7*n) :: rwork ! (workspace) REAL array, dimension (5*N) integer intent(hide),dimension(5*n) :: iwork ! (workspace) INTEGER array, dimension (5*N) integer intent(out),dimension(n),depend(n) :: ifail ! If JOBZ = 'V', then if INFO = 0, the first M elements of ! IFAIL are zero. If INFO > 0, then IFAIL contains the ! indices of the eigenvectors that failed to converge. ! If JOBZ = 'N', then IFAIL is not referenced. integer intent(out) :: info ! = 0: successful exit ! < 0: if INFO = -i, the i-th argument had an illegal value ! > 0: SPOTRF or SSYEVX returned an error code: ! <= N: if INFO = i, SSYEVX failed to converge; ! i off-diagonal elements of an intermediate ! tridiagonal form did not converge to zero; ! > N: if INFO = N + i, for 1 <= i <= N, then the leading ! minor of order i of B is not positive definite. ! The factorization of B could not be completed and ! no eigenvalues or eigenvectors were computed. end subroutine zhegvx end interface end python module froutines symeig-1.5/setup.py000066400000000000000000000047421111257553200143770ustar00rootroot00000000000000from os.path import join from numpy.distutils.core import setup, Extension from numpy.distutils.system_info import get_info short_description = ("The symeig module contains a python wrapper for the" " LAPACK functions to solve the standard and generalized " "eigenvalue problems for symmetric and hermitian" " matrices.") long_description = """ The symeig module contains a Python wrapper for the LAPACK functions to solve the standard and generalized eigenvalue problems for symmetric and hermitian matrices. Those specialized algorithms give an important speed-up with respect to the generic LAPACK eigenvalue problem solver used by NumPy (linalg.eig and linalg.eigh). The wrapper function symeig automatically selects the appropriate LAPACK routine. It is also possible to request only a subset of all eigenvalues, which consumes less memory and results sometimes in an additional speed-up, especially for large matrices. The symeig routine is integrated in the 0.7 release of SciPy. It is available there as scipy.linalg.eigh with a slightly different signature. """ classifiers = ["Development Status :: 5 - Production/Stable", "Intended Audience :: Developers", "Intended Audience :: Science/Research", "License :: OSI Approved :: BSD License" "Operating System :: OS Independent", "Programming Language :: Python", "Topic :: Scientific/Engineering :: Information Analysis", "Topic :: Scientific/Engineering :: Mathematics", "Topic :: Software Development :: Algorithms"] lapack_opt = get_info('lapack_opt') froutines_ext = Extension('froutines',['froutines.pyf'],\ **lapack_opt) setup(name = 'symeig', version = '1.5', author = 'Pietro Berkes and Tiziano Zito', author_email = 'berkes@brandeis.edu, tiziano.zito@bccn-berlin.de', maintainer = 'Pietro Berkes and Tiziano Zito', maintainer_email = 'berkes@brandeis.edu, tiziano.zito@bccn-berlin.de', license = "BSD license", platforms = ["Any"], url = 'http://mdp-toolkit.sourceforge.net/symeig.html', download_url = 'http://sourceforge.net/project/showfiles.php?group_id=116959', description = short_description, long_description = long_description, packages = ['symeig', 'symeig.test'], package_dir = {'symeig': '.'}, ext_package = 'symeig', ext_modules = [froutines_ext]) symeig-1.5/symeig.py000066400000000000000000000176621111257553200145410ustar00rootroot00000000000000import numpy import froutines _symeig_pfx = {'f':'ssy', 'd':'dsy', 'F':'che', 'D':'zhe'} class SymeigException(Exception): pass class LeadingMinorException(SymeigException): pass # definition of symmetric eigenvalue solver def symeig(A,B=None,eigenvectors=1,turbo="on",range=None,type=1,overwrite=False): """Solve standard and generalized eigenvalue problem for symmetric and hermitian matrices. Syntax: w,Z = symeig(A) w = symeig(A,eigenvectors=0) w,Z = symeig(A,range=(lo,hi)) w,Z = symeig(A,B,range=(lo,hi)) Inputs: A -- An N x N real symmetric or complex hermitian matrix. B -- An N x N real symmetric or complex hermitian definite positive matrix. eigenvectors -- if set return eigenvalues and eigenvectors, otherwise only eigenvalues turbo -- (only for generalized eigenvalue problem and if range=None) if turbo = "on", use divide and conquer algorithm (faster but expensive in memory) range -- the tuple (lo,hi) represent the indexes of the smallest and largest (in ascending order) eigenvalues to be returned. 1 <= lo < hi <= N if range = None, returns all eigenvalues and eigenvectors. type -- (only for generalized eigenvalue problem) Specifies the problem type to be solved: type = 1: A*x = (lambda)*B*x = 2: A*B*x = (lambda)*x = 3: B*A*x = (lambda)*x overwrite -- if 'overwrite' is set, computations are done inplace, A and B are overwritten during calculation (you save memory but loose the matrices). If matrices are complex this argument is ignored. Outputs: w -- (selected) eigenvalues in ascending order. Z -- if range = None, Z contains the matrix of eigenvectors, normalized as follows: Z^H * A * Z = lambda and - type = 1 or 2: Z^H * B * Z = I - type = 3 : Z^H * B^(-1) * Z = I where ^H means conjugate transpose. if range, an N x M matrix containing the orthonormal eigenvectors of the matrix A corresponding to the selected eigenvalues, with the i-th column of Z holding the eigenvector associated with w[i]. The eigenvectors are normalized as above. """ # check dimensions: if (len(A.shape) != 2) or (A.shape[0] != A.shape[1]): msg = "wrong A dimensions %s, should be (n, n)"%str(A.shape) raise SymeigException, msg if (B is not None) and (B.shape != A.shape): msg = "wrong B dimensions: "+str(B.shape) raise SymeigException, msg # Set job for fortran routines _job = (eigenvectors and 'V') or 'N' # apply conversion rules to find the common conversion type dtype = _greatest_common_dtype([A,B]) # cast matrices to have the same dtype A = _refcast(A,dtype) B = _refcast(B,dtype) # spare a copy if we can #if A.flags.c_contiguous and not numpy.iscomplexobj(A): # A = A.T #if B is not None and A.flags.c_contiguous and not numpy.iscomplexobj(B): # B = B.T # sanitize range range = _sanitize_range(A.shape[0], range) # Standard Eigenvalue Problem # Use '*evr' routines if B is None: evr = get_froutines_func("evr",_symeig_pfx,dtype) if range is None: w,Z,info = evr(A,jobz=_job,range="A",il=1,iu=A.shape[0], overwrite_a=overwrite) else: (lo,hi)=range w_tot,Z,info = evr(A,jobz=_job,range="I",il=lo,iu=hi, overwrite_a=overwrite) w=w_tot[0:hi-lo+1] # Generalized Eigenvalue Problem else: # Use '*gvx' routines if range is specified if range is not None: gvx = get_froutines_func("gvx",_symeig_pfx,dtype) (lo,hi)=range w_tot,Z,ifail,info = gvx(A,B,iu=hi,itype=type,jobz=_job, il=lo, overwrite_a=overwrite, overwrite_b = overwrite) w=w_tot[0:hi-lo+1] # Use '*gvd' routine if turbo is on and no range is specified elif turbo == "on": gvd = get_froutines_func("gvd",_symeig_pfx,dtype) Z, w,info = gvd(A,B,itype=type,jobz=_job, overwrite_a=overwrite, overwrite_b = overwrite) # Use '*gv' routine if turbo is off and no range is specified else: gv = get_froutines_func("gv",_symeig_pfx,dtype) Z, w,info = gv(A,B,itype=type,jobz=_job, overwrite_a=overwrite, overwrite_b = overwrite) # Check if we had a successful exit # Success if info == 0: if eigenvectors: return w,Z else: return w # Catch failures # Internal errors: these should never happen. # If you get these you found a bug in symeig! elif info < 0: exceptstring = "illegal value in %i-th argument of internal"%(-info)+\ " fortran routine." raise SymeigException,exceptstring elif info > 0 and B==None: exceptstring = "unrecoverable internal error." raise SymeigException,exceptstring # The algorithm failed to converge. elif info > 0 and info <= B.shape[0]: if range is not None: exceptstring="the eigenvectors %s"%(numpy.nonzero(ifail))+\ " failed to converge." raise SymeigException,exceptstring else: exceptstring="internal fortran routine failed to converge: "+\ "%i off-diagonal elements of an "%(info)+\ "intermediate tridiagonal form did not converge"+\ " to zero." raise SymeigException,exceptstring # This occurs when B is not positive definite else: exceptstring="the leading minor of order %i"%(info-B.shape[0])+\ " of B is not positive definite. The"+\ " factorization of B could not be completed"+\ " and no eigenvalues or eigenvectors were computed." raise LeadingMinorException,exceptstring def _sanitize_range(n, range): if range is None: return None (lo,hi) = range if lo < 1: lo = 1 if lo > n: lo = n if hi > n: hi = n if lo > hi: lo, hi = hi, lo return (lo, hi) def _refcast(array, dtype): """ Cast the array to dtype only if necessary, otherwise return a reference. """ if array is None: return None dtype = numpy.dtype(dtype) if array.dtype == dtype: return array return array.astype(dtype) _type_conv = {('f','d'): 'd', ('f','F'): 'F', ('f','D'): 'D', ('d','F'): 'D', ('d','D'): 'D', ('F','d'): 'D', ('F','D'): 'D'} def _greatest_common_dtype(alist): """ Apply conversion rules to find the common conversion type Dtype 'd' is default for 'i' or unknown types (known types: 'f','d','F','D'). """ dtype = 'f' for array in alist: if array==None: continue tc = array.dtype.char if tc not in _symeig_pfx.keys(): tc = 'd' transition = (dtype, tc) if _type_conv.has_key(transition): dtype = _type_conv[transition] return dtype # utilities for choosing the fortran routine with the optimal dtype def get_froutines_func(name, prefix, dtype): """Return the optimal available froutines function for the selected dtype.. The function returned has name prefix{common_type}+name. """ # get the optimal function for the common conversion type func_name = prefix[dtype] + name func = getattr(froutines,func_name) return func symeig-1.5/test/000077500000000000000000000000001111257553200136355ustar00rootroot00000000000000symeig-1.5/test/__init__.py000066400000000000000000000017461111257553200157560ustar00rootroot00000000000000"""symeig test module. Run all tests with: >>> import symeig >>> symeig.test() """ import sys import numpy import unittest import test_symeig _err_str = """\nIMPORTANT: some tests use random numbers. This could occasionally lead to failures due to numerical degeneracies. To rule this out, please run the tests more than once. If you get reproducible failures please report a bug! """ test_suites = {'symeig': test_symeig.get_suite()} def test(suitename = 'all', verbosity = 2, seed = None): if seed is None: seed = int(numpy.random.randint(2**31-1)) numpy.random.seed(seed) sys.stderr.write("Random Seed: " + str(seed)+'\n') if suitename == 'all': suite = unittest.TestSuite(test_suites.values()) else: suite = test_suites[suitename] res = unittest.TextTestRunner(verbosity=verbosity).run(suite) if len(res.errors+res.failures) > 0: sys.stderr.write(_err_str) sys.stderr.write("\nRandom Seed was: " + str(seed)+'\n') symeig-1.5/test/benchmark_symeig.py000077500000000000000000000074211111257553200175250ustar00rootroot00000000000000"""symeig benchmark functions.""" import numpy from symeig import symeig from testing_tools import symrand ## utils ## benchmark functions def symeig_benchmark(dim): """Standard eigenvalue problem: symeig . First argument: matrix dimensionality""" a = MTX_DICT[dim][0].copy() out_d, out_v = symeig(a,overwrite=1) def eig_benchmark(dim): """Standard eigenvalue problem: numpy.linalg.eig . First argument: matrix dimensionality""" a = MTX_DICT[dim][0].copy() out_d, out_v = numpy.linalg.eig(a) def symeig_general_benchmark(dim): """General eigenvalue problem: symeig . First argument: matrix dimensionality""" a = MTX_DICT[dim][0].copy() b = MTX_DICT[dim][1].copy() out_d, out_v = symeig(a,b,overwrite=1) def eig_general_benchmark(dim): """General eigenvalue problem: numpy.linalg.eig . First argument: matrix dimensionality""" try: import scipy.linalg a = MTX_DICT[dim][0].copy() b = MTX_DICT[dim][1].copy() out_d, out_v = scipy.linalg.eig(a,b) except ImportError: pass def _get_random_mtx(dim): d = numpy.random.random(dim) mtx = numpy.random.random((dim, dim)) mtx += mtx.T e, v = symeig(mtx, overwrite=1) if numpy.linalg.det(v)<0: v[:,0] = -v[:,0] h = numpy.dot(numpy.dot(v.T, numpy.diag(d)), v) # to avoid roundoff errors, symmetrize the matrix (again) return 0.5*(h.T+h) symrand = _get_random_mtx EIG_MTX_DIMS = [[2**i] for i in range(4,10)] MTX_DICT = {} for dim in EIG_MTX_DIMS: print dim print 'a' a = symrand(dim[0]) print 'b' b = symrand(dim[0])+numpy.diag([2.]*dim[0]) MTX_DICT[dim[0]] = (a, b) # list of (benchmark function, list of arguments) BENCH_FUNCS = [(symeig_benchmark, EIG_MTX_DIMS), (eig_benchmark, EIG_MTX_DIMS), (symeig_general_benchmark, EIG_MTX_DIMS), (eig_general_benchmark, EIG_MTX_DIMS)] # function used to measure time import time TIMEFUNC = time.time def timeit(func,*args,**kwargs): """Return function execution time in 1/100ths of a second.""" tstart = TIMEFUNC() func(*args,**kwargs) return (TIMEFUNC()-tstart)*100. def _random_seed(): import sys seed = int(numx_rand.randint(2**31-1)) numx_rand.seed(seed) sys.stderr.write("Random Seed: " + str(seed)+'\n') def run_benchmarks(bench_funcs, time_digits=15): results_str = '| %%s | %%%d.2f |' % time_digits label_str = '| %%s | %s |' % 'Time (sec/100)'.center(time_digits) tstart = TIMEFUNC() # loop over all benchmarks functions for func, args_list in bench_funcs: # number of combinations of arguments(cases) ncases = len(args_list) funcname = func.__name__[:-10] # loop over all cases for i in range(ncases): args = args_list[i] # format description string descr = funcname + str(tuple(args)) if i==0: # print summary table header descrlen = len(descr)+6 results_strlen = time_digits+descrlen+7 print '\nTiming results (%s, %d cases):' % (funcname, ncases) print func.__doc__ print '+'+'-'*(results_strlen-2)+'+' print label_str % 'Description'.center(descrlen) print '+'+'-'*(results_strlen-2)+'+' # execute function t = timeit(func, *args) # print summary table entry print results_str % (descr.center(descrlen), t) # print summary table tail print '+'+'-'*(results_strlen-2)+'+' print '\nTotal running time:', (TIMEFUNC()-tstart)*100. def get_benchmarks(): return BENCH_FUNCS if __name__ == '__main__': print "Running benchmarks: " run_benchmarks(get_benchmarks()) symeig-1.5/test/test_symeig.py000077500000000000000000000153751111257553200165610ustar00rootroot00000000000000"""symeig test functions.""" import numpy, unittest from testing_tools import \ assert_array_almost_equal_diff as assert_array_almost_equal from testing_tools import assert_array_equal, assert_type_equal,\ symrand, hermitian from symeig import symeig, SymeigException # some abbrev. dot = numpy.dot # matrix dimension in tests DIM = 5 # digit precision to use in asserts for the different types DIGITS = {'d':11, 'D':11, 'f':3, 'F':3} class SymeigTestCase(unittest.TestCase): def eigenproblem(self, dim, dtype, overwrite, turbo, range): """Solve a standard eigenvalue problem.""" a = symrand(dim, dtype) if overwrite == 1: a_c = a.copy() else: a_c = a w,z = symeig(a, turbo=turbo, overwrite=overwrite, range=range) # assertions assert_type_equal(z.dtype, dtype) w = w.astype(dtype) diag = numpy.diagonal(dot(hermitian(z), dot(a_c, z))).real assert_array_almost_equal(diag, w, DIGITS[dtype]) def geneigenproblem(self, dim, dtype, overwrite, turbo, range): """Solve a generalized eigenvalue problem.""" a = symrand(dim, dtype) # make it definite positive b = symrand(dim, dtype)+numpy.diag([2.1]*dim).astype(dtype) if overwrite == 1: a_c, b_c = a.copy(), b.copy() else: a_c, b_c = a, b w,z = symeig(a,b,turbo=turbo,overwrite=overwrite,range=range) # assertions assert_type_equal(z.dtype, dtype) w = w.astype(dtype) diag1 = numpy.diagonal(dot(hermitian(z), dot(a_c, z))).real assert_array_almost_equal(diag1, w, DIGITS[dtype]) diag2 = numpy.diagonal(dot(hermitian(z), dot(b_c, z))).real assert_array_almost_equal(diag2, \ numpy.ones(diag2.shape[0]), DIGITS[dtype]) # non-contiguous case def eigenproblem_nc(self, dim, dtype): a_c = symrand(dim, dtype) assert a_c.flags.c_contiguous, \ 'Contiguous matrix doen not appear to be contiguous!' a_nc = a_c[::-1,::-1] assert not a_c.flags.f_contiguous,\ 'Not contiguous matrix appears to be fortran contiguous!' #self.assertRaises(SymeigException,symeig,a_nc,overwrite=1) a_fc = numpy.transpose(a_c) assert not a_c.flags.f_contiguous,\ 'Fortran contiguous matrix does not appear to be '+\ 'fortran contiguous!' w,z = symeig(a_fc, overwrite=1) def testOverwriteBug(self): # reproduces a bug when B=None and overwrite=0 a = symrand(5, 'd') w,z = symeig(a, overwrite=0) def testWrongDimensionsBug(self): # reproduces a bug when len(A.shape) != 2 or A.shape[0] != A.shape[1] try: a = numpy.random.rand(10) w, z = symeig(a) msg = 'Did not complain for wrong dimensions!' raise Exception except SymeigException: pass try: a = numpy.random.rand(10, 3) w, z = symeig(a) msg = 'Did not complain for wrong dimensions!' raise Exception except SymeigException: pass try: a = numpy.random.rand(10, 10) b = numpy.random.rand(10, 2) w, z = symeig(a, b) msg = 'Did not complain for wrong dimensions!' raise Exception except SymeigException: pass def testReal(self): range = (2,DIM-1) self.eigenproblem(DIM,'d',0,'off',None) self.eigenproblem(DIM,'f',0,'off',None) self.eigenproblem(DIM,'d',1,'off',None) self.eigenproblem(DIM,'f',1,'off',None) self.eigenproblem(DIM,'d',0,'off',range) self.eigenproblem(DIM,'f',0,'off',range) self.eigenproblem(DIM,'d',1,'off',range) self.eigenproblem(DIM,'f',1,'off',range) def testRealGeneralized(self): range = (2,DIM-1) self.geneigenproblem(DIM,'d',0,'on',None) self.geneigenproblem(DIM,'f',0,'on',None) self.geneigenproblem(DIM,'d',1,'on',None) self.geneigenproblem(DIM,'f',1,'on',None) self.geneigenproblem(DIM,'d',0,'off',None) self.geneigenproblem(DIM,'f',0,'off',None) self.geneigenproblem(DIM,'d',1,'off',None) self.geneigenproblem(DIM,'f',1,'off',None) self.geneigenproblem(DIM,'d',0,'off',range) self.geneigenproblem(DIM,'f',0,'off',range) self.geneigenproblem(DIM,'d',1,'off',range) self.geneigenproblem(DIM,'f',1,'off',range) def testComplex(self): range = (2,DIM-1) self.eigenproblem(DIM,'D',0,'off',None) self.eigenproblem(DIM,'F',0,'off',None) self.eigenproblem(DIM,'D',1,'off',None) self.eigenproblem(DIM,'F',1,'off',None) self.eigenproblem(DIM,'D',0,'off',range) self.eigenproblem(DIM,'F',0,'off',range) self.eigenproblem(DIM,'D',1,'off',range) self.eigenproblem(DIM,'F',1,'off',range) def testComplexGeneralized(self): range = (2,DIM-1) self.geneigenproblem(DIM,'D',0,'on',None) self.geneigenproblem(DIM,'F',0,'on',None) self.geneigenproblem(DIM,'D',1,'on',None) self.geneigenproblem(DIM,'F',1,'on',None) self.geneigenproblem(DIM,'D',0,'off',None) self.geneigenproblem(DIM,'F',0,'off',None) self.geneigenproblem(DIM,'D',1,'off',None) self.geneigenproblem(DIM,'F',1,'off',None) self.geneigenproblem(DIM,'D',0,'off',range) self.geneigenproblem(DIM,'F',0,'off',range) self.geneigenproblem(DIM,'D',1,'off',range) self.geneigenproblem(DIM,'F',1,'off',range) def testNonContiguousMatrix(self): self.eigenproblem_nc(DIM,'f') self.eigenproblem_nc(DIM,'d') def testIntegerMatrix(self): a = numpy.array([[1,2],[2,7]]) b = numpy.array([[3,1],[1,5]]) w,z = symeig(a,overwrite=0) w,z = symeig(a,b,overwrite=0) def testDTypeConversion(self): types = {('f','d'): 'd', ('f','F'): 'F', ('f','D'): 'D', ('d','F'): 'D', ('d','D'): 'D', ('F','d'): 'D', ('F','D'): 'D'} for t1,t2 in types.keys(): a = symrand(DIM,t1) b = symrand(DIM,t2)+numpy.diag([2.1]*DIM).astype(t2) w,z = symeig(a,b) assert_type_equal(z.dtype, types[(t1,t2)]) def testWrongRangeBug(self): a = symrand(10) w,z = symeig(a, range=(20,30)) w,z = symeig(a, range=(30,20)) w,z = symeig(a, range=(0,3)) def get_suite(): suite = unittest.TestSuite() suite.addTest(unittest.makeSuite(SymeigTestCase)) return suite if __name__ == '__main__': numpy.random.seed(1268049219) unittest.TextTestRunner(verbosity=2).run(get_suite()) symeig-1.5/test/testing_tools.py000077500000000000000000000063101111257553200171070ustar00rootroot00000000000000"""Tools for the test- and benchmark functions.""" import time import numpy as numx from numpy.testing import assert_array_equal, assert_array_almost_equal, \ assert_equal, assert_almost_equal #### test tools def assert_array_almost_equal_diff(x,y,digits,err_msg=''): x,y = numx.asarray(x), numx.asarray(y) msg = '\nArrays are not almost equal' assert 0 in [len(numx.shape(x)),len(numx.shape(y))] \ or (len(numx.shape(x))==len(numx.shape(y)) and \ numx.alltrue(numx.equal(numx.shape(x),numx.shape(y)))),\ msg + ' (shapes %s, %s mismatch):\n\t' \ % (numx.shape(x),numx.shape(y)) + err_msg maxdiff = max(numx.ravel(abs(x-y)))/\ max(max(abs(numx.ravel(x))),max(abs(numx.ravel(y)))) if numx.iscomplexobj(x) or numx.iscomplexobj(y): maxdiff = maxdiff/2 cond = maxdiff< 10**(-digits) msg = msg+'\n\t Relative maximum difference: %e'%(maxdiff)+'\n\t'+\ 'Array1: '+str(x)+'\n\t'+\ 'Array2: '+str(y)+'\n\t'+\ 'Absolute Difference: '+str(abs(y-x)) assert cond, msg def assert_type_equal(act, des): assert act == numx.dtype(des), \ 'dtype mismatch: "%s" (should be "%s") '%(act,des) ## random routines def hermitian(x): """Compute the Hermitian, i.e. conjugate transpose, of x.""" return x.T.conj() def symrand(dim_or_eigv, dtype='d'): """Return a random symmetric (Hermitian) matrix. If 'dim_or_eigv' is an integer N, return a NxN matrix, with eigenvalues uniformly distributed on (-1,1). If 'dim_or_eigv' is 1-D real array 'a', return a matrix whose eigenvalues are 'a'. """ if isinstance(dim_or_eigv, int): dim = dim_or_eigv d = (numx.random.rand(dim)*2)-1 elif (isinstance(dim_or_eigv, ndarray) and len(dim_or_eigv.shape) == 1): dim = dim_or_eigv.shape[0] d = dim_or_eigv else: raise TypeError("input type not supported.") v = random_rot(dim) h = numx.dot(numx.dot(v.T.conj(), numx.diag(d)), v) # to avoid roundoff errors, symmetrize the matrix (again) h = 0.5*(h.T+h) if dtype in ('D', 'F'): h2 = symrand(dim_or_eigv) h = h + 1j*(numx.triu(h2)-numx.tril(h2)) return h.astype(dtype) def random_rot(dim): """Return a random rotation matrix, drawn from the Haar distribution (the only uniform distribution on SO(n)). The algorithm is described in the paper Stewart, G.W., 'The efficient generation of random orthogonal matrices with an application to condition estimators', SIAM Journal on Numerical Analysis, 17(3), pp. 403-409, 1980. For more information see http://en.wikipedia.org/wiki/Orthogonal_matrix#Randomization""" H = numx.eye(dim) D = numx.ones((dim, )) for n in range(1, dim): x = numx.random.normal(size=(dim-n+1, )) D[n-1] = numx.sign(x[0]) x[0] -= D[n-1]*numx.sqrt((x*x).sum()) # Householder transformation Hx = numx.eye(dim-n+1) - 2.*numx.outer(x, x)/(x*x).sum() mat = numx.eye(dim) mat[n-1:,n-1:] = Hx H = numx.dot(H, mat) # Fix the last sign such that the determinant is 1 D[-1] = -D.prod() H = (D*H.T).T return H