molscat_14/lapack.f

12443 lines
376 KiB
Fortran

C ------------- BELOW IS DSYEVX --------------------
CAT > DSYEVX.F <<'CUT HERE............'
SUBROUTINE DSYEVX( JOBZ, RANGE, UPLO, N, A, LDA, VL, VU, IL, IU,
$ ABSTOL, M, W, Z, LDZ, WORK, LWORK, IWORK,
$ IFAIL, INFO )
*
* -- LAPACK DRIVER ROUTINE (VERSION 1.1) --
* UNIV. OF TENNESSEE, UNIV. OF CALIFORNIA BERKELEY, NAG LTD.,
* COURANT INSTITUTE, ARGONNE NATIONAL LAB, AND RICE UNIVERSITY
* MARCH 31, 1993
*
* .. SCALAR ARGUMENTS ..
CHARACTER JOBZ, RANGE, UPLO
INTEGER IL, INFO, IU, LDA, LDZ, LWORK, M, N
DOUBLE PRECISION ABSTOL, VL, VU
* ..
* .. ARRAY ARGUMENTS ..
INTEGER IFAIL( * ), IWORK( * )
DOUBLE PRECISION A( LDA, * ), W( * ), WORK( * ), Z( LDZ, * )
* ..
*
* PURPOSE
* =======
*
* DSYEVX COMPUTES SELECTED EIGENVALUES AND, OPTIONALLY, EIGENVECTORS
* OF A REAL SYMMETRIC MATRIX A. EIGENVALUES AND EIGENVECTORS CAN BE
* SELECTED BY SPECIFYING EITHER A RANGE OF VALUES OR A RANGE OF INDICES
* FOR THE DESIRED EIGENVALUES.
*
* ARGUMENTS
* =========
*
* JOBZ (INPUT) CHARACTER*1
* = 'N': COMPUTE EIGENVALUES ONLY;
* = 'V': COMPUTE EIGENVALUES AND EIGENVECTORS.
*
* RANGE (INPUT) CHARACTER*1
* = '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.
*
* UPLO (INPUT) CHARACTER*1
* = 'U': UPPER TRIANGLE OF A IS STORED;
* = 'L': LOWER TRIANGLE OF A IS STORED.
*
* N (INPUT) INTEGER
* THE ORDER OF THE MATRIX A. N >= 0.
*
* A (INPUT/WORKSPACE) DOUBLE PRECISION 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.
*
* LDA (INPUT) INTEGER
* THE LEADING DIMENSION OF THE ARRAY A. LDA >= MAX(1,N).
*
* VL (INPUT) DOUBLE PRECISION
* IF RANGE='V', THE LOWER BOUND OF THE INTERVAL TO BE SEARCHED
* FOR EIGENVALUES. NOT REFERENCED IF RANGE = 'A' OR 'I'.
*
* VU (INPUT) DOUBLE PRECISION
* IF RANGE='V', THE UPPER BOUND OF THE INTERVAL TO BE SEARCHED
* FOR EIGENVALUES. NOT REFERENCED IF RANGE = 'A' OR 'I'.
*
* IL (INPUT) INTEGER
* IF RANGE='I', THE INDEX (FROM SMALLEST TO LARGEST) OF THE
* SMALLEST EIGENVALUE TO BE RETURNED. IL >= 1.
* NOT REFERENCED IF RANGE = 'A' OR 'V'.
*
* IU (INPUT) INTEGER
* IF RANGE='I', THE INDEX (FROM SMALLEST TO LARGEST) OF THE
* LARGEST EIGENVALUE TO BE RETURNED. MIN(IL,N) <= IU <= N.
* NOT REFERENCED IF RANGE = 'A' OR 'V'.
*
* ABSTOL (INPUT) DOUBLE PRECISION
* 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.
*
* SEE "COMPUTING SMALL SINGULAR VALUES OF BIDIAGONAL MATRICES
* WITH GUARANTEED HIGH RELATIVE ACCURACY," BY DEMMEL AND
* KAHAN, LAPACK WORKING NOTE #3.
*
* M (OUTPUT) INTEGER
* THE TOTAL NUMBER OF EIGENVALUES FOUND. 0 <= M <= N.
* IF RANGE = 'A', M = N, AND IF RANGE = 'I', M = IU-IL+1.
*
* W (OUTPUT) DOUBLE PRECISION ARRAY, DIMENSION (N)
* ON NORMAL EXIT, THE FIRST M ENTRIES CONTAIN THE SELECTED
* EIGENVALUES IN ASCENDING ORDER.
*
* Z (OUTPUT) DOUBLE PRECISION ARRAY, DIMENSION (LDZ, MAX(1,M))
* IF JOBZ = 'V', THEN IF INFO = 0, THE FIRST M COLUMNS OF Z
* CONTAIN THE ORTHONORMAL EIGENVECTORS OF THE MATRIX
* CORRESPONDING TO THE SELECTED EIGENVALUES. 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.
* 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.
*
* LDZ (INPUT) INTEGER
* THE LEADING DIMENSION OF THE ARRAY Z. LDZ >= 1, AND IF
* JOBZ = 'V', LDZ >= MAX(1,N).
*
* WORK (WORKSPACE) DOUBLE PRECISION ARRAY, DIMENSION (LWORK)
* ON EXIT, IF INFO = 0, WORK(1) RETURNS THE OPTIMAL LWORK.
*
* LWORK (INPUT) INTEGER
* THE LENGTH OF THE ARRAY WORK. LWORK >= MAX(1,8*N).
* FOR OPTIMAL EFFICIENCY, LWORK >= (NB+3)*N,
* WHERE NB IS THE BLOCKSIZE FOR DSYTRD RETURNED BY ILAENV.
*
* IWORK (WORKSPACE) INTEGER ARRAY, DIMENSION (5*N)
*
* IFAIL (OUTPUT) INTEGER ARRAY, DIMENSION (N)
* 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.
*
* INFO (OUTPUT) INTEGER
* = 0: SUCCESSFUL EXIT
* < 0: IF INFO = -I, THE I-TH ARGUMENT HAD AN ILLEGAL VALUE
* > 0: IF INFO = I, THEN I EIGENVECTORS FAILED TO CONVERGE.
* THEIR INDICES ARE STORED IN ARRAY IFAIL.
*
* =====================================================================
*
* .. PARAMETERS ..
DOUBLE PRECISION ZERO, ONE
PARAMETER ( ZERO = 0.0D0, ONE = 1.0D0 )
* ..
* .. LOCAL SCALARS ..
LOGICAL ALLEIG, INDEIG, LOWER, VALEIG, WANTZ
CHARACTER ORDER
INTEGER I, IINFO, IMAX, INDD, INDE, INDEE, INDIBL,
$ INDISP, INDIWO, INDTAU, INDWKN, INDWRK, ISCALE,
$ ITMP1, J, JJ, LLWORK, LLWRKN, LOPT, NSPLIT
DOUBLE PRECISION ABSTLL, ANRM, BIGNUM, EPS, RMAX, RMIN, SAFMIN,
$ SIGMA, SMLNUM, TMP1, VLL, VUU
* ..
* .. EXTERNAL FUNCTIONS ..
LOGICAL LSAME
DOUBLE PRECISION DLAMCH, DLANSY
EXTERNAL LSAME, DLAMCH, DLANSY
* ..
* .. EXTERNAL SUBROUTINES ..
EXTERNAL DCOPY, DLACPY, DORGTR, DORMTR, DSCAL, DSTEBZ,
$ DSTEIN, DSTEQR, DSTERF, DSWAP, DSYTRD, XERBLA
* ..
* .. INTRINSIC FUNCTIONS ..
INTRINSIC MAX, MIN, SQRT
* ..
* .. EXECUTABLE STATEMENTS ..
*
* TEST THE INPUT PARAMETERS.
*
LOWER = LSAME( UPLO, 'L' )
WANTZ = LSAME( JOBZ, 'V' )
ALLEIG = LSAME( RANGE, 'A' )
VALEIG = LSAME( RANGE, 'V' )
INDEIG = LSAME( RANGE, 'I' )
*
INFO = 0
IF( .NOT.( WANTZ .OR. LSAME( JOBZ, 'N' ) ) ) THEN
INFO = -1
ELSE IF( .NOT.( ALLEIG .OR. VALEIG .OR. INDEIG ) ) THEN
INFO = -2
ELSE IF( .NOT.( LOWER .OR. LSAME( UPLO, 'U' ) ) ) THEN
INFO = -3
ELSE IF( N.LT.0 ) THEN
INFO = -4
ELSE IF( LDA.LT.MAX( 1, N ) ) THEN
INFO = -6
ELSE IF( VALEIG .AND. N.GT.0 .AND. VU.LE.VL ) THEN
INFO = -8
ELSE IF( INDEIG .AND. IL.LT.1 ) THEN
INFO = -9
ELSE IF( INDEIG .AND. ( IU.LT.MIN( N, IL ) .OR. IU.GT.N ) ) THEN
INFO = -10
ELSE IF( LDZ.LT.1 .OR. ( WANTZ .AND. LDZ.LT.N ) ) THEN
INFO = -15
ELSE IF( LWORK.LT.MAX( 1, 8*N ) ) THEN
INFO = -17
END IF
*
IF( INFO.NE.0 ) THEN
CALL XERBLA( 'DSYEVX', -INFO )
RETURN
END IF
*
* QUICK RETURN IF POSSIBLE
*
M = 0
IF( N.EQ.0 ) THEN
WORK( 1 ) = 1
RETURN
END IF
*
IF( N.EQ.1 ) THEN
WORK( 1 ) = 7
IF( ALLEIG .OR. INDEIG ) THEN
M = 1
W( 1 ) = A( 1, 1 )
ELSE
IF( VL.LT.A( 1, 1 ) .AND. VU.GE.A( 1, 1 ) ) THEN
M = 1
W( 1 ) = A( 1, 1 )
END IF
END IF
IF( WANTZ )
$ Z( 1, 1 ) = ONE
RETURN
END IF
*
* GET MACHINE CONSTANTS.
*
SAFMIN = DLAMCH( 'SAFE MINIMUM' )
EPS = DLAMCH( 'PRECISION' )
SMLNUM = SAFMIN / EPS
BIGNUM = ONE / SMLNUM
RMIN = SQRT( SMLNUM )
RMAX = MIN( SQRT( BIGNUM ), ONE / SQRT( SQRT( SAFMIN ) ) )
*
* SCALE MATRIX TO ALLOWABLE RANGE, IF NECESSARY.
*
ISCALE = 0
ABSTLL = ABSTOL
IF( VALEIG ) THEN
VLL = VL
VUU = VU
END IF
ANRM = DLANSY( 'M', UPLO, N, A, LDA, WORK )
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 ) THEN
IF( LOWER ) THEN
DO 10 J = 1, N
CALL DSCAL( N-J+1, SIGMA, A( J, J ), 1 )
10 CONTINUE
ELSE
DO 20 J = 1, N
CALL DSCAL( J, SIGMA, A( 1, J ), 1 )
20 CONTINUE
END IF
IF( ABSTOL.GT.0 )
$ ABSTLL = ABSTOL*SIGMA
IF( VALEIG ) THEN
VLL = VL*SIGMA
VUU = VU*SIGMA
END IF
END IF
*
* CALL DSYTRD TO REDUCE SYMMETRIC MATRIX TO TRIDIAGONAL FORM.
*
INDTAU = 1
INDE = INDTAU + N
INDD = INDE + N
INDWRK = INDD + N
LLWORK = LWORK - INDWRK + 1
CALL DSYTRD( UPLO, N, A, LDA, WORK( INDD ), WORK( INDE ),
$ WORK( INDTAU ), WORK( INDWRK ), LLWORK, IINFO )
LOPT = 3*N + WORK( INDWRK )
*
* IF ALL EIGENVALUES ARE DESIRED AND ABSTOL IS LESS THAN OR EQUAL TO
* ZERO, THEN CALL DSTERF OR DORGTR AND SSTEQR. IF THIS FAILS FOR
* SOME EIGENVALUE, THEN TRY DSTEBZ.
*
IF( ( ALLEIG .OR. ( INDEIG .AND. IL.EQ.1 .AND. IU.EQ.N ) ) .AND.
$ ( ABSTOL.LE.ZERO ) ) THEN
CALL DCOPY( N, WORK( INDD ), 1, W, 1 )
INDEE = INDWRK + 2*N
IF( .NOT.WANTZ ) THEN
CALL DCOPY( N-1, WORK( INDE ), 1, WORK( INDEE ), 1 )
CALL DSTERF( N, W, WORK( INDEE ), INFO )
ELSE
CALL DLACPY( 'A', N, N, A, LDA, Z, LDZ )
CALL DORGTR( UPLO, N, Z, LDZ, WORK( INDTAU ),
$ WORK( INDWRK ), LLWORK, IINFO )
CALL DCOPY( N-1, WORK( INDE ), 1, WORK( INDEE ), 1 )
CALL DSTEQR( JOBZ, N, W, WORK( INDEE ), Z, LDZ,
$ WORK( INDWRK ), INFO )
IF( INFO.EQ.0 ) THEN
DO 30 I = 1, N
IFAIL( I ) = 0
30 CONTINUE
END IF
END IF
IF( INFO.EQ.0 ) THEN
M = N
GO TO 40
END IF
INFO = 0
END IF
*
* OTHERWISE, CALL DSTEBZ AND, IF EIGENVECTORS ARE DESIRED, SSTEIN.
*
IF( WANTZ ) THEN
ORDER = 'B'
ELSE
ORDER = 'E'
END IF
INDIBL = 1
INDISP = INDIBL + N
INDIWO = INDISP + N
CALL DSTEBZ( RANGE, ORDER, N, VLL, VUU, IL, IU, ABSTLL,
$ WORK( INDD ), WORK( INDE ), M, NSPLIT, W,
$ IWORK( INDIBL ), IWORK( INDISP ), WORK( INDWRK ),
$ IWORK( INDIWO ), INFO )
*
IF( WANTZ ) THEN
CALL DSTEIN( N, WORK( INDD ), WORK( INDE ), M, W,
$ IWORK( INDIBL ), IWORK( INDISP ), Z, LDZ,
$ WORK( INDWRK ), IWORK( INDIWO ), IFAIL, INFO )
*
* APPLY ORTHOGONAL MATRIX USED IN REDUCTION TO TRIDIAGONAL
* FORM TO EIGENVECTORS RETURNED BY DSTEIN.
*
INDWKN = INDE
LLWRKN = LWORK - INDWKN + 1
CALL DORMTR( 'L', UPLO, 'N', N, M, A, LDA, WORK( INDTAU ), Z,
$ LDZ, WORK( INDWKN ), LLWRKN, IINFO )
END IF
*
* IF MATRIX WAS SCALED, THEN RESCALE EIGENVALUES APPROPRIATELY.
*
40 CONTINUE
IF( ISCALE.EQ.1 ) THEN
IF( INFO.EQ.0 ) THEN
IMAX = M
ELSE
IMAX = INFO - 1
END IF
CALL DSCAL( IMAX, ONE / SIGMA, W, 1 )
END IF
*
* IF EIGENVALUES ARE NOT IN ORDER, THEN SORT THEM, ALONG WITH
* EIGENVECTORS.
*
IF( WANTZ ) THEN
DO 60 J = 1, M - 1
I = 0
TMP1 = W( J )
DO 50 JJ = J + 1, M
IF( W( JJ ).LT.TMP1 ) THEN
I = JJ
TMP1 = W( JJ )
END IF
50 CONTINUE
*
IF( I.NE.0 ) THEN
ITMP1 = IWORK( INDIBL+I-1 )
W( I ) = W( J )
IWORK( INDIBL+I-1 ) = IWORK( INDIBL+J-1 )
W( J ) = TMP1
IWORK( INDIBL+J-1 ) = ITMP1
CALL DSWAP( N, Z( 1, I ), 1, Z( 1, J ), 1 )
IF( INFO.NE.0 ) THEN
ITMP1 = IFAIL( I )
IFAIL( I ) = IFAIL( J )
IFAIL( J ) = ITMP1
END IF
END IF
60 CONTINUE
END IF
*
* SET WORK(1) TO OPTIMAL WORKSPACE SIZE.
*
WORK( 1 ) = MAX( 7*N, LOPT )
*
RETURN
*
* END OF DSYEVX
*
END
CUT HERE............
CAT > DORMTR.F <<'CUT HERE............'
SUBROUTINE DORMTR( SIDE, UPLO, TRANS, M, N, A, LDA, TAU, C, LDC,
$ WORK, LWORK, INFO )
*
* -- LAPACK ROUTINE (VERSION 1.1) --
* UNIV. OF TENNESSEE, UNIV. OF CALIFORNIA BERKELEY, NAG LTD.,
* COURANT INSTITUTE, ARGONNE NATIONAL LAB, AND RICE UNIVERSITY
* MARCH 31, 1993
*
* .. SCALAR ARGUMENTS ..
CHARACTER SIDE, TRANS, UPLO
INTEGER INFO, LDA, LDC, LWORK, M, N
* ..
* .. ARRAY ARGUMENTS ..
DOUBLE PRECISION A( LDA, * ), C( LDC, * ), TAU( * ),
$ WORK( LWORK )
* ..
*
* PURPOSE
* =======
*
* DORMTR OVERWRITES THE GENERAL REAL M-BY-N MATRIX C WITH
*
* SIDE = 'L' SIDE = 'R'
* TRANS = 'N': Q * C C * Q
* TRANS = 'T': Q**T * C C * Q**T
*
* WHERE Q IS A REAL ORTHOGONAL MATRIX OF ORDER NQ, WITH NQ = M IF
* SIDE = 'L' AND NQ = N IF SIDE = 'R'. Q IS DEFINED AS THE PRODUCT OF
* NQ-1 ELEMENTARY REFLECTORS, AS RETURNED BY DSYTRD:
*
* IF UPLO = 'U', Q = H(NQ-1) . . . H(2) H(1);
*
* IF UPLO = 'L', Q = H(1) H(2) . . . H(NQ-1).
*
* ARGUMENTS
* =========
*
* SIDE (INPUT) CHARACTER*1
* = 'L': APPLY Q OR Q**T FROM THE LEFT;
* = 'R': APPLY Q OR Q**T FROM THE RIGHT.
*
* UPLO (INPUT) CHARACTER*1
* = 'U': UPPER TRIANGLE OF A CONTAINS ELEMENTARY REFLECTORS
* FROM DSYTRD;
* = 'L': LOWER TRIANGLE OF A CONTAINS ELEMENTARY REFLECTORS
* FROM DSYTRD.
*
* TRANS (INPUT) CHARACTER*1
* = 'N': NO TRANSPOSE, APPLY Q;
* = 'T': TRANSPOSE, APPLY Q**T.
*
* M (INPUT) INTEGER
* THE NUMBER OF ROWS OF THE MATRIX C. M >= 0.
*
* N (INPUT) INTEGER
* THE NUMBER OF COLUMNS OF THE MATRIX C. N >= 0.
*
* A (INPUT) DOUBLE PRECISION ARRAY, DIMENSION
* (LDA,M) IF SIDE = 'L'
* (LDA,N) IF SIDE = 'R'
* THE VECTORS WHICH DEFINE THE ELEMENTARY REFLECTORS, AS
* RETURNED BY DSYTRD.
*
* LDA (INPUT) INTEGER
* THE LEADING DIMENSION OF THE ARRAY A.
* LDA >= MAX(1,M) IF SIDE = 'L'; LDA >= MAX(1,N) IF SIDE = 'R'.
*
* TAU (INPUT) DOUBLE PRECISION ARRAY, DIMENSION
* (M-1) IF SIDE = 'L'
* (N-1) IF SIDE = 'R'
* TAU(I) MUST CONTAIN THE SCALAR FACTOR OF THE ELEMENTARY
* REFLECTOR H(I), AS RETURNED BY DSYTRD.
*
* C (INPUT/OUTPUT) DOUBLE PRECISION ARRAY, DIMENSION (LDC,N)
* ON ENTRY, THE M-BY-N MATRIX C.
* ON EXIT, C IS OVERWRITTEN BY Q*C OR Q**T*C OR C*Q**T OR C*Q.
*
* LDC (INPUT) INTEGER
* THE LEADING DIMENSION OF THE ARRAY C. LDC >= MAX(1,M).
*
* WORK (WORKSPACE) DOUBLE PRECISION ARRAY, DIMENSION (LWORK)
* ON EXIT, IF INFO = 0, WORK(1) RETURNS THE OPTIMAL LWORK.
*
* LWORK (INPUT) INTEGER
* THE DIMENSION OF THE ARRAY WORK.
* IF SIDE = 'L', LWORK >= MAX(1,N);
* IF SIDE = 'R', LWORK >= MAX(1,M).
* FOR OPTIMUM PERFORMANCE LWORK >= N*NB IF SIDE = 'L', AND
* LWORK >= M*NB IF SIDE = 'R', WHERE NB IS THE OPTIMAL
* BLOCKSIZE.
*
* INFO (OUTPUT) INTEGER
* = 0: SUCCESSFUL EXIT
* < 0: IF INFO = -I, THE I-TH ARGUMENT HAD AN ILLEGAL VALUE
*
* =====================================================================
*
* .. LOCAL SCALARS ..
LOGICAL LEFT, UPPER
INTEGER I1, I2, IINFO, MI, NI, NQ, NW
* ..
* .. EXTERNAL FUNCTIONS ..
LOGICAL LSAME
EXTERNAL LSAME
* ..
* .. EXTERNAL SUBROUTINES ..
EXTERNAL DORMQL, DORMQR, XERBLA
* ..
* .. INTRINSIC FUNCTIONS ..
INTRINSIC MAX
* ..
* .. EXECUTABLE STATEMENTS ..
*
* TEST THE INPUT ARGUMENTS
*
INFO = 0
LEFT = LSAME( SIDE, 'L' )
UPPER = LSAME( UPLO, 'U' )
*
* NQ IS THE ORDER OF Q AND NW IS THE MINIMUM DIMENSION OF WORK
*
IF( LEFT ) THEN
NQ = M
NW = N
ELSE
NQ = N
NW = M
END IF
IF( .NOT.LEFT .AND. .NOT.LSAME( SIDE, 'R' ) ) THEN
INFO = -1
ELSE IF( .NOT.UPPER .AND. .NOT.LSAME( UPLO, 'L' ) ) THEN
INFO = -2
ELSE IF( .NOT.LSAME( TRANS, 'N' ) .AND. .NOT.LSAME( TRANS, 'T' ) )
$ THEN
INFO = -3
ELSE IF( M.LT.0 ) THEN
INFO = -4
ELSE IF( N.LT.0 ) THEN
INFO = -5
ELSE IF( LDA.LT.MAX( 1, NQ ) ) THEN
INFO = -7
ELSE IF( LDC.LT.MAX( 1, M ) ) THEN
INFO = -10
ELSE IF( LWORK.LT.MAX( 1, NW ) ) THEN
INFO = -12
END IF
IF( INFO.NE.0 ) THEN
CALL XERBLA( 'DORMTR', -INFO )
RETURN
END IF
*
* QUICK RETURN IF POSSIBLE
*
IF( M.EQ.0 .OR. N.EQ.0 .OR. NQ.EQ.1 ) THEN
WORK( 1 ) = 1
RETURN
END IF
*
IF( LEFT ) THEN
MI = M - 1
NI = N
ELSE
MI = M
NI = N - 1
END IF
*
IF( UPPER ) THEN
*
* Q WAS DETERMINED BY A CALL TO DSYTRD WITH UPLO = 'U'
*
CALL DORMQL( SIDE, TRANS, MI, NI, NQ-1, A( 1, 2 ), LDA, TAU, C,
$ LDC, WORK, LWORK, IINFO )
ELSE
*
* Q WAS DETERMINED BY A CALL TO DSYTRD WITH UPLO = 'L'
*
IF( LEFT ) THEN
I1 = 2
I2 = 1
ELSE
I1 = 1
I2 = 2
END IF
CALL DORMQR( SIDE, TRANS, MI, NI, NQ-1, A( 2, 1 ), LDA, TAU,
$ C( I1, I2 ), LDC, WORK, LWORK, IINFO )
END IF
RETURN
*
* END OF DORMTR
*
END
CUT HERE............
CAT > DORMQR.F <<'CUT HERE............'
SUBROUTINE DORMQR( SIDE, TRANS, M, N, K, A, LDA, TAU, C, LDC,
$ WORK, LWORK, INFO )
*
* -- LAPACK ROUTINE (VERSION 1.1) --
* UNIV. OF TENNESSEE, UNIV. OF CALIFORNIA BERKELEY, NAG LTD.,
* COURANT INSTITUTE, ARGONNE NATIONAL LAB, AND RICE UNIVERSITY
* MARCH 31, 1993
*
* .. SCALAR ARGUMENTS ..
CHARACTER SIDE, TRANS
INTEGER INFO, K, LDA, LDC, LWORK, M, N
* ..
* .. ARRAY ARGUMENTS ..
DOUBLE PRECISION A( LDA, * ), C( LDC, * ), TAU( * ),
$ WORK( LWORK )
* ..
*
* PURPOSE
* =======
*
* DORMQR OVERWRITES THE GENERAL REAL M-BY-N MATRIX C WITH
*
* SIDE = 'L' SIDE = 'R'
* TRANS = 'N': Q * C C * Q
* TRANS = 'T': Q**T * C C * Q**T
*
* WHERE Q IS A REAL ORTHOGONAL MATRIX DEFINED AS THE PRODUCT OF K
* ELEMENTARY REFLECTORS
*
* Q = H(1) H(2) . . . H(K)
*
* AS RETURNED BY DGEQRF. Q IS OF ORDER M IF SIDE = 'L' AND OF ORDER N
* IF SIDE = 'R'.
*
* ARGUMENTS
* =========
*
* SIDE (INPUT) CHARACTER*1
* = 'L': APPLY Q OR Q**T FROM THE LEFT;
* = 'R': APPLY Q OR Q**T FROM THE RIGHT.
*
* TRANS (INPUT) CHARACTER*1
* = 'N': NO TRANSPOSE, APPLY Q;
* = 'T': TRANSPOSE, APPLY Q**T.
*
* M (INPUT) INTEGER
* THE NUMBER OF ROWS OF THE MATRIX C. M >= 0.
*
* N (INPUT) INTEGER
* THE NUMBER OF COLUMNS OF THE MATRIX C. N >= 0.
*
* K (INPUT) INTEGER
* THE NUMBER OF ELEMENTARY REFLECTORS WHOSE PRODUCT DEFINES
* THE MATRIX Q.
* IF SIDE = 'L', M >= K >= 0;
* IF SIDE = 'R', N >= K >= 0.
*
* A (INPUT) DOUBLE PRECISION ARRAY, DIMENSION (LDA,K)
* THE I-TH COLUMN MUST CONTAIN THE VECTOR WHICH DEFINES THE
* ELEMENTARY REFLECTOR H(I), FOR I = 1,2,...,K, AS RETURNED BY
* DGEQRF IN THE FIRST K COLUMNS OF ITS ARRAY ARGUMENT A.
* A IS MODIFIED BY THE ROUTINE BUT RESTORED ON EXIT.
*
* LDA (INPUT) INTEGER
* THE LEADING DIMENSION OF THE ARRAY A.
* IF SIDE = 'L', LDA >= MAX(1,M);
* IF SIDE = 'R', LDA >= MAX(1,N).
*
* TAU (INPUT) DOUBLE PRECISION ARRAY, DIMENSION (K)
* TAU(I) MUST CONTAIN THE SCALAR FACTOR OF THE ELEMENTARY
* REFLECTOR H(I), AS RETURNED BY DGEQRF.
*
* C (INPUT/OUTPUT) DOUBLE PRECISION ARRAY, DIMENSION (LDC,N)
* ON ENTRY, THE M-BY-N MATRIX C.
* ON EXIT, C IS OVERWRITTEN BY Q*C OR Q**T*C OR C*Q**T OR C*Q.
*
* LDC (INPUT) INTEGER
* THE LEADING DIMENSION OF THE ARRAY C. LDC >= MAX(1,M).
*
* WORK (WORKSPACE) DOUBLE PRECISION ARRAY, DIMENSION (LWORK)
* ON EXIT, IF INFO = 0, WORK(1) RETURNS THE OPTIMAL LWORK.
*
* LWORK (INPUT) INTEGER
* THE DIMENSION OF THE ARRAY WORK.
* IF SIDE = 'L', LWORK >= MAX(1,N);
* IF SIDE = 'R', LWORK >= MAX(1,M).
* FOR OPTIMUM PERFORMANCE LWORK >= N*NB IF SIDE = 'L', AND
* LWORK >= M*NB IF SIDE = 'R', WHERE NB IS THE OPTIMAL
* BLOCKSIZE.
*
* INFO (OUTPUT) INTEGER
* = 0: SUCCESSFUL EXIT
* < 0: IF INFO = -I, THE I-TH ARGUMENT HAD AN ILLEGAL VALUE
*
* =====================================================================
*
* .. PARAMETERS ..
INTEGER NBMAX, LDT
PARAMETER ( NBMAX = 64, LDT = NBMAX+1 )
* ..
* .. LOCAL SCALARS ..
LOGICAL LEFT, NOTRAN
INTEGER I, I1, I2, I3, IB, IC, IINFO, IWS, JC, LDWORK,
$ MI, NB, NBMIN, NI, NQ, NW
* ..
* .. LOCAL ARRAYS ..
DOUBLE PRECISION T( LDT, NBMAX )
* ..
* .. EXTERNAL FUNCTIONS ..
LOGICAL LSAME
INTEGER ILAENV
EXTERNAL LSAME, ILAENV
* ..
* .. EXTERNAL SUBROUTINES ..
EXTERNAL DLARFB, DLARFT, DORM2R, XERBLA
* ..
* .. INTRINSIC FUNCTIONS ..
INTRINSIC MAX, MIN
* ..
* .. EXECUTABLE STATEMENTS ..
*
* TEST THE INPUT ARGUMENTS
*
INFO = 0
LEFT = LSAME( SIDE, 'L' )
NOTRAN = LSAME( TRANS, 'N' )
*
* NQ IS THE ORDER OF Q AND NW IS THE MINIMUM DIMENSION OF WORK
*
IF( LEFT ) THEN
NQ = M
NW = N
ELSE
NQ = N
NW = M
END IF
IF( .NOT.LEFT .AND. .NOT.LSAME( SIDE, 'R' ) ) THEN
INFO = -1
ELSE IF( .NOT.NOTRAN .AND. .NOT.LSAME( TRANS, 'T' ) ) THEN
INFO = -2
ELSE IF( M.LT.0 ) THEN
INFO = -3
ELSE IF( N.LT.0 ) THEN
INFO = -4
ELSE IF( K.LT.0 .OR. K.GT.NQ ) THEN
INFO = -5
ELSE IF( LDA.LT.MAX( 1, NQ ) ) THEN
INFO = -7
ELSE IF( LDC.LT.MAX( 1, M ) ) THEN
INFO = -10
ELSE IF( LWORK.LT.MAX( 1, NW ) ) THEN
INFO = -12
END IF
IF( INFO.NE.0 ) THEN
CALL XERBLA( 'DORMQR', -INFO )
RETURN
END IF
*
* QUICK RETURN IF POSSIBLE
*
IF( M.EQ.0 .OR. N.EQ.0 .OR. K.EQ.0 ) THEN
WORK( 1 ) = 1
RETURN
END IF
*
* DETERMINE THE BLOCK SIZE. NB MAY BE AT MOST NBMAX, WHERE NBMAX
* IS USED TO DEFINE THE LOCAL ARRAY T.
*
NB = MIN( NBMAX, ILAENV( 1, 'DORMQR', SIDE // TRANS, M, N, K,
$ -1 ) )
NBMIN = 2
LDWORK = NW
IF( NB.GT.1 .AND. NB.LT.K ) THEN
IWS = NW*NB
IF( LWORK.LT.IWS ) THEN
NB = LWORK / LDWORK
NBMIN = MAX( 2, ILAENV( 2, 'DORMQR', SIDE // TRANS, M, N, K,
$ -1 ) )
END IF
ELSE
IWS = NW
END IF
*
IF( NB.LT.NBMIN .OR. NB.GE.K ) THEN
*
* USE UNBLOCKED CODE
*
CALL DORM2R( SIDE, TRANS, M, N, K, A, LDA, TAU, C, LDC, WORK,
$ IINFO )
ELSE
*
* USE BLOCKED CODE
*
IF( ( LEFT .AND. .NOT.NOTRAN ) .OR.
$ ( .NOT.LEFT .AND. NOTRAN ) ) THEN
I1 = 1
I2 = K
I3 = NB
ELSE
I1 = ( ( K-1 ) / NB )*NB + 1
I2 = 1
I3 = -NB
END IF
*
IF( LEFT ) THEN
NI = N
JC = 1
ELSE
MI = M
IC = 1
END IF
*
DO 10 I = I1, I2, I3
IB = MIN( NB, K-I+1 )
*
* FORM THE TRIANGULAR FACTOR OF THE BLOCK REFLECTOR
* H = H(I) H(I+1) . . . H(I+IB-1)
*
CALL DLARFT( 'FORWARD', 'COLUMNWISE', NQ-I+1, IB, A( I, I ),
$ LDA, TAU( I ), T, LDT )
IF( LEFT ) THEN
*
* H OR H' IS APPLIED TO C(I:M,1:N)
*
MI = M - I + 1
IC = I
ELSE
*
* H OR H' IS APPLIED TO C(1:M,I:N)
*
NI = N - I + 1
JC = I
END IF
*
* APPLY H OR H'
*
CALL DLARFB( SIDE, TRANS, 'FORWARD', 'COLUMNWISE', MI, NI,
$ IB, A( I, I ), LDA, T, LDT, C( IC, JC ), LDC,
$ WORK, LDWORK )
10 CONTINUE
END IF
WORK( 1 ) = IWS
RETURN
*
* END OF DORMQR
*
END
CUT HERE............
CAT > DORM2R.F <<'CUT HERE............'
SUBROUTINE DORM2R( SIDE, TRANS, M, N, K, A, LDA, TAU, C, LDC,
$ WORK, INFO )
*
* -- LAPACK ROUTINE (VERSION 1.1) --
* UNIV. OF TENNESSEE, UNIV. OF CALIFORNIA BERKELEY, NAG LTD.,
* COURANT INSTITUTE, ARGONNE NATIONAL LAB, AND RICE UNIVERSITY
* FEBRUARY 29, 1992
*
* .. SCALAR ARGUMENTS ..
CHARACTER SIDE, TRANS
INTEGER INFO, K, LDA, LDC, M, N
* ..
* .. ARRAY ARGUMENTS ..
DOUBLE PRECISION A( LDA, * ), C( LDC, * ), TAU( * ), WORK( * )
* ..
*
* PURPOSE
* =======
*
* DORM2R OVERWRITES THE GENERAL REAL M BY N MATRIX C WITH
*
* Q * C IF SIDE = 'L' AND TRANS = 'N', OR
*
* Q'* C IF SIDE = 'L' AND TRANS = 'T', OR
*
* C * Q IF SIDE = 'R' AND TRANS = 'N', OR
*
* C * Q' IF SIDE = 'R' AND TRANS = 'T',
*
* WHERE Q IS A REAL ORTHOGONAL MATRIX DEFINED AS THE PRODUCT OF K
* ELEMENTARY REFLECTORS
*
* Q = H(1) H(2) . . . H(K)
*
* AS RETURNED BY DGEQRF. Q IS OF ORDER M IF SIDE = 'L' AND OF ORDER N
* IF SIDE = 'R'.
*
* ARGUMENTS
* =========
*
* SIDE (INPUT) CHARACTER*1
* = 'L': APPLY Q OR Q' FROM THE LEFT
* = 'R': APPLY Q OR Q' FROM THE RIGHT
*
* TRANS (INPUT) CHARACTER*1
* = 'N': APPLY Q (NO TRANSPOSE)
* = 'T': APPLY Q' (TRANSPOSE)
*
* M (INPUT) INTEGER
* THE NUMBER OF ROWS OF THE MATRIX C. M >= 0.
*
* N (INPUT) INTEGER
* THE NUMBER OF COLUMNS OF THE MATRIX C. N >= 0.
*
* K (INPUT) INTEGER
* THE NUMBER OF ELEMENTARY REFLECTORS WHOSE PRODUCT DEFINES
* THE MATRIX Q.
* IF SIDE = 'L', M >= K >= 0;
* IF SIDE = 'R', N >= K >= 0.
*
* A (INPUT) DOUBLE PRECISION ARRAY, DIMENSION (LDA,K)
* THE I-TH COLUMN MUST CONTAIN THE VECTOR WHICH DEFINES THE
* ELEMENTARY REFLECTOR H(I), FOR I = 1,2,...,K, AS RETURNED BY
* DGEQRF IN THE FIRST K COLUMNS OF ITS ARRAY ARGUMENT A.
* A IS MODIFIED BY THE ROUTINE BUT RESTORED ON EXIT.
*
* LDA (INPUT) INTEGER
* THE LEADING DIMENSION OF THE ARRAY A.
* IF SIDE = 'L', LDA >= MAX(1,M);
* IF SIDE = 'R', LDA >= MAX(1,N).
*
* TAU (INPUT) DOUBLE PRECISION ARRAY, DIMENSION (K)
* TAU(I) MUST CONTAIN THE SCALAR FACTOR OF THE ELEMENTARY
* REFLECTOR H(I), AS RETURNED BY DGEQRF.
*
* C (INPUT/OUTPUT) DOUBLE PRECISION ARRAY, DIMENSION (LDC,N)
* ON ENTRY, THE M BY N MATRIX C.
* ON EXIT, C IS OVERWRITTEN BY Q*C OR Q'*C OR C*Q' OR C*Q.
*
* LDC (INPUT) INTEGER
* THE LEADING DIMENSION OF THE ARRAY C. LDC >= MAX(1,M).
*
* WORK (WORKSPACE) DOUBLE PRECISION ARRAY, DIMENSION
* (N) IF SIDE = 'L',
* (M) IF SIDE = 'R'
*
* INFO (OUTPUT) INTEGER
* = 0: SUCCESSFUL EXIT
* < 0: IF INFO = -I, THE I-TH ARGUMENT HAD AN ILLEGAL VALUE
*
* =====================================================================
*
* .. PARAMETERS ..
DOUBLE PRECISION ONE
PARAMETER ( ONE = 1.0D+0 )
* ..
* .. LOCAL SCALARS ..
LOGICAL LEFT, NOTRAN
INTEGER I, I1, I2, I3, IC, JC, MI, NI, NQ
DOUBLE PRECISION AII
* ..
* .. EXTERNAL FUNCTIONS ..
LOGICAL LSAME
EXTERNAL LSAME
* ..
* .. EXTERNAL SUBROUTINES ..
EXTERNAL DLARF, XERBLA
* ..
* .. INTRINSIC FUNCTIONS ..
INTRINSIC MAX
* ..
* .. EXECUTABLE STATEMENTS ..
*
* TEST THE INPUT ARGUMENTS
*
INFO = 0
LEFT = LSAME( SIDE, 'L' )
NOTRAN = LSAME( TRANS, 'N' )
*
* NQ IS THE ORDER OF Q
*
IF( LEFT ) THEN
NQ = M
ELSE
NQ = N
END IF
IF( .NOT.LEFT .AND. .NOT.LSAME( SIDE, 'R' ) ) THEN
INFO = -1
ELSE IF( .NOT.NOTRAN .AND. .NOT.LSAME( TRANS, 'T' ) ) THEN
INFO = -2
ELSE IF( M.LT.0 ) THEN
INFO = -3
ELSE IF( N.LT.0 ) THEN
INFO = -4
ELSE IF( K.LT.0 .OR. K.GT.NQ ) THEN
INFO = -5
ELSE IF( LDA.LT.MAX( 1, NQ ) ) THEN
INFO = -7
ELSE IF( LDC.LT.MAX( 1, M ) ) THEN
INFO = -10
END IF
IF( INFO.NE.0 ) THEN
CALL XERBLA( 'DORM2R', -INFO )
RETURN
END IF
*
* QUICK RETURN IF POSSIBLE
*
IF( M.EQ.0 .OR. N.EQ.0 .OR. K.EQ.0 )
$ RETURN
*
IF( ( LEFT .AND. .NOT.NOTRAN ) .OR. ( .NOT.LEFT .AND. NOTRAN ) )
$ THEN
I1 = 1
I2 = K
I3 = 1
ELSE
I1 = K
I2 = 1
I3 = -1
END IF
*
IF( LEFT ) THEN
NI = N
JC = 1
ELSE
MI = M
IC = 1
END IF
*
DO 10 I = I1, I2, I3
IF( LEFT ) THEN
*
* H(I) IS APPLIED TO C(I:M,1:N)
*
MI = M - I + 1
IC = I
ELSE
*
* H(I) IS APPLIED TO C(1:M,I:N)
*
NI = N - I + 1
JC = I
END IF
*
* APPLY H(I)
*
AII = A( I, I )
A( I, I ) = ONE
CALL DLARF( SIDE, MI, NI, A( I, I ), 1, TAU( I ), C( IC, JC ),
$ LDC, WORK )
A( I, I ) = AII
10 CONTINUE
RETURN
*
* END OF DORM2R
*
END
CUT HERE............
CAT > DORMQL.F <<'CUT HERE............'
SUBROUTINE DORMQL( SIDE, TRANS, M, N, K, A, LDA, TAU, C, LDC,
$ WORK, LWORK, INFO )
*
* -- LAPACK ROUTINE (VERSION 1.1) --
* UNIV. OF TENNESSEE, UNIV. OF CALIFORNIA BERKELEY, NAG LTD.,
* COURANT INSTITUTE, ARGONNE NATIONAL LAB, AND RICE UNIVERSITY
* MARCH 31, 1993
*
* .. SCALAR ARGUMENTS ..
CHARACTER SIDE, TRANS
INTEGER INFO, K, LDA, LDC, LWORK, M, N
* ..
* .. ARRAY ARGUMENTS ..
DOUBLE PRECISION A( LDA, * ), C( LDC, * ), TAU( * ),
$ WORK( LWORK )
* ..
*
* PURPOSE
* =======
*
* DORMQL OVERWRITES THE GENERAL REAL M-BY-N MATRIX C WITH
*
* SIDE = 'L' SIDE = 'R'
* TRANS = 'N': Q * C C * Q
* TRANS = 'T': Q**T * C C * Q**T
*
* WHERE Q IS A REAL ORTHOGONAL MATRIX DEFINED AS THE PRODUCT OF K
* ELEMENTARY REFLECTORS
*
* Q = H(K) . . . H(2) H(1)
*
* AS RETURNED BY DGEQLF. Q IS OF ORDER M IF SIDE = 'L' AND OF ORDER N
* IF SIDE = 'R'.
*
* ARGUMENTS
* =========
*
* SIDE (INPUT) CHARACTER*1
* = 'L': APPLY Q OR Q**T FROM THE LEFT;
* = 'R': APPLY Q OR Q**T FROM THE RIGHT.
*
* TRANS (INPUT) CHARACTER*1
* = 'N': NO TRANSPOSE, APPLY Q;
* = 'T': TRANSPOSE, APPLY Q**T.
*
* M (INPUT) INTEGER
* THE NUMBER OF ROWS OF THE MATRIX C. M >= 0.
*
* N (INPUT) INTEGER
* THE NUMBER OF COLUMNS OF THE MATRIX C. N >= 0.
*
* K (INPUT) INTEGER
* THE NUMBER OF ELEMENTARY REFLECTORS WHOSE PRODUCT DEFINES
* THE MATRIX Q.
* IF SIDE = 'L', M >= K >= 0;
* IF SIDE = 'R', N >= K >= 0.
*
* A (INPUT) DOUBLE PRECISION ARRAY, DIMENSION (LDA,K)
* THE I-TH COLUMN MUST CONTAIN THE VECTOR WHICH DEFINES THE
* ELEMENTARY REFLECTOR H(I), FOR I = 1,2,...,K, AS RETURNED BY
* DGEQLF IN THE LAST K COLUMNS OF ITS ARRAY ARGUMENT A.
* A IS MODIFIED BY THE ROUTINE BUT RESTORED ON EXIT.
*
* LDA (INPUT) INTEGER
* THE LEADING DIMENSION OF THE ARRAY A.
* IF SIDE = 'L', LDA >= MAX(1,M);
* IF SIDE = 'R', LDA >= MAX(1,N).
*
* TAU (INPUT) DOUBLE PRECISION ARRAY, DIMENSION (K)
* TAU(I) MUST CONTAIN THE SCALAR FACTOR OF THE ELEMENTARY
* REFLECTOR H(I), AS RETURNED BY DGEQLF.
*
* C (INPUT/OUTPUT) DOUBLE PRECISION ARRAY, DIMENSION (LDC,N)
* ON ENTRY, THE M-BY-N MATRIX C.
* ON EXIT, C IS OVERWRITTEN BY Q*C OR Q**T*C OR C*Q**T OR C*Q.
*
* LDC (INPUT) INTEGER
* THE LEADING DIMENSION OF THE ARRAY C. LDC >= MAX(1,M).
*
* WORK (WORKSPACE) DOUBLE PRECISION ARRAY, DIMENSION (LWORK)
* ON EXIT, IF INFO = 0, WORK(1) RETURNS THE OPTIMAL LWORK.
*
* LWORK (INPUT) INTEGER
* THE DIMENSION OF THE ARRAY WORK.
* IF SIDE = 'L', LWORK >= MAX(1,N);
* IF SIDE = 'R', LWORK >= MAX(1,M).
* FOR OPTIMUM PERFORMANCE LWORK >= N*NB IF SIDE = 'L', AND
* LWORK >= M*NB IF SIDE = 'R', WHERE NB IS THE OPTIMAL
* BLOCKSIZE.
*
* INFO (OUTPUT) INTEGER
* = 0: SUCCESSFUL EXIT
* < 0: IF INFO = -I, THE I-TH ARGUMENT HAD AN ILLEGAL VALUE
*
* =====================================================================
*
* .. PARAMETERS ..
INTEGER NBMAX, LDT
PARAMETER ( NBMAX = 64, LDT = NBMAX+1 )
* ..
* .. LOCAL SCALARS ..
LOGICAL LEFT, NOTRAN
INTEGER I, I1, I2, I3, IB, IINFO, IWS, LDWORK, MI, NB,
$ NBMIN, NI, NQ, NW
* ..
* .. LOCAL ARRAYS ..
DOUBLE PRECISION T( LDT, NBMAX )
* ..
* .. EXTERNAL FUNCTIONS ..
LOGICAL LSAME
INTEGER ILAENV
EXTERNAL LSAME, ILAENV
* ..
* .. EXTERNAL SUBROUTINES ..
EXTERNAL DLARFB, DLARFT, DORM2L, XERBLA
* ..
* .. INTRINSIC FUNCTIONS ..
INTRINSIC MAX, MIN
* ..
* .. EXECUTABLE STATEMENTS ..
*
* TEST THE INPUT ARGUMENTS
*
INFO = 0
LEFT = LSAME( SIDE, 'L' )
NOTRAN = LSAME( TRANS, 'N' )
*
* NQ IS THE ORDER OF Q AND NW IS THE MINIMUM DIMENSION OF WORK
*
IF( LEFT ) THEN
NQ = M
NW = N
ELSE
NQ = N
NW = M
END IF
IF( .NOT.LEFT .AND. .NOT.LSAME( SIDE, 'R' ) ) THEN
INFO = -1
ELSE IF( .NOT.NOTRAN .AND. .NOT.LSAME( TRANS, 'T' ) ) THEN
INFO = -2
ELSE IF( M.LT.0 ) THEN
INFO = -3
ELSE IF( N.LT.0 ) THEN
INFO = -4
ELSE IF( K.LT.0 .OR. K.GT.NQ ) THEN
INFO = -5
ELSE IF( LDA.LT.MAX( 1, NQ ) ) THEN
INFO = -7
ELSE IF( LDC.LT.MAX( 1, M ) ) THEN
INFO = -10
ELSE IF( LWORK.LT.MAX( 1, NW ) ) THEN
INFO = -12
END IF
IF( INFO.NE.0 ) THEN
CALL XERBLA( 'DORMQL', -INFO )
RETURN
END IF
*
* QUICK RETURN IF POSSIBLE
*
IF( M.EQ.0 .OR. N.EQ.0 .OR. K.EQ.0 ) THEN
WORK( 1 ) = 1
RETURN
END IF
*
* DETERMINE THE BLOCK SIZE. NB MAY BE AT MOST NBMAX, WHERE NBMAX
* IS USED TO DEFINE THE LOCAL ARRAY T.
*
NB = MIN( NBMAX, ILAENV( 1, 'DORMQL', SIDE // TRANS, M, N, K,
$ -1 ) )
NBMIN = 2
LDWORK = NW
IF( NB.GT.1 .AND. NB.LT.K ) THEN
IWS = NW*NB
IF( LWORK.LT.IWS ) THEN
NB = LWORK / LDWORK
NBMIN = MAX( 2, ILAENV( 2, 'DORMQL', SIDE // TRANS, M, N, K,
$ -1 ) )
END IF
ELSE
IWS = NW
END IF
*
IF( NB.LT.NBMIN .OR. NB.GE.K ) THEN
*
* USE UNBLOCKED CODE
*
CALL DORM2L( SIDE, TRANS, M, N, K, A, LDA, TAU, C, LDC, WORK,
$ IINFO )
ELSE
*
* USE BLOCKED CODE
*
IF( ( LEFT .AND. NOTRAN ) .OR.
$ ( .NOT.LEFT .AND. .NOT.NOTRAN ) ) THEN
I1 = 1
I2 = K
I3 = NB
ELSE
I1 = ( ( K-1 ) / NB )*NB + 1
I2 = 1
I3 = -NB
END IF
*
IF( LEFT ) THEN
NI = N
ELSE
MI = M
END IF
*
DO 10 I = I1, I2, I3
IB = MIN( NB, K-I+1 )
*
* FORM THE TRIANGULAR FACTOR OF THE BLOCK REFLECTOR
* H = H(I+IB-1) . . . H(I+1) H(I)
*
CALL DLARFT( 'BACKWARD', 'COLUMNWISE', NQ-K+I+IB-1, IB,
$ A( 1, I ), LDA, TAU( I ), T, LDT )
IF( LEFT ) THEN
*
* H OR H' IS APPLIED TO C(1:M-K+I+IB-1,1:N)
*
MI = M - K + I + IB - 1
ELSE
*
* H OR H' IS APPLIED TO C(1:M,1:N-K+I+IB-1)
*
NI = N - K + I + IB - 1
END IF
*
* APPLY H OR H'
*
CALL DLARFB( SIDE, TRANS, 'BACKWARD', 'COLUMNWISE', MI, NI,
$ IB, A( 1, I ), LDA, T, LDT, C, LDC, WORK,
$ LDWORK )
10 CONTINUE
END IF
WORK( 1 ) = IWS
RETURN
*
* END OF DORMQL
*
END
CUT HERE............
CAT > DORM2L.F <<'CUT HERE............'
SUBROUTINE DORM2L( SIDE, TRANS, M, N, K, A, LDA, TAU, C, LDC,
$ WORK, INFO )
*
* -- LAPACK ROUTINE (VERSION 1.1) --
* UNIV. OF TENNESSEE, UNIV. OF CALIFORNIA BERKELEY, NAG LTD.,
* COURANT INSTITUTE, ARGONNE NATIONAL LAB, AND RICE UNIVERSITY
* FEBRUARY 29, 1992
*
* .. SCALAR ARGUMENTS ..
CHARACTER SIDE, TRANS
INTEGER INFO, K, LDA, LDC, M, N
* ..
* .. ARRAY ARGUMENTS ..
DOUBLE PRECISION A( LDA, * ), C( LDC, * ), TAU( * ), WORK( * )
* ..
*
* PURPOSE
* =======
*
* DORM2L OVERWRITES THE GENERAL REAL M BY N MATRIX C WITH
*
* Q * C IF SIDE = 'L' AND TRANS = 'N', OR
*
* Q'* C IF SIDE = 'L' AND TRANS = 'T', OR
*
* C * Q IF SIDE = 'R' AND TRANS = 'N', OR
*
* C * Q' IF SIDE = 'R' AND TRANS = 'T',
*
* WHERE Q IS A REAL ORTHOGONAL MATRIX DEFINED AS THE PRODUCT OF K
* ELEMENTARY REFLECTORS
*
* Q = H(K) . . . H(2) H(1)
*
* AS RETURNED BY DGEQLF. Q IS OF ORDER M IF SIDE = 'L' AND OF ORDER N
* IF SIDE = 'R'.
*
* ARGUMENTS
* =========
*
* SIDE (INPUT) CHARACTER*1
* = 'L': APPLY Q OR Q' FROM THE LEFT
* = 'R': APPLY Q OR Q' FROM THE RIGHT
*
* TRANS (INPUT) CHARACTER*1
* = 'N': APPLY Q (NO TRANSPOSE)
* = 'T': APPLY Q' (TRANSPOSE)
*
* M (INPUT) INTEGER
* THE NUMBER OF ROWS OF THE MATRIX C. M >= 0.
*
* N (INPUT) INTEGER
* THE NUMBER OF COLUMNS OF THE MATRIX C. N >= 0.
*
* K (INPUT) INTEGER
* THE NUMBER OF ELEMENTARY REFLECTORS WHOSE PRODUCT DEFINES
* THE MATRIX Q.
* IF SIDE = 'L', M >= K >= 0;
* IF SIDE = 'R', N >= K >= 0.
*
* A (INPUT) DOUBLE PRECISION ARRAY, DIMENSION (LDA,K)
* THE I-TH COLUMN MUST CONTAIN THE VECTOR WHICH DEFINES THE
* ELEMENTARY REFLECTOR H(I), FOR I = 1,2,...,K, AS RETURNED BY
* DGEQLF IN THE LAST K COLUMNS OF ITS ARRAY ARGUMENT A.
* A IS MODIFIED BY THE ROUTINE BUT RESTORED ON EXIT.
*
* LDA (INPUT) INTEGER
* THE LEADING DIMENSION OF THE ARRAY A.
* IF SIDE = 'L', LDA >= MAX(1,M);
* IF SIDE = 'R', LDA >= MAX(1,N).
*
* TAU (INPUT) DOUBLE PRECISION ARRAY, DIMENSION (K)
* TAU(I) MUST CONTAIN THE SCALAR FACTOR OF THE ELEMENTARY
* REFLECTOR H(I), AS RETURNED BY DGEQLF.
*
* C (INPUT/OUTPUT) DOUBLE PRECISION ARRAY, DIMENSION (LDC,N)
* ON ENTRY, THE M BY N MATRIX C.
* ON EXIT, C IS OVERWRITTEN BY Q*C OR Q'*C OR C*Q' OR C*Q.
*
* LDC (INPUT) INTEGER
* THE LEADING DIMENSION OF THE ARRAY C. LDC >= MAX(1,M).
*
* WORK (WORKSPACE) DOUBLE PRECISION ARRAY, DIMENSION
* (N) IF SIDE = 'L',
* (M) IF SIDE = 'R'
*
* INFO (OUTPUT) INTEGER
* = 0: SUCCESSFUL EXIT
* < 0: IF INFO = -I, THE I-TH ARGUMENT HAD AN ILLEGAL VALUE
*
* =====================================================================
*
* .. PARAMETERS ..
DOUBLE PRECISION ONE
PARAMETER ( ONE = 1.0D+0 )
* ..
* .. LOCAL SCALARS ..
LOGICAL LEFT, NOTRAN
INTEGER I, I1, I2, I3, MI, NI, NQ
DOUBLE PRECISION AII
* ..
* .. EXTERNAL FUNCTIONS ..
LOGICAL LSAME
EXTERNAL LSAME
* ..
* .. EXTERNAL SUBROUTINES ..
EXTERNAL DLARF, XERBLA
* ..
* .. INTRINSIC FUNCTIONS ..
INTRINSIC MAX
* ..
* .. EXECUTABLE STATEMENTS ..
*
* TEST THE INPUT ARGUMENTS
*
INFO = 0
LEFT = LSAME( SIDE, 'L' )
NOTRAN = LSAME( TRANS, 'N' )
*
* NQ IS THE ORDER OF Q
*
IF( LEFT ) THEN
NQ = M
ELSE
NQ = N
END IF
IF( .NOT.LEFT .AND. .NOT.LSAME( SIDE, 'R' ) ) THEN
INFO = -1
ELSE IF( .NOT.NOTRAN .AND. .NOT.LSAME( TRANS, 'T' ) ) THEN
INFO = -2
ELSE IF( M.LT.0 ) THEN
INFO = -3
ELSE IF( N.LT.0 ) THEN
INFO = -4
ELSE IF( K.LT.0 .OR. K.GT.NQ ) THEN
INFO = -5
ELSE IF( LDA.LT.MAX( 1, NQ ) ) THEN
INFO = -7
ELSE IF( LDC.LT.MAX( 1, M ) ) THEN
INFO = -10
END IF
IF( INFO.NE.0 ) THEN
CALL XERBLA( 'DORM2L', -INFO )
RETURN
END IF
*
* QUICK RETURN IF POSSIBLE
*
IF( M.EQ.0 .OR. N.EQ.0 .OR. K.EQ.0 )
$ RETURN
*
IF( ( LEFT .AND. NOTRAN ) .OR. ( .NOT.LEFT .AND. .NOT.NOTRAN ) )
$ THEN
I1 = 1
I2 = K
I3 = 1
ELSE
I1 = K
I2 = 1
I3 = -1
END IF
*
IF( LEFT ) THEN
NI = N
ELSE
MI = M
END IF
*
DO 10 I = I1, I2, I3
IF( LEFT ) THEN
*
* H(I) IS APPLIED TO C(1:M-K+I,1:N)
*
MI = M - K + I
ELSE
*
* H(I) IS APPLIED TO C(1:M,1:N-K+I)
*
NI = N - K + I
END IF
*
* APPLY H(I)
*
AII = A( NQ-K+I, I )
A( NQ-K+I, I ) = ONE
CALL DLARF( SIDE, MI, NI, A( 1, I ), 1, TAU( I ), C, LDC,
$ WORK )
A( NQ-K+I, I ) = AII
10 CONTINUE
RETURN
*
* END OF DORM2L
*
END
CUT HERE............
CAT > DSTEIN.F <<'CUT HERE............'
SUBROUTINE DSTEIN( N, D, E, M, W, IBLOCK, ISPLIT, Z, LDZ, WORK,
$ IWORK, IFAIL, INFO )
*
* -- LAPACK ROUTINE (VERSION 1.1) --
* UNIV. OF TENNESSEE, UNIV. OF CALIFORNIA BERKELEY, NAG LTD.,
* COURANT INSTITUTE, ARGONNE NATIONAL LAB, AND RICE UNIVERSITY
* MARCH 31, 1993
*
* .. SCALAR ARGUMENTS ..
INTEGER INFO, LDZ, M, N
* ..
* .. ARRAY ARGUMENTS ..
INTEGER IBLOCK( * ), IFAIL( * ), ISPLIT( * ),
$ IWORK( * )
DOUBLE PRECISION D( * ), E( * ), W( * ), WORK( * ), Z( LDZ, * )
* ..
*
* PURPOSE
* =======
*
* DSTEIN COMPUTES THE EIGENVECTORS OF A REAL SYMMETRIC TRIDIAGONAL
* MATRIX T CORRESPONDING TO SPECIFIED EIGENVALUES, USING INVERSE
* ITERATION.
*
* THE MAXIMUM NUMBER OF ITERATIONS ALLOWED FOR EACH EIGENVECTOR IS
* SPECIFIED BY AN INTERNAL PARAMETER MAXITS (CURRENTLY SET TO 5).
*
* ARGUMENTS
* =========
*
* N (INPUT) INTEGER
* THE ORDER OF THE MATRIX. N >= 0.
*
* D (INPUT) DOUBLE PRECISION ARRAY, DIMENSION (N)
* THE N DIAGONAL ELEMENTS OF THE TRIDIAGONAL MATRIX T.
*
* E (INPUT) DOUBLE PRECISION ARRAY, DIMENSION (N)
* THE (N-1) SUBDIAGONAL ELEMENTS OF THE TRIDIAGONAL MATRIX
* T, IN ELEMENTS 1 TO N-1. E(N) NEED NOT BE SET.
*
* M (INPUT) INTEGER
* THE NUMBER OF EIGENVECTORS TO BE FOUND. 0 <= M <= N.
*
* W (INPUT) DOUBLE PRECISION ARRAY, DIMENSION (N)
* THE FIRST M ELEMENTS OF W CONTAIN THE EIGENVALUES FOR
* WHICH EIGENVECTORS ARE TO BE COMPUTED. THE EIGENVALUES
* SHOULD BE GROUPED BY SPLIT-OFF BLOCK AND ORDERED FROM
* SMALLEST TO LARGEST WITHIN THE BLOCK. ( THE OUTPUT ARRAY
* W FROM DSTEBZ WITH ORDER = 'B' IS EXPECTED HERE. )
*
* IBLOCK (INPUT) INTEGER ARRAY, DIMENSION (N)
* THE SUBMATRIX INDICES ASSOCIATED WITH THE CORRESPONDING
* EIGENVALUES IN W; IBLOCK(I)=1 IF EIGENVALUE W(I) BELONGS TO
* THE FIRST SUBMATRIX FROM THE TOP, =2 IF W(I) BELONGS TO
* THE SECOND SUBMATRIX, ETC. ( THE OUTPUT ARRAY IBLOCK
* FROM DSTEBZ IS EXPECTED HERE. )
*
* ISPLIT (INPUT) INTEGER ARRAY, DIMENSION (N)
* THE SPLITTING POINTS, AT WHICH T BREAKS UP INTO SUBMATRICES.
* THE FIRST SUBMATRIX CONSISTS OF ROWS/COLUMNS 1 TO
* ISPLIT( 1 ), THE SECOND OF ROWS/COLUMNS ISPLIT( 1 )+1
* THROUGH ISPLIT( 2 ), ETC.
* ( THE OUTPUT ARRAY ISPLIT FROM DSTEBZ IS EXPECTED HERE. )
*
* Z (OUTPUT) DOUBLE PRECISION ARRAY, DIMENSION (LDZ, M)
* THE COMPUTED EIGENVECTORS. THE EIGENVECTOR ASSOCIATED
* WITH THE EIGENVALUE W(I) IS STORED IN THE I-TH COLUMN OF
* Z. ANY VECTOR WHICH FAILS TO CONVERGE IS SET TO ITS CURRENT
* ITERATE AFTER MAXITS ITERATIONS.
*
* LDZ (INPUT) INTEGER
* THE LEADING DIMENSION OF THE ARRAY Z. LDZ >= MAX(1,N).
*
* WORK (WORKSPACE) DOUBLE PRECISION ARRAY, DIMENSION (5*N)
*
* IWORK (WORKSPACE) INTEGER ARRAY, DIMENSION (N)
*
* IFAIL (OUTPUT) INTEGER ARRAY, DIMENSION (M)
* ON NORMAL EXIT, ALL ELEMENTS OF IFAIL ARE ZERO.
* IF ONE OR MORE EIGENVECTORS FAIL TO CONVERGE AFTER
* MAXITS ITERATIONS, THEN THEIR INDICES ARE STORED IN
* ARRAY IFAIL.
*
* INFO (OUTPUT) INTEGER
* = 0: SUCCESSFUL EXIT.
* < 0: IF INFO = -I, THE I-TH ARGUMENT HAD AN ILLEGAL VALUE
* > 0: IF INFO = I, THEN I EIGENVECTORS FAILED TO CONVERGE
* IN MAXITS ITERATIONS. THEIR INDICES ARE STORED IN
* ARRAY IFAIL.
*
* INTERNAL PARAMETERS
* ===================
*
* MAXITS INTEGER, DEFAULT = 5
* THE MAXIMUM NUMBER OF ITERATIONS PERFORMED.
*
* EXTRA INTEGER, DEFAULT = 2
* THE NUMBER OF ITERATIONS PERFORMED AFTER NORM GROWTH
* CRITERION IS SATISFIED, SHOULD BE AT LEAST 1.
*
* =====================================================================
*
* .. PARAMETERS ..
DOUBLE PRECISION ZERO, ONE, TEN, ODM3, ODM1
PARAMETER ( ZERO = 0.0D0, ONE = 1.0D0, TEN = 1.0D1,
$ ODM3 = 1.0D-3, ODM1 = 1.0D-1 )
INTEGER MAXITS, EXTRA
PARAMETER ( MAXITS = 5, EXTRA = 2 )
* ..
* .. LOCAL SCALARS ..
INTEGER B1, BLKSIZ, BN, GPIND, I, IINFO, INDRV1,
$ INDRV2, INDRV3, INDRV4, INDRV5, ITS, J, J1,
$ JBLK, JMAX, NBLK, NRMCHK
DOUBLE PRECISION DTPCRT, EPS, EPS1, NRM, ONENRM, ORTOL, PERTOL,
$ SCL, SEP, TOL, XJ, XJM, ZTR
* ..
* .. LOCAL ARRAYS ..
INTEGER ISEED( 4 )
* ..
* .. EXTERNAL FUNCTIONS ..
INTEGER IDAMAX
DOUBLE PRECISION DASUM, DDOT, DLAMCH, DNRM2
EXTERNAL IDAMAX, DASUM, DDOT, DLAMCH, DNRM2
* ..
* .. EXTERNAL SUBROUTINES ..
EXTERNAL DAXPY, DCOPY, DLAGTF, DLAGTS, DLARNV, DSCAL,
$ XERBLA
* ..
* .. INTRINSIC FUNCTIONS ..
INTRINSIC ABS, MAX, SQRT
* ..
* .. EXECUTABLE STATEMENTS ..
*
* TEST THE INPUT PARAMETERS.
*
INFO = 0
DO 10 I = 1, M
IFAIL( I ) = 0
10 CONTINUE
*
IF( N.LT.0 ) THEN
INFO = -1
ELSE IF( M.LT.0 .OR. M.GT.N ) THEN
INFO = -4
ELSE IF( LDZ.LT.MAX( 1, N ) ) THEN
INFO = -9
ELSE
DO 20 J = 2, M
IF( IBLOCK( J ).LT.IBLOCK( J-1 ) ) THEN
INFO = -6
GO TO 30
END IF
IF( IBLOCK( J ).EQ.IBLOCK( J-1 ) .AND. W( J ).LT.W( J-1 ) )
$ THEN
INFO = -5
GO TO 30
END IF
20 CONTINUE
30 CONTINUE
END IF
*
IF( INFO.NE.0 ) THEN
CALL XERBLA( 'DSTEIN', -INFO )
RETURN
END IF
*
* QUICK RETURN IF POSSIBLE
*
IF( N.EQ.0 .OR. M.EQ.0 ) THEN
RETURN
ELSE IF( N.EQ.1 ) THEN
Z( 1, 1 ) = ONE
RETURN
END IF
*
* GET MACHINE CONSTANTS.
*
EPS = DLAMCH( 'PRECISION' )
*
* INITIALIZE SEED FOR RANDOM NUMBER GENERATOR DLARNV.
*
DO 40 I = 1, 4
ISEED( I ) = 1
40 CONTINUE
*
* INITIALIZE POINTERS.
*
INDRV1 = 0
INDRV2 = INDRV1 + N
INDRV3 = INDRV2 + N
INDRV4 = INDRV3 + N
INDRV5 = INDRV4 + N
*
* COMPUTE EIGENVECTORS OF MATRIX BLOCKS.
*
GPIND = 1
J1 = 1
DO 160 NBLK = 1, IBLOCK( M )
*
* FIND STARTING AND ENDING INDICES OF BLOCK NBLK.
*
IF( NBLK.EQ.1 ) THEN
B1 = 1
ELSE
B1 = ISPLIT( NBLK-1 ) + 1
END IF
BN = ISPLIT( NBLK )
BLKSIZ = BN - B1 + 1
IF( BLKSIZ.EQ.1 )
$ GO TO 60
*
* COMPUTE REORTHOGONALIZATION CRITERION AND STOPPING CRITERION.
*
ONENRM = ABS( D( B1 ) ) + ABS( E( B1 ) )
ONENRM = MAX( ONENRM, ABS( D( BN ) )+ABS( E( BN-1 ) ) )
DO 50 I = B1 + 1, BN - 1
ONENRM = MAX( ONENRM, ABS( D( I ) )+ABS( E( I-1 ) )+
$ ABS( E( I ) ) )
50 CONTINUE
ORTOL = ODM3*ONENRM
*
DTPCRT = SQRT( ODM1 / BLKSIZ )
*
* LOOP THROUGH EIGENVALUES OF BLOCK NBLK.
*
60 CONTINUE
JBLK = 0
DO 150 J = J1, M
IF( IBLOCK( J ).NE.NBLK ) THEN
J1 = J
GO TO 160
END IF
JBLK = JBLK + 1
XJ = W( J )
*
* SKIP ALL THE WORK IF THE BLOCK SIZE IS ONE.
*
IF( BLKSIZ.EQ.1 ) THEN
WORK( INDRV1+1 ) = ONE
GO TO 120
END IF
*
* IF EIGENVALUES J AND J-1 ARE TOO CLOSE, ADD A RELATIVELY
* SMALL PERTURBATION.
*
IF( JBLK.GT.1 ) THEN
EPS1 = ABS( EPS*XJ )
PERTOL = TEN*EPS1
SEP = XJ - XJM
IF( SEP.LT.PERTOL )
$ XJ = XJM + PERTOL
END IF
*
ITS = 0
NRMCHK = 0
*
* GET RANDOM STARTING VECTOR.
*
CALL DLARNV( 3, ISEED, BLKSIZ, WORK( INDRV1+1 ) )
*
* COPY THE MATRIX T SO IT WON'T BE DESTROYED IN FACTORIZATION.
*
CALL DCOPY( BLKSIZ, D( B1 ), 1, WORK( INDRV4+1 ), 1 )
CALL DCOPY( BLKSIZ-1, E( B1 ), 1, WORK( INDRV2+2 ), 1 )
CALL DCOPY( BLKSIZ-1, E( B1 ), 1, WORK( INDRV3+1 ), 1 )
*
* COMPUTE LU FACTORS WITH PARTIAL PIVOTING ( PT = LU )
*
TOL = ZERO
CALL DLAGTF( BLKSIZ, WORK( INDRV4+1 ), XJ, WORK( INDRV2+2 ),
$ WORK( INDRV3+1 ), TOL, WORK( INDRV5+1 ), IWORK,
$ IINFO )
*
* UPDATE ITERATION COUNT.
*
70 CONTINUE
ITS = ITS + 1
IF( ITS.GT.MAXITS )
$ GO TO 100
*
* NORMALIZE AND SCALE THE RIGHTHAND SIDE VECTOR PB.
*
SCL = BLKSIZ*ONENRM*MAX( EPS,
$ ABS( WORK( INDRV4+BLKSIZ ) ) ) /
$ DASUM( BLKSIZ, WORK( INDRV1+1 ), 1 )
CALL DSCAL( BLKSIZ, SCL, WORK( INDRV1+1 ), 1 )
*
* SOLVE THE SYSTEM LU = PB.
*
CALL DLAGTS( -1, BLKSIZ, WORK( INDRV4+1 ), WORK( INDRV2+2 ),
$ WORK( INDRV3+1 ), WORK( INDRV5+1 ), IWORK,
$ WORK( INDRV1+1 ), TOL, IINFO )
*
* REORTHOGONALIZE BY MODIFIED GRAM-SCHMIDT IF EIGENVALUES ARE
* CLOSE ENOUGH.
*
IF( JBLK.EQ.1 )
$ GO TO 90
IF( ABS( XJ-XJM ).GT.ORTOL )
$ GPIND = J
IF( GPIND.NE.J ) THEN
DO 80 I = GPIND, J - 1
ZTR = -DDOT( BLKSIZ, WORK( INDRV1+1 ), 1, Z( B1, I ),
$ 1 )
CALL DAXPY( BLKSIZ, ZTR, Z( B1, I ), 1,
$ WORK( INDRV1+1 ), 1 )
80 CONTINUE
END IF
*
* CHECK THE INFINITY NORM OF THE ITERATE.
*
90 CONTINUE
JMAX = IDAMAX( BLKSIZ, WORK( INDRV1+1 ), 1 )
NRM = ABS( WORK( INDRV1+JMAX ) )
*
* CONTINUE FOR ADDITIONAL ITERATIONS AFTER NORM REACHES
* STOPPING CRITERION.
*
IF( NRM.LT.DTPCRT )
$ GO TO 70
NRMCHK = NRMCHK + 1
IF( NRMCHK.LT.EXTRA+1 )
$ GO TO 70
*
GO TO 110
*
* IF STOPPING CRITERION WAS NOT SATISFIED, UPDATE INFO AND
* STORE EIGENVECTOR NUMBER IN ARRAY IFAIL.
*
100 CONTINUE
INFO = INFO + 1
IFAIL( INFO ) = J
*
* ACCEPT ITERATE AS JTH EIGENVECTOR.
*
110 CONTINUE
SCL = ONE / DNRM2( BLKSIZ, WORK( INDRV1+1 ), 1 )
JMAX = IDAMAX( BLKSIZ, WORK( INDRV1+1 ), 1 )
IF( WORK( INDRV1+JMAX ).LT.ZERO )
$ SCL = -SCL
CALL DSCAL( BLKSIZ, SCL, WORK( INDRV1+1 ), 1 )
120 CONTINUE
DO 130 I = 1, N
Z( I, J ) = ZERO
130 CONTINUE
DO 140 I = 1, BLKSIZ
Z( B1+I-1, J ) = WORK( INDRV1+I )
140 CONTINUE
*
* SAVE THE SHIFT TO CHECK EIGENVALUE SPACING AT NEXT
* ITERATION.
*
XJM = XJ
*
150 CONTINUE
160 CONTINUE
*
RETURN
*
* END OF DSTEIN
*
END
CUT HERE............
CAT > DLAGTS.F <<'CUT HERE............'
SUBROUTINE DLAGTS( JOB, N, A, B, C, D, IN, Y, TOL, INFO )
*
* -- LAPACK AUXILIARY ROUTINE (VERSION 1.1) --
* UNIV. OF TENNESSEE, UNIV. OF CALIFORNIA BERKELEY, NAG LTD.,
* COURANT INSTITUTE, ARGONNE NATIONAL LAB, AND RICE UNIVERSITY
* OCTOBER 31, 1992
*
* .. SCALAR ARGUMENTS ..
INTEGER INFO, JOB, N
DOUBLE PRECISION TOL
* ..
* .. ARRAY ARGUMENTS ..
INTEGER IN( * )
DOUBLE PRECISION A( * ), B( * ), C( * ), D( * ), Y( * )
* ..
*
* PURPOSE
* =======
*
* DLAGTS MAY BE USED TO SOLVE ONE OF THE SYSTEMS OF EQUATIONS
*
* (T - LAMBDA*I)*X = Y OR (T - LAMBDA*I)'*X = Y,
*
* WHERE T IS AN N BY N TRIDIAGONAL MATRIX, FOR X, FOLLOWING THE
* FACTORIZATION OF (T - LAMBDA*I) AS
*
* (T - LAMBDA*I) = P*L*U ,
*
* BY ROUTINE DLAGTF. THE CHOICE OF EQUATION TO BE SOLVED IS
* CONTROLLED BY THE ARGUMENT JOB, AND IN EACH CASE THERE IS AN OPTION
* TO PERTURB ZERO OR VERY SMALL DIAGONAL ELEMENTS OF U, THIS OPTION
* BEING INTENDED FOR USE IN APPLICATIONS SUCH AS INVERSE ITERATION.
*
* ARGUMENTS
* =========
*
* JOB (INPUT) INTEGER
* SPECIFIES THE JOB TO BE PERFORMED BY DLAGTS AS FOLLOWS:
* = 1: THE EQUATIONS (T - LAMBDA*I)X = Y ARE TO BE SOLVED,
* BUT DIAGONAL ELEMENTS OF U ARE NOT TO BE PERTURBED.
* = -1: THE EQUATIONS (T - LAMBDA*I)X = Y ARE TO BE SOLVED
* AND, IF OVERFLOW WOULD OTHERWISE OCCUR, THE DIAGONAL
* ELEMENTS OF U ARE TO BE PERTURBED. SEE ARGUMENT TOL
* BELOW.
* = 2: THE EQUATIONS (T - LAMBDA*I)'X = Y ARE TO BE SOLVED,
* BUT DIAGONAL ELEMENTS OF U ARE NOT TO BE PERTURBED.
* = -2: THE EQUATIONS (T - LAMBDA*I)'X = Y ARE TO BE SOLVED
* AND, IF OVERFLOW WOULD OTHERWISE OCCUR, THE DIAGONAL
* ELEMENTS OF U ARE TO BE PERTURBED. SEE ARGUMENT TOL
* BELOW.
*
* N (INPUT) INTEGER
* THE ORDER OF THE MATRIX T.
*
* A (INPUT) DOUBLE PRECISION ARRAY, DIMENSION (N)
* ON ENTRY, A MUST CONTAIN THE DIAGONAL ELEMENTS OF U AS
* RETURNED FROM DLAGTF.
*
* B (INPUT) DOUBLE PRECISION ARRAY, DIMENSION (N-1)
* ON ENTRY, B MUST CONTAIN THE FIRST SUPER-DIAGONAL ELEMENTS OF
* U AS RETURNED FROM DLAGTF.
*
* C (INPUT) DOUBLE PRECISION ARRAY, DIMENSION (N-1)
* ON ENTRY, C MUST CONTAIN THE SUB-DIAGONAL ELEMENTS OF L AS
* RETURNED FROM DLAGTF.
*
* D (INPUT) DOUBLE PRECISION ARRAY, DIMENSION (N-2)
* ON ENTRY, D MUST CONTAIN THE SECOND SUPER-DIAGONAL ELEMENTS
* OF U AS RETURNED FROM DLAGTF.
*
* IN (INPUT) INTEGER ARRAY, DIMENSION (N)
* ON ENTRY, IN MUST CONTAIN DETAILS OF THE MATRIX P AS RETURNED
* FROM DLAGTF.
*
* Y (INPUT/OUTPUT) DOUBLE PRECISION ARRAY, DIMENSION (N)
* ON ENTRY, THE RIGHT HAND SIDE VECTOR Y.
*
* ON EXIT, Y IS OVERWRITTEN BY THE SOLUTION VECTOR X.
*
* TOL (INPUT/OUTPUT) DOUBLE PRECISION
* ON ENTRY WITH JOB .LT. 0, TOL SHOULD BE THE MINIMUM
* PERTURBATION TO BE MADE TO VERY SMALL DIAGONAL ELEMENTS OF U.
* TOL SHOULD NORMALLY BE CHOSEN AS ABOUT EPS*NORM(U), WHERE EPS
* IS THE RELATIVE MACHINE PRECISION, BUT IF TOL IS SUPPLIED AS
* NON-POSITIVE, THEN IT IS RESET TO EPS*MAX( ABS( U(I,J) ) ).
* IF JOB .GT. 0 THEN TOL IS NOT REFERENCED.
*
* ON EXIT, TOL IS CHANGED AS DESCRIBED ABOVE, ONLY IF TOL IS
* NON-POSITIVE ON ENTRY. OTHERWISE TOL IS UNCHANGED.
*
* INFO (OUTPUT)
* = 0 : SUCCESSFUL EXIT
* .LT. 0: IF INFO = -K, THE KTH ARGUMENT HAD AN ILLEGAL VALUE
* .GT. 0: OVERFLOW WOULD OCCUR WHEN COMPUTING THE INFO(TH)
* ELEMENT OF THE SOLUTION VECTOR X. THIS CAN ONLY OCCUR
* WHEN JOB IS SUPPLIED AS POSITIVE AND EITHER MEANS
* THAT A DIAGONAL ELEMENT OF U IS VERY SMALL, OR THAT
* THE ELEMENTS OF THE RIGHT-HAND SIDE VECTOR Y ARE VERY
* LARGE.
*
* =====================================================================
*
* .. PARAMETERS ..
DOUBLE PRECISION ONE, ZERO
PARAMETER ( ONE = 1.0D+0, ZERO = 0.0D+0 )
* ..
* .. LOCAL SCALARS ..
INTEGER K
DOUBLE PRECISION ABSAK, AK, BIGNUM, EPS, PERT, SFMIN, TEMP
* ..
* .. INTRINSIC FUNCTIONS ..
INTRINSIC ABS, MAX, SIGN
* ..
* .. EXTERNAL FUNCTIONS ..
DOUBLE PRECISION DLAMCH
EXTERNAL DLAMCH
* ..
* .. EXTERNAL SUBROUTINES ..
EXTERNAL XERBLA
* ..
* .. EXECUTABLE STATEMENTS ..
*
INFO = 0
IF( ( ABS( JOB ).GT.2 ) .OR. ( JOB.EQ.0 ) ) THEN
INFO = -1
ELSE IF( N.LT.0 ) THEN
INFO = -2
END IF
IF( INFO.NE.0 ) THEN
CALL XERBLA( 'DLAGTS', -INFO )
RETURN
END IF
*
IF( N.EQ.0 )
$ RETURN
*
EPS = DLAMCH( 'EPSILON' )
SFMIN = DLAMCH( 'SAFE MINIMUM' )
BIGNUM = ONE / SFMIN
*
IF( JOB.LT.0 ) THEN
IF( TOL.LE.ZERO ) THEN
TOL = ABS( A( 1 ) )
IF( N.GT.1 )
$ TOL = MAX( TOL, ABS( A( 2 ) ), ABS( B( 1 ) ) )
DO 10 K = 3, N
TOL = MAX( TOL, ABS( A( K ) ), ABS( B( K-1 ) ),
$ ABS( D( K-2 ) ) )
10 CONTINUE
TOL = TOL*EPS
IF( TOL.EQ.ZERO )
$ TOL = EPS
END IF
END IF
*
IF( ABS( JOB ).EQ.1 ) THEN
DO 20 K = 2, N
IF( IN( K-1 ).EQ.0 ) THEN
Y( K ) = Y( K ) - C( K-1 )*Y( K-1 )
ELSE
TEMP = Y( K-1 )
Y( K-1 ) = Y( K )
Y( K ) = TEMP - C( K-1 )*Y( K )
END IF
20 CONTINUE
IF( JOB.EQ.1 ) THEN
DO 30 K = N, 1, -1
IF( K.LE.N-2 ) THEN
TEMP = Y( K ) - B( K )*Y( K+1 ) - D( K )*Y( K+2 )
ELSE IF( K.EQ.N-1 ) THEN
TEMP = Y( K ) - B( K )*Y( K+1 )
ELSE
TEMP = Y( K )
END IF
AK = A( K )
ABSAK = ABS( AK )
IF( ABSAK.LT.ONE ) THEN
IF( ABSAK.LT.SFMIN ) THEN
IF( ABSAK.EQ.ZERO .OR. ABS( TEMP )*SFMIN.GT.ABSAK )
$ THEN
INFO = K
RETURN
ELSE
TEMP = TEMP*BIGNUM
AK = AK*BIGNUM
END IF
ELSE IF( ABS( TEMP ).GT.ABSAK*BIGNUM ) THEN
INFO = K
RETURN
END IF
END IF
Y( K ) = TEMP / AK
30 CONTINUE
ELSE
DO 50 K = N, 1, -1
IF( K.LE.N-2 ) THEN
TEMP = Y( K ) - B( K )*Y( K+1 ) - D( K )*Y( K+2 )
ELSE IF( K.EQ.N-1 ) THEN
TEMP = Y( K ) - B( K )*Y( K+1 )
ELSE
TEMP = Y( K )
END IF
AK = A( K )
PERT = SIGN( TOL, AK )
40 CONTINUE
ABSAK = ABS( AK )
IF( ABSAK.LT.ONE ) THEN
IF( ABSAK.LT.SFMIN ) THEN
IF( ABSAK.EQ.ZERO .OR. ABS( TEMP )*SFMIN.GT.ABSAK )
$ THEN
AK = AK + PERT
PERT = 2*PERT
GO TO 40
ELSE
TEMP = TEMP*BIGNUM
AK = AK*BIGNUM
END IF
ELSE IF( ABS( TEMP ).GT.ABSAK*BIGNUM ) THEN
AK = AK + PERT
PERT = 2*PERT
GO TO 40
END IF
END IF
Y( K ) = TEMP / AK
50 CONTINUE
END IF
ELSE
*
* COME TO HERE IF JOB = 2 OR -2
*
IF( JOB.EQ.2 ) THEN
DO 60 K = 1, N
IF( K.GE.3 ) THEN
TEMP = Y( K ) - B( K-1 )*Y( K-1 ) - D( K-2 )*Y( K-2 )
ELSE IF( K.EQ.2 ) THEN
TEMP = Y( K ) - B( K-1 )*Y( K-1 )
ELSE
TEMP = Y( K )
END IF
AK = A( K )
ABSAK = ABS( AK )
IF( ABSAK.LT.ONE ) THEN
IF( ABSAK.LT.SFMIN ) THEN
IF( ABSAK.EQ.ZERO .OR. ABS( TEMP )*SFMIN.GT.ABSAK )
$ THEN
INFO = K
RETURN
ELSE
TEMP = TEMP*BIGNUM
AK = AK*BIGNUM
END IF
ELSE IF( ABS( TEMP ).GT.ABSAK*BIGNUM ) THEN
INFO = K
RETURN
END IF
END IF
Y( K ) = TEMP / AK
60 CONTINUE
ELSE
DO 80 K = 1, N
IF( K.GE.3 ) THEN
TEMP = Y( K ) - B( K-1 )*Y( K-1 ) - D( K-2 )*Y( K-2 )
ELSE IF( K.EQ.2 ) THEN
TEMP = Y( K ) - B( K-1 )*Y( K-1 )
ELSE
TEMP = Y( K )
END IF
AK = A( K )
PERT = SIGN( TOL, AK )
70 CONTINUE
ABSAK = ABS( AK )
IF( ABSAK.LT.ONE ) THEN
IF( ABSAK.LT.SFMIN ) THEN
IF( ABSAK.EQ.ZERO .OR. ABS( TEMP )*SFMIN.GT.ABSAK )
$ THEN
AK = AK + PERT
PERT = 2*PERT
GO TO 70
ELSE
TEMP = TEMP*BIGNUM
AK = AK*BIGNUM
END IF
ELSE IF( ABS( TEMP ).GT.ABSAK*BIGNUM ) THEN
AK = AK + PERT
PERT = 2*PERT
GO TO 70
END IF
END IF
Y( K ) = TEMP / AK
80 CONTINUE
END IF
*
DO 90 K = N, 2, -1
IF( IN( K-1 ).EQ.0 ) THEN
Y( K-1 ) = Y( K-1 ) - C( K-1 )*Y( K )
ELSE
TEMP = Y( K-1 )
Y( K-1 ) = Y( K )
Y( K ) = TEMP - C( K-1 )*Y( K )
END IF
90 CONTINUE
END IF
*
* END OF DLAGTS
*
END
CUT HERE............
CAT > DLAGTF.F <<'CUT HERE............'
SUBROUTINE DLAGTF( N, A, LAMBDA, B, C, TOL, D, IN, INFO )
*
* -- LAPACK ROUTINE (VERSION 1.1) --
* UNIV. OF TENNESSEE, UNIV. OF CALIFORNIA BERKELEY, NAG LTD.,
* COURANT INSTITUTE, ARGONNE NATIONAL LAB, AND RICE UNIVERSITY
* OCTOBER 31, 1992
*
* .. SCALAR ARGUMENTS ..
INTEGER INFO, N
DOUBLE PRECISION LAMBDA, TOL
* ..
* .. ARRAY ARGUMENTS ..
INTEGER IN( * )
DOUBLE PRECISION A( * ), B( * ), C( * ), D( * )
* ..
*
* PURPOSE
* =======
*
* DLAGTF FACTORIZES THE MATRIX (T - LAMBDA*I), WHERE T IS AN N BY N
* TRIDIAGONAL MATRIX AND LAMBDA IS A SCALAR, AS
*
* T - LAMBDA*I = PLU,
*
* WHERE P IS A PERMUTATION MATRIX, L IS A UNIT LOWER TRIDIAGONAL MATRIX
* WITH AT MOST ONE NON-ZERO SUB-DIAGONAL ELEMENTS PER COLUMN AND U IS
* AN UPPER TRIANGULAR MATRIX WITH AT MOST TWO NON-ZERO SUPER-DIAGONAL
* ELEMENTS PER COLUMN.
*
* THE FACTORIZATION IS OBTAINED BY GAUSSIAN ELIMINATION WITH PARTIAL
* PIVOTING AND IMPLICIT ROW SCALING.
*
* THE PARAMETER LAMBDA IS INCLUDED IN THE ROUTINE SO THAT DLAGTF MAY
* BE USED, IN CONJUNCTION WITH DLAGTS, TO OBTAIN EIGENVECTORS OF T BY
* INVERSE ITERATION.
*
* ARGUMENTS
* =========
*
* N (INPUT) INTEGER
* THE ORDER OF THE MATRIX T.
*
* A (INPUT/OUTPUT) DOUBLE PRECISION ARRAY, DIMENSION (N)
* ON ENTRY, A MUST CONTAIN THE DIAGONAL ELEMENTS OF T.
*
* ON EXIT, A IS OVERWRITTEN BY THE N DIAGONAL ELEMENTS OF THE
* UPPER TRIANGULAR MATRIX U OF THE FACTORIZATION OF T.
*
* LAMBDA (INPUT) DOUBLE PRECISION
* ON ENTRY, THE SCALAR LAMBDA.
*
* B (INPUT/OUTPUT) DOUBLE PRECISION ARRAY, DIMENSION (N-1)
* ON ENTRY, B MUST CONTAIN THE (N-1) SUPER-DIAGONAL ELEMENTS OF
* T.
*
* ON EXIT, B IS OVERWRITTEN BY THE (N-1) SUPER-DIAGONAL
* ELEMENTS OF THE MATRIX U OF THE FACTORIZATION OF T.
*
* C (INPUT/OUTPUT) DOUBLE PRECISION ARRAY, DIMENSION (N-1)
* ON ENTRY, C MUST CONTAIN THE (N-1) SUB-DIAGONAL ELEMENTS OF
* T.
*
* ON EXIT, C IS OVERWRITTEN BY THE (N-1) SUB-DIAGONAL ELEMENTS
* OF THE MATRIX L OF THE FACTORIZATION OF T.
*
* TOL (INPUT) DOUBLE PRECISION
* ON ENTRY, A RELATIVE TOLERANCE USED TO INDICATE WHETHER OR
* NOT THE MATRIX (T - LAMBDA*I) IS NEARLY SINGULAR. TOL SHOULD
* NORMALLY BE CHOSE AS APPROXIMATELY THE LARGEST RELATIVE ERROR
* IN THE ELEMENTS OF T. FOR EXAMPLE, IF THE ELEMENTS OF T ARE
* CORRECT TO ABOUT 4 SIGNIFICANT FIGURES, THEN TOL SHOULD BE
* SET TO ABOUT 5*10**(-4). IF TOL IS SUPPLIED AS LESS THAN EPS,
* WHERE EPS IS THE RELATIVE MACHINE PRECISION, THEN THE VALUE
* EPS IS USED IN PLACE OF TOL.
*
* D (OUTPUT) DOUBLE PRECISION ARRAY, DIMENSION (N-2)
* ON EXIT, D IS OVERWRITTEN BY THE (N-2) SECOND SUPER-DIAGONAL
* ELEMENTS OF THE MATRIX U OF THE FACTORIZATION OF T.
*
* IN (OUTPUT) INTEGER ARRAY, DIMENSION (N)
* ON EXIT, IN CONTAINS DETAILS OF THE PERMUTATION MATRIX P. IF
* AN INTERCHANGE OCCURRED AT THE KTH STEP OF THE ELIMINATION,
* THEN IN(K) = 1, OTHERWISE IN(K) = 0. THE ELEMENT IN(N)
* RETURNS THE SMALLEST POSITIVE INTEGER J SUCH THAT
*
* ABS( U(J,J) ).LE. NORM( (T - LAMBDA*I)(J) )*TOL,
*
* WHERE NORM( A(J) ) DENOTES THE SUM OF THE ABSOLUTE VALUES OF
* THE JTH ROW OF THE MATRIX A. IF NO SUCH J EXISTS THEN IN(N)
* IS RETURNED AS ZERO. IF IN(N) IS RETURNED AS POSITIVE, THEN A
* DIAGONAL ELEMENT OF U IS SMALL, INDICATING THAT
* (T - LAMBDA*I) IS SINGULAR OR NEARLY SINGULAR,
*
* INFO (OUTPUT)
* = 0 : SUCCESSFUL EXIT
* .LT. 0: IF INFO = -K, THE KTH ARGUMENT HAD AN ILLEGAL VALUE
*
* =====================================================================
*
* .. PARAMETERS ..
DOUBLE PRECISION ZERO
PARAMETER ( ZERO = 0.0D+0 )
* ..
* .. LOCAL SCALARS ..
INTEGER K
DOUBLE PRECISION EPS, MULT, PIV1, PIV2, SCALE1, SCALE2, TEMP, TL
* ..
* .. INTRINSIC FUNCTIONS ..
INTRINSIC ABS, MAX
* ..
* .. EXTERNAL FUNCTIONS ..
DOUBLE PRECISION DLAMCH
EXTERNAL DLAMCH
* ..
* .. EXTERNAL SUBROUTINES ..
EXTERNAL XERBLA
* ..
* .. EXECUTABLE STATEMENTS ..
*
INFO = 0
IF( N.LT.0 ) THEN
INFO = -1
CALL XERBLA( 'DLAGTF', -INFO )
RETURN
END IF
*
IF( N.EQ.0 )
$ RETURN
*
A( 1 ) = A( 1 ) - LAMBDA
IN( N ) = 0
IF( N.EQ.1 ) THEN
IF( A( 1 ).EQ.ZERO )
$ IN( 1 ) = 1
RETURN
END IF
*
EPS = DLAMCH( 'EPSILON' )
*
TL = MAX( TOL, EPS )
SCALE1 = ABS( A( 1 ) ) + ABS( B( 1 ) )
DO 10 K = 1, N - 1
A( K+1 ) = A( K+1 ) - LAMBDA
SCALE2 = ABS( C( K ) ) + ABS( A( K+1 ) )
IF( K.LT.( N-1 ) )
$ SCALE2 = SCALE2 + ABS( B( K+1 ) )
IF( A( K ).EQ.ZERO ) THEN
PIV1 = ZERO
ELSE
PIV1 = ABS( A( K ) ) / SCALE1
END IF
IF( C( K ).EQ.ZERO ) THEN
IN( K ) = 0
PIV2 = ZERO
SCALE1 = SCALE2
IF( K.LT.( N-1 ) )
$ D( K ) = ZERO
ELSE
PIV2 = ABS( C( K ) ) / SCALE2
IF( PIV2.LE.PIV1 ) THEN
IN( K ) = 0
SCALE1 = SCALE2
C( K ) = C( K ) / A( K )
A( K+1 ) = A( K+1 ) - C( K )*B( K )
IF( K.LT.( N-1 ) )
$ D( K ) = ZERO
ELSE
IN( K ) = 1
MULT = A( K ) / C( K )
A( K ) = C( K )
TEMP = A( K+1 )
A( K+1 ) = B( K ) - MULT*TEMP
IF( K.LT.( N-1 ) ) THEN
D( K ) = B( K+1 )
B( K+1 ) = -MULT*D( K )
END IF
B( K ) = TEMP
C( K ) = MULT
END IF
END IF
IF( ( MAX( PIV1, PIV2 ).LE.TL ) .AND. ( IN( N ).EQ.0 ) )
$ IN( N ) = K
10 CONTINUE
IF( ( ABS( A( N ) ).LE.SCALE1*TL ) .AND. ( IN( N ).EQ.0 ) )
$ IN( N ) = N
*
RETURN
*
* END OF DLAGTF
*
END
CUT HERE............
CAT > DLARNV.F <<'CUT HERE............'
SUBROUTINE DLARNV( IDIST, ISEED, N, X )
*
* -- LAPACK AUXILIARY ROUTINE (VERSION 1.1) --
* UNIV. OF TENNESSEE, UNIV. OF CALIFORNIA BERKELEY, NAG LTD.,
* COURANT INSTITUTE, ARGONNE NATIONAL LAB, AND RICE UNIVERSITY
* OCTOBER 31, 1992
*
* .. SCALAR ARGUMENTS ..
INTEGER IDIST, N
* ..
* .. ARRAY ARGUMENTS ..
INTEGER ISEED( 4 )
DOUBLE PRECISION X( * )
* ..
*
* PURPOSE
* =======
*
* DLARNV RETURNS A VECTOR OF N RANDOM REAL NUMBERS FROM A UNIFORM OR
* NORMAL DISTRIBUTION.
*
* ARGUMENTS
* =========
*
* IDIST (INPUT) INTEGER
* SPECIFIES THE DISTRIBUTION OF THE RANDOM NUMBERS:
* = 1: UNIFORM (0,1)
* = 2: UNIFORM (-1,1)
* = 3: NORMAL (0,1)
*
* ISEED (INPUT/OUTPUT) INTEGER ARRAY, DIMENSION (4)
* ON ENTRY, THE SEED OF THE RANDOM NUMBER GENERATOR; THE ARRAY
* ELEMENTS MUST BE BETWEEN 0 AND 4095, AND ISEED(4) MUST BE
* ODD.
* ON EXIT, THE SEED IS UPDATED.
*
* N (INPUT) INTEGER
* THE NUMBER OF RANDOM NUMBERS TO BE GENERATED.
*
* X (OUTPUT) DOUBLE PRECISION ARRAY, DIMENSION (N)
* THE GENERATED RANDOM NUMBERS.
*
* FURTHER DETAILS
* ===============
*
* THIS ROUTINE CALLS THE AUXILIARY ROUTINE DLARUV TO GENERATE RANDOM
* REAL NUMBERS FROM A UNIFORM (0,1) DISTRIBUTION, IN BATCHES OF UP TO
* 128 USING VECTORISABLE CODE. THE BOX-MULLER METHOD IS USED TO
* TRANSFORM NUMBERS FROM A UNIFORM TO A NORMAL DISTRIBUTION.
*
* =====================================================================
*
* .. PARAMETERS ..
DOUBLE PRECISION ONE, TWO
PARAMETER ( ONE = 1.0D+0, TWO = 2.0D+0 )
INTEGER LV
PARAMETER ( LV = 128 )
DOUBLE PRECISION TWOPI
PARAMETER ( TWOPI = 6.28318530717958623199592D+0 )
* ..
* .. LOCAL SCALARS ..
INTEGER I, IL, IL2, IV
* ..
* .. LOCAL ARRAYS ..
DOUBLE PRECISION U( LV )
* ..
* .. INTRINSIC FUNCTIONS ..
INTRINSIC COS, LOG, MIN, SQRT
* ..
* .. EXTERNAL SUBROUTINES ..
EXTERNAL DLARUV
* ..
* .. EXECUTABLE STATEMENTS ..
*
DO 40 IV = 1, N, LV / 2
IL = MIN( LV / 2, N-IV+1 )
IF( IDIST.EQ.3 ) THEN
IL2 = 2*IL
ELSE
IL2 = IL
END IF
*
* CALL DLARUV TO GENERATE IL2 NUMBERS FROM A UNIFORM (0,1)
* DISTRIBUTION (IL2 <= LV)
*
CALL DLARUV( ISEED, IL2, U )
*
IF( IDIST.EQ.1 ) THEN
*
* COPY GENERATED NUMBERS
*
DO 10 I = 1, IL
X( IV+I-1 ) = U( I )
10 CONTINUE
ELSE IF( IDIST.EQ.2 ) THEN
*
* CONVERT GENERATED NUMBERS TO UNIFORM (-1,1) DISTRIBUTION
*
DO 20 I = 1, IL
X( IV+I-1 ) = TWO*U( I ) - ONE
20 CONTINUE
ELSE IF( IDIST.EQ.3 ) THEN
*
* CONVERT GENERATED NUMBERS TO NORMAL (0,1) DISTRIBUTION
*
DO 30 I = 1, IL
X( IV+I-1 ) = SQRT( -TWO*LOG( U( 2*I-1 ) ) )*
$ COS( TWOPI*U( 2*I ) )
30 CONTINUE
END IF
40 CONTINUE
RETURN
*
* END OF DLARNV
*
END
CUT HERE............
CAT > DLARUV.F <<'CUT HERE............'
SUBROUTINE DLARUV( ISEED, N, X )
*
* -- LAPACK AUXILIARY ROUTINE (VERSION 1.1) --
* UNIV. OF TENNESSEE, UNIV. OF CALIFORNIA BERKELEY, NAG LTD.,
* COURANT INSTITUTE, ARGONNE NATIONAL LAB, AND RICE UNIVERSITY
* OCTOBER 31, 1992
*
* .. SCALAR ARGUMENTS ..
INTEGER N
* ..
* .. ARRAY ARGUMENTS ..
INTEGER ISEED( 4 )
DOUBLE PRECISION X( N )
* ..
*
* PURPOSE
* =======
*
* DLARUV RETURNS A VECTOR OF N RANDOM REAL NUMBERS FROM A UNIFORM (0,1)
* DISTRIBUTION (N <= 128).
*
* THIS IS AN AUXILIARY ROUTINE CALLED BY DLARNV AND ZLARNV.
*
* ARGUMENTS
* =========
*
* ISEED (INPUT/OUTPUT) INTEGER ARRAY, DIMENSION (4)
* ON ENTRY, THE SEED OF THE RANDOM NUMBER GENERATOR; THE ARRAY
* ELEMENTS MUST BE BETWEEN 0 AND 4095, AND ISEED(4) MUST BE
* ODD.
* ON EXIT, THE SEED IS UPDATED.
*
* N (INPUT) INTEGER
* THE NUMBER OF RANDOM NUMBERS TO BE GENERATED. N <= 128.
*
* X (OUTPUT) DOUBLE PRECISION ARRAY, DIMENSION (N)
* THE GENERATED RANDOM NUMBERS.
*
* FURTHER DETAILS
* ===============
*
* THIS ROUTINE USES A MULTIPLICATIVE CONGRUENTIAL METHOD WITH MODULUS
* 2**48 AND MULTIPLIER 33952834046453 (SEE G.S.FISHMAN,
* 'MULTIPLICATIVE CONGRUENTIAL RANDOM NUMBER GENERATORS WITH MODULUS
* 2**B: AN EXHAUSTIVE ANALYSIS FOR B = 32 AND A PARTIAL ANALYSIS FOR
* B = 48', MATH. COMP. 189, PP 331-344, 1990).
*
* 48-BIT INTEGERS ARE STORED IN 4 INTEGER ARRAY ELEMENTS WITH 12 BITS
* PER ELEMENT. HENCE THE ROUTINE IS PORTABLE ACROSS MACHINES WITH
* INTEGERS OF 32 BITS OR MORE.
*
* =====================================================================
*
* .. PARAMETERS ..
DOUBLE PRECISION ONE
PARAMETER ( ONE = 1.0D0 )
INTEGER LV, IPW2
DOUBLE PRECISION R
PARAMETER ( LV = 128, IPW2 = 4096, R = ONE / IPW2 )
* ..
* .. LOCAL SCALARS ..
INTEGER I, I1, I2, I3, I4, IT1, IT2, IT3, IT4, J
* ..
* .. LOCAL ARRAYS ..
INTEGER MM( LV, 4 )
* ..
* .. INTRINSIC FUNCTIONS ..
INTRINSIC DBLE, MIN, MOD
* ..
* .. DATA STATEMENTS ..
DATA ( MM( 1, J ), J = 1, 4 ) / 494, 322, 2508,
$ 2549 /
DATA ( MM( 2, J ), J = 1, 4 ) / 2637, 789, 3754,
$ 1145 /
DATA ( MM( 3, J ), J = 1, 4 ) / 255, 1440, 1766,
$ 2253 /
DATA ( MM( 4, J ), J = 1, 4 ) / 2008, 752, 3572,
$ 305 /
DATA ( MM( 5, J ), J = 1, 4 ) / 1253, 2859, 2893,
$ 3301 /
DATA ( MM( 6, J ), J = 1, 4 ) / 3344, 123, 307,
$ 1065 /
DATA ( MM( 7, J ), J = 1, 4 ) / 4084, 1848, 1297,
$ 3133 /
DATA ( MM( 8, J ), J = 1, 4 ) / 1739, 643, 3966,
$ 2913 /
DATA ( MM( 9, J ), J = 1, 4 ) / 3143, 2405, 758,
$ 3285 /
DATA ( MM( 10, J ), J = 1, 4 ) / 3468, 2638, 2598,
$ 1241 /
DATA ( MM( 11, J ), J = 1, 4 ) / 688, 2344, 3406,
$ 1197 /
DATA ( MM( 12, J ), J = 1, 4 ) / 1657, 46, 2922,
$ 3729 /
DATA ( MM( 13, J ), J = 1, 4 ) / 1238, 3814, 1038,
$ 2501 /
DATA ( MM( 14, J ), J = 1, 4 ) / 3166, 913, 2934,
$ 1673 /
DATA ( MM( 15, J ), J = 1, 4 ) / 1292, 3649, 2091,
$ 541 /
DATA ( MM( 16, J ), J = 1, 4 ) / 3422, 339, 2451,
$ 2753 /
DATA ( MM( 17, J ), J = 1, 4 ) / 1270, 3808, 1580,
$ 949 /
DATA ( MM( 18, J ), J = 1, 4 ) / 2016, 822, 1958,
$ 2361 /
DATA ( MM( 19, J ), J = 1, 4 ) / 154, 2832, 2055,
$ 1165 /
DATA ( MM( 20, J ), J = 1, 4 ) / 2862, 3078, 1507,
$ 4081 /
DATA ( MM( 21, J ), J = 1, 4 ) / 697, 3633, 1078,
$ 2725 /
DATA ( MM( 22, J ), J = 1, 4 ) / 1706, 2970, 3273,
$ 3305 /
DATA ( MM( 23, J ), J = 1, 4 ) / 491, 637, 17,
$ 3069 /
DATA ( MM( 24, J ), J = 1, 4 ) / 931, 2249, 854,
$ 3617 /
DATA ( MM( 25, J ), J = 1, 4 ) / 1444, 2081, 2916,
$ 3733 /
DATA ( MM( 26, J ), J = 1, 4 ) / 444, 4019, 3971,
$ 409 /
DATA ( MM( 27, J ), J = 1, 4 ) / 3577, 1478, 2889,
$ 2157 /
DATA ( MM( 28, J ), J = 1, 4 ) / 3944, 242, 3831,
$ 1361 /
DATA ( MM( 29, J ), J = 1, 4 ) / 2184, 481, 2621,
$ 3973 /
DATA ( MM( 30, J ), J = 1, 4 ) / 1661, 2075, 1541,
$ 1865 /
DATA ( MM( 31, J ), J = 1, 4 ) / 3482, 4058, 893,
$ 2525 /
DATA ( MM( 32, J ), J = 1, 4 ) / 657, 622, 736,
$ 1409 /
DATA ( MM( 33, J ), J = 1, 4 ) / 3023, 3376, 3992,
$ 3445 /
DATA ( MM( 34, J ), J = 1, 4 ) / 3618, 812, 787,
$ 3577 /
DATA ( MM( 35, J ), J = 1, 4 ) / 1267, 234, 2125,
$ 77 /
DATA ( MM( 36, J ), J = 1, 4 ) / 1828, 641, 2364,
$ 3761 /
DATA ( MM( 37, J ), J = 1, 4 ) / 164, 4005, 2460,
$ 2149 /
DATA ( MM( 38, J ), J = 1, 4 ) / 3798, 1122, 257,
$ 1449 /
DATA ( MM( 39, J ), J = 1, 4 ) / 3087, 3135, 1574,
$ 3005 /
DATA ( MM( 40, J ), J = 1, 4 ) / 2400, 2640, 3912,
$ 225 /
DATA ( MM( 41, J ), J = 1, 4 ) / 2870, 2302, 1216,
$ 85 /
DATA ( MM( 42, J ), J = 1, 4 ) / 3876, 40, 3248,
$ 3673 /
DATA ( MM( 43, J ), J = 1, 4 ) / 1905, 1832, 3401,
$ 3117 /
DATA ( MM( 44, J ), J = 1, 4 ) / 1593, 2247, 2124,
$ 3089 /
DATA ( MM( 45, J ), J = 1, 4 ) / 1797, 2034, 2762,
$ 1349 /
DATA ( MM( 46, J ), J = 1, 4 ) / 1234, 2637, 149,
$ 2057 /
DATA ( MM( 47, J ), J = 1, 4 ) / 3460, 1287, 2245,
$ 413 /
DATA ( MM( 48, J ), J = 1, 4 ) / 328, 1691, 166,
$ 65 /
DATA ( MM( 49, J ), J = 1, 4 ) / 2861, 496, 466,
$ 1845 /
DATA ( MM( 50, J ), J = 1, 4 ) / 1950, 1597, 4018,
$ 697 /
DATA ( MM( 51, J ), J = 1, 4 ) / 617, 2394, 1399,
$ 3085 /
DATA ( MM( 52, J ), J = 1, 4 ) / 2070, 2584, 190,
$ 3441 /
DATA ( MM( 53, J ), J = 1, 4 ) / 3331, 1843, 2879,
$ 1573 /
DATA ( MM( 54, J ), J = 1, 4 ) / 769, 336, 153,
$ 3689 /
DATA ( MM( 55, J ), J = 1, 4 ) / 1558, 1472, 2320,
$ 2941 /
DATA ( MM( 56, J ), J = 1, 4 ) / 2412, 2407, 18,
$ 929 /
DATA ( MM( 57, J ), J = 1, 4 ) / 2800, 433, 712,
$ 533 /
DATA ( MM( 58, J ), J = 1, 4 ) / 189, 2096, 2159,
$ 2841 /
DATA ( MM( 59, J ), J = 1, 4 ) / 287, 1761, 2318,
$ 4077 /
DATA ( MM( 60, J ), J = 1, 4 ) / 2045, 2810, 2091,
$ 721 /
DATA ( MM( 61, J ), J = 1, 4 ) / 1227, 566, 3443,
$ 2821 /
DATA ( MM( 62, J ), J = 1, 4 ) / 2838, 442, 1510,
$ 2249 /
DATA ( MM( 63, J ), J = 1, 4 ) / 209, 41, 449,
$ 2397 /
DATA ( MM( 64, J ), J = 1, 4 ) / 2770, 1238, 1956,
$ 2817 /
DATA ( MM( 65, J ), J = 1, 4 ) / 3654, 1086, 2201,
$ 245 /
DATA ( MM( 66, J ), J = 1, 4 ) / 3993, 603, 3137,
$ 1913 /
DATA ( MM( 67, J ), J = 1, 4 ) / 192, 840, 3399,
$ 1997 /
DATA ( MM( 68, J ), J = 1, 4 ) / 2253, 3168, 1321,
$ 3121 /
DATA ( MM( 69, J ), J = 1, 4 ) / 3491, 1499, 2271,
$ 997 /
DATA ( MM( 70, J ), J = 1, 4 ) / 2889, 1084, 3667,
$ 1833 /
DATA ( MM( 71, J ), J = 1, 4 ) / 2857, 3438, 2703,
$ 2877 /
DATA ( MM( 72, J ), J = 1, 4 ) / 2094, 2408, 629,
$ 1633 /
DATA ( MM( 73, J ), J = 1, 4 ) / 1818, 1589, 2365,
$ 981 /
DATA ( MM( 74, J ), J = 1, 4 ) / 688, 2391, 2431,
$ 2009 /
DATA ( MM( 75, J ), J = 1, 4 ) / 1407, 288, 1113,
$ 941 /
DATA ( MM( 76, J ), J = 1, 4 ) / 634, 26, 3922,
$ 2449 /
DATA ( MM( 77, J ), J = 1, 4 ) / 3231, 512, 2554,
$ 197 /
DATA ( MM( 78, J ), J = 1, 4 ) / 815, 1456, 184,
$ 2441 /
DATA ( MM( 79, J ), J = 1, 4 ) / 3524, 171, 2099,
$ 285 /
DATA ( MM( 80, J ), J = 1, 4 ) / 1914, 1677, 3228,
$ 1473 /
DATA ( MM( 81, J ), J = 1, 4 ) / 516, 2657, 4012,
$ 2741 /
DATA ( MM( 82, J ), J = 1, 4 ) / 164, 2270, 1921,
$ 3129 /
DATA ( MM( 83, J ), J = 1, 4 ) / 303, 2587, 3452,
$ 909 /
DATA ( MM( 84, J ), J = 1, 4 ) / 2144, 2961, 3901,
$ 2801 /
DATA ( MM( 85, J ), J = 1, 4 ) / 3480, 1970, 572,
$ 421 /
DATA ( MM( 86, J ), J = 1, 4 ) / 119, 1817, 3309,
$ 4073 /
DATA ( MM( 87, J ), J = 1, 4 ) / 3357, 676, 3171,
$ 2813 /
DATA ( MM( 88, J ), J = 1, 4 ) / 837, 1410, 817,
$ 2337 /
DATA ( MM( 89, J ), J = 1, 4 ) / 2826, 3723, 3039,
$ 1429 /
DATA ( MM( 90, J ), J = 1, 4 ) / 2332, 2803, 1696,
$ 1177 /
DATA ( MM( 91, J ), J = 1, 4 ) / 2089, 3185, 1256,
$ 1901 /
DATA ( MM( 92, J ), J = 1, 4 ) / 3780, 184, 3715,
$ 81 /
DATA ( MM( 93, J ), J = 1, 4 ) / 1700, 663, 2077,
$ 1669 /
DATA ( MM( 94, J ), J = 1, 4 ) / 3712, 499, 3019,
$ 2633 /
DATA ( MM( 95, J ), J = 1, 4 ) / 150, 3784, 1497,
$ 2269 /
DATA ( MM( 96, J ), J = 1, 4 ) / 2000, 1631, 1101,
$ 129 /
DATA ( MM( 97, J ), J = 1, 4 ) / 3375, 1925, 717,
$ 1141 /
DATA ( MM( 98, J ), J = 1, 4 ) / 1621, 3912, 51,
$ 249 /
DATA ( MM( 99, J ), J = 1, 4 ) / 3090, 1398, 981,
$ 3917 /
DATA ( MM( 100, J ), J = 1, 4 ) / 3765, 1349, 1978,
$ 2481 /
DATA ( MM( 101, J ), J = 1, 4 ) / 1149, 1441, 1813,
$ 3941 /
DATA ( MM( 102, J ), J = 1, 4 ) / 3146, 2224, 3881,
$ 2217 /
DATA ( MM( 103, J ), J = 1, 4 ) / 33, 2411, 76,
$ 2749 /
DATA ( MM( 104, J ), J = 1, 4 ) / 3082, 1907, 3846,
$ 3041 /
DATA ( MM( 105, J ), J = 1, 4 ) / 2741, 3192, 3694,
$ 1877 /
DATA ( MM( 106, J ), J = 1, 4 ) / 359, 2786, 1682,
$ 345 /
DATA ( MM( 107, J ), J = 1, 4 ) / 3316, 382, 124,
$ 2861 /
DATA ( MM( 108, J ), J = 1, 4 ) / 1749, 37, 1660,
$ 1809 /
DATA ( MM( 109, J ), J = 1, 4 ) / 185, 759, 3997,
$ 3141 /
DATA ( MM( 110, J ), J = 1, 4 ) / 2784, 2948, 479,
$ 2825 /
DATA ( MM( 111, J ), J = 1, 4 ) / 2202, 1862, 1141,
$ 157 /
DATA ( MM( 112, J ), J = 1, 4 ) / 2199, 3802, 886,
$ 2881 /
DATA ( MM( 113, J ), J = 1, 4 ) / 1364, 2423, 3514,
$ 3637 /
DATA ( MM( 114, J ), J = 1, 4 ) / 1244, 2051, 1301,
$ 1465 /
DATA ( MM( 115, J ), J = 1, 4 ) / 2020, 2295, 3604,
$ 2829 /
DATA ( MM( 116, J ), J = 1, 4 ) / 3160, 1332, 1888,
$ 2161 /
DATA ( MM( 117, J ), J = 1, 4 ) / 2785, 1832, 1836,
$ 3365 /
DATA ( MM( 118, J ), J = 1, 4 ) / 2772, 2405, 1990,
$ 361 /
DATA ( MM( 119, J ), J = 1, 4 ) / 1217, 3638, 2058,
$ 2685 /
DATA ( MM( 120, J ), J = 1, 4 ) / 1822, 3661, 692,
$ 3745 /
DATA ( MM( 121, J ), J = 1, 4 ) / 1245, 327, 1194,
$ 2325 /
DATA ( MM( 122, J ), J = 1, 4 ) / 2252, 3660, 20,
$ 3609 /
DATA ( MM( 123, J ), J = 1, 4 ) / 3904, 716, 3285,
$ 3821 /
DATA ( MM( 124, J ), J = 1, 4 ) / 2774, 1842, 2046,
$ 3537 /
DATA ( MM( 125, J ), J = 1, 4 ) / 997, 3987, 2107,
$ 517 /
DATA ( MM( 126, J ), J = 1, 4 ) / 2573, 1368, 3508,
$ 3017 /
DATA ( MM( 127, J ), J = 1, 4 ) / 1148, 1848, 3525,
$ 2141 /
DATA ( MM( 128, J ), J = 1, 4 ) / 545, 2366, 3801,
$ 1537 /
* ..
* .. EXECUTABLE STATEMENTS ..
*
I1 = ISEED( 1 )
I2 = ISEED( 2 )
I3 = ISEED( 3 )
I4 = ISEED( 4 )
*
DO 10 I = 1, MIN( N, LV )
*
* MULTIPLY THE SEED BY I-TH POWER OF THE MULTIPLIER MODULO 2**48
*
IT4 = I4*MM( I, 4 )
IT3 = IT4 / IPW2
IT4 = IT4 - IPW2*IT3
IT3 = IT3 + I3*MM( I, 4 ) + I4*MM( I, 3 )
IT2 = IT3 / IPW2
IT3 = IT3 - IPW2*IT2
IT2 = IT2 + I2*MM( I, 4 ) + I3*MM( I, 3 ) + I4*MM( I, 2 )
IT1 = IT2 / IPW2
IT2 = IT2 - IPW2*IT1
IT1 = IT1 + I1*MM( I, 4 ) + I2*MM( I, 3 ) + I3*MM( I, 2 ) +
$ I4*MM( I, 1 )
IT1 = MOD( IT1, IPW2 )
*
* CONVERT 48-BIT INTEGER TO A REAL NUMBER IN THE INTERVAL (0,1)
*
X( I ) = R*( DBLE( IT1 )+R*( DBLE( IT2 )+R*( DBLE( IT3 )+R*
$ DBLE( IT4 ) ) ) )
10 CONTINUE
*
* RETURN FINAL VALUE OF SEED
*
ISEED( 1 ) = IT1
ISEED( 2 ) = IT2
ISEED( 3 ) = IT3
ISEED( 4 ) = IT4
RETURN
*
* END OF DLARUV
*
END
CUT HERE............
CAT > DSTEBZ.F <<'CUT HERE............'
SUBROUTINE DSTEBZ( RANGE, ORDER, N, VL, VU, IL, IU, ABSTOL, D, E,
$ M, NSPLIT, W, IBLOCK, ISPLIT, WORK, IWORK,
$ INFO )
*
* -- LAPACK ROUTINE (VERSION 1.1) --
* UNIV. OF TENNESSEE, UNIV. OF CALIFORNIA BERKELEY, NAG LTD.,
* COURANT INSTITUTE, ARGONNE NATIONAL LAB, AND RICE UNIVERSITY
* MARCH 31, 1993
*
* .. SCALAR ARGUMENTS ..
CHARACTER ORDER, RANGE
INTEGER IL, INFO, IU, M, N, NSPLIT
DOUBLE PRECISION ABSTOL, VL, VU
* ..
* .. ARRAY ARGUMENTS ..
INTEGER IBLOCK( * ), ISPLIT( * ), IWORK( * )
DOUBLE PRECISION D( * ), E( * ), W( * ), WORK( * )
* ..
*
* PURPOSE
* =======
*
* DSTEBZ COMPUTES THE EIGENVALUES OF A SYMMETRIC TRIDIAGONAL
* MATRIX T. THE USER MAY ASK FOR ALL EIGENVALUES, ALL EIGENVALUES
* IN THE HALF-OPEN INTERVAL (VL, VU], OR THE IL-TH THROUGH IU-TH
* EIGENVALUES.
*
* SEE W. KAHAN "ACCURATE EIGENVALUES OF A SYMMETRIC TRIDIAGONAL
* MATRIX", REPORT CS41, COMPUTER SCIENCE DEPT., STANFORD
* UNIVERSITY, JULY 21, 1966.
*
* ARGUMENTS
* =========
*
* RANGE (INPUT) CHARACTER
* = 'A': ("ALL") ALL EIGENVALUES WILL BE FOUND.
* = 'V': ("VALUE") ALL EIGENVALUES IN THE HALF-OPEN INTERVAL
* (VL, VU] WILL BE FOUND.
* = 'I': ("INDEX") THE IL-TH THROUGH IU-TH EIGENVALUES (OF THE
* ENTIRE MATRIX) WILL BE FOUND.
*
* ORDER (INPUT) CHARACTER
* = 'B': ("BY BLOCK") THE EIGENVALUES WILL BE GROUPED BY
* SPLIT-OFF BLOCK (SEE IBLOCK, ISPLIT) AND
* ORDERED FROM SMALLEST TO LARGEST WITHIN
* THE BLOCK.
* = 'E': ("ENTIRE MATRIX")
* THE EIGENVALUES FOR THE ENTIRE MATRIX
* WILL BE ORDERED FROM SMALLEST TO
* LARGEST.
*
* N (INPUT) INTEGER
* THE DIMENSION OF THE TRIDIAGONAL MATRIX T. N >= 0.
*
* VL (INPUT) DOUBLE PRECISION
* IF RANGE='V', THE LOWER BOUND OF THE INTERVAL TO BE SEARCHED
* FOR EIGENVALUES. EIGENVALUES LESS THAN OR EQUAL TO VL WILL
* NOT BE RETURNED. NOT REFERENCED IF RANGE='A' OR 'I'.
*
* VU (INPUT) DOUBLE PRECISION
* IF RANGE='V', THE UPPER BOUND OF THE INTERVAL TO BE SEARCHED
* FOR EIGENVALUES. EIGENVALUES GREATER THAN VU WILL NOT BE
* RETURNED. VU MUST BE GREATER THAN VL. NOT REFERENCED IF
* RANGE='A' OR 'I'.
*
* IL (INPUT) INTEGER
* IF RANGE='I', THE INDEX (FROM SMALLEST TO LARGEST) OF THE
* SMALLEST EIGENVALUE TO BE RETURNED. IL MUST BE AT LEAST 1.
* NOT REFERENCED IF RANGE='A' OR 'V'.
*
* IU (INPUT) INTEGER
* IF RANGE='I', THE INDEX (FROM SMALLEST TO LARGEST) OF THE
* LARGEST EIGENVALUE TO BE RETURNED. IU MUST BE AT LEAST IL
* AND NO GREATER THAN N. NOT REFERENCED IF RANGE='A' OR 'V'.
*
* ABSTOL (INPUT) DOUBLE PRECISION
* THE ABSOLUTE TOLERANCE FOR THE EIGENVALUES. AN EIGENVALUE
* (OR CLUSTER) IS CONSIDERED TO BE LOCATED IF IT HAS BEEN
* DETERMINED TO LIE IN AN INTERVAL WHOSE WIDTH IS ABSTOL OR
* LESS. IF ABSTOL IS LESS THAN OR EQUAL TO ZERO, THEN ULP*|T|
* WILL BE USED, WHERE |T| MEANS THE 1-NORM OF T.
*
* D (INPUT) DOUBLE PRECISION ARRAY, DIMENSION (N)
* THE N DIAGONAL ELEMENTS OF THE TRIDIAGONAL MATRIX T. TO
* AVOID OVERFLOW, THE MATRIX MUST BE SCALED SO THAT ITS LARGEST
* ENTRY IS NO GREATER THAN OVERFLOW**(1/2) * UNDERFLOW**(1/4)
* IN ABSOLUTE VALUE, AND FOR GREATEST ACCURACY, IT SHOULD NOT
* BE MUCH SMALLER THAN THAT.
*
* E (INPUT) DOUBLE PRECISION ARRAY, DIMENSION (N-1)
* THE (N-1) OFF-DIAGONAL ELEMENTS OF THE TRIDIAGONAL MATRIX T.
* TO AVOID OVERFLOW, THE MATRIX MUST BE SCALED SO THAT ITS
* LARGEST ENTRY IS NO GREATER THAN OVERFLOW**(1/2) *
* UNDERFLOW**(1/4) IN ABSOLUTE VALUE, AND FOR GREATEST
* ACCURACY, IT SHOULD NOT BE MUCH SMALLER THAN THAT.
*
* M (OUTPUT) INTEGER
* THE ACTUAL NUMBER OF EIGENVALUES FOUND. 0 <= M <= N.
* (SEE ALSO THE DESCRIPTION OF INFO=2,3.)
*
* NSPLIT (OUTPUT) INTEGER
* THE NUMBER OF DIAGONAL BLOCKS IN THE MATRIX T.
* 1 <= NSPLIT <= N.
*
* W (OUTPUT) DOUBLE PRECISION ARRAY, DIMENSION (N)
* ON EXIT, THE FIRST M ELEMENTS OF W WILL CONTAIN THE
* EIGENVALUES. (DSTEBZ MAY USE THE REMAINING N-M ELEMENTS AS
* WORKSPACE.)
*
* IBLOCK (OUTPUT) INTEGER ARRAY, DIMENSION (N)
* AT EACH ROW/COLUMN J WHERE E(J) IS ZERO OR SMALL, THE
* MATRIX T IS CONSIDERED TO SPLIT INTO A BLOCK DIAGONAL
* MATRIX. ON EXIT, IBLOCK(I) SPECIFIES WHICH BLOCK (FROM 1 TO
* THE NUMBER OF BLOCKS) THE EIGENVALUE W(I) BELONGS TO.
* (DSTEBZ MAY USE THE REMAINING N-M ELEMENTS AS WORKSPACE.)
*
* ISPLIT (OUTPUT) INTEGER ARRAY, DIMENSION (N)
* THE SPLITTING POINTS, AT WHICH T BREAKS UP INTO SUBMATRICES.
* THE FIRST SUBMATRIX CONSISTS OF ROWS/COLUMNS 1 TO ISPLIT(1),
* THE SECOND OF ROWS/COLUMNS ISPLIT(1)+1 THROUGH ISPLIT(2),
* ETC., AND THE NSPLIT-TH CONSISTS OF ROWS/COLUMNS
* ISPLIT(NSPLIT-1)+1 THROUGH ISPLIT(NSPLIT)=N.
* (ONLY THE FIRST NSPLIT ELEMENTS WILL ACTUALLY BE USED, BUT
* SINCE THE USER CANNOT KNOW A PRIORI WHAT VALUE NSPLIT WILL
* HAVE, N WORDS MUST BE RESERVED FOR ISPLIT.)
*
* WORK (WORKSPACE) DOUBLE PRECISION ARRAY, DIMENSION (4*N)
*
* IWORK (WORKSPACE) INTEGER ARRAY, DIMENSION (3*N)
*
* INFO (OUTPUT) INTEGER
* = 0: SUCCESSFUL EXIT
* < 0: IF INFO = -I, THE I-TH ARGUMENT HAD AN ILLEGAL VALUE
* > 0: SOME OR ALL OF THE EIGENVALUES FAILED TO CONVERGE OR
* WERE NOT COMPUTED:
* =1 OR 3: BISECTION FAILED TO CONVERGE FOR SOME
* EIGENVALUES; THESE EIGENVALUES ARE FLAGGED BY A
* NEGATIVE BLOCK NUMBER. THE EFFECT IS THAT THE
* EIGENVALUES MAY NOT BE AS ACCURATE AS THE
* ABSOLUTE AND RELATIVE TOLERANCES. THIS IS
* GENERALLY CAUSED BY UNEXPECTEDLY INACCURATE
* ARITHMETIC.
* =2 OR 3: RANGE='I' ONLY: NOT ALL OF THE EIGENVALUES
* IL:IU WERE FOUND.
* EFFECT: M < IU+1-IL
* CAUSE: NON-MONOTONIC ARITHMETIC, CAUSING THE
* STURM SEQUENCE TO BE NON-MONOTONIC.
* CURE: RECALCULATE, USING RANGE='A', AND PICK
* OUT EIGENVALUES IL:IU. IN SOME CASES,
* INCREASING THE PARAMETER "FUDGE" MAY
* MAKE THINGS WORK.
* = 4: RANGE='I', AND THE GERSHGORIN INTERVAL
* INITIALLY USED WAS TOO SMALL. NO EIGENVALUES
* WERE COMPUTED.
* PROBABLE CAUSE: YOUR MACHINE HAS SLOPPY
* FLOATING-POINT ARITHMETIC.
* CURE: INCREASE THE PARAMETER "FUDGE",
* RECOMPILE, AND TRY AGAIN.
*
* INTERNAL PARAMETERS
* ===================
*
* RELFAC DOUBLE PRECISION, DEFAULT = 2.0E0
* THE RELATIVE TOLERANCE. AN INTERVAL (A,B] LIES WITHIN
* "RELATIVE TOLERANCE" IF B-A < RELFAC*ULP*MAX(|A|,|B|),
* WHERE "ULP" IS THE MACHINE PRECISION (DISTANCE FROM 1 TO
* THE NEXT LARGER FLOATING POINT NUMBER.)
*
* FUDGE DOUBLE PRECISION, DEFAULT = 2
* A "FUDGE FACTOR" TO WIDEN THE GERSHGORIN INTERVALS. IDEALLY,
* A VALUE OF 1 SHOULD WORK, BUT ON MACHINES WITH SLOPPY
* ARITHMETIC, THIS NEEDS TO BE LARGER. THE DEFAULT FOR
* PUBLICLY RELEASED VERSIONS SHOULD BE LARGE ENOUGH TO HANDLE
* THE WORST MACHINE AROUND. NOTE THAT THIS HAS NO EFFECT
* ON ACCURACY OF THE SOLUTION.
*
* =====================================================================
*
* .. PARAMETERS ..
DOUBLE PRECISION ZERO, ONE, TWO, HALF
PARAMETER ( ZERO = 0.0D0, ONE = 1.0D0, TWO = 2.0D0,
$ HALF = 1.0D0 / TWO )
DOUBLE PRECISION FUDGE, RELFAC
PARAMETER ( FUDGE = 2.0D0, RELFAC = 2.0D0 )
* ..
* .. LOCAL SCALARS ..
LOGICAL NCNVRG, TOOFEW
INTEGER IB, IBEGIN, IDISCL, IDISCU, IE, IEND, IINFO,
$ IM, IN, IOFF, IORDER, IOUT, IRANGE, ITMAX,
$ ITMP1, IW, IWOFF, J, JB, JDISC, JE, NB, NWL,
$ NWU
DOUBLE PRECISION ATOLI, BNORM, GL, GU, PIVMIN, RTOLI, SAFEMN,
$ TMP1, TMP2, TNORM, ULP, WKILL, WL, WLU, WU, WUL
* ..
* .. LOCAL ARRAYS ..
INTEGER IDUMMA( 1 )
* ..
* .. EXTERNAL FUNCTIONS ..
LOGICAL LSAME
INTEGER ILAENV
DOUBLE PRECISION DLAMCH
EXTERNAL LSAME, ILAENV, DLAMCH
* ..
* .. EXTERNAL SUBROUTINES ..
EXTERNAL DLAEBZ, XERBLA
* ..
* .. INTRINSIC FUNCTIONS ..
INTRINSIC ABS, INT, LOG, MAX, MIN, SQRT
* ..
* .. EXECUTABLE STATEMENTS ..
*
INFO = 0
*
* DECODE RANGE
*
IF( LSAME( RANGE, 'A' ) ) THEN
IRANGE = 1
ELSE IF( LSAME( RANGE, 'V' ) ) THEN
IRANGE = 2
ELSE IF( LSAME( RANGE, 'I' ) ) THEN
IRANGE = 3
ELSE
IRANGE = 0
END IF
*
* DECODE ORDER
*
IF( LSAME( ORDER, 'B' ) ) THEN
IORDER = 2
ELSE IF( LSAME( ORDER, 'E' ) .OR. LSAME( ORDER, 'A' ) ) THEN
IORDER = 1
ELSE
IORDER = 0
END IF
*
* CHECK FOR ERRORS
*
IF( IRANGE.LE.0 ) THEN
INFO = -1
ELSE IF( IORDER.LE.0 ) THEN
INFO = -2
ELSE IF( N.LT.0 ) THEN
INFO = -3
ELSE IF( IRANGE.EQ.2 .AND. VL.GE.VU ) THEN
INFO = -5
ELSE IF( IRANGE.EQ.3 .AND. ( IL.LT.1 .OR. IL.GT.MAX( 1, N ) ) )
$ THEN
INFO = -6
ELSE IF( IRANGE.EQ.3 .AND. ( IU.LT.MIN( N, IL ) .OR. IU.GT.N ) )
$ THEN
INFO = -7
END IF
*
IF( INFO.NE.0 ) THEN
CALL XERBLA( 'DSTEBZ', -INFO )
RETURN
END IF
*
* INITIALIZE ERROR FLAGS
*
INFO = 0
NCNVRG = .FALSE.
TOOFEW = .FALSE.
*
* QUICK RETURN IF POSSIBLE
*
M = 0
IF( N.EQ.0 )
$ RETURN
*
* SIMPLIFICATIONS:
*
IF( IRANGE.EQ.3 .AND. IL.EQ.1 .AND. IU.EQ.N )
$ IRANGE = 1
*
* GET MACHINE CONSTANTS
* NB IS THE MINIMUM VECTOR LENGTH FOR VECTOR BISECTION, OR 0
* IF ONLY SCALAR IS TO BE DONE.
*
SAFEMN = DLAMCH( 'S' )
ULP = DLAMCH( 'P' )
RTOLI = ULP*RELFAC
NB = ILAENV( 1, 'DSTEBZ', ' ', N, -1, -1, -1 )
IF( NB.LE.1 )
$ NB = 0
*
* SPECIAL CASE WHEN N=1
*
IF( N.EQ.1 ) THEN
NSPLIT = 1
ISPLIT( 1 ) = 1
IF( IRANGE.EQ.2 .AND. ( VL.GE.D( 1 ) .OR. VU.LT.D( 1 ) ) ) THEN
M = 0
ELSE
W( 1 ) = D( 1 )
IBLOCK( 1 ) = 1
M = 1
END IF
RETURN
END IF
*
* COMPUTE SPLITTING POINTS
*
NSPLIT = 1
WORK( N ) = ZERO
PIVMIN = ONE
*
DO 10 J = 2, N
TMP1 = E( J-1 )**2
IF( ABS( D( J )*D( J-1 ) )*ULP**2+SAFEMN.GT.TMP1 ) THEN
ISPLIT( NSPLIT ) = J - 1
NSPLIT = NSPLIT + 1
WORK( J-1 ) = ZERO
ELSE
WORK( J-1 ) = TMP1
PIVMIN = MAX( PIVMIN, TMP1 )
END IF
10 CONTINUE
ISPLIT( NSPLIT ) = N
PIVMIN = PIVMIN*SAFEMN
*
* COMPUTE INTERVAL AND ATOLI
*
IF( IRANGE.EQ.3 ) THEN
*
* RANGE='I': COMPUTE THE INTERVAL CONTAINING EIGENVALUES
* IL THROUGH IU.
*
* COMPUTE GERSHGORIN INTERVAL FOR ENTIRE (SPLIT) MATRIX
* AND USE IT AS THE INITIAL INTERVAL
*
GU = D( 1 )
GL = D( 1 )
TMP1 = ZERO
*
DO 20 J = 1, N - 1
TMP2 = SQRT( WORK( J ) )
GU = MAX( GU, D( J )+TMP1+TMP2 )
GL = MIN( GL, D( J )-TMP1-TMP2 )
TMP1 = TMP2
20 CONTINUE
*
GU = MAX( GU, D( N )+TMP1 )
GL = MIN( GL, D( N )-TMP1 )
TNORM = MAX( ABS( GL ), ABS( GU ) )
GL = GL - FUDGE*TNORM*ULP*N - FUDGE*TWO*PIVMIN
GU = GU + FUDGE*TNORM*ULP*N + FUDGE*PIVMIN
*
* COMPUTE ITERATION PARAMETERS
*
ITMAX = INT( ( LOG( TNORM+PIVMIN )-LOG( PIVMIN ) ) /
$ LOG( TWO ) ) + 2
IF( ABSTOL.LE.ZERO ) THEN
ATOLI = ULP*TNORM
ELSE
ATOLI = ABSTOL
END IF
*
WORK( N+1 ) = GL
WORK( N+2 ) = GL
WORK( N+3 ) = GU
WORK( N+4 ) = GU
WORK( N+5 ) = GL
WORK( N+6 ) = GU
IWORK( 1 ) = -1
IWORK( 2 ) = -1
IWORK( 3 ) = N + 1
IWORK( 4 ) = N + 1
IWORK( 5 ) = IL - 1
IWORK( 6 ) = IU
*
CALL DLAEBZ( 3, ITMAX, N, 2, 2, NB, ATOLI, RTOLI, PIVMIN, D, E,
$ WORK, IWORK( 5 ), WORK( N+1 ), WORK( N+5 ), IOUT,
$ IWORK, W, IBLOCK, IINFO )
*
IF( IWORK( 6 ).EQ.IU ) THEN
WL = WORK( N+1 )
WLU = WORK( N+3 )
NWL = IWORK( 1 )
WU = WORK( N+4 )
WUL = WORK( N+2 )
NWU = IWORK( 4 )
ELSE
WL = WORK( N+2 )
WLU = WORK( N+4 )
NWL = IWORK( 2 )
WU = WORK( N+3 )
WUL = WORK( N+1 )
NWU = IWORK( 3 )
END IF
*
IF( NWL.LT.0 .OR. NWL.GE.N .OR. NWU.LT.1 .OR. NWU.GT.N ) THEN
INFO = 4
RETURN
END IF
ELSE
*
* RANGE='A' OR 'V' -- SET ATOLI
*
TNORM = MAX( ABS( D( 1 ) )+ABS( E( 1 ) ),
$ ABS( D( N ) )+ABS( E( N-1 ) ) )
*
DO 30 J = 2, N - 1
TNORM = MAX( TNORM, ABS( D( J ) )+ABS( E( J-1 ) )+
$ ABS( E( J ) ) )
30 CONTINUE
*
IF( ABSTOL.LE.ZERO ) THEN
ATOLI = ULP*TNORM
ELSE
ATOLI = ABSTOL
END IF
*
IF( IRANGE.EQ.2 ) THEN
WL = VL
WU = VU
END IF
END IF
*
* FIND EIGENVALUES -- LOOP OVER BLOCKS AND RECOMPUTE NWL AND NWU.
* NWL ACCUMULATES THE NUMBER OF EIGENVALUES .LE. WL,
* NWU ACCUMULATES THE NUMBER OF EIGENVALUES .LE. WU
*
M = 0
IEND = 0
INFO = 0
NWL = 0
NWU = 0
*
DO 70 JB = 1, NSPLIT
IOFF = IEND
IBEGIN = IOFF + 1
IEND = ISPLIT( JB )
IN = IEND - IOFF
*
IF( IN.EQ.1 ) THEN
*
* SPECIAL CASE -- IN=1
*
IF( IRANGE.EQ.1 .OR. WL.GE.D( IBEGIN )-PIVMIN )
$ NWL = NWL + 1
IF( IRANGE.EQ.1 .OR. WU.GE.D( IBEGIN )-PIVMIN )
$ NWU = NWU + 1
IF( IRANGE.EQ.1 .OR. ( WL.LT.D( IBEGIN )-PIVMIN .AND. WU.GE.
$ D( IBEGIN )-PIVMIN ) ) THEN
M = M + 1
W( M ) = D( IBEGIN )
IBLOCK( M ) = JB
END IF
ELSE
*
* GENERAL CASE -- IN > 1
*
* COMPUTE GERSHGORIN INTERVAL
* AND USE IT AS THE INITIAL INTERVAL
*
GU = D( IBEGIN )
GL = D( IBEGIN )
TMP1 = ZERO
*
DO 40 J = IBEGIN, IEND - 1
TMP2 = ABS( E( J ) )
GU = MAX( GU, D( J )+TMP1+TMP2 )
GL = MIN( GL, D( J )-TMP1-TMP2 )
TMP1 = TMP2
40 CONTINUE
*
GU = MAX( GU, D( IEND )+TMP1 )
GL = MIN( GL, D( IEND )-TMP1 )
BNORM = MAX( ABS( GL ), ABS( GU ) )
GL = GL - FUDGE*BNORM*ULP*IN - FUDGE*PIVMIN
GU = GU + FUDGE*BNORM*ULP*IN + FUDGE*PIVMIN
*
IF( IRANGE.GT.1 ) THEN
GL = MAX( GL, WL )
GU = MIN( GU, WU )
IF( GL.GE.GU )
$ GO TO 70
END IF
*
* SET UP INITIAL INTERVAL
*
WORK( N+1 ) = GL
WORK( N+IN+1 ) = GU
CALL DLAEBZ( 1, 0, IN, IN, 1, NB, ATOLI, RTOLI, PIVMIN,
$ D( IBEGIN ), E( IBEGIN ), WORK( IBEGIN ),
$ IDUMMA, WORK( N+1 ), WORK( N+2*IN+1 ), IM,
$ IWORK, W( M+1 ), IBLOCK( M+1 ), IINFO )
*
NWL = NWL + IWORK( 1 )
NWU = NWU + IWORK( IN+1 )
IWOFF = M - IWORK( 1 )
*
* COMPUTE EIGENVALUES
*
ITMAX = INT( ( LOG( GU-GL+PIVMIN )-LOG( PIVMIN ) ) /
$ LOG( TWO ) ) + 2
CALL DLAEBZ( 2, ITMAX, IN, IN, 1, NB, ATOLI, RTOLI, PIVMIN,
$ D( IBEGIN ), E( IBEGIN ), WORK( IBEGIN ),
$ IDUMMA, WORK( N+1 ), WORK( N+2*IN+1 ), IOUT,
$ IWORK, W( M+1 ), IBLOCK( M+1 ), IINFO )
*
* COPY EIGENVALUES INTO W AND IBLOCK
* USE -JB FOR BLOCK NUMBER FOR UNCONVERGED EIGENVALUES.
*
DO 60 J = 1, IOUT
TMP1 = HALF*( WORK( J+N )+WORK( J+IN+N ) )
*
* FLAG NON-CONVERGENCE.
*
IF( J.GT.IOUT-IINFO ) THEN
NCNVRG = .TRUE.
IB = -JB
ELSE
IB = JB
END IF
DO 50 JE = IWORK( J ) + 1 + IWOFF,
$ IWORK( J+IN ) + IWOFF
W( JE ) = TMP1
IBLOCK( JE ) = IB
50 CONTINUE
60 CONTINUE
*
M = M + IM
END IF
70 CONTINUE
*
* IF RANGE='I', THEN (WL,WU) CONTAINS EIGENVALUES NWL+1,...,NWU
* IF NWL+1 < IL OR NWU > IU, DISCARD EXTRA EIGENVALUES.
*
IF( IRANGE.EQ.3 ) THEN
IM = 0
IDISCL = IL - 1 - NWL
IDISCU = NWU - IU
*
IF( IDISCL.GT.0 .OR. IDISCU.GT.0 ) THEN
DO 80 JE = 1, M
IF( W( JE ).LE.WLU .AND. IDISCL.GT.0 ) THEN
IDISCL = IDISCL - 1
ELSE IF( W( JE ).GE.WUL .AND. IDISCU.GT.0 ) THEN
IDISCU = IDISCU - 1
ELSE
IM = IM + 1
W( IM ) = W( JE )
IBLOCK( IM ) = IBLOCK( JE )
END IF
80 CONTINUE
M = IM
END IF
IF( IDISCL.GT.0 .OR. IDISCU.GT.0 ) THEN
*
* CODE TO DEAL WITH EFFECTS OF BAD ARITHMETIC:
* SOME LOW EIGENVALUES TO BE DISCARDED ARE NOT IN (WL,WLU],
* OR HIGH EIGENVALUES TO BE DISCARDED ARE NOT IN (WUL,WU]
* SO JUST KILL OFF THE SMALLEST IDISCL/LARGEST IDISCU
* EIGENVALUES, BY SIMPLY FINDING THE SMALLEST/LARGEST
* EIGENVALUE(S).
*
* (IF N(W) IS MONOTONE NON-DECREASING, THIS SHOULD NEVER
* HAPPEN.)
*
IF( IDISCL.GT.0 ) THEN
WKILL = WU
DO 100 JDISC = 1, IDISCL
IW = 0
DO 90 JE = 1, M
IF( IBLOCK( JE ).NE.0 .AND.
$ ( W( JE ).LT.WKILL .OR. IW.EQ.0 ) ) THEN
IW = JE
WKILL = W( JE )
END IF
90 CONTINUE
IBLOCK( IW ) = 0
100 CONTINUE
END IF
IF( IDISCU.GT.0 ) THEN
*
WKILL = WL
DO 120 JDISC = 1, IDISCU
IW = 0
DO 110 JE = 1, M
IF( IBLOCK( JE ).NE.0 .AND.
$ ( W( JE ).GT.WKILL .OR. IW.EQ.0 ) ) THEN
IW = JE
WKILL = W( JE )
END IF
110 CONTINUE
IBLOCK( IW ) = 0
120 CONTINUE
END IF
IM = 0
DO 130 JE = 1, M
IF( IBLOCK( JE ).NE.0 ) THEN
IM = IM + 1
W( IM ) = W( JE )
IBLOCK( IM ) = IBLOCK( JE )
END IF
130 CONTINUE
M = IM
END IF
IF( IDISCL.LT.0 .OR. IDISCU.LT.0 ) THEN
TOOFEW = .TRUE.
END IF
END IF
*
* IF ORDER='B', DO NOTHING -- THE EIGENVALUES ARE ALREADY SORTED
* BY BLOCK.
* IF ORDER='E' OR 'A', SORT THE EIGENVALUES FROM SMALLEST TO LARGEST
*
IF( IORDER.EQ.1 .AND. NSPLIT.GT.1 ) THEN
DO 150 JE = 1, M - 1
IE = 0
TMP1 = W( JE )
DO 140 J = JE + 1, M
IF( W( J ).LT.TMP1 ) THEN
IE = J
TMP1 = W( J )
END IF
140 CONTINUE
*
IF( IE.NE.0 ) THEN
ITMP1 = IBLOCK( IE )
W( IE ) = W( JE )
IBLOCK( IE ) = IBLOCK( JE )
W( JE ) = TMP1
IBLOCK( JE ) = ITMP1
END IF
150 CONTINUE
END IF
*
INFO = 0
IF( NCNVRG )
$ INFO = INFO + 1
IF( TOOFEW )
$ INFO = INFO + 2
RETURN
*
* END OF DSTEBZ
*
END
CUT HERE............
CAT > DLAEBZ.F <<'CUT HERE............'
SUBROUTINE DLAEBZ( IJOB, NITMAX, N, MMAX, MINP, NBMIN, ABSTOL,
$ RELTOL, PIVMIN, D, E, E2, NVAL, AB, C, MOUT,
$ NAB, WORK, IWORK, INFO )
*
* -- LAPACK AUXILIARY ROUTINE (VERSION 1.1) --
* UNIV. OF TENNESSEE, UNIV. OF CALIFORNIA BERKELEY, NAG LTD.,
* COURANT INSTITUTE, ARGONNE NATIONAL LAB, AND RICE UNIVERSITY
* MARCH 31, 1993
*
* .. SCALAR ARGUMENTS ..
INTEGER IJOB, INFO, MINP, MMAX, MOUT, N, NBMIN, NITMAX
DOUBLE PRECISION ABSTOL, PIVMIN, RELTOL
* ..
* .. ARRAY ARGUMENTS ..
INTEGER IWORK( * ), NAB( MMAX, * ), NVAL( * )
DOUBLE PRECISION AB( MMAX, * ), C( * ), D( * ), E( * ), E2( * ),
$ WORK( * )
* ..
*
* PURPOSE
* =======
*
* DLAEBZ CONTAINS THE ITERATION LOOPS WHICH COMPUTE AND USE THE
* FUNCTION N(W), WHICH IS THE COUNT OF EIGENVALUES OF A SYMMETRIC
* TRIDIAGONAL MATRIX T LESS THAN OR EQUAL TO ITS ARGUMENT W. IT
* PERFORMS A CHOICE OF TWO TYPES OF LOOPS:
*
* IJOB=1, FOLLOWED BY
* IJOB=2: IT TAKES AS INPUT A LIST OF INTERVALS AND RETURNS A LIST OF
* SUFFICIENTLY SMALL INTERVALS WHOSE UNION CONTAINS THE SAME
* EIGENVALUES AS THE UNION OF THE ORIGINAL INTERVALS.
* THE INPUT INTERVALS ARE (AB(J,1),AB(J,2)], J=1,...,MINP.
* THE OUTPUT INTERVAL (AB(J,1),AB(J,2)] WILL CONTAIN
* EIGENVALUES NAB(J,1)+1,...,NAB(J,2), WHERE 1 <= J <= MOUT.
*
* IJOB=3: IT PERFORMS A BINARY SEARCH IN EACH INPUT INTERVAL
* (AB(J,1),AB(J,2)] FOR A POINT W(J) SUCH THAT
* N(W(J))=NVAL(J), AND USES C(J) AS THE STARTING POINT OF
* THE SEARCH. IF SUCH A W(J) IS FOUND, THEN ON OUTPUT
* AB(J,1)=AB(J,2)=W. IF NO SUCH W(J) IS FOUND, THEN ON OUTPUT
* (AB(J,1),AB(J,2)] WILL BE A SMALL INTERVAL CONTAINING THE
* POINT WHERE N(W) JUMPS THROUGH NVAL(J), UNLESS THAT POINT
* LIES OUTSIDE THE INITIAL INTERVAL.
*
* NOTE THAT THE INTERVALS ARE IN ALL CASES HALF-OPEN INTERVALS,
* I.E., OF THE FORM (A,B] , WHICH INCLUDES B BUT NOT A .
*
* SEE W. KAHAN "ACCURATE EIGENVALUES OF A SYMMETRIC TRIDIAGONAL
* MATRIX", REPORT CS41, COMPUTER SCIENCE DEPT., STANFORD
* UNIVERSITY, JULY 21, 1966
*
* NOTE: THE ARGUMENTS ARE, IN GENERAL, *NOT* CHECKED FOR UNREASONABLE
* VALUES.
*
* ARGUMENTS
* =========
*
* IJOB (INPUT) INTEGER
* SPECIFIES WHAT IS TO BE DONE:
* = 1: COMPUTE NAB FOR THE INITIAL INTERVALS.
* = 2: PERFORM BISECTION ITERATION TO FIND EIGENVALUES OF T.
* = 3: PERFORM BISECTION ITERATION TO INVERT N(W), I.E.,
* TO FIND A POINT WHICH HAS A SPECIFIED NUMBER OF
* EIGENVALUES OF T TO ITS LEFT.
* OTHER VALUES WILL CAUSE DLAEBZ TO RETURN WITH INFO=-1.
*
* NITMAX (INPUT) INTEGER
* THE MAXIMUM NUMBER OF "LEVELS" OF BISECTION TO BE
* PERFORMED, I.E., AN INTERVAL OF WIDTH W WILL NOT BE MADE
* SMALLER THAN 2^(-NITMAX) * W. IF NOT ALL INTERVALS
* HAVE CONVERGED AFTER NITMAX ITERATIONS, THEN INFO IS SET
* TO THE NUMBER OF NON-CONVERGED INTERVALS.
*
* N (INPUT) INTEGER
* THE DIMENSION N OF THE TRIDIAGONAL MATRIX T. IT MUST BE AT
* LEAST 1.
*
* MMAX (INPUT) INTEGER
* THE MAXIMUM NUMBER OF INTERVALS. IF MORE THAN MMAX INTERVALS
* ARE GENERATED, THEN DLAEBZ WILL QUIT WITH INFO=MMAX+1.
*
* MINP (INPUT) INTEGER
* THE INITIAL NUMBER OF INTERVALS. IT MAY NOT BE GREATER THAN
* MMAX.
*
* NBMIN (INPUT) INTEGER
* THE SMALLEST NUMBER OF INTERVALS THAT SHOULD BE PROCESSED
* USING A VECTOR LOOP. IF ZERO, THEN ONLY THE SCALAR LOOP
* WILL BE USED.
*
* ABSTOL (INPUT) DOUBLE PRECISION
* THE MINIMUM (ABSOLUTE) WIDTH OF AN INTERVAL. WHEN AN
* INTERVAL IS NARROWER THAN ABSTOL, OR THAN RELTOL TIMES THE
* LARGER (IN MAGNITUDE) ENDPOINT, THEN IT IS CONSIDERED TO BE
* SUFFICIENTLY SMALL, I.E., CONVERGED. THIS MUST BE AT LEAST
* ZERO.
*
* RELTOL (INPUT) DOUBLE PRECISION
* THE MINIMUM RELATIVE WIDTH OF AN INTERVAL. WHEN AN INTERVAL
* IS NARROWER THAN ABSTOL, OR THAN RELTOL TIMES THE LARGER (IN
* MAGNITUDE) ENDPOINT, THEN IT IS CONSIDERED TO BE
* SUFFICIENTLY SMALL, I.E., CONVERGED. NOTE: THIS SHOULD
* ALWAYS BE AT LEAST RADIX*MACHINE EPSILON.
*
* PIVMIN (INPUT) DOUBLE PRECISION
* THE MINIMUM ABSOLUTE VALUE OF A "PIVOT" IN THE STURM
* SEQUENCE LOOP. THIS *MUST* BE AT LEAST MAX |E(J)**2| *
* SAFE_MIN AND AT LEAST SAFE_MIN, WHERE SAFE_MIN IS AT LEAST
* THE SMALLEST NUMBER THAT CAN DIVIDE ONE WITHOUT OVERFLOW.
*
* D (INPUT) DOUBLE PRECISION ARRAY, DIMENSION (N)
* THE DIAGONAL ELEMENTS OF THE TRIDIAGONAL MATRIX T. TO AVOID
* UNDERFLOW, THE MATRIX SHOULD BE SCALED SO THAT ITS LARGEST
* ENTRY IS NO GREATER THAN OVERFLOW**(1/2) * UNDERFLOW**(1/4)
* IN ABSOLUTE VALUE. TO ASSURE THE MOST ACCURATE COMPUTATION
* OF SMALL EIGENVALUES, THE MATRIX SHOULD BE SCALED TO BE
* NOT MUCH SMALLER THAN THAT, EITHER.
*
* E (INPUT) DOUBLE PRECISION ARRAY, DIMENSION (N)
* THE OFFDIAGONAL ELEMENTS OF THE TRIDIAGONAL MATRIX T IN
* POSITIONS 1 THROUGH N-1. E(N) IS ARBITRARY.
* TO AVOID UNDERFLOW, THE
* MATRIX SHOULD BE SCALED SO THAT ITS LARGEST ENTRY IS NO
* GREATER THAN OVERFLOW**(1/2) * UNDERFLOW**(1/4) IN ABSOLUTE
* VALUE. TO ASSURE THE MOST ACCURATE COMPUTATION OF SMALL
* EIGENVALUES, THE MATRIX SHOULD BE SCALED TO BE NOT MUCH
* SMALLER THAN THAT, EITHER.
*
* E2 (INPUT) DOUBLE PRECISION ARRAY, DIMENSION (N)
* THE SQUARES OF THE OFFDIAGONAL ELEMENTS OF THE TRIDIAGONAL
* MATRIX T. E2(N) IS IGNORED.
*
* NVAL (INPUT/OUTPUT) INTEGER ARRAY, DIMENSION (MINP)
* IF IJOB=1 OR 2, NOT REFERENCED.
* IF IJOB=3, THE DESIRED VALUES OF N(W). THE ELEMENTS OF NVAL
* WILL BE REORDERED TO CORRESPOND WITH THE INTERVALS IN AB.
* THUS, NVAL(J) ON OUTPUT WILL NOT, IN GENERAL BE THE SAME AS
* NVAL(J) ON INPUT, BUT IT WILL CORRESPOND WITH THE INTERVAL
* (AB(J,1),AB(J,2)] ON OUTPUT.
*
* AB (INPUT/OUTPUT) DOUBLE PRECISION ARRAY, DIMENSION (MMAX,2)
* THE ENDPOINTS OF THE INTERVALS. AB(J,1) IS A(J), THE LEFT
* ENDPOINT OF THE J-TH INTERVAL, AND AB(J,2) IS B(J), THE
* RIGHT ENDPOINT OF THE J-TH INTERVAL. THE INPUT INTERVALS
* WILL, IN GENERAL, BE MODIFIED, SPLIT, AND REORDERED BY THE
* CALCULATION.
*
* C (INPUT/WORKSPACE) DOUBLE PRECISION ARRAY, DIMENSION (MMAX)
* IF IJOB=1, IGNORED.
* IF IJOB=2, WORKSPACE.
* IF IJOB=3, THEN ON INPUT C(J) SHOULD BE INITIALIZED TO THE
* FIRST SEARCH POINT IN THE BINARY SEARCH.
*
* MOUT (OUTPUT) INTEGER
* IF IJOB=1, THE NUMBER OF EIGENVALUES IN THE INTERVALS.
* IF IJOB=2 OR 3, THE NUMBER OF INTERVALS OUTPUT.
* IF IJOB=3, MOUT WILL EQUAL MINP.
*
* NAB (INPUT/OUTPUT) INTEGER ARRAY, DIMENSION (MMAX,2)
* IF IJOB=1, THEN ON OUTPUT NAB(I,J) WILL BE SET TO N(AB(I,J)).
* IF IJOB=2, THEN ON INPUT, NAB(I,J) SHOULD BE SET. IT MUST
* SATISFY THE CONDITION:
* N(AB(I,1)) <= NAB(I,1) <= NAB(I,2) <= N(AB(I,2)),
* WHICH MEANS THAT IN INTERVAL I ONLY EIGENVALUES
* NAB(I,1)+1,...,NAB(I,2) WILL BE CONSIDERED. USUALLY,
* NAB(I,J)=N(AB(I,J)), FROM A PREVIOUS CALL TO DLAEBZ WITH
* IJOB=1.
* ON OUTPUT, NAB(I,J) WILL CONTAIN
* MAX(NA(K),MIN(NB(K),N(AB(I,J)))), WHERE K IS THE INDEX OF
* THE INPUT INTERVAL THAT THE OUTPUT INTERVAL
* (AB(J,1),AB(J,2)] CAME FROM, AND NA(K) AND NB(K) ARE THE
* THE INPUT VALUES OF NAB(K,1) AND NAB(K,2).
* IF IJOB=3, THEN ON OUTPUT, NAB(I,J) CONTAINS N(AB(I,J)),
* UNLESS N(W) > NVAL(I) FOR ALL SEARCH POINTS W , IN WHICH
* CASE NAB(I,1) WILL NOT BE MODIFIED, I.E., THE OUTPUT
* VALUE WILL BE THE SAME AS THE INPUT VALUE (MODULO
* REORDERINGS -- SEE NVAL AND AB), OR UNLESS N(W) < NVAL(I)
* FOR ALL SEARCH POINTS W , IN WHICH CASE NAB(I,2) WILL
* NOT BE MODIFIED. NORMALLY, NAB SHOULD BE SET TO SOME
* DISTINCTIVE VALUE(S) BEFORE DLAEBZ IS CALLED.
*
* WORK (WORKSPACE) DOUBLE PRECISION ARRAY, DIMENSION (MMAX)
* WORKSPACE.
*
* IWORK (WORKSPACE) INTEGER ARRAY, DIMENSION (MMAX)
* WORKSPACE.
*
* INFO (OUTPUT) INTEGER
* = 0: ALL INTERVALS CONVERGED.
* = 1--MMAX: THE LAST INFO INTERVALS DID NOT CONVERGE.
* = MMAX+1: MORE THAN MMAX INTERVALS WERE GENERATED.
*
* FURTHER DETAILS
* ===============
*
* THIS ROUTINE IS INTENDED TO BE CALLED ONLY BY OTHER LAPACK
* ROUTINES, THUS THE INTERFACE IS LESS USER-FRIENDLY. IT IS INTENDED
* FOR TWO PURPOSES:
*
* (A) FINDING EIGENVALUES. IN THIS CASE, DLAEBZ SHOULD HAVE ONE OR
* MORE INITIAL INTERVALS SET UP IN AB, AND DLAEBZ SHOULD BE CALLED
* WITH IJOB=1. THIS SETS UP NAB, AND ALSO COUNTS THE EIGENVALUES.
* INTERVALS WITH NO EIGENVALUES WOULD USUALLY BE THROWN OUT AT
* THIS POINT. ALSO, IF NOT ALL THE EIGENVALUES IN AN INTERVAL I
* ARE DESIRED, NAB(I,1) CAN BE INCREASED OR NAB(I,2) DECREASED.
* FOR EXAMPLE, SET NAB(I,1)=NAB(I,2)-1 TO GET THE LARGEST
* EIGENVALUE. DLAEBZ IS THEN CALLED WITH IJOB=2 AND MMAX
* NO SMALLER THAN THE VALUE OF MOUT RETURNED BY THE CALL WITH
* IJOB=1. AFTER THIS (IJOB=2) CALL, EIGENVALUES NAB(I,1)+1
* THROUGH NAB(I,2) ARE APPROXIMATELY AB(I,1) (OR AB(I,2)) TO THE
* TOLERANCE SPECIFIED BY ABSTOL AND RELTOL.
*
* (B) FINDING AN INTERVAL (A',B'] CONTAINING EIGENVALUES W(F),...,W(L).
* IN THIS CASE, START WITH A GERSHGORIN INTERVAL (A,B). SET UP
* AB TO CONTAIN 2 SEARCH INTERVALS, BOTH INITIALLY (A,B). ONE
* NVAL ENTRY SHOULD CONTAIN F-1 AND THE OTHER SHOULD CONTAIN L
* , WHILE C SHOULD CONTAIN A AND B, RESP. NAB(I,1) SHOULD BE -1
* AND NAB(I,2) SHOULD BE N+1, TO FLAG AN ERROR IF THE DESIRED
* INTERVAL DOES NOT LIE IN (A,B). DLAEBZ IS THEN CALLED WITH
* IJOB=3. ON EXIT, IF W(F-1) < W(F), THEN ONE OF THE INTERVALS --
* J -- WILL HAVE AB(J,1)=AB(J,2) AND NAB(J,1)=NAB(J,2)=F-1, WHILE
* IF, TO THE SPECIFIED TOLERANCE, W(F-K)=...=W(F+R), K > 0 AND R
* >= 0, THEN THE INTERVAL WILL HAVE N(AB(J,1))=NAB(J,1)=F-K AND
* N(AB(J,2))=NAB(J,2)=F+R. THE CASES W(L) < W(L+1) AND
* W(L-R)=...=W(L+K) ARE HANDLED SIMILARLY.
*
* =====================================================================
*
* .. PARAMETERS ..
DOUBLE PRECISION ZERO, TWO, HALF
PARAMETER ( ZERO = 0.0D0, TWO = 2.0D0,
$ HALF = 1.0D0 / TWO )
* ..
* .. LOCAL SCALARS ..
INTEGER ITMP1, ITMP2, J, JI, JIT, JP, KF, KFNEW, KL,
$ KLNEW
DOUBLE PRECISION TMP1, TMP2
* ..
* .. INTRINSIC FUNCTIONS ..
INTRINSIC ABS, MAX, MIN
* ..
* .. EXECUTABLE STATEMENTS ..
*
* CHECK FOR ERRORS
*
INFO = 0
IF( IJOB.LT.1 .OR. IJOB.GT.3 ) THEN
INFO = -1
RETURN
END IF
*
* INITIALIZE NAB
*
IF( IJOB.EQ.1 ) THEN
*
* COMPUTE THE NUMBER OF EIGENVALUES IN THE INITIAL INTERVALS.
*
MOUT = 0
DO 30 JI = 1, MINP
DO 20 JP = 1, 2
TMP1 = D( 1 ) - AB( JI, JP )
IF( ABS( TMP1 ).LT.PIVMIN )
$ TMP1 = -PIVMIN
NAB( JI, JP ) = 0
IF( TMP1.LE.ZERO )
$ NAB( JI, JP ) = 1
*
DO 10 J = 2, N
TMP1 = D( J ) - E2( J-1 ) / TMP1 - AB( JI, JP )
IF( ABS( TMP1 ).LT.PIVMIN )
$ TMP1 = -PIVMIN
IF( TMP1.LE.ZERO )
$ NAB( JI, JP ) = NAB( JI, JP ) + 1
10 CONTINUE
20 CONTINUE
MOUT = MOUT + NAB( JI, 2 ) - NAB( JI, 1 )
30 CONTINUE
RETURN
END IF
*
* INITIALIZE FOR LOOP
*
* KF AND KL HAVE THE FOLLOWING MEANING:
* INTERVALS 1,...,KF-1 HAVE CONVERGED.
* INTERVALS KF,...,KL STILL NEED TO BE REFINED.
*
KF = 1
KL = MINP
*
* IF IJOB=2, INITIALIZE C.
* IF IJOB=3, USE THE USER-SUPPLIED STARTING POINT.
*
IF( IJOB.EQ.2 ) THEN
DO 40 JI = 1, MINP
C( JI ) = HALF*( AB( JI, 1 )+AB( JI, 2 ) )
40 CONTINUE
END IF
*
* ITERATION LOOP
*
DO 130 JIT = 1, NITMAX
*
* LOOP OVER INTERVALS
*
IF( KL-KF+1.GE.NBMIN .AND. NBMIN.GT.0 ) THEN
*
* BEGIN OF PARALLEL VERSION OF THE LOOP
*
DO 60 JI = KF, KL
*
* COMPUTE N(C), THE NUMBER OF EIGENVALUES LESS THAN C
*
WORK( JI ) = D( 1 ) - C( JI )
IWORK( JI ) = 0
IF( WORK( JI ).LE.PIVMIN ) THEN
IWORK( JI ) = 1
WORK( JI ) = MIN( WORK( JI ), -PIVMIN )
END IF
*
DO 50 J = 2, N
WORK( JI ) = D( J ) - E2( J-1 ) / WORK( JI ) - C( JI )
IF( WORK( JI ).LE.PIVMIN ) THEN
IWORK( JI ) = IWORK( JI ) + 1
WORK( JI ) = MIN( WORK( JI ), -PIVMIN )
END IF
50 CONTINUE
60 CONTINUE
*
IF( IJOB.LE.2 ) THEN
*
* IJOB=2: CHOOSE ALL INTERVALS CONTAINING EIGENVALUES.
*
KLNEW = KL
DO 70 JI = KF, KL
*
* INSURE THAT N(W) IS MONOTONE
*
IWORK( JI ) = MIN( NAB( JI, 2 ),
$ MAX( NAB( JI, 1 ), IWORK( JI ) ) )
*
* UPDATE THE QUEUE -- ADD INTERVALS IF BOTH HALVES
* CONTAIN EIGENVALUES.
*
IF( IWORK( JI ).EQ.NAB( JI, 2 ) ) THEN
*
* NO EIGENVALUE IN THE UPPER INTERVAL:
* JUST USE THE LOWER INTERVAL.
*
AB( JI, 2 ) = C( JI )
*
ELSE IF( IWORK( JI ).EQ.NAB( JI, 1 ) ) THEN
*
* NO EIGENVALUE IN THE LOWER INTERVAL:
* JUST USE THE UPPER INTERVAL.
*
AB( JI, 1 ) = C( JI )
ELSE
KLNEW = KLNEW + 1
IF( KLNEW.LE.MMAX ) THEN
*
* EIGENVALUE IN BOTH INTERVALS -- ADD UPPER TO
* QUEUE.
*
AB( KLNEW, 2 ) = AB( JI, 2 )
NAB( KLNEW, 2 ) = NAB( JI, 2 )
AB( KLNEW, 1 ) = C( JI )
NAB( KLNEW, 1 ) = IWORK( JI )
AB( JI, 2 ) = C( JI )
NAB( JI, 2 ) = IWORK( JI )
ELSE
INFO = MMAX + 1
END IF
END IF
70 CONTINUE
IF( INFO.NE.0 )
$ RETURN
KL = KLNEW
ELSE
*
* IJOB=3: BINARY SEARCH. KEEP ONLY THE INTERVAL CONTAINING
* W S.T. N(W) = NVAL
*
DO 80 JI = KF, KL
IF( IWORK( JI ).LE.NVAL( JI ) ) THEN
AB( JI, 1 ) = C( JI )
NAB( JI, 1 ) = IWORK( JI )
END IF
IF( IWORK( JI ).GE.NVAL( JI ) ) THEN
AB( JI, 2 ) = C( JI )
NAB( JI, 2 ) = IWORK( JI )
END IF
80 CONTINUE
END IF
*
ELSE
*
* END OF PARALLEL VERSION OF THE LOOP
*
* BEGIN OF SERIAL VERSION OF THE LOOP
*
KLNEW = KL
DO 100 JI = KF, KL
*
* COMPUTE N(W), THE NUMBER OF EIGENVALUES LESS THAN W
*
TMP1 = C( JI )
TMP2 = D( 1 ) - TMP1
ITMP1 = 0
IF( TMP2.LE.PIVMIN ) THEN
ITMP1 = 1
TMP2 = MIN( TMP2, -PIVMIN )
END IF
*
* A SERIES OF COMPILER DIRECTIVES TO DEFEAT VECTORIZATION
* FOR THE NEXT LOOP
*
*$PL$ CMCHAR=' '
CDIR$ NEXTSCALAR
C$DIR SCALAR
CDIR$ NEXT SCALAR
CVD$L NOVECTOR
CDEC$ NOVECTOR
CVD$ NOVECTOR
*VDIR NOVECTOR
*VOCL LOOP,SCALAR
CIBM PREFER SCALAR
*$PL$ CMCHAR='*'
*
DO 90 J = 2, N
TMP2 = D( J ) - E2( J-1 ) / TMP2 - TMP1
IF( TMP2.LE.PIVMIN ) THEN
ITMP1 = ITMP1 + 1
TMP2 = MIN( TMP2, -PIVMIN )
END IF
90 CONTINUE
*
IF( IJOB.LE.2 ) THEN
*
* IJOB=2: CHOOSE ALL INTERVALS CONTAINING EIGENVALUES.
*
* INSURE THAT N(W) IS MONOTONE
*
ITMP1 = MIN( NAB( JI, 2 ),
$ MAX( NAB( JI, 1 ), ITMP1 ) )
*
* UPDATE THE QUEUE -- ADD INTERVALS IF BOTH HALVES
* CONTAIN EIGENVALUES.
*
IF( ITMP1.EQ.NAB( JI, 2 ) ) THEN
*
* NO EIGENVALUE IN THE UPPER INTERVAL:
* JUST USE THE LOWER INTERVAL.
*
AB( JI, 2 ) = TMP1
*
ELSE IF( ITMP1.EQ.NAB( JI, 1 ) ) THEN
*
* NO EIGENVALUE IN THE LOWER INTERVAL:
* JUST USE THE UPPER INTERVAL.
*
AB( JI, 1 ) = TMP1
ELSE IF( KLNEW.LT.MMAX ) THEN
*
* EIGENVALUE IN BOTH INTERVALS -- ADD UPPER TO QUEUE.
*
KLNEW = KLNEW + 1
AB( KLNEW, 2 ) = AB( JI, 2 )
NAB( KLNEW, 2 ) = NAB( JI, 2 )
AB( KLNEW, 1 ) = TMP1
NAB( KLNEW, 1 ) = ITMP1
AB( JI, 2 ) = TMP1
NAB( JI, 2 ) = ITMP1
ELSE
INFO = MMAX + 1
RETURN
END IF
ELSE
*
* IJOB=3: BINARY SEARCH. KEEP ONLY THE INTERVAL
* CONTAINING W S.T. N(W) = NVAL
*
IF( ITMP1.LE.NVAL( JI ) ) THEN
AB( JI, 1 ) = TMP1
NAB( JI, 1 ) = ITMP1
END IF
IF( ITMP1.GE.NVAL( JI ) ) THEN
AB( JI, 2 ) = TMP1
NAB( JI, 2 ) = ITMP1
END IF
END IF
100 CONTINUE
KL = KLNEW
*
* END OF SERIAL VERSION OF THE LOOP
*
END IF
*
* CHECK FOR CONVERGENCE
*
KFNEW = KF
DO 110 JI = KF, KL
TMP1 = ABS( AB( JI, 2 )-AB( JI, 1 ) )
TMP2 = MAX( ABS( AB( JI, 2 ) ), ABS( AB( JI, 1 ) ) )
IF( TMP1.LT.MAX( ABSTOL, PIVMIN, RELTOL*TMP2 ) .OR.
$ NAB( JI, 1 ).GE.NAB( JI, 2 ) ) THEN
*
* CONVERGED -- SWAP WITH POSITION KFNEW,
* THEN INCREMENT KFNEW
*
IF( JI.GT.KFNEW ) THEN
TMP1 = AB( JI, 1 )
TMP2 = AB( JI, 2 )
ITMP1 = NAB( JI, 1 )
ITMP2 = NAB( JI, 2 )
AB( JI, 1 ) = AB( KFNEW, 1 )
AB( JI, 2 ) = AB( KFNEW, 2 )
NAB( JI, 1 ) = NAB( KFNEW, 1 )
NAB( JI, 2 ) = NAB( KFNEW, 2 )
AB( KFNEW, 1 ) = TMP1
AB( KFNEW, 2 ) = TMP2
NAB( KFNEW, 1 ) = ITMP1
NAB( KFNEW, 2 ) = ITMP2
IF( IJOB.EQ.3 ) THEN
ITMP1 = NVAL( JI )
NVAL( JI ) = NVAL( KFNEW )
NVAL( KFNEW ) = ITMP1
END IF
END IF
KFNEW = KFNEW + 1
END IF
110 CONTINUE
KF = KFNEW
*
* CHOOSE MIDPOINTS
*
DO 120 JI = KF, KL
C( JI ) = HALF*( AB( JI, 1 )+AB( JI, 2 ) )
120 CONTINUE
*
* IF NO MORE INTERVALS TO REFINE, QUIT.
*
IF( KF.GT.KL )
$ GO TO 140
130 CONTINUE
*
* CONVERGED
*
140 CONTINUE
INFO = MAX( KL+1-KF, 0 )
MOUT = KL
*
RETURN
*
* END OF DLAEBZ
*
END
CUT HERE............
CAT > DSTEQR.F <<'CUT HERE............'
SUBROUTINE DSTEQR( COMPZ, N, D, E, Z, LDZ, WORK, INFO )
*
* -- LAPACK ROUTINE (VERSION 1.1) --
* UNIV. OF TENNESSEE, UNIV. OF CALIFORNIA BERKELEY, NAG LTD.,
* COURANT INSTITUTE, ARGONNE NATIONAL LAB, AND RICE UNIVERSITY
* MARCH 31, 1993
*
* .. SCALAR ARGUMENTS ..
CHARACTER COMPZ
INTEGER INFO, LDZ, N
* ..
* .. ARRAY ARGUMENTS ..
DOUBLE PRECISION D( * ), E( * ), WORK( * ), Z( LDZ, * )
* ..
*
* PURPOSE
* =======
*
* DSTEQR COMPUTES ALL EIGENVALUES AND, OPTIONALLY, EIGENVECTORS OF A
* SYMMETRIC TRIDIAGONAL MATRIX USING THE IMPLICIT QL OR QR METHOD.
* THE EIGENVECTORS OF A FULL OR BAND SYMMETRIC MATRIX CAN ALSO BE FOUND
* IF DSYTRD OR DSPTRD OR DSBTRD HAS BEEN USED TO REDUCE THIS MATRIX TO
* TRIDIAGONAL FORM.
*
* ARGUMENTS
* =========
*
* COMPZ (INPUT) CHARACTER*1
* = 'N': COMPUTE EIGENVALUES ONLY.
* = 'V': COMPUTE EIGENVALUES AND EIGENVECTORS OF THE ORIGINAL
* SYMMETRIC MATRIX. ON ENTRY, Z MUST CONTAIN THE
* ORTHOGONAL MATRIX USED TO REDUCE THE ORIGINAL MATRIX
* TO TRIDIAGONAL FORM.
* = 'I': COMPUTE EIGENVALUES AND EIGENVECTORS OF THE
* TRIDIAGONAL MATRIX. Z IS INITIALIZED TO THE IDENTITY
* MATRIX.
*
* N (INPUT) INTEGER
* THE ORDER OF THE MATRIX. N >= 0.
*
* D (INPUT/OUTPUT) DOUBLE PRECISION ARRAY, DIMENSION (N)
* ON ENTRY, THE DIAGONAL ELEMENTS OF THE TRIDIAGONAL MATRIX.
* ON EXIT, IF INFO = 0, THE EIGENVALUES IN ASCENDING ORDER.
*
* E (INPUT/OUTPUT) DOUBLE PRECISION ARRAY, DIMENSION (N-1)
* ON ENTRY, THE (N-1) SUBDIAGONAL ELEMENTS OF THE TRIDIAGONAL
* MATRIX.
* ON EXIT, E HAS BEEN DESTROYED.
*
* Z (INPUT/OUTPUT) DOUBLE PRECISION ARRAY, DIMENSION (LDZ, N)
* ON ENTRY, IF COMPZ = 'V', THEN Z CONTAINS THE ORTHOGONAL
* MATRIX USED IN THE REDUCTION TO TRIDIAGONAL FORM.
* ON EXIT, IF COMPZ = 'V', Z CONTAINS THE ORTHONORMAL
* EIGENVECTORS OF THE ORIGINAL SYMMETRIC MATRIX, AND IF
* COMPZ = 'I', Z CONTAINS THE ORTHONORMAL EIGENVECTORS OF
* THE SYMMETRIC TRIDIAGONAL MATRIX. IF AN ERROR EXIT IS
* MADE, Z CONTAINS THE EIGENVECTORS ASSOCIATED WITH THE
* STORED EIGENVALUES.
* IF COMPZ = 'N', THEN Z IS NOT REFERENCED.
*
* LDZ (INPUT) INTEGER
* THE LEADING DIMENSION OF THE ARRAY Z. LDZ >= 1, AND IF
* EIGENVECTORS ARE DESIRED, THEN LDZ >= MAX(1,N).
*
* WORK (WORKSPACE) DOUBLE PRECISION ARRAY, DIMENSION (MAX(1,2*N-2))
* IF COMPZ = 'N', THEN WORK IS NOT REFERENCED.
*
* INFO (OUTPUT) INTEGER
* = 0: SUCCESSFUL EXIT
* < 0: IF INFO = -I, THE I-TH ARGUMENT HAD AN ILLEGAL VALUE
* > 0: THE ALGORITHM HAS FAILED TO FIND ALL THE EIGENVALUES IN
* A TOTAL OF 30*N ITERATIONS; IF INFO = I, THEN I
* ELEMENTS OF E HAVE NOT CONVERGED TO ZERO; ON EXIT, D
* AND E CONTAIN THE ELEMENTS OF A SYMMETRIC TRIDIAGONAL
* MATRIX WHICH IS ORTHOGONALLY SIMILAR TO THE ORIGINAL
* MATRIX.
*
* =====================================================================
*
* .. PARAMETERS ..
DOUBLE PRECISION ZERO, ONE, TWO
PARAMETER ( ZERO = 0.0D0, ONE = 1.0D0, TWO = 2.0D0 )
INTEGER MAXIT
PARAMETER ( MAXIT = 30 )
* ..
* .. LOCAL SCALARS ..
INTEGER I, ICOMPZ, II, J, JTOT, K, L, L1, LEND, LENDM1,
$ LENDP1, LM1, M, MM, MM1, NM1, NMAXIT
DOUBLE PRECISION B, C, EPS, F, G, P, R, RT1, RT2, S, TST
* ..
* .. EXTERNAL FUNCTIONS ..
LOGICAL LSAME
DOUBLE PRECISION DLAMCH, DLAPY2
EXTERNAL LSAME, DLAMCH, DLAPY2
* ..
* .. EXTERNAL SUBROUTINES ..
EXTERNAL DLAE2, DLAEV2, DLARTG, DLASR, DLAZRO, DSWAP,
$ XERBLA
* ..
* .. INTRINSIC FUNCTIONS ..
INTRINSIC ABS, MAX, SIGN
* ..
* .. EXECUTABLE STATEMENTS ..
*
* TEST THE INPUT PARAMETERS.
*
INFO = 0
*
IF( LSAME( COMPZ, 'N' ) ) THEN
ICOMPZ = 0
ELSE IF( LSAME( COMPZ, 'V' ) ) THEN
ICOMPZ = 1
ELSE IF( LSAME( COMPZ, 'I' ) ) THEN
ICOMPZ = 2
ELSE
ICOMPZ = -1
END IF
IF( ICOMPZ.LT.0 ) THEN
INFO = -1
ELSE IF( N.LT.0 ) THEN
INFO = -2
ELSE IF( ( LDZ.LT.1 ) .OR. ( ICOMPZ.GT.0 .AND. LDZ.LT.MAX( 1,
$ N ) ) ) THEN
INFO = -6
END IF
IF( INFO.NE.0 ) THEN
CALL XERBLA( 'DSTEQR', -INFO )
RETURN
END IF
*
* QUICK RETURN IF POSSIBLE
*
IF( N.EQ.0 )
$ RETURN
*
IF( N.EQ.1 ) THEN
IF( ICOMPZ.GT.0 )
$ Z( 1, 1 ) = ONE
RETURN
END IF
*
* DETERMINE THE UNIT ROUNDOFF FOR THIS ENVIRONMENT.
*
EPS = DLAMCH( 'E' )
*
* COMPUTE THE EIGENVALUES AND EIGENVECTORS OF THE TRIDIAGONAL
* MATRIX.
*
IF( ICOMPZ.EQ.2 )
$ CALL DLAZRO( N, N, ZERO, ONE, Z, LDZ )
*
NMAXIT = N*MAXIT
JTOT = 0
*
* DETERMINE WHERE THE MATRIX SPLITS AND CHOOSE QL OR QR ITERATION
* FOR EACH BLOCK, ACCORDING TO WHETHER TOP OR BOTTOM DIAGONAL
* ELEMENT IS SMALLER.
*
L1 = 1
NM1 = N - 1
*
10 CONTINUE
IF( L1.GT.N )
$ GO TO 160
IF( L1.GT.1 )
$ E( L1-1 ) = ZERO
IF( L1.LE.NM1 ) THEN
DO 20 M = L1, NM1
TST = ABS( E( M ) )
IF( TST.LE.EPS*( ABS( D( M ) )+ABS( D( M+1 ) ) ) )
$ GO TO 30
20 CONTINUE
END IF
M = N
*
30 CONTINUE
L = L1
LEND = M
IF( ABS( D( LEND ) ).LT.ABS( D( L ) ) ) THEN
L = LEND
LEND = L1
END IF
L1 = M + 1
*
IF( LEND.GE.L ) THEN
*
* QL ITERATION
*
* LOOK FOR SMALL SUBDIAGONAL ELEMENT.
*
40 CONTINUE
IF( L.NE.LEND ) THEN
LENDM1 = LEND - 1
DO 50 M = L, LENDM1
TST = ABS( E( M ) )
IF( TST.LE.EPS*( ABS( D( M ) )+ABS( D( M+1 ) ) ) )
$ GO TO 60
50 CONTINUE
END IF
*
M = LEND
*
60 CONTINUE
IF( M.LT.LEND )
$ E( M ) = ZERO
P = D( L )
IF( M.EQ.L )
$ GO TO 80
*
* IF REMAINING MATRIX IS 2-BY-2, USE DLAE2 OR DLAEV2
* TO COMPUTE ITS EIGENSYSTEM.
*
IF( M.EQ.L+1 ) THEN
IF( ICOMPZ.GT.0 ) THEN
CALL DLAEV2( D( L ), E( L ), D( L+1 ), RT1, RT2, C, S )
WORK( L ) = C
WORK( N-1+L ) = S
CALL DLASR( 'R', 'V', 'B', N, 2, WORK( L ),
$ WORK( N-1+L ), Z( 1, L ), LDZ )
ELSE
CALL DLAE2( D( L ), E( L ), D( L+1 ), RT1, RT2 )
END IF
D( L ) = RT1
D( L+1 ) = RT2
E( L ) = ZERO
L = L + 2
IF( L.LE.LEND )
$ GO TO 40
GO TO 10
END IF
*
IF( JTOT.EQ.NMAXIT )
$ GO TO 140
JTOT = JTOT + 1
*
* FORM SHIFT.
*
G = ( D( L+1 )-P ) / ( TWO*E( L ) )
R = DLAPY2( G, ONE )
G = D( M ) - P + ( E( L ) / ( G+SIGN( R, G ) ) )
*
S = ONE
C = ONE
P = ZERO
*
* INNER LOOP
*
MM1 = M - 1
DO 70 I = MM1, L, -1
F = S*E( I )
B = C*E( I )
CALL DLARTG( G, F, C, S, R )
IF( I.NE.M-1 )
$ E( I+1 ) = R
G = D( I+1 ) - P
R = ( D( I )-G )*S + TWO*C*B
P = S*R
D( I+1 ) = G + P
G = C*R - B
*
* IF EIGENVECTORS ARE DESIRED, THEN SAVE ROTATIONS.
*
IF( ICOMPZ.GT.0 ) THEN
WORK( I ) = C
WORK( N-1+I ) = -S
END IF
*
70 CONTINUE
*
* IF EIGENVECTORS ARE DESIRED, THEN APPLY SAVED ROTATIONS.
*
IF( ICOMPZ.GT.0 ) THEN
MM = M - L + 1
CALL DLASR( 'R', 'V', 'B', N, MM, WORK( L ), WORK( N-1+L ),
$ Z( 1, L ), LDZ )
END IF
*
D( L ) = D( L ) - P
E( L ) = G
GO TO 40
*
* EIGENVALUE FOUND.
*
80 CONTINUE
D( L ) = P
*
L = L + 1
IF( L.LE.LEND )
$ GO TO 40
GO TO 10
*
ELSE
*
* QR ITERATION
*
* LOOK FOR SMALL SUPERDIAGONAL ELEMENT.
*
90 CONTINUE
IF( L.NE.LEND ) THEN
LENDP1 = LEND + 1
DO 100 M = L, LENDP1, -1
TST = ABS( E( M-1 ) )
IF( TST.LE.EPS*( ABS( D( M ) )+ABS( D( M-1 ) ) ) )
$ GO TO 110
100 CONTINUE
END IF
*
M = LEND
*
110 CONTINUE
IF( M.GT.LEND )
$ E( M-1 ) = ZERO
P = D( L )
IF( M.EQ.L )
$ GO TO 130
*
* IF REMAINING MATRIX IS 2-BY-2, USE DLAE2 OR DLAEV2
* TO COMPUTE ITS EIGENSYSTEM.
*
IF( M.EQ.L-1 ) THEN
IF( ICOMPZ.GT.0 ) THEN
CALL DLAEV2( D( L-1 ), E( L-1 ), D( L ), RT1, RT2, C, S )
WORK( M ) = C
WORK( N-1+M ) = S
CALL DLASR( 'R', 'V', 'F', N, 2, WORK( M ),
$ WORK( N-1+M ), Z( 1, L-1 ), LDZ )
ELSE
CALL DLAE2( D( L-1 ), E( L-1 ), D( L ), RT1, RT2 )
END IF
D( L-1 ) = RT1
D( L ) = RT2
E( L-1 ) = ZERO
L = L - 2
IF( L.GE.LEND )
$ GO TO 90
GO TO 10
END IF
*
IF( JTOT.EQ.NMAXIT )
$ GO TO 140
JTOT = JTOT + 1
*
* FORM SHIFT.
*
G = ( D( L-1 )-P ) / ( TWO*E( L-1 ) )
R = DLAPY2( G, ONE )
G = D( M ) - P + ( E( L-1 ) / ( G+SIGN( R, G ) ) )
*
S = ONE
C = ONE
P = ZERO
*
* INNER LOOP
*
LM1 = L - 1
DO 120 I = M, LM1
F = S*E( I )
B = C*E( I )
CALL DLARTG( G, F, C, S, R )
IF( I.NE.M )
$ E( I-1 ) = R
G = D( I ) - P
R = ( D( I+1 )-G )*S + TWO*C*B
P = S*R
D( I ) = G + P
G = C*R - B
*
* IF EIGENVECTORS ARE DESIRED, THEN SAVE ROTATIONS.
*
IF( ICOMPZ.GT.0 ) THEN
WORK( I ) = C
WORK( N-1+I ) = S
END IF
*
120 CONTINUE
*
* IF EIGENVECTORS ARE DESIRED, THEN APPLY SAVED ROTATIONS.
*
IF( ICOMPZ.GT.0 ) THEN
MM = L - M + 1
CALL DLASR( 'R', 'V', 'F', N, MM, WORK( M ), WORK( N-1+M ),
$ Z( 1, M ), LDZ )
END IF
*
D( L ) = D( L ) - P
E( LM1 ) = G
GO TO 90
*
* EIGENVALUE FOUND.
*
130 CONTINUE
D( L ) = P
*
L = L - 1
IF( L.GE.LEND )
$ GO TO 90
GO TO 10
*
END IF
*
* SET ERROR -- NO CONVERGENCE TO AN EIGENVALUE AFTER A TOTAL
* OF N*MAXIT ITERATIONS.
*
140 CONTINUE
DO 150 I = 1, N - 1
IF( E( I ).NE.ZERO )
$ INFO = INFO + 1
150 CONTINUE
RETURN
*
* ORDER EIGENVALUES AND EIGENVECTORS.
*
160 CONTINUE
DO 180 II = 2, N
I = II - 1
K = I
P = D( I )
DO 170 J = II, N
IF( D( J ).LT.P ) THEN
K = J
P = D( J )
END IF
170 CONTINUE
IF( K.NE.I ) THEN
D( K ) = D( I )
D( I ) = P
IF( ICOMPZ.GT.0 )
$ CALL DSWAP( N, Z( 1, I ), 1, Z( 1, K ), 1 )
END IF
180 CONTINUE
*
RETURN
*
* END OF DSTEQR
*
END
CUT HERE............
CAT > DLARTG.F <<'CUT HERE............'
SUBROUTINE DLARTG( F, G, CS, SN, R )
*
* -- LAPACK AUXILIARY ROUTINE (VERSION 1.1) --
* UNIV. OF TENNESSEE, UNIV. OF CALIFORNIA BERKELEY, NAG LTD.,
* COURANT INSTITUTE, ARGONNE NATIONAL LAB, AND RICE UNIVERSITY
* OCTOBER 31, 1992
*
* .. SCALAR ARGUMENTS ..
DOUBLE PRECISION CS, F, G, R, SN
* ..
*
* PURPOSE
* =======
*
* DLARTG GENERATE A PLANE ROTATION SO THAT
*
* [ CS SN ] . [ F ] = [ R ] WHERE CS**2 + SN**2 = 1.
* [ -SN CS ] [ G ] [ 0 ]
*
* THIS IS A FASTER VERSION OF THE BLAS1 ROUTINE DROTG, EXCEPT FOR
* THE FOLLOWING DIFFERENCES:
* F AND G ARE UNCHANGED ON RETURN.
* IF G=0, THEN CS=1 AND SN=0.
* IF F=0 AND (G .NE. 0), THEN CS=0 AND SN=1 WITHOUT DOING ANY
* FLOATING POINT OPERATIONS (SAVES WORK IN DBDSQR WHEN
* THERE ARE ZEROS ON THE DIAGONAL).
*
* ARGUMENTS
* =========
*
* F (INPUT) DOUBLE PRECISION
* THE FIRST COMPONENT OF VECTOR TO BE ROTATED.
*
* G (INPUT) DOUBLE PRECISION
* THE SECOND COMPONENT OF VECTOR TO BE ROTATED.
*
* CS (OUTPUT) DOUBLE PRECISION
* THE COSINE OF THE ROTATION.
*
* SN (OUTPUT) DOUBLE PRECISION
* THE SINE OF THE ROTATION.
*
* R (OUTPUT) DOUBLE PRECISION
* THE NONZERO COMPONENT OF THE ROTATED VECTOR.
*
* =====================================================================
*
* .. PARAMETERS ..
DOUBLE PRECISION ZERO
PARAMETER ( ZERO = 0.0D0 )
DOUBLE PRECISION ONE
PARAMETER ( ONE = 1.0D0 )
* ..
* .. LOCAL SCALARS ..
DOUBLE PRECISION T, TT
* ..
* .. INTRINSIC FUNCTIONS ..
INTRINSIC ABS, SQRT
* ..
* .. EXECUTABLE STATEMENTS ..
*
IF( G.EQ.ZERO ) THEN
CS = ONE
SN = ZERO
R = F
ELSE IF( F.EQ.ZERO ) THEN
CS = ZERO
SN = ONE
R = G
ELSE
IF( ABS( F ).GT.ABS( G ) ) THEN
T = G / F
TT = SQRT( ONE+T*T )
CS = ONE / TT
SN = T*CS
R = F*TT
ELSE
T = F / G
TT = SQRT( ONE+T*T )
SN = ONE / TT
CS = T*SN
R = G*TT
END IF
END IF
RETURN
*
* END OF DLARTG
*
END
CUT HERE............
CAT > DLASR.F <<'CUT HERE............'
SUBROUTINE DLASR( SIDE, PIVOT, DIRECT, M, N, C, S, A, LDA )
*
* -- LAPACK AUXILIARY ROUTINE (VERSION 1.1) --
* UNIV. OF TENNESSEE, UNIV. OF CALIFORNIA BERKELEY, NAG LTD.,
* COURANT INSTITUTE, ARGONNE NATIONAL LAB, AND RICE UNIVERSITY
* OCTOBER 31, 1992
*
* .. SCALAR ARGUMENTS ..
CHARACTER DIRECT, PIVOT, SIDE
INTEGER LDA, M, N
* ..
* .. ARRAY ARGUMENTS ..
DOUBLE PRECISION A( LDA, * ), C( * ), S( * )
* ..
*
* PURPOSE
* =======
*
* DLASR PERFORMS THE TRANSFORMATION
*
* A := P*A, WHEN SIDE = 'L' OR 'L' ( LEFT-HAND SIDE )
*
* A := A*P', WHEN SIDE = 'R' OR 'R' ( RIGHT-HAND SIDE )
*
* WHERE A IS AN M BY N REAL MATRIX AND P IS AN ORTHOGONAL MATRIX,
* CONSISTING OF A SEQUENCE OF PLANE ROTATIONS DETERMINED BY THE
* PARAMETERS PIVOT AND DIRECT AS FOLLOWS ( Z = M WHEN SIDE = 'L' OR 'L'
* AND Z = N WHEN SIDE = 'R' OR 'R' ):
*
* WHEN DIRECT = 'F' OR 'F' ( FORWARD SEQUENCE ) THEN
*
* P = P( Z - 1 )*...*P( 2 )*P( 1 ),
*
* AND WHEN DIRECT = 'B' OR 'B' ( BACKWARD SEQUENCE ) THEN
*
* P = P( 1 )*P( 2 )*...*P( Z - 1 ),
*
* WHERE P( K ) IS A PLANE ROTATION MATRIX FOR THE FOLLOWING PLANES:
*
* WHEN PIVOT = 'V' OR 'V' ( VARIABLE PIVOT ),
* THE PLANE ( K, K + 1 )
*
* WHEN PIVOT = 'T' OR 'T' ( TOP PIVOT ),
* THE PLANE ( 1, K + 1 )
*
* WHEN PIVOT = 'B' OR 'B' ( BOTTOM PIVOT ),
* THE PLANE ( K, Z )
*
* C( K ) AND S( K ) MUST CONTAIN THE COSINE AND SINE THAT DEFINE THE
* MATRIX P( K ). THE TWO BY TWO PLANE ROTATION PART OF THE MATRIX
* P( K ), R( K ), IS ASSUMED TO BE OF THE FORM
*
* R( K ) = ( C( K ) S( K ) ).
* ( -S( K ) C( K ) )
*
* THIS VERSION VECTORISES ACROSS ROWS OF THE ARRAY A WHEN SIDE = 'L'.
*
* ARGUMENTS
* =========
*
* SIDE (INPUT) CHARACTER*1
* SPECIFIES WHETHER THE PLANE ROTATION MATRIX P IS APPLIED TO
* A ON THE LEFT OR THE RIGHT.
* = 'L': LEFT, COMPUTE A := P*A
* = 'R': RIGHT, COMPUTE A:= A*P'
*
* DIRECT (INPUT) CHARACTER*1
* SPECIFIES WHETHER P IS A FORWARD OR BACKWARD SEQUENCE OF
* PLANE ROTATIONS.
* = 'F': FORWARD, P = P( Z - 1 )*...*P( 2 )*P( 1 )
* = 'B': BACKWARD, P = P( 1 )*P( 2 )*...*P( Z - 1 )
*
* PIVOT (INPUT) CHARACTER*1
* SPECIFIES THE PLANE FOR WHICH P(K) IS A PLANE ROTATION
* MATRIX.
* = 'V': VARIABLE PIVOT, THE PLANE (K,K+1)
* = 'T': TOP PIVOT, THE PLANE (1,K+1)
* = 'B': BOTTOM PIVOT, THE PLANE (K,Z)
*
* M (INPUT) INTEGER
* THE NUMBER OF ROWS OF THE MATRIX A. IF M <= 1, AN IMMEDIATE
* RETURN IS EFFECTED.
*
* N (INPUT) INTEGER
* THE NUMBER OF COLUMNS OF THE MATRIX A. IF N <= 1, AN
* IMMEDIATE RETURN IS EFFECTED.
*
* C, S (INPUT) DOUBLE PRECISION ARRAYS, DIMENSION
* (M-1) IF SIDE = 'L'
* (N-1) IF SIDE = 'R'
* C(K) AND S(K) CONTAIN THE COSINE AND SINE THAT DEFINE THE
* MATRIX P(K). THE TWO BY TWO PLANE ROTATION PART OF THE
* MATRIX P(K), R(K), IS ASSUMED TO BE OF THE FORM
* R( K ) = ( C( K ) S( K ) ).
* ( -S( K ) C( K ) )
*
* A (INPUT/OUTPUT) DOUBLE PRECISION ARRAY, DIMENSION (LDA,N)
* THE M BY N MATRIX A. ON EXIT, A IS OVERWRITTEN BY P*A IF
* SIDE = 'R' OR BY A*P' IF SIDE = 'L'.
*
* LDA (INPUT) INTEGER
* THE LEADING DIMENSION OF THE ARRAY A. LDA >= MAX(1,M).
*
* =====================================================================
*
* .. PARAMETERS ..
DOUBLE PRECISION ONE, ZERO
PARAMETER ( ONE = 1.0D+0, ZERO = 0.0D+0 )
* ..
* .. LOCAL SCALARS ..
INTEGER I, INFO, J
DOUBLE PRECISION CTEMP, STEMP, TEMP
* ..
* .. EXTERNAL FUNCTIONS ..
LOGICAL LSAME
EXTERNAL LSAME
* ..
* .. EXTERNAL SUBROUTINES ..
EXTERNAL XERBLA
* ..
* .. INTRINSIC FUNCTIONS ..
INTRINSIC MAX
* ..
* .. EXECUTABLE STATEMENTS ..
*
* TEST THE INPUT PARAMETERS
*
INFO = 0
IF( .NOT.( LSAME( SIDE, 'L' ) .OR. LSAME( SIDE, 'R' ) ) ) THEN
INFO = 1
ELSE IF( .NOT.( LSAME( PIVOT, 'V' ) .OR. LSAME( PIVOT,
$ 'T' ) .OR. LSAME( PIVOT, 'B' ) ) ) THEN
INFO = 2
ELSE IF( .NOT.( LSAME( DIRECT, 'F' ) .OR. LSAME( DIRECT, 'B' ) ) )
$ THEN
INFO = 3
ELSE IF( M.LT.0 ) THEN
INFO = 4
ELSE IF( N.LT.0 ) THEN
INFO = 5
ELSE IF( LDA.LT.MAX( 1, M ) ) THEN
INFO = 9
END IF
IF( INFO.NE.0 ) THEN
CALL XERBLA( 'DLASR ', INFO )
RETURN
END IF
*
* QUICK RETURN IF POSSIBLE
*
IF( ( M.EQ.0 ) .OR. ( N.EQ.0 ) )
$ RETURN
IF( LSAME( SIDE, 'L' ) ) THEN
*
* FORM P * A
*
IF( LSAME( PIVOT, 'V' ) ) THEN
IF( LSAME( DIRECT, 'F' ) ) THEN
DO 20 J = 1, M - 1
CTEMP = C( J )
STEMP = S( J )
IF( ( CTEMP.NE.ONE ) .OR. ( STEMP.NE.ZERO ) ) THEN
DO 10 I = 1, N
TEMP = A( J+1, I )
A( J+1, I ) = CTEMP*TEMP - STEMP*A( J, I )
A( J, I ) = STEMP*TEMP + CTEMP*A( J, I )
10 CONTINUE
END IF
20 CONTINUE
ELSE IF( LSAME( DIRECT, 'B' ) ) THEN
DO 40 J = M - 1, 1, -1
CTEMP = C( J )
STEMP = S( J )
IF( ( CTEMP.NE.ONE ) .OR. ( STEMP.NE.ZERO ) ) THEN
DO 30 I = 1, N
TEMP = A( J+1, I )
A( J+1, I ) = CTEMP*TEMP - STEMP*A( J, I )
A( J, I ) = STEMP*TEMP + CTEMP*A( J, I )
30 CONTINUE
END IF
40 CONTINUE
END IF
ELSE IF( LSAME( PIVOT, 'T' ) ) THEN
IF( LSAME( DIRECT, 'F' ) ) THEN
DO 60 J = 2, M
CTEMP = C( J-1 )
STEMP = S( J-1 )
IF( ( CTEMP.NE.ONE ) .OR. ( STEMP.NE.ZERO ) ) THEN
DO 50 I = 1, N
TEMP = A( J, I )
A( J, I ) = CTEMP*TEMP - STEMP*A( 1, I )
A( 1, I ) = STEMP*TEMP + CTEMP*A( 1, I )
50 CONTINUE
END IF
60 CONTINUE
ELSE IF( LSAME( DIRECT, 'B' ) ) THEN
DO 80 J = M, 2, -1
CTEMP = C( J-1 )
STEMP = S( J-1 )
IF( ( CTEMP.NE.ONE ) .OR. ( STEMP.NE.ZERO ) ) THEN
DO 70 I = 1, N
TEMP = A( J, I )
A( J, I ) = CTEMP*TEMP - STEMP*A( 1, I )
A( 1, I ) = STEMP*TEMP + CTEMP*A( 1, I )
70 CONTINUE
END IF
80 CONTINUE
END IF
ELSE IF( LSAME( PIVOT, 'B' ) ) THEN
IF( LSAME( DIRECT, 'F' ) ) THEN
DO 100 J = 1, M - 1
CTEMP = C( J )
STEMP = S( J )
IF( ( CTEMP.NE.ONE ) .OR. ( STEMP.NE.ZERO ) ) THEN
DO 90 I = 1, N
TEMP = A( J, I )
A( J, I ) = STEMP*A( M, I ) + CTEMP*TEMP
A( M, I ) = CTEMP*A( M, I ) - STEMP*TEMP
90 CONTINUE
END IF
100 CONTINUE
ELSE IF( LSAME( DIRECT, 'B' ) ) THEN
DO 120 J = M - 1, 1, -1
CTEMP = C( J )
STEMP = S( J )
IF( ( CTEMP.NE.ONE ) .OR. ( STEMP.NE.ZERO ) ) THEN
DO 110 I = 1, N
TEMP = A( J, I )
A( J, I ) = STEMP*A( M, I ) + CTEMP*TEMP
A( M, I ) = CTEMP*A( M, I ) - STEMP*TEMP
110 CONTINUE
END IF
120 CONTINUE
END IF
END IF
ELSE IF( LSAME( SIDE, 'R' ) ) THEN
*
* FORM A * P'
*
IF( LSAME( PIVOT, 'V' ) ) THEN
IF( LSAME( DIRECT, 'F' ) ) THEN
DO 140 J = 1, N - 1
CTEMP = C( J )
STEMP = S( J )
IF( ( CTEMP.NE.ONE ) .OR. ( STEMP.NE.ZERO ) ) THEN
DO 130 I = 1, M
TEMP = A( I, J+1 )
A( I, J+1 ) = CTEMP*TEMP - STEMP*A( I, J )
A( I, J ) = STEMP*TEMP + CTEMP*A( I, J )
130 CONTINUE
END IF
140 CONTINUE
ELSE IF( LSAME( DIRECT, 'B' ) ) THEN
DO 160 J = N - 1, 1, -1
CTEMP = C( J )
STEMP = S( J )
IF( ( CTEMP.NE.ONE ) .OR. ( STEMP.NE.ZERO ) ) THEN
DO 150 I = 1, M
TEMP = A( I, J+1 )
A( I, J+1 ) = CTEMP*TEMP - STEMP*A( I, J )
A( I, J ) = STEMP*TEMP + CTEMP*A( I, J )
150 CONTINUE
END IF
160 CONTINUE
END IF
ELSE IF( LSAME( PIVOT, 'T' ) ) THEN
IF( LSAME( DIRECT, 'F' ) ) THEN
DO 180 J = 2, N
CTEMP = C( J-1 )
STEMP = S( J-1 )
IF( ( CTEMP.NE.ONE ) .OR. ( STEMP.NE.ZERO ) ) THEN
DO 170 I = 1, M
TEMP = A( I, J )
A( I, J ) = CTEMP*TEMP - STEMP*A( I, 1 )
A( I, 1 ) = STEMP*TEMP + CTEMP*A( I, 1 )
170 CONTINUE
END IF
180 CONTINUE
ELSE IF( LSAME( DIRECT, 'B' ) ) THEN
DO 200 J = N, 2, -1
CTEMP = C( J-1 )
STEMP = S( J-1 )
IF( ( CTEMP.NE.ONE ) .OR. ( STEMP.NE.ZERO ) ) THEN
DO 190 I = 1, M
TEMP = A( I, J )
A( I, J ) = CTEMP*TEMP - STEMP*A( I, 1 )
A( I, 1 ) = STEMP*TEMP + CTEMP*A( I, 1 )
190 CONTINUE
END IF
200 CONTINUE
END IF
ELSE IF( LSAME( PIVOT, 'B' ) ) THEN
IF( LSAME( DIRECT, 'F' ) ) THEN
DO 220 J = 1, N - 1
CTEMP = C( J )
STEMP = S( J )
IF( ( CTEMP.NE.ONE ) .OR. ( STEMP.NE.ZERO ) ) THEN
DO 210 I = 1, M
TEMP = A( I, J )
A( I, J ) = STEMP*A( I, N ) + CTEMP*TEMP
A( I, N ) = CTEMP*A( I, N ) - STEMP*TEMP
210 CONTINUE
END IF
220 CONTINUE
ELSE IF( LSAME( DIRECT, 'B' ) ) THEN
DO 240 J = N - 1, 1, -1
CTEMP = C( J )
STEMP = S( J )
IF( ( CTEMP.NE.ONE ) .OR. ( STEMP.NE.ZERO ) ) THEN
DO 230 I = 1, M
TEMP = A( I, J )
A( I, J ) = STEMP*A( I, N ) + CTEMP*TEMP
A( I, N ) = CTEMP*A( I, N ) - STEMP*TEMP
230 CONTINUE
END IF
240 CONTINUE
END IF
END IF
END IF
*
RETURN
*
* END OF DLASR
*
END
CUT HERE............
CAT > DLAEV2.F <<'CUT HERE............'
SUBROUTINE DLAEV2( A, B, C, RT1, RT2, CS1, SN1 )
*
* -- LAPACK AUXILIARY ROUTINE (VERSION 1.1) --
* UNIV. OF TENNESSEE, UNIV. OF CALIFORNIA BERKELEY, NAG LTD.,
* COURANT INSTITUTE, ARGONNE NATIONAL LAB, AND RICE UNIVERSITY
* OCTOBER 31, 1992
*
* .. SCALAR ARGUMENTS ..
DOUBLE PRECISION A, B, C, CS1, RT1, RT2, SN1
* ..
*
* PURPOSE
* =======
*
* DLAEV2 COMPUTES THE EIGENDECOMPOSITION OF A 2-BY-2 SYMMETRIC MATRIX
* [ A B ]
* [ B C ].
* ON RETURN, RT1 IS THE EIGENVALUE OF LARGER ABSOLUTE VALUE, RT2 IS THE
* EIGENVALUE OF SMALLER ABSOLUTE VALUE, AND (CS1,SN1) IS THE UNIT RIGHT
* EIGENVECTOR FOR RT1, GIVING THE DECOMPOSITION
*
* [ CS1 SN1 ] [ A B ] [ CS1 -SN1 ] = [ RT1 0 ]
* [-SN1 CS1 ] [ B C ] [ SN1 CS1 ] [ 0 RT2 ].
*
* ARGUMENTS
* =========
*
* A (INPUT) DOUBLE PRECISION
* THE (1,1) ENTRY OF THE 2-BY-2 MATRIX.
*
* B (INPUT) DOUBLE PRECISION
* THE (1,2) ENTRY AND THE CONJUGATE OF THE (2,1) ENTRY OF THE
* 2-BY-2 MATRIX.
*
* C (INPUT) DOUBLE PRECISION
* THE (2,2) ENTRY OF THE 2-BY-2 MATRIX.
*
* RT1 (OUTPUT) DOUBLE PRECISION
* THE EIGENVALUE OF LARGER ABSOLUTE VALUE.
*
* RT2 (OUTPUT) DOUBLE PRECISION
* THE EIGENVALUE OF SMALLER ABSOLUTE VALUE.
*
* CS1 (OUTPUT) DOUBLE PRECISION
* SN1 (OUTPUT) DOUBLE PRECISION
* THE VECTOR (CS1, SN1) IS A UNIT RIGHT EIGENVECTOR FOR RT1.
*
* FURTHER DETAILS
* ===============
*
* RT1 IS ACCURATE TO A FEW ULPS BARRING OVER/UNDERFLOW.
*
* RT2 MAY BE INACCURATE IF THERE IS MASSIVE CANCELLATION IN THE
* DETERMINANT A*C-B*B; HIGHER PRECISION OR CORRECTLY ROUNDED OR
* CORRECTLY TRUNCATED ARITHMETIC WOULD BE NEEDED TO COMPUTE RT2
* ACCURATELY IN ALL CASES.
*
* CS1 AND SN1 ARE ACCURATE TO A FEW ULPS BARRING OVER/UNDERFLOW.
*
* OVERFLOW IS POSSIBLE ONLY IF RT1 IS WITHIN A FACTOR OF 5 OF OVERFLOW.
* UNDERFLOW IS HARMLESS IF THE INPUT DATA IS 0 OR EXCEEDS
* UNDERFLOW_THRESHOLD / MACHEPS.
*
* =====================================================================
*
* .. PARAMETERS ..
DOUBLE PRECISION ONE
PARAMETER ( ONE = 1.0D0 )
DOUBLE PRECISION TWO
PARAMETER ( TWO = 2.0D0 )
DOUBLE PRECISION ZERO
PARAMETER ( ZERO = 0.0D0 )
DOUBLE PRECISION HALF
PARAMETER ( HALF = 0.5D0 )
* ..
* .. LOCAL SCALARS ..
INTEGER SGN1, SGN2
DOUBLE PRECISION AB, ACMN, ACMX, ACS, ADF, CS, CT, DF, RT, SM,
$ TB, TN
* ..
* .. INTRINSIC FUNCTIONS ..
INTRINSIC ABS, SQRT
* ..
* .. EXECUTABLE STATEMENTS ..
*
* COMPUTE THE EIGENVALUES
*
SM = A + C
DF = A - C
ADF = ABS( DF )
TB = B + B
AB = ABS( TB )
IF( ABS( A ).GT.ABS( C ) ) THEN
ACMX = A
ACMN = C
ELSE
ACMX = C
ACMN = A
END IF
IF( ADF.GT.AB ) THEN
RT = ADF*SQRT( ONE+( AB / ADF )**2 )
ELSE IF( ADF.LT.AB ) THEN
RT = AB*SQRT( ONE+( ADF / AB )**2 )
ELSE
*
* INCLUDES CASE AB=ADF=0
*
RT = AB*SQRT( TWO )
END IF
IF( SM.LT.ZERO ) THEN
RT1 = HALF*( SM-RT )
SGN1 = -1
*
* ORDER OF EXECUTION IMPORTANT.
* TO GET FULLY ACCURATE SMALLER EIGENVALUE,
* NEXT LINE NEEDS TO BE EXECUTED IN HIGHER PRECISION.
*
RT2 = ( ACMX / RT1 )*ACMN - ( B / RT1 )*B
ELSE IF( SM.GT.ZERO ) THEN
RT1 = HALF*( SM+RT )
SGN1 = 1
*
* ORDER OF EXECUTION IMPORTANT.
* TO GET FULLY ACCURATE SMALLER EIGENVALUE,
* NEXT LINE NEEDS TO BE EXECUTED IN HIGHER PRECISION.
*
RT2 = ( ACMX / RT1 )*ACMN - ( B / RT1 )*B
ELSE
*
* INCLUDES CASE RT1 = RT2 = 0
*
RT1 = HALF*RT
RT2 = -HALF*RT
SGN1 = 1
END IF
*
* COMPUTE THE EIGENVECTOR
*
IF( DF.GE.ZERO ) THEN
CS = DF + RT
SGN2 = 1
ELSE
CS = DF - RT
SGN2 = -1
END IF
ACS = ABS( CS )
IF( ACS.GT.AB ) THEN
CT = -TB / CS
SN1 = ONE / SQRT( ONE+CT*CT )
CS1 = CT*SN1
ELSE
IF( AB.EQ.ZERO ) THEN
CS1 = ONE
SN1 = ZERO
ELSE
TN = -CS / TB
CS1 = ONE / SQRT( ONE+TN*TN )
SN1 = TN*CS1
END IF
END IF
IF( SGN1.EQ.SGN2 ) THEN
TN = CS1
CS1 = -SN1
SN1 = TN
END IF
RETURN
*
* END OF DLAEV2
*
END
CUT HERE............
CAT > DLAZRO.F <<'CUT HERE............'
SUBROUTINE DLAZRO( M, N, ALPHA, BETA, A, LDA )
*
* -- LAPACK AUXILIARY ROUTINE (VERSION 1.1) --
* UNIV. OF TENNESSEE, UNIV. OF CALIFORNIA BERKELEY, NAG LTD.,
* COURANT INSTITUTE, ARGONNE NATIONAL LAB, AND RICE UNIVERSITY
* OCTOBER 31, 1992
*
* .. SCALAR ARGUMENTS ..
INTEGER LDA, M, N
DOUBLE PRECISION ALPHA, BETA
* ..
* .. ARRAY ARGUMENTS ..
DOUBLE PRECISION A( LDA, * )
* ..
*
* PURPOSE
* =======
*
* DLAZRO INITIALIZES A 2-D ARRAY A TO BETA ON THE DIAGONAL AND
* ALPHA ON THE OFFDIAGONALS.
*
* ARGUMENTS
* =========
*
* M (INPUT) INTEGER
* THE NUMBER OF ROWS OF THE MATRIX A. M >= 0.
*
* N (INPUT) INTEGER
* THE NUMBER OF COLUMNS OF THE MATRIX A. N >= 0.
*
* ALPHA (INPUT) DOUBLE PRECISION
* THE CONSTANT TO WHICH THE OFFDIAGONAL ELEMENTS ARE TO BE SET.
*
* BETA (INPUT) DOUBLE PRECISION
* THE CONSTANT TO WHICH THE DIAGONAL ELEMENTS ARE TO BE SET.
*
* A (OUTPUT) DOUBLE PRECISION ARRAY, DIMENSION (LDA,N)
* ON EXIT, THE LEADING M BY N SUBMATRIX OF A IS SET SUCH THAT
* A(I,J) = ALPHA, 1 <= I <= M, 1 <= J <= N, I <> J
* A(I,I) = BETA, 1 <= I <= MIN(M,N).
*
* LDA (INPUT) INTEGER
* THE LEADING DIMENSION OF THE ARRAY A. LDA >= MAX(1,M).
*
* =====================================================================
*
* .. LOCAL SCALARS ..
INTEGER I, J
* ..
* .. INTRINSIC FUNCTIONS ..
INTRINSIC MIN
* ..
* .. EXECUTABLE STATEMENTS ..
*
DO 20 J = 1, N
DO 10 I = 1, M
A( I, J ) = ALPHA
10 CONTINUE
20 CONTINUE
*
DO 30 I = 1, MIN( M, N )
A( I, I ) = BETA
30 CONTINUE
*
RETURN
*
* END OF DLAZRO
*
END
CUT HERE............
CAT > DORGTR.F <<'CUT HERE............'
SUBROUTINE DORGTR( UPLO, N, A, LDA, TAU, WORK, LWORK, INFO )
*
* -- LAPACK ROUTINE (VERSION 1.1) --
* UNIV. OF TENNESSEE, UNIV. OF CALIFORNIA BERKELEY, NAG LTD.,
* COURANT INSTITUTE, ARGONNE NATIONAL LAB, AND RICE UNIVERSITY
* MARCH 31, 1993
*
* .. SCALAR ARGUMENTS ..
CHARACTER UPLO
INTEGER INFO, LDA, LWORK, N
* ..
* .. ARRAY ARGUMENTS ..
DOUBLE PRECISION A( LDA, * ), TAU( * ), WORK( LWORK )
* ..
*
* PURPOSE
* =======
*
* DORGTR GENERATES A REAL ORTHOGONAL MATRIX Q WHICH IS DEFINED AS THE
* PRODUCT OF N-1 ELEMENTARY REFLECTORS OF ORDER N, AS RETURNED BY
* DSYTRD:
*
* IF UPLO = 'U', Q = H(N-1) . . . H(2) H(1),
*
* IF UPLO = 'L', Q = H(1) H(2) . . . H(N-1).
*
* ARGUMENTS
* =========
*
* UPLO (INPUT) CHARACTER*1
* = 'U': UPPER TRIANGLE OF A CONTAINS ELEMENTARY REFLECTORS
* FROM DSYTRD;
* = 'L': LOWER TRIANGLE OF A CONTAINS ELEMENTARY REFLECTORS
* FROM DSYTRD.
*
* N (INPUT) INTEGER
* THE ORDER OF THE MATRIX Q. N >= 0.
*
* A (INPUT/OUTPUT) DOUBLE PRECISION ARRAY, DIMENSION (LDA,N)
* ON ENTRY, THE VECTORS WHICH DEFINE THE ELEMENTARY REFLECTORS,
* AS RETURNED BY DSYTRD.
* ON EXIT, THE N-BY-N ORTHOGONAL MATRIX Q.
*
* LDA (INPUT) INTEGER
* THE LEADING DIMENSION OF THE ARRAY A. LDA >= MAX(1,N).
*
* TAU (INPUT) DOUBLE PRECISION ARRAY, DIMENSION (N-1)
* TAU(I) MUST CONTAIN THE SCALAR FACTOR OF THE ELEMENTARY
* REFLECTOR H(I), AS RETURNED BY DSYTRD.
*
* WORK (WORKSPACE) DOUBLE PRECISION ARRAY, DIMENSION (LWORK)
* ON EXIT, IF INFO = 0, WORK(1) RETURNS THE OPTIMAL LWORK.
*
* LWORK (INPUT) INTEGER
* THE DIMENSION OF THE ARRAY WORK. LWORK >= MAX(1,N-1).
* FOR OPTIMUM PERFORMANCE LWORK >= (N-1)*NB, WHERE NB IS
* THE OPTIMAL BLOCKSIZE.
*
* INFO (OUTPUT) INTEGER
* = 0: SUCCESSFUL EXIT
* < 0: IF INFO = -I, THE I-TH ARGUMENT HAD AN ILLEGAL VALUE
*
* =====================================================================
*
* .. PARAMETERS ..
DOUBLE PRECISION ZERO, ONE
PARAMETER ( ZERO = 0.0D+0, ONE = 1.0D+0 )
* ..
* .. LOCAL SCALARS ..
LOGICAL UPPER
INTEGER I, IINFO, J
* ..
* .. EXTERNAL FUNCTIONS ..
LOGICAL LSAME
EXTERNAL LSAME
* ..
* .. EXTERNAL SUBROUTINES ..
EXTERNAL DORGQL, DORGQR, XERBLA
* ..
* .. INTRINSIC FUNCTIONS ..
INTRINSIC MAX
* ..
* .. EXECUTABLE STATEMENTS ..
*
* TEST THE INPUT ARGUMENTS
*
INFO = 0
UPPER = LSAME( UPLO, 'U' )
IF( .NOT.UPPER .AND. .NOT.LSAME( UPLO, 'L' ) ) THEN
INFO = -1
ELSE IF( N.LT.0 ) THEN
INFO = -2
ELSE IF( LDA.LT.MAX( 1, N ) ) THEN
INFO = -4
ELSE IF( LWORK.LT.MAX( 1, N-1 ) ) THEN
INFO = -7
END IF
IF( INFO.NE.0 ) THEN
CALL XERBLA( 'DORGTR', -INFO )
RETURN
END IF
*
* QUICK RETURN IF POSSIBLE
*
IF( N.EQ.0 ) THEN
WORK( 1 ) = 1
RETURN
END IF
*
IF( UPPER ) THEN
*
* Q WAS DETERMINED BY A CALL TO DSYTRD WITH UPLO = 'U'
*
* SHIFT THE VECTORS WHICH DEFINE THE ELEMENTARY REFLECTORS ONE
* COLUMN TO THE LEFT, AND SET THE LAST ROW AND COLUMN OF Q TO
* THOSE OF THE UNIT MATRIX
*
DO 20 J = 1, N - 1
DO 10 I = 1, J - 1
A( I, J ) = A( I, J+1 )
10 CONTINUE
A( N, J ) = ZERO
20 CONTINUE
DO 30 I = 1, N - 1
A( I, N ) = ZERO
30 CONTINUE
A( N, N ) = ONE
*
* GENERATE Q(1:N-1,1:N-1)
*
CALL DORGQL( N-1, N-1, N-1, A, LDA, TAU, WORK, LWORK, IINFO )
*
ELSE
*
* Q WAS DETERMINED BY A CALL TO DSYTRD WITH UPLO = 'L'.
*
* SHIFT THE VECTORS WHICH DEFINE THE ELEMENTARY REFLECTORS ONE
* COLUMN TO THE RIGHT, AND SET THE FIRST ROW AND COLUMN OF Q TO
* THOSE OF THE UNIT MATRIX
*
DO 50 J = N, 2, -1
A( 1, J ) = ZERO
DO 40 I = J + 1, N
A( I, J ) = A( I, J-1 )
40 CONTINUE
50 CONTINUE
A( 1, 1 ) = ONE
DO 60 I = 2, N
A( I, 1 ) = ZERO
60 CONTINUE
IF( N.GT.1 ) THEN
*
* GENERATE Q(2:N,2:N)
*
CALL DORGQR( N-1, N-1, N-1, A( 2, 2 ), LDA, TAU, WORK,
$ LWORK, IINFO )
END IF
END IF
RETURN
*
* END OF DORGTR
*
END
CUT HERE............
CAT > DORGQR.F <<'CUT HERE............'
SUBROUTINE DORGQR( M, N, K, A, LDA, TAU, WORK, LWORK, INFO )
*
* -- LAPACK ROUTINE (VERSION 1.1) --
* UNIV. OF TENNESSEE, UNIV. OF CALIFORNIA BERKELEY, NAG LTD.,
* COURANT INSTITUTE, ARGONNE NATIONAL LAB, AND RICE UNIVERSITY
* MARCH 31, 1993
*
* .. SCALAR ARGUMENTS ..
INTEGER INFO, K, LDA, LWORK, M, N
* ..
* .. ARRAY ARGUMENTS ..
DOUBLE PRECISION A( LDA, * ), TAU( * ), WORK( LWORK )
* ..
*
* PURPOSE
* =======
*
* DORGQR GENERATES AN M-BY-N REAL MATRIX Q WITH ORTHONORMAL COLUMNS,
* WHICH IS DEFINED AS THE FIRST N COLUMNS OF A PRODUCT OF K ELEMENTARY
* REFLECTORS OF ORDER M
*
* Q = H(1) H(2) . . . H(K)
*
* AS RETURNED BY DGEQRF.
*
* ARGUMENTS
* =========
*
* M (INPUT) INTEGER
* THE NUMBER OF ROWS OF THE MATRIX Q. M >= 0.
*
* N (INPUT) INTEGER
* THE NUMBER OF COLUMNS OF THE MATRIX Q. M >= N >= 0.
*
* K (INPUT) INTEGER
* THE NUMBER OF ELEMENTARY REFLECTORS WHOSE PRODUCT DEFINES THE
* MATRIX Q. N >= K >= 0.
*
* A (INPUT/OUTPUT) DOUBLE PRECISION ARRAY, DIMENSION (LDA,N)
* ON ENTRY, THE I-TH COLUMN MUST CONTAIN THE VECTOR WHICH
* DEFINES THE ELEMENTARY REFLECTOR H(I), FOR I = 1,2,...,K, AS
* RETURNED BY DGEQRF IN THE FIRST K COLUMNS OF ITS ARRAY
* ARGUMENT A.
* ON EXIT, THE M-BY-N MATRIX Q.
*
* LDA (INPUT) INTEGER
* THE FIRST DIMENSION OF THE ARRAY A. LDA >= MAX(1,M).
*
* TAU (INPUT) DOUBLE PRECISION ARRAY, DIMENSION (K)
* TAU(I) MUST CONTAIN THE SCALAR FACTOR OF THE ELEMENTARY
* REFLECTOR H(I), AS RETURNED BY DGEQRF.
*
* WORK (WORKSPACE) DOUBLE PRECISION ARRAY, DIMENSION (LWORK)
* ON EXIT, IF INFO = 0, WORK(1) RETURNS THE OPTIMAL LWORK.
*
* LWORK (INPUT) INTEGER
* THE DIMENSION OF THE ARRAY WORK. LWORK >= MAX(1,N).
* FOR OPTIMUM PERFORMANCE LWORK >= N*NB, WHERE NB IS THE
* OPTIMAL BLOCKSIZE.
*
* INFO (OUTPUT) INTEGER
* = 0: SUCCESSFUL EXIT
* < 0: IF INFO = -I, THE I-TH ARGUMENT HAS AN ILLEGAL VALUE
*
* =====================================================================
*
* .. PARAMETERS ..
DOUBLE PRECISION ZERO
PARAMETER ( ZERO = 0.0D+0 )
* ..
* .. LOCAL SCALARS ..
INTEGER I, IB, IINFO, IWS, J, KI, KK, L, LDWORK, NB,
$ NBMIN, NX
* ..
* .. EXTERNAL SUBROUTINES ..
EXTERNAL DLARFB, DLARFT, DORG2R, XERBLA
* ..
* .. INTRINSIC FUNCTIONS ..
INTRINSIC MAX, MIN
* ..
* .. EXTERNAL FUNCTIONS ..
INTEGER ILAENV
EXTERNAL ILAENV
* ..
* .. EXECUTABLE STATEMENTS ..
*
* TEST THE INPUT ARGUMENTS
*
INFO = 0
IF( M.LT.0 ) THEN
INFO = -1
ELSE IF( N.LT.0 .OR. N.GT.M ) THEN
INFO = -2
ELSE IF( K.LT.0 .OR. K.GT.N ) THEN
INFO = -3
ELSE IF( LDA.LT.MAX( 1, M ) ) THEN
INFO = -5
ELSE IF( LWORK.LT.MAX( 1, N ) ) THEN
INFO = -8
END IF
IF( INFO.NE.0 ) THEN
CALL XERBLA( 'DORGQR', -INFO )
RETURN
END IF
*
* QUICK RETURN IF POSSIBLE
*
IF( N.LE.0 ) THEN
WORK( 1 ) = 1
RETURN
END IF
*
* DETERMINE THE BLOCK SIZE.
*
NB = ILAENV( 1, 'DORGQR', ' ', M, N, K, -1 )
NBMIN = 2
NX = 0
IWS = N
IF( NB.GT.1 .AND. NB.LT.K ) THEN
*
* DETERMINE WHEN TO CROSS OVER FROM BLOCKED TO UNBLOCKED CODE.
*
NX = MAX( 0, ILAENV( 3, 'DORGQR', ' ', M, N, K, -1 ) )
IF( NX.LT.K ) THEN
*
* DETERMINE IF WORKSPACE IS LARGE ENOUGH FOR BLOCKED CODE.
*
LDWORK = N
IWS = LDWORK*NB
IF( LWORK.LT.IWS ) THEN
*
* NOT ENOUGH WORKSPACE TO USE OPTIMAL NB: REDUCE NB AND
* DETERMINE THE MINIMUM VALUE OF NB.
*
NB = LWORK / LDWORK
NBMIN = MAX( 2, ILAENV( 2, 'DORGQR', ' ', M, N, K, -1 ) )
END IF
END IF
END IF
*
IF( NB.GE.NBMIN .AND. NB.LT.K .AND. NX.LT.K ) THEN
*
* USE BLOCKED CODE AFTER THE LAST BLOCK.
* THE FIRST KK COLUMNS ARE HANDLED BY THE BLOCK METHOD.
*
KI = ( ( K-NX-1 ) / NB )*NB
KK = MIN( K, KI+NB )
*
* SET A(1:KK,KK+1:N) TO ZERO.
*
DO 20 J = KK + 1, N
DO 10 I = 1, KK
A( I, J ) = ZERO
10 CONTINUE
20 CONTINUE
ELSE
KK = 0
END IF
*
* USE UNBLOCKED CODE FOR THE LAST OR ONLY BLOCK.
*
IF( KK.LT.N )
$ CALL DORG2R( M-KK, N-KK, K-KK, A( KK+1, KK+1 ), LDA,
$ TAU( KK+1 ), WORK, IINFO )
*
IF( KK.GT.0 ) THEN
*
* USE BLOCKED CODE
*
DO 50 I = KI + 1, 1, -NB
IB = MIN( NB, K-I+1 )
IF( I+IB.LE.N ) THEN
*
* FORM THE TRIANGULAR FACTOR OF THE BLOCK REFLECTOR
* H = H(I) H(I+1) . . . H(I+IB-1)
*
CALL DLARFT( 'FORWARD', 'COLUMNWISE', M-I+1, IB,
$ A( I, I ), LDA, TAU( I ), WORK, LDWORK )
*
* APPLY H TO A(I:M,I+IB:N) FROM THE LEFT
*
CALL DLARFB( 'LEFT', 'NO TRANSPOSE', 'FORWARD',
$ 'COLUMNWISE', M-I+1, N-I-IB+1, IB,
$ A( I, I ), LDA, WORK, LDWORK, A( I, I+IB ),
$ LDA, WORK( IB+1 ), LDWORK )
END IF
*
* APPLY H TO ROWS I:M OF CURRENT BLOCK
*
CALL DORG2R( M-I+1, IB, IB, A( I, I ), LDA, TAU( I ), WORK,
$ IINFO )
*
* SET ROWS 1:I-1 OF CURRENT BLOCK TO ZERO
*
DO 40 J = I, I + IB - 1
DO 30 L = 1, I - 1
A( L, J ) = ZERO
30 CONTINUE
40 CONTINUE
50 CONTINUE
END IF
*
WORK( 1 ) = IWS
RETURN
*
* END OF DORGQR
*
END
CUT HERE............
CAT > DORG2R.F <<'CUT HERE............'
SUBROUTINE DORG2R( M, N, K, A, LDA, TAU, WORK, INFO )
*
* -- LAPACK ROUTINE (VERSION 1.1) --
* UNIV. OF TENNESSEE, UNIV. OF CALIFORNIA BERKELEY, NAG LTD.,
* COURANT INSTITUTE, ARGONNE NATIONAL LAB, AND RICE UNIVERSITY
* FEBRUARY 29, 1992
*
* .. SCALAR ARGUMENTS ..
INTEGER INFO, K, LDA, M, N
* ..
* .. ARRAY ARGUMENTS ..
DOUBLE PRECISION A( LDA, * ), TAU( * ), WORK( * )
* ..
*
* PURPOSE
* =======
*
* DORG2R GENERATES AN M BY N REAL MATRIX Q WITH ORTHONORMAL COLUMNS,
* WHICH IS DEFINED AS THE FIRST N COLUMNS OF A PRODUCT OF K ELEMENTARY
* REFLECTORS OF ORDER M
*
* Q = H(1) H(2) . . . H(K)
*
* AS RETURNED BY DGEQRF.
*
* ARGUMENTS
* =========
*
* M (INPUT) INTEGER
* THE NUMBER OF ROWS OF THE MATRIX Q. M >= 0.
*
* N (INPUT) INTEGER
* THE NUMBER OF COLUMNS OF THE MATRIX Q. M >= N >= 0.
*
* K (INPUT) INTEGER
* THE NUMBER OF ELEMENTARY REFLECTORS WHOSE PRODUCT DEFINES THE
* MATRIX Q. N >= K >= 0.
*
* A (INPUT/OUTPUT) DOUBLE PRECISION ARRAY, DIMENSION (LDA,N)
* ON ENTRY, THE I-TH COLUMN MUST CONTAIN THE VECTOR WHICH
* DEFINES THE ELEMENTARY REFLECTOR H(I), FOR I = 1,2,...,K, AS
* RETURNED BY DGEQRF IN THE FIRST K COLUMNS OF ITS ARRAY
* ARGUMENT A.
* ON EXIT, THE M-BY-N MATRIX Q.
*
* LDA (INPUT) INTEGER
* THE FIRST DIMENSION OF THE ARRAY A. LDA >= MAX(1,M).
*
* TAU (INPUT) DOUBLE PRECISION ARRAY, DIMENSION (K)
* TAU(I) MUST CONTAIN THE SCALAR FACTOR OF THE ELEMENTARY
* REFLECTOR H(I), AS RETURNED BY DGEQRF.
*
* WORK (WORKSPACE) DOUBLE PRECISION ARRAY, DIMENSION (N)
*
* INFO (OUTPUT) INTEGER
* = 0: SUCCESSFUL EXIT
* < 0: IF INFO = -I, THE I-TH ARGUMENT HAS AN ILLEGAL VALUE
*
* =====================================================================
*
* .. PARAMETERS ..
DOUBLE PRECISION ONE, ZERO
PARAMETER ( ONE = 1.0D+0, ZERO = 0.0D+0 )
* ..
* .. LOCAL SCALARS ..
INTEGER I, J, L
* ..
* .. EXTERNAL SUBROUTINES ..
EXTERNAL DLARF, DSCAL, XERBLA
* ..
* .. INTRINSIC FUNCTIONS ..
INTRINSIC MAX
* ..
* .. EXECUTABLE STATEMENTS ..
*
* TEST THE INPUT ARGUMENTS
*
INFO = 0
IF( M.LT.0 ) THEN
INFO = -1
ELSE IF( N.LT.0 .OR. N.GT.M ) THEN
INFO = -2
ELSE IF( K.LT.0 .OR. K.GT.N ) THEN
INFO = -3
ELSE IF( LDA.LT.MAX( 1, M ) ) THEN
INFO = -5
END IF
IF( INFO.NE.0 ) THEN
CALL XERBLA( 'DORG2R', -INFO )
RETURN
END IF
*
* QUICK RETURN IF POSSIBLE
*
IF( N.LE.0 )
$ RETURN
*
* INITIALISE COLUMNS K+1:N TO COLUMNS OF THE UNIT MATRIX
*
DO 20 J = K + 1, N
DO 10 L = 1, M
A( L, J ) = ZERO
10 CONTINUE
A( J, J ) = ONE
20 CONTINUE
*
DO 40 I = K, 1, -1
*
* APPLY H(I) TO A(I:M,I:N) FROM THE LEFT
*
IF( I.LT.N ) THEN
A( I, I ) = ONE
CALL DLARF( 'LEFT', M-I+1, N-I, A( I, I ), 1, TAU( I ),
$ A( I, I+1 ), LDA, WORK )
END IF
IF( I.LT.M )
$ CALL DSCAL( M-I, -TAU( I ), A( I+1, I ), 1 )
A( I, I ) = ONE - TAU( I )
*
* SET A(1:I-1,I) TO ZERO
*
DO 30 L = 1, I - 1
A( L, I ) = ZERO
30 CONTINUE
40 CONTINUE
RETURN
*
* END OF DORG2R
*
END
CUT HERE............
CAT > DORGQL.F <<'CUT HERE............'
SUBROUTINE DORGQL( M, N, K, A, LDA, TAU, WORK, LWORK, INFO )
*
* -- LAPACK ROUTINE (VERSION 1.1) --
* UNIV. OF TENNESSEE, UNIV. OF CALIFORNIA BERKELEY, NAG LTD.,
* COURANT INSTITUTE, ARGONNE NATIONAL LAB, AND RICE UNIVERSITY
* MARCH 31, 1993
*
* .. SCALAR ARGUMENTS ..
INTEGER INFO, K, LDA, LWORK, M, N
* ..
* .. ARRAY ARGUMENTS ..
DOUBLE PRECISION A( LDA, * ), TAU( * ), WORK( LWORK )
* ..
*
* PURPOSE
* =======
*
* DORGQL GENERATES AN M-BY-N REAL MATRIX Q WITH ORTHONORMAL COLUMNS,
* WHICH IS DEFINED AS THE LAST N COLUMNS OF A PRODUCT OF K ELEMENTARY
* REFLECTORS OF ORDER M
*
* Q = H(K) . . . H(2) H(1)
*
* AS RETURNED BY DGEQLF.
*
* ARGUMENTS
* =========
*
* M (INPUT) INTEGER
* THE NUMBER OF ROWS OF THE MATRIX Q. M >= 0.
*
* N (INPUT) INTEGER
* THE NUMBER OF COLUMNS OF THE MATRIX Q. M >= N >= 0.
*
* K (INPUT) INTEGER
* THE NUMBER OF ELEMENTARY REFLECTORS WHOSE PRODUCT DEFINES THE
* MATRIX Q. N >= K >= 0.
*
* A (INPUT/OUTPUT) DOUBLE PRECISION ARRAY, DIMENSION (LDA,N)
* ON ENTRY, THE (N-K+I)-TH COLUMN MUST CONTAIN THE VECTOR WHICH
* DEFINES THE ELEMENTARY REFLECTOR H(I), FOR I = 1,2,...,K, AS
* RETURNED BY DGEQLF IN THE LAST K COLUMNS OF ITS ARRAY
* ARGUMENT A.
* ON EXIT, THE M-BY-N MATRIX Q.
*
* LDA (INPUT) INTEGER
* THE FIRST DIMENSION OF THE ARRAY A. LDA >= MAX(1,M).
*
* TAU (INPUT) DOUBLE PRECISION ARRAY, DIMENSION (K)
* TAU(I) MUST CONTAIN THE SCALAR FACTOR OF THE ELEMENTARY
* REFLECTOR H(I), AS RETURNED BY DGEQLF.
*
* WORK (WORKSPACE) DOUBLE PRECISION ARRAY, DIMENSION (LWORK)
* ON EXIT, IF INFO = 0, WORK(1) RETURNS THE OPTIMAL LWORK.
*
* LWORK (INPUT) INTEGER
* THE DIMENSION OF THE ARRAY WORK. LWORK >= MAX(1,N).
* FOR OPTIMUM PERFORMANCE LWORK >= N*NB, WHERE NB IS THE
* OPTIMAL BLOCKSIZE.
*
* INFO (OUTPUT) INTEGER
* = 0: SUCCESSFUL EXIT
* < 0: IF INFO = -I, THE I-TH ARGUMENT HAS AN ILLEGAL VALUE
*
* =====================================================================
*
* .. PARAMETERS ..
DOUBLE PRECISION ZERO
PARAMETER ( ZERO = 0.0D+0 )
* ..
* .. LOCAL SCALARS ..
INTEGER I, IB, IINFO, IWS, J, KK, L, LDWORK, NB, NBMIN,
$ NX
* ..
* .. EXTERNAL SUBROUTINES ..
EXTERNAL DLARFB, DLARFT, DORG2L, XERBLA
* ..
* .. INTRINSIC FUNCTIONS ..
INTRINSIC MAX, MIN
* ..
* .. EXTERNAL FUNCTIONS ..
INTEGER ILAENV
EXTERNAL ILAENV
* ..
* .. EXECUTABLE STATEMENTS ..
*
* TEST THE INPUT ARGUMENTS
*
INFO = 0
IF( M.LT.0 ) THEN
INFO = -1
ELSE IF( N.LT.0 .OR. N.GT.M ) THEN
INFO = -2
ELSE IF( K.LT.0 .OR. K.GT.N ) THEN
INFO = -3
ELSE IF( LDA.LT.MAX( 1, M ) ) THEN
INFO = -5
ELSE IF( LWORK.LT.MAX( 1, N ) ) THEN
INFO = -8
END IF
IF( INFO.NE.0 ) THEN
CALL XERBLA( 'DORGQL', -INFO )
RETURN
END IF
*
* QUICK RETURN IF POSSIBLE
*
IF( N.LE.0 ) THEN
WORK( 1 ) = 1
RETURN
END IF
*
* DETERMINE THE BLOCK SIZE.
*
NB = ILAENV( 1, 'DORGQL', ' ', M, N, K, -1 )
NBMIN = 2
NX = 0
IWS = N
IF( NB.GT.1 .AND. NB.LT.K ) THEN
*
* DETERMINE WHEN TO CROSS OVER FROM BLOCKED TO UNBLOCKED CODE.
*
NX = MAX( 0, ILAENV( 3, 'DORGQL', ' ', M, N, K, -1 ) )
IF( NX.LT.K ) THEN
*
* DETERMINE IF WORKSPACE IS LARGE ENOUGH FOR BLOCKED CODE.
*
LDWORK = N
IWS = LDWORK*NB
IF( LWORK.LT.IWS ) THEN
*
* NOT ENOUGH WORKSPACE TO USE OPTIMAL NB: REDUCE NB AND
* DETERMINE THE MINIMUM VALUE OF NB.
*
NB = LWORK / LDWORK
NBMIN = MAX( 2, ILAENV( 2, 'DORGQL', ' ', M, N, K, -1 ) )
END IF
END IF
END IF
*
IF( NB.GE.NBMIN .AND. NB.LT.K .AND. NX.LT.K ) THEN
*
* USE BLOCKED CODE AFTER THE FIRST BLOCK.
* THE LAST KK COLUMNS ARE HANDLED BY THE BLOCK METHOD.
*
KK = MIN( K, ( ( K-NX+NB-1 ) / NB )*NB )
*
* SET A(M-KK+1:M,1:N-KK) TO ZERO.
*
DO 20 J = 1, N - KK
DO 10 I = M - KK + 1, M
A( I, J ) = ZERO
10 CONTINUE
20 CONTINUE
ELSE
KK = 0
END IF
*
* USE UNBLOCKED CODE FOR THE FIRST OR ONLY BLOCK.
*
CALL DORG2L( M-KK, N-KK, K-KK, A, LDA, TAU, WORK, IINFO )
*
IF( KK.GT.0 ) THEN
*
* USE BLOCKED CODE
*
DO 50 I = K - KK + 1, K, NB
IB = MIN( NB, K-I+1 )
IF( N-K+I.GT.1 ) THEN
*
* FORM THE TRIANGULAR FACTOR OF THE BLOCK REFLECTOR
* H = H(I+IB-1) . . . H(I+1) H(I)
*
CALL DLARFT( 'BACKWARD', 'COLUMNWISE', M-K+I+IB-1, IB,
$ A( 1, N-K+I ), LDA, TAU( I ), WORK, LDWORK )
*
* APPLY H TO A(1:M-K+I+IB-1,1:N-K+I-1) FROM THE LEFT
*
CALL DLARFB( 'LEFT', 'NO TRANSPOSE', 'BACKWARD',
$ 'COLUMNWISE', M-K+I+IB-1, N-K+I-1, IB,
$ A( 1, N-K+I ), LDA, WORK, LDWORK, A, LDA,
$ WORK( IB+1 ), LDWORK )
END IF
*
* APPLY H TO ROWS 1:M-K+I+IB-1 OF CURRENT BLOCK
*
CALL DORG2L( M-K+I+IB-1, IB, IB, A( 1, N-K+I ), LDA,
$ TAU( I ), WORK, IINFO )
*
* SET ROWS M-K+I+IB:M OF CURRENT BLOCK TO ZERO
*
DO 40 J = N - K + I, N - K + I + IB - 1
DO 30 L = M - K + I + IB, M
A( L, J ) = ZERO
30 CONTINUE
40 CONTINUE
50 CONTINUE
END IF
*
WORK( 1 ) = IWS
RETURN
*
* END OF DORGQL
*
END
CUT HERE............
CAT > DLARFB.F <<'CUT HERE............'
SUBROUTINE DLARFB( SIDE, TRANS, DIRECT, STOREV, M, N, K, V, LDV,
$ T, LDT, C, LDC, WORK, LDWORK )
*
* -- LAPACK AUXILIARY ROUTINE (VERSION 1.1) --
* UNIV. OF TENNESSEE, UNIV. OF CALIFORNIA BERKELEY, NAG LTD.,
* COURANT INSTITUTE, ARGONNE NATIONAL LAB, AND RICE UNIVERSITY
* FEBRUARY 29, 1992
*
* .. SCALAR ARGUMENTS ..
CHARACTER DIRECT, SIDE, STOREV, TRANS
INTEGER K, LDC, LDT, LDV, LDWORK, M, N
* ..
* .. ARRAY ARGUMENTS ..
DOUBLE PRECISION C( LDC, * ), T( LDT, * ), V( LDV, * ),
$ WORK( LDWORK, * )
* ..
*
* PURPOSE
* =======
*
* DLARFB APPLIES A REAL BLOCK REFLECTOR H OR ITS TRANSPOSE H' TO A
* REAL M BY N MATRIX C, FROM EITHER THE LEFT OR THE RIGHT.
*
* ARGUMENTS
* =========
*
* SIDE (INPUT) CHARACTER*1
* = 'L': APPLY H OR H' FROM THE LEFT
* = 'R': APPLY H OR H' FROM THE RIGHT
*
* TRANS (INPUT) CHARACTER*1
* = 'N': APPLY H (NO TRANSPOSE)
* = 'T': APPLY H' (TRANSPOSE)
*
* DIRECT (INPUT) CHARACTER*1
* INDICATES HOW H IS FORMED FROM A PRODUCT OF ELEMENTARY
* REFLECTORS
* = 'F': H = H(1) H(2) . . . H(K) (FORWARD)
* = 'B': H = H(K) . . . H(2) H(1) (BACKWARD)
*
* STOREV (INPUT) CHARACTER*1
* INDICATES HOW THE VECTORS WHICH DEFINE THE ELEMENTARY
* REFLECTORS ARE STORED:
* = 'C': COLUMNWISE
* = 'R': ROWWISE
*
* M (INPUT) INTEGER
* THE NUMBER OF ROWS OF THE MATRIX C.
*
* N (INPUT) INTEGER
* THE NUMBER OF COLUMNS OF THE MATRIX C.
*
* K (INPUT) INTEGER
* THE ORDER OF THE MATRIX T (= THE NUMBER OF ELEMENTARY
* REFLECTORS WHOSE PRODUCT DEFINES THE BLOCK REFLECTOR).
*
* V (INPUT) DOUBLE PRECISION ARRAY, DIMENSION
* (LDV,K) IF STOREV = 'C'
* (LDV,M) IF STOREV = 'R' AND SIDE = 'L'
* (LDV,N) IF STOREV = 'R' AND SIDE = 'R'
* THE MATRIX V. SEE FURTHER DETAILS.
*
* LDV (INPUT) INTEGER
* THE LEADING DIMENSION OF THE ARRAY V.
* IF STOREV = 'C' AND SIDE = 'L', LDV >= MAX(1,M);
* IF STOREV = 'C' AND SIDE = 'R', LDV >= MAX(1,N);
* IF STOREV = 'R', LDV >= K.
*
* T (INPUT) DOUBLE PRECISION ARRAY, DIMENSION (LDT,K)
* THE TRIANGULAR K BY K MATRIX T IN THE REPRESENTATION OF THE
* BLOCK REFLECTOR.
*
* LDT (INPUT) INTEGER
* THE LEADING DIMENSION OF THE ARRAY T. LDT >= K.
*
* C (INPUT/OUTPUT) DOUBLE PRECISION ARRAY, DIMENSION (LDC,N)
* ON ENTRY, THE M BY N MATRIX C.
* ON EXIT, C IS OVERWRITTEN BY H*C OR H'*C OR C*H OR C*H'.
*
* LDC (INPUT) INTEGER
* THE LEADING DIMENSION OF THE ARRAY C. LDA >= MAX(1,M).
*
* WORK (WORKSPACE) DOUBLE PRECISION ARRAY, DIMENSION (LDWORK,K)
*
* LDWORK (INPUT) INTEGER
* THE LEADING DIMENSION OF THE ARRAY WORK.
* IF SIDE = 'L', LDWORK >= MAX(1,N);
* IF SIDE = 'R', LDWORK >= MAX(1,M).
*
* =====================================================================
*
* .. PARAMETERS ..
DOUBLE PRECISION ONE
PARAMETER ( ONE = 1.0D+0 )
* ..
* .. LOCAL SCALARS ..
CHARACTER TRANST
INTEGER I, J
* ..
* .. EXTERNAL FUNCTIONS ..
LOGICAL LSAME
EXTERNAL LSAME
* ..
* .. EXTERNAL SUBROUTINES ..
EXTERNAL DCOPY, DGEMM, DTRMM
* ..
* .. EXECUTABLE STATEMENTS ..
*
* QUICK RETURN IF POSSIBLE
*
IF( M.LE.0 .OR. N.LE.0 )
$ RETURN
*
IF( LSAME( TRANS, 'N' ) ) THEN
TRANST = 'T'
ELSE
TRANST = 'N'
END IF
*
IF( LSAME( STOREV, 'C' ) ) THEN
*
IF( LSAME( DIRECT, 'F' ) ) THEN
*
* LET V = ( V1 ) (FIRST K ROWS)
* ( V2 )
* WHERE V1 IS UNIT LOWER TRIANGULAR.
*
IF( LSAME( SIDE, 'L' ) ) THEN
*
* FORM H * C OR H' * C WHERE C = ( C1 )
* ( C2 )
*
* W := C' * V = (C1'*V1 + C2'*V2) (STORED IN WORK)
*
* W := C1'
*
DO 10 J = 1, K
CALL DCOPY( N, C( J, 1 ), LDC, WORK( 1, J ), 1 )
10 CONTINUE
*
* W := W * V1
*
CALL DTRMM( 'RIGHT', 'LOWER', 'NO TRANSPOSE', 'UNIT', N,
$ K, ONE, V, LDV, WORK, LDWORK )
IF( M.GT.K ) THEN
*
* W := W + C2'*V2
*
CALL DGEMM( 'TRANSPOSE', 'NO TRANSPOSE', N, K, M-K,
$ ONE, C( K+1, 1 ), LDC, V( K+1, 1 ), LDV,
$ ONE, WORK, LDWORK )
END IF
*
* W := W * T' OR W * T
*
CALL DTRMM( 'RIGHT', 'UPPER', TRANST, 'NON-UNIT', N, K,
$ ONE, T, LDT, WORK, LDWORK )
*
* C := C - V * W'
*
IF( M.GT.K ) THEN
*
* C2 := C2 - V2 * W'
*
CALL DGEMM( 'NO TRANSPOSE', 'TRANSPOSE', M-K, N, K,
$ -ONE, V( K+1, 1 ), LDV, WORK, LDWORK, ONE,
$ C( K+1, 1 ), LDC )
END IF
*
* W := W * V1'
*
CALL DTRMM( 'RIGHT', 'LOWER', 'TRANSPOSE', 'UNIT', N, K,
$ ONE, V, LDV, WORK, LDWORK )
*
* C1 := C1 - W'
*
DO 30 J = 1, K
DO 20 I = 1, N
C( J, I ) = C( J, I ) - WORK( I, J )
20 CONTINUE
30 CONTINUE
*
ELSE IF( LSAME( SIDE, 'R' ) ) THEN
*
* FORM C * H OR C * H' WHERE C = ( C1 C2 )
*
* W := C * V = (C1*V1 + C2*V2) (STORED IN WORK)
*
* W := C1
*
DO 40 J = 1, K
CALL DCOPY( M, C( 1, J ), 1, WORK( 1, J ), 1 )
40 CONTINUE
*
* W := W * V1
*
CALL DTRMM( 'RIGHT', 'LOWER', 'NO TRANSPOSE', 'UNIT', M,
$ K, ONE, V, LDV, WORK, LDWORK )
IF( N.GT.K ) THEN
*
* W := W + C2 * V2
*
CALL DGEMM( 'NO TRANSPOSE', 'NO TRANSPOSE', M, K, N-K,
$ ONE, C( 1, K+1 ), LDC, V( K+1, 1 ), LDV,
$ ONE, WORK, LDWORK )
END IF
*
* W := W * T OR W * T'
*
CALL DTRMM( 'RIGHT', 'UPPER', TRANS, 'NON-UNIT', M, K,
$ ONE, T, LDT, WORK, LDWORK )
*
* C := C - W * V'
*
IF( N.GT.K ) THEN
*
* C2 := C2 - W * V2'
*
CALL DGEMM( 'NO TRANSPOSE', 'TRANSPOSE', M, N-K, K,
$ -ONE, WORK, LDWORK, V( K+1, 1 ), LDV, ONE,
$ C( 1, K+1 ), LDC )
END IF
*
* W := W * V1'
*
CALL DTRMM( 'RIGHT', 'LOWER', 'TRANSPOSE', 'UNIT', M, K,
$ ONE, V, LDV, WORK, LDWORK )
*
* C1 := C1 - W
*
DO 60 J = 1, K
DO 50 I = 1, M
C( I, J ) = C( I, J ) - WORK( I, J )
50 CONTINUE
60 CONTINUE
END IF
*
ELSE
*
* LET V = ( V1 )
* ( V2 ) (LAST K ROWS)
* WHERE V2 IS UNIT UPPER TRIANGULAR.
*
IF( LSAME( SIDE, 'L' ) ) THEN
*
* FORM H * C OR H' * C WHERE C = ( C1 )
* ( C2 )
*
* W := C' * V = (C1'*V1 + C2'*V2) (STORED IN WORK)
*
* W := C2'
*
DO 70 J = 1, K
CALL DCOPY( N, C( M-K+J, 1 ), LDC, WORK( 1, J ), 1 )
70 CONTINUE
*
* W := W * V2
*
CALL DTRMM( 'RIGHT', 'UPPER', 'NO TRANSPOSE', 'UNIT', N,
$ K, ONE, V( M-K+1, 1 ), LDV, WORK, LDWORK )
IF( M.GT.K ) THEN
*
* W := W + C1'*V1
*
CALL DGEMM( 'TRANSPOSE', 'NO TRANSPOSE', N, K, M-K,
$ ONE, C, LDC, V, LDV, ONE, WORK, LDWORK )
END IF
*
* W := W * T' OR W * T
*
CALL DTRMM( 'RIGHT', 'LOWER', TRANST, 'NON-UNIT', N, K,
$ ONE, T, LDT, WORK, LDWORK )
*
* C := C - V * W'
*
IF( M.GT.K ) THEN
*
* C1 := C1 - V1 * W'
*
CALL DGEMM( 'NO TRANSPOSE', 'TRANSPOSE', M-K, N, K,
$ -ONE, V, LDV, WORK, LDWORK, ONE, C, LDC )
END IF
*
* W := W * V2'
*
CALL DTRMM( 'RIGHT', 'UPPER', 'TRANSPOSE', 'UNIT', N, K,
$ ONE, V( M-K+1, 1 ), LDV, WORK, LDWORK )
*
* C2 := C2 - W'
*
DO 90 J = 1, K
DO 80 I = 1, N
C( M-K+J, I ) = C( M-K+J, I ) - WORK( I, J )
80 CONTINUE
90 CONTINUE
*
ELSE IF( LSAME( SIDE, 'R' ) ) THEN
*
* FORM C * H OR C * H' WHERE C = ( C1 C2 )
*
* W := C * V = (C1*V1 + C2*V2) (STORED IN WORK)
*
* W := C2
*
DO 100 J = 1, K
CALL DCOPY( M, C( 1, N-K+J ), 1, WORK( 1, J ), 1 )
100 CONTINUE
*
* W := W * V2
*
CALL DTRMM( 'RIGHT', 'UPPER', 'NO TRANSPOSE', 'UNIT', M,
$ K, ONE, V( N-K+1, 1 ), LDV, WORK, LDWORK )
IF( N.GT.K ) THEN
*
* W := W + C1 * V1
*
CALL DGEMM( 'NO TRANSPOSE', 'NO TRANSPOSE', M, K, N-K,
$ ONE, C, LDC, V, LDV, ONE, WORK, LDWORK )
END IF
*
* W := W * T OR W * T'
*
CALL DTRMM( 'RIGHT', 'LOWER', TRANS, 'NON-UNIT', M, K,
$ ONE, T, LDT, WORK, LDWORK )
*
* C := C - W * V'
*
IF( N.GT.K ) THEN
*
* C1 := C1 - W * V1'
*
CALL DGEMM( 'NO TRANSPOSE', 'TRANSPOSE', M, N-K, K,
$ -ONE, WORK, LDWORK, V, LDV, ONE, C, LDC )
END IF
*
* W := W * V2'
*
CALL DTRMM( 'RIGHT', 'UPPER', 'TRANSPOSE', 'UNIT', M, K,
$ ONE, V( N-K+1, 1 ), LDV, WORK, LDWORK )
*
* C2 := C2 - W
*
DO 120 J = 1, K
DO 110 I = 1, M
C( I, N-K+J ) = C( I, N-K+J ) - WORK( I, J )
110 CONTINUE
120 CONTINUE
END IF
END IF
*
ELSE IF( LSAME( STOREV, 'R' ) ) THEN
*
IF( LSAME( DIRECT, 'F' ) ) THEN
*
* LET V = ( V1 V2 ) (V1: FIRST K COLUMNS)
* WHERE V1 IS UNIT UPPER TRIANGULAR.
*
IF( LSAME( SIDE, 'L' ) ) THEN
*
* FORM H * C OR H' * C WHERE C = ( C1 )
* ( C2 )
*
* W := C' * V' = (C1'*V1' + C2'*V2') (STORED IN WORK)
*
* W := C1'
*
DO 130 J = 1, K
CALL DCOPY( N, C( J, 1 ), LDC, WORK( 1, J ), 1 )
130 CONTINUE
*
* W := W * V1'
*
CALL DTRMM( 'RIGHT', 'UPPER', 'TRANSPOSE', 'UNIT', N, K,
$ ONE, V, LDV, WORK, LDWORK )
IF( M.GT.K ) THEN
*
* W := W + C2'*V2'
*
CALL DGEMM( 'TRANSPOSE', 'TRANSPOSE', N, K, M-K, ONE,
$ C( K+1, 1 ), LDC, V( 1, K+1 ), LDV, ONE,
$ WORK, LDWORK )
END IF
*
* W := W * T' OR W * T
*
CALL DTRMM( 'RIGHT', 'UPPER', TRANST, 'NON-UNIT', N, K,
$ ONE, T, LDT, WORK, LDWORK )
*
* C := C - V' * W'
*
IF( M.GT.K ) THEN
*
* C2 := C2 - V2' * W'
*
CALL DGEMM( 'TRANSPOSE', 'TRANSPOSE', M-K, N, K, -ONE,
$ V( 1, K+1 ), LDV, WORK, LDWORK, ONE,
$ C( K+1, 1 ), LDC )
END IF
*
* W := W * V1
*
CALL DTRMM( 'RIGHT', 'UPPER', 'NO TRANSPOSE', 'UNIT', N,
$ K, ONE, V, LDV, WORK, LDWORK )
*
* C1 := C1 - W'
*
DO 150 J = 1, K
DO 140 I = 1, N
C( J, I ) = C( J, I ) - WORK( I, J )
140 CONTINUE
150 CONTINUE
*
ELSE IF( LSAME( SIDE, 'R' ) ) THEN
*
* FORM C * H OR C * H' WHERE C = ( C1 C2 )
*
* W := C * V' = (C1*V1' + C2*V2') (STORED IN WORK)
*
* W := C1
*
DO 160 J = 1, K
CALL DCOPY( M, C( 1, J ), 1, WORK( 1, J ), 1 )
160 CONTINUE
*
* W := W * V1'
*
CALL DTRMM( 'RIGHT', 'UPPER', 'TRANSPOSE', 'UNIT', M, K,
$ ONE, V, LDV, WORK, LDWORK )
IF( N.GT.K ) THEN
*
* W := W + C2 * V2'
*
CALL DGEMM( 'NO TRANSPOSE', 'TRANSPOSE', M, K, N-K,
$ ONE, C( 1, K+1 ), LDC, V( 1, K+1 ), LDV,
$ ONE, WORK, LDWORK )
END IF
*
* W := W * T OR W * T'
*
CALL DTRMM( 'RIGHT', 'UPPER', TRANS, 'NON-UNIT', M, K,
$ ONE, T, LDT, WORK, LDWORK )
*
* C := C - W * V
*
IF( N.GT.K ) THEN
*
* C2 := C2 - W * V2
*
CALL DGEMM( 'NO TRANSPOSE', 'NO TRANSPOSE', M, N-K, K,
$ -ONE, WORK, LDWORK, V( 1, K+1 ), LDV, ONE,
$ C( 1, K+1 ), LDC )
END IF
*
* W := W * V1
*
CALL DTRMM( 'RIGHT', 'UPPER', 'NO TRANSPOSE', 'UNIT', M,
$ K, ONE, V, LDV, WORK, LDWORK )
*
* C1 := C1 - W
*
DO 180 J = 1, K
DO 170 I = 1, M
C( I, J ) = C( I, J ) - WORK( I, J )
170 CONTINUE
180 CONTINUE
*
END IF
*
ELSE
*
* LET V = ( V1 V2 ) (V2: LAST K COLUMNS)
* WHERE V2 IS UNIT LOWER TRIANGULAR.
*
IF( LSAME( SIDE, 'L' ) ) THEN
*
* FORM H * C OR H' * C WHERE C = ( C1 )
* ( C2 )
*
* W := C' * V' = (C1'*V1' + C2'*V2') (STORED IN WORK)
*
* W := C2'
*
DO 190 J = 1, K
CALL DCOPY( N, C( M-K+J, 1 ), LDC, WORK( 1, J ), 1 )
190 CONTINUE
*
* W := W * V2'
*
CALL DTRMM( 'RIGHT', 'LOWER', 'TRANSPOSE', 'UNIT', N, K,
$ ONE, V( 1, M-K+1 ), LDV, WORK, LDWORK )
IF( M.GT.K ) THEN
*
* W := W + C1'*V1'
*
CALL DGEMM( 'TRANSPOSE', 'TRANSPOSE', N, K, M-K, ONE,
$ C, LDC, V, LDV, ONE, WORK, LDWORK )
END IF
*
* W := W * T' OR W * T
*
CALL DTRMM( 'RIGHT', 'LOWER', TRANST, 'NON-UNIT', N, K,
$ ONE, T, LDT, WORK, LDWORK )
*
* C := C - V' * W'
*
IF( M.GT.K ) THEN
*
* C1 := C1 - V1' * W'
*
CALL DGEMM( 'TRANSPOSE', 'TRANSPOSE', M-K, N, K, -ONE,
$ V, LDV, WORK, LDWORK, ONE, C, LDC )
END IF
*
* W := W * V2
*
CALL DTRMM( 'RIGHT', 'LOWER', 'NO TRANSPOSE', 'UNIT', N,
$ K, ONE, V( 1, M-K+1 ), LDV, WORK, LDWORK )
*
* C2 := C2 - W'
*
DO 210 J = 1, K
DO 200 I = 1, N
C( M-K+J, I ) = C( M-K+J, I ) - WORK( I, J )
200 CONTINUE
210 CONTINUE
*
ELSE IF( LSAME( SIDE, 'R' ) ) THEN
*
* FORM C * H OR C * H' WHERE C = ( C1 C2 )
*
* W := C * V' = (C1*V1' + C2*V2') (STORED IN WORK)
*
* W := C2
*
DO 220 J = 1, K
CALL DCOPY( M, C( 1, N-K+J ), 1, WORK( 1, J ), 1 )
220 CONTINUE
*
* W := W * V2'
*
CALL DTRMM( 'RIGHT', 'LOWER', 'TRANSPOSE', 'UNIT', M, K,
$ ONE, V( 1, N-K+1 ), LDV, WORK, LDWORK )
IF( N.GT.K ) THEN
*
* W := W + C1 * V1'
*
CALL DGEMM( 'NO TRANSPOSE', 'TRANSPOSE', M, K, N-K,
$ ONE, C, LDC, V, LDV, ONE, WORK, LDWORK )
END IF
*
* W := W * T OR W * T'
*
CALL DTRMM( 'RIGHT', 'LOWER', TRANS, 'NON-UNIT', M, K,
$ ONE, T, LDT, WORK, LDWORK )
*
* C := C - W * V
*
IF( N.GT.K ) THEN
*
* C1 := C1 - W * V1
*
CALL DGEMM( 'NO TRANSPOSE', 'NO TRANSPOSE', M, N-K, K,
$ -ONE, WORK, LDWORK, V, LDV, ONE, C, LDC )
END IF
*
* W := W * V2
*
CALL DTRMM( 'RIGHT', 'LOWER', 'NO TRANSPOSE', 'UNIT', M,
$ K, ONE, V( 1, N-K+1 ), LDV, WORK, LDWORK )
*
* C1 := C1 - W
*
DO 240 J = 1, K
DO 230 I = 1, M
C( I, N-K+J ) = C( I, N-K+J ) - WORK( I, J )
230 CONTINUE
240 CONTINUE
*
END IF
*
END IF
END IF
*
RETURN
*
* END OF DLARFB
*
END
CUT HERE............
CAT > DLARFT.F <<'CUT HERE............'
SUBROUTINE DLARFT( DIRECT, STOREV, N, K, V, LDV, TAU, T, LDT )
*
* -- LAPACK AUXILIARY ROUTINE (VERSION 1.1) --
* UNIV. OF TENNESSEE, UNIV. OF CALIFORNIA BERKELEY, NAG LTD.,
* COURANT INSTITUTE, ARGONNE NATIONAL LAB, AND RICE UNIVERSITY
* FEBRUARY 29, 1992
*
* .. SCALAR ARGUMENTS ..
CHARACTER DIRECT, STOREV
INTEGER K, LDT, LDV, N
* ..
* .. ARRAY ARGUMENTS ..
DOUBLE PRECISION T( LDT, * ), TAU( * ), V( LDV, * )
* ..
*
* PURPOSE
* =======
*
* DLARFT FORMS THE TRIANGULAR FACTOR T OF A REAL BLOCK REFLECTOR H
* OF ORDER N, WHICH IS DEFINED AS A PRODUCT OF K ELEMENTARY REFLECTORS.
*
* IF DIRECT = 'F', H = H(1) H(2) . . . H(K) AND T IS UPPER TRIANGULAR;
*
* IF DIRECT = 'B', H = H(K) . . . H(2) H(1) AND T IS LOWER TRIANGULAR.
*
* IF STOREV = 'C', THE VECTOR WHICH DEFINES THE ELEMENTARY REFLECTOR
* H(I) IS STORED IN THE I-TH COLUMN OF THE ARRAY V, AND
*
* H = I - V * T * V'
*
* IF STOREV = 'R', THE VECTOR WHICH DEFINES THE ELEMENTARY REFLECTOR
* H(I) IS STORED IN THE I-TH ROW OF THE ARRAY V, AND
*
* H = I - V' * T * V
*
* ARGUMENTS
* =========
*
* DIRECT (INPUT) CHARACTER*1
* SPECIFIES THE ORDER IN WHICH THE ELEMENTARY REFLECTORS ARE
* MULTIPLIED TO FORM THE BLOCK REFLECTOR:
* = 'F': H = H(1) H(2) . . . H(K) (FORWARD)
* = 'B': H = H(K) . . . H(2) H(1) (BACKWARD)
*
* STOREV (INPUT) CHARACTER*1
* SPECIFIES HOW THE VECTORS WHICH DEFINE THE ELEMENTARY
* REFLECTORS ARE STORED (SEE ALSO FURTHER DETAILS):
* = 'C': COLUMNWISE
* = 'R': ROWWISE
*
* N (INPUT) INTEGER
* THE ORDER OF THE BLOCK REFLECTOR H. N >= 0.
*
* K (INPUT) INTEGER
* THE ORDER OF THE TRIANGULAR FACTOR T (= THE NUMBER OF
* ELEMENTARY REFLECTORS). K >= 1.
*
* V (INPUT/OUTPUT) DOUBLE PRECISION ARRAY, DIMENSION
* (LDV,K) IF STOREV = 'C'
* (LDV,N) IF STOREV = 'R'
* THE MATRIX V. SEE FURTHER DETAILS.
*
* LDV (INPUT) INTEGER
* THE LEADING DIMENSION OF THE ARRAY V.
* IF STOREV = 'C', LDV >= MAX(1,N); IF STOREV = 'R', LDV >= K.
*
* TAU (INPUT) DOUBLE PRECISION ARRAY, DIMENSION (K)
* TAU(I) MUST CONTAIN THE SCALAR FACTOR OF THE ELEMENTARY
* REFLECTOR H(I).
*
* T (OUTPUT) DOUBLE PRECISION ARRAY, DIMENSION (LDT,K)
* THE K BY K TRIANGULAR FACTOR T OF THE BLOCK REFLECTOR.
* IF DIRECT = 'F', T IS UPPER TRIANGULAR; IF DIRECT = 'B', T IS
* LOWER TRIANGULAR. THE REST OF THE ARRAY IS NOT USED.
*
* LDT (INPUT) INTEGER
* THE LEADING DIMENSION OF THE ARRAY T. LDT >= K.
*
* FURTHER DETAILS
* ===============
*
* THE SHAPE OF THE MATRIX V AND THE STORAGE OF THE VECTORS WHICH DEFINE
* THE H(I) IS BEST ILLUSTRATED BY THE FOLLOWING EXAMPLE WITH N = 5 AND
* K = 3. THE ELEMENTS EQUAL TO 1 ARE NOT STORED; THE CORRESPONDING
* ARRAY ELEMENTS ARE MODIFIED BUT RESTORED ON EXIT. THE REST OF THE
* ARRAY IS NOT USED.
*
* DIRECT = 'F' AND STOREV = 'C': DIRECT = 'F' AND STOREV = 'R':
*
* V = ( 1 ) V = ( 1 V1 V1 V1 V1 )
* ( V1 1 ) ( 1 V2 V2 V2 )
* ( V1 V2 1 ) ( 1 V3 V3 )
* ( V1 V2 V3 )
* ( V1 V2 V3 )
*
* DIRECT = 'B' AND STOREV = 'C': DIRECT = 'B' AND STOREV = 'R':
*
* V = ( V1 V2 V3 ) V = ( V1 V1 1 )
* ( V1 V2 V3 ) ( V2 V2 V2 1 )
* ( 1 V2 V3 ) ( V3 V3 V3 V3 1 )
* ( 1 V3 )
* ( 1 )
*
* =====================================================================
*
* .. PARAMETERS ..
DOUBLE PRECISION ONE, ZERO
PARAMETER ( ONE = 1.0D+0, ZERO = 0.0D+0 )
* ..
* .. LOCAL SCALARS ..
INTEGER I, J
DOUBLE PRECISION VII
* ..
* .. EXTERNAL SUBROUTINES ..
EXTERNAL DGEMV, DTRMV
* ..
* .. EXTERNAL FUNCTIONS ..
LOGICAL LSAME
EXTERNAL LSAME
* ..
* .. EXECUTABLE STATEMENTS ..
*
* QUICK RETURN IF POSSIBLE
*
IF( N.EQ.0 )
$ RETURN
*
IF( LSAME( DIRECT, 'F' ) ) THEN
DO 20 I = 1, K
IF( TAU( I ).EQ.ZERO ) THEN
*
* H(I) = I
*
DO 10 J = 1, I
T( J, I ) = ZERO
10 CONTINUE
ELSE
*
* GENERAL CASE
*
VII = V( I, I )
V( I, I ) = ONE
IF( LSAME( STOREV, 'C' ) ) THEN
*
* T(1:I-1,I) := - TAU(I) * V(I:N,1:I-1)' * V(I:N,I)
*
CALL DGEMV( 'TRANSPOSE', N-I+1, I-1, -TAU( I ),
$ V( I, 1 ), LDV, V( I, I ), 1, ZERO,
$ T( 1, I ), 1 )
ELSE
*
* T(1:I-1,I) := - TAU(I) * V(1:I-1,I:N) * V(I,I:N)'
*
CALL DGEMV( 'NO TRANSPOSE', I-1, N-I+1, -TAU( I ),
$ V( 1, I ), LDV, V( I, I ), LDV, ZERO,
$ T( 1, I ), 1 )
END IF
V( I, I ) = VII
*
* T(1:I-1,I) := T(1:I-1,1:I-1) * T(1:I-1,I)
*
CALL DTRMV( 'UPPER', 'NO TRANSPOSE', 'NON-UNIT', I-1, T,
$ LDT, T( 1, I ), 1 )
T( I, I ) = TAU( I )
END IF
20 CONTINUE
ELSE
DO 40 I = K, 1, -1
IF( TAU( I ).EQ.ZERO ) THEN
*
* H(I) = I
*
DO 30 J = I, K
T( J, I ) = ZERO
30 CONTINUE
ELSE
*
* GENERAL CASE
*
IF( I.LT.K ) THEN
IF( LSAME( STOREV, 'C' ) ) THEN
VII = V( N-K+I, I )
V( N-K+I, I ) = ONE
*
* T(I+1:K,I) :=
* - TAU(I) * V(1:N-K+I,I+1:K)' * V(1:N-K+I,I)
*
CALL DGEMV( 'TRANSPOSE', N-K+I, K-I, -TAU( I ),
$ V( 1, I+1 ), LDV, V( 1, I ), 1, ZERO,
$ T( I+1, I ), 1 )
V( N-K+I, I ) = VII
ELSE
VII = V( I, N-K+I )
V( I, N-K+I ) = ONE
*
* T(I+1:K,I) :=
* - TAU(I) * V(I+1:K,1:N-K+I) * V(I,1:N-K+I)'
*
CALL DGEMV( 'NO TRANSPOSE', K-I, N-K+I, -TAU( I ),
$ V( I+1, 1 ), LDV, V( I, 1 ), LDV, ZERO,
$ T( I+1, I ), 1 )
V( I, N-K+I ) = VII
END IF
*
* T(I+1:K,I) := T(I+1:K,I+1:K) * T(I+1:K,I)
*
CALL DTRMV( 'LOWER', 'NO TRANSPOSE', 'NON-UNIT', K-I,
$ T( I+1, I+1 ), LDT, T( I+1, I ), 1 )
END IF
T( I, I ) = TAU( I )
END IF
40 CONTINUE
END IF
RETURN
*
* END OF DLARFT
*
END
CUT HERE............
CAT > DORG2L.F <<'CUT HERE............'
SUBROUTINE DORG2L( M, N, K, A, LDA, TAU, WORK, INFO )
*
* -- LAPACK ROUTINE (VERSION 1.1) --
* UNIV. OF TENNESSEE, UNIV. OF CALIFORNIA BERKELEY, NAG LTD.,
* COURANT INSTITUTE, ARGONNE NATIONAL LAB, AND RICE UNIVERSITY
* FEBRUARY 29, 1992
*
* .. SCALAR ARGUMENTS ..
INTEGER INFO, K, LDA, M, N
* ..
* .. ARRAY ARGUMENTS ..
DOUBLE PRECISION A( LDA, * ), TAU( * ), WORK( * )
* ..
*
* PURPOSE
* =======
*
* DORG2L GENERATES AN M BY N REAL MATRIX Q WITH ORTHONORMAL COLUMNS,
* WHICH IS DEFINED AS THE LAST N COLUMNS OF A PRODUCT OF K ELEMENTARY
* REFLECTORS OF ORDER M
*
* Q = H(K) . . . H(2) H(1)
*
* AS RETURNED BY DGEQLF.
*
* ARGUMENTS
* =========
*
* M (INPUT) INTEGER
* THE NUMBER OF ROWS OF THE MATRIX Q. M >= 0.
*
* N (INPUT) INTEGER
* THE NUMBER OF COLUMNS OF THE MATRIX Q. M >= N >= 0.
*
* K (INPUT) INTEGER
* THE NUMBER OF ELEMENTARY REFLECTORS WHOSE PRODUCT DEFINES THE
* MATRIX Q. N >= K >= 0.
*
* A (INPUT/OUTPUT) DOUBLE PRECISION ARRAY, DIMENSION (LDA,N)
* ON ENTRY, THE (N-K+I)-TH COLUMN MUST CONTAIN THE VECTOR WHICH
* DEFINES THE ELEMENTARY REFLECTOR H(I), FOR I = 1,2,...,K, AS
* RETURNED BY DGEQLF IN THE LAST K COLUMNS OF ITS ARRAY
* ARGUMENT A.
* ON EXIT, THE M BY N MATRIX Q.
*
* LDA (INPUT) INTEGER
* THE FIRST DIMENSION OF THE ARRAY A. LDA >= MAX(1,M).
*
* TAU (INPUT) DOUBLE PRECISION ARRAY, DIMENSION (K)
* TAU(I) MUST CONTAIN THE SCALAR FACTOR OF THE ELEMENTARY
* REFLECTOR H(I), AS RETURNED BY DGEQLF.
*
* WORK (WORKSPACE) DOUBLE PRECISION ARRAY, DIMENSION (N)
*
* INFO (OUTPUT) INTEGER
* = 0: SUCCESSFUL EXIT
* < 0: IF INFO = -I, THE I-TH ARGUMENT HAS AN ILLEGAL VALUE
*
* =====================================================================
*
* .. PARAMETERS ..
DOUBLE PRECISION ONE, ZERO
PARAMETER ( ONE = 1.0D+0, ZERO = 0.0D+0 )
* ..
* .. LOCAL SCALARS ..
INTEGER I, II, J, L
* ..
* .. EXTERNAL SUBROUTINES ..
EXTERNAL DLARF, DSCAL, XERBLA
* ..
* .. INTRINSIC FUNCTIONS ..
INTRINSIC MAX
* ..
* .. EXECUTABLE STATEMENTS ..
*
* TEST THE INPUT ARGUMENTS
*
INFO = 0
IF( M.LT.0 ) THEN
INFO = -1
ELSE IF( N.LT.0 .OR. N.GT.M ) THEN
INFO = -2
ELSE IF( K.LT.0 .OR. K.GT.N ) THEN
INFO = -3
ELSE IF( LDA.LT.MAX( 1, M ) ) THEN
INFO = -5
END IF
IF( INFO.NE.0 ) THEN
CALL XERBLA( 'DORG2L', -INFO )
RETURN
END IF
*
* QUICK RETURN IF POSSIBLE
*
IF( N.LE.0 )
$ RETURN
*
* INITIALISE COLUMNS 1:N-K TO COLUMNS OF THE UNIT MATRIX
*
DO 20 J = 1, N - K
DO 10 L = 1, M
A( L, J ) = ZERO
10 CONTINUE
A( M-N+J, J ) = ONE
20 CONTINUE
*
DO 40 I = 1, K
II = N - K + I
*
* APPLY H(I) TO A(1:M-K+I,1:N-K+I) FROM THE LEFT
*
A( M-N+II, II ) = ONE
CALL DLARF( 'LEFT', M-N+II, II-1, A( 1, II ), 1, TAU( I ), A,
$ LDA, WORK )
CALL DSCAL( M-N+II-1, -TAU( I ), A( 1, II ), 1 )
A( M-N+II, II ) = ONE - TAU( I )
*
* SET A(M-K+I+1:M,N-K+I) TO ZERO
*
DO 30 L = M - N + II + 1, M
A( L, II ) = ZERO
30 CONTINUE
40 CONTINUE
RETURN
*
* END OF DORG2L
*
END
CUT HERE............
CAT > DLARF.F <<'CUT HERE............'
SUBROUTINE DLARF( SIDE, M, N, V, INCV, TAU, C, LDC, WORK )
*
* -- LAPACK AUXILIARY ROUTINE (VERSION 1.1) --
* UNIV. OF TENNESSEE, UNIV. OF CALIFORNIA BERKELEY, NAG LTD.,
* COURANT INSTITUTE, ARGONNE NATIONAL LAB, AND RICE UNIVERSITY
* FEBRUARY 29, 1992
*
* .. SCALAR ARGUMENTS ..
CHARACTER SIDE
INTEGER INCV, LDC, M, N
DOUBLE PRECISION TAU
* ..
* .. ARRAY ARGUMENTS ..
DOUBLE PRECISION C( LDC, * ), V( * ), WORK( * )
* ..
*
* PURPOSE
* =======
*
* DLARF APPLIES A REAL ELEMENTARY REFLECTOR H TO A REAL M BY N MATRIX
* C, FROM EITHER THE LEFT OR THE RIGHT. H IS REPRESENTED IN THE FORM
*
* H = I - TAU * V * V'
*
* WHERE TAU IS A REAL SCALAR AND V IS A REAL VECTOR.
*
* IF TAU = 0, THEN H IS TAKEN TO BE THE UNIT MATRIX.
*
* ARGUMENTS
* =========
*
* SIDE (INPUT) CHARACTER*1
* = 'L': FORM H * C
* = 'R': FORM C * H
*
* M (INPUT) INTEGER
* THE NUMBER OF ROWS OF THE MATRIX C.
*
* N (INPUT) INTEGER
* THE NUMBER OF COLUMNS OF THE MATRIX C.
*
* V (INPUT) DOUBLE PRECISION ARRAY, DIMENSION
* (1 + (M-1)*ABS(INCV)) IF SIDE = 'L'
* OR (1 + (N-1)*ABS(INCV)) IF SIDE = 'R'
* THE VECTOR V IN THE REPRESENTATION OF H. V IS NOT USED IF
* TAU = 0.
*
* INCV (INPUT) INTEGER
* THE INCREMENT BETWEEN ELEMENTS OF V. INCV <> 0.
*
* TAU (INPUT) DOUBLE PRECISION
* THE VALUE TAU IN THE REPRESENTATION OF H.
*
* C (INPUT/OUTPUT) DOUBLE PRECISION ARRAY, DIMENSION (LDC,N)
* ON ENTRY, THE M BY N MATRIX C.
* ON EXIT, C IS OVERWRITTEN BY THE MATRIX H * C IF SIDE = 'L',
* OR C * H IF SIDE = 'R'.
*
* LDC (INPUT) INTEGER
* THE LEADING DIMENSION OF THE ARRAY C. LDC >= MAX(1,M).
*
* WORK (WORKSPACE) DOUBLE PRECISION ARRAY, DIMENSION
* (N) IF SIDE = 'L'
* OR (M) IF SIDE = 'R'
*
* =====================================================================
*
* .. PARAMETERS ..
DOUBLE PRECISION ONE, ZERO
PARAMETER ( ONE = 1.0D+0, ZERO = 0.0D+0 )
* ..
* .. EXTERNAL SUBROUTINES ..
EXTERNAL DGEMV, DGER
* ..
* .. EXTERNAL FUNCTIONS ..
LOGICAL LSAME
EXTERNAL LSAME
* ..
* .. EXECUTABLE STATEMENTS ..
*
IF( LSAME( SIDE, 'L' ) ) THEN
*
* FORM H * C
*
IF( TAU.NE.ZERO ) THEN
*
* W := C' * V
*
CALL DGEMV( 'TRANSPOSE', M, N, ONE, C, LDC, V, INCV, ZERO,
$ WORK, 1 )
*
* C := C - V * W'
*
CALL DGER( M, N, -TAU, V, INCV, WORK, 1, C, LDC )
END IF
ELSE
*
* FORM C * H
*
IF( TAU.NE.ZERO ) THEN
*
* W := C * V
*
CALL DGEMV( 'NO TRANSPOSE', M, N, ONE, C, LDC, V, INCV,
$ ZERO, WORK, 1 )
*
* C := C - W * V'
*
CALL DGER( M, N, -TAU, WORK, 1, V, INCV, C, LDC )
END IF
END IF
RETURN
*
* END OF DLARF
*
END
CUT HERE............
CAT > DLACPY.F <<'CUT HERE............'
SUBROUTINE DLACPY( UPLO, M, N, A, LDA, B, LDB )
*
* -- LAPACK AUXILIARY ROUTINE (VERSION 1.1) --
* UNIV. OF TENNESSEE, UNIV. OF CALIFORNIA BERKELEY, NAG LTD.,
* COURANT INSTITUTE, ARGONNE NATIONAL LAB, AND RICE UNIVERSITY
* FEBRUARY 29, 1992
*
* .. SCALAR ARGUMENTS ..
CHARACTER UPLO
INTEGER LDA, LDB, M, N
* ..
* .. ARRAY ARGUMENTS ..
DOUBLE PRECISION A( LDA, * ), B( LDB, * )
* ..
*
* PURPOSE
* =======
*
* DLACPY COPIES ALL OR PART OF A TWO-DIMENSIONAL MATRIX A TO ANOTHER
* MATRIX B.
*
* ARGUMENTS
* =========
*
* UPLO (INPUT) CHARACTER*1
* SPECIFIES THE PART OF THE MATRIX A TO BE COPIED TO B.
* = 'U': UPPER TRIANGULAR PART
* = 'L': LOWER TRIANGULAR PART
* OTHERWISE: ALL OF THE MATRIX A
*
* M (INPUT) INTEGER
* THE NUMBER OF ROWS OF THE MATRIX A. M >= 0.
*
* N (INPUT) INTEGER
* THE NUMBER OF COLUMNS OF THE MATRIX A. N >= 0.
*
* A (INPUT) DOUBLE PRECISION ARRAY, DIMENSION (LDA,N)
* THE M BY N MATRIX A. IF UPLO = 'U', ONLY THE UPPER TRIANGLE
* OR TRAPEZOID IS ACCESSED; IF UPLO = 'L', ONLY THE LOWER
* TRIANGLE OR TRAPEZOID IS ACCESSED.
*
* LDA (INPUT) INTEGER
* THE LEADING DIMENSION OF THE ARRAY A. LDA >= MAX(1,M).
*
* B (OUTPUT) DOUBLE PRECISION ARRAY, DIMENSION (LDB,N)
* ON EXIT, B = A IN THE LOCATIONS SPECIFIED BY UPLO.
*
* LDB (INPUT) INTEGER
* THE LEADING DIMENSION OF THE ARRAY B. LDB >= MAX(1,M).
*
* =====================================================================
*
* .. LOCAL SCALARS ..
INTEGER I, J
* ..
* .. EXTERNAL FUNCTIONS ..
LOGICAL LSAME
EXTERNAL LSAME
* ..
* .. INTRINSIC FUNCTIONS ..
INTRINSIC MIN
* ..
* .. EXECUTABLE STATEMENTS ..
*
IF( LSAME( UPLO, 'U' ) ) THEN
DO 20 J = 1, N
DO 10 I = 1, MIN( J, M )
B( I, J ) = A( I, J )
10 CONTINUE
20 CONTINUE
ELSE IF( LSAME( UPLO, 'L' ) ) THEN
DO 40 J = 1, N
DO 30 I = J, M
B( I, J ) = A( I, J )
30 CONTINUE
40 CONTINUE
ELSE
DO 60 J = 1, N
DO 50 I = 1, M
B( I, J ) = A( I, J )
50 CONTINUE
60 CONTINUE
END IF
RETURN
*
* END OF DLACPY
*
END
CUT HERE............
CAT > DSTERF.F <<'CUT HERE............'
SUBROUTINE DSTERF( N, D, E, INFO )
*
* -- LAPACK ROUTINE (VERSION 1.1) --
* UNIV. OF TENNESSEE, UNIV. OF CALIFORNIA BERKELEY, NAG LTD.,
* COURANT INSTITUTE, ARGONNE NATIONAL LAB, AND RICE UNIVERSITY
* MARCH 31, 1993
*
* .. SCALAR ARGUMENTS ..
INTEGER INFO, N
* ..
* .. ARRAY ARGUMENTS ..
DOUBLE PRECISION D( * ), E( * )
* ..
*
* PURPOSE
* =======
*
* DSTERF COMPUTES ALL EIGENVALUES OF A SYMMETRIC TRIDIAGONAL MATRIX
* USING THE PAL-WALKER-KAHAN VARIANT OF THE QL OR QR ALGORITHM.
*
* ARGUMENTS
* =========
*
* N (INPUT) INTEGER
* THE ORDER OF THE MATRIX. N >= 0.
*
* D (INPUT/OUTPUT) DOUBLE PRECISION ARRAY, DIMENSION (N)
* ON ENTRY, THE N DIAGONAL ELEMENTS OF THE TRIDIAGONAL MATRIX.
* ON EXIT, IF INFO = 0, THE EIGENVALUES IN ASCENDING ORDER.
*
* E (INPUT/OUTPUT) DOUBLE PRECISION ARRAY, DIMENSION (N-1)
* ON ENTRY, THE (N-1) SUBDIAGONAL ELEMENTS OF THE TRIDIAGONAL
* MATRIX.
* ON EXIT, E HAS BEEN DESTROYED.
*
* INFO (OUTPUT) INTEGER
* = 0: SUCCESSFUL EXIT
* < 0: IF INFO = -I, THE I-TH ARGUMENT HAD AN ILLEGAL VALUE
* > 0: THE ALGORITHM FAILED TO FIND ALL OF THE EIGENVALUES IN
* A TOTAL OF 30*N ITERATIONS; IF INFO = I, THEN I
* ELEMENTS OF E HAVE NOT CONVERGED TO ZERO.
*
* =====================================================================
*
* .. PARAMETERS ..
DOUBLE PRECISION ZERO, ONE, TWO
PARAMETER ( ZERO = 0.0D0, ONE = 1.0D0, TWO = 2.0D0 )
INTEGER MAXIT
PARAMETER ( MAXIT = 30 )
* ..
* .. LOCAL SCALARS ..
INTEGER I, II, J, JTOT, K, L, L1, LEND, LENDM1, LENDP1,
$ LM1, M, MM1, NM1, NMAXIT
DOUBLE PRECISION ALPHA, BB, C, EPS, GAMMA, OLDC, OLDGAM, P, R,
$ RT1, RT2, RTE, S, SIGMA, TST
* ..
* .. EXTERNAL FUNCTIONS ..
DOUBLE PRECISION DLAMCH, DLAPY2
EXTERNAL DLAMCH, DLAPY2
* ..
* .. EXTERNAL SUBROUTINES ..
EXTERNAL DLAE2, XERBLA
* ..
* .. INTRINSIC FUNCTIONS ..
INTRINSIC ABS, SIGN, SQRT
* ..
* .. EXECUTABLE STATEMENTS ..
*
* TEST THE INPUT PARAMETERS.
*
INFO = 0
*
* QUICK RETURN IF POSSIBLE
*
IF( N.LT.0 ) THEN
INFO = -1
CALL XERBLA( 'DSTERF', -INFO )
RETURN
END IF
IF( N.LE.1 )
$ RETURN
*
* DETERMINE THE UNIT ROUNDOFF FOR THIS ENVIRONMENT.
*
EPS = DLAMCH( 'E' )
*
* COMPUTE THE EIGENVALUES OF THE TRIDIAGONAL MATRIX.
*
DO 10 I = 1, N - 1
E( I ) = E( I )**2
10 CONTINUE
*
NMAXIT = N*MAXIT
SIGMA = ZERO
JTOT = 0
*
* DETERMINE WHERE THE MATRIX SPLITS AND CHOOSE QL OR QR ITERATION
* FOR EACH BLOCK, ACCORDING TO WHETHER TOP OR BOTTOM DIAGONAL
* ELEMENT IS SMALLER.
*
L1 = 1
NM1 = N - 1
*
20 CONTINUE
IF( L1.GT.N )
$ GO TO 170
IF( L1.GT.1 )
$ E( L1-1 ) = ZERO
IF( L1.LE.NM1 ) THEN
DO 30 M = L1, NM1
TST = SQRT( ABS( E( M ) ) )
IF( TST.LE.EPS*( ABS( D( M ) )+ABS( D( M+1 ) ) ) )
$ GO TO 40
30 CONTINUE
END IF
M = N
*
40 CONTINUE
L = L1
LEND = M
IF( ABS( D( LEND ) ).LT.ABS( D( L ) ) ) THEN
L = LEND
LEND = L1
END IF
L1 = M + 1
*
IF( LEND.GE.L ) THEN
*
* QL ITERATION
*
* LOOK FOR SMALL SUBDIAGONAL ELEMENT.
*
50 CONTINUE
IF( L.NE.LEND ) THEN
LENDM1 = LEND - 1
DO 60 M = L, LENDM1
TST = SQRT( ABS( E( M ) ) )
IF( TST.LE.EPS*( ABS( D( M ) )+ABS( D( M+1 ) ) ) )
$ GO TO 70
60 CONTINUE
END IF
*
M = LEND
*
70 CONTINUE
IF( M.LT.LEND )
$ E( M ) = ZERO
P = D( L )
IF( M.EQ.L )
$ GO TO 90
*
* IF REMAINING MATRIX IS 2 BY 2, USE DLAE2 TO COMPUTE ITS
* EIGENVALUES.
*
IF( M.EQ.L+1 ) THEN
RTE = SQRT( E( L ) )
CALL DLAE2( D( L ), RTE, D( L+1 ), RT1, RT2 )
D( L ) = RT1
D( L+1 ) = RT2
E( L ) = ZERO
L = L + 2
IF( L.LE.LEND )
$ GO TO 50
GO TO 20
END IF
*
IF( JTOT.EQ.NMAXIT )
$ GO TO 150
JTOT = JTOT + 1
*
* FORM SHIFT.
*
RTE = SQRT( E( L ) )
SIGMA = ( D( L+1 )-P ) / ( TWO*RTE )
R = DLAPY2( SIGMA, ONE )
SIGMA = P - ( RTE / ( SIGMA+SIGN( R, SIGMA ) ) )
*
C = ONE
S = ZERO
GAMMA = D( M ) - SIGMA
P = GAMMA*GAMMA
*
* INNER LOOP
*
MM1 = M - 1
DO 80 I = MM1, L, -1
BB = E( I )
R = P + BB
IF( I.NE.M-1 )
$ E( I+1 ) = S*R
OLDC = C
C = P / R
S = BB / R
OLDGAM = GAMMA
ALPHA = D( I )
GAMMA = C*( ALPHA-SIGMA ) - S*OLDGAM
D( I+1 ) = OLDGAM + ( ALPHA-GAMMA )
IF( C.NE.ZERO ) THEN
P = ( GAMMA*GAMMA ) / C
ELSE
P = OLDC*BB
END IF
80 CONTINUE
*
E( L ) = S*P
D( L ) = SIGMA + GAMMA
GO TO 50
*
* EIGENVALUE FOUND.
*
90 CONTINUE
D( L ) = P
*
L = L + 1
IF( L.LE.LEND )
$ GO TO 50
GO TO 20
*
ELSE
*
* QR ITERATION
*
* LOOK FOR SMALL SUPERDIAGONAL ELEMENT.
*
100 CONTINUE
IF( L.NE.LEND ) THEN
LENDP1 = LEND + 1
DO 110 M = L, LENDP1, -1
TST = SQRT( ABS( E( M-1 ) ) )
IF( TST.LE.EPS*( ABS( D( M ) )+ABS( D( M-1 ) ) ) )
$ GO TO 120
110 CONTINUE
END IF
*
M = LEND
*
120 CONTINUE
IF( M.GT.LEND )
$ E( M-1 ) = ZERO
P = D( L )
IF( M.EQ.L )
$ GO TO 140
*
* IF REMAINING MATRIX IS 2 BY 2, USE DLAE2 TO COMPUTE ITS
* EIGENVALUES.
*
IF( M.EQ.L-1 ) THEN
RTE = SQRT( E( L-1 ) )
CALL DLAE2( D( L ), RTE, D( L-1 ), RT1, RT2 )
D( L ) = RT1
D( L-1 ) = RT2
E( L-1 ) = ZERO
L = L - 2
IF( L.GE.LEND )
$ GO TO 100
GO TO 20
END IF
*
IF( JTOT.EQ.NMAXIT )
$ GO TO 150
JTOT = JTOT + 1
*
* FORM SHIFT.
*
RTE = SQRT( E( L-1 ) )
SIGMA = ( D( L-1 )-P ) / ( TWO*RTE )
R = DLAPY2( SIGMA, ONE )
SIGMA = P - ( RTE / ( SIGMA+SIGN( R, SIGMA ) ) )
*
C = ONE
S = ZERO
GAMMA = D( M ) - SIGMA
P = GAMMA*GAMMA
*
* INNER LOOP
*
LM1 = L - 1
DO 130 I = M, LM1
BB = E( I )
R = P + BB
IF( I.NE.M )
$ E( I-1 ) = S*R
OLDC = C
C = P / R
S = BB / R
OLDGAM = GAMMA
ALPHA = D( I+1 )
GAMMA = C*( ALPHA-SIGMA ) - S*OLDGAM
D( I ) = OLDGAM + ( ALPHA-GAMMA )
IF( C.NE.ZERO ) THEN
P = ( GAMMA*GAMMA ) / C
ELSE
P = OLDC*BB
END IF
130 CONTINUE
*
E( LM1 ) = S*P
D( L ) = SIGMA + GAMMA
GO TO 100
*
* EIGENVALUE FOUND.
*
140 CONTINUE
D( L ) = P
*
L = L - 1
IF( L.GE.LEND )
$ GO TO 100
GO TO 20
*
END IF
*
* SET ERROR -- NO CONVERGENCE TO AN EIGENVALUE AFTER A TOTAL
* OF N*MAXIT ITERATIONS.
*
150 CONTINUE
DO 160 I = 1, N - 1
IF( E( I ).NE.ZERO )
$ INFO = INFO + 1
160 CONTINUE
RETURN
*
* SORT EIGENVALUES IN INCREASING ORDER.
*
170 CONTINUE
DO 190 II = 2, N
I = II - 1
K = I
P = D( I )
DO 180 J = II, N
IF( D( J ).LT.P ) THEN
K = J
P = D( J )
END IF
180 CONTINUE
IF( K.NE.I ) THEN
D( K ) = D( I )
D( I ) = P
END IF
190 CONTINUE
*
RETURN
*
* END OF DSTERF
*
END
CUT HERE............
CAT > DLAE2.F <<'CUT HERE............'
SUBROUTINE DLAE2( A, B, C, RT1, RT2 )
*
* -- LAPACK AUXILIARY ROUTINE (VERSION 1.1) --
* UNIV. OF TENNESSEE, UNIV. OF CALIFORNIA BERKELEY, NAG LTD.,
* COURANT INSTITUTE, ARGONNE NATIONAL LAB, AND RICE UNIVERSITY
* OCTOBER 31, 1992
*
* .. SCALAR ARGUMENTS ..
DOUBLE PRECISION A, B, C, RT1, RT2
* ..
*
* PURPOSE
* =======
*
* DLAE2 COMPUTES THE EIGENVALUES OF A 2-BY-2 SYMMETRIC MATRIX
* [ A B ]
* [ B C ].
* ON RETURN, RT1 IS THE EIGENVALUE OF LARGER ABSOLUTE VALUE, AND RT2
* IS THE EIGENVALUE OF SMALLER ABSOLUTE VALUE.
*
* ARGUMENTS
* =========
*
* A (INPUT) DOUBLE PRECISION
* THE (1,1) ENTRY OF THE 2-BY-2 MATRIX.
*
* B (INPUT) DOUBLE PRECISION
* THE (1,2) AND (2,1) ENTRIES OF THE 2-BY-2 MATRIX.
*
* C (INPUT) DOUBLE PRECISION
* THE (2,2) ENTRY OF THE 2-BY-2 MATRIX.
*
* RT1 (OUTPUT) DOUBLE PRECISION
* THE EIGENVALUE OF LARGER ABSOLUTE VALUE.
*
* RT2 (OUTPUT) DOUBLE PRECISION
* THE EIGENVALUE OF SMALLER ABSOLUTE VALUE.
*
* FURTHER DETAILS
* ===============
*
* RT1 IS ACCURATE TO A FEW ULPS BARRING OVER/UNDERFLOW.
*
* RT2 MAY BE INACCURATE IF THERE IS MASSIVE CANCELLATION IN THE
* DETERMINANT A*C-B*B; HIGHER PRECISION OR CORRECTLY ROUNDED OR
* CORRECTLY TRUNCATED ARITHMETIC WOULD BE NEEDED TO COMPUTE RT2
* ACCURATELY IN ALL CASES.
*
* OVERFLOW IS POSSIBLE ONLY IF RT1 IS WITHIN A FACTOR OF 5 OF OVERFLOW.
* UNDERFLOW IS HARMLESS IF THE INPUT DATA IS 0 OR EXCEEDS
* UNDERFLOW_THRESHOLD / MACHEPS.
*
* =====================================================================
*
* .. PARAMETERS ..
DOUBLE PRECISION ONE
PARAMETER ( ONE = 1.0D0 )
DOUBLE PRECISION TWO
PARAMETER ( TWO = 2.0D0 )
DOUBLE PRECISION ZERO
PARAMETER ( ZERO = 0.0D0 )
DOUBLE PRECISION HALF
PARAMETER ( HALF = 0.5D0 )
* ..
* .. LOCAL SCALARS ..
DOUBLE PRECISION AB, ACMN, ACMX, ADF, DF, RT, SM, TB
* ..
* .. INTRINSIC FUNCTIONS ..
INTRINSIC ABS, SQRT
* ..
* .. EXECUTABLE STATEMENTS ..
*
* COMPUTE THE EIGENVALUES
*
SM = A + C
DF = A - C
ADF = ABS( DF )
TB = B + B
AB = ABS( TB )
IF( ABS( A ).GT.ABS( C ) ) THEN
ACMX = A
ACMN = C
ELSE
ACMX = C
ACMN = A
END IF
IF( ADF.GT.AB ) THEN
RT = ADF*SQRT( ONE+( AB / ADF )**2 )
ELSE IF( ADF.LT.AB ) THEN
RT = AB*SQRT( ONE+( ADF / AB )**2 )
ELSE
*
* INCLUDES CASE AB=ADF=0
*
RT = AB*SQRT( TWO )
END IF
IF( SM.LT.ZERO ) THEN
RT1 = HALF*( SM-RT )
*
* ORDER OF EXECUTION IMPORTANT.
* TO GET FULLY ACCURATE SMALLER EIGENVALUE,
* NEXT LINE NEEDS TO BE EXECUTED IN HIGHER PRECISION.
*
RT2 = ( ACMX / RT1 )*ACMN - ( B / RT1 )*B
ELSE IF( SM.GT.ZERO ) THEN
RT1 = HALF*( SM+RT )
*
* ORDER OF EXECUTION IMPORTANT.
* TO GET FULLY ACCURATE SMALLER EIGENVALUE,
* NEXT LINE NEEDS TO BE EXECUTED IN HIGHER PRECISION.
*
RT2 = ( ACMX / RT1 )*ACMN - ( B / RT1 )*B
ELSE
*
* INCLUDES CASE RT1 = RT2 = 0
*
RT1 = HALF*RT
RT2 = -HALF*RT
END IF
RETURN
*
* END OF DLAE2
*
END
CUT HERE............
CAT > DSYTRD.F <<'CUT HERE............'
SUBROUTINE DSYTRD( UPLO, N, A, LDA, D, E, TAU, WORK, LWORK, INFO )
*
* -- LAPACK ROUTINE (VERSION 1.1) --
* UNIV. OF TENNESSEE, UNIV. OF CALIFORNIA BERKELEY, NAG LTD.,
* COURANT INSTITUTE, ARGONNE NATIONAL LAB, AND RICE UNIVERSITY
* MARCH 31, 1993
*
* .. SCALAR ARGUMENTS ..
CHARACTER UPLO
INTEGER INFO, LDA, LWORK, N
* ..
* .. ARRAY ARGUMENTS ..
DOUBLE PRECISION A( LDA, * ), D( * ), E( * ), TAU( * ),
$ WORK( * )
* ..
*
* PURPOSE
* =======
*
* DSYTRD REDUCES A REAL SYMMETRIC MATRIX A TO REAL SYMMETRIC
* TRIDIAGONAL FORM T BY AN ORTHOGONAL SIMILARITY TRANSFORMATION:
* Q**T * A * Q = T.
*
* ARGUMENTS
* =========
*
* UPLO (INPUT) CHARACTER*1
* = 'U': UPPER TRIANGLE OF A IS STORED;
* = 'L': LOWER TRIANGLE OF A IS STORED.
*
* N (INPUT) INTEGER
* THE ORDER OF THE MATRIX A. N >= 0.
*
* A (INPUT/OUTPUT) DOUBLE PRECISION 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, AND THE STRICTLY LOWER
* TRIANGULAR PART OF A IS NOT REFERENCED. IF UPLO = 'L', THE
* LEADING N-BY-N LOWER TRIANGULAR PART OF A CONTAINS THE LOWER
* TRIANGULAR PART OF THE MATRIX A, AND THE STRICTLY UPPER
* TRIANGULAR PART OF A IS NOT REFERENCED.
* ON EXIT, IF UPLO = 'U', THE DIAGONAL AND FIRST SUPERDIAGONAL
* OF A ARE OVERWRITTEN BY THE CORRESPONDING ELEMENTS OF THE
* TRIDIAGONAL MATRIX T, AND THE ELEMENTS ABOVE THE FIRST
* SUPERDIAGONAL, WITH THE ARRAY TAU, REPRESENT THE ORTHOGONAL
* MATRIX Q AS A PRODUCT OF ELEMENTARY REFLECTORS; IF UPLO
* = 'L', THE DIAGONAL AND FIRST SUBDIAGONAL OF A ARE OVER-
* WRITTEN BY THE CORRESPONDING ELEMENTS OF THE TRIDIAGONAL
* MATRIX T, AND THE ELEMENTS BELOW THE FIRST SUBDIAGONAL, WITH
* THE ARRAY TAU, REPRESENT THE ORTHOGONAL MATRIX Q AS A PRODUCT
* OF ELEMENTARY REFLECTORS. SEE FURTHER DETAILS.
*
* LDA (INPUT) INTEGER
* THE LEADING DIMENSION OF THE ARRAY A. LDA >= MAX(1,N).
*
* D (OUTPUT) DOUBLE PRECISION ARRAY, DIMENSION (N)
* THE DIAGONAL ELEMENTS OF THE TRIDIAGONAL MATRIX T:
* D(I) = A(I,I).
*
* E (OUTPUT) DOUBLE PRECISION ARRAY, DIMENSION (N-1)
* THE OFF-DIAGONAL ELEMENTS OF THE TRIDIAGONAL MATRIX T:
* E(I) = A(I,I+1) IF UPLO = 'U', E(I) = A(I+1,I) IF UPLO = 'L'.
*
* TAU (OUTPUT) DOUBLE PRECISION ARRAY, DIMENSION (N-1)
* THE SCALAR FACTORS OF THE ELEMENTARY REFLECTORS (SEE FURTHER
* DETAILS).
*
* WORK (WORKSPACE) DOUBLE PRECISION ARRAY, DIMENSION (LWORK)
* ON EXIT, IF INFO = 0, WORK(1) RETURNS THE OPTIMAL LWORK.
*
* LWORK (INPUT) INTEGER
* THE DIMENSION OF THE ARRAY WORK. LWORK >= 1.
* FOR OPTIMUM PERFORMANCE LWORK >= N*NB, WHERE NB IS THE
* OPTIMAL BLOCKSIZE.
*
* INFO (OUTPUT) INTEGER
* = 0: SUCCESSFUL EXIT
* < 0: IF INFO = -I, THE I-TH ARGUMENT HAD AN ILLEGAL VALUE
*
* FURTHER DETAILS
* ===============
*
* IF UPLO = 'U', THE MATRIX Q IS REPRESENTED AS A PRODUCT OF ELEMENTARY
* REFLECTORS
*
* Q = H(N-1) . . . H(2) H(1).
*
* EACH H(I) HAS THE FORM
*
* H(I) = I - TAU * V * V'
*
* WHERE TAU IS A REAL SCALAR, AND V IS A REAL VECTOR WITH
* V(I+1:N) = 0 AND V(I) = 1; V(1:I-1) IS STORED ON EXIT IN
* A(1:I-1,I+1), AND TAU IN TAU(I).
*
* IF UPLO = 'L', THE MATRIX Q IS REPRESENTED AS A PRODUCT OF ELEMENTARY
* REFLECTORS
*
* Q = H(1) H(2) . . . H(N-1).
*
* EACH H(I) HAS THE FORM
*
* H(I) = I - TAU * V * V'
*
* WHERE TAU IS A REAL SCALAR, AND V IS A REAL VECTOR WITH
* V(1:I) = 0 AND V(I+1) = 1; V(I+2:N) IS STORED ON EXIT IN A(I+2:N,I),
* AND TAU IN TAU(I).
*
* THE CONTENTS OF A ON EXIT ARE ILLUSTRATED BY THE FOLLOWING EXAMPLES
* WITH N = 5:
*
* IF UPLO = 'U': IF UPLO = 'L':
*
* ( D E V2 V3 V4 ) ( D )
* ( D E V3 V4 ) ( E D )
* ( D E V4 ) ( V1 E D )
* ( D E ) ( V1 V2 E D )
* ( D ) ( V1 V2 V3 E D )
*
* WHERE D AND E DENOTE DIAGONAL AND OFF-DIAGONAL ELEMENTS OF T, AND VI
* DENOTES AN ELEMENT OF THE VECTOR DEFINING H(I).
*
* =====================================================================
*
* .. PARAMETERS ..
DOUBLE PRECISION ONE
PARAMETER ( ONE = 1.0D0 )
* ..
* .. LOCAL SCALARS ..
LOGICAL UPPER
INTEGER I, IINFO, IWS, J, KK, LDWORK, NB, NBMIN, NX
* ..
* .. EXTERNAL SUBROUTINES ..
EXTERNAL DLATRD, DSYR2K, DSYTD2, XERBLA
* ..
* .. INTRINSIC FUNCTIONS ..
INTRINSIC MAX
* ..
* .. EXTERNAL FUNCTIONS ..
LOGICAL LSAME
INTEGER ILAENV
EXTERNAL LSAME, ILAENV
* ..
* .. EXECUTABLE STATEMENTS ..
*
* TEST THE INPUT PARAMETERS
*
INFO = 0
UPPER = LSAME( UPLO, 'U' )
IF( .NOT.UPPER .AND. .NOT.LSAME( UPLO, 'L' ) ) THEN
INFO = -1
ELSE IF( N.LT.0 ) THEN
INFO = -2
ELSE IF( LDA.LT.MAX( 1, N ) ) THEN
INFO = -4
ELSE IF( LWORK.LT.1 ) THEN
INFO = -9
END IF
IF( INFO.NE.0 ) THEN
CALL XERBLA( 'DSYTRD', -INFO )
RETURN
END IF
*
* QUICK RETURN IF POSSIBLE
*
IF( N.EQ.0 ) THEN
WORK( 1 ) = 1
RETURN
END IF
*
* DETERMINE THE BLOCK SIZE.
*
NB = ILAENV( 1, 'DSYTRD', UPLO, N, -1, -1, -1 )
NX = N
IWS = 1
IF( NB.GT.1 .AND. NB.LT.N ) THEN
*
* DETERMINE WHEN TO CROSS OVER FROM BLOCKED TO UNBLOCKED CODE
* (LAST BLOCK IS ALWAYS HANDLED BY UNBLOCKED CODE).
*
NX = MAX( NB, ILAENV( 3, 'DSYTRD', UPLO, N, -1, -1, -1 ) )
IF( NX.LT.N ) THEN
*
* DETERMINE IF WORKSPACE IS LARGE ENOUGH FOR BLOCKED CODE.
*
LDWORK = N
IWS = LDWORK*NB
IF( LWORK.LT.IWS ) THEN
*
* NOT ENOUGH WORKSPACE TO USE OPTIMAL NB: DETERMINE THE
* MINIMUM VALUE OF NB, AND REDUCE NB OR FORCE USE OF
* UNBLOCKED CODE BY SETTING NX = N.
*
NB = LWORK / LDWORK
NBMIN = ILAENV( 2, 'DSYTRD', UPLO, N, -1, -1, -1 )
IF( NB.LT.NBMIN )
$ NX = N
END IF
ELSE
NX = N
END IF
ELSE
NB = 1
END IF
*
IF( UPPER ) THEN
*
* REDUCE THE UPPER TRIANGLE OF A.
* COLUMNS 1:KK ARE HANDLED BY THE UNBLOCKED METHOD.
*
KK = N - ( ( N-NX+NB-1 ) / NB )*NB
DO 20 I = N - NB + 1, KK + 1, -NB
*
* REDUCE COLUMNS I:I+NB-1 TO TRIDIAGONAL FORM AND FORM THE
* MATRIX W WHICH IS NEEDED TO UPDATE THE UNREDUCED PART OF
* THE MATRIX
*
CALL DLATRD( UPLO, I+NB-1, NB, A, LDA, E, TAU, WORK,
$ LDWORK )
*
* UPDATE THE UNREDUCED SUBMATRIX A(1:I-1,1:I-1), USING AN
* UPDATE OF THE FORM: A := A - V*W' - W*V'
*
CALL DSYR2K( UPLO, 'NO TRANSPOSE', I-1, NB, -ONE, A( 1, I ),
$ LDA, WORK, LDWORK, ONE, A, LDA )
*
* COPY SUPERDIAGONAL ELEMENTS BACK INTO A, AND DIAGONAL
* ELEMENTS INTO D
*
DO 10 J = I, I + NB - 1
A( J-1, J ) = E( J-1 )
D( J ) = A( J, J )
10 CONTINUE
20 CONTINUE
*
* USE UNBLOCKED CODE TO REDUCE THE LAST OR ONLY BLOCK
*
CALL DSYTD2( UPLO, KK, A, LDA, D, E, TAU, IINFO )
ELSE
*
* REDUCE THE LOWER TRIANGLE OF A
*
DO 40 I = 1, N - NX, NB
*
* REDUCE COLUMNS I:I+NB-1 TO TRIDIAGONAL FORM AND FORM THE
* MATRIX W WHICH IS NEEDED TO UPDATE THE UNREDUCED PART OF
* THE MATRIX
*
CALL DLATRD( UPLO, N-I+1, NB, A( I, I ), LDA, E( I ),
$ TAU( I ), WORK, LDWORK )
*
* UPDATE THE UNREDUCED SUBMATRIX A(I+IB:N,I+IB:N), USING
* AN UPDATE OF THE FORM: A := A - V*W' - W*V'
*
CALL DSYR2K( UPLO, 'NO TRANSPOSE', N-I-NB+1, NB, -ONE,
$ A( I+NB, I ), LDA, WORK( NB+1 ), LDWORK, ONE,
$ A( I+NB, I+NB ), LDA )
*
* COPY SUBDIAGONAL ELEMENTS BACK INTO A, AND DIAGONAL
* ELEMENTS INTO D
*
DO 30 J = I, I + NB - 1
A( J+1, J ) = E( J )
D( J ) = A( J, J )
30 CONTINUE
40 CONTINUE
*
* USE UNBLOCKED CODE TO REDUCE THE LAST OR ONLY BLOCK
*
CALL DSYTD2( UPLO, N-I+1, A( I, I ), LDA, D( I ), E( I ),
$ TAU( I ), IINFO )
END IF
*
WORK( 1 ) = IWS
RETURN
*
* END OF DSYTRD
*
END
CUT HERE............
CAT > DSYTD2.F <<'CUT HERE............'
SUBROUTINE DSYTD2( UPLO, N, A, LDA, D, E, TAU, INFO )
*
* -- LAPACK ROUTINE (VERSION 1.1) --
* UNIV. OF TENNESSEE, UNIV. OF CALIFORNIA BERKELEY, NAG LTD.,
* COURANT INSTITUTE, ARGONNE NATIONAL LAB, AND RICE UNIVERSITY
* OCTOBER 31, 1992
*
* .. SCALAR ARGUMENTS ..
CHARACTER UPLO
INTEGER INFO, LDA, N
* ..
* .. ARRAY ARGUMENTS ..
DOUBLE PRECISION A( LDA, * ), D( * ), E( * ), TAU( * )
* ..
*
* PURPOSE
* =======
*
* DSYTD2 REDUCES A REAL SYMMETRIC MATRIX A TO SYMMETRIC TRIDIAGONAL
* FORM T BY AN ORTHOGONAL SIMILARITY TRANSFORMATION: Q' * A * Q = T.
*
* ARGUMENTS
* =========
*
* UPLO (INPUT) CHARACTER*1
* SPECIFIES WHETHER THE UPPER OR LOWER TRIANGULAR PART OF THE
* SYMMETRIC MATRIX A IS STORED:
* = 'U': UPPER TRIANGULAR
* = 'L': LOWER TRIANGULAR
*
* N (INPUT) INTEGER
* THE ORDER OF THE MATRIX A. N >= 0.
*
* A (INPUT/OUTPUT) DOUBLE PRECISION 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, AND THE STRICTLY LOWER
* TRIANGULAR PART OF A IS NOT REFERENCED. IF UPLO = 'L', THE
* LEADING N-BY-N LOWER TRIANGULAR PART OF A CONTAINS THE LOWER
* TRIANGULAR PART OF THE MATRIX A, AND THE STRICTLY UPPER
* TRIANGULAR PART OF A IS NOT REFERENCED.
* ON EXIT, IF UPLO = 'U', THE DIAGONAL AND FIRST SUPERDIAGONAL
* OF A ARE OVERWRITTEN BY THE CORRESPONDING ELEMENTS OF THE
* TRIDIAGONAL MATRIX T, AND THE ELEMENTS ABOVE THE FIRST
* SUPERDIAGONAL, WITH THE ARRAY TAU, REPRESENT THE ORTHOGONAL
* MATRIX Q AS A PRODUCT OF ELEMENTARY REFLECTORS; IF UPLO
* = 'L', THE DIAGONAL AND FIRST SUBDIAGONAL OF A ARE OVER-
* WRITTEN BY THE CORRESPONDING ELEMENTS OF THE TRIDIAGONAL
* MATRIX T, AND THE ELEMENTS BELOW THE FIRST SUBDIAGONAL, WITH
* THE ARRAY TAU, REPRESENT THE ORTHOGONAL MATRIX Q AS A PRODUCT
* OF ELEMENTARY REFLECTORS. SEE FURTHER DETAILS.
*
* LDA (INPUT) INTEGER
* THE LEADING DIMENSION OF THE ARRAY A. LDA >= MAX(1,N).
*
* D (OUTPUT) DOUBLE PRECISION ARRAY, DIMENSION (N)
* THE DIAGONAL ELEMENTS OF THE TRIDIAGONAL MATRIX T:
* D(I) = A(I,I).
*
* E (OUTPUT) DOUBLE PRECISION ARRAY, DIMENSION (N-1)
* THE OFF-DIAGONAL ELEMENTS OF THE TRIDIAGONAL MATRIX T:
* E(I) = A(I,I+1) IF UPLO = 'U', E(I) = A(I+1,I) IF UPLO = 'L'.
*
* TAU (OUTPUT) DOUBLE PRECISION ARRAY, DIMENSION (N-1)
* THE SCALAR FACTORS OF THE ELEMENTARY REFLECTORS (SEE FURTHER
* DETAILS).
*
* INFO (OUTPUT) INTEGER
* = 0: SUCCESSFUL EXIT
* < 0: IF INFO = -I, THE I-TH ARGUMENT HAD AN ILLEGAL VALUE.
*
* FURTHER DETAILS
* ===============
*
* IF UPLO = 'U', THE MATRIX Q IS REPRESENTED AS A PRODUCT OF ELEMENTARY
* REFLECTORS
*
* Q = H(N-1) . . . H(2) H(1).
*
* EACH H(I) HAS THE FORM
*
* H(I) = I - TAU * V * V'
*
* WHERE TAU IS A REAL SCALAR, AND V IS A REAL VECTOR WITH
* V(I+1:N) = 0 AND V(I) = 1; V(1:I-1) IS STORED ON EXIT IN
* A(1:I-1,I+1), AND TAU IN TAU(I).
*
* IF UPLO = 'L', THE MATRIX Q IS REPRESENTED AS A PRODUCT OF ELEMENTARY
* REFLECTORS
*
* Q = H(1) H(2) . . . H(N-1).
*
* EACH H(I) HAS THE FORM
*
* H(I) = I - TAU * V * V'
*
* WHERE TAU IS A REAL SCALAR, AND V IS A REAL VECTOR WITH
* V(1:I) = 0 AND V(I+1) = 1; V(I+2:N) IS STORED ON EXIT IN A(I+2:N,I),
* AND TAU IN TAU(I).
*
* THE CONTENTS OF A ON EXIT ARE ILLUSTRATED BY THE FOLLOWING EXAMPLES
* WITH N = 5:
*
* IF UPLO = 'U': IF UPLO = 'L':
*
* ( D E V2 V3 V4 ) ( D )
* ( D E V3 V4 ) ( E D )
* ( D E V4 ) ( V1 E D )
* ( D E ) ( V1 V2 E D )
* ( D ) ( V1 V2 V3 E D )
*
* WHERE D AND E DENOTE DIAGONAL AND OFF-DIAGONAL ELEMENTS OF T, AND VI
* DENOTES AN ELEMENT OF THE VECTOR DEFINING H(I).
*
* =====================================================================
*
* .. PARAMETERS ..
DOUBLE PRECISION ONE, ZERO, HALF
PARAMETER ( ONE = 1.0D0, ZERO = 0.0D0,
$ HALF = 1.0D0 / 2.0D0 )
* ..
* .. LOCAL SCALARS ..
LOGICAL UPPER
INTEGER I
DOUBLE PRECISION ALPHA, TAUI
* ..
* .. EXTERNAL SUBROUTINES ..
EXTERNAL DAXPY, DLARFG, DSYMV, DSYR2, XERBLA
* ..
* .. EXTERNAL FUNCTIONS ..
LOGICAL LSAME
DOUBLE PRECISION DDOT
EXTERNAL LSAME, DDOT
* ..
* .. INTRINSIC FUNCTIONS ..
INTRINSIC MAX, MIN
* ..
* .. EXECUTABLE STATEMENTS ..
*
* TEST THE INPUT PARAMETERS
*
INFO = 0
UPPER = LSAME( UPLO, 'U' )
IF( .NOT.UPPER .AND. .NOT.LSAME( UPLO, 'L' ) ) THEN
INFO = -1
ELSE IF( N.LT.0 ) THEN
INFO = -2
ELSE IF( LDA.LT.MAX( 1, N ) ) THEN
INFO = -4
END IF
IF( INFO.NE.0 ) THEN
CALL XERBLA( 'DSYTD2', -INFO )
RETURN
END IF
*
* QUICK RETURN IF POSSIBLE
*
IF( N.LE.0 )
$ RETURN
*
IF( UPPER ) THEN
*
* REDUCE THE UPPER TRIANGLE OF A
*
DO 10 I = N - 1, 1, -1
*
* GENERATE ELEMENTARY REFLECTOR H(I) = I - TAU * V * V'
* TO ANNIHILATE A(1:I-1,I+1)
*
CALL DLARFG( I, A( I, I+1 ), A( 1, I+1 ), 1, TAUI )
E( I ) = A( I, I+1 )
*
IF( TAUI.NE.ZERO ) THEN
*
* APPLY H(I) FROM BOTH SIDES TO A(1:I,1:I)
*
A( I, I+1 ) = ONE
*
* COMPUTE X := TAU * A * V STORING X IN TAU(1:I)
*
CALL DSYMV( UPLO, I, TAUI, A, LDA, A( 1, I+1 ), 1, ZERO,
$ TAU, 1 )
*
* COMPUTE W := X - 1/2 * TAU * (X'*V) * V
*
ALPHA = -HALF*TAUI*DDOT( I, TAU, 1, A( 1, I+1 ), 1 )
CALL DAXPY( I, ALPHA, A( 1, I+1 ), 1, TAU, 1 )
*
* APPLY THE TRANSFORMATION AS A RANK-2 UPDATE:
* A := A - V * W' - W * V'
*
CALL DSYR2( UPLO, I, -ONE, A( 1, I+1 ), 1, TAU, 1, A,
$ LDA )
*
A( I, I+1 ) = E( I )
END IF
D( I+1 ) = A( I+1, I+1 )
TAU( I ) = TAUI
10 CONTINUE
D( 1 ) = A( 1, 1 )
ELSE
*
* REDUCE THE LOWER TRIANGLE OF A
*
DO 20 I = 1, N - 1
*
* GENERATE ELEMENTARY REFLECTOR H(I) = I - TAU * V * V'
* TO ANNIHILATE A(I+2:N,I)
*
CALL DLARFG( N-I, A( I+1, I ), A( MIN( I+2, N ), I ), 1,
$ TAUI )
E( I ) = A( I+1, I )
*
IF( TAUI.NE.ZERO ) THEN
*
* APPLY H(I) FROM BOTH SIDES TO A(I+1:N,I+1:N)
*
A( I+1, I ) = ONE
*
* COMPUTE X := TAU * A * V STORING Y IN TAU(I:N-1)
*
CALL DSYMV( UPLO, N-I, TAUI, A( I+1, I+1 ), LDA,
$ A( I+1, I ), 1, ZERO, TAU( I ), 1 )
*
* COMPUTE W := X - 1/2 * TAU * (X'*V) * V
*
ALPHA = -HALF*TAUI*DDOT( N-I, TAU( I ), 1, A( I+1, I ),
$ 1 )
CALL DAXPY( N-I, ALPHA, A( I+1, I ), 1, TAU( I ), 1 )
*
* APPLY THE TRANSFORMATION AS A RANK-2 UPDATE:
* A := A - V * W' - W * V'
*
CALL DSYR2( UPLO, N-I, -ONE, A( I+1, I ), 1, TAU( I ), 1,
$ A( I+1, I+1 ), LDA )
*
A( I+1, I ) = E( I )
END IF
D( I ) = A( I, I )
TAU( I ) = TAUI
20 CONTINUE
D( N ) = A( N, N )
END IF
*
RETURN
*
* END OF DSYTD2
*
END
CUT HERE............
CAT > DLATRD.F <<'CUT HERE............'
SUBROUTINE DLATRD( UPLO, N, NB, A, LDA, E, TAU, W, LDW )
*
* -- LAPACK AUXILIARY ROUTINE (VERSION 1.1) --
* UNIV. OF TENNESSEE, UNIV. OF CALIFORNIA BERKELEY, NAG LTD.,
* COURANT INSTITUTE, ARGONNE NATIONAL LAB, AND RICE UNIVERSITY
* OCTOBER 31, 1992
*
* .. SCALAR ARGUMENTS ..
CHARACTER UPLO
INTEGER LDA, LDW, N, NB
* ..
* .. ARRAY ARGUMENTS ..
DOUBLE PRECISION A( LDA, * ), E( * ), TAU( * ), W( LDW, * )
* ..
*
* PURPOSE
* =======
*
* DLATRD REDUCES NB ROWS AND COLUMNS OF A REAL SYMMETRIC MATRIX A TO
* SYMMETRIC TRIDIAGONAL FORM BY AN ORTHOGONAL SIMILARITY
* TRANSFORMATION Q' * A * Q, AND RETURNS THE MATRICES V AND W WHICH ARE
* NEEDED TO APPLY THE TRANSFORMATION TO THE UNREDUCED PART OF A.
*
* IF UPLO = 'U', DLATRD REDUCES THE LAST NB ROWS AND COLUMNS OF A
* MATRIX, OF WHICH THE UPPER TRIANGLE IS SUPPLIED;
* IF UPLO = 'L', DLATRD REDUCES THE FIRST NB ROWS AND COLUMNS OF A
* MATRIX, OF WHICH THE LOWER TRIANGLE IS SUPPLIED.
*
* THIS IS AN AUXILIARY ROUTINE CALLED BY DSYTRD.
*
* ARGUMENTS
* =========
*
* UPLO (INPUT) CHARACTER
* SPECIFIES WHETHER THE UPPER OR LOWER TRIANGULAR PART OF THE
* SYMMETRIC MATRIX A IS STORED:
* = 'U': UPPER TRIANGULAR
* = 'L': LOWER TRIANGULAR
*
* N (INPUT) INTEGER
* THE ORDER OF THE MATRIX A.
*
* NB (INPUT) INTEGER
* THE NUMBER OF ROWS AND COLUMNS TO BE REDUCED.
*
* A (INPUT/OUTPUT) DOUBLE PRECISION 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, AND THE STRICTLY LOWER
* TRIANGULAR PART OF A IS NOT REFERENCED. IF UPLO = 'L', THE
* LEADING N-BY-N LOWER TRIANGULAR PART OF A CONTAINS THE LOWER
* TRIANGULAR PART OF THE MATRIX A, AND THE STRICTLY UPPER
* TRIANGULAR PART OF A IS NOT REFERENCED.
* ON EXIT:
* IF UPLO = 'U', THE LAST NB COLUMNS HAVE BEEN REDUCED TO
* TRIDIAGONAL FORM, WITH THE DIAGONAL ELEMENTS OVERWRITING
* THE DIAGONAL ELEMENTS OF A; THE ELEMENTS ABOVE THE DIAGONAL
* WITH THE ARRAY TAU, REPRESENT THE ORTHOGONAL MATRIX Q AS A
* PRODUCT OF ELEMENTARY REFLECTORS;
* IF UPLO = 'L', THE FIRST NB COLUMNS HAVE BEEN REDUCED TO
* TRIDIAGONAL FORM, WITH THE DIAGONAL ELEMENTS OVERWRITING
* THE DIAGONAL ELEMENTS OF A; THE ELEMENTS BELOW THE DIAGONAL
* WITH THE ARRAY TAU, REPRESENT THE ORTHOGONAL MATRIX Q AS A
* PRODUCT OF ELEMENTARY REFLECTORS.
* SEE FURTHER DETAILS.
*
* LDA (INPUT) INTEGER
* THE LEADING DIMENSION OF THE ARRAY A. LDA >= (1,N).
*
* E (OUTPUT) DOUBLE PRECISION ARRAY, DIMENSION (N-1)
* IF UPLO = 'U', E(N-NB:N-1) CONTAINS THE SUPERDIAGONAL
* ELEMENTS OF THE LAST NB COLUMNS OF THE REDUCED MATRIX;
* IF UPLO = 'L', E(1:NB) CONTAINS THE SUBDIAGONAL ELEMENTS OF
* THE FIRST NB COLUMNS OF THE REDUCED MATRIX.
*
* TAU (OUTPUT) DOUBLE PRECISION ARRAY, DIMENSION (N-1)
* THE SCALAR FACTORS OF THE ELEMENTARY REFLECTORS, STORED IN
* TAU(N-NB:N-1) IF UPLO = 'U', AND IN TAU(1:NB) IF UPLO = 'L'.
* SEE FURTHER DETAILS.
*
* W (OUTPUT) DOUBLE PRECISION ARRAY, DIMENSION (LDW,NB)
* THE N-BY-NB MATRIX W REQUIRED TO UPDATE THE UNREDUCED PART
* OF A.
*
* LDW (INPUT) INTEGER
* THE LEADING DIMENSION OF THE ARRAY W. LDW >= MAX(1,N).
*
* FURTHER DETAILS
* ===============
*
* IF UPLO = 'U', THE MATRIX Q IS REPRESENTED AS A PRODUCT OF ELEMENTARY
* REFLECTORS
*
* Q = H(N) H(N-1) . . . H(N-NB+1).
*
* EACH H(I) HAS THE FORM
*
* H(I) = I - TAU * V * V'
*
* WHERE TAU IS A REAL SCALAR, AND V IS A REAL VECTOR WITH
* V(I:N) = 0 AND V(I-1) = 1; V(1:I-1) IS STORED ON EXIT IN A(1:I-1,I),
* AND TAU IN TAU(I-1).
*
* IF UPLO = 'L', THE MATRIX Q IS REPRESENTED AS A PRODUCT OF ELEMENTARY
* REFLECTORS
*
* Q = H(1) H(2) . . . H(NB).
*
* EACH H(I) HAS THE FORM
*
* H(I) = I - TAU * V * V'
*
* WHERE TAU IS A REAL SCALAR, AND V IS A REAL VECTOR WITH
* V(1:I) = 0 AND V(I+1) = 1; V(I+1:N) IS STORED ON EXIT IN A(I+1:N,I),
* AND TAU IN TAU(I).
*
* THE ELEMENTS OF THE VECTORS V TOGETHER FORM THE N-BY-NB MATRIX V
* WHICH IS NEEDED, WITH W, TO APPLY THE TRANSFORMATION TO THE UNREDUCED
* PART OF THE MATRIX, USING A SYMMETRIC RANK-2K UPDATE OF THE FORM:
* A := A - V*W' - W*V'.
*
* THE CONTENTS OF A ON EXIT ARE ILLUSTRATED BY THE FOLLOWING EXAMPLES
* WITH N = 5 AND NB = 2:
*
* IF UPLO = 'U': IF UPLO = 'L':
*
* ( A A A V4 V5 ) ( D )
* ( A A V4 V5 ) ( 1 D )
* ( A 1 V5 ) ( V1 1 A )
* ( D 1 ) ( V1 V2 A A )
* ( D ) ( V1 V2 A A A )
*
* WHERE D DENOTES A DIAGONAL ELEMENT OF THE REDUCED MATRIX, A DENOTES
* AN ELEMENT OF THE ORIGINAL MATRIX THAT IS UNCHANGED, AND VI DENOTES
* AN ELEMENT OF THE VECTOR DEFINING H(I).
*
* =====================================================================
*
* .. PARAMETERS ..
DOUBLE PRECISION ZERO, ONE, HALF
PARAMETER ( ZERO = 0.0D+0, ONE = 1.0D+0, HALF = 0.5D+0 )
* ..
* .. LOCAL SCALARS ..
INTEGER I, IW
DOUBLE PRECISION ALPHA
* ..
* .. EXTERNAL SUBROUTINES ..
EXTERNAL DAXPY, DGEMV, DLARFG, DSCAL, DSYMV
* ..
* .. EXTERNAL FUNCTIONS ..
LOGICAL LSAME
DOUBLE PRECISION DDOT
EXTERNAL LSAME, DDOT
* ..
* .. INTRINSIC FUNCTIONS ..
INTRINSIC MIN
* ..
* .. EXECUTABLE STATEMENTS ..
*
* QUICK RETURN IF POSSIBLE
*
IF( N.LE.0 )
$ RETURN
*
IF( LSAME( UPLO, 'U' ) ) THEN
*
* REDUCE LAST NB COLUMNS OF UPPER TRIANGLE
*
DO 10 I = N, N - NB + 1, -1
IW = I - N + NB
IF( I.LT.N ) THEN
*
* UPDATE A(1:I,I)
*
CALL DGEMV( 'NO TRANSPOSE', I, N-I, -ONE, A( 1, I+1 ),
$ LDA, W( I, IW+1 ), LDW, ONE, A( 1, I ), 1 )
CALL DGEMV( 'NO TRANSPOSE', I, N-I, -ONE, W( 1, IW+1 ),
$ LDW, A( I, I+1 ), LDA, ONE, A( 1, I ), 1 )
END IF
IF( I.GT.1 ) THEN
*
* GENERATE ELEMENTARY REFLECTOR H(I) TO ANNIHILATE
* A(1:I-2,I)
*
CALL DLARFG( I-1, A( I-1, I ), A( 1, I ), 1, TAU( I-1 ) )
E( I-1 ) = A( I-1, I )
A( I-1, I ) = ONE
*
* COMPUTE W(1:I-1,I)
*
CALL DSYMV( 'UPPER', I-1, ONE, A, LDA, A( 1, I ), 1,
$ ZERO, W( 1, IW ), 1 )
IF( I.LT.N ) THEN
CALL DGEMV( 'TRANSPOSE', I-1, N-I, ONE, W( 1, IW+1 ),
$ LDW, A( 1, I ), 1, ZERO, W( I+1, IW ), 1 )
CALL DGEMV( 'NO TRANSPOSE', I-1, N-I, -ONE,
$ A( 1, I+1 ), LDA, W( I+1, IW ), 1, ONE,
$ W( 1, IW ), 1 )
CALL DGEMV( 'TRANSPOSE', I-1, N-I, ONE, A( 1, I+1 ),
$ LDA, A( 1, I ), 1, ZERO, W( I+1, IW ), 1 )
CALL DGEMV( 'NO TRANSPOSE', I-1, N-I, -ONE,
$ W( 1, IW+1 ), LDW, W( I+1, IW ), 1, ONE,
$ W( 1, IW ), 1 )
END IF
CALL DSCAL( I-1, TAU( I-1 ), W( 1, IW ), 1 )
ALPHA = -HALF*TAU( I-1 )*DDOT( I-1, W( 1, IW ), 1,
$ A( 1, I ), 1 )
CALL DAXPY( I-1, ALPHA, A( 1, I ), 1, W( 1, IW ), 1 )
END IF
*
10 CONTINUE
ELSE
*
* REDUCE FIRST NB COLUMNS OF LOWER TRIANGLE
*
DO 20 I = 1, NB
*
* UPDATE A(I:N,I)
*
CALL DGEMV( 'NO TRANSPOSE', N-I+1, I-1, -ONE, A( I, 1 ),
$ LDA, W( I, 1 ), LDW, ONE, A( I, I ), 1 )
CALL DGEMV( 'NO TRANSPOSE', N-I+1, I-1, -ONE, W( I, 1 ),
$ LDW, A( I, 1 ), LDA, ONE, A( I, I ), 1 )
IF( I.LT.N ) THEN
*
* GENERATE ELEMENTARY REFLECTOR H(I) TO ANNIHILATE
* A(I+2:N,I)
*
CALL DLARFG( N-I, A( I+1, I ), A( MIN( I+2, N ), I ), 1,
$ TAU( I ) )
E( I ) = A( I+1, I )
A( I+1, I ) = ONE
*
* COMPUTE W(I+1:N,I)
*
CALL DSYMV( 'LOWER', N-I, ONE, A( I+1, I+1 ), LDA,
$ A( I+1, I ), 1, ZERO, W( I+1, I ), 1 )
CALL DGEMV( 'TRANSPOSE', N-I, I-1, ONE, W( I+1, 1 ), LDW,
$ A( I+1, I ), 1, ZERO, W( 1, I ), 1 )
CALL DGEMV( 'NO TRANSPOSE', N-I, I-1, -ONE, A( I+1, 1 ),
$ LDA, W( 1, I ), 1, ONE, W( I+1, I ), 1 )
CALL DGEMV( 'TRANSPOSE', N-I, I-1, ONE, A( I+1, 1 ), LDA,
$ A( I+1, I ), 1, ZERO, W( 1, I ), 1 )
CALL DGEMV( 'NO TRANSPOSE', N-I, I-1, -ONE, W( I+1, 1 ),
$ LDW, W( 1, I ), 1, ONE, W( I+1, I ), 1 )
CALL DSCAL( N-I, TAU( I ), W( I+1, I ), 1 )
ALPHA = -HALF*TAU( I )*DDOT( N-I, W( I+1, I ), 1,
$ A( I+1, I ), 1 )
CALL DAXPY( N-I, ALPHA, A( I+1, I ), 1, W( I+1, I ), 1 )
END IF
*
20 CONTINUE
END IF
*
RETURN
*
* END OF DLATRD
*
END
CUT HERE............
CAT > DLARFG.F <<'CUT HERE............'
SUBROUTINE DLARFG( N, ALPHA, X, INCX, TAU )
*
* -- LAPACK AUXILIARY ROUTINE (VERSION 1.1) --
* UNIV. OF TENNESSEE, UNIV. OF CALIFORNIA BERKELEY, NAG LTD.,
* COURANT INSTITUTE, ARGONNE NATIONAL LAB, AND RICE UNIVERSITY
* FEBRUARY 29, 1992
*
* .. SCALAR ARGUMENTS ..
INTEGER INCX, N
DOUBLE PRECISION ALPHA, TAU
* ..
* .. ARRAY ARGUMENTS ..
DOUBLE PRECISION X( * )
* ..
*
* PURPOSE
* =======
*
* DLARFG GENERATES A REAL ELEMENTARY REFLECTOR H OF ORDER N, SUCH
* THAT
*
* H * ( ALPHA ) = ( BETA ), H' * H = I.
* ( X ) ( 0 )
*
* WHERE ALPHA AND BETA ARE SCALARS, AND X IS AN (N-1)-ELEMENT REAL
* VECTOR. H IS REPRESENTED IN THE FORM
*
* H = I - TAU * ( 1 ) * ( 1 V' ) ,
* ( V )
*
* WHERE TAU IS A REAL SCALAR AND V IS A REAL (N-1)-ELEMENT
* VECTOR.
*
* IF THE ELEMENTS OF X ARE ALL ZERO, THEN TAU = 0 AND H IS TAKEN TO BE
* THE UNIT MATRIX.
*
* OTHERWISE 1 <= TAU <= 2.
*
* ARGUMENTS
* =========
*
* N (INPUT) INTEGER
* THE ORDER OF THE ELEMENTARY REFLECTOR.
*
* ALPHA (INPUT/OUTPUT) DOUBLE PRECISION
* ON ENTRY, THE VALUE ALPHA.
* ON EXIT, IT IS OVERWRITTEN WITH THE VALUE BETA.
*
* X (INPUT/OUTPUT) DOUBLE PRECISION ARRAY, DIMENSION
* (1+(N-2)*ABS(INCX))
* ON ENTRY, THE VECTOR X.
* ON EXIT, IT IS OVERWRITTEN WITH THE VECTOR V.
*
* INCX (INPUT) INTEGER
* THE INCREMENT BETWEEN ELEMENTS OF X. INCX <> 0.
*
* TAU (OUTPUT) DOUBLE PRECISION
* THE VALUE TAU.
*
* =====================================================================
*
* .. PARAMETERS ..
DOUBLE PRECISION ONE, ZERO
PARAMETER ( ONE = 1.0D+0, ZERO = 0.0D+0 )
* ..
* .. LOCAL SCALARS ..
INTEGER J, KNT
DOUBLE PRECISION BETA, RSAFMN, SAFMIN, XNORM
* ..
* .. EXTERNAL FUNCTIONS ..
DOUBLE PRECISION DLAMCH, DLAPY2, DNRM2
EXTERNAL DLAMCH, DLAPY2, DNRM2
* ..
* .. INTRINSIC FUNCTIONS ..
INTRINSIC ABS, SIGN
* ..
* .. EXTERNAL SUBROUTINES ..
EXTERNAL DSCAL
* ..
* .. EXECUTABLE STATEMENTS ..
*
IF( N.LE.1 ) THEN
TAU = ZERO
RETURN
END IF
*
XNORM = DNRM2( N-1, X, INCX )
*
IF( XNORM.EQ.ZERO ) THEN
*
* H = I
*
TAU = ZERO
ELSE
*
* GENERAL CASE
*
BETA = -SIGN( DLAPY2( ALPHA, XNORM ), ALPHA )
SAFMIN = DLAMCH( 'S' )
IF( ABS( BETA ).LT.SAFMIN ) THEN
*
* XNORM, BETA MAY BE INACCURATE; SCALE X AND RECOMPUTE THEM
*
RSAFMN = ONE / SAFMIN
KNT = 0
10 CONTINUE
KNT = KNT + 1
CALL DSCAL( N-1, RSAFMN, X, INCX )
BETA = BETA*RSAFMN
ALPHA = ALPHA*RSAFMN
IF( ABS( BETA ).LT.SAFMIN )
$ GO TO 10
*
* NEW BETA IS AT MOST 1, AT LEAST SAFMIN
*
XNORM = DNRM2( N-1, X, INCX )
BETA = -SIGN( DLAPY2( ALPHA, XNORM ), ALPHA )
TAU = ( BETA-ALPHA ) / BETA
CALL DSCAL( N-1, ONE / ( ALPHA-BETA ), X, INCX )
*
* IF ALPHA IS SUBNORMAL, IT MAY LOSE RELATIVE ACCURACY
*
ALPHA = BETA
DO 20 J = 1, KNT
ALPHA = ALPHA*SAFMIN
20 CONTINUE
ELSE
TAU = ( BETA-ALPHA ) / BETA
CALL DSCAL( N-1, ONE / ( ALPHA-BETA ), X, INCX )
ALPHA = BETA
END IF
END IF
*
RETURN
*
* END OF DLARFG
*
END
CUT HERE............
CAT > DLAMCH.F <<'CUT HERE............'
DOUBLE PRECISION FUNCTION DLAMCH( CMACH )
*
* -- LAPACK AUXILIARY ROUTINE (VERSION 1.1) --
* UNIV. OF TENNESSEE, UNIV. OF CALIFORNIA BERKELEY, NAG LTD.,
* COURANT INSTITUTE, ARGONNE NATIONAL LAB, AND RICE UNIVERSITY
* OCTOBER 31, 1992
*
* .. SCALAR ARGUMENTS ..
CHARACTER CMACH
* ..
*
* PURPOSE
* =======
*
* DLAMCH DETERMINES DOUBLE PRECISION MACHINE PARAMETERS.
*
* ARGUMENTS
* =========
*
* CMACH (INPUT) CHARACTER*1
* SPECIFIES THE VALUE TO BE RETURNED BY DLAMCH:
* = 'E' OR 'E', DLAMCH := EPS
* = 'S' OR 'S , DLAMCH := SFMIN
* = 'B' OR 'B', DLAMCH := BASE
* = 'P' OR 'P', DLAMCH := EPS*BASE
* = 'N' OR 'N', DLAMCH := T
* = 'R' OR 'R', DLAMCH := RND
* = 'M' OR 'M', DLAMCH := EMIN
* = 'U' OR 'U', DLAMCH := RMIN
* = 'L' OR 'L', DLAMCH := EMAX
* = 'O' OR 'O', DLAMCH := RMAX
*
* WHERE
*
* EPS = RELATIVE MACHINE PRECISION
* SFMIN = SAFE MINIMUM, SUCH THAT 1/SFMIN DOES NOT OVERFLOW
* BASE = BASE OF THE MACHINE
* PREC = EPS*BASE
* T = NUMBER OF (BASE) DIGITS IN THE MANTISSA
* RND = 1.0 WHEN ROUNDING OCCURS IN ADDITION, 0.0 OTHERWISE
* EMIN = MINIMUM EXPONENT BEFORE (GRADUAL) UNDERFLOW
* RMIN = UNDERFLOW THRESHOLD - BASE**(EMIN-1)
* EMAX = LARGEST EXPONENT BEFORE OVERFLOW
* RMAX = OVERFLOW THRESHOLD - (BASE**EMAX)*(1-EPS)
*
* =====================================================================
*
* .. PARAMETERS ..
DOUBLE PRECISION ONE, ZERO
PARAMETER ( ONE = 1.0D+0, ZERO = 0.0D+0 )
* ..
* .. LOCAL SCALARS ..
LOGICAL FIRST, LRND
INTEGER BETA, IMAX, IMIN, IT
DOUBLE PRECISION BASE, EMAX, EMIN, EPS, PREC, RMACH, RMAX, RMIN,
$ RND, SFMIN, SMALL, T
* ..
* .. EXTERNAL FUNCTIONS ..
LOGICAL LSAME
EXTERNAL LSAME
* ..
* .. EXTERNAL SUBROUTINES ..
EXTERNAL DLAMC2
* ..
* .. SAVE STATEMENT ..
SAVE FIRST, EPS, SFMIN, BASE, T, RND, EMIN, RMIN,
$ EMAX, RMAX, PREC
* ..
* .. DATA STATEMENTS ..
DATA FIRST / .TRUE. /
* ..
* .. EXECUTABLE STATEMENTS ..
*
IF( FIRST ) THEN
FIRST = .FALSE.
CALL DLAMC2( BETA, IT, LRND, EPS, IMIN, RMIN, IMAX, RMAX )
BASE = BETA
T = IT
IF( LRND ) THEN
RND = ONE
EPS = ( BASE**( 1-IT ) ) / 2
ELSE
RND = ZERO
EPS = BASE**( 1-IT )
END IF
PREC = EPS*BASE
EMIN = IMIN
EMAX = IMAX
SFMIN = RMIN
SMALL = ONE / RMAX
IF( SMALL.GE.SFMIN ) THEN
*
* USE SMALL PLUS A BIT, TO AVOID THE POSSIBILITY OF ROUNDING
* CAUSING OVERFLOW WHEN COMPUTING 1/SFMIN.
*
SFMIN = SMALL*( ONE+EPS )
END IF
END IF
*
IF( LSAME( CMACH, 'E' ) ) THEN
RMACH = EPS
ELSE IF( LSAME( CMACH, 'S' ) ) THEN
RMACH = SFMIN
ELSE IF( LSAME( CMACH, 'B' ) ) THEN
RMACH = BASE
ELSE IF( LSAME( CMACH, 'P' ) ) THEN
RMACH = PREC
ELSE IF( LSAME( CMACH, 'N' ) ) THEN
RMACH = T
ELSE IF( LSAME( CMACH, 'R' ) ) THEN
RMACH = RND
ELSE IF( LSAME( CMACH, 'M' ) ) THEN
RMACH = EMIN
ELSE IF( LSAME( CMACH, 'U' ) ) THEN
RMACH = RMIN
ELSE IF( LSAME( CMACH, 'L' ) ) THEN
RMACH = EMAX
ELSE IF( LSAME( CMACH, 'O' ) ) THEN
RMACH = RMAX
END IF
*
DLAMCH = RMACH
RETURN
*
* END OF DLAMCH
*
END
*
************************************************************************
*
SUBROUTINE DLAMC1( BETA, T, RND, IEEE1 )
*
* -- LAPACK AUXILIARY ROUTINE (VERSION 1.1) --
* UNIV. OF TENNESSEE, UNIV. OF CALIFORNIA BERKELEY, NAG LTD.,
* COURANT INSTITUTE, ARGONNE NATIONAL LAB, AND RICE UNIVERSITY
* OCTOBER 31, 1992
*
* .. SCALAR ARGUMENTS ..
LOGICAL IEEE1, RND
INTEGER BETA, T
* ..
*
* PURPOSE
* =======
*
* DLAMC1 DETERMINES THE MACHINE PARAMETERS GIVEN BY BETA, T, RND, AND
* IEEE1.
*
* ARGUMENTS
* =========
*
* BETA (OUTPUT) INTEGER
* THE BASE OF THE MACHINE.
*
* T (OUTPUT) INTEGER
* THE NUMBER OF ( BETA ) DIGITS IN THE MANTISSA.
*
* RND (OUTPUT) LOGICAL
* SPECIFIES WHETHER PROPER ROUNDING ( RND = .TRUE. ) OR
* CHOPPING ( RND = .FALSE. ) OCCURS IN ADDITION. THIS MAY NOT
* BE A RELIABLE GUIDE TO THE WAY IN WHICH THE MACHINE PERFORMS
* ITS ARITHMETIC.
*
* IEEE1 (OUTPUT) LOGICAL
* SPECIFIES WHETHER ROUNDING APPEARS TO BE DONE IN THE IEEE
* 'ROUND TO NEAREST' STYLE.
*
* FURTHER DETAILS
* ===============
*
* THE ROUTINE IS BASED ON THE ROUTINE ENVRON BY MALCOLM AND
* INCORPORATES SUGGESTIONS BY GENTLEMAN AND MAROVICH. SEE
*
* MALCOLM M. A. (1972) ALGORITHMS TO REVEAL PROPERTIES OF
* FLOATING-POINT ARITHMETIC. COMMS. OF THE ACM, 15, 949-951.
*
* GENTLEMAN W. M. AND MAROVICH S. B. (1974) MORE ON ALGORITHMS
* THAT REVEAL PROPERTIES OF FLOATING POINT ARITHMETIC UNITS.
* COMMS. OF THE ACM, 17, 276-277.
*
* =====================================================================
*
* .. LOCAL SCALARS ..
LOGICAL FIRST, LIEEE1, LRND
INTEGER LBETA, LT
DOUBLE PRECISION A, B, C, F, ONE, QTR, SAVEC, T1, T2
* ..
* .. EXTERNAL FUNCTIONS ..
DOUBLE PRECISION DLAMC3
EXTERNAL DLAMC3
* ..
* .. SAVE STATEMENT ..
SAVE FIRST, LIEEE1, LBETA, LRND, LT
* ..
* .. DATA STATEMENTS ..
DATA FIRST / .TRUE. /
* ..
* .. EXECUTABLE STATEMENTS ..
*
IF( FIRST ) THEN
FIRST = .FALSE.
ONE = 1
*
* LBETA, LIEEE1, LT AND LRND ARE THE LOCAL VALUES OF BETA,
* IEEE1, T AND RND.
*
* THROUGHOUT THIS ROUTINE WE USE THE FUNCTION DLAMC3 TO ENSURE
* THAT RELEVANT VALUES ARE STORED AND NOT HELD IN REGISTERS, OR
* ARE NOT AFFECTED BY OPTIMIZERS.
*
* COMPUTE A = 2.0**M WITH THE SMALLEST POSITIVE INTEGER M SUCH
* THAT
*
* FL( A + 1.0 ) = A.
*
A = 1
C = 1
*
*+ WHILE( C.EQ.ONE )LOOP
10 CONTINUE
IF( C.EQ.ONE ) THEN
A = 2*A
C = DLAMC3( A, ONE )
C = DLAMC3( C, -A )
GO TO 10
END IF
*+ END WHILE
*
* NOW COMPUTE B = 2.0**M WITH THE SMALLEST POSITIVE INTEGER M
* SUCH THAT
*
* FL( A + B ) .GT. A.
*
B = 1
C = DLAMC3( A, B )
*
*+ WHILE( C.EQ.A )LOOP
20 CONTINUE
IF( C.EQ.A ) THEN
B = 2*B
C = DLAMC3( A, B )
GO TO 20
END IF
*+ END WHILE
*
* NOW COMPUTE THE BASE. A AND C ARE NEIGHBOURING FLOATING POINT
* NUMBERS IN THE INTERVAL ( BETA**T, BETA**( T + 1 ) ) AND SO
* THEIR DIFFERENCE IS BETA. ADDING 0.25 TO C IS TO ENSURE THAT IT
* IS TRUNCATED TO BETA AND NOT ( BETA - 1 ).
*
QTR = ONE / 4
SAVEC = C
C = DLAMC3( C, -A )
LBETA = C + QTR
*
* NOW DETERMINE WHETHER ROUNDING OR CHOPPING OCCURS, BY ADDING A
* BIT LESS THAN BETA/2 AND A BIT MORE THAN BETA/2 TO A.
*
B = LBETA
F = DLAMC3( B / 2, -B / 100 )
C = DLAMC3( F, A )
IF( C.EQ.A ) THEN
LRND = .TRUE.
ELSE
LRND = .FALSE.
END IF
F = DLAMC3( B / 2, B / 100 )
C = DLAMC3( F, A )
IF( ( LRND ) .AND. ( C.EQ.A ) )
$ LRND = .FALSE.
*
* TRY AND DECIDE WHETHER ROUNDING IS DONE IN THE IEEE 'ROUND TO
* NEAREST' STYLE. B/2 IS HALF A UNIT IN THE LAST PLACE OF THE TWO
* NUMBERS A AND SAVEC. FURTHERMORE, A IS EVEN, I.E. HAS LAST BIT
* ZERO, AND SAVEC IS ODD. THUS ADDING B/2 TO A SHOULD NOT CHANGE
* A, BUT ADDING B/2 TO SAVEC SHOULD CHANGE SAVEC.
*
T1 = DLAMC3( B / 2, A )
T2 = DLAMC3( B / 2, SAVEC )
LIEEE1 = ( T1.EQ.A ) .AND. ( T2.GT.SAVEC ) .AND. LRND
*
* NOW FIND THE MANTISSA, T. IT SHOULD BE THE INTEGER PART OF
* LOG TO THE BASE BETA OF A, HOWEVER IT IS SAFER TO DETERMINE T
* BY POWERING. SO WE FIND T AS THE SMALLEST POSITIVE INTEGER FOR
* WHICH
*
* FL( BETA**T + 1.0 ) = 1.0.
*
LT = 0
A = 1
C = 1
*
*+ WHILE( C.EQ.ONE )LOOP
30 CONTINUE
IF( C.EQ.ONE ) THEN
LT = LT + 1
A = A*LBETA
C = DLAMC3( A, ONE )
C = DLAMC3( C, -A )
GO TO 30
END IF
*+ END WHILE
*
END IF
*
BETA = LBETA
T = LT
RND = LRND
IEEE1 = LIEEE1
RETURN
*
* END OF DLAMC1
*
END
*
************************************************************************
*
SUBROUTINE DLAMC2( BETA, T, RND, EPS, EMIN, RMIN, EMAX, RMAX )
*
* -- LAPACK AUXILIARY ROUTINE (VERSION 1.1) --
* UNIV. OF TENNESSEE, UNIV. OF CALIFORNIA BERKELEY, NAG LTD.,
* COURANT INSTITUTE, ARGONNE NATIONAL LAB, AND RICE UNIVERSITY
* OCTOBER 31, 1992
*
* .. SCALAR ARGUMENTS ..
LOGICAL RND
INTEGER BETA, EMAX, EMIN, T
DOUBLE PRECISION EPS, RMAX, RMIN
* ..
*
* PURPOSE
* =======
*
* DLAMC2 DETERMINES THE MACHINE PARAMETERS SPECIFIED IN ITS ARGUMENT
* LIST.
*
* ARGUMENTS
* =========
*
* BETA (OUTPUT) INTEGER
* THE BASE OF THE MACHINE.
*
* T (OUTPUT) INTEGER
* THE NUMBER OF ( BETA ) DIGITS IN THE MANTISSA.
*
* RND (OUTPUT) LOGICAL
* SPECIFIES WHETHER PROPER ROUNDING ( RND = .TRUE. ) OR
* CHOPPING ( RND = .FALSE. ) OCCURS IN ADDITION. THIS MAY NOT
* BE A RELIABLE GUIDE TO THE WAY IN WHICH THE MACHINE PERFORMS
* ITS ARITHMETIC.
*
* EPS (OUTPUT) DOUBLE PRECISION
* THE SMALLEST POSITIVE NUMBER SUCH THAT
*
* FL( 1.0 - EPS ) .LT. 1.0,
*
* WHERE FL DENOTES THE COMPUTED VALUE.
*
* EMIN (OUTPUT) INTEGER
* THE MINIMUM EXPONENT BEFORE (GRADUAL) UNDERFLOW OCCURS.
*
* RMIN (OUTPUT) DOUBLE PRECISION
* THE SMALLEST NORMALIZED NUMBER FOR THE MACHINE, GIVEN BY
* BASE**( EMIN - 1 ), WHERE BASE IS THE FLOATING POINT VALUE
* OF BETA.
*
* EMAX (OUTPUT) INTEGER
* THE MAXIMUM EXPONENT BEFORE OVERFLOW OCCURS.
*
* RMAX (OUTPUT) DOUBLE PRECISION
* THE LARGEST POSITIVE NUMBER FOR THE MACHINE, GIVEN BY
* BASE**EMAX * ( 1 - EPS ), WHERE BASE IS THE FLOATING POINT
* VALUE OF BETA.
*
* FURTHER DETAILS
* ===============
*
* THE COMPUTATION OF EPS IS BASED ON A ROUTINE PARANOIA BY
* W. KAHAN OF THE UNIVERSITY OF CALIFORNIA AT BERKELEY.
*
* =====================================================================
*
* .. LOCAL SCALARS ..
LOGICAL FIRST, IEEE, IWARN, LIEEE1, LRND
INTEGER GNMIN, GPMIN, I, LBETA, LEMAX, LEMIN, LT,
$ NGNMIN, NGPMIN
DOUBLE PRECISION A, B, C, HALF, LEPS, LRMAX, LRMIN, ONE, RBASE,
$ SIXTH, SMALL, THIRD, TWO, ZERO
* ..
* .. EXTERNAL FUNCTIONS ..
DOUBLE PRECISION DLAMC3
EXTERNAL DLAMC3
* ..
* .. EXTERNAL SUBROUTINES ..
EXTERNAL DLAMC1, DLAMC4, DLAMC5
* ..
* .. INTRINSIC FUNCTIONS ..
INTRINSIC ABS, MAX, MIN
* ..
* .. SAVE STATEMENT ..
SAVE FIRST, IWARN, LBETA, LEMAX, LEMIN, LEPS, LRMAX,
$ LRMIN, LT
* ..
* .. DATA STATEMENTS ..
DATA FIRST / .TRUE. / , IWARN / .FALSE. /
* ..
* .. EXECUTABLE STATEMENTS ..
*
IF( FIRST ) THEN
FIRST = .FALSE.
ZERO = 0
ONE = 1
TWO = 2
*
* LBETA, LT, LRND, LEPS, LEMIN AND LRMIN ARE THE LOCAL VALUES OF
* BETA, T, RND, EPS, EMIN AND RMIN.
*
* THROUGHOUT THIS ROUTINE WE USE THE FUNCTION DLAMC3 TO ENSURE
* THAT RELEVANT VALUES ARE STORED AND NOT HELD IN REGISTERS, OR
* ARE NOT AFFECTED BY OPTIMIZERS.
*
* DLAMC1 RETURNS THE PARAMETERS LBETA, LT, LRND AND LIEEE1.
*
CALL DLAMC1( LBETA, LT, LRND, LIEEE1 )
*
* START TO FIND EPS.
*
B = LBETA
A = B**( -LT )
LEPS = A
*
* TRY SOME TRICKS TO SEE WHETHER OR NOT THIS IS THE CORRECT EPS.
*
B = TWO / 3
HALF = ONE / 2
SIXTH = DLAMC3( B, -HALF )
THIRD = DLAMC3( SIXTH, SIXTH )
B = DLAMC3( THIRD, -HALF )
B = DLAMC3( B, SIXTH )
B = ABS( B )
IF( B.LT.LEPS )
$ B = LEPS
*
LEPS = 1
*
*+ WHILE( ( LEPS.GT.B ).AND.( B.GT.ZERO ) )LOOP
10 CONTINUE
IF( ( LEPS.GT.B ) .AND. ( B.GT.ZERO ) ) THEN
LEPS = B
C = DLAMC3( HALF*LEPS, ( TWO**5 )*( LEPS**2 ) )
C = DLAMC3( HALF, -C )
B = DLAMC3( HALF, C )
C = DLAMC3( HALF, -B )
B = DLAMC3( HALF, C )
GO TO 10
END IF
*+ END WHILE
*
IF( A.LT.LEPS )
$ LEPS = A
*
* COMPUTATION OF EPS COMPLETE.
*
* NOW FIND EMIN. LET A = + OR - 1, AND + OR - (1 + BASE**(-3)).
* KEEP DIVIDING A BY BETA UNTIL (GRADUAL) UNDERFLOW OCCURS. THIS
* IS DETECTED WHEN WE CANNOT RECOVER THE PREVIOUS A.
*
RBASE = ONE / LBETA
SMALL = ONE
DO 20 I = 1, 3
SMALL = DLAMC3( SMALL*RBASE, ZERO )
20 CONTINUE
A = DLAMC3( ONE, SMALL )
CALL DLAMC4( NGPMIN, ONE, LBETA )
CALL DLAMC4( NGNMIN, -ONE, LBETA )
CALL DLAMC4( GPMIN, A, LBETA )
CALL DLAMC4( GNMIN, -A, LBETA )
IEEE = .FALSE.
*
IF( ( NGPMIN.EQ.NGNMIN ) .AND. ( GPMIN.EQ.GNMIN ) ) THEN
IF( NGPMIN.EQ.GPMIN ) THEN
LEMIN = NGPMIN
* ( NON TWOS-COMPLEMENT MACHINES, NO GRADUAL UNDERFLOW;
* E.G., VAX )
ELSE IF( ( GPMIN-NGPMIN ).EQ.3 ) THEN
LEMIN = NGPMIN - 1 + LT
IEEE = .TRUE.
* ( NON TWOS-COMPLEMENT MACHINES, WITH GRADUAL UNDERFLOW;
* E.G., IEEE STANDARD FOLLOWERS )
ELSE
LEMIN = MIN( NGPMIN, GPMIN )
* ( A GUESS; NO KNOWN MACHINE )
IWARN = .TRUE.
END IF
*
ELSE IF( ( NGPMIN.EQ.GPMIN ) .AND. ( NGNMIN.EQ.GNMIN ) ) THEN
IF( ABS( NGPMIN-NGNMIN ).EQ.1 ) THEN
LEMIN = MAX( NGPMIN, NGNMIN )
* ( TWOS-COMPLEMENT MACHINES, NO GRADUAL UNDERFLOW;
* E.G., CYBER 205 )
ELSE
LEMIN = MIN( NGPMIN, NGNMIN )
* ( A GUESS; NO KNOWN MACHINE )
IWARN = .TRUE.
END IF
*
ELSE IF( ( ABS( NGPMIN-NGNMIN ).EQ.1 ) .AND.
$ ( GPMIN.EQ.GNMIN ) ) THEN
IF( ( GPMIN-MIN( NGPMIN, NGNMIN ) ).EQ.3 ) THEN
LEMIN = MAX( NGPMIN, NGNMIN ) - 1 + LT
* ( TWOS-COMPLEMENT MACHINES WITH GRADUAL UNDERFLOW;
* NO KNOWN MACHINE )
ELSE
LEMIN = MIN( NGPMIN, NGNMIN )
* ( A GUESS; NO KNOWN MACHINE )
IWARN = .TRUE.
END IF
*
ELSE
LEMIN = MIN( NGPMIN, NGNMIN, GPMIN, GNMIN )
* ( A GUESS; NO KNOWN MACHINE )
IWARN = .TRUE.
END IF
***
* COMMENT OUT THIS IF BLOCK IF EMIN IS OK
IF( IWARN ) THEN
FIRST = .TRUE.
WRITE( 6, FMT = 9999 )LEMIN
END IF
***
*
* ASSUME IEEE ARITHMETIC IF WE FOUND DENORMALISED NUMBERS ABOVE,
* OR IF ARITHMETIC SEEMS TO ROUND IN THE IEEE STYLE, DETERMINED
* IN ROUTINE DLAMC1. A TRUE IEEE MACHINE SHOULD HAVE BOTH THINGS
* TRUE; HOWEVER, FAULTY MACHINES MAY HAVE ONE OR THE OTHER.
*
IEEE = IEEE .OR. LIEEE1
*
* COMPUTE RMIN BY SUCCESSIVE DIVISION BY BETA. WE COULD COMPUTE
* RMIN AS BASE**( EMIN - 1 ), BUT SOME MACHINES UNDERFLOW DURING
* THIS COMPUTATION.
*
LRMIN = 1
DO 30 I = 1, 1 - LEMIN
LRMIN = DLAMC3( LRMIN*RBASE, ZERO )
30 CONTINUE
*
* FINALLY, CALL DLAMC5 TO COMPUTE EMAX AND RMAX.
*
CALL DLAMC5( LBETA, LT, LEMIN, IEEE, LEMAX, LRMAX )
END IF
*
BETA = LBETA
T = LT
RND = LRND
EPS = LEPS
EMIN = LEMIN
RMIN = LRMIN
EMAX = LEMAX
RMAX = LRMAX
*
RETURN
*
9999 FORMAT( / / ' WARNING. THE VALUE EMIN MAY BE INCORRECT:-',
$ ' EMIN = ', I8, /
$ ' IF, AFTER INSPECTION, THE VALUE EMIN LOOKS',
$ ' ACCEPTABLE PLEASE COMMENT OUT ',
$ / ' THE IF BLOCK AS MARKED WITHIN THE CODE OF ROUTINE',
$ ' DLAMC2,', / ' OTHERWISE SUPPLY EMIN EXPLICITLY.', / )
*
* END OF DLAMC2
*
END
*
************************************************************************
*
DOUBLE PRECISION FUNCTION DLAMC3( A, B )
*
* -- LAPACK AUXILIARY ROUTINE (VERSION 1.1) --
* UNIV. OF TENNESSEE, UNIV. OF CALIFORNIA BERKELEY, NAG LTD.,
* COURANT INSTITUTE, ARGONNE NATIONAL LAB, AND RICE UNIVERSITY
* OCTOBER 31, 1992
*
* .. SCALAR ARGUMENTS ..
DOUBLE PRECISION A, B
* ..
*
* PURPOSE
* =======
*
* DLAMC3 IS INTENDED TO FORCE A AND B TO BE STORED PRIOR TO DOING
* THE ADDITION OF A AND B , FOR USE IN SITUATIONS WHERE OPTIMIZERS
* MIGHT HOLD ONE OF THESE IN A REGISTER.
*
* ARGUMENTS
* =========
*
* A, B (INPUT) DOUBLE PRECISION
* THE VALUES A AND B.
*
* =====================================================================
*
* .. EXECUTABLE STATEMENTS ..
*
DLAMC3 = A + B
*
RETURN
*
* END OF DLAMC3
*
END
*
************************************************************************
*
SUBROUTINE DLAMC4( EMIN, START, BASE )
*
* -- LAPACK AUXILIARY ROUTINE (VERSION 1.1) --
* UNIV. OF TENNESSEE, UNIV. OF CALIFORNIA BERKELEY, NAG LTD.,
* COURANT INSTITUTE, ARGONNE NATIONAL LAB, AND RICE UNIVERSITY
* OCTOBER 31, 1992
*
* .. SCALAR ARGUMENTS ..
INTEGER BASE, EMIN
DOUBLE PRECISION START
* ..
*
* PURPOSE
* =======
*
* DLAMC4 IS A SERVICE ROUTINE FOR DLAMC2.
*
* ARGUMENTS
* =========
*
* EMIN (OUTPUT) EMIN
* THE MINIMUM EXPONENT BEFORE (GRADUAL) UNDERFLOW, COMPUTED BY
* SETTING A = START AND DIVIDING BY BASE UNTIL THE PREVIOUS A
* CAN NOT BE RECOVERED.
*
* START (INPUT) DOUBLE PRECISION
* THE STARTING POINT FOR DETERMINING EMIN.
*
* BASE (INPUT) INTEGER
* THE BASE OF THE MACHINE.
*
* =====================================================================
*
* .. LOCAL SCALARS ..
INTEGER I
DOUBLE PRECISION A, B1, B2, C1, C2, D1, D2, ONE, RBASE, ZERO
* ..
* .. EXTERNAL FUNCTIONS ..
DOUBLE PRECISION DLAMC3
EXTERNAL DLAMC3
* ..
* .. EXECUTABLE STATEMENTS ..
*
A = START
ONE = 1
RBASE = ONE / BASE
ZERO = 0
EMIN = 1
B1 = DLAMC3( A*RBASE, ZERO )
C1 = A
C2 = A
D1 = A
D2 = A
*+ WHILE( ( C1.EQ.A ).AND.( C2.EQ.A ).AND.
* $ ( D1.EQ.A ).AND.( D2.EQ.A ) )LOOP
10 CONTINUE
IF( ( C1.EQ.A ) .AND. ( C2.EQ.A ) .AND. ( D1.EQ.A ) .AND.
$ ( D2.EQ.A ) ) THEN
EMIN = EMIN - 1
A = B1
B1 = DLAMC3( A / BASE, ZERO )
C1 = DLAMC3( B1*BASE, ZERO )
D1 = ZERO
DO 20 I = 1, BASE
D1 = D1 + B1
20 CONTINUE
B2 = DLAMC3( A*RBASE, ZERO )
C2 = DLAMC3( B2 / RBASE, ZERO )
D2 = ZERO
DO 30 I = 1, BASE
D2 = D2 + B2
30 CONTINUE
GO TO 10
END IF
*+ END WHILE
*
RETURN
*
* END OF DLAMC4
*
END
*
************************************************************************
*
SUBROUTINE DLAMC5( BETA, P, EMIN, IEEE, EMAX, RMAX )
*
* -- LAPACK AUXILIARY ROUTINE (VERSION 1.1) --
* UNIV. OF TENNESSEE, UNIV. OF CALIFORNIA BERKELEY, NAG LTD.,
* COURANT INSTITUTE, ARGONNE NATIONAL LAB, AND RICE UNIVERSITY
* OCTOBER 31, 1992
*
* .. SCALAR ARGUMENTS ..
LOGICAL IEEE
INTEGER BETA, EMAX, EMIN, P
DOUBLE PRECISION RMAX
* ..
*
* PURPOSE
* =======
*
* DLAMC5 ATTEMPTS TO COMPUTE RMAX, THE LARGEST MACHINE FLOATING-POINT
* NUMBER, WITHOUT OVERFLOW. IT ASSUMES THAT EMAX + ABS(EMIN) SUM
* APPROXIMATELY TO A POWER OF 2. IT WILL FAIL ON MACHINES WHERE THIS
* ASSUMPTION DOES NOT HOLD, FOR EXAMPLE, THE CYBER 205 (EMIN = -28625,
* EMAX = 28718). IT WILL ALSO FAIL IF THE VALUE SUPPLIED FOR EMIN IS
* TOO LARGE (I.E. TOO CLOSE TO ZERO), PROBABLY WITH OVERFLOW.
*
* ARGUMENTS
* =========
*
* BETA (INPUT) INTEGER
* THE BASE OF FLOATING-POINT ARITHMETIC.
*
* P (INPUT) INTEGER
* THE NUMBER OF BASE BETA DIGITS IN THE MANTISSA OF A
* FLOATING-POINT VALUE.
*
* EMIN (INPUT) INTEGER
* THE MINIMUM EXPONENT BEFORE (GRADUAL) UNDERFLOW.
*
* IEEE (INPUT) LOGICAL
* A LOGICAL FLAG SPECIFYING WHETHER OR NOT THE ARITHMETIC
* SYSTEM IS THOUGHT TO COMPLY WITH THE IEEE STANDARD.
*
* EMAX (OUTPUT) INTEGER
* THE LARGEST EXPONENT BEFORE OVERFLOW
*
* RMAX (OUTPUT) DOUBLE PRECISION
* THE LARGEST MACHINE FLOATING-POINT NUMBER.
*
* =====================================================================
*
* .. PARAMETERS ..
DOUBLE PRECISION ZERO, ONE
PARAMETER ( ZERO = 0.0D0, ONE = 1.0D0 )
* ..
* .. LOCAL SCALARS ..
INTEGER EXBITS, EXPSUM, I, LEXP, NBITS, TRY, UEXP
DOUBLE PRECISION OLDY, RECBAS, Y, Z
* ..
* .. EXTERNAL FUNCTIONS ..
DOUBLE PRECISION DLAMC3
EXTERNAL DLAMC3
* ..
* .. INTRINSIC FUNCTIONS ..
INTRINSIC MOD
* ..
* .. EXECUTABLE STATEMENTS ..
*
* FIRST COMPUTE LEXP AND UEXP, TWO POWERS OF 2 THAT BOUND
* ABS(EMIN). WE THEN ASSUME THAT EMAX + ABS(EMIN) WILL SUM
* APPROXIMATELY TO THE BOUND THAT IS CLOSEST TO ABS(EMIN).
* (EMAX IS THE EXPONENT OF THE REQUIRED NUMBER RMAX).
*
LEXP = 1
EXBITS = 1
10 CONTINUE
TRY = LEXP*2
IF( TRY.LE.( -EMIN ) ) THEN
LEXP = TRY
EXBITS = EXBITS + 1
GO TO 10
END IF
IF( LEXP.EQ.-EMIN ) THEN
UEXP = LEXP
ELSE
UEXP = TRY
EXBITS = EXBITS + 1
END IF
*
* NOW -LEXP IS LESS THAN OR EQUAL TO EMIN, AND -UEXP IS GREATER
* THAN OR EQUAL TO EMIN. EXBITS IS THE NUMBER OF BITS NEEDED TO
* STORE THE EXPONENT.
*
IF( ( UEXP+EMIN ).GT.( -LEXP-EMIN ) ) THEN
EXPSUM = 2*LEXP
ELSE
EXPSUM = 2*UEXP
END IF
*
* EXPSUM IS THE EXPONENT RANGE, APPROXIMATELY EQUAL TO
* EMAX - EMIN + 1 .
*
EMAX = EXPSUM + EMIN - 1
NBITS = 1 + EXBITS + P
*
* NBITS IS THE TOTAL NUMBER OF BITS NEEDED TO STORE A
* FLOATING-POINT NUMBER.
*
IF( ( MOD( NBITS, 2 ).EQ.1 ) .AND. ( BETA.EQ.2 ) ) THEN
*
* EITHER THERE ARE AN ODD NUMBER OF BITS USED TO STORE A
* FLOATING-POINT NUMBER, WHICH IS UNLIKELY, OR SOME BITS ARE
* NOT USED IN THE REPRESENTATION OF NUMBERS, WHICH IS POSSIBLE,
* (E.G. CRAY MACHINES) OR THE MANTISSA HAS AN IMPLICIT BIT,
* (E.G. IEEE MACHINES, DEC VAX MACHINES), WHICH IS PERHAPS THE
* MOST LIKELY. WE HAVE TO ASSUME THE LAST ALTERNATIVE.
* IF THIS IS TRUE, THEN WE NEED TO REDUCE EMAX BY ONE BECAUSE
* THERE MUST BE SOME WAY OF REPRESENTING ZERO IN AN IMPLICIT-BIT
* SYSTEM. ON MACHINES LIKE CRAY, WE ARE REDUCING EMAX BY ONE
* UNNECESSARILY.
*
EMAX = EMAX - 1
END IF
*
IF( IEEE ) THEN
*
* ASSUME WE ARE ON AN IEEE MACHINE WHICH RESERVES ONE EXPONENT
* FOR INFINITY AND NAN.
*
EMAX = EMAX - 1
END IF
*
* NOW CREATE RMAX, THE LARGEST MACHINE NUMBER, WHICH SHOULD
* BE EQUAL TO (1.0 - BETA**(-P)) * BETA**EMAX .
*
* FIRST COMPUTE 1.0 - BETA**(-P), BEING CAREFUL THAT THE
* RESULT IS LESS THAN 1.0 .
*
RECBAS = ONE / BETA
Z = BETA - ONE
Y = ZERO
DO 20 I = 1, P
Z = Z*RECBAS
IF( Y.LT.ONE )
$ OLDY = Y
Y = DLAMC3( Y, Z )
20 CONTINUE
IF( Y.GE.ONE )
$ Y = OLDY
*
* NOW MULTIPLY BY BETA**EMAX TO GET RMAX.
*
DO 30 I = 1, EMAX
Y = DLAMC3( Y*BETA, ZERO )
30 CONTINUE
*
RMAX = Y
RETURN
*
* END OF DLAMC5
*
END
CUT HERE............
CAT > DLAPY2.F <<'CUT HERE............'
DOUBLE PRECISION FUNCTION DLAPY2( X, Y )
*
* -- LAPACK AUXILIARY ROUTINE (VERSION 1.1) --
* UNIV. OF TENNESSEE, UNIV. OF CALIFORNIA BERKELEY, NAG LTD.,
* COURANT INSTITUTE, ARGONNE NATIONAL LAB, AND RICE UNIVERSITY
* OCTOBER 31, 1992
*
* .. SCALAR ARGUMENTS ..
DOUBLE PRECISION X, Y
* ..
*
* PURPOSE
* =======
*
* DLAPY2 RETURNS SQRT(X**2+Y**2), TAKING CARE NOT TO CAUSE UNNECESSARY
* OVERFLOW.
*
* ARGUMENTS
* =========
*
* X (INPUT) DOUBLE PRECISION
* Y (INPUT) DOUBLE PRECISION
* X AND Y SPECIFY THE VALUES X AND Y.
*
* =====================================================================
*
* .. PARAMETERS ..
DOUBLE PRECISION ZERO
PARAMETER ( ZERO = 0.0D0 )
DOUBLE PRECISION ONE
PARAMETER ( ONE = 1.0D0 )
* ..
* .. LOCAL SCALARS ..
DOUBLE PRECISION W, XABS, YABS, Z
* ..
* .. INTRINSIC FUNCTIONS ..
INTRINSIC ABS, MAX, MIN, SQRT
* ..
* .. EXECUTABLE STATEMENTS ..
*
XABS = ABS( X )
YABS = ABS( Y )
W = MAX( XABS, YABS )
Z = MIN( XABS, YABS )
IF( Z.EQ.ZERO ) THEN
DLAPY2 = W
ELSE
DLAPY2 = W*SQRT( ONE+( Z / W )**2 )
END IF
RETURN
*
* END OF DLAPY2
*
END
CUT HERE............
CAT > ILAENV.F <<'CUT HERE............'
INTEGER FUNCTION ILAENV( ISPEC, NAME, OPTS, N1, N2, N3,
$ N4 )
*
* -- LAPACK AUXILIARY ROUTINE (PRELIMINARY VERSION) --
* UNIV. OF TENNESSEE, UNIV. OF CALIFORNIA BERKELEY, NAG LTD.,
* COURANT INSTITUTE, ARGONNE NATIONAL LAB, AND RICE UNIVERSITY
* FEBRUARY 20, 1992
*
* .. SCALAR ARGUMENTS ..
CHARACTER*( * ) NAME, OPTS
INTEGER ISPEC, N1, N2, N3, N4
* ..
*
* PURPOSE
* =======
*
* ILAENV IS CALLED FROM THE LAPACK ROUTINES TO CHOOSE PROBLEM-DEPENDENT
* PARAMETERS FOR THE LOCAL ENVIRONMENT. SEE ISPEC FOR A DESCRIPTION OF
* THE PARAMETERS.
*
* THIS VERSION PROVIDES A SET OF PARAMETERS WHICH SHOULD GIVE GOOD,
* BUT NOT OPTIMAL, PERFORMANCE ON MANY OF THE CURRENTLY AVAILABLE
* COMPUTERS. USERS ARE ENCOURAGED TO MODIFY THIS SUBROUTINE TO SET
* THE TUNING PARAMETERS FOR THEIR PARTICULAR MACHINE USING THE OPTION
* AND PROBLEM SIZE INFORMATION IN THE ARGUMENTS.
*
* THIS ROUTINE WILL NOT FUNCTION CORRECTLY IF IT IS CONVERTED TO ALL
* LOWER CASE. CONVERTING IT TO ALL UPPER CASE IS ALLOWED.
*
* ARGUMENTS
* =========
*
* ISPEC (INPUT) INTEGER
* SPECIFIES THE PARAMETER TO BE RETURNED AS THE VALUE OF
* ILAENV.
* = 1: THE OPTIMAL BLOCKSIZE; IF THIS VALUE IS 1, AN UNBLOCKED
* ALGORITHM WILL GIVE THE BEST PERFORMANCE.
* = 2: THE MINIMUM BLOCK SIZE FOR WHICH THE BLOCK ROUTINE
* SHOULD BE USED; IF THE USABLE BLOCK SIZE IS LESS THAN
* THIS VALUE, AN UNBLOCKED ROUTINE SHOULD BE USED.
* = 3: THE CROSSOVER POINT (IN A BLOCK ROUTINE, FOR N LESS
* THAN THIS VALUE, AN UNBLOCKED ROUTINE SHOULD BE USED)
* = 4: THE NUMBER OF SHIFTS, USED IN THE NONSYMMETRIC
* EIGENVALUE ROUTINES
* = 5: THE MINIMUM COLUMN DIMENSION FOR BLOCKING TO BE USED;
* RECTANGULAR BLOCKS MUST HAVE DIMENSION AT LEAST K BY M,
* WHERE K IS GIVEN BY ILAENV(2,...) AND M BY ILAENV(5,...)
* = 6: THE CROSSOVER POINT FOR THE SVD (WHEN REDUCING AN M BY N
* MATRIX TO BIDIAGONAL FORM, IF MAX(M,N)/MIN(M,N) EXCEEDS
* THIS VALUE, A QR FACTORIZATION IS USED FIRST TO REDUCE
* THE MATRIX TO A TRIANGULAR FORM.)
* = 7: THE NUMBER OF PROCESSORS
* = 8: THE CROSSOVER POINT FOR THE MULTISHIFT QR AND QZ METHODS
* FOR NONSYMMETRIC EIGENVALUE PROBLEMS.
*
* NAME (INPUT) CHARACTER*(*)
* THE NAME OF THE CALLING SUBROUTINE, IN EITHER UPPER CASE OR
* LOWER CASE.
*
* OPTS (INPUT) CHARACTER*(*)
* THE CHARACTER OPTIONS TO THE SUBROUTINE NAME, CONCATENATED
* INTO A SINGLE CHARACTER STRING. FOR EXAMPLE, UPLO = 'U',
* TRANS = 'T', AND DIAG = 'N' FOR A TRIANGULAR ROUTINE WOULD
* BE SPECIFIED AS OPTS = 'UTN'.
*
* N1 (INPUT) INTEGER
* N2 (INPUT) INTEGER
* N3 (INPUT) INTEGER
* N4 (INPUT) INTEGER
* PROBLEM DIMENSIONS FOR THE SUBROUTINE NAME; THESE MAY NOT ALL
* BE REQUIRED.
*
* (ILAENV) (OUTPUT) INTEGER
* >= 0: THE VALUE OF THE PARAMETER SPECIFIED BY ISPEC
* < 0: IF ILAENV = -K, THE K-TH ARGUMENT HAD AN ILLEGAL VALUE.
*
* FURTHER DETAILS
* ===============
*
* THE FOLLOWING CONVENTIONS HAVE BEEN USED WHEN CALLING ILAENV FROM THE
* LAPACK ROUTINES:
* 1) OPTS IS A CONCATENATION OF ALL OF THE CHARACTER OPTIONS TO
* SUBROUTINE NAME, IN THE SAME ORDER THAT THEY APPEAR IN THE
* ARGUMENT LIST FOR NAME, EVEN IF THEY ARE NOT USED IN DETERMINING
* THE VALUE OF THE PARAMETER SPECIFIED BY ISPEC.
* 2) THE PROBLEM DIMENSIONS N1, N2, N3, N4 ARE SPECIFIED IN THE ORDER
* THAT THEY APPEAR IN THE ARGUMENT LIST FOR NAME. N1 IS USED
* FIRST, N2 SECOND, AND SO ON, AND UNUSED PROBLEM DIMENSIONS ARE
* PASSED A VALUE OF -1.
* 3) THE PARAMETER VALUE RETURNED BY ILAENV IS CHECKED FOR VALIDITY IN
* THE CALLING SUBROUTINE. FOR EXAMPLE, ILAENV IS USED TO RETRIEVE
* THE OPTIMAL BLOCKSIZE FOR STRTRI AS FOLLOWS:
*
* NB = ILAENV( 1, 'STRTRI', UPLO // DIAG, N, -1, -1, -1 )
* IF( NB.LE.1 ) NB = MAX( 1, N )
*
* =====================================================================
*
* .. LOCAL SCALARS ..
LOGICAL CNAME, SNAME
CHARACTER*1 C1
CHARACTER*2 C2, C4
CHARACTER*3 C3
CHARACTER*6 SUBNAM
INTEGER I, IC, IZ, NB, NBMIN, NX
* ..
* .. INTRINSIC FUNCTIONS ..
INTRINSIC CHAR, ICHAR, INT, MIN, REAL
* ..
* .. EXECUTABLE STATEMENTS ..
*
GO TO ( 100, 100, 100, 400, 500, 600, 700, 800 ) ISPEC
*
* INVALID VALUE FOR ISPEC
*
ILAENV = -1
RETURN
*
100 CONTINUE
*
* CONVERT NAME TO UPPER CASE IF THE FIRST CHARACTER IS LOWER CASE.
*
ILAENV = 1
SUBNAM = NAME
IC = ICHAR( SUBNAM( 1:1 ) )
IZ = ICHAR( 'Z' )
IF( IZ.EQ.90 .OR. IZ.EQ.122 ) THEN
*
* ASCII CHARACTER SET
*
IF( IC.GE.97 .AND. IC.LE.122 ) THEN
SUBNAM( 1:1 ) = CHAR( IC-32 )
DO 10 I = 2, 6
IC = ICHAR( SUBNAM( I:I ) )
IF( IC.GE.97 .AND. IC.LE.122 )
$ SUBNAM( I:I ) = CHAR( IC-32 )
10 CONTINUE
END IF
*
ELSE IF( IZ.EQ.233 .OR. IZ.EQ.169 ) THEN
*
* EBCDIC CHARACTER SET
*
IF( ( IC.GE.129 .AND. IC.LE.137 ) .OR.
$ ( IC.GE.145 .AND. IC.LE.153 ) .OR.
$ ( IC.GE.162 .AND. IC.LE.169 ) ) THEN
SUBNAM( 1:1 ) = CHAR( IC+64 )
DO 20 I = 2, 6
IC = ICHAR( SUBNAM( I:I ) )
IF( ( IC.GE.129 .AND. IC.LE.137 ) .OR.
$ ( IC.GE.145 .AND. IC.LE.153 ) .OR.
$ ( IC.GE.162 .AND. IC.LE.169 ) )
$ SUBNAM( I:I ) = CHAR( IC+64 )
20 CONTINUE
END IF
*
ELSE IF( IZ.EQ.218 .OR. IZ.EQ.250 ) THEN
*
* PRIME MACHINES: ASCII+128
*
IF( IC.GE.225 .AND. IC.LE.250 ) THEN
SUBNAM( 1:1 ) = CHAR( IC-32 )
DO 30 I = 2, 6
IC = ICHAR( SUBNAM( I:I ) )
IF( IC.GE.225 .AND. IC.LE.250 )
$ SUBNAM( I:I ) = CHAR( IC-32 )
30 CONTINUE
END IF
END IF
*
C1 = SUBNAM( 1:1 )
SNAME = C1.EQ.'S' .OR. C1.EQ.'D'
CNAME = C1.EQ.'C' .OR. C1.EQ.'Z'
IF( .NOT.( CNAME .OR. SNAME ) )
$ RETURN
C2 = SUBNAM( 2:3 )
C3 = SUBNAM( 4:6 )
C4 = C3( 2:3 )
*
GO TO ( 110, 200, 300 ) ISPEC
*
110 CONTINUE
*
* ISPEC = 1: BLOCK SIZE
*
* IN THESE EXAMPLES, SEPARATE CODE IS PROVIDED FOR SETTING NB FOR
* REAL AND COMPLEX. WE ASSUME THAT NB WILL TAKE THE SAME VALUE IN
* SINGLE OR DOUBLE PRECISION.
*
NB = 1
*
IF( C2.EQ.'GE' ) THEN
IF( C3.EQ.'TRF' ) THEN
IF( SNAME ) THEN
NB = 64
ELSE
NB = 64
END IF
ELSE IF( C3.EQ.'QRF' .OR. C3.EQ.'RQF' .OR. C3.EQ.'LQF' .OR.
$ C3.EQ.'QLF' ) THEN
IF( SNAME ) THEN
NB = 32
ELSE
NB = 32
END IF
ELSE IF( C3.EQ.'HRD' ) THEN
IF( SNAME ) THEN
NB = 32
ELSE
NB = 32
END IF
ELSE IF( C3.EQ.'BRD' ) THEN
IF( SNAME ) THEN
NB = 32
ELSE
NB = 32
END IF
ELSE IF( C3.EQ.'TRI' ) THEN
IF( SNAME ) THEN
NB = 64
ELSE
NB = 64
END IF
END IF
ELSE IF( C2.EQ.'PO' ) THEN
IF( C3.EQ.'TRF' ) THEN
IF( SNAME ) THEN
NB = 64
ELSE
NB = 64
END IF
END IF
ELSE IF( C2.EQ.'SY' ) THEN
IF( C3.EQ.'TRF' ) THEN
IF( SNAME ) THEN
NB = 64
ELSE
NB = 64
END IF
ELSE IF( SNAME .AND. C3.EQ.'TRD' ) THEN
NB = 1
ELSE IF( SNAME .AND. C3.EQ.'GST' ) THEN
NB = 64
END IF
ELSE IF( CNAME .AND. C2.EQ.'HE' ) THEN
IF( C3.EQ.'TRF' ) THEN
NB = 64
ELSE IF( C3.EQ.'TRD' ) THEN
NB = 1
ELSE IF( C3.EQ.'GST' ) THEN
NB = 64
END IF
ELSE IF( SNAME .AND. C2.EQ.'OR' ) THEN
IF( C3( 1:1 ).EQ.'G' ) THEN
IF( C4.EQ.'QR' .OR. C4.EQ.'RQ' .OR. C4.EQ.'LQ' .OR.
$ C4.EQ.'QL' .OR. C4.EQ.'HR' .OR. C4.EQ.'TR' .OR.
$ C4.EQ.'BR' ) THEN
NB = 32
END IF
ELSE IF( C3( 1:1 ).EQ.'M' ) THEN
IF( C4.EQ.'QR' .OR. C4.EQ.'RQ' .OR. C4.EQ.'LQ' .OR.
$ C4.EQ.'QL' .OR. C4.EQ.'HR' .OR. C4.EQ.'TR' .OR.
$ C4.EQ.'BR' ) THEN
NB = 32
END IF
END IF
ELSE IF( CNAME .AND. C2.EQ.'UN' ) THEN
IF( C3( 1:1 ).EQ.'G' ) THEN
IF( C4.EQ.'QR' .OR. C4.EQ.'RQ' .OR. C4.EQ.'LQ' .OR.
$ C4.EQ.'QL' .OR. C4.EQ.'HR' .OR. C4.EQ.'TR' .OR.
$ C4.EQ.'BR' ) THEN
NB = 32
END IF
ELSE IF( C3( 1:1 ).EQ.'M' ) THEN
IF( C4.EQ.'QR' .OR. C4.EQ.'RQ' .OR. C4.EQ.'LQ' .OR.
$ C4.EQ.'QL' .OR. C4.EQ.'HR' .OR. C4.EQ.'TR' .OR.
$ C4.EQ.'BR' ) THEN
NB = 32
END IF
END IF
ELSE IF( C2.EQ.'GB' ) THEN
IF( C3.EQ.'TRF' ) THEN
IF( SNAME ) THEN
IF( N4.LE.64 ) THEN
NB = 1
ELSE
NB = 32
END IF
ELSE
IF( N4.LE.64 ) THEN
NB = 1
ELSE
NB = 32
END IF
END IF
END IF
ELSE IF( C2.EQ.'PB' ) THEN
IF( C3.EQ.'TRF' ) THEN
IF( SNAME ) THEN
IF( N2.LE.64 ) THEN
NB = 1
ELSE
NB = 32
END IF
ELSE
IF( N2.LE.64 ) THEN
NB = 1
ELSE
NB = 32
END IF
END IF
END IF
ELSE IF( C2.EQ.'TR' ) THEN
IF( C3.EQ.'TRI' ) THEN
IF( SNAME ) THEN
NB = 64
ELSE
NB = 64
END IF
END IF
ELSE IF( C2.EQ.'LA' ) THEN
IF( C3.EQ.'UUM' ) THEN
IF( SNAME ) THEN
NB = 64
ELSE
NB = 64
END IF
END IF
ELSE IF( SNAME .AND. C2.EQ.'ST' ) THEN
IF( C3.EQ.'EBZ' ) THEN
NB = 1
END IF
END IF
ILAENV = NB
RETURN
*
200 CONTINUE
*
* ISPEC = 2: MINIMUM BLOCK SIZE
*
NBMIN = 2
IF( C2.EQ.'GE' ) THEN
IF( C3.EQ.'QRF' .OR. C3.EQ.'RQF' .OR. C3.EQ.'LQF' .OR.
$ C3.EQ.'QLF' ) THEN
IF( SNAME ) THEN
NBMIN = 2
ELSE
NBMIN = 2
END IF
ELSE IF( C3.EQ.'HRD' ) THEN
IF( SNAME ) THEN
NBMIN = 2
ELSE
NBMIN = 2
END IF
ELSE IF( C3.EQ.'BRD' ) THEN
IF( SNAME ) THEN
NBMIN = 2
ELSE
NBMIN = 2
END IF
ELSE IF( C3.EQ.'TRI' ) THEN
IF( SNAME ) THEN
NBMIN = 2
ELSE
NBMIN = 2
END IF
END IF
ELSE IF( C2.EQ.'SY' ) THEN
IF( C3.EQ.'TRF' ) THEN
IF( SNAME ) THEN
NBMIN = 2
ELSE
NBMIN = 2
END IF
ELSE IF( SNAME .AND. C3.EQ.'TRD' ) THEN
NBMIN = 2
END IF
ELSE IF( CNAME .AND. C2.EQ.'HE' ) THEN
IF( C3.EQ.'TRD' ) THEN
NBMIN = 2
END IF
ELSE IF( SNAME .AND. C2.EQ.'OR' ) THEN
IF( C3( 1:1 ).EQ.'G' ) THEN
IF( C4.EQ.'QR' .OR. C4.EQ.'RQ' .OR. C4.EQ.'LQ' .OR.
$ C4.EQ.'QL' .OR. C4.EQ.'HR' .OR. C4.EQ.'TR' .OR.
$ C4.EQ.'BR' ) THEN
NBMIN = 2
END IF
ELSE IF( C3( 1:1 ).EQ.'M' ) THEN
IF( C4.EQ.'QR' .OR. C4.EQ.'RQ' .OR. C4.EQ.'LQ' .OR.
$ C4.EQ.'QL' .OR. C4.EQ.'HR' .OR. C4.EQ.'TR' .OR.
$ C4.EQ.'BR' ) THEN
NBMIN = 2
END IF
END IF
ELSE IF( CNAME .AND. C2.EQ.'UN' ) THEN
IF( C3( 1:1 ).EQ.'G' ) THEN
IF( C4.EQ.'QR' .OR. C4.EQ.'RQ' .OR. C4.EQ.'LQ' .OR.
$ C4.EQ.'QL' .OR. C4.EQ.'HR' .OR. C4.EQ.'TR' .OR.
$ C4.EQ.'BR' ) THEN
NBMIN = 2
END IF
ELSE IF( C3( 1:1 ).EQ.'M' ) THEN
IF( C4.EQ.'QR' .OR. C4.EQ.'RQ' .OR. C4.EQ.'LQ' .OR.
$ C4.EQ.'QL' .OR. C4.EQ.'HR' .OR. C4.EQ.'TR' .OR.
$ C4.EQ.'BR' ) THEN
NBMIN = 2
END IF
END IF
END IF
ILAENV = NBMIN
RETURN
*
300 CONTINUE
*
* ISPEC = 3: CROSSOVER POINT
*
NX = 0
IF( C2.EQ.'GE' ) THEN
IF( C3.EQ.'QRF' .OR. C3.EQ.'RQF' .OR. C3.EQ.'LQF' .OR.
$ C3.EQ.'QLF' ) THEN
IF( SNAME ) THEN
NX = 128
ELSE
NX = 128
END IF
ELSE IF( C3.EQ.'HRD' ) THEN
IF( SNAME ) THEN
NX = 128
ELSE
NX = 128
END IF
ELSE IF( C3.EQ.'BRD' ) THEN
IF( SNAME ) THEN
NX = 128
ELSE
NX = 128
END IF
END IF
ELSE IF( C2.EQ.'SY' ) THEN
IF( SNAME .AND. C3.EQ.'TRD' ) THEN
NX = 1
END IF
ELSE IF( CNAME .AND. C2.EQ.'HE' ) THEN
IF( C3.EQ.'TRD' ) THEN
NX = 1
END IF
ELSE IF( SNAME .AND. C2.EQ.'OR' ) THEN
IF( C3( 1:1 ).EQ.'G' ) THEN
IF( C4.EQ.'QR' .OR. C4.EQ.'RQ' .OR. C4.EQ.'LQ' .OR.
$ C4.EQ.'QL' .OR. C4.EQ.'HR' .OR. C4.EQ.'TR' .OR.
$ C4.EQ.'BR' ) THEN
NX = 128
END IF
END IF
ELSE IF( CNAME .AND. C2.EQ.'UN' ) THEN
IF( C3( 1:1 ).EQ.'G' ) THEN
IF( C4.EQ.'QR' .OR. C4.EQ.'RQ' .OR. C4.EQ.'LQ' .OR.
$ C4.EQ.'QL' .OR. C4.EQ.'HR' .OR. C4.EQ.'TR' .OR.
$ C4.EQ.'BR' ) THEN
NX = 128
END IF
END IF
END IF
ILAENV = NX
RETURN
*
400 CONTINUE
*
* ISPEC = 4: NUMBER OF SHIFTS (USED BY XHSEQR)
*
ILAENV = 6
RETURN
*
500 CONTINUE
*
* ISPEC = 5: MINIMUM COLUMN DIMENSION (NOT USED)
*
ILAENV = 2
RETURN
*
600 CONTINUE
*
* ISPEC = 6: CROSSOVER POINT FOR SVD (USED BY XGELSS AND XGESVD)
*
ILAENV = INT( REAL( MIN( N1, N2 ) )*1.6E0 )
RETURN
*
700 CONTINUE
*
* ISPEC = 7: NUMBER OF PROCESSORS (NOT USED)
*
ILAENV = 1
RETURN
*
800 CONTINUE
*
* ISPEC = 8: CROSSOVER POINT FOR MULTISHIFT (USED BY XHSEQR)
*
ILAENV = 50
RETURN
*
* END OF ILAENV
*
END
CUT HERE............
CAT > DLANSY.F <<'CUT HERE............'
DOUBLE PRECISION FUNCTION DLANSY( NORM, UPLO, N, A, LDA, WORK )
*
* -- LAPACK AUXILIARY ROUTINE (VERSION 1.1) --
* UNIV. OF TENNESSEE, UNIV. OF CALIFORNIA BERKELEY, NAG LTD.,
* COURANT INSTITUTE, ARGONNE NATIONAL LAB, AND RICE UNIVERSITY
* OCTOBER 31, 1992
*
* .. SCALAR ARGUMENTS ..
CHARACTER NORM, UPLO
INTEGER LDA, N
* ..
* .. ARRAY ARGUMENTS ..
DOUBLE PRECISION A( LDA, * ), WORK( * )
* ..
*
* PURPOSE
* =======
*
* DLANSY RETURNS THE VALUE OF THE ONE NORM, OR THE FROBENIUS NORM, OR
* THE INFINITY NORM, OR THE ELEMENT OF LARGEST ABSOLUTE VALUE OF A
* REAL SYMMETRIC MATRIX A.
*
* DESCRIPTION
* ===========
*
* DLANSY RETURNS THE VALUE
*
* DLANSY = ( MAX(ABS(A(I,J))), NORM = 'M' OR 'M'
* (
* ( NORM1(A), NORM = '1', 'O' OR 'O'
* (
* ( NORMI(A), NORM = 'I' OR 'I'
* (
* ( NORMF(A), NORM = 'F', 'F', 'E' OR 'E'
*
* WHERE NORM1 DENOTES THE ONE NORM OF A MATRIX (MAXIMUM COLUMN SUM),
* NORMI DENOTES THE INFINITY NORM OF A MATRIX (MAXIMUM ROW SUM) AND
* NORMF DENOTES THE FROBENIUS NORM OF A MATRIX (SQUARE ROOT OF SUM OF
* SQUARES). NOTE THAT MAX(ABS(A(I,J))) IS NOT A MATRIX NORM.
*
* ARGUMENTS
* =========
*
* NORM (INPUT) CHARACTER*1
* SPECIFIES THE VALUE TO BE RETURNED IN DLANSY AS DESCRIBED
* ABOVE.
*
* UPLO (INPUT) CHARACTER*1
* SPECIFIES WHETHER THE UPPER OR LOWER TRIANGULAR PART OF THE
* SYMMETRIC MATRIX A IS TO BE REFERENCED.
* = 'U': UPPER TRIANGULAR PART OF A IS REFERENCED
* = 'L': LOWER TRIANGULAR PART OF A IS REFERENCED
*
* N (INPUT) INTEGER
* THE ORDER OF THE MATRIX A. N >= 0. WHEN N = 0, DLANSY IS
* SET TO ZERO.
*
* A (INPUT) DOUBLE PRECISION ARRAY, DIMENSION (LDA,N)
* 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, AND THE STRICTLY LOWER TRIANGULAR PART OF A
* IS NOT REFERENCED. IF UPLO = 'L', THE LEADING N BY N LOWER
* TRIANGULAR PART OF A CONTAINS THE LOWER TRIANGULAR PART OF
* THE MATRIX A, AND THE STRICTLY UPPER TRIANGULAR PART OF A IS
* NOT REFERENCED.
*
* LDA (INPUT) INTEGER
* THE LEADING DIMENSION OF THE ARRAY A. LDA >= MAX(N,1).
*
* WORK (WORKSPACE) DOUBLE PRECISION ARRAY, DIMENSION (LWORK),
* WHERE LWORK >= N WHEN NORM = 'I' OR '1' OR 'O'; OTHERWISE,
* WORK IS NOT REFERENCED.
*
* =====================================================================
*
* .. PARAMETERS ..
DOUBLE PRECISION ONE, ZERO
PARAMETER ( ONE = 1.0D+0, ZERO = 0.0D+0 )
* ..
* .. LOCAL SCALARS ..
INTEGER I, J
DOUBLE PRECISION ABSA, SCALE, SUM, VALUE
* ..
* .. EXTERNAL SUBROUTINES ..
EXTERNAL DLASSQ
* ..
* .. EXTERNAL FUNCTIONS ..
LOGICAL LSAME
EXTERNAL LSAME
* ..
* .. INTRINSIC FUNCTIONS ..
INTRINSIC ABS, MAX, SQRT
* ..
* .. EXECUTABLE STATEMENTS ..
*
IF( N.EQ.0 ) THEN
VALUE = ZERO
ELSE IF( LSAME( NORM, 'M' ) ) THEN
*
* FIND MAX(ABS(A(I,J))).
*
VALUE = ZERO
IF( LSAME( UPLO, 'U' ) ) THEN
DO 20 J = 1, N
DO 10 I = 1, J
VALUE = MAX( VALUE, ABS( A( I, J ) ) )
10 CONTINUE
20 CONTINUE
ELSE
DO 40 J = 1, N
DO 30 I = J, N
VALUE = MAX( VALUE, ABS( A( I, J ) ) )
30 CONTINUE
40 CONTINUE
END IF
ELSE IF( ( LSAME( NORM, 'I' ) ) .OR. ( LSAME( NORM, 'O' ) ) .OR.
$ ( NORM.EQ.'1' ) ) THEN
*
* FIND NORMI(A) ( = NORM1(A), SINCE A IS SYMMETRIC).
*
VALUE = ZERO
IF( LSAME( UPLO, 'U' ) ) THEN
DO 60 J = 1, N
SUM = ZERO
DO 50 I = 1, J - 1
ABSA = ABS( A( I, J ) )
SUM = SUM + ABSA
WORK( I ) = WORK( I ) + ABSA
50 CONTINUE
WORK( J ) = SUM + ABS( A( J, J ) )
60 CONTINUE
DO 70 I = 1, N
VALUE = MAX( VALUE, WORK( I ) )
70 CONTINUE
ELSE
DO 80 I = 1, N
WORK( I ) = ZERO
80 CONTINUE
DO 100 J = 1, N
SUM = WORK( J ) + ABS( A( J, J ) )
DO 90 I = J + 1, N
ABSA = ABS( A( I, J ) )
SUM = SUM + ABSA
WORK( I ) = WORK( I ) + ABSA
90 CONTINUE
VALUE = MAX( VALUE, SUM )
100 CONTINUE
END IF
ELSE IF( ( LSAME( NORM, 'F' ) ) .OR. ( LSAME( NORM, 'E' ) ) ) THEN
*
* FIND NORMF(A).
*
SCALE = ZERO
SUM = ONE
IF( LSAME( UPLO, 'U' ) ) THEN
DO 110 J = 2, N
CALL DLASSQ( J-1, A( 1, J ), 1, SCALE, SUM )
110 CONTINUE
ELSE
DO 120 J = 1, N - 1
CALL DLASSQ( N-J, A( J+1, J ), 1, SCALE, SUM )
120 CONTINUE
END IF
SUM = 2*SUM
CALL DLASSQ( N, A, LDA+1, SCALE, SUM )
VALUE = SCALE*SQRT( SUM )
END IF
*
DLANSY = VALUE
RETURN
*
* END OF DLANSY
*
END
CUT HERE............
CAT > DLASSQ.F <<'CUT HERE............'
SUBROUTINE DLASSQ( N, X, INCX, SCALE, SUMSQ )
*
* -- LAPACK AUXILIARY ROUTINE (VERSION 1.1) --
* UNIV. OF TENNESSEE, UNIV. OF CALIFORNIA BERKELEY, NAG LTD.,
* COURANT INSTITUTE, ARGONNE NATIONAL LAB, AND RICE UNIVERSITY
* OCTOBER 31, 1992
*
* .. SCALAR ARGUMENTS ..
INTEGER INCX, N
DOUBLE PRECISION SCALE, SUMSQ
* ..
* .. ARRAY ARGUMENTS ..
DOUBLE PRECISION X( * )
* ..
*
* PURPOSE
* =======
*
* DLASSQ RETURNS THE VALUES SCL AND SMSQ SUCH THAT
*
* ( SCL**2 )*SMSQ = X( 1 )**2 +...+ X( N )**2 + ( SCALE**2 )*SUMSQ,
*
* WHERE X( I ) = X( 1 + ( I - 1 )*INCX ). THE VALUE OF SUMSQ IS
* ASSUMED TO BE NON-NEGATIVE AND SCL RETURNS THE VALUE
*
* SCL = MAX( SCALE, ABS( X( I ) ) ).
*
* SCALE AND SUMSQ MUST BE SUPPLIED IN SCALE AND SUMSQ AND
* SCL AND SMSQ ARE OVERWRITTEN ON SCALE AND SUMSQ RESPECTIVELY.
*
* THE ROUTINE MAKES ONLY ONE PASS THROUGH THE VECTOR X.
*
* ARGUMENTS
* =========
*
* N (INPUT) INTEGER
* THE NUMBER OF ELEMENTS TO BE USED FROM THE VECTOR X.
*
* X (INPUT) DOUBLE PRECISION
* THE VECTOR FOR WHICH A SCALED SUM OF SQUARES IS COMPUTED.
* X( I ) = X( 1 + ( I - 1 )*INCX ), 1 <= I <= N.
*
* INCX (INPUT) INTEGER
* THE INCREMENT BETWEEN SUCCESSIVE VALUES OF THE VECTOR X.
* INCX > 0.
*
* SCALE (INPUT/OUTPUT) DOUBLE PRECISION
* ON ENTRY, THE VALUE SCALE IN THE EQUATION ABOVE.
* ON EXIT, SCALE IS OVERWRITTEN WITH SCL , THE SCALING FACTOR
* FOR THE SUM OF SQUARES.
*
* SUMSQ (INPUT/OUTPUT) DOUBLE PRECISION
* ON ENTRY, THE VALUE SUMSQ IN THE EQUATION ABOVE.
* ON EXIT, SUMSQ IS OVERWRITTEN WITH SMSQ , THE BASIC SUM OF
* SQUARES FROM WHICH SCL HAS BEEN FACTORED OUT.
*
* =====================================================================
*
* .. PARAMETERS ..
DOUBLE PRECISION ZERO
PARAMETER ( ZERO = 0.0D+0 )
* ..
* .. LOCAL SCALARS ..
INTEGER IX
DOUBLE PRECISION ABSXI
* ..
* .. INTRINSIC FUNCTIONS ..
INTRINSIC ABS
* ..
* .. EXECUTABLE STATEMENTS ..
*
IF( N.GT.0 ) THEN
DO 10 IX = 1, 1 + ( N-1 )*INCX, INCX
IF( X( IX ).NE.ZERO ) THEN
ABSXI = ABS( X( IX ) )
IF( SCALE.LT.ABSXI ) THEN
SUMSQ = 1 + SUMSQ*( SCALE / ABSXI )**2
SCALE = ABSXI
ELSE
SUMSQ = SUMSQ + ( ABSXI / SCALE )**2
END IF
END IF
10 CONTINUE
END IF
RETURN
*
* END OF DLASSQ
*
END
CUT HERE............
C ----------------- BELOW IS DSYTRF -------------------
CAT > DSYTRF.F <<'CUT HERE..........'
SUBROUTINE DSYTRF( UPLO, N, A, LDA, IPIV, WORK, LWORK, INFO )
*
* -- LAPACK ROUTINE (VERSION 1.0B) --
* UNIV. OF TENNESSEE, UNIV. OF CALIFORNIA BERKELEY, NAG LTD.,
* COURANT INSTITUTE, ARGONNE NATIONAL LAB, AND RICE UNIVERSITY
* FEBRUARY 29, 1992
*
* .. SCALAR ARGUMENTS ..
CHARACTER UPLO
INTEGER INFO, LDA, LWORK, N
* ..
* .. ARRAY ARGUMENTS ..
INTEGER IPIV( * )
DOUBLE PRECISION A( LDA, * ), WORK( LWORK )
* ..
*
* PURPOSE
* =======
*
* DSYTRF COMPUTES THE FACTORIZATION OF A REAL SYMMETRIC MATRIX A USING
* THE BUNCH-KAUFMAN DIAGONAL PIVOTING METHOD:
*
* A = U*D*U' OR A = L*D*L'
*
* WHERE U (OR L) IS A PRODUCT OF PERMUTATION AND UNIT UPPER (LOWER)
* TRIANGULAR MATRICES, U' IS THE TRANSPOSE OF U, AND D IS SYMMETRIC AND
* BLOCK DIAGONAL WITH 1-BY-1 AND 2-BY-2 DIAGONAL BLOCKS.
*
* THIS IS THE BLOCKED VERSION OF THE ALGORITHM, CALLING LEVEL 3 BLAS.
*
* ARGUMENTS
* =========
*
* UPLO (INPUT) CHARACTER*1
* SPECIFIES WHETHER THE UPPER OR LOWER TRIANGULAR PART OF THE
* SYMMETRIC MATRIX A IS STORED:
* = 'U': UPPER TRIANGULAR
* = 'L': LOWER TRIANGULAR
*
* N (INPUT) INTEGER
* THE ORDER OF THE MATRIX A. N >= 0.
*
* A (INPUT/OUTPUT) DOUBLE PRECISION 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, AND THE STRICTLY LOWER
* TRIANGULAR PART OF A IS NOT REFERENCED. IF UPLO = 'L', THE
* LEADING N-BY-N LOWER TRIANGULAR PART OF A CONTAINS THE LOWER
* TRIANGULAR PART OF THE MATRIX A, AND THE STRICTLY UPPER
* TRIANGULAR PART OF A IS NOT REFERENCED.
*
* ON EXIT, THE BLOCK DIAGONAL MATRIX D AND THE MULTIPLIERS USED
* TO OBTAIN THE FACTOR U OR L (SEE BELOW FOR FURTHER DETAILS).
*
* LDA (INPUT) INTEGER
* THE LEADING DIMENSION OF THE ARRAY A. LDA >= MAX(1,N).
*
* IPIV (OUTPUT) INTEGER ARRAY, DIMENSION (N)
* DETAILS OF THE INTERCHANGES AND THE BLOCK STRUCTURE OF D.
* IF IPIV(K) > 0, THEN ROWS AND COLUMNS K AND IPIV(K) WERE
* INTERCHANGED AND D(K,K) IS A 1-BY-1 DIAGONAL BLOCK.
* IF UPLO = 'U' AND IPIV(K) = IPIV(K-1) < 0, THEN ROWS AND
* COLUMNS K-1 AND -IPIV(K) WERE INTERCHANGED AND D(K-1:K,K-1:K)
* IS A 2-BY-2 DIAGONAL BLOCK. IF UPLO = 'L' AND IPIV(K) =
* IPIV(K+1) < 0, THEN ROWS AND COLUMNS K+1 AND -IPIV(K) WERE
* INTERCHANGED AND D(K:K+1,K:K+1) IS A 2-BY-2 DIAGONAL BLOCK.
*
* WORK (WORKSPACE) DOUBLE PRECISION ARRAY, DIMENSION (LWORK)
* IF INFO RETURNS 0, THEN WORK(1) RETURNS N*NB, THE MINIMUM
* VALUE OF LWORK REQUIRED TO USE THE OPTIMAL BLOCKSIZE.
*
* LWORK (INPUT) INTEGER
* THE LENGTH OF WORK. LWORK SHOULD BE >= N*NB, WHERE NB IS THE
* BLOCK SIZE RETURNED BY ILAENV.
*
* INFO (OUTPUT) INTEGER
* = 0: SUCCESSFUL EXIT
* < 0: IF INFO = -K, THE K-TH ARGUMENT HAD AN ILLEGAL VALUE
* > 0: IF INFO = K, D(K,K) IS EXACTLY ZERO. THE FACTORIZATION
* HAS BEEN COMPLETED, BUT THE BLOCK DIAGONAL MATRIX D IS
* EXACTLY SINGULAR, AND DIVISION BY ZERO WILL OCCUR IF IT
* IS USED TO SOLVE A SYSTEM OF EQUATIONS.
*
* FURTHER DETAILS
* ===============
*
* IF UPLO = 'U', THEN A = U*D*U', WHERE
* U = P(N)*U(N)* ... *P(K)U(K)* ...,
* I.E., U IS A PRODUCT OF TERMS P(K)*U(K), WHERE K DECREASES FROM N TO
* 1 IN STEPS OF 1 OR 2, AND D IS A BLOCK DIAGONAL MATRIX WITH 1-BY-1
* AND 2-BY-2 DIAGONAL BLOCKS D(K). P(K) IS A PERMUTATION MATRIX AS
* DEFINED BY IPIV(K), AND U(K) IS A UNIT UPPER TRIANGULAR MATRIX, SUCH
* THAT IF THE DIAGONAL BLOCK D(K) IS OF ORDER S (S = 1 OR 2), THEN
*
* ( I V 0 ) K-S
* U(K) = ( 0 I 0 ) S
* ( 0 0 I ) N-K
* K-S S N-K
*
* IF S = 1, D(K) OVERWRITES A(K,K), AND V OVERWRITES A(1:K-1,K).
* IF S = 2, THE UPPER TRIANGLE OF D(K) OVERWRITES A(K-1,K-1), A(K-1,K),
* AND A(K,K), AND V OVERWRITES A(1:K-2,K-1:K).
*
* IF UPLO = 'L', THEN A = L*D*L', WHERE
* L = P(1)*L(1)* ... *P(K)*L(K)* ...,
* I.E., L IS A PRODUCT OF TERMS P(K)*L(K), WHERE K INCREASES FROM 1 TO
* N IN STEPS OF 1 OR 2, AND D IS A BLOCK DIAGONAL MATRIX WITH 1-BY-1
* AND 2-BY-2 DIAGONAL BLOCKS D(K). P(K) IS A PERMUTATION MATRIX AS
* DEFINED BY IPIV(K), AND L(K) IS A UNIT LOWER TRIANGULAR MATRIX, SUCH
* THAT IF THE DIAGONAL BLOCK D(K) IS OF ORDER S (S = 1 OR 2), THEN
*
* ( I 0 0 ) K-1
* L(K) = ( 0 I 0 ) S
* ( 0 V I ) N-K-S+1
* K-1 S N-K-S+1
*
* IF S = 1, D(K) OVERWRITES A(K,K), AND V OVERWRITES A(K+1:N,K).
* IF S = 2, THE LOWER TRIANGLE OF D(K) OVERWRITES A(K,K), A(K+1,K),
* AND A(K+1,K+1), AND V OVERWRITES A(K+2:N,K:K+1).
*
* =====================================================================
*
* .. LOCAL SCALARS ..
LOGICAL UPPER
INTEGER IINFO, IWS, J, K, KB, LDWORK, NB, NBMIN
* ..
* .. EXTERNAL FUNCTIONS ..
LOGICAL LSAME
INTEGER ILAENV
EXTERNAL LSAME, ILAENV
* ..
* .. EXTERNAL SUBROUTINES ..
EXTERNAL DLASYF, DSYTF2, XERBLA
* ..
* .. INTRINSIC FUNCTIONS ..
INTRINSIC MAX
* ..
* .. EXECUTABLE STATEMENTS ..
*
* TEST THE INPUT PARAMETERS.
*
INFO = 0
UPPER = LSAME( UPLO, 'U' )
IF( .NOT.UPPER .AND. .NOT.LSAME( UPLO, 'L' ) ) THEN
INFO = -1
ELSE IF( N.LT.0 ) THEN
INFO = -2
ELSE IF( LDA.LT.MAX( 1, N ) ) THEN
INFO = -4
ELSE IF( LWORK.LT.1 ) THEN
INFO = -7
END IF
IF( INFO.NE.0 ) THEN
CALL XERBLA( 'DSYTRF', -INFO )
RETURN
END IF
*
* DETERMINE THE BLOCK SIZE
*
NB = ILAENV( 1, 'DSYTRF', UPLO, N, -1, -1, -1 )
NBMIN = 2
LDWORK = N
IF( NB.GT.1 .AND. NB.LT.N ) THEN
IWS = LDWORK*NB
IF( LWORK.LT.IWS ) THEN
NB = MAX( LWORK / LDWORK, 1 )
NBMIN = MAX( 2, ILAENV( 2, 'DSYTRF', UPLO, N, -1, -1, -1 ) )
END IF
ELSE
IWS = 1
END IF
IF( NB.LT.NBMIN )
$ NB = N
*
IF( UPPER ) THEN
*
* FACTORIZE A AS U*D*U' USING THE UPPER TRIANGLE OF A
*
* K IS THE MAIN LOOP INDEX, DECREASING FROM N TO 1 IN STEPS OF
* KB, WHERE KB IS THE NUMBER OF COLUMNS FACTORIZED BY DLASYF;
* KB IS EITHER NB OR NB-1, OR K FOR THE LAST BLOCK
*
K = N
10 CONTINUE
*
* IF K < 1, EXIT FROM LOOP
*
IF( K.LT.1 )
$ GO TO 40
*
IF( K.GT.NB ) THEN
*
* FACTORIZE COLUMNS K-KB+1:K OF A AND USE BLOCKED CODE TO
* UPDATE COLUMNS 1:K-KB
*
CALL DLASYF( UPLO, K, NB, KB, A, LDA, IPIV, WORK, LDWORK,
$ IINFO )
ELSE
*
* USE UNBLOCKED CODE TO FACTORIZE COLUMNS 1:K OF A
*
CALL DSYTF2( UPLO, K, A, LDA, IPIV, IINFO )
KB = K
END IF
*
* SET INFO ON THE FIRST OCCURRENCE OF A ZERO PIVOT
*
IF( INFO.EQ.0 .AND. IINFO.GT.0 )
$ INFO = IINFO
*
* DECREASE K AND RETURN TO THE START OF THE MAIN LOOP
*
K = K - KB
GO TO 10
*
ELSE
*
* FACTORIZE A AS L*D*L' USING THE LOWER TRIANGLE OF A
*
* K IS THE MAIN LOOP INDEX, INCREASING FROM 1 TO N IN STEPS OF
* KB, WHERE KB IS THE NUMBER OF COLUMNS FACTORIZED BY DLASYF;
* KB IS EITHER NB OR NB-1, OR N-K+1 FOR THE LAST BLOCK
*
K = 1
20 CONTINUE
*
* IF K > N, EXIT FROM LOOP
*
IF( K.GT.N )
$ GO TO 40
*
IF( K.LE.N-NB ) THEN
*
* FACTORIZE COLUMNS K:K+KB-1 OF A AND USE BLOCKED CODE TO
* UPDATE COLUMNS K+KB:N
*
CALL DLASYF( UPLO, N-K+1, NB, KB, A( K, K ), LDA, IPIV( K ),
$ WORK, LDWORK, IINFO )
ELSE
*
* USE UNBLOCKED CODE TO FACTORIZE COLUMNS K:N OF A
*
CALL DSYTF2( UPLO, N-K+1, A( K, K ), LDA, IPIV( K ), IINFO )
KB = N - K + 1
END IF
*
* SET INFO ON THE FIRST OCCURRENCE OF A ZERO PIVOT
*
IF( INFO.EQ.0 .AND. IINFO.GT.0 )
$ INFO = IINFO + K - 1
*
* ADJUST IPIV
*
DO 30 J = K, K + KB - 1
IF( IPIV( J ).GT.0 ) THEN
IPIV( J ) = IPIV( J ) + K - 1
ELSE
IPIV( J ) = IPIV( J ) - K + 1
END IF
30 CONTINUE
*
* INCREASE K AND RETURN TO THE START OF THE MAIN LOOP
*
K = K + KB
GO TO 20
*
END IF
*
40 CONTINUE
WORK( 1 ) = IWS
RETURN
*
* END OF DSYTRF
*
END
CUT HERE..........
CAT > DSYTF2.F <<'CUT HERE..........'
SUBROUTINE DSYTF2( UPLO, N, A, LDA, IPIV, INFO )
*
* -- LAPACK ROUTINE (VERSION 1.0B) --
* UNIV. OF TENNESSEE, UNIV. OF CALIFORNIA BERKELEY, NAG LTD.,
* COURANT INSTITUTE, ARGONNE NATIONAL LAB, AND RICE UNIVERSITY
* OCTOBER 31, 1992
*
* .. SCALAR ARGUMENTS ..
CHARACTER UPLO
INTEGER INFO, LDA, N
* ..
* .. ARRAY ARGUMENTS ..
INTEGER IPIV( * )
DOUBLE PRECISION A( LDA, * )
* ..
*
* PURPOSE
* =======
*
* DSYTF2 COMPUTES THE FACTORIZATION OF A REAL SYMMETRIC MATRIX A USING
* THE BUNCH-KAUFMAN DIAGONAL PIVOTING METHOD:
*
* A = U*D*U' OR A = L*D*L'
*
* WHERE U (OR L) IS A PRODUCT OF PERMUTATION AND UNIT UPPER (LOWER)
* TRIANGULAR MATRICES, U' IS THE TRANSPOSE OF U, AND D IS SYMMETRIC AND
* BLOCK DIAGONAL WITH 1-BY-1 AND 2-BY-2 DIAGONAL BLOCKS.
*
* THIS IS THE UNBLOCKED VERSION OF THE ALGORITHM, CALLING LEVEL 2 BLAS.
*
* ARGUMENTS
* =========
*
* UPLO (INPUT) CHARACTER*1
* SPECIFIES WHETHER THE UPPER OR LOWER TRIANGULAR PART OF THE
* SYMMETRIC MATRIX A IS STORED:
* = 'U': UPPER TRIANGULAR
* = 'L': LOWER TRIANGULAR
*
* N (INPUT) INTEGER
* THE ORDER OF THE MATRIX A. N >= 0.
*
* A (INPUT/OUTPUT) DOUBLE PRECISION 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, AND THE STRICTLY LOWER
* TRIANGULAR PART OF A IS NOT REFERENCED. IF UPLO = 'L', THE
* LEADING N-BY-N LOWER TRIANGULAR PART OF A CONTAINS THE LOWER
* TRIANGULAR PART OF THE MATRIX A, AND THE STRICTLY UPPER
* TRIANGULAR PART OF A IS NOT REFERENCED.
*
* ON EXIT, THE BLOCK DIAGONAL MATRIX D AND THE MULTIPLIERS USED
* TO OBTAIN THE FACTOR U OR L (SEE BELOW FOR FURTHER DETAILS).
*
* LDA (INPUT) INTEGER
* THE LEADING DIMENSION OF THE ARRAY A. LDA >= MAX(1,N).
*
* IPIV (OUTPUT) INTEGER ARRAY, DIMENSION (N)
* DETAILS OF THE INTERCHANGES AND THE BLOCK STRUCTURE OF D.
* IF IPIV(K) > 0, THEN ROWS AND COLUMNS K AND IPIV(K) WERE
* INTERCHANGED AND D(K,K) IS A 1-BY-1 DIAGONAL BLOCK.
* IF UPLO = 'U' AND IPIV(K) = IPIV(K-1) < 0, THEN ROWS AND
* COLUMNS K-1 AND -IPIV(K) WERE INTERCHANGED AND D(K-1:K,K-1:K)
* IS A 2-BY-2 DIAGONAL BLOCK. IF UPLO = 'L' AND IPIV(K) =
* IPIV(K+1) < 0, THEN ROWS AND COLUMNS K+1 AND -IPIV(K) WERE
* INTERCHANGED AND D(K:K+1,K:K+1) IS A 2-BY-2 DIAGONAL BLOCK.
*
* INFO (OUTPUT) INTEGER
* = 0: SUCCESSFUL EXIT
* < 0: IF INFO = -K, THE K-TH ARGUMENT HAD AN ILLEGAL VALUE
* > 0: IF INFO = K, D(K,K) IS EXACTLY ZERO. THE FACTORIZATION
* HAS BEEN COMPLETED, BUT THE BLOCK DIAGONAL MATRIX D IS
* EXACTLY SINGULAR, AND DIVISION BY ZERO WILL OCCUR IF IT
* IS USED TO SOLVE A SYSTEM OF EQUATIONS.
*
* FURTHER DETAILS
* ===============
*
* IF UPLO = 'U', THEN A = U*D*U', WHERE
* U = P(N)*U(N)* ... *P(K)U(K)* ...,
* I.E., U IS A PRODUCT OF TERMS P(K)*U(K), WHERE K DECREASES FROM N TO
* 1 IN STEPS OF 1 OR 2, AND D IS A BLOCK DIAGONAL MATRIX WITH 1-BY-1
* AND 2-BY-2 DIAGONAL BLOCKS D(K). P(K) IS A PERMUTATION MATRIX AS
* DEFINED BY IPIV(K), AND U(K) IS A UNIT UPPER TRIANGULAR MATRIX, SUCH
* THAT IF THE DIAGONAL BLOCK D(K) IS OF ORDER S (S = 1 OR 2), THEN
*
* ( I V 0 ) K-S
* U(K) = ( 0 I 0 ) S
* ( 0 0 I ) N-K
* K-S S N-K
*
* IF S = 1, D(K) OVERWRITES A(K,K), AND V OVERWRITES A(1:K-1,K).
* IF S = 2, THE UPPER TRIANGLE OF D(K) OVERWRITES A(K-1,K-1), A(K-1,K),
* AND A(K,K), AND V OVERWRITES A(1:K-2,K-1:K).
*
* IF UPLO = 'L', THEN A = L*D*L', WHERE
* L = P(1)*L(1)* ... *P(K)*L(K)* ...,
* I.E., L IS A PRODUCT OF TERMS P(K)*L(K), WHERE K INCREASES FROM 1 TO
* N IN STEPS OF 1 OR 2, AND D IS A BLOCK DIAGONAL MATRIX WITH 1-BY-1
* AND 2-BY-2 DIAGONAL BLOCKS D(K). P(K) IS A PERMUTATION MATRIX AS
* DEFINED BY IPIV(K), AND L(K) IS A UNIT LOWER TRIANGULAR MATRIX, SUCH
* THAT IF THE DIAGONAL BLOCK D(K) IS OF ORDER S (S = 1 OR 2), THEN
*
* ( I 0 0 ) K-1
* L(K) = ( 0 I 0 ) S
* ( 0 V I ) N-K-S+1
* K-1 S N-K-S+1
*
* IF S = 1, D(K) OVERWRITES A(K,K), AND V OVERWRITES A(K+1:N,K).
* IF S = 2, THE LOWER TRIANGLE OF D(K) OVERWRITES A(K,K), A(K+1,K),
* AND A(K+1,K+1), AND V OVERWRITES A(K+2:N,K:K+1).
*
* =====================================================================
*
* .. PARAMETERS ..
DOUBLE PRECISION ZERO, ONE
PARAMETER ( ZERO = 0.0D+0, ONE = 1.0D+0 )
DOUBLE PRECISION EIGHT, SEVTEN
PARAMETER ( EIGHT = 8.0D+0, SEVTEN = 17.0D+0 )
* ..
* .. LOCAL SCALARS ..
LOGICAL UPPER
INTEGER IMAX, JMAX, K, KK, KP, KSTEP
DOUBLE PRECISION ABSAKK, ALPHA, C, COLMAX, R1, R2, ROWMAX, S, T
* ..
* .. EXTERNAL FUNCTIONS ..
LOGICAL LSAME
INTEGER IDAMAX
EXTERNAL LSAME, IDAMAX
* ..
* .. EXTERNAL SUBROUTINES ..
EXTERNAL DLAEV2, DROT, DSCAL, DSWAP, DSYR, XERBLA
* ..
* .. INTRINSIC FUNCTIONS ..
INTRINSIC ABS, MAX, SQRT
* ..
* .. EXECUTABLE STATEMENTS ..
*
* TEST THE INPUT PARAMETERS.
*
INFO = 0
UPPER = LSAME( UPLO, 'U' )
IF( .NOT.UPPER .AND. .NOT.LSAME( UPLO, 'L' ) ) THEN
INFO = -1
ELSE IF( N.LT.0 ) THEN
INFO = -2
ELSE IF( LDA.LT.MAX( 1, N ) ) THEN
INFO = -4
END IF
IF( INFO.NE.0 ) THEN
CALL XERBLA( 'DSYTF2', -INFO )
RETURN
END IF
*
* INITIALIZE ALPHA FOR USE IN CHOOSING PIVOT BLOCK SIZE.
*
ALPHA = ( ONE+SQRT( SEVTEN ) ) / EIGHT
*
IF( UPPER ) THEN
*
* FACTORIZE A AS U*D*U' USING THE UPPER TRIANGLE OF A
*
* K IS THE MAIN LOOP INDEX, DECREASING FROM N TO 1 IN STEPS OF
* 1 OR 2
*
K = N
10 CONTINUE
*
* IF K < 1, EXIT FROM LOOP
*
IF( K.LT.1 )
$ GO TO 30
KSTEP = 1
*
* DETERMINE ROWS AND COLUMNS TO BE INTERCHANGED AND WHETHER
* A 1-BY-1 OR 2-BY-2 PIVOT BLOCK WILL BE USED
*
ABSAKK = ABS( A( K, K ) )
*
* IMAX IS THE ROW-INDEX OF THE LARGEST OFF-DIAGONAL ELEMENT IN
* COLUMN K, AND COLMAX IS ITS ABSOLUTE VALUE
*
IF( K.GT.1 ) THEN
IMAX = IDAMAX( K-1, A( 1, K ), 1 )
COLMAX = ABS( A( IMAX, K ) )
ELSE
COLMAX = ZERO
END IF
*
IF( MAX( ABSAKK, COLMAX ).EQ.ZERO ) THEN
*
* COLUMN K IS ZERO: SET INFO AND CONTINUE
*
IF( INFO.EQ.0 )
$ INFO = K
KP = K
ELSE
IF( ABSAKK.GE.ALPHA*COLMAX ) THEN
*
* NO INTERCHANGE, USE 1-BY-1 PIVOT BLOCK
*
KP = K
ELSE
*
* JMAX IS THE COLUMN-INDEX OF THE LARGEST OFF-DIAGONAL
* ELEMENT IN ROW IMAX, AND ROWMAX IS ITS ABSOLUTE VALUE
*
JMAX = IMAX + IDAMAX( K-IMAX, A( IMAX, IMAX+1 ), LDA )
ROWMAX = ABS( A( IMAX, JMAX ) )
IF( IMAX.GT.1 ) THEN
JMAX = IDAMAX( IMAX-1, A( 1, IMAX ), 1 )
ROWMAX = MAX( ROWMAX, ABS( A( JMAX, IMAX ) ) )
END IF
*
IF( ABSAKK.GE.ALPHA*COLMAX*( COLMAX / ROWMAX ) ) THEN
*
* NO INTERCHANGE, USE 1-BY-1 PIVOT BLOCK
*
KP = K
ELSE IF( ABS( A( IMAX, IMAX ) ).GE.ALPHA*ROWMAX ) THEN
*
* INTERCHANGE ROWS AND COLUMNS K AND IMAX, USE 1-BY-1
* PIVOT BLOCK
*
KP = IMAX
ELSE
*
* INTERCHANGE ROWS AND COLUMNS K-1 AND IMAX, USE 2-BY-2
* PIVOT BLOCK
*
KP = IMAX
KSTEP = 2
END IF
END IF
*
KK = K - KSTEP + 1
IF( KP.NE.KK ) THEN
*
* INTERCHANGE ROWS AND COLUMNS KK AND KP IN THE LEADING
* SUBMATRIX A(1:K,1:K)
*
CALL DSWAP( KP-1, A( 1, KK ), 1, A( 1, KP ), 1 )
CALL DSWAP( KK-KP-1, A( KP+1, KK ), 1, A( KP, KP+1 ),
$ LDA )
T = A( KK, KK )
A( KK, KK ) = A( KP, KP )
A( KP, KP ) = T
IF( KSTEP.EQ.2 ) THEN
T = A( K-1, K )
A( K-1, K ) = A( KP, K )
A( KP, K ) = T
END IF
END IF
*
* UPDATE THE LEADING SUBMATRIX
*
IF( KSTEP.EQ.1 ) THEN
*
* 1-BY-1 PIVOT BLOCK D(K): COLUMN K NOW HOLDS
*
* W(K) = U(K)*D(K)
*
* WHERE U(K) IS THE K-TH COLUMN OF U
*
* PERFORM A RANK-1 UPDATE OF A(1:K-1,1:K-1) AS
*
* A := A - U(K)*D(K)*U(K)' = A - W(K)*1/D(K)*W(K)'
*
R1 = ONE / A( K, K )
CALL DSYR( UPLO, K-1, -R1, A( 1, K ), 1, A, LDA )
*
* STORE U(K) IN COLUMN K
*
CALL DSCAL( K-1, R1, A( 1, K ), 1 )
ELSE
*
* 2-BY-2 PIVOT BLOCK D(K): COLUMNS K AND K-1 NOW HOLD
*
* ( W(K-1) W(K) ) = ( U(K-1) U(K) )*D(K)
*
* WHERE U(K) AND U(K-1) ARE THE K-TH AND (K-1)-TH COLUMNS
* OF U
*
* PERFORM A RANK-2 UPDATE OF A(1:K-2,1:K-2) AS
*
* A := A - ( U(K-1) U(K) )*D(K)*( U(K-1) U(K) )'
* = A - ( W(K-1) W(K) )*INV(D(K))*( W(K-1) W(K) )'
*
* CONVERT THIS TO TWO RANK-1 UPDATES BY USING THE EIGEN-
* DECOMPOSITION OF D(K)
*
CALL DLAEV2( A( K-1, K-1 ), A( K-1, K ), A( K, K ), R1,
$ R2, C, S )
R1 = ONE / R1
R2 = ONE / R2
CALL DROT( K-2, A( 1, K-1 ), 1, A( 1, K ), 1, C, S )
CALL DSYR( UPLO, K-2, -R1, A( 1, K-1 ), 1, A, LDA )
CALL DSYR( UPLO, K-2, -R2, A( 1, K ), 1, A, LDA )
*
* STORE U(K) AND U(K-1) IN COLUMNS K AND K-1
*
CALL DSCAL( K-2, R1, A( 1, K-1 ), 1 )
CALL DSCAL( K-2, R2, A( 1, K ), 1 )
CALL DROT( K-2, A( 1, K-1 ), 1, A( 1, K ), 1, C, -S )
END IF
END IF
*
* STORE DETAILS OF THE INTERCHANGES IN IPIV
*
IF( KSTEP.EQ.1 ) THEN
IPIV( K ) = KP
ELSE
IPIV( K ) = -KP
IPIV( K-1 ) = -KP
END IF
*
* DECREASE K AND RETURN TO THE START OF THE MAIN LOOP
*
K = K - KSTEP
GO TO 10
*
ELSE
*
* FACTORIZE A AS L*D*L' USING THE LOWER TRIANGLE OF A
*
* K IS THE MAIN LOOP INDEX, INCREASING FROM 1 TO N IN STEPS OF
* 1 OR 2
*
K = 1
20 CONTINUE
*
* IF K > N, EXIT FROM LOOP
*
IF( K.GT.N )
$ GO TO 30
KSTEP = 1
*
* DETERMINE ROWS AND COLUMNS TO BE INTERCHANGED AND WHETHER
* A 1-BY-1 OR 2-BY-2 PIVOT BLOCK WILL BE USED
*
ABSAKK = ABS( A( K, K ) )
*
* IMAX IS THE ROW-INDEX OF THE LARGEST OFF-DIAGONAL ELEMENT IN
* COLUMN K, AND COLMAX IS ITS ABSOLUTE VALUE
*
IF( K.LT.N ) THEN
IMAX = K + IDAMAX( N-K, A( K+1, K ), 1 )
COLMAX = ABS( A( IMAX, K ) )
ELSE
COLMAX = ZERO
END IF
*
IF( MAX( ABSAKK, COLMAX ).EQ.ZERO ) THEN
*
* COLUMN K IS ZERO: SET INFO AND CONTINUE
*
IF( INFO.EQ.0 )
$ INFO = K
KP = K
ELSE
IF( ABSAKK.GE.ALPHA*COLMAX ) THEN
*
* NO INTERCHANGE, USE 1-BY-1 PIVOT BLOCK
*
KP = K
ELSE
*
* JMAX IS THE COLUMN-INDEX OF THE LARGEST OFF-DIAGONAL
* ELEMENT IN ROW IMAX, AND ROWMAX IS ITS ABSOLUTE VALUE
*
JMAX = K - 1 + IDAMAX( IMAX-K, A( IMAX, K ), LDA )
ROWMAX = ABS( A( IMAX, JMAX ) )
IF( IMAX.LT.N ) THEN
JMAX = IMAX + IDAMAX( N-IMAX, A( IMAX+1, IMAX ), 1 )
ROWMAX = MAX( ROWMAX, ABS( A( JMAX, IMAX ) ) )
END IF
*
IF( ABSAKK.GE.ALPHA*COLMAX*( COLMAX / ROWMAX ) ) THEN
*
* NO INTERCHANGE, USE 1-BY-1 PIVOT BLOCK
*
KP = K
ELSE IF( ABS( A( IMAX, IMAX ) ).GE.ALPHA*ROWMAX ) THEN
*
* INTERCHANGE ROWS AND COLUMNS K AND IMAX, USE 1-BY-1
* PIVOT BLOCK
*
KP = IMAX
ELSE
*
* INTERCHANGE ROWS AND COLUMNS K+1 AND IMAX, USE 2-BY-2
* PIVOT BLOCK
*
KP = IMAX
KSTEP = 2
END IF
END IF
*
KK = K + KSTEP - 1
IF( KP.NE.KK ) THEN
*
* INTERCHANGE ROWS AND COLUMNS KK AND KP IN THE TRAILING
* SUBMATRIX A(K:N,K:N)
*
IF( KP.LT.N )
$ CALL DSWAP( N-KP, A( KP+1, KK ), 1, A( KP+1, KP ), 1 )
CALL DSWAP( KP-KK-1, A( KK+1, KK ), 1, A( KP, KK+1 ),
$ LDA )
T = A( KK, KK )
A( KK, KK ) = A( KP, KP )
A( KP, KP ) = T
IF( KSTEP.EQ.2 ) THEN
T = A( K+1, K )
A( K+1, K ) = A( KP, K )
A( KP, K ) = T
END IF
END IF
*
* UPDATE THE TRAILING SUBMATRIX
*
IF( KSTEP.EQ.1 ) THEN
*
* 1-BY-1 PIVOT BLOCK D(K): COLUMN K NOW HOLDS
*
* W(K) = L(K)*D(K)
*
* WHERE L(K) IS THE K-TH COLUMN OF L
*
IF( K.LT.N ) THEN
*
* PERFORM A RANK-1 UPDATE OF A(K+1:N,K+1:N) AS
*
* A := A - L(K)*D(K)*L(K)' = A - W(K)*(1/D(K))*W(K)'
*
R1 = ONE / A( K, K )
CALL DSYR( UPLO, N-K, -R1, A( K+1, K ), 1,
$ A( K+1, K+1 ), LDA )
*
* STORE L(K) IN COLUMN K
*
CALL DSCAL( N-K, R1, A( K+1, K ), 1 )
END IF
ELSE
*
* 2-BY-2 PIVOT BLOCK D(K): COLUMNS K AND K+1 NOW HOLD
*
* ( W(K) W(K+1) ) = ( L(K) L(K+1) )*D(K)
*
* WHERE L(K) AND L(K+1) ARE THE K-TH AND (K+1)-TH COLUMNS
* OF L
*
IF( K.LT.N-1 ) THEN
*
* PERFORM A RANK-2 UPDATE OF A(K+2:N,K+2:N) AS
*
* A := A - ( L(K) L(K+1) )*D(K)*( L(K) L(K+1) )'
* = A - ( W(K) W(K+1) )*INV(D(K))*( W(K) W(K+1) )'
*
* CONVERT THIS TO TWO RANK-1 UPDATES BY USING THE EIGEN-
* DECOMPOSITION OF D(K)
*
CALL DLAEV2( A( K, K ), A( K+1, K ), A( K+1, K+1 ),
$ R1, R2, C, S )
R1 = ONE / R1
R2 = ONE / R2
CALL DROT( N-K-1, A( K+2, K ), 1, A( K+2, K+1 ), 1, C,
$ S )
CALL DSYR( UPLO, N-K-1, -R1, A( K+2, K ), 1,
$ A( K+2, K+2 ), LDA )
CALL DSYR( UPLO, N-K-1, -R2, A( K+2, K+1 ), 1,
$ A( K+2, K+2 ), LDA )
*
* STORE L(K) AND L(K+1) IN COLUMNS K AND K+1
*
CALL DSCAL( N-K-1, R1, A( K+2, K ), 1 )
CALL DSCAL( N-K-1, R2, A( K+2, K+1 ), 1 )
CALL DROT( N-K-1, A( K+2, K ), 1, A( K+2, K+1 ), 1, C,
$ -S )
END IF
END IF
END IF
*
* STORE DETAILS OF THE INTERCHANGES IN IPIV
*
IF( KSTEP.EQ.1 ) THEN
IPIV( K ) = KP
ELSE
IPIV( K ) = -KP
IPIV( K+1 ) = -KP
END IF
*
* INCREASE K AND RETURN TO THE START OF THE MAIN LOOP
*
K = K + KSTEP
GO TO 20
*
END IF
*
30 CONTINUE
RETURN
*
* END OF DSYTF2
*
END
CUT HERE..........
CAT > DLASYF.F <<'CUT HERE..........'
SUBROUTINE DLASYF( UPLO, N, NB, KB, A, LDA, IPIV, W, LDW, INFO )
*
* -- LAPACK ROUTINE (VERSION 1.0B) --
* UNIV. OF TENNESSEE, UNIV. OF CALIFORNIA BERKELEY, NAG LTD.,
* COURANT INSTITUTE, ARGONNE NATIONAL LAB, AND RICE UNIVERSITY
* FEBRUARY 29, 1992
*
* .. SCALAR ARGUMENTS ..
CHARACTER UPLO
INTEGER INFO, KB, LDA, LDW, N, NB
* ..
* .. ARRAY ARGUMENTS ..
INTEGER IPIV( * )
DOUBLE PRECISION A( LDA, * ), W( LDW, * )
* ..
*
* PURPOSE
* =======
*
* DLASYF COMPUTES A PARTIAL FACTORIZATION OF A REAL SYMMETRIC MATRIX A
* USING THE BUNCH-KAUFMAN DIAGONAL PIVOTING METHOD. THE PARTIAL
* FACTORIZATION HAS THE FORM:
*
* A = ( I U12 ) ( A11 0 ) ( I 0 ) IF UPLO = 'U', OR:
* ( 0 U22 ) ( 0 D ) ( U12' U22' )
*
* A = ( L11 0 ) ( D 0 ) ( L11' L21' ) IF UPLO = 'L'
* ( L21 I ) ( 0 A22 ) ( 0 I )
*
* WHERE THE ORDER OF D IS AT MOST NB. THE ACTUAL ORDER IS RETURNED IN
* THE ARGUMENT KB, AND IS EITHER NB OR NB-1, OR N IF N <= NB.
*
* DLASYF IS AN AUXILIARY ROUTINE CALLED BY DSYTRF. IT USES BLOCKED CODE
* (CALLING LEVEL 3 BLAS) TO UPDATE THE SUBMATRIX A11 (IF UPLO = 'U') OR
* A22 (IF UPLO = 'L').
*
* ARGUMENTS
* =========
*
* UPLO (INPUT) CHARACTER*1
* SPECIFIES WHETHER THE UPPER OR LOWER TRIANGULAR PART OF THE
* SYMMETRIC MATRIX A IS STORED:
* = 'U': UPPER TRIANGULAR
* = 'L': LOWER TRIANGULAR
*
* N (INPUT) INTEGER
* THE ORDER OF THE MATRIX A. N >= 0.
*
* NB (INPUT) INTEGER
* THE MAXIMUM NUMBER OF COLUMNS OF THE MATRIX A THAT SHOULD BE
* FACTORED. NB SHOULD BE AT LEAST 2 TO ALLOW FOR 2-BY-2 PIVOT
* BLOCKS.
*
* KB (OUTPUT) INTEGER
* THE NUMBER OF COLUMNS OF A THAT WERE ACTUALLY FACTORED.
* KB IS EITHER NB-1 OR NB, OR N IF N <= NB.
*
* A (INPUT/OUTPUT) DOUBLE PRECISION 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, AND THE STRICTLY LOWER
* TRIANGULAR PART OF A IS NOT REFERENCED. IF UPLO = 'L', THE
* LEADING N-BY-N LOWER TRIANGULAR PART OF A CONTAINS THE LOWER
* TRIANGULAR PART OF THE MATRIX A, AND THE STRICTLY UPPER
* TRIANGULAR PART OF A IS NOT REFERENCED.
* ON EXIT, A CONTAINS DETAILS OF THE PARTIAL FACTORIZATION.
*
* LDA (INPUT) INTEGER
* THE LEADING DIMENSION OF THE ARRAY A. LDA >= MAX(1,N).
*
* IPIV (OUTPUT) INTEGER ARRAY, DIMENSION (N)
* DETAILS OF THE INTERCHANGES AND THE BLOCK STRUCTURE OF D.
* IF UPLO = 'U', ONLY THE LAST KB ELEMENTS OF IPIV ARE SET;
* IF UPLO = 'L', ONLY THE FIRST KB ELEMENTS ARE SET.
*
* IF IPIV(K) > 0, THEN ROWS AND COLUMNS K AND IPIV(K) WERE
* INTERCHANGED AND D(K,K) IS A 1-BY-1 DIAGONAL BLOCK.
* IF UPLO = 'U' AND IPIV(K) = IPIV(K-1) < 0, THEN ROWS AND
* COLUMNS K-1 AND -IPIV(K) WERE INTERCHANGED AND D(K-1:K,K-1:K)
* IS A 2-BY-2 DIAGONAL BLOCK. IF UPLO = 'L' AND IPIV(K) =
* IPIV(K+1) < 0, THEN ROWS AND COLUMNS K+1 AND -IPIV(K) WERE
* INTERCHANGED AND D(K:K+1,K:K+1) IS A 2-BY-2 DIAGONAL BLOCK.
*
* W (WORKSPACE) DOUBLE PRECISION ARRAY, DIMENSION (LDW,NB)
*
* LDW (INPUT) INTEGER
* THE LEADING DIMENSION OF THE ARRAY W. LDW >= MAX(1,N).
*
* INFO (OUTPUT) INTEGER
* = 0: SUCCESSFUL EXIT
* > 0: IF INFO = K, D(K,K) IS EXACTLY ZERO. THE FACTORIZATION
* HAS BEEN COMPLETED, BUT THE BLOCK DIAGONAL MATRIX D IS
* EXACTLY SINGULAR.
*
* =====================================================================
*
* .. PARAMETERS ..
DOUBLE PRECISION ZERO, ONE
PARAMETER ( ZERO = 0.0D+0, ONE = 1.0D+0 )
DOUBLE PRECISION EIGHT, SEVTEN
PARAMETER ( EIGHT = 8.0D+0, SEVTEN = 17.0D+0 )
* ..
* .. LOCAL SCALARS ..
INTEGER IMAX, J, JB, JJ, JMAX, JP, K, KK, KKW, KP,
$ KSTEP, KW
DOUBLE PRECISION ABSAKK, ALPHA, COLMAX, D11, D21, D22, R1,
$ ROWMAX, T
* ..
* .. EXTERNAL FUNCTIONS ..
LOGICAL LSAME
INTEGER IDAMAX
EXTERNAL LSAME, IDAMAX
* ..
* .. EXTERNAL SUBROUTINES ..
EXTERNAL DCOPY, DGEMM, DGEMV, DSCAL, DSWAP
* ..
* .. INTRINSIC FUNCTIONS ..
INTRINSIC ABS, MAX, MIN, SQRT
* ..
* .. EXECUTABLE STATEMENTS ..
*
INFO = 0
*
* INITIALIZE ALPHA FOR USE IN CHOOSING PIVOT BLOCK SIZE.
*
ALPHA = ( ONE+SQRT( SEVTEN ) ) / EIGHT
*
IF( LSAME( UPLO, 'U' ) ) THEN
*
* FACTORIZE THE TRAILING COLUMNS OF A USING THE UPPER TRIANGLE
* OF A AND WORKING BACKWARDS, AND COMPUTE THE MATRIX W = U12*D
* FOR USE IN UPDATING A11
*
* K IS THE MAIN LOOP INDEX, DECREASING FROM N IN STEPS OF 1 OR 2
*
* KW IS THE COLUMN OF W WHICH CORRESPONDS TO COLUMN K OF A
*
K = N
10 CONTINUE
KW = NB + K - N
*
* EXIT FROM LOOP
*
IF( ( K.LE.N-NB+1 .AND. NB.LT.N ) .OR. K.LT.1 )
$ GO TO 30
*
* COPY COLUMN K OF A TO COLUMN KW OF W AND UPDATE IT
*
CALL DCOPY( K, A( 1, K ), 1, W( 1, KW ), 1 )
IF( K.LT.N )
$ CALL DGEMV( 'NO TRANSPOSE', K, N-K, -ONE, A( 1, K+1 ), LDA,
$ W( K, KW+1 ), LDW, ONE, W( 1, KW ), 1 )
*
KSTEP = 1
*
* DETERMINE ROWS AND COLUMNS TO BE INTERCHANGED AND WHETHER
* A 1-BY-1 OR 2-BY-2 PIVOT BLOCK WILL BE USED
*
ABSAKK = ABS( W( K, KW ) )
*
* IMAX IS THE ROW-INDEX OF THE LARGEST OFF-DIAGONAL ELEMENT IN
* COLUMN K, AND COLMAX IS ITS ABSOLUTE VALUE
*
IF( K.GT.1 ) THEN
IMAX = IDAMAX( K-1, W( 1, KW ), 1 )
COLMAX = ABS( W( IMAX, KW ) )
ELSE
COLMAX = ZERO
END IF
*
IF( MAX( ABSAKK, COLMAX ).EQ.ZERO ) THEN
*
* COLUMN K IS ZERO: SET INFO AND CONTINUE
*
IF( INFO.EQ.0 )
$ INFO = K
KP = K
ELSE
IF( ABSAKK.GE.ALPHA*COLMAX ) THEN
*
* NO INTERCHANGE, USE 1-BY-1 PIVOT BLOCK
*
KP = K
ELSE
*
* COPY COLUMN IMAX TO COLUMN KW-1 OF W AND UPDATE IT
*
CALL DCOPY( IMAX, A( 1, IMAX ), 1, W( 1, KW-1 ), 1 )
CALL DCOPY( K-IMAX, A( IMAX, IMAX+1 ), LDA,
$ W( IMAX+1, KW-1 ), 1 )
IF( K.LT.N )
$ CALL DGEMV( 'NO TRANSPOSE', K, N-K, -ONE, A( 1, K+1 ),
$ LDA, W( IMAX, KW+1 ), LDW, ONE,
$ W( 1, KW-1 ), 1 )
*
* JMAX IS THE COLUMN-INDEX OF THE LARGEST OFF-DIAGONAL
* ELEMENT IN ROW IMAX, AND ROWMAX IS ITS ABSOLUTE VALUE
*
JMAX = IMAX + IDAMAX( K-IMAX, W( IMAX+1, KW-1 ), 1 )
ROWMAX = ABS( W( JMAX, KW-1 ) )
IF( IMAX.GT.1 ) THEN
JMAX = IDAMAX( IMAX-1, W( 1, KW-1 ), 1 )
ROWMAX = MAX( ROWMAX, ABS( W( JMAX, KW-1 ) ) )
END IF
*
IF( ABSAKK.GE.ALPHA*COLMAX*( COLMAX / ROWMAX ) ) THEN
*
* NO INTERCHANGE, USE 1-BY-1 PIVOT BLOCK
*
KP = K
ELSE IF( ABS( W( IMAX, KW-1 ) ).GE.ALPHA*ROWMAX ) THEN
*
* INTERCHANGE ROWS AND COLUMNS K AND IMAX, USE 1-BY-1
* PIVOT BLOCK
*
KP = IMAX
*
* COPY COLUMN KW-1 OF W TO COLUMN KW
*
CALL DCOPY( K, W( 1, KW-1 ), 1, W( 1, KW ), 1 )
ELSE
*
* INTERCHANGE ROWS AND COLUMNS K-1 AND IMAX, USE 2-BY-2
* PIVOT BLOCK
*
KP = IMAX
KSTEP = 2
END IF
END IF
*
KK = K - KSTEP + 1
KKW = NB + KK - N
*
* UPDATED COLUMN KP IS ALREADY STORED IN COLUMN KKW OF W
*
IF( KP.NE.KK ) THEN
*
* COPY NON-UPDATED COLUMN KK TO COLUMN KP
*
A( KP, K ) = A( KK, K )
CALL DCOPY( K-1-KP, A( KP+1, KK ), 1, A( KP, KP+1 ),
$ LDA )
CALL DCOPY( KP, A( 1, KK ), 1, A( 1, KP ), 1 )
*
* INTERCHANGE ROWS KK AND KP IN LAST KK COLUMNS OF A AND W
*
CALL DSWAP( N-KK+1, A( KK, KK ), LDA, A( KP, KK ), LDA )
CALL DSWAP( N-KK+1, W( KK, KKW ), LDW, W( KP, KKW ),
$ LDW )
END IF
*
IF( KSTEP.EQ.1 ) THEN
*
* 1-BY-1 PIVOT BLOCK D(K): COLUMN KW OF W NOW HOLDS
*
* W(K) = U(K)*D(K)
*
* WHERE U(K) IS THE K-TH COLUMN OF U
*
* STORE U(K) IN COLUMN K OF A
*
CALL DCOPY( K, W( 1, KW ), 1, A( 1, K ), 1 )
R1 = ONE / A( K, K )
CALL DSCAL( K-1, R1, A( 1, K ), 1 )
ELSE
*
* 2-BY-2 PIVOT BLOCK D(K): COLUMNS KW AND KW-1 OF W NOW
* HOLD
*
* ( W(K-1) W(K) ) = ( U(K-1) U(K) )*D(K)
*
* WHERE U(K) AND U(K-1) ARE THE K-TH AND (K-1)-TH COLUMNS
* OF U
*
IF( K.GT.2 ) THEN
*
* STORE U(K) AND U(K-1) IN COLUMNS K AND K-1 OF A
*
D21 = W( K-1, KW )
D11 = W( K, KW ) / D21
D22 = W( K-1, KW-1 ) / D21
T = ONE / ( D11*D22-ONE )
D21 = T / D21
DO 20 J = 1, K - 2
A( J, K-1 ) = D21*( D11*W( J, KW-1 )-W( J, KW ) )
A( J, K ) = D21*( D22*W( J, KW )-W( J, KW-1 ) )
20 CONTINUE
END IF
*
* COPY D(K) TO A
*
A( K-1, K-1 ) = W( K-1, KW-1 )
A( K-1, K ) = W( K-1, KW )
A( K, K ) = W( K, KW )
END IF
END IF
*
* STORE DETAILS OF THE INTERCHANGES IN IPIV
*
IF( KSTEP.EQ.1 ) THEN
IPIV( K ) = KP
ELSE
IPIV( K ) = -KP
IPIV( K-1 ) = -KP
END IF
*
* DECREASE K AND RETURN TO THE START OF THE MAIN LOOP
*
K = K - KSTEP
GO TO 10
*
30 CONTINUE
*
* UPDATE THE UPPER TRIANGLE OF A11 (= A(1:K,1:K)) AS
*
* A11 := A11 - U12*D*U12' = A11 - U12*W'
*
* COMPUTING BLOCKS OF NB COLUMNS AT A TIME
*
DO 50 J = ( ( K-1 ) / NB )*NB + 1, 1, -NB
JB = MIN( NB, K-J+1 )
*
* UPDATE THE UPPER TRIANGLE OF THE DIAGONAL BLOCK
*
DO 40 JJ = J, J + JB - 1
CALL DGEMV( 'NO TRANSPOSE', JJ-J+1, N-K, -ONE,
$ A( J, K+1 ), LDA, W( JJ, KW+1 ), LDW, ONE,
$ A( J, JJ ), 1 )
40 CONTINUE
*
* UPDATE THE RECTANGULAR SUPERDIAGONAL BLOCK
*
CALL DGEMM( 'NO TRANSPOSE', 'TRANSPOSE', J-1, JB, N-K, -ONE,
$ A( 1, K+1 ), LDA, W( J, KW+1 ), LDW, ONE,
$ A( 1, J ), LDA )
50 CONTINUE
*
* PUT U12 IN STANDARD FORM BY PARTIALLY UNDOING THE INTERCHANGES
* IN COLUMNS K+1:N
*
J = K + 1
60 CONTINUE
JJ = J
JP = IPIV( J )
IF( JP.LT.0 ) THEN
JP = -JP
J = J + 1
END IF
J = J + 1
IF( JP.NE.JJ .AND. J.LE.N )
$ CALL DSWAP( N-J+1, A( JP, J ), LDA, A( JJ, J ), LDA )
IF( J.LE.N )
$ GO TO 60
*
* SET KB TO THE NUMBER OF COLUMNS FACTORIZED
*
KB = N - K
*
ELSE
*
* FACTORIZE THE LEADING COLUMNS OF A USING THE LOWER TRIANGLE
* OF A AND WORKING FORWARDS, AND COMPUTE THE MATRIX W = L21*D
* FOR USE IN UPDATING A22
*
* K IS THE MAIN LOOP INDEX, INCREASING FROM 1 IN STEPS OF 1 OR 2
*
K = 1
70 CONTINUE
*
* EXIT FROM LOOP
*
IF( ( K.GE.NB .AND. NB.LT.N ) .OR. K.GT.N )
$ GO TO 90
*
* COPY COLUMN K OF A TO COLUMN K OF W AND UPDATE IT
*
CALL DCOPY( N-K+1, A( K, K ), 1, W( K, K ), 1 )
CALL DGEMV( 'NO TRANSPOSE', N-K+1, K-1, -ONE, A( K, 1 ), LDA,
$ W( K, 1 ), LDW, ONE, W( K, K ), 1 )
*
KSTEP = 1
*
* DETERMINE ROWS AND COLUMNS TO BE INTERCHANGED AND WHETHER
* A 1-BY-1 OR 2-BY-2 PIVOT BLOCK WILL BE USED
*
ABSAKK = ABS( W( K, K ) )
*
* IMAX IS THE ROW-INDEX OF THE LARGEST OFF-DIAGONAL ELEMENT IN
* COLUMN K, AND COLMAX IS ITS ABSOLUTE VALUE
*
IF( K.LT.N ) THEN
IMAX = K + IDAMAX( N-K, W( K+1, K ), 1 )
COLMAX = ABS( W( IMAX, K ) )
ELSE
COLMAX = ZERO
END IF
*
IF( MAX( ABSAKK, COLMAX ).EQ.ZERO ) THEN
*
* COLUMN K IS ZERO: SET INFO AND CONTINUE
*
IF( INFO.EQ.0 )
$ INFO = K
KP = K
ELSE
IF( ABSAKK.GE.ALPHA*COLMAX ) THEN
*
* NO INTERCHANGE, USE 1-BY-1 PIVOT BLOCK
*
KP = K
ELSE
*
* COPY COLUMN IMAX TO COLUMN K+1 OF W AND UPDATE IT
*
CALL DCOPY( IMAX-K, A( IMAX, K ), LDA, W( K, K+1 ), 1 )
CALL DCOPY( N-IMAX+1, A( IMAX, IMAX ), 1, W( IMAX, K+1 ),
$ 1 )
CALL DGEMV( 'NO TRANSPOSE', N-K+1, K-1, -ONE, A( K, 1 ),
$ LDA, W( IMAX, 1 ), LDW, ONE, W( K, K+1 ), 1 )
*
* JMAX IS THE COLUMN-INDEX OF THE LARGEST OFF-DIAGONAL
* ELEMENT IN ROW IMAX, AND ROWMAX IS ITS ABSOLUTE VALUE
*
JMAX = K - 1 + IDAMAX( IMAX-K, W( K, K+1 ), 1 )
ROWMAX = ABS( W( JMAX, K+1 ) )
IF( IMAX.LT.N ) THEN
JMAX = IMAX + IDAMAX( N-IMAX, W( IMAX+1, K+1 ), 1 )
ROWMAX = MAX( ROWMAX, ABS( W( JMAX, K+1 ) ) )
END IF
*
IF( ABSAKK.GE.ALPHA*COLMAX*( COLMAX / ROWMAX ) ) THEN
*
* NO INTERCHANGE, USE 1-BY-1 PIVOT BLOCK
*
KP = K
ELSE IF( ABS( W( IMAX, K+1 ) ).GE.ALPHA*ROWMAX ) THEN
*
* INTERCHANGE ROWS AND COLUMNS K AND IMAX, USE 1-BY-1
* PIVOT BLOCK
*
KP = IMAX
*
* COPY COLUMN K+1 OF W TO COLUMN K
*
CALL DCOPY( N-K+1, W( K, K+1 ), 1, W( K, K ), 1 )
ELSE
*
* INTERCHANGE ROWS AND COLUMNS K+1 AND IMAX, USE 2-BY-2
* PIVOT BLOCK
*
KP = IMAX
KSTEP = 2
END IF
END IF
*
KK = K + KSTEP - 1
*
* UPDATED COLUMN KP IS ALREADY STORED IN COLUMN KK OF W
*
IF( KP.NE.KK ) THEN
*
* COPY NON-UPDATED COLUMN KK TO COLUMN KP
*
A( KP, K ) = A( KK, K )
CALL DCOPY( KP-K-1, A( K+1, KK ), 1, A( KP, K+1 ), LDA )
CALL DCOPY( N-KP+1, A( KP, KK ), 1, A( KP, KP ), 1 )
*
* INTERCHANGE ROWS KK AND KP IN FIRST KK COLUMNS OF A AND W
*
CALL DSWAP( KK, A( KK, 1 ), LDA, A( KP, 1 ), LDA )
CALL DSWAP( KK, W( KK, 1 ), LDW, W( KP, 1 ), LDW )
END IF
*
IF( KSTEP.EQ.1 ) THEN
*
* 1-BY-1 PIVOT BLOCK D(K): COLUMN K OF W NOW HOLDS
*
* W(K) = L(K)*D(K)
*
* WHERE L(K) IS THE K-TH COLUMN OF L
*
* STORE L(K) IN COLUMN K OF A
*
CALL DCOPY( N-K+1, W( K, K ), 1, A( K, K ), 1 )
IF( K.LT.N ) THEN
R1 = ONE / A( K, K )
CALL DSCAL( N-K, R1, A( K+1, K ), 1 )
END IF
ELSE
*
* 2-BY-2 PIVOT BLOCK D(K): COLUMNS K AND K+1 OF W NOW HOLD
*
* ( W(K) W(K+1) ) = ( L(K) L(K+1) )*D(K)
*
* WHERE L(K) AND L(K+1) ARE THE K-TH AND (K+1)-TH COLUMNS
* OF L
*
IF( K.LT.N-1 ) THEN
*
* STORE L(K) AND L(K+1) IN COLUMNS K AND K+1 OF A
*
D21 = W( K+1, K )
D11 = W( K+1, K+1 ) / D21
D22 = W( K, K ) / D21
T = ONE / ( D11*D22-ONE )
D21 = T / D21
DO 80 J = K + 2, N
A( J, K ) = D21*( D11*W( J, K )-W( J, K+1 ) )
A( J, K+1 ) = D21*( D22*W( J, K+1 )-W( J, K ) )
80 CONTINUE
END IF
*
* COPY D(K) TO A
*
A( K, K ) = W( K, K )
A( K+1, K ) = W( K+1, K )
A( K+1, K+1 ) = W( K+1, K+1 )
END IF
END IF
*
* STORE DETAILS OF THE INTERCHANGES IN IPIV
*
IF( KSTEP.EQ.1 ) THEN
IPIV( K ) = KP
ELSE
IPIV( K ) = -KP
IPIV( K+1 ) = -KP
END IF
*
* INCREASE K AND RETURN TO THE START OF THE MAIN LOOP
*
K = K + KSTEP
GO TO 70
*
90 CONTINUE
*
* UPDATE THE LOWER TRIANGLE OF A22 (= A(K:N,K:N)) AS
*
* A22 := A22 - L21*D*L21' = A22 - L21*W'
*
* COMPUTING BLOCKS OF NB COLUMNS AT A TIME
*
DO 110 J = K, N, NB
JB = MIN( NB, N-J+1 )
*
* UPDATE THE LOWER TRIANGLE OF THE DIAGONAL BLOCK
*
DO 100 JJ = J, J + JB - 1
CALL DGEMV( 'NO TRANSPOSE', J+JB-JJ, K-1, -ONE,
$ A( JJ, 1 ), LDA, W( JJ, 1 ), LDW, ONE,
$ A( JJ, JJ ), 1 )
100 CONTINUE
*
* UPDATE THE RECTANGULAR SUBDIAGONAL BLOCK
*
IF( J+JB.LE.N )
$ CALL DGEMM( 'NO TRANSPOSE', 'TRANSPOSE', N-J-JB+1, JB,
$ K-1, -ONE, A( J+JB, 1 ), LDA, W( J, 1 ), LDW,
$ ONE, A( J+JB, J ), LDA )
110 CONTINUE
*
* PUT L21 IN STANDARD FORM BY PARTIALLY UNDOING THE INTERCHANGES
* IN COLUMNS 1:K-1
*
J = K - 1
120 CONTINUE
JJ = J
JP = IPIV( J )
IF( JP.LT.0 ) THEN
JP = -JP
J = J - 1
END IF
J = J - 1
IF( JP.NE.JJ .AND. J.GE.1 )
$ CALL DSWAP( J, A( JP, 1 ), LDA, A( JJ, 1 ), LDA )
IF( J.GE.1 )
$ GO TO 120
*
* SET KB TO THE NUMBER OF COLUMNS FACTORIZED
*
KB = K - 1
*
END IF
RETURN
*
* END OF DLASYF
*
END
CUT HERE..........
C --------------------- BELOW IS DSYTRI ------------------
SUBROUTINE DSYTRI( UPLO, N, A, LDA, IPIV, WORK, INFO )
*
* -- LAPACK ROUTINE (VERSION 1.0B) --
* UNIV. OF TENNESSEE, UNIV. OF CALIFORNIA BERKELEY, NAG LTD.,
* COURANT INSTITUTE, ARGONNE NATIONAL LAB, AND RICE UNIVERSITY
* OCTOBER 31, 1992
*
* .. SCALAR ARGUMENTS ..
CHARACTER UPLO
INTEGER INFO, LDA, N
* ..
* .. ARRAY ARGUMENTS ..
INTEGER IPIV( * )
DOUBLE PRECISION A( LDA, * ), WORK( * )
* ..
*
* PURPOSE
* =======
*
* DSYTRI COMPUTES THE INVERSE OF A REAL SYMMETRIC INDEFINITE MATRIX
* A USING THE FACTORIZATION A = U*D*U' OR A = L*D*L' COMPUTED BY
* DSYTRF.
*
* ARGUMENTS
* =========
*
* UPLO (INPUT) CHARACTER*1
* SPECIFIES WHETHER THE DETAILS OF THE FACTORIZATION ARE STORED
* AS AN UPPER OR LOWER TRIANGULAR MATRIX.
* = 'U': UPPER TRIANGULAR (FORM IS A = U*D*U')
* = 'L': LOWER TRIANGULAR (FORM IS A = L*D*L')
*
* N (INPUT) INTEGER
* THE ORDER OF THE MATRIX A. N >= 0.
*
* A (INPUT/OUTPUT) DOUBLE PRECISION ARRAY, DIMENSION (LDA,N)
* ON ENTRY, THE BLOCK DIAGONAL MATRIX D AND THE MULTIPLIERS
* USED TO OBTAIN THE FACTOR U OR L AS COMPUTED BY DSYTRF.
*
* ON EXIT, IF INFO = 0, THE (SYMMETRIC) INVERSE OF THE ORIGINAL
* MATRIX. IF UPLO = 'U', THE UPPER TRIANGULAR PART OF THE
* INVERSE IS FORMED AND THE PART OF A BELOW THE DIAGONAL IS NOT
* REFERENCED; IF UPLO = 'L' THE LOWER TRIANGULAR PART OF THE
* INVERSE IS FORMED AND THE PART OF A ABOVE THE DIAGONAL IS
* NOT REFERENCED.
*
* LDA (INPUT) INTEGER
* THE LEADING DIMENSION OF THE ARRAY A. LDA >= MAX(1,N).
*
* IPIV (INPUT) INTEGER ARRAY, DIMENSION (N)
* DETAILS OF THE INTERCHANGES AND THE BLOCK STRUCTURE OF D
* AS DETERMINED BY DSYTRF.
*
* WORK (WORKSPACE) DOUBLE PRECISION ARRAY, DIMENSION (N)
*
* INFO (OUTPUT) INTEGER
* = 0: SUCCESSFUL EXIT
* < 0: IF INFO = -K, THE K-TH ARGUMENT HAD AN ILLEGAL VALUE
* > 0: IF INFO = K, D(K,K) = 0; THE MATRIX IS SINGULAR AND ITS
* INVERSE COULD NOT BE COMPUTED.
*
* =====================================================================
*
* .. PARAMETERS ..
DOUBLE PRECISION ONE, ZERO
PARAMETER ( ONE = 1.0D+0, ZERO = 0.0D+0 )
* ..
* .. LOCAL SCALARS ..
LOGICAL UPPER
INTEGER K, KP, KSTEP
DOUBLE PRECISION AK, AKKP1, AKP1, D, T, TEMP
* ..
* .. EXTERNAL FUNCTIONS ..
LOGICAL LSAME
DOUBLE PRECISION DDOT
EXTERNAL LSAME, DDOT
* ..
* .. EXTERNAL SUBROUTINES ..
EXTERNAL DCOPY, DSWAP, DSYMV, XERBLA
* ..
* .. INTRINSIC FUNCTIONS ..
INTRINSIC ABS, MAX
* ..
* .. EXECUTABLE STATEMENTS ..
*
* TEST THE INPUT PARAMETERS.
*
INFO = 0
UPPER = LSAME( UPLO, 'U' )
IF( .NOT.UPPER .AND. .NOT.LSAME( UPLO, 'L' ) ) THEN
INFO = -1
ELSE IF( N.LT.0 ) THEN
INFO = -2
ELSE IF( LDA.LT.MAX( 1, N ) ) THEN
INFO = -4
END IF
IF( INFO.NE.0 ) THEN
CALL XERBLA( 'DSYTRI', -INFO )
RETURN
END IF
*
* QUICK RETURN IF POSSIBLE
*
IF( N.EQ.0 )
$ RETURN
*
* CHECK THAT THE DIAGONAL MATRIX D IS NONSINGULAR.
*
IF( UPPER ) THEN
*
* UPPER TRIANGULAR STORAGE: EXAMINE D FROM BOTTOM TO TOP
*
DO 10 INFO = N, 1, -1
IF( IPIV( INFO ).GT.0 .AND. A( INFO, INFO ).EQ.ZERO )
$ RETURN
10 CONTINUE
ELSE
*
* LOWER TRIANGULAR STORAGE: EXAMINE D FROM TOP TO BOTTOM.
*
DO 20 INFO = 1, N
IF( IPIV( INFO ).GT.0 .AND. A( INFO, INFO ).EQ.ZERO )
$ RETURN
20 CONTINUE
END IF
INFO = 0
*
IF( UPPER ) THEN
*
* COMPUTE INV(A) FROM THE FACTORIZATION A = U*D*U'.
*
* K IS THE MAIN LOOP INDEX, INCREASING FROM 1 TO N IN STEPS OF
* 1 OR 2, DEPENDING ON THE SIZE OF THE DIAGONAL BLOCKS.
*
K = 1
30 CONTINUE
*
* IF K > N, EXIT FROM LOOP.
*
IF( K.GT.N )
$ GO TO 40
*
IF( IPIV( K ).GT.0 ) THEN
*
* 1 X 1 DIAGONAL BLOCK
*
* INVERT THE DIAGONAL BLOCK.
*
A( K, K ) = ONE / A( K, K )
*
* COMPUTE COLUMN K OF THE INVERSE.
*
IF( K.GT.1 ) THEN
CALL DCOPY( K-1, A( 1, K ), 1, WORK, 1 )
CALL DSYMV( UPLO, K-1, -ONE, A, LDA, WORK, 1, ZERO,
$ A( 1, K ), 1 )
A( K, K ) = A( K, K ) - DDOT( K-1, WORK, 1, A( 1, K ),
$ 1 )
END IF
KSTEP = 1
ELSE
*
* 2 X 2 DIAGONAL BLOCK
*
* INVERT THE DIAGONAL BLOCK.
*
T = ABS( A( K, K+1 ) )
AK = A( K, K ) / T
AKP1 = A( K+1, K+1 ) / T
AKKP1 = A( K, K+1 ) / T
D = T*( AK*AKP1-ONE )
A( K, K ) = AKP1 / D
A( K+1, K+1 ) = AK / D
A( K, K+1 ) = -AKKP1 / D
*
* COMPUTE COLUMNS K AND K+1 OF THE INVERSE.
*
IF( K.GT.1 ) THEN
CALL DCOPY( K-1, A( 1, K ), 1, WORK, 1 )
CALL DSYMV( UPLO, K-1, -ONE, A, LDA, WORK, 1, ZERO,
$ A( 1, K ), 1 )
A( K, K ) = A( K, K ) - DDOT( K-1, WORK, 1, A( 1, K ),
$ 1 )
A( K, K+1 ) = A( K, K+1 ) -
$ DDOT( K-1, A( 1, K ), 1, A( 1, K+1 ), 1 )
CALL DCOPY( K-1, A( 1, K+1 ), 1, WORK, 1 )
CALL DSYMV( UPLO, K-1, -ONE, A, LDA, WORK, 1, ZERO,
$ A( 1, K+1 ), 1 )
A( K+1, K+1 ) = A( K+1, K+1 ) -
$ DDOT( K-1, WORK, 1, A( 1, K+1 ), 1 )
END IF
KSTEP = 2
END IF
*
KP = ABS( IPIV( K ) )
IF( KP.NE.K ) THEN
*
* INTERCHANGE ROWS AND COLUMNS K AND KP IN THE LEADING
* SUBMATRIX A(1:K+1,1:K+1)
*
CALL DSWAP( KP-1, A( 1, K ), 1, A( 1, KP ), 1 )
CALL DSWAP( K-KP-1, A( KP+1, K ), 1, A( KP, KP+1 ), LDA )
TEMP = A( K, K )
A( K, K ) = A( KP, KP )
A( KP, KP ) = TEMP
IF( KSTEP.EQ.2 ) THEN
TEMP = A( K, K+1 )
A( K, K+1 ) = A( KP, K+1 )
A( KP, K+1 ) = TEMP
END IF
END IF
*
K = K + KSTEP
GO TO 30
40 CONTINUE
*
ELSE
*
* COMPUTE INV(A) FROM THE FACTORIZATION A = L*D*L'.
*
* K IS THE MAIN LOOP INDEX, INCREASING FROM 1 TO N IN STEPS OF
* 1 OR 2, DEPENDING ON THE SIZE OF THE DIAGONAL BLOCKS.
*
K = N
50 CONTINUE
*
* IF K < 1, EXIT FROM LOOP.
*
IF( K.LT.1 )
$ GO TO 60
*
IF( IPIV( K ).GT.0 ) THEN
*
* 1 X 1 DIAGONAL BLOCK
*
* INVERT THE DIAGONAL BLOCK.
*
A( K, K ) = ONE / A( K, K )
*
* COMPUTE COLUMN K OF THE INVERSE.
*
IF( K.LT.N ) THEN
CALL DCOPY( N-K, A( K+1, K ), 1, WORK, 1 )
CALL DSYMV( UPLO, N-K, -ONE, A( K+1, K+1 ), LDA, WORK, 1,
$ ZERO, A( K+1, K ), 1 )
A( K, K ) = A( K, K ) - DDOT( N-K, WORK, 1, A( K+1, K ),
$ 1 )
END IF
KSTEP = 1
ELSE
*
* 2 X 2 DIAGONAL BLOCK
*
* INVERT THE DIAGONAL BLOCK.
*
T = ABS( A( K, K-1 ) )
AK = A( K-1, K-1 ) / T
AKP1 = A( K, K ) / T
AKKP1 = A( K, K-1 ) / T
D = T*( AK*AKP1-ONE )
A( K-1, K-1 ) = AKP1 / D
A( K, K ) = AK / D
A( K, K-1 ) = -AKKP1 / D
*
* COMPUTE COLUMNS K-1 AND K OF THE INVERSE.
*
IF( K.LT.N ) THEN
CALL DCOPY( N-K, A( K+1, K ), 1, WORK, 1 )
CALL DSYMV( UPLO, N-K, -ONE, A( K+1, K+1 ), LDA, WORK, 1,
$ ZERO, A( K+1, K ), 1 )
A( K, K ) = A( K, K ) - DDOT( N-K, WORK, 1, A( K+1, K ),
$ 1 )
A( K, K-1 ) = A( K, K-1 ) -
$ DDOT( N-K, A( K+1, K ), 1, A( K+1, K-1 ),
$ 1 )
CALL DCOPY( N-K, A( K+1, K-1 ), 1, WORK, 1 )
CALL DSYMV( UPLO, N-K, -ONE, A( K+1, K+1 ), LDA, WORK, 1,
$ ZERO, A( K+1, K-1 ), 1 )
A( K-1, K-1 ) = A( K-1, K-1 ) -
$ DDOT( N-K, WORK, 1, A( K+1, K-1 ), 1 )
END IF
KSTEP = 2
END IF
*
KP = ABS( IPIV( K ) )
IF( KP.NE.K ) THEN
*
* INTERCHANGE ROWS AND COLUMNS K AND KP IN THE TRAILING
* SUBMATRIX A(K-1:N,K-1:N)
*
IF( KP.LT.N )
$ CALL DSWAP( N-KP, A( KP+1, K ), 1, A( KP+1, KP ), 1 )
CALL DSWAP( KP-K-1, A( K+1, K ), 1, A( KP, K+1 ), LDA )
TEMP = A( K, K )
A( K, K ) = A( KP, KP )
A( KP, KP ) = TEMP
IF( KSTEP.EQ.2 ) THEN
TEMP = A( K, K-1 )
A( K, K-1 ) = A( KP, K-1 )
A( KP, K-1 ) = TEMP
END IF
END IF
*
K = K - KSTEP
GO TO 50
60 CONTINUE
END IF
*
RETURN
*
* END OF DSYTRI
*
END
C ------------------ BELOW IS DGESV ------------------------
SUBROUTINE DGESV( N, NRHS, A, LDA, IPIV, B, LDB, INFO )
*
* -- LAPACK DRIVER ROUTINE (VERSION 1.1) --
* UNIV. OF TENNESSEE, UNIV. OF CALIFORNIA BERKELEY, NAG LTD.,
* COURANT INSTITUTE, ARGONNE NATIONAL LAB, AND RICE UNIVERSITY
* MARCH 31, 1993
*
* .. SCALAR ARGUMENTS ..
INTEGER INFO, LDA, LDB, N, NRHS
* ..
* .. ARRAY ARGUMENTS ..
INTEGER IPIV( * )
DOUBLE PRECISION A( LDA, * ), B( LDB, * )
* ..
*
* PURPOSE
* =======
*
* DGESV COMPUTES THE SOLUTION TO A REAL SYSTEM OF LINEAR EQUATIONS
* A * X = B,
* WHERE A IS AN N-BY-N MATRIX AND X AND B ARE N-BY-NRHS MATRICES.
*
* THE LU DECOMPOSITION WITH PARTIAL PIVOTING AND ROW INTERCHANGES IS
* USED TO FACTOR A AS
* A = P * L * U,
* WHERE P IS A PERMUTATION MATRIX, L IS UNIT LOWER TRIANGULAR, AND U IS
* UPPER TRIANGULAR. THE FACTORED FORM OF A IS THEN USED TO SOLVE THE
* SYSTEM OF EQUATIONS A * X = B.
*
* ARGUMENTS
* =========
*
* N (INPUT) INTEGER
* THE NUMBER OF LINEAR EQUATIONS, I.E., THE ORDER OF THE
* MATRIX A. N >= 0.
*
* NRHS (INPUT) INTEGER
* THE NUMBER OF RIGHT HAND SIDES, I.E., THE NUMBER OF COLUMNS
* OF THE MATRIX B. NRHS >= 0.
*
* A (INPUT/OUTPUT) DOUBLE PRECISION ARRAY, DIMENSION (LDA,N)
* ON ENTRY, THE N-BY-N COEFFICIENT MATRIX A.
* ON EXIT, THE FACTORS L AND U FROM THE FACTORIZATION
* A = P*L*U; THE UNIT DIAGONAL ELEMENTS OF L ARE NOT STORED.
*
* LDA (INPUT) INTEGER
* THE LEADING DIMENSION OF THE ARRAY A. LDA >= MAX(1,N).
*
* IPIV (OUTPUT) INTEGER ARRAY, DIMENSION (N)
* THE PIVOT INDICES THAT DEFINE THE PERMUTATION MATRIX P;
* ROW I OF THE MATRIX WAS INTERCHANGED WITH ROW IPIV(I).
*
* B (INPUT/OUTPUT) DOUBLE PRECISION ARRAY, DIMENSION (LDB,NRHS)
* ON ENTRY, THE N-BY-NRHS MATRIX OF RIGHT HAND SIDE MATRIX B.
* ON EXIT, IF INFO = 0, THE N-BY-NRHS SOLUTION MATRIX X.
*
* LDB (INPUT) INTEGER
* THE LEADING DIMENSION OF THE ARRAY B. LDB >= MAX(1,N).
*
* INFO (OUTPUT) INTEGER
* = 0: SUCCESSFUL EXIT
* < 0: IF INFO = -I, THE I-TH ARGUMENT HAD AN ILLEGAL VALUE
* > 0: IF INFO = I, U(I,I) IS EXACTLY ZERO. THE FACTORIZATION
* HAS BEEN COMPLETED, BUT THE FACTOR U IS EXACTLY
* SINGULAR, SO THE SOLUTION COULD NOT BE COMPUTED.
*
* =====================================================================
*
* .. EXTERNAL SUBROUTINES ..
EXTERNAL DGETRF, DGETRS, XERBLA
* ..
* .. INTRINSIC FUNCTIONS ..
INTRINSIC MAX
* ..
* .. EXECUTABLE STATEMENTS ..
*
* TEST THE INPUT PARAMETERS.
*
INFO = 0
IF( N.LT.0 ) THEN
INFO = -1
ELSE IF( NRHS.LT.0 ) THEN
INFO = -2
ELSE IF( LDA.LT.MAX( 1, N ) ) THEN
INFO = -4
ELSE IF( LDB.LT.MAX( 1, N ) ) THEN
INFO = -7
END IF
IF( INFO.NE.0 ) THEN
CALL XERBLA( 'DGESV ', -INFO )
RETURN
END IF
*
* COMPUTE THE LU FACTORIZATION OF A.
*
CALL DGETRF( N, N, A, LDA, IPIV, INFO )
IF( INFO.EQ.0 ) THEN
*
* SOLVE THE SYSTEM A*X = B, OVERWRITING B WITH X.
*
CALL DGETRS( 'NO TRANSPOSE', N, NRHS, A, LDA, IPIV, B, LDB,
$ INFO )
END IF
RETURN
*
* END OF DGESV
*
END
CUT HERE............
CAT > DGETRS.F <<'CUT HERE............'
SUBROUTINE DGETRS( TRANS, N, NRHS, A, LDA, IPIV, B, LDB, INFO )
*
* -- LAPACK ROUTINE (VERSION 1.1) --
* UNIV. OF TENNESSEE, UNIV. OF CALIFORNIA BERKELEY, NAG LTD.,
* COURANT INSTITUTE, ARGONNE NATIONAL LAB, AND RICE UNIVERSITY
* MARCH 31, 1993
*
* .. SCALAR ARGUMENTS ..
CHARACTER TRANS
INTEGER INFO, LDA, LDB, N, NRHS
* ..
* .. ARRAY ARGUMENTS ..
INTEGER IPIV( * )
DOUBLE PRECISION A( LDA, * ), B( LDB, * )
* ..
*
* PURPOSE
* =======
*
* DGETRS SOLVES A SYSTEM OF LINEAR EQUATIONS
* A * X = B OR A' * X = B
* WITH A GENERAL N-BY-N MATRIX A USING THE LU FACTORIZATION COMPUTED
* BY DGETRF.
*
* ARGUMENTS
* =========
*
* TRANS (INPUT) CHARACTER*1
* SPECIFIES THE FORM OF THE SYSTEM OF EQUATIONS:
* = 'N': A * X = B (NO TRANSPOSE)
* = 'T': A'* X = B (TRANSPOSE)
* = 'C': A'* X = B (CONJUGATE TRANSPOSE = TRANSPOSE)
*
* N (INPUT) INTEGER
* THE ORDER OF THE MATRIX A. N >= 0.
*
* NRHS (INPUT) INTEGER
* THE NUMBER OF RIGHT HAND SIDES, I.E., THE NUMBER OF COLUMNS
* OF THE MATRIX B. NRHS >= 0.
*
* A (INPUT) DOUBLE PRECISION ARRAY, DIMENSION (LDA,N)
* THE FACTORS L AND U FROM THE FACTORIZATION A = P*L*U
* AS COMPUTED BY DGETRF.
*
* LDA (INPUT) INTEGER
* THE LEADING DIMENSION OF THE ARRAY A. LDA >= MAX(1,N).
*
* IPIV (INPUT) INTEGER ARRAY, DIMENSION (N)
* THE PIVOT INDICES FROM DGETRF; FOR 1<=I<=N, ROW I OF THE
* MATRIX WAS INTERCHANGED WITH ROW IPIV(I).
*
* B (INPUT/OUTPUT) DOUBLE PRECISION ARRAY, DIMENSION (LDB,NRHS)
* ON ENTRY, THE RIGHT HAND SIDE MATRIX B.
* ON EXIT, THE SOLUTION MATRIX X.
*
* LDB (INPUT) INTEGER
* THE LEADING DIMENSION OF THE ARRAY B. LDB >= MAX(1,N).
*
* INFO (OUTPUT) INTEGER
* = 0: SUCCESSFUL EXIT
* < 0: IF INFO = -I, THE I-TH ARGUMENT HAD AN ILLEGAL VALUE
*
* =====================================================================
*
* .. PARAMETERS ..
DOUBLE PRECISION ONE
PARAMETER ( ONE = 1.0D+0 )
* ..
* .. LOCAL SCALARS ..
LOGICAL NOTRAN
* ..
* .. EXTERNAL FUNCTIONS ..
LOGICAL LSAME
EXTERNAL LSAME
* ..
* .. EXTERNAL SUBROUTINES ..
EXTERNAL DLASWP, DTRSM, XERBLA
* ..
* .. INTRINSIC FUNCTIONS ..
INTRINSIC MAX
* ..
* .. EXECUTABLE STATEMENTS ..
*
* TEST THE INPUT PARAMETERS.
*
INFO = 0
NOTRAN = LSAME( TRANS, 'N' )
IF( .NOT.NOTRAN .AND. .NOT.LSAME( TRANS, 'T' ) .AND. .NOT.
$ LSAME( TRANS, 'C' ) ) THEN
INFO = -1
ELSE IF( N.LT.0 ) THEN
INFO = -2
ELSE IF( NRHS.LT.0 ) THEN
INFO = -3
ELSE IF( LDA.LT.MAX( 1, N ) ) THEN
INFO = -5
ELSE IF( LDB.LT.MAX( 1, N ) ) THEN
INFO = -8
END IF
IF( INFO.NE.0 ) THEN
CALL XERBLA( 'DGETRS', -INFO )
RETURN
END IF
*
* QUICK RETURN IF POSSIBLE
*
IF( N.EQ.0 .OR. NRHS.EQ.0 )
$ RETURN
*
IF( NOTRAN ) THEN
*
* SOLVE A * X = B.
*
* APPLY ROW INTERCHANGES TO THE RIGHT HAND SIDES.
*
CALL DLASWP( NRHS, B, LDB, 1, N, IPIV, 1 )
*
* SOLVE L*X = B, OVERWRITING B WITH X.
*
CALL DTRSM( 'LEFT', 'LOWER', 'NO TRANSPOSE', 'UNIT', N, NRHS,
$ ONE, A, LDA, B, LDB )
*
* SOLVE U*X = B, OVERWRITING B WITH X.
*
CALL DTRSM( 'LEFT', 'UPPER', 'NO TRANSPOSE', 'NON-UNIT', N,
$ NRHS, ONE, A, LDA, B, LDB )
ELSE
*
* SOLVE A' * X = B.
*
* SOLVE U'*X = B, OVERWRITING B WITH X.
*
CALL DTRSM( 'LEFT', 'UPPER', 'TRANSPOSE', 'NON-UNIT', N, NRHS,
$ ONE, A, LDA, B, LDB )
*
* SOLVE L'*X = B, OVERWRITING B WITH X.
*
CALL DTRSM( 'LEFT', 'LOWER', 'TRANSPOSE', 'UNIT', N, NRHS, ONE,
$ A, LDA, B, LDB )
*
* APPLY ROW INTERCHANGES TO THE SOLUTION VECTORS.
*
CALL DLASWP( NRHS, B, LDB, 1, N, IPIV, -1 )
END IF
*
RETURN
*
* END OF DGETRS
*
END
CUT HERE............
CAT > DGETRF.F <<'CUT HERE............'
SUBROUTINE DGETRF( M, N, A, LDA, IPIV, INFO )
*
* -- LAPACK ROUTINE (VERSION 1.1) --
* UNIV. OF TENNESSEE, UNIV. OF CALIFORNIA BERKELEY, NAG LTD.,
* COURANT INSTITUTE, ARGONNE NATIONAL LAB, AND RICE UNIVERSITY
* MARCH 31, 1993
*
* .. SCALAR ARGUMENTS ..
INTEGER INFO, LDA, M, N
* ..
* .. ARRAY ARGUMENTS ..
INTEGER IPIV( * )
DOUBLE PRECISION A( LDA, * )
* ..
*
* PURPOSE
* =======
*
* DGETRF COMPUTES AN LU FACTORIZATION OF A GENERAL M-BY-N MATRIX A
* USING PARTIAL PIVOTING WITH ROW INTERCHANGES.
*
* THE FACTORIZATION HAS THE FORM
* A = P * L * U
* WHERE P IS A PERMUTATION MATRIX, L IS LOWER TRIANGULAR WITH UNIT
* DIAGONAL ELEMENTS (LOWER TRAPEZOIDAL IF M > N), AND U IS UPPER
* TRIANGULAR (UPPER TRAPEZOIDAL IF M < N).
*
* THIS IS THE RIGHT-LOOKING LEVEL 3 BLAS VERSION OF THE ALGORITHM.
*
* ARGUMENTS
* =========
*
* M (INPUT) INTEGER
* THE NUMBER OF ROWS OF THE MATRIX A. M >= 0.
*
* N (INPUT) INTEGER
* THE NUMBER OF COLUMNS OF THE MATRIX A. N >= 0.
*
* A (INPUT/OUTPUT) DOUBLE PRECISION ARRAY, DIMENSION (LDA,N)
* ON ENTRY, THE M-BY-N MATRIX TO BE FACTORED.
* ON EXIT, THE FACTORS L AND U FROM THE FACTORIZATION
* A = P*L*U; THE UNIT DIAGONAL ELEMENTS OF L ARE NOT STORED.
*
* LDA (INPUT) INTEGER
* THE LEADING DIMENSION OF THE ARRAY A. LDA >= MAX(1,M).
*
* IPIV (OUTPUT) INTEGER ARRAY, DIMENSION (MIN(M,N))
* THE PIVOT INDICES; FOR 1 <= I <= MIN(M,N), ROW I OF THE
* MATRIX WAS INTERCHANGED WITH ROW IPIV(I).
*
* INFO (OUTPUT) INTEGER
* = 0: SUCCESSFUL EXIT
* < 0: IF INFO = -I, THE I-TH ARGUMENT HAD AN ILLEGAL VALUE
* > 0: IF INFO = I, U(I,I) IS EXACTLY ZERO. THE FACTORIZATION
* HAS BEEN COMPLETED, BUT THE FACTOR U IS EXACTLY
* SINGULAR, AND DIVISION BY ZERO WILL OCCUR IF IT IS USED
* TO SOLVE A SYSTEM OF EQUATIONS.
*
* =====================================================================
*
* .. PARAMETERS ..
DOUBLE PRECISION ONE
PARAMETER ( ONE = 1.0D+0 )
* ..
* .. LOCAL SCALARS ..
INTEGER I, IINFO, J, JB, NB
* ..
* .. EXTERNAL SUBROUTINES ..
EXTERNAL DGEMM, DGETF2, DLASWP, DTRSM, XERBLA
* ..
* .. EXTERNAL FUNCTIONS ..
INTEGER ILAENV
EXTERNAL ILAENV
* ..
* .. INTRINSIC FUNCTIONS ..
INTRINSIC MAX, MIN
* ..
* .. EXECUTABLE STATEMENTS ..
*
* TEST THE INPUT PARAMETERS.
*
INFO = 0
IF( M.LT.0 ) THEN
INFO = -1
ELSE IF( N.LT.0 ) THEN
INFO = -2
ELSE IF( LDA.LT.MAX( 1, M ) ) THEN
INFO = -4
END IF
IF( INFO.NE.0 ) THEN
CALL XERBLA( 'DGETRF', -INFO )
RETURN
END IF
*
* QUICK RETURN IF POSSIBLE
*
IF( M.EQ.0 .OR. N.EQ.0 )
$ RETURN
*
* DETERMINE THE BLOCK SIZE FOR THIS ENVIRONMENT.
*
NB = ILAENV( 1, 'DGETRF', ' ', M, N, -1, -1 )
IF( NB.LE.1 .OR. NB.GE.MIN( M, N ) ) THEN
*
* USE UNBLOCKED CODE.
*
CALL DGETF2( M, N, A, LDA, IPIV, INFO )
ELSE
*
* USE BLOCKED CODE.
*
DO 20 J = 1, MIN( M, N ), NB
JB = MIN( MIN( M, N )-J+1, NB )
*
* FACTOR DIAGONAL AND SUBDIAGONAL BLOCKS AND TEST FOR EXACT
* SINGULARITY.
*
CALL DGETF2( M-J+1, JB, A( J, J ), LDA, IPIV( J ), IINFO )
*
* ADJUST INFO AND THE PIVOT INDICES.
*
IF( INFO.EQ.0 .AND. IINFO.GT.0 )
$ INFO = IINFO + J - 1
DO 10 I = J, MIN( M, J+JB-1 )
IPIV( I ) = J - 1 + IPIV( I )
10 CONTINUE
*
* APPLY INTERCHANGES TO COLUMNS 1:J-1.
*
CALL DLASWP( J-1, A, LDA, J, J+JB-1, IPIV, 1 )
*
IF( J+JB.LE.N ) THEN
*
* APPLY INTERCHANGES TO COLUMNS J+JB:N.
*
CALL DLASWP( N-J-JB+1, A( 1, J+JB ), LDA, J, J+JB-1,
$ IPIV, 1 )
*
* COMPUTE BLOCK ROW OF U.
*
CALL DTRSM( 'LEFT', 'LOWER', 'NO TRANSPOSE', 'UNIT', JB,
$ N-J-JB+1, ONE, A( J, J ), LDA, A( J, J+JB ),
$ LDA )
IF( J+JB.LE.M ) THEN
*
* UPDATE TRAILING SUBMATRIX.
*
CALL DGEMM( 'NO TRANSPOSE', 'NO TRANSPOSE', M-J-JB+1,
$ N-J-JB+1, JB, -ONE, A( J+JB, J ), LDA,
$ A( J, J+JB ), LDA, ONE, A( J+JB, J+JB ),
$ LDA )
END IF
END IF
20 CONTINUE
END IF
RETURN
*
* END OF DGETRF
*
END
CUT HERE............
CAT > DLASWP.F <<'CUT HERE............'
SUBROUTINE DLASWP( N, A, LDA, K1, K2, IPIV, INCX )
*
* -- LAPACK AUXILIARY ROUTINE (VERSION 1.1) --
* UNIV. OF TENNESSEE, UNIV. OF CALIFORNIA BERKELEY, NAG LTD.,
* COURANT INSTITUTE, ARGONNE NATIONAL LAB, AND RICE UNIVERSITY
* OCTOBER 31, 1992
*
* .. SCALAR ARGUMENTS ..
INTEGER INCX, K1, K2, LDA, N
* ..
* .. ARRAY ARGUMENTS ..
INTEGER IPIV( * )
DOUBLE PRECISION A( LDA, * )
* ..
*
* PURPOSE
* =======
*
* DLASWP PERFORMS A SERIES OF ROW INTERCHANGES ON THE MATRIX A.
* ONE ROW INTERCHANGE IS INITIATED FOR EACH OF ROWS K1 THROUGH K2 OF A.
*
* ARGUMENTS
* =========
*
* N (INPUT) INTEGER
* THE NUMBER OF COLUMNS OF THE MATRIX A.
*
* A (INPUT/OUTPUT) DOUBLE PRECISION ARRAY, DIMENSION (LDA,N)
* ON ENTRY, THE MATRIX OF COLUMN DIMENSION N TO WHICH THE ROW
* INTERCHANGES WILL BE APPLIED.
* ON EXIT, THE PERMUTED MATRIX.
*
* LDA (INPUT) INTEGER
* THE LEADING DIMENSION OF THE ARRAY A.
*
* K1 (INPUT) INTEGER
* THE FIRST ELEMENT OF IPIV FOR WHICH A ROW INTERCHANGE WILL
* BE DONE.
*
* K2 (INPUT) INTEGER
* THE LAST ELEMENT OF IPIV FOR WHICH A ROW INTERCHANGE WILL
* BE DONE.
*
* IPIV (INPUT) INTEGER ARRAY, DIMENSION (M*ABS(INCX))
* THE VECTOR OF PIVOT INDICES. ONLY THE ELEMENTS IN POSITIONS
* K1 THROUGH K2 OF IPIV ARE ACCESSED.
* IPIV(K) = L IMPLIES ROWS K AND L ARE TO BE INTERCHANGED.
*
* INCX (INPUT) INTEGER
* THE INCREMENT BETWEEN SUCCESSIVE VALUES OF IPIV. IF IPIV
* IS NEGATIVE, THE PIVOTS ARE APPLIED IN REVERSE ORDER.
*
* =====================================================================
*
* .. LOCAL SCALARS ..
INTEGER I, IP, IX
* ..
* .. EXTERNAL SUBROUTINES ..
EXTERNAL DSWAP
* ..
* .. EXECUTABLE STATEMENTS ..
*
* INTERCHANGE ROW I WITH ROW IPIV(I) FOR EACH OF ROWS K1 THROUGH K2.
*
IF( INCX.EQ.0 )
$ RETURN
IF( INCX.GT.0 ) THEN
IX = K1
ELSE
IX = 1 + ( 1-K2 )*INCX
END IF
IF( INCX.EQ.1 ) THEN
DO 10 I = K1, K2
IP = IPIV( I )
IF( IP.NE.I )
$ CALL DSWAP( N, A( I, 1 ), LDA, A( IP, 1 ), LDA )
10 CONTINUE
ELSE IF( INCX.GT.1 ) THEN
DO 20 I = K1, K2
IP = IPIV( IX )
IF( IP.NE.I )
$ CALL DSWAP( N, A( I, 1 ), LDA, A( IP, 1 ), LDA )
IX = IX + INCX
20 CONTINUE
ELSE IF( INCX.LT.0 ) THEN
DO 30 I = K2, K1, -1
IP = IPIV( IX )
IF( IP.NE.I )
$ CALL DSWAP( N, A( I, 1 ), LDA, A( IP, 1 ), LDA )
IX = IX + INCX
30 CONTINUE
END IF
*
RETURN
*
* END OF DLASWP
*
END
CUT HERE............
CAT > DGETF2.F <<'CUT HERE............'
SUBROUTINE DGETF2( M, N, A, LDA, IPIV, INFO )
*
* -- LAPACK ROUTINE (VERSION 1.1) --
* UNIV. OF TENNESSEE, UNIV. OF CALIFORNIA BERKELEY, NAG LTD.,
* COURANT INSTITUTE, ARGONNE NATIONAL LAB, AND RICE UNIVERSITY
* JUNE 30, 1992
*
* .. SCALAR ARGUMENTS ..
INTEGER INFO, LDA, M, N
* ..
* .. ARRAY ARGUMENTS ..
INTEGER IPIV( * )
DOUBLE PRECISION A( LDA, * )
* ..
*
* PURPOSE
* =======
*
* DGETF2 COMPUTES AN LU FACTORIZATION OF A GENERAL M-BY-N MATRIX A
* USING PARTIAL PIVOTING WITH ROW INTERCHANGES.
*
* THE FACTORIZATION HAS THE FORM
* A = P * L * U
* WHERE P IS A PERMUTATION MATRIX, L IS LOWER TRIANGULAR WITH UNIT
* DIAGONAL ELEMENTS (LOWER TRAPEZOIDAL IF M > N), AND U IS UPPER
* TRIANGULAR (UPPER TRAPEZOIDAL IF M < N).
*
* THIS IS THE RIGHT-LOOKING LEVEL 2 BLAS VERSION OF THE ALGORITHM.
*
* ARGUMENTS
* =========
*
* M (INPUT) INTEGER
* THE NUMBER OF ROWS OF THE MATRIX A. M >= 0.
*
* N (INPUT) INTEGER
* THE NUMBER OF COLUMNS OF THE MATRIX A. N >= 0.
*
* A (INPUT/OUTPUT) DOUBLE PRECISION ARRAY, DIMENSION (LDA,N)
* ON ENTRY, THE M BY N MATRIX TO BE FACTORED.
* ON EXIT, THE FACTORS L AND U FROM THE FACTORIZATION
* A = P*L*U; THE UNIT DIAGONAL ELEMENTS OF L ARE NOT STORED.
*
* LDA (INPUT) INTEGER
* THE LEADING DIMENSION OF THE ARRAY A. LDA >= MAX(1,M).
*
* IPIV (OUTPUT) INTEGER ARRAY, DIMENSION (MIN(M,N))
* THE PIVOT INDICES; FOR 1 <= I <= MIN(M,N), ROW I OF THE
* MATRIX WAS INTERCHANGED WITH ROW IPIV(I).
*
* INFO (OUTPUT) INTEGER
* = 0: SUCCESSFUL EXIT
* < 0: IF INFO = -K, THE K-TH ARGUMENT HAD AN ILLEGAL VALUE
* > 0: IF INFO = K, U(K,K) IS EXACTLY ZERO. THE FACTORIZATION
* HAS BEEN COMPLETED, BUT THE FACTOR U IS EXACTLY
* SINGULAR, AND DIVISION BY ZERO WILL OCCUR IF IT IS USED
* TO SOLVE A SYSTEM OF EQUATIONS.
*
* =====================================================================
*
* .. PARAMETERS ..
DOUBLE PRECISION ONE, ZERO
PARAMETER ( ONE = 1.0D+0, ZERO = 0.0D+0 )
* ..
* .. LOCAL SCALARS ..
INTEGER J, JP
* ..
* .. EXTERNAL FUNCTIONS ..
INTEGER IDAMAX
EXTERNAL IDAMAX
* ..
* .. EXTERNAL SUBROUTINES ..
EXTERNAL DGER, DSCAL, DSWAP, XERBLA
* ..
* .. INTRINSIC FUNCTIONS ..
INTRINSIC MAX, MIN
* ..
* .. EXECUTABLE STATEMENTS ..
*
* TEST THE INPUT PARAMETERS.
*
INFO = 0
IF( M.LT.0 ) THEN
INFO = -1
ELSE IF( N.LT.0 ) THEN
INFO = -2
ELSE IF( LDA.LT.MAX( 1, M ) ) THEN
INFO = -4
END IF
IF( INFO.NE.0 ) THEN
CALL XERBLA( 'DGETF2', -INFO )
RETURN
END IF
*
* QUICK RETURN IF POSSIBLE
*
IF( M.EQ.0 .OR. N.EQ.0 )
$ RETURN
*
DO 10 J = 1, MIN( M, N )
*
* FIND PIVOT AND TEST FOR SINGULARITY.
*
JP = J - 1 + IDAMAX( M-J+1, A( J, J ), 1 )
IPIV( J ) = JP
IF( A( JP, J ).NE.ZERO ) THEN
*
* APPLY THE INTERCHANGE TO COLUMNS 1:N.
*
IF( JP.NE.J )
$ CALL DSWAP( N, A( J, 1 ), LDA, A( JP, 1 ), LDA )
*
* COMPUTE ELEMENTS J+1:M OF J-TH COLUMN.
*
IF( J.LT.M )
$ CALL DSCAL( M-J, ONE / A( J, J ), A( J+1, J ), 1 )
*
ELSE IF( INFO.EQ.0 ) THEN
*
INFO = J
END IF
*
IF( J.LT.MIN( M, N ) ) THEN
*
* UPDATE TRAILING SUBMATRIX.
*
CALL DGER( M-J, N-J, -ONE, A( J+1, J ), 1, A( J, J+1 ), LDA,
$ A( J+1, J+1 ), LDA )
END IF
10 CONTINUE
RETURN
*
* END OF DGETF2
*
END
CUT HERE............