This is mostly a long term maintenance improvement.
Many coding styles require elimination of trailing whitespace, and
many editors and source code management configurations automatically
gobble up whitespace. When these tools gobble up whitespace, it
complicates reviewing the meaningful code changes.
By removing whitespace on one patch, it makes future
code reviews much easier.
=SCRIPT====================================================================
if which tempfile &>/dev/null; then
TEMPMAKER=tempfile
elif which mktemp &>/dev/null; then
TEMPMAKER=mktemp
else
echo "Cannot find tempfile program." 2>&1
exit 1
fi
MYTEMP=$($TEMPMAKER)
trap 'rm -f $MYTEMP' SIGINT SIGTERM
stripit() {
echo "stripping $1"
sed 's/[ \t]*$//' "$1" > $MYTEMP
cp $MYTEMP "$1"
}
if [ $# -gt 0 ]; then
while [ "$1" != "" ]; do
stripit $1
shift
done
else
while read -t 2; do
stripit $REPLY
done
fi
rm $MYTEMP
=================================================
299 lines
8.6 KiB
FortranFixed
299 lines
8.6 KiB
FortranFixed
*> \brief <b> CHEEV computes the eigenvalues and, optionally, the left and/or right eigenvectors for HE matrices</b>
|
|
*
|
|
* =========== DOCUMENTATION ===========
|
|
*
|
|
* Online html documentation available at
|
|
* http://www.netlib.org/lapack/explore-html/
|
|
*
|
|
*> \htmlonly
|
|
*> Download CHEEV + dependencies
|
|
*> <a href="http://www.netlib.org/cgi-bin/netlibfiles.tgz?format=tgz&filename=/lapack/lapack_routine/cheev.f">
|
|
*> [TGZ]</a>
|
|
*> <a href="http://www.netlib.org/cgi-bin/netlibfiles.zip?format=zip&filename=/lapack/lapack_routine/cheev.f">
|
|
*> [ZIP]</a>
|
|
*> <a href="http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/cheev.f">
|
|
*> [TXT]</a>
|
|
*> \endhtmlonly
|
|
*
|
|
* Definition:
|
|
* ===========
|
|
*
|
|
* SUBROUTINE CHEEV( JOBZ, UPLO, N, A, LDA, W, WORK, LWORK, RWORK,
|
|
* INFO )
|
|
*
|
|
* .. Scalar Arguments ..
|
|
* CHARACTER JOBZ, UPLO
|
|
* INTEGER INFO, LDA, LWORK, N
|
|
* ..
|
|
* .. Array Arguments ..
|
|
* REAL RWORK( * ), W( * )
|
|
* COMPLEX A( LDA, * ), WORK( * )
|
|
* ..
|
|
*
|
|
*
|
|
*> \par Purpose:
|
|
* =============
|
|
*>
|
|
*> \verbatim
|
|
*>
|
|
*> CHEEV computes all eigenvalues and, optionally, eigenvectors of a
|
|
*> complex Hermitian matrix A.
|
|
*> \endverbatim
|
|
*
|
|
* Arguments:
|
|
* ==========
|
|
*
|
|
*> \param[in] JOBZ
|
|
*> \verbatim
|
|
*> JOBZ is CHARACTER*1
|
|
*> = 'N': Compute eigenvalues only;
|
|
*> = 'V': Compute eigenvalues and eigenvectors.
|
|
*> \endverbatim
|
|
*>
|
|
*> \param[in] UPLO
|
|
*> \verbatim
|
|
*> UPLO is CHARACTER*1
|
|
*> = 'U': Upper triangle of A is stored;
|
|
*> = 'L': Lower triangle of A is stored.
|
|
*> \endverbatim
|
|
*>
|
|
*> \param[in] N
|
|
*> \verbatim
|
|
*> N is INTEGER
|
|
*> The order of the matrix A. N >= 0.
|
|
*> \endverbatim
|
|
*>
|
|
*> \param[in,out] A
|
|
*> \verbatim
|
|
*> A is 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, if JOBZ = 'V', then if INFO = 0, A contains the
|
|
*> orthonormal eigenvectors of the matrix A.
|
|
*> If JOBZ = 'N', then on exit the lower triangle (if UPLO='L')
|
|
*> or the upper triangle (if UPLO='U') of A, including the
|
|
*> diagonal, is destroyed.
|
|
*> \endverbatim
|
|
*>
|
|
*> \param[in] LDA
|
|
*> \verbatim
|
|
*> LDA is INTEGER
|
|
*> The leading dimension of the array A. LDA >= max(1,N).
|
|
*> \endverbatim
|
|
*>
|
|
*> \param[out] W
|
|
*> \verbatim
|
|
*> W is REAL array, dimension (N)
|
|
*> If INFO = 0, the eigenvalues in ascending order.
|
|
*> \endverbatim
|
|
*>
|
|
*> \param[out] WORK
|
|
*> \verbatim
|
|
*> WORK is COMPLEX array, dimension (MAX(1,LWORK))
|
|
*> On exit, if INFO = 0, WORK(1) returns the optimal LWORK.
|
|
*> \endverbatim
|
|
*>
|
|
*> \param[in] LWORK
|
|
*> \verbatim
|
|
*> LWORK is INTEGER
|
|
*> 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.
|
|
*>
|
|
*> If LWORK = -1, then a workspace query is assumed; the routine
|
|
*> only calculates the optimal size of the WORK array, returns
|
|
*> this value as the first entry of the WORK array, and no error
|
|
*> message related to LWORK is issued by XERBLA.
|
|
*> \endverbatim
|
|
*>
|
|
*> \param[out] RWORK
|
|
*> \verbatim
|
|
*> RWORK is REAL array, dimension (max(1, 3*N-2))
|
|
*> \endverbatim
|
|
*>
|
|
*> \param[out] INFO
|
|
*> \verbatim
|
|
*> INFO is INTEGER
|
|
*> = 0: successful exit
|
|
*> < 0: if INFO = -i, the i-th argument had an illegal value
|
|
*> > 0: if INFO = i, the algorithm failed to converge; i
|
|
*> off-diagonal elements of an intermediate tridiagonal
|
|
*> form did not converge to zero.
|
|
*> \endverbatim
|
|
*
|
|
* Authors:
|
|
* ========
|
|
*
|
|
*> \author Univ. of Tennessee
|
|
*> \author Univ. of California Berkeley
|
|
*> \author Univ. of Colorado Denver
|
|
*> \author NAG Ltd.
|
|
*
|
|
*> \date November 2011
|
|
*
|
|
*> \ingroup complexHEeigen
|
|
*
|
|
* =====================================================================
|
|
SUBROUTINE CHEEV( JOBZ, UPLO, N, A, LDA, W, WORK, LWORK, RWORK,
|
|
$ INFO )
|
|
*
|
|
* -- LAPACK driver routine (version 3.4.0) --
|
|
* -- LAPACK is a software package provided by Univ. of Tennessee, --
|
|
* -- Univ. of California Berkeley, Univ. of Colorado Denver and NAG Ltd..--
|
|
* November 2011
|
|
*
|
|
* .. Scalar Arguments ..
|
|
CHARACTER JOBZ, UPLO
|
|
INTEGER INFO, LDA, LWORK, N
|
|
* ..
|
|
* .. Array Arguments ..
|
|
REAL RWORK( * ), W( * )
|
|
COMPLEX A( LDA, * ), WORK( * )
|
|
* ..
|
|
*
|
|
* =====================================================================
|
|
*
|
|
* .. Parameters ..
|
|
REAL ZERO, ONE
|
|
PARAMETER ( ZERO = 0.0E0, ONE = 1.0E0 )
|
|
COMPLEX CONE
|
|
PARAMETER ( CONE = ( 1.0E0, 0.0E0 ) )
|
|
* ..
|
|
* .. Local Scalars ..
|
|
LOGICAL LOWER, LQUERY, WANTZ
|
|
INTEGER IINFO, IMAX, INDE, INDTAU, INDWRK, ISCALE,
|
|
$ LLWORK, LWKOPT, NB
|
|
REAL ANRM, BIGNUM, EPS, RMAX, RMIN, SAFMIN, SIGMA,
|
|
$ SMLNUM
|
|
* ..
|
|
* .. External Functions ..
|
|
LOGICAL LSAME
|
|
INTEGER ILAENV
|
|
REAL CLANHE, SLAMCH
|
|
EXTERNAL ILAENV, LSAME, CLANHE, SLAMCH
|
|
* ..
|
|
* .. External Subroutines ..
|
|
EXTERNAL CHETRD, CLASCL, CSTEQR, CUNGTR, SSCAL, SSTERF,
|
|
$ XERBLA
|
|
* ..
|
|
* .. Intrinsic Functions ..
|
|
INTRINSIC MAX, SQRT
|
|
* ..
|
|
* .. Executable Statements ..
|
|
*
|
|
* Test the input parameters.
|
|
*
|
|
WANTZ = LSAME( JOBZ, 'V' )
|
|
LOWER = LSAME( UPLO, 'L' )
|
|
LQUERY = ( LWORK.EQ.-1 )
|
|
*
|
|
INFO = 0
|
|
IF( .NOT.( WANTZ .OR. LSAME( JOBZ, 'N' ) ) ) THEN
|
|
INFO = -1
|
|
ELSE IF( .NOT.( LOWER .OR. LSAME( UPLO, 'U' ) ) ) THEN
|
|
INFO = -2
|
|
ELSE IF( N.LT.0 ) THEN
|
|
INFO = -3
|
|
ELSE IF( LDA.LT.MAX( 1, N ) ) THEN
|
|
INFO = -5
|
|
END IF
|
|
*
|
|
IF( INFO.EQ.0 ) THEN
|
|
NB = ILAENV( 1, 'CHETRD', UPLO, N, -1, -1, -1 )
|
|
LWKOPT = MAX( 1, ( NB+1 )*N )
|
|
WORK( 1 ) = LWKOPT
|
|
*
|
|
IF( LWORK.LT.MAX( 1, 2*N-1 ) .AND. .NOT.LQUERY )
|
|
$ INFO = -8
|
|
END IF
|
|
*
|
|
IF( INFO.NE.0 ) THEN
|
|
CALL XERBLA( 'CHEEV ', -INFO )
|
|
RETURN
|
|
ELSE IF( LQUERY ) THEN
|
|
RETURN
|
|
END IF
|
|
*
|
|
* Quick return if possible
|
|
*
|
|
IF( N.EQ.0 ) THEN
|
|
RETURN
|
|
END IF
|
|
*
|
|
IF( N.EQ.1 ) THEN
|
|
W( 1 ) = A( 1, 1 )
|
|
WORK( 1 ) = 1
|
|
IF( WANTZ )
|
|
$ A( 1, 1 ) = CONE
|
|
RETURN
|
|
END IF
|
|
*
|
|
* Get machine constants.
|
|
*
|
|
SAFMIN = SLAMCH( 'Safe minimum' )
|
|
EPS = SLAMCH( 'Precision' )
|
|
SMLNUM = SAFMIN / EPS
|
|
BIGNUM = ONE / SMLNUM
|
|
RMIN = SQRT( SMLNUM )
|
|
RMAX = SQRT( BIGNUM )
|
|
*
|
|
* Scale matrix to allowable range, if necessary.
|
|
*
|
|
ANRM = CLANHE( 'M', UPLO, N, A, LDA, RWORK )
|
|
ISCALE = 0
|
|
IF( ANRM.GT.ZERO .AND. ANRM.LT.RMIN ) THEN
|
|
ISCALE = 1
|
|
SIGMA = RMIN / ANRM
|
|
ELSE IF( ANRM.GT.RMAX ) THEN
|
|
ISCALE = 1
|
|
SIGMA = RMAX / ANRM
|
|
END IF
|
|
IF( ISCALE.EQ.1 )
|
|
$ CALL CLASCL( UPLO, 0, 0, ONE, SIGMA, N, N, A, LDA, INFO )
|
|
*
|
|
* Call CHETRD to reduce Hermitian matrix to tridiagonal form.
|
|
*
|
|
INDE = 1
|
|
INDTAU = 1
|
|
INDWRK = INDTAU + N
|
|
LLWORK = LWORK - INDWRK + 1
|
|
CALL CHETRD( UPLO, N, A, LDA, W, RWORK( INDE ), WORK( INDTAU ),
|
|
$ WORK( INDWRK ), LLWORK, IINFO )
|
|
*
|
|
* For eigenvalues only, call SSTERF. For eigenvectors, first call
|
|
* CUNGTR to generate the unitary matrix, then call CSTEQR.
|
|
*
|
|
IF( .NOT.WANTZ ) THEN
|
|
CALL SSTERF( N, W, RWORK( INDE ), INFO )
|
|
ELSE
|
|
CALL CUNGTR( UPLO, N, A, LDA, WORK( INDTAU ), WORK( INDWRK ),
|
|
$ LLWORK, IINFO )
|
|
INDWRK = INDE + N
|
|
CALL CSTEQR( JOBZ, N, W, RWORK( INDE ), A, LDA,
|
|
$ RWORK( INDWRK ), INFO )
|
|
END IF
|
|
*
|
|
* If matrix was scaled, then rescale eigenvalues appropriately.
|
|
*
|
|
IF( ISCALE.EQ.1 ) THEN
|
|
IF( INFO.EQ.0 ) THEN
|
|
IMAX = N
|
|
ELSE
|
|
IMAX = INFO - 1
|
|
END IF
|
|
CALL SSCAL( IMAX, ONE / SIGMA, W, 1 )
|
|
END IF
|
|
*
|
|
* Set WORK(1) to optimal complex workspace size.
|
|
*
|
|
WORK( 1 ) = LWKOPT
|
|
*
|
|
RETURN
|
|
*
|
|
* End of CHEEV
|
|
*
|
|
END
|