Rev 22546 | Blame | Compare with Previous | Last modification | View Log | Download | RSS feed
SUBROUTINE DOPGTR( UPLO, N, AP, TAU, Q, LDQ, WORK, INFO )** -- LAPACK routine (version 3.0) --* Univ. of Tennessee, Univ. of California Berkeley, NAG Ltd.,* Courant Institute, Argonne National Lab, and Rice University* September 30, 1994** .. Scalar Arguments ..CHARACTER UPLOINTEGER INFO, LDQ, N* ..* .. Array Arguments ..DOUBLE PRECISION AP( * ), Q( LDQ, * ), TAU( * ), WORK( * )* ..** Purpose* =======** DOPGTR generates a real orthogonal matrix Q which is defined as the* product of n-1 elementary reflectors H(i) of order n, as returned by* DSPTRD using packed storage:** 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 triangular packed storage used in previous* call to DSPTRD;* = 'L': Lower triangular packed storage used in previous* call to DSPTRD.** N (input) INTEGER* The order of the matrix Q. N >= 0.** AP (input) DOUBLE PRECISION array, dimension (N*(N+1)/2)* The vectors which define the elementary reflectors, as* returned by DSPTRD.** TAU (input) DOUBLE PRECISION array, dimension (N-1)* TAU(i) must contain the scalar factor of the elementary* reflector H(i), as returned by DSPTRD.** Q (output) DOUBLE PRECISION array, dimension (LDQ,N)* The N-by-N orthogonal matrix Q.** LDQ (input) INTEGER* The leading dimension of the array Q. LDQ >= max(1,N).** WORK (workspace) DOUBLE PRECISION array, dimension (N-1)** INFO (output) INTEGER* = 0: successful exit* < 0: if INFO = -i, the i-th argument had an illegal value** =====================================================================** .. Parameters ..DOUBLE PRECISION ZERO, ONEPARAMETER ( ZERO = 0.0D+0, ONE = 1.0D+0 )* ..* .. Local Scalars ..LOGICAL UPPERINTEGER I, IINFO, IJ, J* ..* .. External Functions ..LOGICAL LSAMEEXTERNAL LSAME* ..* .. External Subroutines ..EXTERNAL DORG2L, DORG2R, XERBLA* ..* .. Intrinsic Functions ..INTRINSIC MAX* ..* .. Executable Statements ..** Test the input arguments*INFO = 0UPPER = LSAME( UPLO, 'U' )IF( .NOT.UPPER .AND. .NOT.LSAME( UPLO, 'L' ) ) THENINFO = -1ELSE IF( N.LT.0 ) THENINFO = -2ELSE IF( LDQ.LT.MAX( 1, N ) ) THENINFO = -6END IFIF( INFO.NE.0 ) THENCALL XERBLA( 'DOPGTR', -INFO )RETURNEND IF** Quick return if possible*IF( N.EQ.0 )$ RETURN*IF( UPPER ) THEN** Q was determined by a call to DSPTRD with UPLO = 'U'** Unpack the vectors which define the elementary reflectors and* set the last row and column of Q equal to those of the unit* matrix*IJ = 2DO 20 J = 1, N - 1DO 10 I = 1, J - 1Q( I, J ) = AP( IJ )IJ = IJ + 110 CONTINUEIJ = IJ + 2Q( N, J ) = ZERO20 CONTINUEDO 30 I = 1, N - 1Q( I, N ) = ZERO30 CONTINUEQ( N, N ) = ONE** Generate Q(1:n-1,1:n-1)*CALL DORG2L( N-1, N-1, N-1, Q, LDQ, TAU, WORK, IINFO )*ELSE** Q was determined by a call to DSPTRD with UPLO = 'L'.** Unpack the vectors which define the elementary reflectors and* set the first row and column of Q equal to those of the unit* matrix*Q( 1, 1 ) = ONEDO 40 I = 2, NQ( I, 1 ) = ZERO40 CONTINUEIJ = 3DO 60 J = 2, NQ( 1, J ) = ZERODO 50 I = J + 1, NQ( I, J ) = AP( IJ )IJ = IJ + 150 CONTINUEIJ = IJ + 260 CONTINUEIF( N.GT.1 ) THEN** Generate Q(2:n,2:n)*CALL DORG2R( N-1, N-1, N-1, Q( 2, 2 ), LDQ, TAU, WORK,$ IINFO )END IFEND IFRETURN** End of DOPGTR*ENDSUBROUTINE DOPMTR( SIDE, UPLO, TRANS, M, N, AP, TAU, C, LDC, WORK,$ INFO )** -- LAPACK routine (version 3.0) --* Univ. of Tennessee, Univ. of California Berkeley, NAG Ltd.,* Courant Institute, Argonne National Lab, and Rice University* September 30, 1994** .. Scalar Arguments ..CHARACTER SIDE, TRANS, UPLOINTEGER INFO, LDC, M, N* ..* .. Array Arguments ..DOUBLE PRECISION AP( * ), C( LDC, * ), TAU( * ), WORK( * )* ..** Purpose* =======** DOPMTR 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 DSPTRD using packed* storage:** 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 triangular packed storage used in previous* call to DSPTRD;* = 'L': Lower triangular packed storage used in previous* call to DSPTRD.** 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.** AP (input) DOUBLE PRECISION array, dimension* (M*(M+1)/2) if SIDE = 'L'* (N*(N+1)/2) if SIDE = 'R'* The vectors which define the elementary reflectors, as* returned by DSPTRD. AP is modified by the routine but* restored on exit.** TAU (input) DOUBLE PRECISION array, dimension (M-1) if SIDE = 'L'* or (N-1) if SIDE = 'R'* TAU(i) must contain the scalar factor of the elementary* reflector H(i), as returned by DSPTRD.** 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* (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 ONEPARAMETER ( ONE = 1.0D+0 )* ..* .. Local Scalars ..LOGICAL FORWRD, LEFT, NOTRAN, UPPERINTEGER I, I1, I2, I3, IC, II, JC, MI, NI, NQDOUBLE PRECISION AII* ..* .. External Functions ..LOGICAL LSAMEEXTERNAL LSAME* ..* .. External Subroutines ..EXTERNAL DLARF, XERBLA* ..* .. Intrinsic Functions ..INTRINSIC MAX* ..* .. Executable Statements ..** Test the input arguments*INFO = 0LEFT = LSAME( SIDE, 'L' )NOTRAN = LSAME( TRANS, 'N' )UPPER = LSAME( UPLO, 'U' )** NQ is the order of Q*IF( LEFT ) THENNQ = MELSENQ = NEND IFIF( .NOT.LEFT .AND. .NOT.LSAME( SIDE, 'R' ) ) THENINFO = -1ELSE IF( .NOT.UPPER .AND. .NOT.LSAME( UPLO, 'L' ) ) THENINFO = -2ELSE IF( .NOT.NOTRAN .AND. .NOT.LSAME( TRANS, 'T' ) ) THENINFO = -3ELSE IF( M.LT.0 ) THENINFO = -4ELSE IF( N.LT.0 ) THENINFO = -5ELSE IF( LDC.LT.MAX( 1, M ) ) THENINFO = -9END IFIF( INFO.NE.0 ) THENCALL XERBLA( 'DOPMTR', -INFO )RETURNEND IF** Quick return if possible*IF( M.EQ.0 .OR. N.EQ.0 )$ RETURN*IF( UPPER ) THEN** Q was determined by a call to DSPTRD with UPLO = 'U'*FORWRD = ( LEFT .AND. NOTRAN ) .OR.$ ( .NOT.LEFT .AND. .NOT.NOTRAN )*IF( FORWRD ) THENI1 = 1I2 = NQ - 1I3 = 1II = 2ELSEI1 = NQ - 1I2 = 1I3 = -1II = NQ*( NQ+1 ) / 2 - 1END IF*IF( LEFT ) THENNI = NELSEMI = MEND IF*DO 10 I = I1, I2, I3IF( LEFT ) THEN** H(i) is applied to C(1:i,1:n)*MI = IELSE** H(i) is applied to C(1:m,1:i)*NI = IEND IF** Apply H(i)*AII = AP( II )AP( II ) = ONECALL DLARF( SIDE, MI, NI, AP( II-I+1 ), 1, TAU( I ), C, LDC,$ WORK )AP( II ) = AII*IF( FORWRD ) THENII = II + I + 2ELSEII = II - I - 1END IF10 CONTINUEELSE** Q was determined by a call to DSPTRD with UPLO = 'L'.*FORWRD = ( LEFT .AND. .NOT.NOTRAN ) .OR.$ ( .NOT.LEFT .AND. NOTRAN )*IF( FORWRD ) THENI1 = 1I2 = NQ - 1I3 = 1II = 2ELSEI1 = NQ - 1I2 = 1I3 = -1II = NQ*( NQ+1 ) / 2 - 1END IF*IF( LEFT ) THENNI = NJC = 1ELSEMI = MIC = 1END IF*DO 20 I = I1, I2, I3AII = AP( II )AP( II ) = ONEIF( LEFT ) THEN** H(i) is applied to C(i+1:m,1:n)*MI = M - IIC = I + 1ELSE** H(i) is applied to C(1:m,i+1:n)*NI = N - IJC = I + 1END IF** Apply H(i)*CALL DLARF( SIDE, MI, NI, AP( II ), 1, TAU( I ),$ C( IC, JC ), LDC, WORK )AP( II ) = AII*IF( FORWRD ) THENII = II + NQ - I + 1ELSEII = II - NQ + I - 2END IF20 CONTINUEEND IFRETURN** End of DOPMTR*ENDSUBROUTINE DORG2L( M, N, K, A, LDA, TAU, WORK, INFO )** -- LAPACK routine (version 3.0) --* 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, ZEROPARAMETER ( 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 = 0IF( M.LT.0 ) THENINFO = -1ELSE IF( N.LT.0 .OR. N.GT.M ) THENINFO = -2ELSE IF( K.LT.0 .OR. K.GT.N ) THENINFO = -3ELSE IF( LDA.LT.MAX( 1, M ) ) THENINFO = -5END IFIF( INFO.NE.0 ) THENCALL XERBLA( 'DORG2L', -INFO )RETURNEND 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 - KDO 10 L = 1, MA( L, J ) = ZERO10 CONTINUEA( M-N+J, J ) = ONE20 CONTINUE*DO 40 I = 1, KII = N - K + I** Apply H(i) to A(1:m-k+i,1:n-k+i) from the left*A( M-N+II, II ) = ONECALL 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, MA( L, II ) = ZERO30 CONTINUE40 CONTINUERETURN** End of DORG2L*ENDSUBROUTINE DORG2R( M, N, K, A, LDA, TAU, WORK, INFO )** -- LAPACK routine (version 3.0) --* 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, ZEROPARAMETER ( 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 = 0IF( M.LT.0 ) THENINFO = -1ELSE IF( N.LT.0 .OR. N.GT.M ) THENINFO = -2ELSE IF( K.LT.0 .OR. K.GT.N ) THENINFO = -3ELSE IF( LDA.LT.MAX( 1, M ) ) THENINFO = -5END IFIF( INFO.NE.0 ) THENCALL XERBLA( 'DORG2R', -INFO )RETURNEND 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, NDO 10 L = 1, MA( L, J ) = ZERO10 CONTINUEA( J, J ) = ONE20 CONTINUE*DO 40 I = K, 1, -1** Apply H(i) to A(i:m,i:n) from the left*IF( I.LT.N ) THENA( I, I ) = ONECALL DLARF( 'Left', M-I+1, N-I, A( I, I ), 1, TAU( I ),$ A( I, I+1 ), LDA, WORK )END IFIF( 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 - 1A( L, I ) = ZERO30 CONTINUE40 CONTINUERETURN** End of DORG2R*ENDSUBROUTINE DORGBR( VECT, M, N, K, A, LDA, TAU, WORK, LWORK, INFO )** -- LAPACK routine (version 3.0) --* Univ. of Tennessee, Univ. of California Berkeley, NAG Ltd.,* Courant Institute, Argonne National Lab, and Rice University* June 30, 1999** .. Scalar Arguments ..CHARACTER VECTINTEGER INFO, K, LDA, LWORK, M, N* ..* .. Array Arguments ..DOUBLE PRECISION A( LDA, * ), TAU( * ), WORK( * )* ..** Purpose* =======** DORGBR generates one of the real orthogonal matrices Q or P**T* determined by DGEBRD when reducing a real matrix A to bidiagonal* form: A = Q * B * P**T. Q and P**T are defined as products of* elementary reflectors H(i) or G(i) respectively.** If VECT = 'Q', A is assumed to have been an M-by-K matrix, and Q* is of order M:* if m >= k, Q = H(1) H(2) . . . H(k) and DORGBR returns the first n* columns of Q, where m >= n >= k;* if m < k, Q = H(1) H(2) . . . H(m-1) and DORGBR returns Q as an* M-by-M matrix.** If VECT = 'P', A is assumed to have been a K-by-N matrix, and P**T* is of order N:* if k < n, P**T = G(k) . . . G(2) G(1) and DORGBR returns the first m* rows of P**T, where n >= m >= k;* if k >= n, P**T = G(n-1) . . . G(2) G(1) and DORGBR returns P**T as* an N-by-N matrix.** Arguments* =========** VECT (input) CHARACTER*1* Specifies whether the matrix Q or the matrix P**T is* required, as defined in the transformation applied by DGEBRD:* = 'Q': generate Q;* = 'P': generate P**T.** M (input) INTEGER* The number of rows of the matrix Q or P**T to be returned.* M >= 0.** N (input) INTEGER* The number of columns of the matrix Q or P**T to be returned.* N >= 0.* If VECT = 'Q', M >= N >= min(M,K);* if VECT = 'P', N >= M >= min(N,K).** K (input) INTEGER* If VECT = 'Q', the number of columns in the original M-by-K* matrix reduced by DGEBRD.* If VECT = 'P', the number of rows in the original K-by-N* matrix reduced by DGEBRD.* K >= 0.** A (input/output) DOUBLE PRECISION array, dimension (LDA,N)* On entry, the vectors which define the elementary reflectors,* as returned by DGEBRD.* On exit, the M-by-N matrix Q or P**T.** LDA (input) INTEGER* The leading dimension of the array A. LDA >= max(1,M).** TAU (input) DOUBLE PRECISION array, dimension* (min(M,K)) if VECT = 'Q'* (min(N,K)) if VECT = 'P'* TAU(i) must contain the scalar factor of the elementary* reflector H(i) or G(i), which determines Q or P**T, as* returned by DGEBRD in its array argument TAUQ or TAUP.** WORK (workspace/output) 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,min(M,N)).* For optimum performance LWORK >= min(M,N)*NB, where NB* is the optimal blocksize.** If LWORK = -1, then a workspace query is assumed; the routine* only calculates the optimal size of the WORK array, returns* this value as the first entry of the WORK array, and no error* message related to LWORK is issued by XERBLA.** INFO (output) INTEGER* = 0: successful exit* < 0: if INFO = -i, the i-th argument had an illegal value** =====================================================================** .. Parameters ..DOUBLE PRECISION ZERO, ONEPARAMETER ( ZERO = 0.0D+0, ONE = 1.0D+0 )* ..* .. Local Scalars ..LOGICAL LQUERY, WANTQINTEGER I, IINFO, J, LWKOPT, MN, NB* ..* .. External Functions ..LOGICAL LSAMEINTEGER ILAENVEXTERNAL LSAME, ILAENV* ..* .. External Subroutines ..EXTERNAL DORGLQ, DORGQR, XERBLA* ..* .. Intrinsic Functions ..INTRINSIC MAX, MIN* ..* .. Executable Statements ..** Test the input arguments*INFO = 0WANTQ = LSAME( VECT, 'Q' )MN = MIN( M, N )LQUERY = ( LWORK.EQ.-1 )IF( .NOT.WANTQ .AND. .NOT.LSAME( VECT, 'P' ) ) THENINFO = -1ELSE IF( M.LT.0 ) THENINFO = -2ELSE IF( N.LT.0 .OR. ( WANTQ .AND. ( N.GT.M .OR. N.LT.MIN( M,$ K ) ) ) .OR. ( .NOT.WANTQ .AND. ( M.GT.N .OR. M.LT.$ MIN( N, K ) ) ) ) THENINFO = -3ELSE IF( K.LT.0 ) THENINFO = -4ELSE IF( LDA.LT.MAX( 1, M ) ) THENINFO = -6ELSE IF( LWORK.LT.MAX( 1, MN ) .AND. .NOT.LQUERY ) THENINFO = -9END IF*IF( INFO.EQ.0 ) THENIF( WANTQ ) THENNB = ILAENV( 1, 'DORGQR', ' ', M, N, K, -1 )ELSENB = ILAENV( 1, 'DORGLQ', ' ', M, N, K, -1 )END IFLWKOPT = MAX( 1, MN )*NBWORK( 1 ) = LWKOPTEND IF*IF( INFO.NE.0 ) THENCALL XERBLA( 'DORGBR', -INFO )RETURNELSE IF( LQUERY ) THENRETURNEND IF** Quick return if possible*IF( M.EQ.0 .OR. N.EQ.0 ) THENWORK( 1 ) = 1RETURNEND IF*IF( WANTQ ) THEN** Form Q, determined by a call to DGEBRD to reduce an m-by-k* matrix*IF( M.GE.K ) THEN** If m >= k, assume m >= n >= k*CALL DORGQR( M, N, K, A, LDA, TAU, WORK, LWORK, IINFO )*ELSE** If m < k, assume m = n** 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 20 J = M, 2, -1A( 1, J ) = ZERODO 10 I = J + 1, MA( I, J ) = A( I, J-1 )10 CONTINUE20 CONTINUEA( 1, 1 ) = ONEDO 30 I = 2, MA( I, 1 ) = ZERO30 CONTINUEIF( M.GT.1 ) THEN** Form Q(2:m,2:m)*CALL DORGQR( M-1, M-1, M-1, A( 2, 2 ), LDA, TAU, WORK,$ LWORK, IINFO )END IFEND IFELSE** Form P', determined by a call to DGEBRD to reduce a k-by-n* matrix*IF( K.LT.N ) THEN** If k < n, assume k <= m <= n*CALL DORGLQ( M, N, K, A, LDA, TAU, WORK, LWORK, IINFO )*ELSE** If k >= n, assume m = n** Shift the vectors which define the elementary reflectors one* row downward, and set the first row and column of P' to* those of the unit matrix*A( 1, 1 ) = ONEDO 40 I = 2, NA( I, 1 ) = ZERO40 CONTINUEDO 60 J = 2, NDO 50 I = J - 1, 2, -1A( I, J ) = A( I-1, J )50 CONTINUEA( 1, J ) = ZERO60 CONTINUEIF( N.GT.1 ) THEN** Form P'(2:n,2:n)*CALL DORGLQ( N-1, N-1, N-1, A( 2, 2 ), LDA, TAU, WORK,$ LWORK, IINFO )END IFEND IFEND IFWORK( 1 ) = LWKOPTRETURN** End of DORGBR*ENDSUBROUTINE DORGHR( N, ILO, IHI, A, LDA, TAU, WORK, LWORK, INFO )** -- LAPACK routine (version 3.0) --* Univ. of Tennessee, Univ. of California Berkeley, NAG Ltd.,* Courant Institute, Argonne National Lab, and Rice University* June 30, 1999** .. Scalar Arguments ..INTEGER IHI, ILO, INFO, LDA, LWORK, N* ..* .. Array Arguments ..DOUBLE PRECISION A( LDA, * ), TAU( * ), WORK( * )* ..** Purpose* =======** DORGHR generates a real orthogonal matrix Q which is defined as the* product of IHI-ILO elementary reflectors of order N, as returned by* DGEHRD:** Q = H(ilo) H(ilo+1) . . . H(ihi-1).** Arguments* =========** N (input) INTEGER* The order of the matrix Q. N >= 0.** ILO (input) INTEGER* IHI (input) INTEGER* ILO and IHI must have the same values as in the previous call* of DGEHRD. Q is equal to the unit matrix except in the* submatrix Q(ilo+1:ihi,ilo+1:ihi).* 1 <= ILO <= IHI <= N, if N > 0; ILO=1 and IHI=0, if N=0.** A (input/output) DOUBLE PRECISION array, dimension (LDA,N)* On entry, the vectors which define the elementary reflectors,* as returned by DGEHRD.* 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 DGEHRD.** WORK (workspace/output) 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 >= IHI-ILO.* For optimum performance LWORK >= (IHI-ILO)*NB, where NB is* the optimal blocksize.** If LWORK = -1, then a workspace query is assumed; the routine* only calculates the optimal size of the WORK array, returns* this value as the first entry of the WORK array, and no error* message related to LWORK is issued by XERBLA.** INFO (output) INTEGER* = 0: successful exit* < 0: if INFO = -i, the i-th argument had an illegal value** =====================================================================** .. Parameters ..DOUBLE PRECISION ZERO, ONEPARAMETER ( ZERO = 0.0D+0, ONE = 1.0D+0 )* ..* .. Local Scalars ..LOGICAL LQUERYINTEGER I, IINFO, J, LWKOPT, NB, NH* ..* .. External Subroutines ..EXTERNAL DORGQR, XERBLA* ..* .. External Functions ..INTEGER ILAENVEXTERNAL ILAENV* ..* .. Intrinsic Functions ..INTRINSIC MAX, MIN* ..* .. Executable Statements ..** Test the input arguments*INFO = 0NH = IHI - ILOLQUERY = ( LWORK.EQ.-1 )IF( N.LT.0 ) THENINFO = -1ELSE IF( ILO.LT.1 .OR. ILO.GT.MAX( 1, N ) ) THENINFO = -2ELSE IF( IHI.LT.MIN( ILO, N ) .OR. IHI.GT.N ) THENINFO = -3ELSE IF( LDA.LT.MAX( 1, N ) ) THENINFO = -5ELSE IF( LWORK.LT.MAX( 1, NH ) .AND. .NOT.LQUERY ) THENINFO = -8END IF*IF( INFO.EQ.0 ) THENNB = ILAENV( 1, 'DORGQR', ' ', NH, NH, NH, -1 )LWKOPT = MAX( 1, NH )*NBWORK( 1 ) = LWKOPTEND IF*IF( INFO.NE.0 ) THENCALL XERBLA( 'DORGHR', -INFO )RETURNELSE IF( LQUERY ) THENRETURNEND IF** Quick return if possible*IF( N.EQ.0 ) THENWORK( 1 ) = 1RETURNEND IF** Shift the vectors which define the elementary reflectors one* column to the right, and set the first ilo and the last n-ihi* rows and columns to those of the unit matrix*DO 40 J = IHI, ILO + 1, -1DO 10 I = 1, J - 1A( I, J ) = ZERO10 CONTINUEDO 20 I = J + 1, IHIA( I, J ) = A( I, J-1 )20 CONTINUEDO 30 I = IHI + 1, NA( I, J ) = ZERO30 CONTINUE40 CONTINUEDO 60 J = 1, ILODO 50 I = 1, NA( I, J ) = ZERO50 CONTINUEA( J, J ) = ONE60 CONTINUEDO 80 J = IHI + 1, NDO 70 I = 1, NA( I, J ) = ZERO70 CONTINUEA( J, J ) = ONE80 CONTINUE*IF( NH.GT.0 ) THEN** Generate Q(ilo+1:ihi,ilo+1:ihi)*CALL DORGQR( NH, NH, NH, A( ILO+1, ILO+1 ), LDA, TAU( ILO ),$ WORK, LWORK, IINFO )END IFWORK( 1 ) = LWKOPTRETURN** End of DORGHR*ENDSUBROUTINE DORGL2( M, N, K, A, LDA, TAU, WORK, INFO )** -- LAPACK routine (version 3.0) --* Univ. of Tennessee, Univ. of California Berkeley, NAG Ltd.,* Courant Institute, Argonne National Lab, and Rice University* June 30, 1999** .. Scalar Arguments ..INTEGER INFO, K, LDA, M, N* ..* .. Array Arguments ..DOUBLE PRECISION A( LDA, * ), TAU( * ), WORK( * )* ..** Purpose* =======** DORGL2 generates an m by n real matrix Q with orthonormal rows,* which is defined as the first m rows of a product of k elementary* reflectors of order n** Q = H(k) . . . H(2) H(1)** as returned by DGELQF.** 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. N >= M.** K (input) INTEGER* The number of elementary reflectors whose product defines the* matrix Q. M >= K >= 0.** A (input/output) DOUBLE PRECISION array, dimension (LDA,N)* On entry, the i-th row must contain the vector which defines* the elementary reflector H(i), for i = 1,2,...,k, as returned* by DGELQF in the first k rows 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 DGELQF.** WORK (workspace) DOUBLE PRECISION array, dimension (M)** INFO (output) INTEGER* = 0: successful exit* < 0: if INFO = -i, the i-th argument has an illegal value** =====================================================================** .. Parameters ..DOUBLE PRECISION ONE, ZEROPARAMETER ( 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 = 0IF( M.LT.0 ) THENINFO = -1ELSE IF( N.LT.M ) THENINFO = -2ELSE IF( K.LT.0 .OR. K.GT.M ) THENINFO = -3ELSE IF( LDA.LT.MAX( 1, M ) ) THENINFO = -5END IFIF( INFO.NE.0 ) THENCALL XERBLA( 'DORGL2', -INFO )RETURNEND IF** Quick return if possible*IF( M.LE.0 )$ RETURN*IF( K.LT.M ) THEN** Initialise rows k+1:m to rows of the unit matrix*DO 20 J = 1, NDO 10 L = K + 1, MA( L, J ) = ZERO10 CONTINUEIF( J.GT.K .AND. J.LE.M )$ A( J, J ) = ONE20 CONTINUEEND IF*DO 40 I = K, 1, -1** Apply H(i) to A(i:m,i:n) from the right*IF( I.LT.N ) THENIF( I.LT.M ) THENA( I, I ) = ONECALL DLARF( 'Right', M-I, N-I+1, A( I, I ), LDA,$ TAU( I ), A( I+1, I ), LDA, WORK )END IFCALL DSCAL( N-I, -TAU( I ), A( I, I+1 ), LDA )END IFA( I, I ) = ONE - TAU( I )** Set A(i,1:i-1) to zero*DO 30 L = 1, I - 1A( I, L ) = ZERO30 CONTINUE40 CONTINUERETURN** End of DORGL2*ENDSUBROUTINE DORGLQ( M, N, K, A, LDA, TAU, WORK, LWORK, INFO )** -- LAPACK routine (version 3.0) --* Univ. of Tennessee, Univ. of California Berkeley, NAG Ltd.,* Courant Institute, Argonne National Lab, and Rice University* June 30, 1999** .. Scalar Arguments ..INTEGER INFO, K, LDA, LWORK, M, N* ..* .. Array Arguments ..DOUBLE PRECISION A( LDA, * ), TAU( * ), WORK( * )* ..** Purpose* =======** DORGLQ generates an M-by-N real matrix Q with orthonormal rows,* which is defined as the first M rows of a product of K elementary* reflectors of order N** Q = H(k) . . . H(2) H(1)** as returned by DGELQF.** 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. N >= M.** K (input) INTEGER* The number of elementary reflectors whose product defines the* matrix Q. M >= K >= 0.** A (input/output) DOUBLE PRECISION array, dimension (LDA,N)* On entry, the i-th row must contain the vector which defines* the elementary reflector H(i), for i = 1,2,...,k, as returned* by DGELQF in the first k rows 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 DGELQF.** WORK (workspace/output) 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,M).* For optimum performance LWORK >= M*NB, where NB is* the optimal blocksize.** If LWORK = -1, then a workspace query is assumed; the routine* only calculates the optimal size of the WORK array, returns* this value as the first entry of the WORK array, and no error* message related to LWORK is issued by XERBLA.** INFO (output) INTEGER* = 0: successful exit* < 0: if INFO = -i, the i-th argument has an illegal value** =====================================================================** .. Parameters ..DOUBLE PRECISION ZEROPARAMETER ( ZERO = 0.0D+0 )* ..* .. Local Scalars ..LOGICAL LQUERYINTEGER I, IB, IINFO, IWS, J, KI, KK, L, LDWORK,$ LWKOPT, NB, NBMIN, NX* ..* .. External Subroutines ..EXTERNAL DLARFB, DLARFT, DORGL2, XERBLA* ..* .. Intrinsic Functions ..INTRINSIC MAX, MIN* ..* .. External Functions ..INTEGER ILAENVEXTERNAL ILAENV* ..* .. Executable Statements ..** Test the input arguments*INFO = 0NB = ILAENV( 1, 'DORGLQ', ' ', M, N, K, -1 )LWKOPT = MAX( 1, M )*NBWORK( 1 ) = LWKOPTLQUERY = ( LWORK.EQ.-1 )IF( M.LT.0 ) THENINFO = -1ELSE IF( N.LT.M ) THENINFO = -2ELSE IF( K.LT.0 .OR. K.GT.M ) THENINFO = -3ELSE IF( LDA.LT.MAX( 1, M ) ) THENINFO = -5ELSE IF( LWORK.LT.MAX( 1, M ) .AND. .NOT.LQUERY ) THENINFO = -8END IFIF( INFO.NE.0 ) THENCALL XERBLA( 'DORGLQ', -INFO )RETURNELSE IF( LQUERY ) THENRETURNEND IF** Quick return if possible*IF( M.LE.0 ) THENWORK( 1 ) = 1RETURNEND IF*NBMIN = 2NX = 0IWS = MIF( NB.GT.1 .AND. NB.LT.K ) THEN** Determine when to cross over from blocked to unblocked code.*NX = MAX( 0, ILAENV( 3, 'DORGLQ', ' ', M, N, K, -1 ) )IF( NX.LT.K ) THEN** Determine if workspace is large enough for blocked code.*LDWORK = MIWS = LDWORK*NBIF( LWORK.LT.IWS ) THEN** Not enough workspace to use optimal NB: reduce NB and* determine the minimum value of NB.*NB = LWORK / LDWORKNBMIN = MAX( 2, ILAENV( 2, 'DORGLQ', ' ', M, N, K, -1 ) )END IFEND IFEND IF*IF( NB.GE.NBMIN .AND. NB.LT.K .AND. NX.LT.K ) THEN** Use blocked code after the last block.* The first kk rows are handled by the block method.*KI = ( ( K-NX-1 ) / NB )*NBKK = MIN( K, KI+NB )** Set A(kk+1:m,1:kk) to zero.*DO 20 J = 1, KKDO 10 I = KK + 1, MA( I, J ) = ZERO10 CONTINUE20 CONTINUEELSEKK = 0END IF** Use unblocked code for the last or only block.*IF( KK.LT.M )$ CALL DORGL2( 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, -NBIB = MIN( NB, K-I+1 )IF( I+IB.LE.M ) THEN** Form the triangular factor of the block reflector* H = H(i) H(i+1) . . . H(i+ib-1)*CALL DLARFT( 'Forward', 'Rowwise', N-I+1, IB, A( I, I ),$ LDA, TAU( I ), WORK, LDWORK )** Apply H' to A(i+ib:m,i:n) from the right*CALL DLARFB( 'Right', 'Transpose', 'Forward', 'Rowwise',$ M-I-IB+1, N-I+1, IB, A( I, I ), LDA, WORK,$ LDWORK, A( I+IB, I ), LDA, WORK( IB+1 ),$ LDWORK )END IF** Apply H' to columns i:n of current block*CALL DORGL2( IB, N-I+1, IB, A( I, I ), LDA, TAU( I ), WORK,$ IINFO )** Set columns 1:i-1 of current block to zero*DO 40 J = 1, I - 1DO 30 L = I, I + IB - 1A( L, J ) = ZERO30 CONTINUE40 CONTINUE50 CONTINUEEND IF*WORK( 1 ) = IWSRETURN** End of DORGLQ*ENDSUBROUTINE DORGQL( M, N, K, A, LDA, TAU, WORK, LWORK, INFO )** -- LAPACK routine (version 3.0) --* Univ. of Tennessee, Univ. of California Berkeley, NAG Ltd.,* Courant Institute, Argonne National Lab, and Rice University* June 30, 1999** .. Scalar Arguments ..INTEGER INFO, K, LDA, LWORK, M, N* ..* .. Array Arguments ..DOUBLE PRECISION A( LDA, * ), TAU( * ), WORK( * )* ..** 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/output) 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.** If LWORK = -1, then a workspace query is assumed; the routine* only calculates the optimal size of the WORK array, returns* this value as the first entry of the WORK array, and no error* message related to LWORK is issued by XERBLA.** INFO (output) INTEGER* = 0: successful exit* < 0: if INFO = -i, the i-th argument has an illegal value** =====================================================================** .. Parameters ..DOUBLE PRECISION ZEROPARAMETER ( ZERO = 0.0D+0 )* ..* .. Local Scalars ..LOGICAL LQUERYINTEGER I, IB, IINFO, IWS, J, KK, L, LDWORK, LWKOPT,$ NB, NBMIN, NX* ..* .. External Subroutines ..EXTERNAL DLARFB, DLARFT, DORG2L, XERBLA* ..* .. Intrinsic Functions ..INTRINSIC MAX, MIN* ..* .. External Functions ..INTEGER ILAENVEXTERNAL ILAENV* ..* .. Executable Statements ..** Test the input arguments*INFO = 0NB = ILAENV( 1, 'DORGQL', ' ', M, N, K, -1 )LWKOPT = MAX( 1, N )*NBWORK( 1 ) = LWKOPTLQUERY = ( LWORK.EQ.-1 )IF( M.LT.0 ) THENINFO = -1ELSE IF( N.LT.0 .OR. N.GT.M ) THENINFO = -2ELSE IF( K.LT.0 .OR. K.GT.N ) THENINFO = -3ELSE IF( LDA.LT.MAX( 1, M ) ) THENINFO = -5ELSE IF( LWORK.LT.MAX( 1, N ) .AND. .NOT.LQUERY ) THENINFO = -8END IFIF( INFO.NE.0 ) THENCALL XERBLA( 'DORGQL', -INFO )RETURNELSE IF( LQUERY ) THENRETURNEND IF** Quick return if possible*IF( N.LE.0 ) THENWORK( 1 ) = 1RETURNEND IF*NBMIN = 2NX = 0IWS = NIF( 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 = NIWS = LDWORK*NBIF( LWORK.LT.IWS ) THEN** Not enough workspace to use optimal NB: reduce NB and* determine the minimum value of NB.*NB = LWORK / LDWORKNBMIN = MAX( 2, ILAENV( 2, 'DORGQL', ' ', M, N, K, -1 ) )END IFEND IFEND 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 - KKDO 10 I = M - KK + 1, MA( I, J ) = ZERO10 CONTINUE20 CONTINUEELSEKK = 0END 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, NBIB = 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 - 1DO 30 L = M - K + I + IB, MA( L, J ) = ZERO30 CONTINUE40 CONTINUE50 CONTINUEEND IF*WORK( 1 ) = IWSRETURN** End of DORGQL*ENDSUBROUTINE DORGQR( M, N, K, A, LDA, TAU, WORK, LWORK, INFO )** -- LAPACK routine (version 3.0) --* Univ. of Tennessee, Univ. of California Berkeley, NAG Ltd.,* Courant Institute, Argonne National Lab, and Rice University* June 30, 1999** .. Scalar Arguments ..INTEGER INFO, K, LDA, LWORK, M, N* ..* .. Array Arguments ..DOUBLE PRECISION A( LDA, * ), TAU( * ), WORK( * )* ..** 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/output) 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.** If LWORK = -1, then a workspace query is assumed; the routine* only calculates the optimal size of the WORK array, returns* this value as the first entry of the WORK array, and no error* message related to LWORK is issued by XERBLA.** INFO (output) INTEGER* = 0: successful exit* < 0: if INFO = -i, the i-th argument has an illegal value** =====================================================================** .. Parameters ..DOUBLE PRECISION ZEROPARAMETER ( ZERO = 0.0D+0 )* ..* .. Local Scalars ..LOGICAL LQUERYINTEGER I, IB, IINFO, IWS, J, KI, KK, L, LDWORK,$ LWKOPT, NB, NBMIN, NX* ..* .. External Subroutines ..EXTERNAL DLARFB, DLARFT, DORG2R, XERBLA* ..* .. Intrinsic Functions ..INTRINSIC MAX, MIN* ..* .. External Functions ..INTEGER ILAENVEXTERNAL ILAENV* ..* .. Executable Statements ..** Test the input arguments*INFO = 0NB = ILAENV( 1, 'DORGQR', ' ', M, N, K, -1 )LWKOPT = MAX( 1, N )*NBWORK( 1 ) = LWKOPTLQUERY = ( LWORK.EQ.-1 )IF( M.LT.0 ) THENINFO = -1ELSE IF( N.LT.0 .OR. N.GT.M ) THENINFO = -2ELSE IF( K.LT.0 .OR. K.GT.N ) THENINFO = -3ELSE IF( LDA.LT.MAX( 1, M ) ) THENINFO = -5ELSE IF( LWORK.LT.MAX( 1, N ) .AND. .NOT.LQUERY ) THENINFO = -8END IFIF( INFO.NE.0 ) THENCALL XERBLA( 'DORGQR', -INFO )RETURNELSE IF( LQUERY ) THENRETURNEND IF** Quick return if possible*IF( N.LE.0 ) THENWORK( 1 ) = 1RETURNEND IF*NBMIN = 2NX = 0IWS = NIF( 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 = NIWS = LDWORK*NBIF( LWORK.LT.IWS ) THEN** Not enough workspace to use optimal NB: reduce NB and* determine the minimum value of NB.*NB = LWORK / LDWORKNBMIN = MAX( 2, ILAENV( 2, 'DORGQR', ' ', M, N, K, -1 ) )END IFEND IFEND 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 )*NBKK = MIN( K, KI+NB )** Set A(1:kk,kk+1:n) to zero.*DO 20 J = KK + 1, NDO 10 I = 1, KKA( I, J ) = ZERO10 CONTINUE20 CONTINUEELSEKK = 0END 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, -NBIB = 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 - 1DO 30 L = 1, I - 1A( L, J ) = ZERO30 CONTINUE40 CONTINUE50 CONTINUEEND IF*WORK( 1 ) = IWSRETURN** End of DORGQR*ENDSUBROUTINE DORGR2( M, N, K, A, LDA, TAU, WORK, INFO )** -- LAPACK routine (version 3.0) --* 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* =======** DORGR2 generates an m by n real matrix Q with orthonormal rows,* which is defined as the last m rows of a product of k elementary* reflectors of order n** Q = H(1) H(2) . . . H(k)** as returned by DGERQF.** 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. N >= M.** K (input) INTEGER* The number of elementary reflectors whose product defines the* matrix Q. M >= K >= 0.** A (input/output) DOUBLE PRECISION array, dimension (LDA,N)* On entry, the (m-k+i)-th row must contain the vector which* defines the elementary reflector H(i), for i = 1,2,...,k, as* returned by DGERQF in the last k rows 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 DGERQF.** WORK (workspace) DOUBLE PRECISION array, dimension (M)** INFO (output) INTEGER* = 0: successful exit* < 0: if INFO = -i, the i-th argument has an illegal value** =====================================================================** .. Parameters ..DOUBLE PRECISION ONE, ZEROPARAMETER ( 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 = 0IF( M.LT.0 ) THENINFO = -1ELSE IF( N.LT.M ) THENINFO = -2ELSE IF( K.LT.0 .OR. K.GT.M ) THENINFO = -3ELSE IF( LDA.LT.MAX( 1, M ) ) THENINFO = -5END IFIF( INFO.NE.0 ) THENCALL XERBLA( 'DORGR2', -INFO )RETURNEND IF** Quick return if possible*IF( M.LE.0 )$ RETURN*IF( K.LT.M ) THEN** Initialise rows 1:m-k to rows of the unit matrix*DO 20 J = 1, NDO 10 L = 1, M - KA( L, J ) = ZERO10 CONTINUEIF( J.GT.N-M .AND. J.LE.N-K )$ A( M-N+J, J ) = ONE20 CONTINUEEND IF*DO 40 I = 1, KII = M - K + I** Apply H(i) to A(1:m-k+i,1:n-k+i) from the right*A( II, N-M+II ) = ONECALL DLARF( 'Right', II-1, N-M+II, A( II, 1 ), LDA, TAU( I ),$ A, LDA, WORK )CALL DSCAL( N-M+II-1, -TAU( I ), A( II, 1 ), LDA )A( II, N-M+II ) = ONE - TAU( I )** Set A(m-k+i,n-k+i+1:n) to zero*DO 30 L = N - M + II + 1, NA( II, L ) = ZERO30 CONTINUE40 CONTINUERETURN** End of DORGR2*ENDSUBROUTINE DORGRQ( M, N, K, A, LDA, TAU, WORK, LWORK, INFO )** -- LAPACK routine (version 3.0) --* Univ. of Tennessee, Univ. of California Berkeley, NAG Ltd.,* Courant Institute, Argonne National Lab, and Rice University* June 30, 1999** .. Scalar Arguments ..INTEGER INFO, K, LDA, LWORK, M, N* ..* .. Array Arguments ..DOUBLE PRECISION A( LDA, * ), TAU( * ), WORK( * )* ..** Purpose* =======** DORGRQ generates an M-by-N real matrix Q with orthonormal rows,* which is defined as the last M rows of a product of K elementary* reflectors of order N** Q = H(1) H(2) . . . H(k)** as returned by DGERQF.** 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. N >= M.** K (input) INTEGER* The number of elementary reflectors whose product defines the* matrix Q. M >= K >= 0.** A (input/output) DOUBLE PRECISION array, dimension (LDA,N)* On entry, the (m-k+i)-th row must contain the vector which* defines the elementary reflector H(i), for i = 1,2,...,k, as* returned by DGERQF in the last k rows 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 DGERQF.** WORK (workspace/output) 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,M).* For optimum performance LWORK >= M*NB, where NB is the* optimal blocksize.** If LWORK = -1, then a workspace query is assumed; the routine* only calculates the optimal size of the WORK array, returns* this value as the first entry of the WORK array, and no error* message related to LWORK is issued by XERBLA.** INFO (output) INTEGER* = 0: successful exit* < 0: if INFO = -i, the i-th argument has an illegal value** =====================================================================** .. Parameters ..DOUBLE PRECISION ZEROPARAMETER ( ZERO = 0.0D+0 )* ..* .. Local Scalars ..LOGICAL LQUERYINTEGER I, IB, II, IINFO, IWS, J, KK, L, LDWORK,$ LWKOPT, NB, NBMIN, NX* ..* .. External Subroutines ..EXTERNAL DLARFB, DLARFT, DORGR2, XERBLA* ..* .. Intrinsic Functions ..INTRINSIC MAX, MIN* ..* .. External Functions ..INTEGER ILAENVEXTERNAL ILAENV* ..* .. Executable Statements ..** Test the input arguments*INFO = 0NB = ILAENV( 1, 'DORGRQ', ' ', M, N, K, -1 )LWKOPT = MAX( 1, M )*NBWORK( 1 ) = LWKOPTLQUERY = ( LWORK.EQ.-1 )IF( M.LT.0 ) THENINFO = -1ELSE IF( N.LT.M ) THENINFO = -2ELSE IF( K.LT.0 .OR. K.GT.M ) THENINFO = -3ELSE IF( LDA.LT.MAX( 1, M ) ) THENINFO = -5ELSE IF( LWORK.LT.MAX( 1, M ) .AND. .NOT.LQUERY ) THENINFO = -8END IFIF( INFO.NE.0 ) THENCALL XERBLA( 'DORGRQ', -INFO )RETURNELSE IF( LQUERY ) THENRETURNEND IF** Quick return if possible*IF( M.LE.0 ) THENWORK( 1 ) = 1RETURNEND IF*NBMIN = 2NX = 0IWS = MIF( NB.GT.1 .AND. NB.LT.K ) THEN** Determine when to cross over from blocked to unblocked code.*NX = MAX( 0, ILAENV( 3, 'DORGRQ', ' ', M, N, K, -1 ) )IF( NX.LT.K ) THEN** Determine if workspace is large enough for blocked code.*LDWORK = MIWS = LDWORK*NBIF( LWORK.LT.IWS ) THEN** Not enough workspace to use optimal NB: reduce NB and* determine the minimum value of NB.*NB = LWORK / LDWORKNBMIN = MAX( 2, ILAENV( 2, 'DORGRQ', ' ', M, N, K, -1 ) )END IFEND IFEND IF*IF( NB.GE.NBMIN .AND. NB.LT.K .AND. NX.LT.K ) THEN** Use blocked code after the first block.* The last kk rows are handled by the block method.*KK = MIN( K, ( ( K-NX+NB-1 ) / NB )*NB )** Set A(1:m-kk,n-kk+1:n) to zero.*DO 20 J = N - KK + 1, NDO 10 I = 1, M - KKA( I, J ) = ZERO10 CONTINUE20 CONTINUEELSEKK = 0END IF** Use unblocked code for the first or only block.*CALL DORGR2( 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, NBIB = MIN( NB, K-I+1 )II = M - K + IIF( II.GT.1 ) THEN** Form the triangular factor of the block reflector* H = H(i+ib-1) . . . H(i+1) H(i)*CALL DLARFT( 'Backward', 'Rowwise', N-K+I+IB-1, IB,$ A( II, 1 ), LDA, TAU( I ), WORK, LDWORK )** Apply H' to A(1:m-k+i-1,1:n-k+i+ib-1) from the right*CALL DLARFB( 'Right', 'Transpose', 'Backward', 'Rowwise',$ II-1, N-K+I+IB-1, IB, A( II, 1 ), LDA, WORK,$ LDWORK, A, LDA, WORK( IB+1 ), LDWORK )END IF** Apply H' to columns 1:n-k+i+ib-1 of current block*CALL DORGR2( IB, N-K+I+IB-1, IB, A( II, 1 ), LDA, TAU( I ),$ WORK, IINFO )** Set columns n-k+i+ib:n of current block to zero*DO 40 L = N - K + I + IB, NDO 30 J = II, II + IB - 1A( J, L ) = ZERO30 CONTINUE40 CONTINUE50 CONTINUEEND IF*WORK( 1 ) = IWSRETURN** End of DORGRQ*ENDSUBROUTINE DORGTR( UPLO, N, A, LDA, TAU, WORK, LWORK, INFO )** -- LAPACK routine (version 3.0) --* Univ. of Tennessee, Univ. of California Berkeley, NAG Ltd.,* Courant Institute, Argonne National Lab, and Rice University* June 30, 1999** .. Scalar Arguments ..CHARACTER UPLOINTEGER INFO, LDA, LWORK, N* ..* .. Array Arguments ..DOUBLE PRECISION A( LDA, * ), TAU( * ), WORK( * )* ..** 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/output) 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.** If LWORK = -1, then a workspace query is assumed; the routine* only calculates the optimal size of the WORK array, returns* this value as the first entry of the WORK array, and no error* message related to LWORK is issued by XERBLA.** INFO (output) INTEGER* = 0: successful exit* < 0: if INFO = -i, the i-th argument had an illegal value** =====================================================================** .. Parameters ..DOUBLE PRECISION ZERO, ONEPARAMETER ( ZERO = 0.0D+0, ONE = 1.0D+0 )* ..* .. Local Scalars ..LOGICAL LQUERY, UPPERINTEGER I, IINFO, J, LWKOPT, NB* ..* .. External Functions ..LOGICAL LSAMEINTEGER ILAENVEXTERNAL LSAME, ILAENV* ..* .. External Subroutines ..EXTERNAL DORGQL, DORGQR, XERBLA* ..* .. Intrinsic Functions ..INTRINSIC MAX* ..* .. Executable Statements ..** Test the input arguments*INFO = 0LQUERY = ( LWORK.EQ.-1 )UPPER = LSAME( UPLO, 'U' )IF( .NOT.UPPER .AND. .NOT.LSAME( UPLO, 'L' ) ) THENINFO = -1ELSE IF( N.LT.0 ) THENINFO = -2ELSE IF( LDA.LT.MAX( 1, N ) ) THENINFO = -4ELSE IF( LWORK.LT.MAX( 1, N-1 ) .AND. .NOT.LQUERY ) THENINFO = -7END IF*IF( INFO.EQ.0 ) THENIF( UPPER ) THENNB = ILAENV( 1, 'DORGQL', ' ', N-1, N-1, N-1, -1 )ELSENB = ILAENV( 1, 'DORGQR', ' ', N-1, N-1, N-1, -1 )END IFLWKOPT = MAX( 1, N-1 )*NBWORK( 1 ) = LWKOPTEND IF*IF( INFO.NE.0 ) THENCALL XERBLA( 'DORGTR', -INFO )RETURNELSE IF( LQUERY ) THENRETURNEND IF** Quick return if possible*IF( N.EQ.0 ) THENWORK( 1 ) = 1RETURNEND 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 - 1DO 10 I = 1, J - 1A( I, J ) = A( I, J+1 )10 CONTINUEA( N, J ) = ZERO20 CONTINUEDO 30 I = 1, N - 1A( I, N ) = ZERO30 CONTINUEA( 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, -1A( 1, J ) = ZERODO 40 I = J + 1, NA( I, J ) = A( I, J-1 )40 CONTINUE50 CONTINUEA( 1, 1 ) = ONEDO 60 I = 2, NA( I, 1 ) = ZERO60 CONTINUEIF( 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 IFEND IFWORK( 1 ) = LWKOPTRETURN** End of DORGTR*ENDSUBROUTINE DORM2L( SIDE, TRANS, M, N, K, A, LDA, TAU, C, LDC,$ WORK, INFO )** -- LAPACK routine (version 3.0) --* Univ. of Tennessee, Univ. of California Berkeley, NAG Ltd.,* Courant Institute, Argonne National Lab, and Rice University* February 29, 1992** .. Scalar Arguments ..CHARACTER SIDE, TRANSINTEGER 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 ONEPARAMETER ( ONE = 1.0D+0 )* ..* .. Local Scalars ..LOGICAL LEFT, NOTRANINTEGER I, I1, I2, I3, MI, NI, NQDOUBLE PRECISION AII* ..* .. External Functions ..LOGICAL LSAMEEXTERNAL LSAME* ..* .. External Subroutines ..EXTERNAL DLARF, XERBLA* ..* .. Intrinsic Functions ..INTRINSIC MAX* ..* .. Executable Statements ..** Test the input arguments*INFO = 0LEFT = LSAME( SIDE, 'L' )NOTRAN = LSAME( TRANS, 'N' )** NQ is the order of Q*IF( LEFT ) THENNQ = MELSENQ = NEND IFIF( .NOT.LEFT .AND. .NOT.LSAME( SIDE, 'R' ) ) THENINFO = -1ELSE IF( .NOT.NOTRAN .AND. .NOT.LSAME( TRANS, 'T' ) ) THENINFO = -2ELSE IF( M.LT.0 ) THENINFO = -3ELSE IF( N.LT.0 ) THENINFO = -4ELSE IF( K.LT.0 .OR. K.GT.NQ ) THENINFO = -5ELSE IF( LDA.LT.MAX( 1, NQ ) ) THENINFO = -7ELSE IF( LDC.LT.MAX( 1, M ) ) THENINFO = -10END IFIF( INFO.NE.0 ) THENCALL XERBLA( 'DORM2L', -INFO )RETURNEND 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 ) )$ THENI1 = 1I2 = KI3 = 1ELSEI1 = KI2 = 1I3 = -1END IF*IF( LEFT ) THENNI = NELSEMI = MEND IF*DO 10 I = I1, I2, I3IF( LEFT ) THEN** H(i) is applied to C(1:m-k+i,1:n)*MI = M - K + IELSE** H(i) is applied to C(1:m,1:n-k+i)*NI = N - K + IEND IF** Apply H(i)*AII = A( NQ-K+I, I )A( NQ-K+I, I ) = ONECALL DLARF( SIDE, MI, NI, A( 1, I ), 1, TAU( I ), C, LDC,$ WORK )A( NQ-K+I, I ) = AII10 CONTINUERETURN** End of DORM2L*ENDSUBROUTINE DORM2R( SIDE, TRANS, M, N, K, A, LDA, TAU, C, LDC,$ WORK, INFO )** -- LAPACK routine (version 3.0) --* Univ. of Tennessee, Univ. of California Berkeley, NAG Ltd.,* Courant Institute, Argonne National Lab, and Rice University* February 29, 1992** .. Scalar Arguments ..CHARACTER SIDE, TRANSINTEGER 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 ONEPARAMETER ( ONE = 1.0D+0 )* ..* .. Local Scalars ..LOGICAL LEFT, NOTRANINTEGER I, I1, I2, I3, IC, JC, MI, NI, NQDOUBLE PRECISION AII* ..* .. External Functions ..LOGICAL LSAMEEXTERNAL LSAME* ..* .. External Subroutines ..EXTERNAL DLARF, XERBLA* ..* .. Intrinsic Functions ..INTRINSIC MAX* ..* .. Executable Statements ..** Test the input arguments*INFO = 0LEFT = LSAME( SIDE, 'L' )NOTRAN = LSAME( TRANS, 'N' )** NQ is the order of Q*IF( LEFT ) THENNQ = MELSENQ = NEND IFIF( .NOT.LEFT .AND. .NOT.LSAME( SIDE, 'R' ) ) THENINFO = -1ELSE IF( .NOT.NOTRAN .AND. .NOT.LSAME( TRANS, 'T' ) ) THENINFO = -2ELSE IF( M.LT.0 ) THENINFO = -3ELSE IF( N.LT.0 ) THENINFO = -4ELSE IF( K.LT.0 .OR. K.GT.NQ ) THENINFO = -5ELSE IF( LDA.LT.MAX( 1, NQ ) ) THENINFO = -7ELSE IF( LDC.LT.MAX( 1, M ) ) THENINFO = -10END IFIF( INFO.NE.0 ) THENCALL XERBLA( 'DORM2R', -INFO )RETURNEND 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 ) )$ THENI1 = 1I2 = KI3 = 1ELSEI1 = KI2 = 1I3 = -1END IF*IF( LEFT ) THENNI = NJC = 1ELSEMI = MIC = 1END IF*DO 10 I = I1, I2, I3IF( LEFT ) THEN** H(i) is applied to C(i:m,1:n)*MI = M - I + 1IC = IELSE** H(i) is applied to C(1:m,i:n)*NI = N - I + 1JC = IEND IF** Apply H(i)*AII = A( I, I )A( I, I ) = ONECALL DLARF( SIDE, MI, NI, A( I, I ), 1, TAU( I ), C( IC, JC ),$ LDC, WORK )A( I, I ) = AII10 CONTINUERETURN** End of DORM2R*ENDSUBROUTINE DORMBR( VECT, SIDE, TRANS, M, N, K, A, LDA, TAU, C,$ LDC, WORK, LWORK, INFO )** -- LAPACK routine (version 3.0) --* Univ. of Tennessee, Univ. of California Berkeley, NAG Ltd.,* Courant Institute, Argonne National Lab, and Rice University* June 30, 1999** .. Scalar Arguments ..CHARACTER SIDE, TRANS, VECTINTEGER INFO, K, LDA, LDC, LWORK, M, N* ..* .. Array Arguments ..DOUBLE PRECISION A( LDA, * ), C( LDC, * ), TAU( * ), WORK( * )* ..** Purpose* =======** If VECT = 'Q', DORMBR 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** If VECT = 'P', DORMBR overwrites the general real M-by-N matrix C* with* SIDE = 'L' SIDE = 'R'* TRANS = 'N': P * C C * P* TRANS = 'T': P**T * C C * P**T** Here Q and P**T are the orthogonal matrices determined by DGEBRD when* reducing a real matrix A to bidiagonal form: A = Q * B * P**T. Q and* P**T are defined as products of elementary reflectors H(i) and G(i)* respectively.** Let nq = m if SIDE = 'L' and nq = n if SIDE = 'R'. Thus nq is the* order of the orthogonal matrix Q or P**T that is applied.** If VECT = 'Q', A is assumed to have been an NQ-by-K matrix:* if nq >= k, Q = H(1) H(2) . . . H(k);* if nq < k, Q = H(1) H(2) . . . H(nq-1).** If VECT = 'P', A is assumed to have been a K-by-NQ matrix:* if k < nq, P = G(1) G(2) . . . G(k);* if k >= nq, P = G(1) G(2) . . . G(nq-1).** Arguments* =========** VECT (input) CHARACTER*1* = 'Q': apply Q or Q**T;* = 'P': apply P or P**T.** SIDE (input) CHARACTER*1* = 'L': apply Q, Q**T, P or P**T from the Left;* = 'R': apply Q, Q**T, P or P**T from the Right.** TRANS (input) CHARACTER*1* = 'N': No transpose, apply Q or P;* = 'T': Transpose, apply Q**T or P**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* If VECT = 'Q', the number of columns in the original* matrix reduced by DGEBRD.* If VECT = 'P', the number of rows in the original* matrix reduced by DGEBRD.* K >= 0.** A (input) DOUBLE PRECISION array, dimension* (LDA,min(nq,K)) if VECT = 'Q'* (LDA,nq) if VECT = 'P'* The vectors which define the elementary reflectors H(i) and* G(i), whose products determine the matrices Q and P, as* returned by DGEBRD.** LDA (input) INTEGER* The leading dimension of the array A.* If VECT = 'Q', LDA >= max(1,nq);* if VECT = 'P', LDA >= max(1,min(nq,K)).** TAU (input) DOUBLE PRECISION array, dimension (min(nq,K))* TAU(i) must contain the scalar factor of the elementary* reflector H(i) or G(i) which determines Q or P, as returned* by DGEBRD in the array argument TAUQ or TAUP.** 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* or P*C or P**T*C or C*P or C*P**T.** LDC (input) INTEGER* The leading dimension of the array C. LDC >= max(1,M).** WORK (workspace/output) 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.** If LWORK = -1, then a workspace query is assumed; the routine* only calculates the optimal size of the WORK array, returns* this value as the first entry of the WORK array, and no error* message related to LWORK is issued by XERBLA.** INFO (output) INTEGER* = 0: successful exit* < 0: if INFO = -i, the i-th argument had an illegal value** =====================================================================** .. Local Scalars ..LOGICAL APPLYQ, LEFT, LQUERY, NOTRANCHARACTER TRANSTINTEGER I1, I2, IINFO, LWKOPT, MI, NB, NI, NQ, NW* ..* .. External Functions ..LOGICAL LSAMEINTEGER ILAENVEXTERNAL LSAME, ILAENV* ..* .. External Subroutines ..EXTERNAL DORMLQ, DORMQR, XERBLA* ..* .. Intrinsic Functions ..INTRINSIC MAX, MIN* ..* .. Executable Statements ..** Test the input arguments*INFO = 0APPLYQ = LSAME( VECT, 'Q' )LEFT = LSAME( SIDE, 'L' )NOTRAN = LSAME( TRANS, 'N' )LQUERY = ( LWORK.EQ.-1 )** NQ is the order of Q or P and NW is the minimum dimension of WORK*IF( LEFT ) THENNQ = MNW = NELSENQ = NNW = MEND IFIF( .NOT.APPLYQ .AND. .NOT.LSAME( VECT, 'P' ) ) THENINFO = -1ELSE IF( .NOT.LEFT .AND. .NOT.LSAME( SIDE, 'R' ) ) THENINFO = -2ELSE IF( .NOT.NOTRAN .AND. .NOT.LSAME( TRANS, 'T' ) ) THENINFO = -3ELSE IF( M.LT.0 ) THENINFO = -4ELSE IF( N.LT.0 ) THENINFO = -5ELSE IF( K.LT.0 ) THENINFO = -6ELSE IF( ( APPLYQ .AND. LDA.LT.MAX( 1, NQ ) ) .OR.$ ( .NOT.APPLYQ .AND. LDA.LT.MAX( 1, MIN( NQ, K ) ) ) )$ THENINFO = -8ELSE IF( LDC.LT.MAX( 1, M ) ) THENINFO = -11ELSE IF( LWORK.LT.MAX( 1, NW ) .AND. .NOT.LQUERY ) THENINFO = -13END IF*IF( INFO.EQ.0 ) THENIF( APPLYQ ) THENIF( LEFT ) THENNB = ILAENV( 1, 'DORMQR', SIDE // TRANS, M-1, N, M-1,$ -1 )ELSENB = ILAENV( 1, 'DORMQR', SIDE // TRANS, M, N-1, N-1,$ -1 )END IFELSEIF( LEFT ) THENNB = ILAENV( 1, 'DORMLQ', SIDE // TRANS, M-1, N, M-1,$ -1 )ELSENB = ILAENV( 1, 'DORMLQ', SIDE // TRANS, M, N-1, N-1,$ -1 )END IFEND IFLWKOPT = MAX( 1, NW )*NBWORK( 1 ) = LWKOPTEND IF*IF( INFO.NE.0 ) THENCALL XERBLA( 'DORMBR', -INFO )RETURNELSE IF( LQUERY ) THENRETURNEND IF** Quick return if possible*WORK( 1 ) = 1IF( M.EQ.0 .OR. N.EQ.0 )$ RETURN*IF( APPLYQ ) THEN** Apply Q*IF( NQ.GE.K ) THEN** Q was determined by a call to DGEBRD with nq >= k*CALL DORMQR( SIDE, TRANS, M, N, K, A, LDA, TAU, C, LDC,$ WORK, LWORK, IINFO )ELSE IF( NQ.GT.1 ) THEN** Q was determined by a call to DGEBRD with nq < k*IF( LEFT ) THENMI = M - 1NI = NI1 = 2I2 = 1ELSEMI = MNI = N - 1I1 = 1I2 = 2END IFCALL DORMQR( SIDE, TRANS, MI, NI, NQ-1, A( 2, 1 ), LDA, TAU,$ C( I1, I2 ), LDC, WORK, LWORK, IINFO )END IFELSE** Apply P*IF( NOTRAN ) THENTRANST = 'T'ELSETRANST = 'N'END IFIF( NQ.GT.K ) THEN** P was determined by a call to DGEBRD with nq > k*CALL DORMLQ( SIDE, TRANST, M, N, K, A, LDA, TAU, C, LDC,$ WORK, LWORK, IINFO )ELSE IF( NQ.GT.1 ) THEN** P was determined by a call to DGEBRD with nq <= k*IF( LEFT ) THENMI = M - 1NI = NI1 = 2I2 = 1ELSEMI = MNI = N - 1I1 = 1I2 = 2END IFCALL DORMLQ( SIDE, TRANST, MI, NI, NQ-1, A( 1, 2 ), LDA,$ TAU, C( I1, I2 ), LDC, WORK, LWORK, IINFO )END IFEND IFWORK( 1 ) = LWKOPTRETURN** End of DORMBR*ENDSUBROUTINE DORMHR( SIDE, TRANS, M, N, ILO, IHI, A, LDA, TAU, C,$ LDC, WORK, LWORK, INFO )** -- LAPACK routine (version 3.0) --* Univ. of Tennessee, Univ. of California Berkeley, NAG Ltd.,* Courant Institute, Argonne National Lab, and Rice University* June 30, 1999** .. Scalar Arguments ..CHARACTER SIDE, TRANSINTEGER IHI, ILO, INFO, LDA, LDC, LWORK, M, N* ..* .. Array Arguments ..DOUBLE PRECISION A( LDA, * ), C( LDC, * ), TAU( * ), WORK( * )* ..** Purpose* =======** DORMHR 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* IHI-ILO elementary reflectors, as returned by DGEHRD:** Q = H(ilo) H(ilo+1) . . . H(ihi-1).** 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.** ILO (input) INTEGER* IHI (input) INTEGER* ILO and IHI must have the same values as in the previous call* of DGEHRD. Q is equal to the unit matrix except in the* submatrix Q(ilo+1:ihi,ilo+1:ihi).* If SIDE = 'L', then 1 <= ILO <= IHI <= M, if M > 0, and* ILO = 1 and IHI = 0, if M = 0;* if SIDE = 'R', then 1 <= ILO <= IHI <= N, if N > 0, and* ILO = 1 and IHI = 0, if 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 DGEHRD.** 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 DGEHRD.** 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/output) 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.** If LWORK = -1, then a workspace query is assumed; the routine* only calculates the optimal size of the WORK array, returns* this value as the first entry of the WORK array, and no error* message related to LWORK is issued by XERBLA.** INFO (output) INTEGER* = 0: successful exit* < 0: if INFO = -i, the i-th argument had an illegal value** =====================================================================** .. Local Scalars ..LOGICAL LEFT, LQUERYINTEGER I1, I2, IINFO, LWKOPT, MI, NB, NH, NI, NQ, NW* ..* .. External Functions ..LOGICAL LSAMEINTEGER ILAENVEXTERNAL LSAME, ILAENV* ..* .. External Subroutines ..EXTERNAL DORMQR, XERBLA* ..* .. Intrinsic Functions ..INTRINSIC MAX, MIN* ..* .. Executable Statements ..** Test the input arguments*INFO = 0NH = IHI - ILOLEFT = LSAME( SIDE, 'L' )LQUERY = ( LWORK.EQ.-1 )** NQ is the order of Q and NW is the minimum dimension of WORK*IF( LEFT ) THENNQ = MNW = NELSENQ = NNW = MEND IFIF( .NOT.LEFT .AND. .NOT.LSAME( SIDE, 'R' ) ) THENINFO = -1ELSE IF( .NOT.LSAME( TRANS, 'N' ) .AND. .NOT.LSAME( TRANS, 'T' ) )$ THENINFO = -2ELSE IF( M.LT.0 ) THENINFO = -3ELSE IF( N.LT.0 ) THENINFO = -4ELSE IF( ILO.LT.1 .OR. ILO.GT.MAX( 1, NQ ) ) THENINFO = -5ELSE IF( IHI.LT.MIN( ILO, NQ ) .OR. IHI.GT.NQ ) THENINFO = -6ELSE IF( LDA.LT.MAX( 1, NQ ) ) THENINFO = -8ELSE IF( LDC.LT.MAX( 1, M ) ) THENINFO = -11ELSE IF( LWORK.LT.MAX( 1, NW ) .AND. .NOT.LQUERY ) THENINFO = -13END IF*IF( INFO.EQ.0 ) THENIF( LEFT ) THENNB = ILAENV( 1, 'DORMQR', SIDE // TRANS, NH, N, NH, -1 )ELSENB = ILAENV( 1, 'DORMQR', SIDE // TRANS, M, NH, NH, -1 )END IFLWKOPT = MAX( 1, NW )*NBWORK( 1 ) = LWKOPTEND IF*IF( INFO.NE.0 ) THENCALL XERBLA( 'DORMHR', -INFO )RETURNELSE IF( LQUERY ) THENRETURNEND IF** Quick return if possible*IF( M.EQ.0 .OR. N.EQ.0 .OR. NH.EQ.0 ) THENWORK( 1 ) = 1RETURNEND IF*IF( LEFT ) THENMI = NHNI = NI1 = ILO + 1I2 = 1ELSEMI = MNI = NHI1 = 1I2 = ILO + 1END IF*CALL DORMQR( SIDE, TRANS, MI, NI, NH, A( ILO+1, ILO ), LDA,$ TAU( ILO ), C( I1, I2 ), LDC, WORK, LWORK, IINFO )*WORK( 1 ) = LWKOPTRETURN** End of DORMHR*ENDSUBROUTINE DORML2( SIDE, TRANS, M, N, K, A, LDA, TAU, C, LDC,$ WORK, INFO )** -- LAPACK routine (version 3.0) --* Univ. of Tennessee, Univ. of California Berkeley, NAG Ltd.,* Courant Institute, Argonne National Lab, and Rice University* February 29, 1992** .. Scalar Arguments ..CHARACTER SIDE, TRANSINTEGER INFO, K, LDA, LDC, M, N* ..* .. Array Arguments ..DOUBLE PRECISION A( LDA, * ), C( LDC, * ), TAU( * ), WORK( * )* ..** Purpose* =======** DORML2 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 DGELQF. 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,M) if SIDE = 'L',* (LDA,N) if SIDE = 'R'* The i-th row must contain the vector which defines the* elementary reflector H(i), for i = 1,2,...,k, as returned by* DGELQF in the first k rows 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. LDA >= max(1,K).** TAU (input) DOUBLE PRECISION array, dimension (K)* TAU(i) must contain the scalar factor of the elementary* reflector H(i), as returned by DGELQF.** 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 ONEPARAMETER ( ONE = 1.0D+0 )* ..* .. Local Scalars ..LOGICAL LEFT, NOTRANINTEGER I, I1, I2, I3, IC, JC, MI, NI, NQDOUBLE PRECISION AII* ..* .. External Functions ..LOGICAL LSAMEEXTERNAL LSAME* ..* .. External Subroutines ..EXTERNAL DLARF, XERBLA* ..* .. Intrinsic Functions ..INTRINSIC MAX* ..* .. Executable Statements ..** Test the input arguments*INFO = 0LEFT = LSAME( SIDE, 'L' )NOTRAN = LSAME( TRANS, 'N' )** NQ is the order of Q*IF( LEFT ) THENNQ = MELSENQ = NEND IFIF( .NOT.LEFT .AND. .NOT.LSAME( SIDE, 'R' ) ) THENINFO = -1ELSE IF( .NOT.NOTRAN .AND. .NOT.LSAME( TRANS, 'T' ) ) THENINFO = -2ELSE IF( M.LT.0 ) THENINFO = -3ELSE IF( N.LT.0 ) THENINFO = -4ELSE IF( K.LT.0 .OR. K.GT.NQ ) THENINFO = -5ELSE IF( LDA.LT.MAX( 1, K ) ) THENINFO = -7ELSE IF( LDC.LT.MAX( 1, M ) ) THENINFO = -10END IFIF( INFO.NE.0 ) THENCALL XERBLA( 'DORML2', -INFO )RETURNEND 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 ) )$ THENI1 = 1I2 = KI3 = 1ELSEI1 = KI2 = 1I3 = -1END IF*IF( LEFT ) THENNI = NJC = 1ELSEMI = MIC = 1END IF*DO 10 I = I1, I2, I3IF( LEFT ) THEN** H(i) is applied to C(i:m,1:n)*MI = M - I + 1IC = IELSE** H(i) is applied to C(1:m,i:n)*NI = N - I + 1JC = IEND IF** Apply H(i)*AII = A( I, I )A( I, I ) = ONECALL DLARF( SIDE, MI, NI, A( I, I ), LDA, TAU( I ),$ C( IC, JC ), LDC, WORK )A( I, I ) = AII10 CONTINUERETURN** End of DORML2*ENDSUBROUTINE DORMLQ( SIDE, TRANS, M, N, K, A, LDA, TAU, C, LDC,$ WORK, LWORK, INFO )** -- LAPACK routine (version 3.0) --* Univ. of Tennessee, Univ. of California Berkeley, NAG Ltd.,* Courant Institute, Argonne National Lab, and Rice University* June 30, 1999** .. Scalar Arguments ..CHARACTER SIDE, TRANSINTEGER INFO, K, LDA, LDC, LWORK, M, N* ..* .. Array Arguments ..DOUBLE PRECISION A( LDA, * ), C( LDC, * ), TAU( * ), WORK( * )* ..** Purpose* =======** DORMLQ 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 DGELQF. 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,M) if SIDE = 'L',* (LDA,N) if SIDE = 'R'* The i-th row must contain the vector which defines the* elementary reflector H(i), for i = 1,2,...,k, as returned by* DGELQF in the first k rows 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. LDA >= max(1,K).** TAU (input) DOUBLE PRECISION array, dimension (K)* TAU(i) must contain the scalar factor of the elementary* reflector H(i), as returned by DGELQF.** 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/output) 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.** If LWORK = -1, then a workspace query is assumed; the routine* only calculates the optimal size of the WORK array, returns* this value as the first entry of the WORK array, and no error* message related to LWORK is issued by XERBLA.** INFO (output) INTEGER* = 0: successful exit* < 0: if INFO = -i, the i-th argument had an illegal value** =====================================================================** .. Parameters ..INTEGER NBMAX, LDTPARAMETER ( NBMAX = 64, LDT = NBMAX+1 )* ..* .. Local Scalars ..LOGICAL LEFT, LQUERY, NOTRANCHARACTER TRANSTINTEGER I, I1, I2, I3, IB, IC, IINFO, IWS, JC, LDWORK,$ LWKOPT, MI, NB, NBMIN, NI, NQ, NW* ..* .. Local Arrays ..DOUBLE PRECISION T( LDT, NBMAX )* ..* .. External Functions ..LOGICAL LSAMEINTEGER ILAENVEXTERNAL LSAME, ILAENV* ..* .. External Subroutines ..EXTERNAL DLARFB, DLARFT, DORML2, XERBLA* ..* .. Intrinsic Functions ..INTRINSIC MAX, MIN* ..* .. Executable Statements ..** Test the input arguments*INFO = 0LEFT = LSAME( SIDE, 'L' )NOTRAN = LSAME( TRANS, 'N' )LQUERY = ( LWORK.EQ.-1 )** NQ is the order of Q and NW is the minimum dimension of WORK*IF( LEFT ) THENNQ = MNW = NELSENQ = NNW = MEND IFIF( .NOT.LEFT .AND. .NOT.LSAME( SIDE, 'R' ) ) THENINFO = -1ELSE IF( .NOT.NOTRAN .AND. .NOT.LSAME( TRANS, 'T' ) ) THENINFO = -2ELSE IF( M.LT.0 ) THENINFO = -3ELSE IF( N.LT.0 ) THENINFO = -4ELSE IF( K.LT.0 .OR. K.GT.NQ ) THENINFO = -5ELSE IF( LDA.LT.MAX( 1, K ) ) THENINFO = -7ELSE IF( LDC.LT.MAX( 1, M ) ) THENINFO = -10ELSE IF( LWORK.LT.MAX( 1, NW ) .AND. .NOT.LQUERY ) THENINFO = -12END IF*IF( INFO.EQ.0 ) THEN** 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, 'DORMLQ', SIDE // TRANS, M, N, K,$ -1 ) )LWKOPT = MAX( 1, NW )*NBWORK( 1 ) = LWKOPTEND IF*IF( INFO.NE.0 ) THENCALL XERBLA( 'DORMLQ', -INFO )RETURNELSE IF( LQUERY ) THENRETURNEND IF** Quick return if possible*IF( M.EQ.0 .OR. N.EQ.0 .OR. K.EQ.0 ) THENWORK( 1 ) = 1RETURNEND IF*NBMIN = 2LDWORK = NWIF( NB.GT.1 .AND. NB.LT.K ) THENIWS = NW*NBIF( LWORK.LT.IWS ) THENNB = LWORK / LDWORKNBMIN = MAX( 2, ILAENV( 2, 'DORMLQ', SIDE // TRANS, M, N, K,$ -1 ) )END IFELSEIWS = NWEND IF*IF( NB.LT.NBMIN .OR. NB.GE.K ) THEN** Use unblocked code*CALL DORML2( 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 ) ) THENI1 = 1I2 = KI3 = NBELSEI1 = ( ( K-1 ) / NB )*NB + 1I2 = 1I3 = -NBEND IF*IF( LEFT ) THENNI = NJC = 1ELSEMI = MIC = 1END IF*IF( NOTRAN ) THENTRANST = 'T'ELSETRANST = 'N'END IF*DO 10 I = I1, I2, I3IB = 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', 'Rowwise', 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 + 1IC = IELSE** H or H' is applied to C(1:m,i:n)*NI = N - I + 1JC = IEND IF** Apply H or H'*CALL DLARFB( SIDE, TRANST, 'Forward', 'Rowwise', MI, NI, IB,$ A( I, I ), LDA, T, LDT, C( IC, JC ), LDC, WORK,$ LDWORK )10 CONTINUEEND IFWORK( 1 ) = LWKOPTRETURN** End of DORMLQ*ENDSUBROUTINE DORMQL( SIDE, TRANS, M, N, K, A, LDA, TAU, C, LDC,$ WORK, LWORK, INFO )** -- LAPACK routine (version 3.0) --* Univ. of Tennessee, Univ. of California Berkeley, NAG Ltd.,* Courant Institute, Argonne National Lab, and Rice University* June 30, 1999** .. Scalar Arguments ..CHARACTER SIDE, TRANSINTEGER INFO, K, LDA, LDC, LWORK, M, N* ..* .. Array Arguments ..DOUBLE PRECISION A( LDA, * ), C( LDC, * ), TAU( * ), WORK( * )* ..** 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/output) 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.** If LWORK = -1, then a workspace query is assumed; the routine* only calculates the optimal size of the WORK array, returns* this value as the first entry of the WORK array, and no error* message related to LWORK is issued by XERBLA.** INFO (output) INTEGER* = 0: successful exit* < 0: if INFO = -i, the i-th argument had an illegal value** =====================================================================** .. Parameters ..INTEGER NBMAX, LDTPARAMETER ( NBMAX = 64, LDT = NBMAX+1 )* ..* .. Local Scalars ..LOGICAL LEFT, LQUERY, NOTRANINTEGER I, I1, I2, I3, IB, IINFO, IWS, LDWORK, LWKOPT,$ MI, NB, NBMIN, NI, NQ, NW* ..* .. Local Arrays ..DOUBLE PRECISION T( LDT, NBMAX )* ..* .. External Functions ..LOGICAL LSAMEINTEGER ILAENVEXTERNAL LSAME, ILAENV* ..* .. External Subroutines ..EXTERNAL DLARFB, DLARFT, DORM2L, XERBLA* ..* .. Intrinsic Functions ..INTRINSIC MAX, MIN* ..* .. Executable Statements ..** Test the input arguments*INFO = 0LEFT = LSAME( SIDE, 'L' )NOTRAN = LSAME( TRANS, 'N' )LQUERY = ( LWORK.EQ.-1 )** NQ is the order of Q and NW is the minimum dimension of WORK*IF( LEFT ) THENNQ = MNW = NELSENQ = NNW = MEND IFIF( .NOT.LEFT .AND. .NOT.LSAME( SIDE, 'R' ) ) THENINFO = -1ELSE IF( .NOT.NOTRAN .AND. .NOT.LSAME( TRANS, 'T' ) ) THENINFO = -2ELSE IF( M.LT.0 ) THENINFO = -3ELSE IF( N.LT.0 ) THENINFO = -4ELSE IF( K.LT.0 .OR. K.GT.NQ ) THENINFO = -5ELSE IF( LDA.LT.MAX( 1, NQ ) ) THENINFO = -7ELSE IF( LDC.LT.MAX( 1, M ) ) THENINFO = -10ELSE IF( LWORK.LT.MAX( 1, NW ) .AND. .NOT.LQUERY ) THENINFO = -12END IF*IF( INFO.EQ.0 ) THEN** 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 ) )LWKOPT = MAX( 1, NW )*NBWORK( 1 ) = LWKOPTEND IF*IF( INFO.NE.0 ) THENCALL XERBLA( 'DORMQL', -INFO )RETURNELSE IF( LQUERY ) THENRETURNEND IF** Quick return if possible*IF( M.EQ.0 .OR. N.EQ.0 .OR. K.EQ.0 ) THENWORK( 1 ) = 1RETURNEND IF*NBMIN = 2LDWORK = NWIF( NB.GT.1 .AND. NB.LT.K ) THENIWS = NW*NBIF( LWORK.LT.IWS ) THENNB = LWORK / LDWORKNBMIN = MAX( 2, ILAENV( 2, 'DORMQL', SIDE // TRANS, M, N, K,$ -1 ) )END IFELSEIWS = NWEND 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 ) ) THENI1 = 1I2 = KI3 = NBELSEI1 = ( ( K-1 ) / NB )*NB + 1I2 = 1I3 = -NBEND IF*IF( LEFT ) THENNI = NELSEMI = MEND IF*DO 10 I = I1, I2, I3IB = 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 - 1ELSE** H or H' is applied to C(1:m,1:n-k+i+ib-1)*NI = N - K + I + IB - 1END 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 CONTINUEEND IFWORK( 1 ) = LWKOPTRETURN** End of DORMQL*ENDSUBROUTINE DORMQR( SIDE, TRANS, M, N, K, A, LDA, TAU, C, LDC,$ WORK, LWORK, INFO )** -- LAPACK routine (version 3.0) --* Univ. of Tennessee, Univ. of California Berkeley, NAG Ltd.,* Courant Institute, Argonne National Lab, and Rice University* June 30, 1999** .. Scalar Arguments ..CHARACTER SIDE, TRANSINTEGER INFO, K, LDA, LDC, LWORK, M, N* ..* .. Array Arguments ..DOUBLE PRECISION A( LDA, * ), C( LDC, * ), TAU( * ), WORK( * )* ..** 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/output) 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.** If LWORK = -1, then a workspace query is assumed; the routine* only calculates the optimal size of the WORK array, returns* this value as the first entry of the WORK array, and no error* message related to LWORK is issued by XERBLA.** INFO (output) INTEGER* = 0: successful exit* < 0: if INFO = -i, the i-th argument had an illegal value** =====================================================================** .. Parameters ..INTEGER NBMAX, LDTPARAMETER ( NBMAX = 64, LDT = NBMAX+1 )* ..* .. Local Scalars ..LOGICAL LEFT, LQUERY, NOTRANINTEGER I, I1, I2, I3, IB, IC, IINFO, IWS, JC, LDWORK,$ LWKOPT, MI, NB, NBMIN, NI, NQ, NW* ..* .. Local Arrays ..DOUBLE PRECISION T( LDT, NBMAX )* ..* .. External Functions ..LOGICAL LSAMEINTEGER ILAENVEXTERNAL LSAME, ILAENV* ..* .. External Subroutines ..EXTERNAL DLARFB, DLARFT, DORM2R, XERBLA* ..* .. Intrinsic Functions ..INTRINSIC MAX, MIN* ..* .. Executable Statements ..** Test the input arguments*INFO = 0LEFT = LSAME( SIDE, 'L' )NOTRAN = LSAME( TRANS, 'N' )LQUERY = ( LWORK.EQ.-1 )** NQ is the order of Q and NW is the minimum dimension of WORK*IF( LEFT ) THENNQ = MNW = NELSENQ = NNW = MEND IFIF( .NOT.LEFT .AND. .NOT.LSAME( SIDE, 'R' ) ) THENINFO = -1ELSE IF( .NOT.NOTRAN .AND. .NOT.LSAME( TRANS, 'T' ) ) THENINFO = -2ELSE IF( M.LT.0 ) THENINFO = -3ELSE IF( N.LT.0 ) THENINFO = -4ELSE IF( K.LT.0 .OR. K.GT.NQ ) THENINFO = -5ELSE IF( LDA.LT.MAX( 1, NQ ) ) THENINFO = -7ELSE IF( LDC.LT.MAX( 1, M ) ) THENINFO = -10ELSE IF( LWORK.LT.MAX( 1, NW ) .AND. .NOT.LQUERY ) THENINFO = -12END IF*IF( INFO.EQ.0 ) THEN** 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 ) )LWKOPT = MAX( 1, NW )*NBWORK( 1 ) = LWKOPTEND IF*IF( INFO.NE.0 ) THENCALL XERBLA( 'DORMQR', -INFO )RETURNELSE IF( LQUERY ) THENRETURNEND IF** Quick return if possible*IF( M.EQ.0 .OR. N.EQ.0 .OR. K.EQ.0 ) THENWORK( 1 ) = 1RETURNEND IF*NBMIN = 2LDWORK = NWIF( NB.GT.1 .AND. NB.LT.K ) THENIWS = NW*NBIF( LWORK.LT.IWS ) THENNB = LWORK / LDWORKNBMIN = MAX( 2, ILAENV( 2, 'DORMQR', SIDE // TRANS, M, N, K,$ -1 ) )END IFELSEIWS = NWEND 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 ) ) THENI1 = 1I2 = KI3 = NBELSEI1 = ( ( K-1 ) / NB )*NB + 1I2 = 1I3 = -NBEND IF*IF( LEFT ) THENNI = NJC = 1ELSEMI = MIC = 1END IF*DO 10 I = I1, I2, I3IB = 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 + 1IC = IELSE** H or H' is applied to C(1:m,i:n)*NI = N - I + 1JC = IEND 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 CONTINUEEND IFWORK( 1 ) = LWKOPTRETURN** End of DORMQR*ENDSUBROUTINE DORMR2( SIDE, TRANS, M, N, K, A, LDA, TAU, C, LDC,$ WORK, INFO )** -- LAPACK routine (version 3.0) --* Univ. of Tennessee, Univ. of California Berkeley, NAG Ltd.,* Courant Institute, Argonne National Lab, and Rice University* February 29, 1992** .. Scalar Arguments ..CHARACTER SIDE, TRANSINTEGER INFO, K, LDA, LDC, M, N* ..* .. Array Arguments ..DOUBLE PRECISION A( LDA, * ), C( LDC, * ), TAU( * ), WORK( * )* ..** Purpose* =======** DORMR2 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 DGERQF. 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,M) if SIDE = 'L',* (LDA,N) if SIDE = 'R'* The i-th row must contain the vector which defines the* elementary reflector H(i), for i = 1,2,...,k, as returned by* DGERQF in the last k rows 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. LDA >= max(1,K).** TAU (input) DOUBLE PRECISION array, dimension (K)* TAU(i) must contain the scalar factor of the elementary* reflector H(i), as returned by DGERQF.** 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 ONEPARAMETER ( ONE = 1.0D+0 )* ..* .. Local Scalars ..LOGICAL LEFT, NOTRANINTEGER I, I1, I2, I3, MI, NI, NQDOUBLE PRECISION AII* ..* .. External Functions ..LOGICAL LSAMEEXTERNAL LSAME* ..* .. External Subroutines ..EXTERNAL DLARF, XERBLA* ..* .. Intrinsic Functions ..INTRINSIC MAX* ..* .. Executable Statements ..** Test the input arguments*INFO = 0LEFT = LSAME( SIDE, 'L' )NOTRAN = LSAME( TRANS, 'N' )** NQ is the order of Q*IF( LEFT ) THENNQ = MELSENQ = NEND IFIF( .NOT.LEFT .AND. .NOT.LSAME( SIDE, 'R' ) ) THENINFO = -1ELSE IF( .NOT.NOTRAN .AND. .NOT.LSAME( TRANS, 'T' ) ) THENINFO = -2ELSE IF( M.LT.0 ) THENINFO = -3ELSE IF( N.LT.0 ) THENINFO = -4ELSE IF( K.LT.0 .OR. K.GT.NQ ) THENINFO = -5ELSE IF( LDA.LT.MAX( 1, K ) ) THENINFO = -7ELSE IF( LDC.LT.MAX( 1, M ) ) THENINFO = -10END IFIF( INFO.NE.0 ) THENCALL XERBLA( 'DORMR2', -INFO )RETURNEND 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 ) )$ THENI1 = 1I2 = KI3 = 1ELSEI1 = KI2 = 1I3 = -1END IF*IF( LEFT ) THENNI = NELSEMI = MEND IF*DO 10 I = I1, I2, I3IF( LEFT ) THEN** H(i) is applied to C(1:m-k+i,1:n)*MI = M - K + IELSE** H(i) is applied to C(1:m,1:n-k+i)*NI = N - K + IEND IF** Apply H(i)*AII = A( I, NQ-K+I )A( I, NQ-K+I ) = ONECALL DLARF( SIDE, MI, NI, A( I, 1 ), LDA, TAU( I ), C, LDC,$ WORK )A( I, NQ-K+I ) = AII10 CONTINUERETURN** End of DORMR2*ENDSUBROUTINE DORMR3( SIDE, TRANS, M, N, K, L, A, LDA, TAU, C, LDC,$ WORK, INFO )** -- LAPACK routine (version 3.0) --* Univ. of Tennessee, Univ. of California Berkeley, NAG Ltd.,* Courant Institute, Argonne National Lab, and Rice University* June 30, 1999** .. Scalar Arguments ..CHARACTER SIDE, TRANSINTEGER INFO, K, L, LDA, LDC, M, N* ..* .. Array Arguments ..DOUBLE PRECISION A( LDA, * ), C( LDC, * ), TAU( * ), WORK( * )* ..** Purpose* =======** DORMR3 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 DTZRZF. 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.** L (input) INTEGER* The number of columns of the matrix A containing* the meaningful part of the Householder reflectors.* If SIDE = 'L', M >= L >= 0, if SIDE = 'R', N >= L >= 0.** A (input) DOUBLE PRECISION array, dimension* (LDA,M) if SIDE = 'L',* (LDA,N) if SIDE = 'R'* The i-th row must contain the vector which defines the* elementary reflector H(i), for i = 1,2,...,k, as returned by* DTZRZF in the last k rows 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. LDA >= max(1,K).** TAU (input) DOUBLE PRECISION array, dimension (K)* TAU(i) must contain the scalar factor of the elementary* reflector H(i), as returned by DTZRZF.** 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** Further Details* ===============** Based on contributions by* A. Petitet, Computer Science Dept., Univ. of Tenn., Knoxville, USA** =====================================================================** .. Local Scalars ..LOGICAL LEFT, NOTRANINTEGER I, I1, I2, I3, IC, JA, JC, MI, NI, NQ* ..* .. External Functions ..LOGICAL LSAMEEXTERNAL LSAME* ..* .. External Subroutines ..EXTERNAL DLARZ, XERBLA* ..* .. Intrinsic Functions ..INTRINSIC MAX* ..* .. Executable Statements ..** Test the input arguments*INFO = 0LEFT = LSAME( SIDE, 'L' )NOTRAN = LSAME( TRANS, 'N' )** NQ is the order of Q*IF( LEFT ) THENNQ = MELSENQ = NEND IFIF( .NOT.LEFT .AND. .NOT.LSAME( SIDE, 'R' ) ) THENINFO = -1ELSE IF( .NOT.NOTRAN .AND. .NOT.LSAME( TRANS, 'T' ) ) THENINFO = -2ELSE IF( M.LT.0 ) THENINFO = -3ELSE IF( N.LT.0 ) THENINFO = -4ELSE IF( K.LT.0 .OR. K.GT.NQ ) THENINFO = -5ELSE IF( L.LT.0 .OR. ( LEFT .AND. ( L.GT.M ) ) .OR.$ ( .NOT.LEFT .AND. ( L.GT.N ) ) ) THENINFO = -6ELSE IF( LDA.LT.MAX( 1, K ) ) THENINFO = -8ELSE IF( LDC.LT.MAX( 1, M ) ) THENINFO = -11END IFIF( INFO.NE.0 ) THENCALL XERBLA( 'DORMR3', -INFO )RETURNEND 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 ) ) THENI1 = 1I2 = KI3 = 1ELSEI1 = KI2 = 1I3 = -1END IF*IF( LEFT ) THENNI = NJA = M - L + 1JC = 1ELSEMI = MJA = N - L + 1IC = 1END IF*DO 10 I = I1, I2, I3IF( LEFT ) THEN** H(i) or H(i)' is applied to C(i:m,1:n)*MI = M - I + 1IC = IELSE** H(i) or H(i)' is applied to C(1:m,i:n)*NI = N - I + 1JC = IEND IF** Apply H(i) or H(i)'*CALL DLARZ( SIDE, MI, NI, L, A( I, JA ), LDA, TAU( I ),$ C( IC, JC ), LDC, WORK )*10 CONTINUE*RETURN** End of DORMR3*ENDSUBROUTINE DORMRQ( SIDE, TRANS, M, N, K, A, LDA, TAU, C, LDC,$ WORK, LWORK, INFO )** -- LAPACK routine (version 3.0) --* Univ. of Tennessee, Univ. of California Berkeley, NAG Ltd.,* Courant Institute, Argonne National Lab, and Rice University* June 30, 1999** .. Scalar Arguments ..CHARACTER SIDE, TRANSINTEGER INFO, K, LDA, LDC, LWORK, M, N* ..* .. Array Arguments ..DOUBLE PRECISION A( LDA, * ), C( LDC, * ), TAU( * ), WORK( * )* ..** Purpose* =======** DORMRQ 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 DGERQF. 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,M) if SIDE = 'L',* (LDA,N) if SIDE = 'R'* The i-th row must contain the vector which defines the* elementary reflector H(i), for i = 1,2,...,k, as returned by* DGERQF in the last k rows 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. LDA >= max(1,K).** TAU (input) DOUBLE PRECISION array, dimension (K)* TAU(i) must contain the scalar factor of the elementary* reflector H(i), as returned by DGERQF.** 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/output) 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.** If LWORK = -1, then a workspace query is assumed; the routine* only calculates the optimal size of the WORK array, returns* this value as the first entry of the WORK array, and no error* message related to LWORK is issued by XERBLA.** INFO (output) INTEGER* = 0: successful exit* < 0: if INFO = -i, the i-th argument had an illegal value** =====================================================================** .. Parameters ..INTEGER NBMAX, LDTPARAMETER ( NBMAX = 64, LDT = NBMAX+1 )* ..* .. Local Scalars ..LOGICAL LEFT, LQUERY, NOTRANCHARACTER TRANSTINTEGER I, I1, I2, I3, IB, IINFO, IWS, LDWORK, LWKOPT,$ MI, NB, NBMIN, NI, NQ, NW* ..* .. Local Arrays ..DOUBLE PRECISION T( LDT, NBMAX )* ..* .. External Functions ..LOGICAL LSAMEINTEGER ILAENVEXTERNAL LSAME, ILAENV* ..* .. External Subroutines ..EXTERNAL DLARFB, DLARFT, DORMR2, XERBLA* ..* .. Intrinsic Functions ..INTRINSIC MAX, MIN* ..* .. Executable Statements ..** Test the input arguments*INFO = 0LEFT = LSAME( SIDE, 'L' )NOTRAN = LSAME( TRANS, 'N' )LQUERY = ( LWORK.EQ.-1 )** NQ is the order of Q and NW is the minimum dimension of WORK*IF( LEFT ) THENNQ = MNW = NELSENQ = NNW = MEND IFIF( .NOT.LEFT .AND. .NOT.LSAME( SIDE, 'R' ) ) THENINFO = -1ELSE IF( .NOT.NOTRAN .AND. .NOT.LSAME( TRANS, 'T' ) ) THENINFO = -2ELSE IF( M.LT.0 ) THENINFO = -3ELSE IF( N.LT.0 ) THENINFO = -4ELSE IF( K.LT.0 .OR. K.GT.NQ ) THENINFO = -5ELSE IF( LDA.LT.MAX( 1, K ) ) THENINFO = -7ELSE IF( LDC.LT.MAX( 1, M ) ) THENINFO = -10ELSE IF( LWORK.LT.MAX( 1, NW ) .AND. .NOT.LQUERY ) THENINFO = -12END IF*IF( INFO.EQ.0 ) THEN** 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, 'DORMRQ', SIDE // TRANS, M, N, K,$ -1 ) )LWKOPT = MAX( 1, NW )*NBWORK( 1 ) = LWKOPTEND IF*IF( INFO.NE.0 ) THENCALL XERBLA( 'DORMRQ', -INFO )RETURNELSE IF( LQUERY ) THENRETURNEND IF** Quick return if possible*IF( M.EQ.0 .OR. N.EQ.0 .OR. K.EQ.0 ) THENWORK( 1 ) = 1RETURNEND IF*NBMIN = 2LDWORK = NWIF( NB.GT.1 .AND. NB.LT.K ) THENIWS = NW*NBIF( LWORK.LT.IWS ) THENNB = LWORK / LDWORKNBMIN = MAX( 2, ILAENV( 2, 'DORMRQ', SIDE // TRANS, M, N, K,$ -1 ) )END IFELSEIWS = NWEND IF*IF( NB.LT.NBMIN .OR. NB.GE.K ) THEN** Use unblocked code*CALL DORMR2( 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 ) ) THENI1 = 1I2 = KI3 = NBELSEI1 = ( ( K-1 ) / NB )*NB + 1I2 = 1I3 = -NBEND IF*IF( LEFT ) THENNI = NELSEMI = MEND IF*IF( NOTRAN ) THENTRANST = 'T'ELSETRANST = 'N'END IF*DO 10 I = I1, I2, I3IB = 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', 'Rowwise', NQ-K+I+IB-1, IB,$ A( I, 1 ), 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 - 1ELSE** H or H' is applied to C(1:m,1:n-k+i+ib-1)*NI = N - K + I + IB - 1END IF** Apply H or H'*CALL DLARFB( SIDE, TRANST, 'Backward', 'Rowwise', MI, NI,$ IB, A( I, 1 ), LDA, T, LDT, C, LDC, WORK,$ LDWORK )10 CONTINUEEND IFWORK( 1 ) = LWKOPTRETURN** End of DORMRQ*ENDSUBROUTINE DORMRZ( SIDE, TRANS, M, N, K, L, A, LDA, TAU, C, LDC,$ WORK, LWORK, INFO )** -- LAPACK routine (version 3.0) --* Univ. of Tennessee, Univ. of California Berkeley, NAG Ltd.,* Courant Institute, Argonne National Lab, and Rice University* October 31, 1999** .. Scalar Arguments ..CHARACTER SIDE, TRANSINTEGER INFO, K, L, LDA, LDC, LWORK, M, N* ..* .. Array Arguments ..DOUBLE PRECISION A( LDA, * ), C( LDC, * ), TAU( * ), WORK( * )* ..** Purpose* =======** DORMRZ 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 DTZRZF. 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.** L (input) INTEGER* The number of columns of the matrix A containing* the meaningful part of the Householder reflectors.* If SIDE = 'L', M >= L >= 0, if SIDE = 'R', N >= L >= 0.** A (input) DOUBLE PRECISION array, dimension* (LDA,M) if SIDE = 'L',* (LDA,N) if SIDE = 'R'* The i-th row must contain the vector which defines the* elementary reflector H(i), for i = 1,2,...,k, as returned by* DTZRZF in the last k rows 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. LDA >= max(1,K).** TAU (input) DOUBLE PRECISION array, dimension (K)* TAU(i) must contain the scalar factor of the elementary* reflector H(i), as returned by DTZRZF.** 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**H*C or C*Q**H or C*Q.** LDC (input) INTEGER* The leading dimension of the array C. LDC >= max(1,M).** WORK (workspace/output) 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.** If LWORK = -1, then a workspace query is assumed; the routine* only calculates the optimal size of the WORK array, returns* this value as the first entry of the WORK array, and no error* message related to LWORK is issued by XERBLA.** INFO (output) INTEGER* = 0: successful exit* < 0: if INFO = -i, the i-th argument had an illegal value** Further Details* ===============** Based on contributions by* A. Petitet, Computer Science Dept., Univ. of Tenn., Knoxville, USA** =====================================================================** .. Parameters ..INTEGER NBMAX, LDTPARAMETER ( NBMAX = 64, LDT = NBMAX+1 )* ..* .. Local Scalars ..LOGICAL LEFT, LQUERY, NOTRANCHARACTER TRANSTINTEGER I, I1, I2, I3, IB, IC, IINFO, IWS, JA, JC,$ LDWORK, LWKOPT, MI, NB, NBMIN, NI, NQ, NW* ..* .. Local Arrays ..DOUBLE PRECISION T( LDT, NBMAX )* ..* .. External Functions ..LOGICAL LSAMEINTEGER ILAENVEXTERNAL LSAME, ILAENV* ..* .. External Subroutines ..EXTERNAL DLARZB, DLARZT, DORMR3, XERBLA* ..* .. Intrinsic Functions ..INTRINSIC MAX, MIN* ..* .. Executable Statements ..** Test the input arguments*INFO = 0LEFT = LSAME( SIDE, 'L' )NOTRAN = LSAME( TRANS, 'N' )LQUERY = ( LWORK.EQ.-1 )** NQ is the order of Q and NW is the minimum dimension of WORK*IF( LEFT ) THENNQ = MNW = NELSENQ = NNW = MEND IFIF( .NOT.LEFT .AND. .NOT.LSAME( SIDE, 'R' ) ) THENINFO = -1ELSE IF( .NOT.NOTRAN .AND. .NOT.LSAME( TRANS, 'T' ) ) THENINFO = -2ELSE IF( M.LT.0 ) THENINFO = -3ELSE IF( N.LT.0 ) THENINFO = -4ELSE IF( K.LT.0 .OR. K.GT.NQ ) THENINFO = -5ELSE IF( L.LT.0 .OR. ( LEFT .AND. ( L.GT.M ) ) .OR.$ ( .NOT.LEFT .AND. ( L.GT.N ) ) ) THENINFO = -6ELSE IF( LDA.LT.MAX( 1, K ) ) THENINFO = -8ELSE IF( LDC.LT.MAX( 1, M ) ) THENINFO = -11ELSE IF( LWORK.LT.MAX( 1, NW ) .AND. .NOT.LQUERY ) THENINFO = -13END IF*IF( INFO.EQ.0 ) THEN** 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, 'DORMRQ', SIDE // TRANS, M, N, K,$ -1 ) )LWKOPT = MAX( 1, NW )*NBWORK( 1 ) = LWKOPTEND IF*IF( INFO.NE.0 ) THENCALL XERBLA( 'DORMRZ', -INFO )RETURNELSE IF( LQUERY ) THENRETURNEND IF** Quick return if possible*IF( M.EQ.0 .OR. N.EQ.0 .OR. K.EQ.0 ) THENWORK( 1 ) = 1RETURNEND IF*NBMIN = 2LDWORK = NWIF( NB.GT.1 .AND. NB.LT.K ) THENIWS = NW*NBIF( LWORK.LT.IWS ) THENNB = LWORK / LDWORKNBMIN = MAX( 2, ILAENV( 2, 'DORMRQ', SIDE // TRANS, M, N, K,$ -1 ) )END IFELSEIWS = NWEND IF*IF( NB.LT.NBMIN .OR. NB.GE.K ) THEN** Use unblocked code*CALL DORMR3( SIDE, TRANS, M, N, K, L, A, LDA, TAU, C, LDC,$ WORK, IINFO )ELSE** Use blocked code*IF( ( LEFT .AND. .NOT.NOTRAN ) .OR.$ ( .NOT.LEFT .AND. NOTRAN ) ) THENI1 = 1I2 = KI3 = NBELSEI1 = ( ( K-1 ) / NB )*NB + 1I2 = 1I3 = -NBEND IF*IF( LEFT ) THENNI = NJC = 1JA = M - L + 1ELSEMI = MIC = 1JA = N - L + 1END IF*IF( NOTRAN ) THENTRANST = 'T'ELSETRANST = 'N'END IF*DO 10 I = I1, I2, I3IB = MIN( NB, K-I+1 )** Form the triangular factor of the block reflector* H = H(i+ib-1) . . . H(i+1) H(i)*CALL DLARZT( 'Backward', 'Rowwise', L, IB, A( I, JA ), LDA,$ TAU( I ), T, LDT )*IF( LEFT ) THEN** H or H' is applied to C(i:m,1:n)*MI = M - I + 1IC = IELSE** H or H' is applied to C(1:m,i:n)*NI = N - I + 1JC = IEND IF** Apply H or H'*CALL DLARZB( SIDE, TRANST, 'Backward', 'Rowwise', MI, NI,$ IB, L, A( I, JA ), LDA, T, LDT, C( IC, JC ),$ LDC, WORK, LDWORK )10 CONTINUE*END IF*WORK( 1 ) = LWKOPT*RETURN** End of DORMRZ*ENDSUBROUTINE DORMTR( SIDE, UPLO, TRANS, M, N, A, LDA, TAU, C, LDC,$ WORK, LWORK, INFO )** -- LAPACK routine (version 3.0) --* Univ. of Tennessee, Univ. of California Berkeley, NAG Ltd.,* Courant Institute, Argonne National Lab, and Rice University* June 30, 1999** .. Scalar Arguments ..CHARACTER SIDE, TRANS, UPLOINTEGER INFO, LDA, LDC, LWORK, M, N* ..* .. Array Arguments ..DOUBLE PRECISION A( LDA, * ), C( LDC, * ), TAU( * ), WORK( * )* ..** 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/output) 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.** If LWORK = -1, then a workspace query is assumed; the routine* only calculates the optimal size of the WORK array, returns* this value as the first entry of the WORK array, and no error* message related to LWORK is issued by XERBLA.** INFO (output) INTEGER* = 0: successful exit* < 0: if INFO = -i, the i-th argument had an illegal value** =====================================================================** .. Local Scalars ..LOGICAL LEFT, LQUERY, UPPERINTEGER I1, I2, IINFO, LWKOPT, MI, NB, NI, NQ, NW* ..* .. External Functions ..LOGICAL LSAMEINTEGER ILAENVEXTERNAL LSAME, ILAENV* ..* .. External Subroutines ..EXTERNAL DORMQL, DORMQR, XERBLA* ..* .. Intrinsic Functions ..INTRINSIC MAX* ..* .. Executable Statements ..** Test the input arguments*INFO = 0LEFT = LSAME( SIDE, 'L' )UPPER = LSAME( UPLO, 'U' )LQUERY = ( LWORK.EQ.-1 )** NQ is the order of Q and NW is the minimum dimension of WORK*IF( LEFT ) THENNQ = MNW = NELSENQ = NNW = MEND IFIF( .NOT.LEFT .AND. .NOT.LSAME( SIDE, 'R' ) ) THENINFO = -1ELSE IF( .NOT.UPPER .AND. .NOT.LSAME( UPLO, 'L' ) ) THENINFO = -2ELSE IF( .NOT.LSAME( TRANS, 'N' ) .AND. .NOT.LSAME( TRANS, 'T' ) )$ THENINFO = -3ELSE IF( M.LT.0 ) THENINFO = -4ELSE IF( N.LT.0 ) THENINFO = -5ELSE IF( LDA.LT.MAX( 1, NQ ) ) THENINFO = -7ELSE IF( LDC.LT.MAX( 1, M ) ) THENINFO = -10ELSE IF( LWORK.LT.MAX( 1, NW ) .AND. .NOT.LQUERY ) THENINFO = -12END IF*IF( INFO.EQ.0 ) THENIF( UPPER ) THENIF( LEFT ) THENNB = ILAENV( 1, 'DORMQL', SIDE // TRANS, M-1, N, M-1,$ -1 )ELSENB = ILAENV( 1, 'DORMQL', SIDE // TRANS, M, N-1, N-1,$ -1 )END IFELSEIF( LEFT ) THENNB = ILAENV( 1, 'DORMQR', SIDE // TRANS, M-1, N, M-1,$ -1 )ELSENB = ILAENV( 1, 'DORMQR', SIDE // TRANS, M, N-1, N-1,$ -1 )END IFEND IFLWKOPT = MAX( 1, NW )*NBWORK( 1 ) = LWKOPTEND IF*IF( INFO.NE.0 ) THENCALL XERBLA( 'DORMTR', -INFO )RETURNELSE IF( LQUERY ) THENRETURNEND IF** Quick return if possible*IF( M.EQ.0 .OR. N.EQ.0 .OR. NQ.EQ.1 ) THENWORK( 1 ) = 1RETURNEND IF*IF( LEFT ) THENMI = M - 1NI = NELSEMI = MNI = N - 1END 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 ) THENI1 = 2I2 = 1ELSEI1 = 1I2 = 2END IFCALL DORMQR( SIDE, TRANS, MI, NI, NQ-1, A( 2, 1 ), LDA, TAU,$ C( I1, I2 ), LDC, WORK, LWORK, IINFO )END IFWORK( 1 ) = LWKOPTRETURN** End of DORMTR*ENDSUBROUTINE DPBCON( UPLO, N, KD, AB, LDAB, ANORM, RCOND, WORK,$ IWORK, INFO )** -- LAPACK routine (version 3.0) --* Univ. of Tennessee, Univ. of California Berkeley, NAG Ltd.,* Courant Institute, Argonne National Lab, and Rice University* September 30, 1994** .. Scalar Arguments ..CHARACTER UPLOINTEGER INFO, KD, LDAB, NDOUBLE PRECISION ANORM, RCOND* ..* .. Array Arguments ..INTEGER IWORK( * )DOUBLE PRECISION AB( LDAB, * ), WORK( * )* ..** Purpose* =======** DPBCON estimates the reciprocal of the condition number (in the* 1-norm) of a real symmetric positive definite band matrix using the* Cholesky factorization A = U**T*U or A = L*L**T computed by DPBTRF.** An estimate is obtained for norm(inv(A)), and the reciprocal of the* condition number is computed as RCOND = 1 / (ANORM * norm(inv(A))).** Arguments* =========** UPLO (input) CHARACTER*1* = 'U': Upper triangular factor stored in AB;* = 'L': Lower triangular factor stored in AB.** N (input) INTEGER* The order of the matrix A. N >= 0.** KD (input) INTEGER* The number of superdiagonals of the matrix A if UPLO = 'U',* or the number of subdiagonals if UPLO = 'L'. KD >= 0.** AB (input) DOUBLE PRECISION array, dimension (LDAB,N)* The triangular factor U or L from the Cholesky factorization* A = U**T*U or A = L*L**T of the band matrix A, stored in the* first KD+1 rows of the array. The j-th column of U or L is* stored in the j-th column of the array AB as follows:* if UPLO ='U', AB(kd+1+i-j,j) = U(i,j) for max(1,j-kd)<=i<=j;* if UPLO ='L', AB(1+i-j,j) = L(i,j) for j<=i<=min(n,j+kd).** LDAB (input) INTEGER* The leading dimension of the array AB. LDAB >= KD+1.** ANORM (input) DOUBLE PRECISION* The 1-norm (or infinity-norm) of the symmetric band matrix A.** RCOND (output) DOUBLE PRECISION* The reciprocal of the condition number of the matrix A,* computed as RCOND = 1/(ANORM * AINVNM), where AINVNM is an* estimate of the 1-norm of inv(A) computed in this routine.** WORK (workspace) DOUBLE PRECISION array, dimension (3*N)** IWORK (workspace) INTEGER array, dimension (N)** INFO (output) INTEGER* = 0: successful exit* < 0: if INFO = -i, the i-th argument had an illegal value** =====================================================================** .. Parameters ..DOUBLE PRECISION ONE, ZEROPARAMETER ( ONE = 1.0D+0, ZERO = 0.0D+0 )* ..* .. Local Scalars ..LOGICAL UPPERCHARACTER NORMININTEGER IX, KASEDOUBLE PRECISION AINVNM, SCALE, SCALEL, SCALEU, SMLNUM* ..* .. External Functions ..LOGICAL LSAMEINTEGER IDAMAXDOUBLE PRECISION DLAMCHEXTERNAL LSAME, IDAMAX, DLAMCH* ..* .. External Subroutines ..EXTERNAL DLACON, DLATBS, DRSCL, XERBLA* ..* .. Intrinsic Functions ..INTRINSIC ABS* ..* .. Executable Statements ..** Test the input parameters.*INFO = 0UPPER = LSAME( UPLO, 'U' )IF( .NOT.UPPER .AND. .NOT.LSAME( UPLO, 'L' ) ) THENINFO = -1ELSE IF( N.LT.0 ) THENINFO = -2ELSE IF( KD.LT.0 ) THENINFO = -3ELSE IF( LDAB.LT.KD+1 ) THENINFO = -5ELSE IF( ANORM.LT.ZERO ) THENINFO = -6END IFIF( INFO.NE.0 ) THENCALL XERBLA( 'DPBCON', -INFO )RETURNEND IF** Quick return if possible*RCOND = ZEROIF( N.EQ.0 ) THENRCOND = ONERETURNELSE IF( ANORM.EQ.ZERO ) THENRETURNEND IF*SMLNUM = DLAMCH( 'Safe minimum' )** Estimate the 1-norm of the inverse.*KASE = 0NORMIN = 'N'10 CONTINUECALL DLACON( N, WORK( N+1 ), WORK, IWORK, AINVNM, KASE )IF( KASE.NE.0 ) THENIF( UPPER ) THEN** Multiply by inv(U').*CALL DLATBS( 'Upper', 'Transpose', 'Non-unit', NORMIN, N,$ KD, AB, LDAB, WORK, SCALEL, WORK( 2*N+1 ),$ INFO )NORMIN = 'Y'** Multiply by inv(U).*CALL DLATBS( 'Upper', 'No transpose', 'Non-unit', NORMIN, N,$ KD, AB, LDAB, WORK, SCALEU, WORK( 2*N+1 ),$ INFO )ELSE** Multiply by inv(L).*CALL DLATBS( 'Lower', 'No transpose', 'Non-unit', NORMIN, N,$ KD, AB, LDAB, WORK, SCALEL, WORK( 2*N+1 ),$ INFO )NORMIN = 'Y'** Multiply by inv(L').*CALL DLATBS( 'Lower', 'Transpose', 'Non-unit', NORMIN, N,$ KD, AB, LDAB, WORK, SCALEU, WORK( 2*N+1 ),$ INFO )END IF** Multiply by 1/SCALE if doing so will not cause overflow.*SCALE = SCALEL*SCALEUIF( SCALE.NE.ONE ) THENIX = IDAMAX( N, WORK, 1 )IF( SCALE.LT.ABS( WORK( IX ) )*SMLNUM .OR. SCALE.EQ.ZERO )$ GO TO 20CALL DRSCL( N, SCALE, WORK, 1 )END IFGO TO 10END IF** Compute the estimate of the reciprocal condition number.*IF( AINVNM.NE.ZERO )$ RCOND = ( ONE / AINVNM ) / ANORM*20 CONTINUE*RETURN** End of DPBCON*ENDSUBROUTINE DPBEQU( UPLO, N, KD, AB, LDAB, S, SCOND, AMAX, INFO )** -- LAPACK routine (version 3.0) --* Univ. of Tennessee, Univ. of California Berkeley, NAG Ltd.,* Courant Institute, Argonne National Lab, and Rice University* March 31, 1993** .. Scalar Arguments ..CHARACTER UPLOINTEGER INFO, KD, LDAB, NDOUBLE PRECISION AMAX, SCOND* ..* .. Array Arguments ..DOUBLE PRECISION AB( LDAB, * ), S( * )* ..** Purpose* =======** DPBEQU computes row and column scalings intended to equilibrate a* symmetric positive definite band matrix A and reduce its condition* number (with respect to the two-norm). S contains the scale factors,* S(i) = 1/sqrt(A(i,i)), chosen so that the scaled matrix B with* elements B(i,j) = S(i)*A(i,j)*S(j) has ones on the diagonal. This* choice of S puts the condition number of B within a factor N of the* smallest possible condition number over all possible diagonal* scalings.** Arguments* =========** UPLO (input) CHARACTER*1* = 'U': Upper triangular of A is stored;* = 'L': Lower triangular of A is stored.** N (input) INTEGER* The order of the matrix A. N >= 0.** KD (input) INTEGER* The number of superdiagonals of the matrix A if UPLO = 'U',* or the number of subdiagonals if UPLO = 'L'. KD >= 0.** AB (input) DOUBLE PRECISION array, dimension (LDAB,N)* The upper or lower triangle of the symmetric band matrix A,* stored in the first KD+1 rows of the array. The j-th column* of A is stored in the j-th column of the array AB as follows:* if UPLO = 'U', AB(kd+1+i-j,j) = A(i,j) for max(1,j-kd)<=i<=j;* if UPLO = 'L', AB(1+i-j,j) = A(i,j) for j<=i<=min(n,j+kd).** LDAB (input) INTEGER* The leading dimension of the array A. LDAB >= KD+1.** S (output) DOUBLE PRECISION array, dimension (N)* If INFO = 0, S contains the scale factors for A.** SCOND (output) DOUBLE PRECISION* If INFO = 0, S contains the ratio of the smallest S(i) to* the largest S(i). If SCOND >= 0.1 and AMAX is neither too* large nor too small, it is not worth scaling by S.** AMAX (output) DOUBLE PRECISION* Absolute value of largest matrix element. If AMAX is very* close to overflow or very close to underflow, the matrix* should be scaled.** INFO (output) INTEGER* = 0: successful exit* < 0: if INFO = -i, the i-th argument had an illegal value.* > 0: if INFO = i, the i-th diagonal element is nonpositive.** =====================================================================** .. Parameters ..DOUBLE PRECISION ZERO, ONEPARAMETER ( ZERO = 0.0D+0, ONE = 1.0D+0 )* ..* .. Local Scalars ..LOGICAL UPPERINTEGER I, JDOUBLE PRECISION SMIN* ..* .. External Functions ..LOGICAL LSAMEEXTERNAL LSAME* ..* .. External Subroutines ..EXTERNAL XERBLA* ..* .. Intrinsic Functions ..INTRINSIC MAX, MIN, SQRT* ..* .. Executable Statements ..** Test the input parameters.*INFO = 0UPPER = LSAME( UPLO, 'U' )IF( .NOT.UPPER .AND. .NOT.LSAME( UPLO, 'L' ) ) THENINFO = -1ELSE IF( N.LT.0 ) THENINFO = -2ELSE IF( KD.LT.0 ) THENINFO = -3ELSE IF( LDAB.LT.KD+1 ) THENINFO = -5END IFIF( INFO.NE.0 ) THENCALL XERBLA( 'DPBEQU', -INFO )RETURNEND IF** Quick return if possible*IF( N.EQ.0 ) THENSCOND = ONEAMAX = ZERORETURNEND IF*IF( UPPER ) THENJ = KD + 1ELSEJ = 1END IF** Initialize SMIN and AMAX.*S( 1 ) = AB( J, 1 )SMIN = S( 1 )AMAX = S( 1 )** Find the minimum and maximum diagonal elements.*DO 10 I = 2, NS( I ) = AB( J, I )SMIN = MIN( SMIN, S( I ) )AMAX = MAX( AMAX, S( I ) )10 CONTINUE*IF( SMIN.LE.ZERO ) THEN** Find the first non-positive diagonal element and return.*DO 20 I = 1, NIF( S( I ).LE.ZERO ) THENINFO = IRETURNEND IF20 CONTINUEELSE** Set the scale factors to the reciprocals* of the diagonal elements.*DO 30 I = 1, NS( I ) = ONE / SQRT( S( I ) )30 CONTINUE** Compute SCOND = min(S(I)) / max(S(I))*SCOND = SQRT( SMIN ) / SQRT( AMAX )END IFRETURN** End of DPBEQU*ENDSUBROUTINE DPBRFS( UPLO, N, KD, NRHS, AB, LDAB, AFB, LDAFB, B,$ LDB, X, LDX, FERR, BERR, WORK, IWORK, INFO )** -- LAPACK routine (version 3.0) --* Univ. of Tennessee, Univ. of California Berkeley, NAG Ltd.,* Courant Institute, Argonne National Lab, and Rice University* September 30, 1994** .. Scalar Arguments ..CHARACTER UPLOINTEGER INFO, KD, LDAB, LDAFB, LDB, LDX, N, NRHS* ..* .. Array Arguments ..INTEGER IWORK( * )DOUBLE PRECISION AB( LDAB, * ), AFB( LDAFB, * ), B( LDB, * ),$ BERR( * ), FERR( * ), WORK( * ), X( LDX, * )* ..** Purpose* =======** DPBRFS improves the computed solution to a system of linear* equations when the coefficient matrix is symmetric positive definite* and banded, and provides error bounds and backward error estimates* for the solution.** 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.** KD (input) INTEGER* The number of superdiagonals of the matrix A if UPLO = 'U',* or the number of subdiagonals if UPLO = 'L'. KD >= 0.** NRHS (input) INTEGER* The number of right hand sides, i.e., the number of columns* of the matrices B and X. NRHS >= 0.** AB (input) DOUBLE PRECISION array, dimension (LDAB,N)* The upper or lower triangle of the symmetric band matrix A,* stored in the first KD+1 rows of the array. The j-th column* of A is stored in the j-th column of the array AB as follows:* if UPLO = 'U', AB(kd+1+i-j,j) = A(i,j) for max(1,j-kd)<=i<=j;* if UPLO = 'L', AB(1+i-j,j) = A(i,j) for j<=i<=min(n,j+kd).** LDAB (input) INTEGER* The leading dimension of the array AB. LDAB >= KD+1.** AFB (input) DOUBLE PRECISION array, dimension (LDAFB,N)* The triangular factor U or L from the Cholesky factorization* A = U**T*U or A = L*L**T of the band matrix A as computed by* DPBTRF, in the same storage format as A (see AB).** LDAFB (input) INTEGER* The leading dimension of the array AFB. LDAFB >= KD+1.** B (input) DOUBLE PRECISION array, dimension (LDB,NRHS)* The right hand side matrix B.** LDB (input) INTEGER* The leading dimension of the array B. LDB >= max(1,N).** X (input/output) DOUBLE PRECISION array, dimension (LDX,NRHS)* On entry, the solution matrix X, as computed by DPBTRS.* On exit, the improved solution matrix X.** LDX (input) INTEGER* The leading dimension of the array X. LDX >= max(1,N).** FERR (output) DOUBLE PRECISION array, dimension (NRHS)* The estimated forward error bound for each solution vector* X(j) (the j-th column of the solution matrix X).* If XTRUE is the true solution corresponding to X(j), FERR(j)* is an estimated upper bound for the magnitude of the largest* element in (X(j) - XTRUE) divided by the magnitude of the* largest element in X(j). The estimate is as reliable as* the estimate for RCOND, and is almost always a slight* overestimate of the true error.** BERR (output) DOUBLE PRECISION array, dimension (NRHS)* The componentwise relative backward error of each solution* vector X(j) (i.e., the smallest relative change in* any element of A or B that makes X(j) an exact solution).** WORK (workspace) DOUBLE PRECISION array, dimension (3*N)** IWORK (workspace) INTEGER array, dimension (N)** INFO (output) INTEGER* = 0: successful exit* < 0: if INFO = -i, the i-th argument had an illegal value** Internal Parameters* ===================** ITMAX is the maximum number of steps of iterative refinement.** =====================================================================** .. Parameters ..INTEGER ITMAXPARAMETER ( ITMAX = 5 )DOUBLE PRECISION ZEROPARAMETER ( ZERO = 0.0D+0 )DOUBLE PRECISION ONEPARAMETER ( ONE = 1.0D+0 )DOUBLE PRECISION TWOPARAMETER ( TWO = 2.0D+0 )DOUBLE PRECISION THREEPARAMETER ( THREE = 3.0D+0 )* ..* .. Local Scalars ..LOGICAL UPPERINTEGER COUNT, I, J, K, KASE, L, NZDOUBLE PRECISION EPS, LSTRES, S, SAFE1, SAFE2, SAFMIN, XK* ..* .. External Subroutines ..EXTERNAL DAXPY, DCOPY, DLACON, DPBTRS, DSBMV, XERBLA* ..* .. Intrinsic Functions ..INTRINSIC ABS, MAX, MIN* ..* .. External Functions ..LOGICAL LSAMEDOUBLE PRECISION DLAMCHEXTERNAL LSAME, DLAMCH* ..* .. Executable Statements ..** Test the input parameters.*INFO = 0UPPER = LSAME( UPLO, 'U' )IF( .NOT.UPPER .AND. .NOT.LSAME( UPLO, 'L' ) ) THENINFO = -1ELSE IF( N.LT.0 ) THENINFO = -2ELSE IF( KD.LT.0 ) THENINFO = -3ELSE IF( NRHS.LT.0 ) THENINFO = -4ELSE IF( LDAB.LT.KD+1 ) THENINFO = -6ELSE IF( LDAFB.LT.KD+1 ) THENINFO = -8ELSE IF( LDB.LT.MAX( 1, N ) ) THENINFO = -10ELSE IF( LDX.LT.MAX( 1, N ) ) THENINFO = -12END IFIF( INFO.NE.0 ) THENCALL XERBLA( 'DPBRFS', -INFO )RETURNEND IF** Quick return if possible*IF( N.EQ.0 .OR. NRHS.EQ.0 ) THENDO 10 J = 1, NRHSFERR( J ) = ZEROBERR( J ) = ZERO10 CONTINUERETURNEND IF** NZ = maximum number of nonzero elements in each row of A, plus 1*NZ = MIN( N+1, 2*KD+2 )EPS = DLAMCH( 'Epsilon' )SAFMIN = DLAMCH( 'Safe minimum' )SAFE1 = NZ*SAFMINSAFE2 = SAFE1 / EPS** Do for each right hand side*DO 140 J = 1, NRHS*COUNT = 1LSTRES = THREE20 CONTINUE** Loop until stopping criterion is satisfied.** Compute residual R = B - A * X*CALL DCOPY( N, B( 1, J ), 1, WORK( N+1 ), 1 )CALL DSBMV( UPLO, N, KD, -ONE, AB, LDAB, X( 1, J ), 1, ONE,$ WORK( N+1 ), 1 )** Compute componentwise relative backward error from formula** max(i) ( abs(R(i)) / ( abs(A)*abs(X) + abs(B) )(i) )** where abs(Z) is the componentwise absolute value of the matrix* or vector Z. If the i-th component of the denominator is less* than SAFE2, then SAFE1 is added to the i-th components of the* numerator and denominator before dividing.*DO 30 I = 1, NWORK( I ) = ABS( B( I, J ) )30 CONTINUE** Compute abs(A)*abs(X) + abs(B).*IF( UPPER ) THENDO 50 K = 1, NS = ZEROXK = ABS( X( K, J ) )L = KD + 1 - KDO 40 I = MAX( 1, K-KD ), K - 1WORK( I ) = WORK( I ) + ABS( AB( L+I, K ) )*XKS = S + ABS( AB( L+I, K ) )*ABS( X( I, J ) )40 CONTINUEWORK( K ) = WORK( K ) + ABS( AB( KD+1, K ) )*XK + S50 CONTINUEELSEDO 70 K = 1, NS = ZEROXK = ABS( X( K, J ) )WORK( K ) = WORK( K ) + ABS( AB( 1, K ) )*XKL = 1 - KDO 60 I = K + 1, MIN( N, K+KD )WORK( I ) = WORK( I ) + ABS( AB( L+I, K ) )*XKS = S + ABS( AB( L+I, K ) )*ABS( X( I, J ) )60 CONTINUEWORK( K ) = WORK( K ) + S70 CONTINUEEND IFS = ZERODO 80 I = 1, NIF( WORK( I ).GT.SAFE2 ) THENS = MAX( S, ABS( WORK( N+I ) ) / WORK( I ) )ELSES = MAX( S, ( ABS( WORK( N+I ) )+SAFE1 ) /$ ( WORK( I )+SAFE1 ) )END IF80 CONTINUEBERR( J ) = S** Test stopping criterion. Continue iterating if* 1) The residual BERR(J) is larger than machine epsilon, and* 2) BERR(J) decreased by at least a factor of 2 during the* last iteration, and* 3) At most ITMAX iterations tried.*IF( BERR( J ).GT.EPS .AND. TWO*BERR( J ).LE.LSTRES .AND.$ COUNT.LE.ITMAX ) THEN** Update solution and try again.*CALL DPBTRS( UPLO, N, KD, 1, AFB, LDAFB, WORK( N+1 ), N,$ INFO )CALL DAXPY( N, ONE, WORK( N+1 ), 1, X( 1, J ), 1 )LSTRES = BERR( J )COUNT = COUNT + 1GO TO 20END IF** Bound error from formula** norm(X - XTRUE) / norm(X) .le. FERR =* norm( abs(inv(A))** ( abs(R) + NZ*EPS*( abs(A)*abs(X)+abs(B) ))) / norm(X)** where* norm(Z) is the magnitude of the largest component of Z* inv(A) is the inverse of A* abs(Z) is the componentwise absolute value of the matrix or* vector Z* NZ is the maximum number of nonzeros in any row of A, plus 1* EPS is machine epsilon** The i-th component of abs(R)+NZ*EPS*(abs(A)*abs(X)+abs(B))* is incremented by SAFE1 if the i-th component of* abs(A)*abs(X) + abs(B) is less than SAFE2.** Use DLACON to estimate the infinity-norm of the matrix* inv(A) * diag(W),* where W = abs(R) + NZ*EPS*( abs(A)*abs(X)+abs(B) )))*DO 90 I = 1, NIF( WORK( I ).GT.SAFE2 ) THENWORK( I ) = ABS( WORK( N+I ) ) + NZ*EPS*WORK( I )ELSEWORK( I ) = ABS( WORK( N+I ) ) + NZ*EPS*WORK( I ) + SAFE1END IF90 CONTINUE*KASE = 0100 CONTINUECALL DLACON( N, WORK( 2*N+1 ), WORK( N+1 ), IWORK, FERR( J ),$ KASE )IF( KASE.NE.0 ) THENIF( KASE.EQ.1 ) THEN** Multiply by diag(W)*inv(A').*CALL DPBTRS( UPLO, N, KD, 1, AFB, LDAFB, WORK( N+1 ), N,$ INFO )DO 110 I = 1, NWORK( N+I ) = WORK( N+I )*WORK( I )110 CONTINUEELSE IF( KASE.EQ.2 ) THEN** Multiply by inv(A)*diag(W).*DO 120 I = 1, NWORK( N+I ) = WORK( N+I )*WORK( I )120 CONTINUECALL DPBTRS( UPLO, N, KD, 1, AFB, LDAFB, WORK( N+1 ), N,$ INFO )END IFGO TO 100END IF** Normalize error.*LSTRES = ZERODO 130 I = 1, NLSTRES = MAX( LSTRES, ABS( X( I, J ) ) )130 CONTINUEIF( LSTRES.NE.ZERO )$ FERR( J ) = FERR( J ) / LSTRES*140 CONTINUE*RETURN** End of DPBRFS*ENDSUBROUTINE DPBSTF( UPLO, N, KD, AB, LDAB, INFO )** -- LAPACK routine (version 3.0) --* Univ. of Tennessee, Univ. of California Berkeley, NAG Ltd.,* Courant Institute, Argonne National Lab, and Rice University* September 30, 1994** .. Scalar Arguments ..CHARACTER UPLOINTEGER INFO, KD, LDAB, N* ..* .. Array Arguments ..DOUBLE PRECISION AB( LDAB, * )* ..** Purpose* =======** DPBSTF computes a split Cholesky factorization of a real* symmetric positive definite band matrix A.** This routine is designed to be used in conjunction with DSBGST.** The factorization has the form A = S**T*S where S is a band matrix* of the same bandwidth as A and the following structure:** S = ( U )* ( M L )** where U is upper triangular of order m = (n+kd)/2, and L is lower* triangular of order n-m.** 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.** KD (input) INTEGER* The number of superdiagonals of the matrix A if UPLO = 'U',* or the number of subdiagonals if UPLO = 'L'. KD >= 0.** AB (input/output) DOUBLE PRECISION array, dimension (LDAB,N)* On entry, the upper or lower triangle of the symmetric band* matrix A, stored in the first kd+1 rows of the array. The* j-th column of A is stored in the j-th column of the array AB* as follows:* if UPLO = 'U', AB(kd+1+i-j,j) = A(i,j) for max(1,j-kd)<=i<=j;* if UPLO = 'L', AB(1+i-j,j) = A(i,j) for j<=i<=min(n,j+kd).** On exit, if INFO = 0, the factor S from the split Cholesky* factorization A = S**T*S. See Further Details.** LDAB (input) INTEGER* The leading dimension of the array AB. LDAB >= KD+1.** INFO (output) INTEGER* = 0: successful exit* < 0: if INFO = -i, the i-th argument had an illegal value* > 0: if INFO = i, the factorization could not be completed,* because the updated element a(i,i) was negative; the* matrix A is not positive definite.** Further Details* ===============** The band storage scheme is illustrated by the following example, when* N = 7, KD = 2:** S = ( s11 s12 s13 )* ( s22 s23 s24 )* ( s33 s34 )* ( s44 )* ( s53 s54 s55 )* ( s64 s65 s66 )* ( s75 s76 s77 )** If UPLO = 'U', the array AB holds:** on entry: on exit:** * * a13 a24 a35 a46 a57 * * s13 s24 s53 s64 s75* * a12 a23 a34 a45 a56 a67 * s12 s23 s34 s54 s65 s76* a11 a22 a33 a44 a55 a66 a77 s11 s22 s33 s44 s55 s66 s77** If UPLO = 'L', the array AB holds:** on entry: on exit:** a11 a22 a33 a44 a55 a66 a77 s11 s22 s33 s44 s55 s66 s77* a21 a32 a43 a54 a65 a76 * s12 s23 s34 s54 s65 s76 ** a31 a42 a53 a64 a64 * * s13 s24 s53 s64 s75 * *** Array elements marked * are not used by the routine.** =====================================================================** .. Parameters ..DOUBLE PRECISION ONE, ZEROPARAMETER ( ONE = 1.0D+0, ZERO = 0.0D+0 )* ..* .. Local Scalars ..LOGICAL UPPERINTEGER J, KLD, KM, MDOUBLE PRECISION AJJ* ..* .. External Functions ..LOGICAL LSAMEEXTERNAL LSAME* ..* .. External Subroutines ..EXTERNAL DSCAL, DSYR, XERBLA* ..* .. Intrinsic Functions ..INTRINSIC MAX, MIN, SQRT* ..* .. Executable Statements ..** Test the input parameters.*INFO = 0UPPER = LSAME( UPLO, 'U' )IF( .NOT.UPPER .AND. .NOT.LSAME( UPLO, 'L' ) ) THENINFO = -1ELSE IF( N.LT.0 ) THENINFO = -2ELSE IF( KD.LT.0 ) THENINFO = -3ELSE IF( LDAB.LT.KD+1 ) THENINFO = -5END IFIF( INFO.NE.0 ) THENCALL XERBLA( 'DPBSTF', -INFO )RETURNEND IF** Quick return if possible*IF( N.EQ.0 )$ RETURN*KLD = MAX( 1, LDAB-1 )** Set the splitting point m.*M = ( N+KD ) / 2*IF( UPPER ) THEN** Factorize A(m+1:n,m+1:n) as L**T*L, and update A(1:m,1:m).*DO 10 J = N, M + 1, -1** Compute s(j,j) and test for non-positive-definiteness.*AJJ = AB( KD+1, J )IF( AJJ.LE.ZERO )$ GO TO 50AJJ = SQRT( AJJ )AB( KD+1, J ) = AJJKM = MIN( J-1, KD )** Compute elements j-km:j-1 of the j-th column and update the* the leading submatrix within the band.*CALL DSCAL( KM, ONE / AJJ, AB( KD+1-KM, J ), 1 )CALL DSYR( 'Upper', KM, -ONE, AB( KD+1-KM, J ), 1,$ AB( KD+1, J-KM ), KLD )10 CONTINUE** Factorize the updated submatrix A(1:m,1:m) as U**T*U.*DO 20 J = 1, M** Compute s(j,j) and test for non-positive-definiteness.*AJJ = AB( KD+1, J )IF( AJJ.LE.ZERO )$ GO TO 50AJJ = SQRT( AJJ )AB( KD+1, J ) = AJJKM = MIN( KD, M-J )** Compute elements j+1:j+km of the j-th row and update the* trailing submatrix within the band.*IF( KM.GT.0 ) THENCALL DSCAL( KM, ONE / AJJ, AB( KD, J+1 ), KLD )CALL DSYR( 'Upper', KM, -ONE, AB( KD, J+1 ), KLD,$ AB( KD+1, J+1 ), KLD )END IF20 CONTINUEELSE** Factorize A(m+1:n,m+1:n) as L**T*L, and update A(1:m,1:m).*DO 30 J = N, M + 1, -1** Compute s(j,j) and test for non-positive-definiteness.*AJJ = AB( 1, J )IF( AJJ.LE.ZERO )$ GO TO 50AJJ = SQRT( AJJ )AB( 1, J ) = AJJKM = MIN( J-1, KD )** Compute elements j-km:j-1 of the j-th row and update the* trailing submatrix within the band.*CALL DSCAL( KM, ONE / AJJ, AB( KM+1, J-KM ), KLD )CALL DSYR( 'Lower', KM, -ONE, AB( KM+1, J-KM ), KLD,$ AB( 1, J-KM ), KLD )30 CONTINUE** Factorize the updated submatrix A(1:m,1:m) as U**T*U.*DO 40 J = 1, M** Compute s(j,j) and test for non-positive-definiteness.*AJJ = AB( 1, J )IF( AJJ.LE.ZERO )$ GO TO 50AJJ = SQRT( AJJ )AB( 1, J ) = AJJKM = MIN( KD, M-J )** Compute elements j+1:j+km of the j-th column and update the* trailing submatrix within the band.*IF( KM.GT.0 ) THENCALL DSCAL( KM, ONE / AJJ, AB( 2, J ), 1 )CALL DSYR( 'Lower', KM, -ONE, AB( 2, J ), 1,$ AB( 1, J+1 ), KLD )END IF40 CONTINUEEND IFRETURN*50 CONTINUEINFO = JRETURN** End of DPBSTF*ENDSUBROUTINE DPBTF2( UPLO, N, KD, AB, LDAB, INFO )** -- LAPACK routine (version 3.0) --* Univ. of Tennessee, Univ. of California Berkeley, NAG Ltd.,* Courant Institute, Argonne National Lab, and Rice University* February 29, 1992** .. Scalar Arguments ..CHARACTER UPLOINTEGER INFO, KD, LDAB, N* ..* .. Array Arguments ..DOUBLE PRECISION AB( LDAB, * )* ..** Purpose* =======** DPBTF2 computes the Cholesky factorization of a real symmetric* positive definite band matrix A.** The factorization has the form* A = U' * U , if UPLO = 'U', or* A = L * L', if UPLO = 'L',* where U is an upper triangular matrix, U' is the transpose of U, and* L is lower triangular.** 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.** KD (input) INTEGER* The number of super-diagonals of the matrix A if UPLO = 'U',* or the number of sub-diagonals if UPLO = 'L'. KD >= 0.** AB (input/output) DOUBLE PRECISION array, dimension (LDAB,N)* On entry, the upper or lower triangle of the symmetric band* matrix A, stored in the first KD+1 rows of the array. The* j-th column of A is stored in the j-th column of the array AB* as follows:* if UPLO = 'U', AB(kd+1+i-j,j) = A(i,j) for max(1,j-kd)<=i<=j;* if UPLO = 'L', AB(1+i-j,j) = A(i,j) for j<=i<=min(n,j+kd).** On exit, if INFO = 0, the triangular factor U or L from the* Cholesky factorization A = U'*U or A = L*L' of the band* matrix A, in the same storage format as A.** LDAB (input) INTEGER* The leading dimension of the array AB. LDAB >= KD+1.** INFO (output) INTEGER* = 0: successful exit* < 0: if INFO = -k, the k-th argument had an illegal value* > 0: if INFO = k, the leading minor of order k is not* positive definite, and the factorization could not be* completed.** Further Details* ===============** The band storage scheme is illustrated by the following example, when* N = 6, KD = 2, and UPLO = 'U':** On entry: On exit:** * * a13 a24 a35 a46 * * u13 u24 u35 u46* * a12 a23 a34 a45 a56 * u12 u23 u34 u45 u56* a11 a22 a33 a44 a55 a66 u11 u22 u33 u44 u55 u66** Similarly, if UPLO = 'L' the format of A is as follows:** On entry: On exit:** a11 a22 a33 a44 a55 a66 l11 l22 l33 l44 l55 l66* a21 a32 a43 a54 a65 * l21 l32 l43 l54 l65 ** a31 a42 a53 a64 * * l31 l42 l53 l64 * *** Array elements marked * are not used by the routine.** =====================================================================** .. Parameters ..DOUBLE PRECISION ONE, ZEROPARAMETER ( ONE = 1.0D+0, ZERO = 0.0D+0 )* ..* .. Local Scalars ..LOGICAL UPPERINTEGER J, KLD, KNDOUBLE PRECISION AJJ* ..* .. External Functions ..LOGICAL LSAMEEXTERNAL LSAME* ..* .. External Subroutines ..EXTERNAL DSCAL, DSYR, XERBLA* ..* .. Intrinsic Functions ..INTRINSIC MAX, MIN, SQRT* ..* .. Executable Statements ..** Test the input parameters.*INFO = 0UPPER = LSAME( UPLO, 'U' )IF( .NOT.UPPER .AND. .NOT.LSAME( UPLO, 'L' ) ) THENINFO = -1ELSE IF( N.LT.0 ) THENINFO = -2ELSE IF( KD.LT.0 ) THENINFO = -3ELSE IF( LDAB.LT.KD+1 ) THENINFO = -5END IFIF( INFO.NE.0 ) THENCALL XERBLA( 'DPBTF2', -INFO )RETURNEND IF** Quick return if possible*IF( N.EQ.0 )$ RETURN*KLD = MAX( 1, LDAB-1 )*IF( UPPER ) THEN** Compute the Cholesky factorization A = U'*U.*DO 10 J = 1, N** Compute U(J,J) and test for non-positive-definiteness.*AJJ = AB( KD+1, J )IF( AJJ.LE.ZERO )$ GO TO 30AJJ = SQRT( AJJ )AB( KD+1, J ) = AJJ** Compute elements J+1:J+KN of row J and update the* trailing submatrix within the band.*KN = MIN( KD, N-J )IF( KN.GT.0 ) THENCALL DSCAL( KN, ONE / AJJ, AB( KD, J+1 ), KLD )CALL DSYR( 'Upper', KN, -ONE, AB( KD, J+1 ), KLD,$ AB( KD+1, J+1 ), KLD )END IF10 CONTINUEELSE** Compute the Cholesky factorization A = L*L'.*DO 20 J = 1, N** Compute L(J,J) and test for non-positive-definiteness.*AJJ = AB( 1, J )IF( AJJ.LE.ZERO )$ GO TO 30AJJ = SQRT( AJJ )AB( 1, J ) = AJJ** Compute elements J+1:J+KN of column J and update the* trailing submatrix within the band.*KN = MIN( KD, N-J )IF( KN.GT.0 ) THENCALL DSCAL( KN, ONE / AJJ, AB( 2, J ), 1 )CALL DSYR( 'Lower', KN, -ONE, AB( 2, J ), 1,$ AB( 1, J+1 ), KLD )END IF20 CONTINUEEND IFRETURN*30 CONTINUEINFO = JRETURN** End of DPBTF2*ENDSUBROUTINE DPBTRF( UPLO, N, KD, AB, LDAB, INFO )** -- LAPACK routine (version 3.0) --* Univ. of Tennessee, Univ. of California Berkeley, NAG Ltd.,* Courant Institute, Argonne National Lab, and Rice University* March 31, 1993** .. Scalar Arguments ..CHARACTER UPLOINTEGER INFO, KD, LDAB, N* ..* .. Array Arguments ..DOUBLE PRECISION AB( LDAB, * )* ..** Purpose* =======** DPBTRF computes the Cholesky factorization of a real symmetric* positive definite band matrix A.** The factorization has the form* A = U**T * U, if UPLO = 'U', or* A = L * L**T, if UPLO = 'L',* where U is an upper triangular matrix and L is lower triangular.** 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.** KD (input) INTEGER* The number of superdiagonals of the matrix A if UPLO = 'U',* or the number of subdiagonals if UPLO = 'L'. KD >= 0.** AB (input/output) DOUBLE PRECISION array, dimension (LDAB,N)* On entry, the upper or lower triangle of the symmetric band* matrix A, stored in the first KD+1 rows of the array. The* j-th column of A is stored in the j-th column of the array AB* as follows:* if UPLO = 'U', AB(kd+1+i-j,j) = A(i,j) for max(1,j-kd)<=i<=j;* if UPLO = 'L', AB(1+i-j,j) = A(i,j) for j<=i<=min(n,j+kd).** On exit, if INFO = 0, the triangular factor U or L from the* Cholesky factorization A = U**T*U or A = L*L**T of the band* matrix A, in the same storage format as A.** LDAB (input) INTEGER* The leading dimension of the array AB. LDAB >= KD+1.** INFO (output) INTEGER* = 0: successful exit* < 0: if INFO = -i, the i-th argument had an illegal value* > 0: if INFO = i, the leading minor of order i is not* positive definite, and the factorization could not be* completed.** Further Details* ===============** The band storage scheme is illustrated by the following example, when* N = 6, KD = 2, and UPLO = 'U':** On entry: On exit:** * * a13 a24 a35 a46 * * u13 u24 u35 u46* * a12 a23 a34 a45 a56 * u12 u23 u34 u45 u56* a11 a22 a33 a44 a55 a66 u11 u22 u33 u44 u55 u66** Similarly, if UPLO = 'L' the format of A is as follows:** On entry: On exit:** a11 a22 a33 a44 a55 a66 l11 l22 l33 l44 l55 l66* a21 a32 a43 a54 a65 * l21 l32 l43 l54 l65 ** a31 a42 a53 a64 * * l31 l42 l53 l64 * *** Array elements marked * are not used by the routine.** Contributed by* Peter Mayes and Giuseppe Radicati, IBM ECSEC, Rome, March 23, 1989** =====================================================================** .. Parameters ..DOUBLE PRECISION ONE, ZEROPARAMETER ( ONE = 1.0D+0, ZERO = 0.0D+0 )INTEGER NBMAX, LDWORKPARAMETER ( NBMAX = 32, LDWORK = NBMAX+1 )* ..* .. Local Scalars ..INTEGER I, I2, I3, IB, II, J, JJ, NB* ..* .. Local Arrays ..DOUBLE PRECISION WORK( LDWORK, NBMAX )* ..* .. External Functions ..LOGICAL LSAMEINTEGER ILAENVEXTERNAL LSAME, ILAENV* ..* .. External Subroutines ..EXTERNAL DGEMM, DPBTF2, DPOTF2, DSYRK, DTRSM, XERBLA* ..* .. Intrinsic Functions ..INTRINSIC MIN* ..* .. Executable Statements ..** Test the input parameters.*INFO = 0IF( ( .NOT.LSAME( UPLO, 'U' ) ) .AND.$ ( .NOT.LSAME( UPLO, 'L' ) ) ) THENINFO = -1ELSE IF( N.LT.0 ) THENINFO = -2ELSE IF( KD.LT.0 ) THENINFO = -3ELSE IF( LDAB.LT.KD+1 ) THENINFO = -5END IFIF( INFO.NE.0 ) THENCALL XERBLA( 'DPBTRF', -INFO )RETURNEND IF** Quick return if possible*IF( N.EQ.0 )$ RETURN** Determine the block size for this environment*NB = ILAENV( 1, 'DPBTRF', UPLO, N, KD, -1, -1 )** The block size must not exceed the semi-bandwidth KD, and must not* exceed the limit set by the size of the local array WORK.*NB = MIN( NB, NBMAX )*IF( NB.LE.1 .OR. NB.GT.KD ) THEN** Use unblocked code*CALL DPBTF2( UPLO, N, KD, AB, LDAB, INFO )ELSE** Use blocked code*IF( LSAME( UPLO, 'U' ) ) THEN** Compute the Cholesky factorization of a symmetric band* matrix, given the upper triangle of the matrix in band* storage.** Zero the upper triangle of the work array.*DO 20 J = 1, NBDO 10 I = 1, J - 1WORK( I, J ) = ZERO10 CONTINUE20 CONTINUE** Process the band matrix one diagonal block at a time.*DO 70 I = 1, N, NBIB = MIN( NB, N-I+1 )** Factorize the diagonal block*CALL DPOTF2( UPLO, IB, AB( KD+1, I ), LDAB-1, II )IF( II.NE.0 ) THENINFO = I + II - 1GO TO 150END IFIF( I+IB.LE.N ) THEN** Update the relevant part of the trailing submatrix.* If A11 denotes the diagonal block which has just been* factorized, then we need to update the remaining* blocks in the diagram:** A11 A12 A13* A22 A23* A33** The numbers of rows and columns in the partitioning* are IB, I2, I3 respectively. The blocks A12, A22 and* A23 are empty if IB = KD. The upper triangle of A13* lies outside the band.*I2 = MIN( KD-IB, N-I-IB+1 )I3 = MIN( IB, N-I-KD+1 )*IF( I2.GT.0 ) THEN** Update A12*CALL DTRSM( 'Left', 'Upper', 'Transpose',$ 'Non-unit', IB, I2, ONE, AB( KD+1, I ),$ LDAB-1, AB( KD+1-IB, I+IB ), LDAB-1 )** Update A22*CALL DSYRK( 'Upper', 'Transpose', I2, IB, -ONE,$ AB( KD+1-IB, I+IB ), LDAB-1, ONE,$ AB( KD+1, I+IB ), LDAB-1 )END IF*IF( I3.GT.0 ) THEN** Copy the lower triangle of A13 into the work array.*DO 40 JJ = 1, I3DO 30 II = JJ, IBWORK( II, JJ ) = AB( II-JJ+1, JJ+I+KD-1 )30 CONTINUE40 CONTINUE** Update A13 (in the work array).*CALL DTRSM( 'Left', 'Upper', 'Transpose',$ 'Non-unit', IB, I3, ONE, AB( KD+1, I ),$ LDAB-1, WORK, LDWORK )** Update A23*IF( I2.GT.0 )$ CALL DGEMM( 'Transpose', 'No Transpose', I2, I3,$ IB, -ONE, AB( KD+1-IB, I+IB ),$ LDAB-1, WORK, LDWORK, ONE,$ AB( 1+IB, I+KD ), LDAB-1 )** Update A33*CALL DSYRK( 'Upper', 'Transpose', I3, IB, -ONE,$ WORK, LDWORK, ONE, AB( KD+1, I+KD ),$ LDAB-1 )** Copy the lower triangle of A13 back into place.*DO 60 JJ = 1, I3DO 50 II = JJ, IBAB( II-JJ+1, JJ+I+KD-1 ) = WORK( II, JJ )50 CONTINUE60 CONTINUEEND IFEND IF70 CONTINUEELSE** Compute the Cholesky factorization of a symmetric band* matrix, given the lower triangle of the matrix in band* storage.** Zero the lower triangle of the work array.*DO 90 J = 1, NBDO 80 I = J + 1, NBWORK( I, J ) = ZERO80 CONTINUE90 CONTINUE** Process the band matrix one diagonal block at a time.*DO 140 I = 1, N, NBIB = MIN( NB, N-I+1 )** Factorize the diagonal block*CALL DPOTF2( UPLO, IB, AB( 1, I ), LDAB-1, II )IF( II.NE.0 ) THENINFO = I + II - 1GO TO 150END IFIF( I+IB.LE.N ) THEN** Update the relevant part of the trailing submatrix.* If A11 denotes the diagonal block which has just been* factorized, then we need to update the remaining* blocks in the diagram:** A11* A21 A22* A31 A32 A33** The numbers of rows and columns in the partitioning* are IB, I2, I3 respectively. The blocks A21, A22 and* A32 are empty if IB = KD. The lower triangle of A31* lies outside the band.*I2 = MIN( KD-IB, N-I-IB+1 )I3 = MIN( IB, N-I-KD+1 )*IF( I2.GT.0 ) THEN** Update A21*CALL DTRSM( 'Right', 'Lower', 'Transpose',$ 'Non-unit', I2, IB, ONE, AB( 1, I ),$ LDAB-1, AB( 1+IB, I ), LDAB-1 )** Update A22*CALL DSYRK( 'Lower', 'No Transpose', I2, IB, -ONE,$ AB( 1+IB, I ), LDAB-1, ONE,$ AB( 1, I+IB ), LDAB-1 )END IF*IF( I3.GT.0 ) THEN** Copy the upper triangle of A31 into the work array.*DO 110 JJ = 1, IBDO 100 II = 1, MIN( JJ, I3 )WORK( II, JJ ) = AB( KD+1-JJ+II, JJ+I-1 )100 CONTINUE110 CONTINUE** Update A31 (in the work array).*CALL DTRSM( 'Right', 'Lower', 'Transpose',$ 'Non-unit', I3, IB, ONE, AB( 1, I ),$ LDAB-1, WORK, LDWORK )** Update A32*IF( I2.GT.0 )$ CALL DGEMM( 'No transpose', 'Transpose', I3, I2,$ IB, -ONE, WORK, LDWORK,$ AB( 1+IB, I ), LDAB-1, ONE,$ AB( 1+KD-IB, I+IB ), LDAB-1 )** Update A33*CALL DSYRK( 'Lower', 'No Transpose', I3, IB, -ONE,$ WORK, LDWORK, ONE, AB( 1, I+KD ),$ LDAB-1 )** Copy the upper triangle of A31 back into place.*DO 130 JJ = 1, IBDO 120 II = 1, MIN( JJ, I3 )AB( KD+1-JJ+II, JJ+I-1 ) = WORK( II, JJ )120 CONTINUE130 CONTINUEEND IFEND IF140 CONTINUEEND IFEND IFRETURN*150 CONTINUERETURN** End of DPBTRF*ENDSUBROUTINE DPBTRS( UPLO, N, KD, NRHS, AB, LDAB, B, LDB, INFO )** -- LAPACK routine (version 3.0) --* Univ. of Tennessee, Univ. of California Berkeley, NAG Ltd.,* Courant Institute, Argonne National Lab, and Rice University* September 30, 1994** .. Scalar Arguments ..CHARACTER UPLOINTEGER INFO, KD, LDAB, LDB, N, NRHS* ..* .. Array Arguments ..DOUBLE PRECISION AB( LDAB, * ), B( LDB, * )* ..** Purpose* =======** DPBTRS solves a system of linear equations A*X = B with a symmetric* positive definite band matrix A using the Cholesky factorization* A = U**T*U or A = L*L**T computed by DPBTRF.** Arguments* =========** UPLO (input) CHARACTER*1* = 'U': Upper triangular factor stored in AB;* = 'L': Lower triangular factor stored in AB.** N (input) INTEGER* The order of the matrix A. N >= 0.** KD (input) INTEGER* The number of superdiagonals of the matrix A if UPLO = 'U',* or the number of subdiagonals if UPLO = 'L'. KD >= 0.** NRHS (input) INTEGER* The number of right hand sides, i.e., the number of columns* of the matrix B. NRHS >= 0.** AB (input) DOUBLE PRECISION array, dimension (LDAB,N)* The triangular factor U or L from the Cholesky factorization* A = U**T*U or A = L*L**T of the band matrix A, stored in the* first KD+1 rows of the array. The j-th column of U or L is* stored in the j-th column of the array AB as follows:* if UPLO ='U', AB(kd+1+i-j,j) = U(i,j) for max(1,j-kd)<=i<=j;* if UPLO ='L', AB(1+i-j,j) = L(i,j) for j<=i<=min(n,j+kd).** LDAB (input) INTEGER* The leading dimension of the array AB. LDAB >= KD+1.** 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** =====================================================================** .. Local Scalars ..LOGICAL UPPERINTEGER J* ..* .. External Functions ..LOGICAL LSAMEEXTERNAL LSAME* ..* .. External Subroutines ..EXTERNAL DTBSV, XERBLA* ..* .. Intrinsic Functions ..INTRINSIC MAX* ..* .. Executable Statements ..** Test the input parameters.*INFO = 0UPPER = LSAME( UPLO, 'U' )IF( .NOT.UPPER .AND. .NOT.LSAME( UPLO, 'L' ) ) THENINFO = -1ELSE IF( N.LT.0 ) THENINFO = -2ELSE IF( KD.LT.0 ) THENINFO = -3ELSE IF( NRHS.LT.0 ) THENINFO = -4ELSE IF( LDAB.LT.KD+1 ) THENINFO = -6ELSE IF( LDB.LT.MAX( 1, N ) ) THENINFO = -8END IFIF( INFO.NE.0 ) THENCALL XERBLA( 'DPBTRS', -INFO )RETURNEND IF** Quick return if possible*IF( N.EQ.0 .OR. NRHS.EQ.0 )$ RETURN*IF( UPPER ) THEN** Solve A*X = B where A = U'*U.*DO 10 J = 1, NRHS** Solve U'*X = B, overwriting B with X.*CALL DTBSV( 'Upper', 'Transpose', 'Non-unit', N, KD, AB,$ LDAB, B( 1, J ), 1 )** Solve U*X = B, overwriting B with X.*CALL DTBSV( 'Upper', 'No transpose', 'Non-unit', N, KD, AB,$ LDAB, B( 1, J ), 1 )10 CONTINUEELSE** Solve A*X = B where A = L*L'.*DO 20 J = 1, NRHS** Solve L*X = B, overwriting B with X.*CALL DTBSV( 'Lower', 'No transpose', 'Non-unit', N, KD, AB,$ LDAB, B( 1, J ), 1 )** Solve L'*X = B, overwriting B with X.*CALL DTBSV( 'Lower', 'Transpose', 'Non-unit', N, KD, AB,$ LDAB, B( 1, J ), 1 )20 CONTINUEEND IF*RETURN** End of DPBTRS*ENDSUBROUTINE DPOCON( UPLO, N, A, LDA, ANORM, RCOND, WORK, IWORK,$ INFO )** -- LAPACK routine (version 3.0) --* Univ. of Tennessee, Univ. of California Berkeley, NAG Ltd.,* Courant Institute, Argonne National Lab, and Rice University* March 31, 1993** .. Scalar Arguments ..CHARACTER UPLOINTEGER INFO, LDA, NDOUBLE PRECISION ANORM, RCOND* ..* .. Array Arguments ..INTEGER IWORK( * )DOUBLE PRECISION A( LDA, * ), WORK( * )* ..** Purpose* =======** DPOCON estimates the reciprocal of the condition number (in the* 1-norm) of a real symmetric positive definite matrix using the* Cholesky factorization A = U**T*U or A = L*L**T computed by DPOTRF.** An estimate is obtained for norm(inv(A)), and the reciprocal of the* condition number is computed as RCOND = 1 / (ANORM * norm(inv(A))).** 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) DOUBLE PRECISION array, dimension (LDA,N)* The triangular factor U or L from the Cholesky factorization* A = U**T*U or A = L*L**T, as computed by DPOTRF.** LDA (input) INTEGER* The leading dimension of the array A. LDA >= max(1,N).** ANORM (input) DOUBLE PRECISION* The 1-norm (or infinity-norm) of the symmetric matrix A.** RCOND (output) DOUBLE PRECISION* The reciprocal of the condition number of the matrix A,* computed as RCOND = 1/(ANORM * AINVNM), where AINVNM is an* estimate of the 1-norm of inv(A) computed in this routine.** WORK (workspace) DOUBLE PRECISION array, dimension (3*N)** IWORK (workspace) INTEGER array, dimension (N)** INFO (output) INTEGER* = 0: successful exit* < 0: if INFO = -i, the i-th argument had an illegal value** =====================================================================** .. Parameters ..DOUBLE PRECISION ONE, ZEROPARAMETER ( ONE = 1.0D+0, ZERO = 0.0D+0 )* ..* .. Local Scalars ..LOGICAL UPPERCHARACTER NORMININTEGER IX, KASEDOUBLE PRECISION AINVNM, SCALE, SCALEL, SCALEU, SMLNUM* ..* .. External Functions ..LOGICAL LSAMEINTEGER IDAMAXDOUBLE PRECISION DLAMCHEXTERNAL LSAME, IDAMAX, DLAMCH* ..* .. External Subroutines ..EXTERNAL DLACON, DLATRS, DRSCL, XERBLA* ..* .. Intrinsic Functions ..INTRINSIC ABS, MAX* ..* .. Executable Statements ..** Test the input parameters.*INFO = 0UPPER = LSAME( UPLO, 'U' )IF( .NOT.UPPER .AND. .NOT.LSAME( UPLO, 'L' ) ) THENINFO = -1ELSE IF( N.LT.0 ) THENINFO = -2ELSE IF( LDA.LT.MAX( 1, N ) ) THENINFO = -4ELSE IF( ANORM.LT.ZERO ) THENINFO = -5END IFIF( INFO.NE.0 ) THENCALL XERBLA( 'DPOCON', -INFO )RETURNEND IF** Quick return if possible*RCOND = ZEROIF( N.EQ.0 ) THENRCOND = ONERETURNELSE IF( ANORM.EQ.ZERO ) THENRETURNEND IF*SMLNUM = DLAMCH( 'Safe minimum' )** Estimate the 1-norm of inv(A).*KASE = 0NORMIN = 'N'10 CONTINUECALL DLACON( N, WORK( N+1 ), WORK, IWORK, AINVNM, KASE )IF( KASE.NE.0 ) THENIF( UPPER ) THEN** Multiply by inv(U').*CALL DLATRS( 'Upper', 'Transpose', 'Non-unit', NORMIN, N, A,$ LDA, WORK, SCALEL, WORK( 2*N+1 ), INFO )NORMIN = 'Y'** Multiply by inv(U).*CALL DLATRS( 'Upper', 'No transpose', 'Non-unit', NORMIN, N,$ A, LDA, WORK, SCALEU, WORK( 2*N+1 ), INFO )ELSE** Multiply by inv(L).*CALL DLATRS( 'Lower', 'No transpose', 'Non-unit', NORMIN, N,$ A, LDA, WORK, SCALEL, WORK( 2*N+1 ), INFO )NORMIN = 'Y'** Multiply by inv(L').*CALL DLATRS( 'Lower', 'Transpose', 'Non-unit', NORMIN, N, A,$ LDA, WORK, SCALEU, WORK( 2*N+1 ), INFO )END IF** Multiply by 1/SCALE if doing so will not cause overflow.*SCALE = SCALEL*SCALEUIF( SCALE.NE.ONE ) THENIX = IDAMAX( N, WORK, 1 )IF( SCALE.LT.ABS( WORK( IX ) )*SMLNUM .OR. SCALE.EQ.ZERO )$ GO TO 20CALL DRSCL( N, SCALE, WORK, 1 )END IFGO TO 10END IF** Compute the estimate of the reciprocal condition number.*IF( AINVNM.NE.ZERO )$ RCOND = ( ONE / AINVNM ) / ANORM*20 CONTINUERETURN** End of DPOCON*ENDSUBROUTINE DPOEQU( N, A, LDA, S, SCOND, AMAX, INFO )** -- LAPACK routine (version 3.0) --* 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, NDOUBLE PRECISION AMAX, SCOND* ..* .. Array Arguments ..DOUBLE PRECISION A( LDA, * ), S( * )* ..** Purpose* =======** DPOEQU computes row and column scalings intended to equilibrate a* symmetric positive definite matrix A and reduce its condition number* (with respect to the two-norm). S contains the scale factors,* S(i) = 1/sqrt(A(i,i)), chosen so that the scaled matrix B with* elements B(i,j) = S(i)*A(i,j)*S(j) has ones on the diagonal. This* choice of S puts the condition number of B within a factor N of the* smallest possible condition number over all possible diagonal* scalings.** Arguments* =========** N (input) INTEGER* The order of the matrix A. N >= 0.** A (input) DOUBLE PRECISION array, dimension (LDA,N)* The N-by-N symmetric positive definite matrix whose scaling* factors are to be computed. Only the diagonal elements of A* are referenced.** LDA (input) INTEGER* The leading dimension of the array A. LDA >= max(1,N).** S (output) DOUBLE PRECISION array, dimension (N)* If INFO = 0, S contains the scale factors for A.** SCOND (output) DOUBLE PRECISION* If INFO = 0, S contains the ratio of the smallest S(i) to* the largest S(i). If SCOND >= 0.1 and AMAX is neither too* large nor too small, it is not worth scaling by S.** AMAX (output) DOUBLE PRECISION* Absolute value of largest matrix element. If AMAX is very* close to overflow or very close to underflow, the matrix* should be scaled.** INFO (output) INTEGER* = 0: successful exit* < 0: if INFO = -i, the i-th argument had an illegal value* > 0: if INFO = i, the i-th diagonal element is nonpositive.** =====================================================================** .. Parameters ..DOUBLE PRECISION ZERO, ONEPARAMETER ( ZERO = 0.0D+0, ONE = 1.0D+0 )* ..* .. Local Scalars ..INTEGER IDOUBLE PRECISION SMIN* ..* .. External Subroutines ..EXTERNAL XERBLA* ..* .. Intrinsic Functions ..INTRINSIC MAX, MIN, SQRT* ..* .. Executable Statements ..** Test the input parameters.*INFO = 0IF( N.LT.0 ) THENINFO = -1ELSE IF( LDA.LT.MAX( 1, N ) ) THENINFO = -3END IFIF( INFO.NE.0 ) THENCALL XERBLA( 'DPOEQU', -INFO )RETURNEND IF** Quick return if possible*IF( N.EQ.0 ) THENSCOND = ONEAMAX = ZERORETURNEND IF** Find the minimum and maximum diagonal elements.*S( 1 ) = A( 1, 1 )SMIN = S( 1 )AMAX = S( 1 )DO 10 I = 2, NS( I ) = A( I, I )SMIN = MIN( SMIN, S( I ) )AMAX = MAX( AMAX, S( I ) )10 CONTINUE*IF( SMIN.LE.ZERO ) THEN** Find the first non-positive diagonal element and return.*DO 20 I = 1, NIF( S( I ).LE.ZERO ) THENINFO = IRETURNEND IF20 CONTINUEELSE** Set the scale factors to the reciprocals* of the diagonal elements.*DO 30 I = 1, NS( I ) = ONE / SQRT( S( I ) )30 CONTINUE** Compute SCOND = min(S(I)) / max(S(I))*SCOND = SQRT( SMIN ) / SQRT( AMAX )END IFRETURN** End of DPOEQU*ENDSUBROUTINE DPORFS( UPLO, N, NRHS, A, LDA, AF, LDAF, B, LDB, X,$ LDX, FERR, BERR, WORK, IWORK, INFO )** -- LAPACK routine (version 3.0) --* Univ. of Tennessee, Univ. of California Berkeley, NAG Ltd.,* Courant Institute, Argonne National Lab, and Rice University* September 30, 1994** .. Scalar Arguments ..CHARACTER UPLOINTEGER INFO, LDA, LDAF, LDB, LDX, N, NRHS* ..* .. Array Arguments ..INTEGER IWORK( * )DOUBLE PRECISION A( LDA, * ), AF( LDAF, * ), B( LDB, * ),$ BERR( * ), FERR( * ), WORK( * ), X( LDX, * )* ..** Purpose* =======** DPORFS improves the computed solution to a system of linear* equations when the coefficient matrix is symmetric positive definite,* and provides error bounds and backward error estimates for the* solution.** 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.** NRHS (input) INTEGER* The number of right hand sides, i.e., the number of columns* of the matrices B and X. NRHS >= 0.** 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(1,N).** AF (input) DOUBLE PRECISION array, dimension (LDAF,N)* The triangular factor U or L from the Cholesky factorization* A = U**T*U or A = L*L**T, as computed by DPOTRF.** LDAF (input) INTEGER* The leading dimension of the array AF. LDAF >= max(1,N).** B (input) DOUBLE PRECISION array, dimension (LDB,NRHS)* The right hand side matrix B.** LDB (input) INTEGER* The leading dimension of the array B. LDB >= max(1,N).** X (input/output) DOUBLE PRECISION array, dimension (LDX,NRHS)* On entry, the solution matrix X, as computed by DPOTRS.* On exit, the improved solution matrix X.** LDX (input) INTEGER* The leading dimension of the array X. LDX >= max(1,N).** FERR (output) DOUBLE PRECISION array, dimension (NRHS)* The estimated forward error bound for each solution vector* X(j) (the j-th column of the solution matrix X).* If XTRUE is the true solution corresponding to X(j), FERR(j)* is an estimated upper bound for the magnitude of the largest* element in (X(j) - XTRUE) divided by the magnitude of the* largest element in X(j). The estimate is as reliable as* the estimate for RCOND, and is almost always a slight* overestimate of the true error.** BERR (output) DOUBLE PRECISION array, dimension (NRHS)* The componentwise relative backward error of each solution* vector X(j) (i.e., the smallest relative change in* any element of A or B that makes X(j) an exact solution).** WORK (workspace) DOUBLE PRECISION array, dimension (3*N)** IWORK (workspace) INTEGER array, dimension (N)** INFO (output) INTEGER* = 0: successful exit* < 0: if INFO = -i, the i-th argument had an illegal value** Internal Parameters* ===================** ITMAX is the maximum number of steps of iterative refinement.** =====================================================================** .. Parameters ..INTEGER ITMAXPARAMETER ( ITMAX = 5 )DOUBLE PRECISION ZEROPARAMETER ( ZERO = 0.0D+0 )DOUBLE PRECISION ONEPARAMETER ( ONE = 1.0D+0 )DOUBLE PRECISION TWOPARAMETER ( TWO = 2.0D+0 )DOUBLE PRECISION THREEPARAMETER ( THREE = 3.0D+0 )* ..* .. Local Scalars ..LOGICAL UPPERINTEGER COUNT, I, J, K, KASE, NZDOUBLE PRECISION EPS, LSTRES, S, SAFE1, SAFE2, SAFMIN, XK* ..* .. External Subroutines ..EXTERNAL DAXPY, DCOPY, DLACON, DPOTRS, DSYMV, XERBLA* ..* .. Intrinsic Functions ..INTRINSIC ABS, MAX* ..* .. External Functions ..LOGICAL LSAMEDOUBLE PRECISION DLAMCHEXTERNAL LSAME, DLAMCH* ..* .. Executable Statements ..** Test the input parameters.*INFO = 0UPPER = LSAME( UPLO, 'U' )IF( .NOT.UPPER .AND. .NOT.LSAME( UPLO, 'L' ) ) THENINFO = -1ELSE IF( N.LT.0 ) THENINFO = -2ELSE IF( NRHS.LT.0 ) THENINFO = -3ELSE IF( LDA.LT.MAX( 1, N ) ) THENINFO = -5ELSE IF( LDAF.LT.MAX( 1, N ) ) THENINFO = -7ELSE IF( LDB.LT.MAX( 1, N ) ) THENINFO = -9ELSE IF( LDX.LT.MAX( 1, N ) ) THENINFO = -11END IFIF( INFO.NE.0 ) THENCALL XERBLA( 'DPORFS', -INFO )RETURNEND IF** Quick return if possible*IF( N.EQ.0 .OR. NRHS.EQ.0 ) THENDO 10 J = 1, NRHSFERR( J ) = ZEROBERR( J ) = ZERO10 CONTINUERETURNEND IF** NZ = maximum number of nonzero elements in each row of A, plus 1*NZ = N + 1EPS = DLAMCH( 'Epsilon' )SAFMIN = DLAMCH( 'Safe minimum' )SAFE1 = NZ*SAFMINSAFE2 = SAFE1 / EPS** Do for each right hand side*DO 140 J = 1, NRHS*COUNT = 1LSTRES = THREE20 CONTINUE** Loop until stopping criterion is satisfied.** Compute residual R = B - A * X*CALL DCOPY( N, B( 1, J ), 1, WORK( N+1 ), 1 )CALL DSYMV( UPLO, N, -ONE, A, LDA, X( 1, J ), 1, ONE,$ WORK( N+1 ), 1 )** Compute componentwise relative backward error from formula** max(i) ( abs(R(i)) / ( abs(A)*abs(X) + abs(B) )(i) )** where abs(Z) is the componentwise absolute value of the matrix* or vector Z. If the i-th component of the denominator is less* than SAFE2, then SAFE1 is added to the i-th components of the* numerator and denominator before dividing.*DO 30 I = 1, NWORK( I ) = ABS( B( I, J ) )30 CONTINUE** Compute abs(A)*abs(X) + abs(B).*IF( UPPER ) THENDO 50 K = 1, NS = ZEROXK = ABS( X( K, J ) )DO 40 I = 1, K - 1WORK( I ) = WORK( I ) + ABS( A( I, K ) )*XKS = S + ABS( A( I, K ) )*ABS( X( I, J ) )40 CONTINUEWORK( K ) = WORK( K ) + ABS( A( K, K ) )*XK + S50 CONTINUEELSEDO 70 K = 1, NS = ZEROXK = ABS( X( K, J ) )WORK( K ) = WORK( K ) + ABS( A( K, K ) )*XKDO 60 I = K + 1, NWORK( I ) = WORK( I ) + ABS( A( I, K ) )*XKS = S + ABS( A( I, K ) )*ABS( X( I, J ) )60 CONTINUEWORK( K ) = WORK( K ) + S70 CONTINUEEND IFS = ZERODO 80 I = 1, NIF( WORK( I ).GT.SAFE2 ) THENS = MAX( S, ABS( WORK( N+I ) ) / WORK( I ) )ELSES = MAX( S, ( ABS( WORK( N+I ) )+SAFE1 ) /$ ( WORK( I )+SAFE1 ) )END IF80 CONTINUEBERR( J ) = S** Test stopping criterion. Continue iterating if* 1) The residual BERR(J) is larger than machine epsilon, and* 2) BERR(J) decreased by at least a factor of 2 during the* last iteration, and* 3) At most ITMAX iterations tried.*IF( BERR( J ).GT.EPS .AND. TWO*BERR( J ).LE.LSTRES .AND.$ COUNT.LE.ITMAX ) THEN** Update solution and try again.*CALL DPOTRS( UPLO, N, 1, AF, LDAF, WORK( N+1 ), N, INFO )CALL DAXPY( N, ONE, WORK( N+1 ), 1, X( 1, J ), 1 )LSTRES = BERR( J )COUNT = COUNT + 1GO TO 20END IF** Bound error from formula** norm(X - XTRUE) / norm(X) .le. FERR =* norm( abs(inv(A))** ( abs(R) + NZ*EPS*( abs(A)*abs(X)+abs(B) ))) / norm(X)** where* norm(Z) is the magnitude of the largest component of Z* inv(A) is the inverse of A* abs(Z) is the componentwise absolute value of the matrix or* vector Z* NZ is the maximum number of nonzeros in any row of A, plus 1* EPS is machine epsilon** The i-th component of abs(R)+NZ*EPS*(abs(A)*abs(X)+abs(B))* is incremented by SAFE1 if the i-th component of* abs(A)*abs(X) + abs(B) is less than SAFE2.** Use DLACON to estimate the infinity-norm of the matrix* inv(A) * diag(W),* where W = abs(R) + NZ*EPS*( abs(A)*abs(X)+abs(B) )))*DO 90 I = 1, NIF( WORK( I ).GT.SAFE2 ) THENWORK( I ) = ABS( WORK( N+I ) ) + NZ*EPS*WORK( I )ELSEWORK( I ) = ABS( WORK( N+I ) ) + NZ*EPS*WORK( I ) + SAFE1END IF90 CONTINUE*KASE = 0100 CONTINUECALL DLACON( N, WORK( 2*N+1 ), WORK( N+1 ), IWORK, FERR( J ),$ KASE )IF( KASE.NE.0 ) THENIF( KASE.EQ.1 ) THEN** Multiply by diag(W)*inv(A').*CALL DPOTRS( UPLO, N, 1, AF, LDAF, WORK( N+1 ), N, INFO )DO 110 I = 1, NWORK( N+I ) = WORK( I )*WORK( N+I )110 CONTINUEELSE IF( KASE.EQ.2 ) THEN** Multiply by inv(A)*diag(W).*DO 120 I = 1, NWORK( N+I ) = WORK( I )*WORK( N+I )120 CONTINUECALL DPOTRS( UPLO, N, 1, AF, LDAF, WORK( N+1 ), N, INFO )END IFGO TO 100END IF** Normalize error.*LSTRES = ZERODO 130 I = 1, NLSTRES = MAX( LSTRES, ABS( X( I, J ) ) )130 CONTINUEIF( LSTRES.NE.ZERO )$ FERR( J ) = FERR( J ) / LSTRES*140 CONTINUE*RETURN** End of DPORFS*ENDSUBROUTINE DPOTF2( UPLO, N, A, LDA, INFO )** -- LAPACK routine (version 3.0) --* Univ. of Tennessee, Univ. of California Berkeley, NAG Ltd.,* Courant Institute, Argonne National Lab, and Rice University* February 29, 1992** .. Scalar Arguments ..CHARACTER UPLOINTEGER INFO, LDA, N* ..* .. Array Arguments ..DOUBLE PRECISION A( LDA, * )* ..** Purpose* =======** DPOTF2 computes the Cholesky factorization of a real symmetric* positive definite matrix A.** The factorization has the form* A = U' * U , if UPLO = 'U', or* A = L * L', if UPLO = 'L',* where U is an upper triangular matrix and L is lower triangular.** 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, if INFO = 0, the factor U or L from the Cholesky* factorization A = U'*U or A = L*L'.** LDA (input) INTEGER* The leading dimension of the array A. LDA >= max(1,N).** INFO (output) INTEGER* = 0: successful exit* < 0: if INFO = -k, the k-th argument had an illegal value* > 0: if INFO = k, the leading minor of order k is not* positive definite, and the factorization could not be* completed.** =====================================================================** .. Parameters ..DOUBLE PRECISION ONE, ZEROPARAMETER ( ONE = 1.0D+0, ZERO = 0.0D+0 )* ..* .. Local Scalars ..LOGICAL UPPERINTEGER JDOUBLE PRECISION AJJ* ..* .. External Functions ..LOGICAL LSAMEDOUBLE PRECISION DDOTEXTERNAL LSAME, DDOT* ..* .. External Subroutines ..EXTERNAL DGEMV, DSCAL, XERBLA* ..* .. Intrinsic Functions ..INTRINSIC MAX, SQRT* ..* .. Executable Statements ..** Test the input parameters.*INFO = 0UPPER = LSAME( UPLO, 'U' )IF( .NOT.UPPER .AND. .NOT.LSAME( UPLO, 'L' ) ) THENINFO = -1ELSE IF( N.LT.0 ) THENINFO = -2ELSE IF( LDA.LT.MAX( 1, N ) ) THENINFO = -4END IFIF( INFO.NE.0 ) THENCALL XERBLA( 'DPOTF2', -INFO )RETURNEND IF** Quick return if possible*IF( N.EQ.0 )$ RETURN*IF( UPPER ) THEN** Compute the Cholesky factorization A = U'*U.*DO 10 J = 1, N** Compute U(J,J) and test for non-positive-definiteness.*AJJ = A( J, J ) - DDOT( J-1, A( 1, J ), 1, A( 1, J ), 1 )IF( AJJ.LE.ZERO ) THENA( J, J ) = AJJGO TO 30END IFAJJ = SQRT( AJJ )A( J, J ) = AJJ** Compute elements J+1:N of row J.*IF( J.LT.N ) THENCALL DGEMV( 'Transpose', J-1, N-J, -ONE, A( 1, J+1 ),$ LDA, A( 1, J ), 1, ONE, A( J, J+1 ), LDA )CALL DSCAL( N-J, ONE / AJJ, A( J, J+1 ), LDA )END IF10 CONTINUEELSE** Compute the Cholesky factorization A = L*L'.*DO 20 J = 1, N** Compute L(J,J) and test for non-positive-definiteness.*AJJ = A( J, J ) - DDOT( J-1, A( J, 1 ), LDA, A( J, 1 ),$ LDA )IF( AJJ.LE.ZERO ) THENA( J, J ) = AJJGO TO 30END IFAJJ = SQRT( AJJ )A( J, J ) = AJJ** Compute elements J+1:N of column J.*IF( J.LT.N ) THENCALL DGEMV( 'No transpose', N-J, J-1, -ONE, A( J+1, 1 ),$ LDA, A( J, 1 ), LDA, ONE, A( J+1, J ), 1 )CALL DSCAL( N-J, ONE / AJJ, A( J+1, J ), 1 )END IF20 CONTINUEEND IFGO TO 40*30 CONTINUEINFO = J*40 CONTINUERETURN** End of DPOTF2*ENDSUBROUTINE DPOTRF( UPLO, N, A, LDA, INFO )** -- LAPACK routine (version 3.0) --* Univ. of Tennessee, Univ. of California Berkeley, NAG Ltd.,* Courant Institute, Argonne National Lab, and Rice University* March 31, 1993** .. Scalar Arguments ..CHARACTER UPLOINTEGER INFO, LDA, N* ..* .. Array Arguments ..DOUBLE PRECISION A( LDA, * )* ..** Purpose* =======** DPOTRF computes the Cholesky factorization of a real symmetric* positive definite matrix A.** The factorization has the form* A = U**T * U, if UPLO = 'U', or* A = L * L**T, if UPLO = 'L',* where U is an upper triangular matrix and L is lower triangular.** This is the block version of the algorithm, calling Level 3 BLAS.** 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 INFO = 0, the factor U or L from the Cholesky* factorization A = U**T*U or A = L*L**T.** LDA (input) INTEGER* The leading dimension of the array A. LDA >= 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, the leading minor of order i is not* positive definite, and the factorization could not be* completed.** =====================================================================** .. Parameters ..DOUBLE PRECISION ONEPARAMETER ( ONE = 1.0D+0 )* ..* .. Local Scalars ..LOGICAL UPPERINTEGER J, JB, NB* ..* .. External Functions ..LOGICAL LSAMEINTEGER ILAENVEXTERNAL LSAME, ILAENV* ..* .. External Subroutines ..EXTERNAL DGEMM, DPOTF2, DSYRK, DTRSM, XERBLA* ..* .. Intrinsic Functions ..INTRINSIC MAX, MIN* ..* .. Executable Statements ..** Test the input parameters.*INFO = 0UPPER = LSAME( UPLO, 'U' )IF( .NOT.UPPER .AND. .NOT.LSAME( UPLO, 'L' ) ) THENINFO = -1ELSE IF( N.LT.0 ) THENINFO = -2ELSE IF( LDA.LT.MAX( 1, N ) ) THENINFO = -4END IFIF( INFO.NE.0 ) THENCALL XERBLA( 'DPOTRF', -INFO )RETURNEND IF** Quick return if possible*IF( N.EQ.0 )$ RETURN** Determine the block size for this environment.*NB = ILAENV( 1, 'DPOTRF', UPLO, N, -1, -1, -1 )IF( NB.LE.1 .OR. NB.GE.N ) THEN** Use unblocked code.*CALL DPOTF2( UPLO, N, A, LDA, INFO )ELSE** Use blocked code.*IF( UPPER ) THEN** Compute the Cholesky factorization A = U'*U.*DO 10 J = 1, N, NB** Update and factorize the current diagonal block and test* for non-positive-definiteness.*JB = MIN( NB, N-J+1 )CALL DSYRK( 'Upper', 'Transpose', JB, J-1, -ONE,$ A( 1, J ), LDA, ONE, A( J, J ), LDA )CALL DPOTF2( 'Upper', JB, A( J, J ), LDA, INFO )IF( INFO.NE.0 )$ GO TO 30IF( J+JB.LE.N ) THEN** Compute the current block row.*CALL DGEMM( 'Transpose', 'No transpose', JB, N-J-JB+1,$ J-1, -ONE, A( 1, J ), LDA, A( 1, J+JB ),$ LDA, ONE, A( J, J+JB ), LDA )CALL DTRSM( 'Left', 'Upper', 'Transpose', 'Non-unit',$ JB, N-J-JB+1, ONE, A( J, J ), LDA,$ A( J, J+JB ), LDA )END IF10 CONTINUE*ELSE** Compute the Cholesky factorization A = L*L'.*DO 20 J = 1, N, NB** Update and factorize the current diagonal block and test* for non-positive-definiteness.*JB = MIN( NB, N-J+1 )CALL DSYRK( 'Lower', 'No transpose', JB, J-1, -ONE,$ A( J, 1 ), LDA, ONE, A( J, J ), LDA )CALL DPOTF2( 'Lower', JB, A( J, J ), LDA, INFO )IF( INFO.NE.0 )$ GO TO 30IF( J+JB.LE.N ) THEN** Compute the current block column.*CALL DGEMM( 'No transpose', 'Transpose', N-J-JB+1, JB,$ J-1, -ONE, A( J+JB, 1 ), LDA, A( J, 1 ),$ LDA, ONE, A( J+JB, J ), LDA )CALL DTRSM( 'Right', 'Lower', 'Transpose', 'Non-unit',$ N-J-JB+1, JB, ONE, A( J, J ), LDA,$ A( J+JB, J ), LDA )END IF20 CONTINUEEND IFEND IFGO TO 40*30 CONTINUEINFO = INFO + J - 1*40 CONTINUERETURN** End of DPOTRF*ENDSUBROUTINE DPOTRI( UPLO, N, A, LDA, INFO )** -- LAPACK routine (version 3.0) --* Univ. of Tennessee, Univ. of California Berkeley, NAG Ltd.,* Courant Institute, Argonne National Lab, and Rice University* March 31, 1993** .. Scalar Arguments ..CHARACTER UPLOINTEGER INFO, LDA, N* ..* .. Array Arguments ..DOUBLE PRECISION A( LDA, * )* ..** Purpose* =======** DPOTRI computes the inverse of a real symmetric positive definite* matrix A using the Cholesky factorization A = U**T*U or A = L*L**T* computed by DPOTRF.** 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 triangular factor U or L from the Cholesky* factorization A = U**T*U or A = L*L**T, as computed by* DPOTRF.* On exit, the upper or lower triangle of the (symmetric)* inverse of A, overwriting the input factor U or L.** LDA (input) INTEGER* The leading dimension of the array A. LDA >= 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, the (i,i) element of the factor U or L is* zero, and the inverse could not be computed.** =====================================================================** .. External Functions ..LOGICAL LSAMEEXTERNAL LSAME* ..* .. External Subroutines ..EXTERNAL DLAUUM, DTRTRI, XERBLA* ..* .. Intrinsic Functions ..INTRINSIC MAX* ..* .. Executable Statements ..** Test the input parameters.*INFO = 0IF( .NOT.LSAME( UPLO, 'U' ) .AND. .NOT.LSAME( UPLO, 'L' ) ) THENINFO = -1ELSE IF( N.LT.0 ) THENINFO = -2ELSE IF( LDA.LT.MAX( 1, N ) ) THENINFO = -4END IFIF( INFO.NE.0 ) THENCALL XERBLA( 'DPOTRI', -INFO )RETURNEND IF** Quick return if possible*IF( N.EQ.0 )$ RETURN** Invert the triangular Cholesky factor U or L.*CALL DTRTRI( UPLO, 'Non-unit', N, A, LDA, INFO )IF( INFO.GT.0 )$ RETURN** Form inv(U)*inv(U)' or inv(L)'*inv(L).*CALL DLAUUM( UPLO, N, A, LDA, INFO )*RETURN** End of DPOTRI*ENDSUBROUTINE DPOTRS( UPLO, N, NRHS, A, LDA, B, LDB, INFO )** -- LAPACK routine (version 3.0) --* Univ. of Tennessee, Univ. of California Berkeley, NAG Ltd.,* Courant Institute, Argonne National Lab, and Rice University* March 31, 1993** .. Scalar Arguments ..CHARACTER UPLOINTEGER INFO, LDA, LDB, N, NRHS* ..* .. Array Arguments ..DOUBLE PRECISION A( LDA, * ), B( LDB, * )* ..** Purpose* =======** DPOTRS solves a system of linear equations A*X = B with a symmetric* positive definite matrix A using the Cholesky factorization* A = U**T*U or A = L*L**T computed by DPOTRF.** 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.** 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 triangular factor U or L from the Cholesky factorization* A = U**T*U or A = L*L**T, as computed by DPOTRF.** LDA (input) INTEGER* The leading dimension of the array A. LDA >= max(1,N).** 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 ONEPARAMETER ( ONE = 1.0D+0 )* ..* .. Local Scalars ..LOGICAL UPPER* ..* .. External Functions ..LOGICAL LSAMEEXTERNAL LSAME* ..* .. External Subroutines ..EXTERNAL DTRSM, XERBLA* ..* .. Intrinsic Functions ..INTRINSIC MAX* ..* .. Executable Statements ..** Test the input parameters.*INFO = 0UPPER = LSAME( UPLO, 'U' )IF( .NOT.UPPER .AND. .NOT.LSAME( UPLO, 'L' ) ) THENINFO = -1ELSE IF( N.LT.0 ) THENINFO = -2ELSE IF( NRHS.LT.0 ) THENINFO = -3ELSE IF( LDA.LT.MAX( 1, N ) ) THENINFO = -5ELSE IF( LDB.LT.MAX( 1, N ) ) THENINFO = -7END IFIF( INFO.NE.0 ) THENCALL XERBLA( 'DPOTRS', -INFO )RETURNEND IF** Quick return if possible*IF( N.EQ.0 .OR. NRHS.EQ.0 )$ RETURN*IF( UPPER ) THEN** Solve A*X = B where A = U'*U.** Solve U'*X = B, overwriting B with X.*CALL DTRSM( 'Left', 'Upper', 'Transpose', 'Non-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 where A = L*L'.** Solve L*X = B, overwriting B with X.*CALL DTRSM( 'Left', 'Lower', 'No transpose', 'Non-unit', N,$ NRHS, ONE, A, LDA, B, LDB )** Solve L'*X = B, overwriting B with X.*CALL DTRSM( 'Left', 'Lower', 'Transpose', 'Non-unit', N, NRHS,$ ONE, A, LDA, B, LDB )END IF*RETURN** End of DPOTRS*ENDSUBROUTINE DPPCON( UPLO, N, AP, ANORM, RCOND, WORK, IWORK, INFO )** -- LAPACK routine (version 3.0) --* Univ. of Tennessee, Univ. of California Berkeley, NAG Ltd.,* Courant Institute, Argonne National Lab, and Rice University* March 31, 1993** .. Scalar Arguments ..CHARACTER UPLOINTEGER INFO, NDOUBLE PRECISION ANORM, RCOND* ..* .. Array Arguments ..INTEGER IWORK( * )DOUBLE PRECISION AP( * ), WORK( * )* ..** Purpose* =======** DPPCON estimates the reciprocal of the condition number (in the* 1-norm) of a real symmetric positive definite packed matrix using* the Cholesky factorization A = U**T*U or A = L*L**T computed by* DPPTRF.** An estimate is obtained for norm(inv(A)), and the reciprocal of the* condition number is computed as RCOND = 1 / (ANORM * norm(inv(A))).** 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.** AP (input) DOUBLE PRECISION array, dimension (N*(N+1)/2)* The triangular factor U or L from the Cholesky factorization* A = U**T*U or A = L*L**T, packed columnwise in a linear* array. The j-th column of U or L is stored in the array AP* as follows:* if UPLO = 'U', AP(i + (j-1)*j/2) = U(i,j) for 1<=i<=j;* if UPLO = 'L', AP(i + (j-1)*(2n-j)/2) = L(i,j) for j<=i<=n.** ANORM (input) DOUBLE PRECISION* The 1-norm (or infinity-norm) of the symmetric matrix A.** RCOND (output) DOUBLE PRECISION* The reciprocal of the condition number of the matrix A,* computed as RCOND = 1/(ANORM * AINVNM), where AINVNM is an* estimate of the 1-norm of inv(A) computed in this routine.** WORK (workspace) DOUBLE PRECISION array, dimension (3*N)** IWORK (workspace) INTEGER array, dimension (N)** INFO (output) INTEGER* = 0: successful exit* < 0: if INFO = -i, the i-th argument had an illegal value** =====================================================================** .. Parameters ..DOUBLE PRECISION ONE, ZEROPARAMETER ( ONE = 1.0D+0, ZERO = 0.0D+0 )* ..* .. Local Scalars ..LOGICAL UPPERCHARACTER NORMININTEGER IX, KASEDOUBLE PRECISION AINVNM, SCALE, SCALEL, SCALEU, SMLNUM* ..* .. External Functions ..LOGICAL LSAMEINTEGER IDAMAXDOUBLE PRECISION DLAMCHEXTERNAL LSAME, IDAMAX, DLAMCH* ..* .. External Subroutines ..EXTERNAL DLACON, DLATPS, DRSCL, XERBLA* ..* .. Intrinsic Functions ..INTRINSIC ABS* ..* .. Executable Statements ..** Test the input parameters.*INFO = 0UPPER = LSAME( UPLO, 'U' )IF( .NOT.UPPER .AND. .NOT.LSAME( UPLO, 'L' ) ) THENINFO = -1ELSE IF( N.LT.0 ) THENINFO = -2ELSE IF( ANORM.LT.ZERO ) THENINFO = -4END IFIF( INFO.NE.0 ) THENCALL XERBLA( 'DPPCON', -INFO )RETURNEND IF** Quick return if possible*RCOND = ZEROIF( N.EQ.0 ) THENRCOND = ONERETURNELSE IF( ANORM.EQ.ZERO ) THENRETURNEND IF*SMLNUM = DLAMCH( 'Safe minimum' )** Estimate the 1-norm of the inverse.*KASE = 0NORMIN = 'N'10 CONTINUECALL DLACON( N, WORK( N+1 ), WORK, IWORK, AINVNM, KASE )IF( KASE.NE.0 ) THENIF( UPPER ) THEN** Multiply by inv(U').*CALL DLATPS( 'Upper', 'Transpose', 'Non-unit', NORMIN, N,$ AP, WORK, SCALEL, WORK( 2*N+1 ), INFO )NORMIN = 'Y'** Multiply by inv(U).*CALL DLATPS( 'Upper', 'No transpose', 'Non-unit', NORMIN, N,$ AP, WORK, SCALEU, WORK( 2*N+1 ), INFO )ELSE** Multiply by inv(L).*CALL DLATPS( 'Lower', 'No transpose', 'Non-unit', NORMIN, N,$ AP, WORK, SCALEL, WORK( 2*N+1 ), INFO )NORMIN = 'Y'** Multiply by inv(L').*CALL DLATPS( 'Lower', 'Transpose', 'Non-unit', NORMIN, N,$ AP, WORK, SCALEU, WORK( 2*N+1 ), INFO )END IF** Multiply by 1/SCALE if doing so will not cause overflow.*SCALE = SCALEL*SCALEUIF( SCALE.NE.ONE ) THENIX = IDAMAX( N, WORK, 1 )IF( SCALE.LT.ABS( WORK( IX ) )*SMLNUM .OR. SCALE.EQ.ZERO )$ GO TO 20CALL DRSCL( N, SCALE, WORK, 1 )END IFGO TO 10END IF** Compute the estimate of the reciprocal condition number.*IF( AINVNM.NE.ZERO )$ RCOND = ( ONE / AINVNM ) / ANORM*20 CONTINUERETURN** End of DPPCON*ENDSUBROUTINE DPPEQU( UPLO, N, AP, S, SCOND, AMAX, INFO )** -- LAPACK routine (version 3.0) --* Univ. of Tennessee, Univ. of California Berkeley, NAG Ltd.,* Courant Institute, Argonne National Lab, and Rice University* March 31, 1993** .. Scalar Arguments ..CHARACTER UPLOINTEGER INFO, NDOUBLE PRECISION AMAX, SCOND* ..* .. Array Arguments ..DOUBLE PRECISION AP( * ), S( * )* ..** Purpose* =======** DPPEQU computes row and column scalings intended to equilibrate a* symmetric positive definite matrix A in packed storage and reduce* its condition number (with respect to the two-norm). S contains the* scale factors, S(i)=1/sqrt(A(i,i)), chosen so that the scaled matrix* B with elements B(i,j)=S(i)*A(i,j)*S(j) has ones on the diagonal.* This choice of S puts the condition number of B within a factor N of* the smallest possible condition number over all possible diagonal* scalings.** 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.** AP (input) DOUBLE PRECISION array, dimension (N*(N+1)/2)* The upper or lower triangle of the symmetric matrix A, packed* columnwise in a linear array. The j-th column of A is stored* in the array AP as follows:* if UPLO = 'U', AP(i + (j-1)*j/2) = A(i,j) for 1<=i<=j;* if UPLO = 'L', AP(i + (j-1)*(2n-j)/2) = A(i,j) for j<=i<=n.** S (output) DOUBLE PRECISION array, dimension (N)* If INFO = 0, S contains the scale factors for A.** SCOND (output) DOUBLE PRECISION* If INFO = 0, S contains the ratio of the smallest S(i) to* the largest S(i). If SCOND >= 0.1 and AMAX is neither too* large nor too small, it is not worth scaling by S.** AMAX (output) DOUBLE PRECISION* Absolute value of largest matrix element. If AMAX is very* close to overflow or very close to underflow, the matrix* should be scaled.** INFO (output) INTEGER* = 0: successful exit* < 0: if INFO = -i, the i-th argument had an illegal value* > 0: if INFO = i, the i-th diagonal element is nonpositive.** =====================================================================** .. Parameters ..DOUBLE PRECISION ONE, ZEROPARAMETER ( ONE = 1.0D+0, ZERO = 0.0D+0 )* ..* .. Local Scalars ..LOGICAL UPPERINTEGER I, JJDOUBLE PRECISION SMIN* ..* .. External Functions ..LOGICAL LSAMEEXTERNAL LSAME* ..* .. External Subroutines ..EXTERNAL XERBLA* ..* .. Intrinsic Functions ..INTRINSIC MAX, MIN, SQRT* ..* .. Executable Statements ..** Test the input parameters.*INFO = 0UPPER = LSAME( UPLO, 'U' )IF( .NOT.UPPER .AND. .NOT.LSAME( UPLO, 'L' ) ) THENINFO = -1ELSE IF( N.LT.0 ) THENINFO = -2END IFIF( INFO.NE.0 ) THENCALL XERBLA( 'DPPEQU', -INFO )RETURNEND IF** Quick return if possible*IF( N.EQ.0 ) THENSCOND = ONEAMAX = ZERORETURNEND IF** Initialize SMIN and AMAX.*S( 1 ) = AP( 1 )SMIN = S( 1 )AMAX = S( 1 )*IF( UPPER ) THEN** UPLO = 'U': Upper triangle of A is stored.* Find the minimum and maximum diagonal elements.*JJ = 1DO 10 I = 2, NJJ = JJ + IS( I ) = AP( JJ )SMIN = MIN( SMIN, S( I ) )AMAX = MAX( AMAX, S( I ) )10 CONTINUE*ELSE** UPLO = 'L': Lower triangle of A is stored.* Find the minimum and maximum diagonal elements.*JJ = 1DO 20 I = 2, NJJ = JJ + N - I + 2S( I ) = AP( JJ )SMIN = MIN( SMIN, S( I ) )AMAX = MAX( AMAX, S( I ) )20 CONTINUEEND IF*IF( SMIN.LE.ZERO ) THEN** Find the first non-positive diagonal element and return.*DO 30 I = 1, NIF( S( I ).LE.ZERO ) THENINFO = IRETURNEND IF30 CONTINUEELSE** Set the scale factors to the reciprocals* of the diagonal elements.*DO 40 I = 1, NS( I ) = ONE / SQRT( S( I ) )40 CONTINUE** Compute SCOND = min(S(I)) / max(S(I))*SCOND = SQRT( SMIN ) / SQRT( AMAX )END IFRETURN** End of DPPEQU*ENDSUBROUTINE DPPRFS( UPLO, N, NRHS, AP, AFP, B, LDB, X, LDX, FERR,$ BERR, WORK, IWORK, INFO )** -- LAPACK routine (version 3.0) --* Univ. of Tennessee, Univ. of California Berkeley, NAG Ltd.,* Courant Institute, Argonne National Lab, and Rice University* September 30, 1994** .. Scalar Arguments ..CHARACTER UPLOINTEGER INFO, LDB, LDX, N, NRHS* ..* .. Array Arguments ..INTEGER IWORK( * )DOUBLE PRECISION AFP( * ), AP( * ), B( LDB, * ), BERR( * ),$ FERR( * ), WORK( * ), X( LDX, * )* ..** Purpose* =======** DPPRFS improves the computed solution to a system of linear* equations when the coefficient matrix is symmetric positive definite* and packed, and provides error bounds and backward error estimates* for the solution.** 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.** NRHS (input) INTEGER* The number of right hand sides, i.e., the number of columns* of the matrices B and X. NRHS >= 0.** AP (input) DOUBLE PRECISION array, dimension (N*(N+1)/2)* The upper or lower triangle of the symmetric matrix A, packed* columnwise in a linear array. The j-th column of A is stored* in the array AP as follows:* if UPLO = 'U', AP(i + (j-1)*j/2) = A(i,j) for 1<=i<=j;* if UPLO = 'L', AP(i + (j-1)*(2n-j)/2) = A(i,j) for j<=i<=n.** AFP (input) DOUBLE PRECISION array, dimension (N*(N+1)/2)* The triangular factor U or L from the Cholesky factorization* A = U**T*U or A = L*L**T, as computed by DPPTRF/ZPPTRF,* packed columnwise in a linear array in the same format as A* (see AP).** B (input) DOUBLE PRECISION array, dimension (LDB,NRHS)* The right hand side matrix B.** LDB (input) INTEGER* The leading dimension of the array B. LDB >= max(1,N).** X (input/output) DOUBLE PRECISION array, dimension (LDX,NRHS)* On entry, the solution matrix X, as computed by DPPTRS.* On exit, the improved solution matrix X.** LDX (input) INTEGER* The leading dimension of the array X. LDX >= max(1,N).** FERR (output) DOUBLE PRECISION array, dimension (NRHS)* The estimated forward error bound for each solution vector* X(j) (the j-th column of the solution matrix X).* If XTRUE is the true solution corresponding to X(j), FERR(j)* is an estimated upper bound for the magnitude of the largest* element in (X(j) - XTRUE) divided by the magnitude of the* largest element in X(j). The estimate is as reliable as* the estimate for RCOND, and is almost always a slight* overestimate of the true error.** BERR (output) DOUBLE PRECISION array, dimension (NRHS)* The componentwise relative backward error of each solution* vector X(j) (i.e., the smallest relative change in* any element of A or B that makes X(j) an exact solution).** WORK (workspace) DOUBLE PRECISION array, dimension (3*N)** IWORK (workspace) INTEGER array, dimension (N)** INFO (output) INTEGER* = 0: successful exit* < 0: if INFO = -i, the i-th argument had an illegal value** Internal Parameters* ===================** ITMAX is the maximum number of steps of iterative refinement.** =====================================================================** .. Parameters ..INTEGER ITMAXPARAMETER ( ITMAX = 5 )DOUBLE PRECISION ZEROPARAMETER ( ZERO = 0.0D+0 )DOUBLE PRECISION ONEPARAMETER ( ONE = 1.0D+0 )DOUBLE PRECISION TWOPARAMETER ( TWO = 2.0D+0 )DOUBLE PRECISION THREEPARAMETER ( THREE = 3.0D+0 )* ..* .. Local Scalars ..LOGICAL UPPERINTEGER COUNT, I, IK, J, K, KASE, KK, NZDOUBLE PRECISION EPS, LSTRES, S, SAFE1, SAFE2, SAFMIN, XK* ..* .. External Subroutines ..EXTERNAL DAXPY, DCOPY, DLACON, DPPTRS, DSPMV, XERBLA* ..* .. Intrinsic Functions ..INTRINSIC ABS, MAX* ..* .. External Functions ..LOGICAL LSAMEDOUBLE PRECISION DLAMCHEXTERNAL LSAME, DLAMCH* ..* .. Executable Statements ..** Test the input parameters.*INFO = 0UPPER = LSAME( UPLO, 'U' )IF( .NOT.UPPER .AND. .NOT.LSAME( UPLO, 'L' ) ) THENINFO = -1ELSE IF( N.LT.0 ) THENINFO = -2ELSE IF( NRHS.LT.0 ) THENINFO = -3ELSE IF( LDB.LT.MAX( 1, N ) ) THENINFO = -7ELSE IF( LDX.LT.MAX( 1, N ) ) THENINFO = -9END IFIF( INFO.NE.0 ) THENCALL XERBLA( 'DPPRFS', -INFO )RETURNEND IF** Quick return if possible*IF( N.EQ.0 .OR. NRHS.EQ.0 ) THENDO 10 J = 1, NRHSFERR( J ) = ZEROBERR( J ) = ZERO10 CONTINUERETURNEND IF** NZ = maximum number of nonzero elements in each row of A, plus 1*NZ = N + 1EPS = DLAMCH( 'Epsilon' )SAFMIN = DLAMCH( 'Safe minimum' )SAFE1 = NZ*SAFMINSAFE2 = SAFE1 / EPS** Do for each right hand side*DO 140 J = 1, NRHS*COUNT = 1LSTRES = THREE20 CONTINUE** Loop until stopping criterion is satisfied.** Compute residual R = B - A * X*CALL DCOPY( N, B( 1, J ), 1, WORK( N+1 ), 1 )CALL DSPMV( UPLO, N, -ONE, AP, X( 1, J ), 1, ONE, WORK( N+1 ),$ 1 )** Compute componentwise relative backward error from formula** max(i) ( abs(R(i)) / ( abs(A)*abs(X) + abs(B) )(i) )** where abs(Z) is the componentwise absolute value of the matrix* or vector Z. If the i-th component of the denominator is less* than SAFE2, then SAFE1 is added to the i-th components of the* numerator and denominator before dividing.*DO 30 I = 1, NWORK( I ) = ABS( B( I, J ) )30 CONTINUE** Compute abs(A)*abs(X) + abs(B).*KK = 1IF( UPPER ) THENDO 50 K = 1, NS = ZEROXK = ABS( X( K, J ) )IK = KKDO 40 I = 1, K - 1WORK( I ) = WORK( I ) + ABS( AP( IK ) )*XKS = S + ABS( AP( IK ) )*ABS( X( I, J ) )IK = IK + 140 CONTINUEWORK( K ) = WORK( K ) + ABS( AP( KK+K-1 ) )*XK + SKK = KK + K50 CONTINUEELSEDO 70 K = 1, NS = ZEROXK = ABS( X( K, J ) )WORK( K ) = WORK( K ) + ABS( AP( KK ) )*XKIK = KK + 1DO 60 I = K + 1, NWORK( I ) = WORK( I ) + ABS( AP( IK ) )*XKS = S + ABS( AP( IK ) )*ABS( X( I, J ) )IK = IK + 160 CONTINUEWORK( K ) = WORK( K ) + SKK = KK + ( N-K+1 )70 CONTINUEEND IFS = ZERODO 80 I = 1, NIF( WORK( I ).GT.SAFE2 ) THENS = MAX( S, ABS( WORK( N+I ) ) / WORK( I ) )ELSES = MAX( S, ( ABS( WORK( N+I ) )+SAFE1 ) /$ ( WORK( I )+SAFE1 ) )END IF80 CONTINUEBERR( J ) = S** Test stopping criterion. Continue iterating if* 1) The residual BERR(J) is larger than machine epsilon, and* 2) BERR(J) decreased by at least a factor of 2 during the* last iteration, and* 3) At most ITMAX iterations tried.*IF( BERR( J ).GT.EPS .AND. TWO*BERR( J ).LE.LSTRES .AND.$ COUNT.LE.ITMAX ) THEN** Update solution and try again.*CALL DPPTRS( UPLO, N, 1, AFP, WORK( N+1 ), N, INFO )CALL DAXPY( N, ONE, WORK( N+1 ), 1, X( 1, J ), 1 )LSTRES = BERR( J )COUNT = COUNT + 1GO TO 20END IF** Bound error from formula** norm(X - XTRUE) / norm(X) .le. FERR =* norm( abs(inv(A))** ( abs(R) + NZ*EPS*( abs(A)*abs(X)+abs(B) ))) / norm(X)** where* norm(Z) is the magnitude of the largest component of Z* inv(A) is the inverse of A* abs(Z) is the componentwise absolute value of the matrix or* vector Z* NZ is the maximum number of nonzeros in any row of A, plus 1* EPS is machine epsilon** The i-th component of abs(R)+NZ*EPS*(abs(A)*abs(X)+abs(B))* is incremented by SAFE1 if the i-th component of* abs(A)*abs(X) + abs(B) is less than SAFE2.** Use DLACON to estimate the infinity-norm of the matrix* inv(A) * diag(W),* where W = abs(R) + NZ*EPS*( abs(A)*abs(X)+abs(B) )))*DO 90 I = 1, NIF( WORK( I ).GT.SAFE2 ) THENWORK( I ) = ABS( WORK( N+I ) ) + NZ*EPS*WORK( I )ELSEWORK( I ) = ABS( WORK( N+I ) ) + NZ*EPS*WORK( I ) + SAFE1END IF90 CONTINUE*KASE = 0100 CONTINUECALL DLACON( N, WORK( 2*N+1 ), WORK( N+1 ), IWORK, FERR( J ),$ KASE )IF( KASE.NE.0 ) THENIF( KASE.EQ.1 ) THEN** Multiply by diag(W)*inv(A').*CALL DPPTRS( UPLO, N, 1, AFP, WORK( N+1 ), N, INFO )DO 110 I = 1, NWORK( N+I ) = WORK( I )*WORK( N+I )110 CONTINUEELSE IF( KASE.EQ.2 ) THEN** Multiply by inv(A)*diag(W).*DO 120 I = 1, NWORK( N+I ) = WORK( I )*WORK( N+I )120 CONTINUECALL DPPTRS( UPLO, N, 1, AFP, WORK( N+1 ), N, INFO )END IFGO TO 100END IF** Normalize error.*LSTRES = ZERODO 130 I = 1, NLSTRES = MAX( LSTRES, ABS( X( I, J ) ) )130 CONTINUEIF( LSTRES.NE.ZERO )$ FERR( J ) = FERR( J ) / LSTRES*140 CONTINUE*RETURN** End of DPPRFS*ENDSUBROUTINE DPPTRF( UPLO, N, AP, INFO )** -- LAPACK routine (version 3.0) --* Univ. of Tennessee, Univ. of California Berkeley, NAG Ltd.,* Courant Institute, Argonne National Lab, and Rice University* March 31, 1993** .. Scalar Arguments ..CHARACTER UPLOINTEGER INFO, N* ..* .. Array Arguments ..DOUBLE PRECISION AP( * )* ..** Purpose* =======** DPPTRF computes the Cholesky factorization of a real symmetric* positive definite matrix A stored in packed format.** The factorization has the form* A = U**T * U, if UPLO = 'U', or* A = L * L**T, if UPLO = 'L',* where U is an upper triangular matrix and L is lower triangular.** 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.** AP (input/output) DOUBLE PRECISION array, dimension (N*(N+1)/2)* On entry, the upper or lower triangle of the symmetric matrix* A, packed columnwise in a linear array. The j-th column of A* is stored in the array AP as follows:* if UPLO = 'U', AP(i + (j-1)*j/2) = A(i,j) for 1<=i<=j;* if UPLO = 'L', AP(i + (j-1)*(2n-j)/2) = A(i,j) for j<=i<=n.* See below for further details.** On exit, if INFO = 0, the triangular factor U or L from the* Cholesky factorization A = U**T*U or A = L*L**T, in the same* storage format as A.** INFO (output) INTEGER* = 0: successful exit* < 0: if INFO = -i, the i-th argument had an illegal value* > 0: if INFO = i, the leading minor of order i is not* positive definite, and the factorization could not be* completed.** Further Details* ======= =======** The packed storage scheme is illustrated by the following example* when N = 4, UPLO = 'U':** Two-dimensional storage of the symmetric matrix A:** a11 a12 a13 a14* a22 a23 a24* a33 a34 (aij = aji)* a44** Packed storage of the upper triangle of A:** AP = [ a11, a12, a22, a13, a23, a33, a14, a24, a34, a44 ]** =====================================================================** .. Parameters ..DOUBLE PRECISION ONE, ZEROPARAMETER ( ONE = 1.0D+0, ZERO = 0.0D+0 )* ..* .. Local Scalars ..LOGICAL UPPERINTEGER J, JC, JJDOUBLE PRECISION AJJ* ..* .. External Functions ..LOGICAL LSAMEDOUBLE PRECISION DDOTEXTERNAL LSAME, DDOT* ..* .. External Subroutines ..EXTERNAL DSCAL, DSPR, DTPSV, XERBLA* ..* .. Intrinsic Functions ..INTRINSIC SQRT* ..* .. Executable Statements ..** Test the input parameters.*INFO = 0UPPER = LSAME( UPLO, 'U' )IF( .NOT.UPPER .AND. .NOT.LSAME( UPLO, 'L' ) ) THENINFO = -1ELSE IF( N.LT.0 ) THENINFO = -2END IFIF( INFO.NE.0 ) THENCALL XERBLA( 'DPPTRF', -INFO )RETURNEND IF** Quick return if possible*IF( N.EQ.0 )$ RETURN*IF( UPPER ) THEN** Compute the Cholesky factorization A = U'*U.*JJ = 0DO 10 J = 1, NJC = JJ + 1JJ = JJ + J** Compute elements 1:J-1 of column J.*IF( J.GT.1 )$ CALL DTPSV( 'Upper', 'Transpose', 'Non-unit', J-1, AP,$ AP( JC ), 1 )** Compute U(J,J) and test for non-positive-definiteness.*AJJ = AP( JJ ) - DDOT( J-1, AP( JC ), 1, AP( JC ), 1 )IF( AJJ.LE.ZERO ) THENAP( JJ ) = AJJGO TO 30END IFAP( JJ ) = SQRT( AJJ )10 CONTINUEELSE** Compute the Cholesky factorization A = L*L'.*JJ = 1DO 20 J = 1, N** Compute L(J,J) and test for non-positive-definiteness.*AJJ = AP( JJ )IF( AJJ.LE.ZERO ) THENAP( JJ ) = AJJGO TO 30END IFAJJ = SQRT( AJJ )AP( JJ ) = AJJ** Compute elements J+1:N of column J and update the trailing* submatrix.*IF( J.LT.N ) THENCALL DSCAL( N-J, ONE / AJJ, AP( JJ+1 ), 1 )CALL DSPR( 'Lower', N-J, -ONE, AP( JJ+1 ), 1,$ AP( JJ+N-J+1 ) )JJ = JJ + N - J + 1END IF20 CONTINUEEND IFGO TO 40*30 CONTINUEINFO = J*40 CONTINUERETURN** End of DPPTRF*ENDSUBROUTINE DPPTRI( UPLO, N, AP, INFO )** -- LAPACK routine (version 3.0) --* Univ. of Tennessee, Univ. of California Berkeley, NAG Ltd.,* Courant Institute, Argonne National Lab, and Rice University* March 31, 1993** .. Scalar Arguments ..CHARACTER UPLOINTEGER INFO, N* ..* .. Array Arguments ..DOUBLE PRECISION AP( * )* ..** Purpose* =======** DPPTRI computes the inverse of a real symmetric positive definite* matrix A using the Cholesky factorization A = U**T*U or A = L*L**T* computed by DPPTRF.** Arguments* =========** UPLO (input) CHARACTER*1* = 'U': Upper triangular factor is stored in AP;* = 'L': Lower triangular factor is stored in AP.** N (input) INTEGER* The order of the matrix A. N >= 0.** AP (input/output) DOUBLE PRECISION array, dimension (N*(N+1)/2)* On entry, the triangular factor U or L from the Cholesky* factorization A = U**T*U or A = L*L**T, packed columnwise as* a linear array. The j-th column of U or L is stored in the* array AP as follows:* if UPLO = 'U', AP(i + (j-1)*j/2) = U(i,j) for 1<=i<=j;* if UPLO = 'L', AP(i + (j-1)*(2n-j)/2) = L(i,j) for j<=i<=n.** On exit, the upper or lower triangle of the (symmetric)* inverse of A, overwriting the input factor U or L.** INFO (output) INTEGER* = 0: successful exit* < 0: if INFO = -i, the i-th argument had an illegal value* > 0: if INFO = i, the (i,i) element of the factor U or L is* zero, and the inverse could not be computed.** =====================================================================** .. Parameters ..DOUBLE PRECISION ONEPARAMETER ( ONE = 1.0D+0 )* ..* .. Local Scalars ..LOGICAL UPPERINTEGER J, JC, JJ, JJNDOUBLE PRECISION AJJ* ..* .. External Functions ..LOGICAL LSAMEDOUBLE PRECISION DDOTEXTERNAL LSAME, DDOT* ..* .. External Subroutines ..EXTERNAL DSCAL, DSPR, DTPMV, DTPTRI, XERBLA* ..* .. Executable Statements ..** Test the input parameters.*INFO = 0UPPER = LSAME( UPLO, 'U' )IF( .NOT.UPPER .AND. .NOT.LSAME( UPLO, 'L' ) ) THENINFO = -1ELSE IF( N.LT.0 ) THENINFO = -2END IFIF( INFO.NE.0 ) THENCALL XERBLA( 'DPPTRI', -INFO )RETURNEND IF** Quick return if possible*IF( N.EQ.0 )$ RETURN** Invert the triangular Cholesky factor U or L.*CALL DTPTRI( UPLO, 'Non-unit', N, AP, INFO )IF( INFO.GT.0 )$ RETURN*IF( UPPER ) THEN** Compute the product inv(U) * inv(U)'.*JJ = 0DO 10 J = 1, NJC = JJ + 1JJ = JJ + JIF( J.GT.1 )$ CALL DSPR( 'Upper', J-1, ONE, AP( JC ), 1, AP )AJJ = AP( JJ )CALL DSCAL( J, AJJ, AP( JC ), 1 )10 CONTINUE*ELSE** Compute the product inv(L)' * inv(L).*JJ = 1DO 20 J = 1, NJJN = JJ + N - J + 1AP( JJ ) = DDOT( N-J+1, AP( JJ ), 1, AP( JJ ), 1 )IF( J.LT.N )$ CALL DTPMV( 'Lower', 'Transpose', 'Non-unit', N-J,$ AP( JJN ), AP( JJ+1 ), 1 )JJ = JJN20 CONTINUEEND IF*RETURN** End of DPPTRI*ENDSUBROUTINE DPPTRS( UPLO, N, NRHS, AP, B, LDB, INFO )** -- LAPACK routine (version 3.0) --* Univ. of Tennessee, Univ. of California Berkeley, NAG Ltd.,* Courant Institute, Argonne National Lab, and Rice University* March 31, 1993** .. Scalar Arguments ..CHARACTER UPLOINTEGER INFO, LDB, N, NRHS* ..* .. Array Arguments ..DOUBLE PRECISION AP( * ), B( LDB, * )* ..** Purpose* =======** DPPTRS solves a system of linear equations A*X = B with a symmetric* positive definite matrix A in packed storage using the Cholesky* factorization A = U**T*U or A = L*L**T computed by DPPTRF.** 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.** NRHS (input) INTEGER* The number of right hand sides, i.e., the number of columns* of the matrix B. NRHS >= 0.** AP (input) DOUBLE PRECISION array, dimension (N*(N+1)/2)* The triangular factor U or L from the Cholesky factorization* A = U**T*U or A = L*L**T, packed columnwise in a linear* array. The j-th column of U or L is stored in the array AP* as follows:* if UPLO = 'U', AP(i + (j-1)*j/2) = U(i,j) for 1<=i<=j;* if UPLO = 'L', AP(i + (j-1)*(2n-j)/2) = L(i,j) for j<=i<=n.** 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** =====================================================================** .. Local Scalars ..LOGICAL UPPERINTEGER I* ..* .. External Functions ..LOGICAL LSAMEEXTERNAL LSAME* ..* .. External Subroutines ..EXTERNAL DTPSV, XERBLA* ..* .. Intrinsic Functions ..INTRINSIC MAX* ..* .. Executable Statements ..** Test the input parameters.*INFO = 0UPPER = LSAME( UPLO, 'U' )IF( .NOT.UPPER .AND. .NOT.LSAME( UPLO, 'L' ) ) THENINFO = -1ELSE IF( N.LT.0 ) THENINFO = -2ELSE IF( NRHS.LT.0 ) THENINFO = -3ELSE IF( LDB.LT.MAX( 1, N ) ) THENINFO = -6END IFIF( INFO.NE.0 ) THENCALL XERBLA( 'DPPTRS', -INFO )RETURNEND IF** Quick return if possible*IF( N.EQ.0 .OR. NRHS.EQ.0 )$ RETURN*IF( UPPER ) THEN** Solve A*X = B where A = U'*U.*DO 10 I = 1, NRHS** Solve U'*X = B, overwriting B with X.*CALL DTPSV( 'Upper', 'Transpose', 'Non-unit', N, AP,$ B( 1, I ), 1 )** Solve U*X = B, overwriting B with X.*CALL DTPSV( 'Upper', 'No transpose', 'Non-unit', N, AP,$ B( 1, I ), 1 )10 CONTINUEELSE** Solve A*X = B where A = L*L'.*DO 20 I = 1, NRHS** Solve L*Y = B, overwriting B with X.*CALL DTPSV( 'Lower', 'No transpose', 'Non-unit', N, AP,$ B( 1, I ), 1 )** Solve L'*X = Y, overwriting B with X.*CALL DTPSV( 'Lower', 'Transpose', 'Non-unit', N, AP,$ B( 1, I ), 1 )20 CONTINUEEND IF*RETURN** End of DPPTRS*ENDSUBROUTINE DPTCON( N, D, E, ANORM, RCOND, WORK, INFO )** -- LAPACK routine (version 3.0) --* Univ. of Tennessee, Univ. of California Berkeley, NAG Ltd.,* Courant Institute, Argonne National Lab, and Rice University* March 31, 1993** .. Scalar Arguments ..INTEGER INFO, NDOUBLE PRECISION ANORM, RCOND* ..* .. Array Arguments ..DOUBLE PRECISION D( * ), E( * ), WORK( * )* ..** Purpose* =======** DPTCON computes the reciprocal of the condition number (in the* 1-norm) of a real symmetric positive definite tridiagonal matrix* using the factorization A = L*D*L**T or A = U**T*D*U computed by* DPTTRF.** Norm(inv(A)) is computed by a direct method, and the reciprocal of* the condition number is computed as* RCOND = 1 / (ANORM * norm(inv(A))).** Arguments* =========** N (input) INTEGER* The order of the matrix A. N >= 0.** D (input) DOUBLE PRECISION array, dimension (N)* The n diagonal elements of the diagonal matrix D from the* factorization of A, as computed by DPTTRF.** E (input) DOUBLE PRECISION array, dimension (N-1)* The (n-1) off-diagonal elements of the unit bidiagonal factor* U or L from the factorization of A, as computed by DPTTRF.** ANORM (input) DOUBLE PRECISION* The 1-norm of the original matrix A.** RCOND (output) DOUBLE PRECISION* The reciprocal of the condition number of the matrix A,* computed as RCOND = 1/(ANORM * AINVNM), where AINVNM is the* 1-norm of inv(A) computed in this routine.** WORK (workspace) DOUBLE PRECISION array, dimension (N)** INFO (output) INTEGER* = 0: successful exit* < 0: if INFO = -i, the i-th argument had an illegal value** Further Details* ===============** The method used is described in Nicholas J. Higham, "Efficient* Algorithms for Computing the Condition Number of a Tridiagonal* Matrix", SIAM J. Sci. Stat. Comput., Vol. 7, No. 1, January 1986.** =====================================================================** .. Parameters ..DOUBLE PRECISION ONE, ZEROPARAMETER ( ONE = 1.0D+0, ZERO = 0.0D+0 )* ..* .. Local Scalars ..INTEGER I, IXDOUBLE PRECISION AINVNM* ..* .. External Functions ..INTEGER IDAMAXEXTERNAL IDAMAX* ..* .. External Subroutines ..EXTERNAL XERBLA* ..* .. Intrinsic Functions ..INTRINSIC ABS* ..* .. Executable Statements ..** Test the input arguments.*INFO = 0IF( N.LT.0 ) THENINFO = -1ELSE IF( ANORM.LT.ZERO ) THENINFO = -4END IFIF( INFO.NE.0 ) THENCALL XERBLA( 'DPTCON', -INFO )RETURNEND IF** Quick return if possible*RCOND = ZEROIF( N.EQ.0 ) THENRCOND = ONERETURNELSE IF( ANORM.EQ.ZERO ) THENRETURNEND IF** Check that D(1:N) is positive.*DO 10 I = 1, NIF( D( I ).LE.ZERO )$ RETURN10 CONTINUE** Solve M(A) * x = e, where M(A) = (m(i,j)) is given by** m(i,j) = abs(A(i,j)), i = j,* m(i,j) = -abs(A(i,j)), i .ne. j,** and e = [ 1, 1, ..., 1 ]'. Note M(A) = M(L)*D*M(L)'.** Solve M(L) * x = e.*WORK( 1 ) = ONEDO 20 I = 2, NWORK( I ) = ONE + WORK( I-1 )*ABS( E( I-1 ) )20 CONTINUE** Solve D * M(L)' * x = b.*WORK( N ) = WORK( N ) / D( N )DO 30 I = N - 1, 1, -1WORK( I ) = WORK( I ) / D( I ) + WORK( I+1 )*ABS( E( I ) )30 CONTINUE** Compute AINVNM = max(x(i)), 1<=i<=n.*IX = IDAMAX( N, WORK, 1 )AINVNM = ABS( WORK( IX ) )** Compute the reciprocal condition number.*IF( AINVNM.NE.ZERO )$ RCOND = ( ONE / AINVNM ) / ANORM*RETURN** End of DPTCON*ENDSUBROUTINE DPTEQR( COMPZ, N, D, E, Z, LDZ, WORK, INFO )** -- LAPACK routine (version 3.0) --* Univ. of Tennessee, Univ. of California Berkeley, NAG Ltd.,* Courant Institute, Argonne National Lab, and Rice University* October 31, 1999** .. Scalar Arguments ..CHARACTER COMPZINTEGER INFO, LDZ, N* ..* .. Array Arguments ..DOUBLE PRECISION D( * ), E( * ), WORK( * ), Z( LDZ, * )* ..** Purpose* =======** DPTEQR computes all eigenvalues and, optionally, eigenvectors of a* symmetric positive definite tridiagonal matrix by first factoring the* matrix using DPTTRF, and then calling DBDSQR to compute the singular* values of the bidiagonal factor.** This routine computes the eigenvalues of the positive definite* tridiagonal matrix to high relative accuracy. This means that if the* eigenvalues range over many orders of magnitude in size, then the* small eigenvalues and corresponding eigenvectors will be computed* more accurately than, for example, with the standard QR method.** The eigenvectors of a full or band symmetric positive definite matrix* can also be found if DSYTRD, DSPTRD, or DSBTRD has been used to* reduce this matrix to tridiagonal form. (The reduction to tridiagonal* form, however, may preclude the possibility of obtaining high* relative accuracy in the small eigenvalues of the original matrix, if* these eigenvalues range over many orders of magnitude.)** Arguments* =========** COMPZ (input) CHARACTER*1* = 'N': Compute eigenvalues only.* = 'V': Compute eigenvectors of original symmetric* matrix also. Array Z contains the orthogonal* matrix used to reduce the original matrix to* tridiagonal form.* = 'I': Compute eigenvectors of tridiagonal matrix also.** 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 normal exit, D contains the eigenvalues, in descending* 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', the orthogonal matrix used in the* reduction to tridiagonal form.* On exit, if COMPZ = 'V', the orthonormal eigenvectors of the* original symmetric matrix;* if COMPZ = 'I', the orthonormal eigenvectors of the* tridiagonal matrix.* If INFO > 0 on exit, Z contains the eigenvectors associated* with only 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* COMPZ = 'V' or 'I', LDZ >= max(1,N).** WORK (workspace) DOUBLE PRECISION array, dimension (4*N)** INFO (output) INTEGER* = 0: successful exit.* < 0: if INFO = -i, the i-th argument had an illegal value.* > 0: if INFO = i, and i is:* <= N the Cholesky factorization of the matrix could* not be performed because the i-th principal minor* was not positive definite.* > N the SVD algorithm failed to converge;* if INFO = N+i, i off-diagonal elements of the* bidiagonal factor did not converge to zero.** =====================================================================** .. Parameters ..DOUBLE PRECISION ZERO, ONEPARAMETER ( ZERO = 0.0D0, ONE = 1.0D0 )* ..* .. External Functions ..LOGICAL LSAMEEXTERNAL LSAME* ..* .. External Subroutines ..EXTERNAL DBDSQR, DLASET, DPTTRF, XERBLA* ..* .. Local Arrays ..DOUBLE PRECISION C( 1, 1 ), VT( 1, 1 )* ..* .. Local Scalars ..INTEGER I, ICOMPZ, NRU* ..* .. Intrinsic Functions ..INTRINSIC MAX, SQRT* ..* .. Executable Statements ..** Test the input parameters.*INFO = 0*IF( LSAME( COMPZ, 'N' ) ) THENICOMPZ = 0ELSE IF( LSAME( COMPZ, 'V' ) ) THENICOMPZ = 1ELSE IF( LSAME( COMPZ, 'I' ) ) THENICOMPZ = 2ELSEICOMPZ = -1END IFIF( ICOMPZ.LT.0 ) THENINFO = -1ELSE IF( N.LT.0 ) THENINFO = -2ELSE IF( ( LDZ.LT.1 ) .OR. ( ICOMPZ.GT.0 .AND. LDZ.LT.MAX( 1,$ N ) ) ) THENINFO = -6END IFIF( INFO.NE.0 ) THENCALL XERBLA( 'DPTEQR', -INFO )RETURNEND IF** Quick return if possible*IF( N.EQ.0 )$ RETURN*IF( N.EQ.1 ) THENIF( ICOMPZ.GT.0 )$ Z( 1, 1 ) = ONERETURNEND IFIF( ICOMPZ.EQ.2 )$ CALL DLASET( 'Full', N, N, ZERO, ONE, Z, LDZ )** Call DPTTRF to factor the matrix.*CALL DPTTRF( N, D, E, INFO )IF( INFO.NE.0 )$ RETURNDO 10 I = 1, ND( I ) = SQRT( D( I ) )10 CONTINUEDO 20 I = 1, N - 1E( I ) = E( I )*D( I )20 CONTINUE** Call DBDSQR to compute the singular values/vectors of the* bidiagonal factor.*IF( ICOMPZ.GT.0 ) THENNRU = NELSENRU = 0END IFCALL DBDSQR( 'Lower', N, 0, NRU, 0, D, E, VT, 1, Z, LDZ, C, 1,$ WORK, INFO )** Square the singular values.*IF( INFO.EQ.0 ) THENDO 30 I = 1, ND( I ) = D( I )*D( I )30 CONTINUEELSEINFO = N + INFOEND IF*RETURN** End of DPTEQR*ENDSUBROUTINE DPTRFS( N, NRHS, D, E, DF, EF, B, LDB, X, LDX, FERR,$ BERR, WORK, INFO )** -- LAPACK routine (version 3.0) --* Univ. of Tennessee, Univ. of California Berkeley, NAG Ltd.,* Courant Institute, Argonne National Lab, and Rice University* September 30, 1994** .. Scalar Arguments ..INTEGER INFO, LDB, LDX, N, NRHS* ..* .. Array Arguments ..DOUBLE PRECISION B( LDB, * ), BERR( * ), D( * ), DF( * ),$ E( * ), EF( * ), FERR( * ), WORK( * ),$ X( LDX, * )* ..** Purpose* =======** DPTRFS improves the computed solution to a system of linear* equations when the coefficient matrix is symmetric positive definite* and tridiagonal, and provides error bounds and backward error* estimates for the solution.** Arguments* =========** 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.** D (input) DOUBLE PRECISION array, dimension (N)* The n diagonal elements of the tridiagonal matrix A.** E (input) DOUBLE PRECISION array, dimension (N-1)* The (n-1) subdiagonal elements of the tridiagonal matrix A.** DF (input) DOUBLE PRECISION array, dimension (N)* The n diagonal elements of the diagonal matrix D from the* factorization computed by DPTTRF.** EF (input) DOUBLE PRECISION array, dimension (N-1)* The (n-1) subdiagonal elements of the unit bidiagonal factor* L from the factorization computed by DPTTRF.** B (input) DOUBLE PRECISION array, dimension (LDB,NRHS)* The right hand side matrix B.** LDB (input) INTEGER* The leading dimension of the array B. LDB >= max(1,N).** X (input/output) DOUBLE PRECISION array, dimension (LDX,NRHS)* On entry, the solution matrix X, as computed by DPTTRS.* On exit, the improved solution matrix X.** LDX (input) INTEGER* The leading dimension of the array X. LDX >= max(1,N).** FERR (output) DOUBLE PRECISION array, dimension (NRHS)* The forward error bound for each solution vector* X(j) (the j-th column of the solution matrix X).* If XTRUE is the true solution corresponding to X(j), FERR(j)* is an estimated upper bound for the magnitude of the largest* element in (X(j) - XTRUE) divided by the magnitude of the* largest element in X(j).** BERR (output) DOUBLE PRECISION array, dimension (NRHS)* The componentwise relative backward error of each solution* vector X(j) (i.e., the smallest relative change in* any element of A or B that makes X(j) an exact solution).** WORK (workspace) DOUBLE PRECISION array, dimension (2*N)** INFO (output) INTEGER* = 0: successful exit* < 0: if INFO = -i, the i-th argument had an illegal value** Internal Parameters* ===================** ITMAX is the maximum number of steps of iterative refinement.** =====================================================================** .. Parameters ..INTEGER ITMAXPARAMETER ( ITMAX = 5 )DOUBLE PRECISION ZEROPARAMETER ( ZERO = 0.0D+0 )DOUBLE PRECISION ONEPARAMETER ( ONE = 1.0D+0 )DOUBLE PRECISION TWOPARAMETER ( TWO = 2.0D+0 )DOUBLE PRECISION THREEPARAMETER ( THREE = 3.0D+0 )* ..* .. Local Scalars ..INTEGER COUNT, I, IX, J, NZDOUBLE PRECISION BI, CX, DX, EPS, EX, LSTRES, S, SAFE1, SAFE2,$ SAFMIN* ..* .. External Subroutines ..EXTERNAL DAXPY, DPTTRS, XERBLA* ..* .. Intrinsic Functions ..INTRINSIC ABS, MAX* ..* .. External Functions ..INTEGER IDAMAXDOUBLE PRECISION DLAMCHEXTERNAL IDAMAX, DLAMCH* ..* .. Executable Statements ..** Test the input parameters.*INFO = 0IF( N.LT.0 ) THENINFO = -1ELSE IF( NRHS.LT.0 ) THENINFO = -2ELSE IF( LDB.LT.MAX( 1, N ) ) THENINFO = -8ELSE IF( LDX.LT.MAX( 1, N ) ) THENINFO = -10END IFIF( INFO.NE.0 ) THENCALL XERBLA( 'DPTRFS', -INFO )RETURNEND IF** Quick return if possible*IF( N.EQ.0 .OR. NRHS.EQ.0 ) THENDO 10 J = 1, NRHSFERR( J ) = ZEROBERR( J ) = ZERO10 CONTINUERETURNEND IF** NZ = maximum number of nonzero elements in each row of A, plus 1*NZ = 4EPS = DLAMCH( 'Epsilon' )SAFMIN = DLAMCH( 'Safe minimum' )SAFE1 = NZ*SAFMINSAFE2 = SAFE1 / EPS** Do for each right hand side*DO 90 J = 1, NRHS*COUNT = 1LSTRES = THREE20 CONTINUE** Loop until stopping criterion is satisfied.** Compute residual R = B - A * X. Also compute* abs(A)*abs(x) + abs(b) for use in the backward error bound.*IF( N.EQ.1 ) THENBI = B( 1, J )DX = D( 1 )*X( 1, J )WORK( N+1 ) = BI - DXWORK( 1 ) = ABS( BI ) + ABS( DX )ELSEBI = B( 1, J )DX = D( 1 )*X( 1, J )EX = E( 1 )*X( 2, J )WORK( N+1 ) = BI - DX - EXWORK( 1 ) = ABS( BI ) + ABS( DX ) + ABS( EX )DO 30 I = 2, N - 1BI = B( I, J )CX = E( I-1 )*X( I-1, J )DX = D( I )*X( I, J )EX = E( I )*X( I+1, J )WORK( N+I ) = BI - CX - DX - EXWORK( I ) = ABS( BI ) + ABS( CX ) + ABS( DX ) + ABS( EX )30 CONTINUEBI = B( N, J )CX = E( N-1 )*X( N-1, J )DX = D( N )*X( N, J )WORK( N+N ) = BI - CX - DXWORK( N ) = ABS( BI ) + ABS( CX ) + ABS( DX )END IF** Compute componentwise relative backward error from formula** max(i) ( abs(R(i)) / ( abs(A)*abs(X) + abs(B) )(i) )** where abs(Z) is the componentwise absolute value of the matrix* or vector Z. If the i-th component of the denominator is less* than SAFE2, then SAFE1 is added to the i-th components of the* numerator and denominator before dividing.*S = ZERODO 40 I = 1, NIF( WORK( I ).GT.SAFE2 ) THENS = MAX( S, ABS( WORK( N+I ) ) / WORK( I ) )ELSES = MAX( S, ( ABS( WORK( N+I ) )+SAFE1 ) /$ ( WORK( I )+SAFE1 ) )END IF40 CONTINUEBERR( J ) = S** Test stopping criterion. Continue iterating if* 1) The residual BERR(J) is larger than machine epsilon, and* 2) BERR(J) decreased by at least a factor of 2 during the* last iteration, and* 3) At most ITMAX iterations tried.*IF( BERR( J ).GT.EPS .AND. TWO*BERR( J ).LE.LSTRES .AND.$ COUNT.LE.ITMAX ) THEN** Update solution and try again.*CALL DPTTRS( N, 1, DF, EF, WORK( N+1 ), N, INFO )CALL DAXPY( N, ONE, WORK( N+1 ), 1, X( 1, J ), 1 )LSTRES = BERR( J )COUNT = COUNT + 1GO TO 20END IF** Bound error from formula** norm(X - XTRUE) / norm(X) .le. FERR =* norm( abs(inv(A))** ( abs(R) + NZ*EPS*( abs(A)*abs(X)+abs(B) ))) / norm(X)** where* norm(Z) is the magnitude of the largest component of Z* inv(A) is the inverse of A* abs(Z) is the componentwise absolute value of the matrix or* vector Z* NZ is the maximum number of nonzeros in any row of A, plus 1* EPS is machine epsilon** The i-th component of abs(R)+NZ*EPS*(abs(A)*abs(X)+abs(B))* is incremented by SAFE1 if the i-th component of* abs(A)*abs(X) + abs(B) is less than SAFE2.*DO 50 I = 1, NIF( WORK( I ).GT.SAFE2 ) THENWORK( I ) = ABS( WORK( N+I ) ) + NZ*EPS*WORK( I )ELSEWORK( I ) = ABS( WORK( N+I ) ) + NZ*EPS*WORK( I ) + SAFE1END IF50 CONTINUEIX = IDAMAX( N, WORK, 1 )FERR( J ) = WORK( IX )** Estimate the norm of inv(A).** Solve M(A) * x = e, where M(A) = (m(i,j)) is given by** m(i,j) = abs(A(i,j)), i = j,* m(i,j) = -abs(A(i,j)), i .ne. j,** and e = [ 1, 1, ..., 1 ]'. Note M(A) = M(L)*D*M(L)'.** Solve M(L) * x = e.*WORK( 1 ) = ONEDO 60 I = 2, NWORK( I ) = ONE + WORK( I-1 )*ABS( EF( I-1 ) )60 CONTINUE** Solve D * M(L)' * x = b.*WORK( N ) = WORK( N ) / DF( N )DO 70 I = N - 1, 1, -1WORK( I ) = WORK( I ) / DF( I ) + WORK( I+1 )*ABS( EF( I ) )70 CONTINUE** Compute norm(inv(A)) = max(x(i)), 1<=i<=n.*IX = IDAMAX( N, WORK, 1 )FERR( J ) = FERR( J )*ABS( WORK( IX ) )** Normalize error.*LSTRES = ZERODO 80 I = 1, NLSTRES = MAX( LSTRES, ABS( X( I, J ) ) )80 CONTINUEIF( LSTRES.NE.ZERO )$ FERR( J ) = FERR( J ) / LSTRES*90 CONTINUE*RETURN** End of DPTRFS*ENDSUBROUTINE DPTSV( N, NRHS, D, E, B, LDB, INFO )** -- LAPACK routine (version 3.0) --* Univ. of Tennessee, Univ. of California Berkeley, NAG Ltd.,* Courant Institute, Argonne National Lab, and Rice University* February 25, 1997** .. Scalar Arguments ..INTEGER INFO, LDB, N, NRHS* ..* .. Array Arguments ..DOUBLE PRECISION B( LDB, * ), D( * ), E( * )* ..** Purpose* =======** DPTSV computes the solution to a real system of linear equations* A*X = B, where A is an N-by-N symmetric positive definite tridiagonal* matrix, and X and B are N-by-NRHS matrices.** A is factored as A = L*D*L**T, and the factored form of A is then* used to solve the system of equations.** Arguments* =========** 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.** D (input/output) DOUBLE PRECISION array, dimension (N)* On entry, the n diagonal elements of the tridiagonal matrix* A. On exit, the n diagonal elements of the diagonal matrix* D from the factorization A = L*D*L**T.** E (input/output) DOUBLE PRECISION array, dimension (N-1)* On entry, the (n-1) subdiagonal elements of the tridiagonal* matrix A. On exit, the (n-1) subdiagonal elements of the* unit bidiagonal factor L from the L*D*L**T factorization of* A. (E can also be regarded as the superdiagonal of the unit* bidiagonal factor U from the U**T*D*U factorization of A.)** B (input/output) DOUBLE PRECISION array, dimension (LDB,NRHS)* On entry, the N-by-NRHS 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, the leading minor of order i is not* positive definite, and the solution has not been* computed. The factorization has not been completed* unless i = N.** =====================================================================** .. External Subroutines ..EXTERNAL DPTTRF, DPTTRS, XERBLA* ..* .. Intrinsic Functions ..INTRINSIC MAX* ..* .. Executable Statements ..** Test the input parameters.*INFO = 0IF( N.LT.0 ) THENINFO = -1ELSE IF( NRHS.LT.0 ) THENINFO = -2ELSE IF( LDB.LT.MAX( 1, N ) ) THENINFO = -6END IFIF( INFO.NE.0 ) THENCALL XERBLA( 'DPTSV ', -INFO )RETURNEND IF** Compute the L*D*L' (or U'*D*U) factorization of A.*CALL DPTTRF( N, D, E, INFO )IF( INFO.EQ.0 ) THEN** Solve the system A*X = B, overwriting B with X.*CALL DPTTRS( N, NRHS, D, E, B, LDB, INFO )END IFRETURN** End of DPTSV*ENDSUBROUTINE DPTSVX( FACT, N, NRHS, D, E, DF, EF, B, LDB, X, LDX,$ RCOND, FERR, BERR, WORK, INFO )** -- LAPACK routine (version 3.0) --* Univ. of Tennessee, Univ. of California Berkeley, NAG Ltd.,* Courant Institute, Argonne National Lab, and Rice University* June 30, 1999** .. Scalar Arguments ..CHARACTER FACTINTEGER INFO, LDB, LDX, N, NRHSDOUBLE PRECISION RCOND* ..* .. Array Arguments ..DOUBLE PRECISION B( LDB, * ), BERR( * ), D( * ), DF( * ),$ E( * ), EF( * ), FERR( * ), WORK( * ),$ X( LDX, * )* ..** Purpose* =======** DPTSVX uses the factorization A = L*D*L**T to compute the solution* to a real system of linear equations A*X = B, where A is an N-by-N* symmetric positive definite tridiagonal matrix and X and B are* N-by-NRHS matrices.** Error bounds on the solution and a condition estimate are also* provided.** Description* ===========** The following steps are performed:** 1. If FACT = 'N', the matrix A is factored as A = L*D*L**T, where L* is a unit lower bidiagonal matrix and D is diagonal. The* factorization can also be regarded as having the form* A = U**T*D*U.** 2. If the leading i-by-i principal minor is not positive definite,* then the routine returns with INFO = i. Otherwise, the factored* form of A is used to estimate the condition number of the matrix* A. If the reciprocal of the condition number is less than machine* precision, INFO = N+1 is returned as a warning, but the routine* still goes on to solve for X and compute error bounds as* described below.** 3. The system of equations is solved for X using the factored form* of A.** 4. Iterative refinement is applied to improve the computed solution* matrix and calculate error bounds and backward error estimates* for it.** Arguments* =========** FACT (input) CHARACTER*1* Specifies whether or not the factored form of A has been* supplied on entry.* = 'F': On entry, DF and EF contain the factored form of A.* D, E, DF, and EF will not be modified.* = 'N': The matrix A will be copied to DF and EF and* factored.** 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 matrices B and X. NRHS >= 0.** D (input) DOUBLE PRECISION array, dimension (N)* The n diagonal elements of the tridiagonal matrix A.** E (input) DOUBLE PRECISION array, dimension (N-1)* The (n-1) subdiagonal elements of the tridiagonal matrix A.** DF (input or output) DOUBLE PRECISION array, dimension (N)* If FACT = 'F', then DF is an input argument and on entry* contains the n diagonal elements of the diagonal matrix D* from the L*D*L**T factorization of A.* If FACT = 'N', then DF is an output argument and on exit* contains the n diagonal elements of the diagonal matrix D* from the L*D*L**T factorization of A.** EF (input or output) DOUBLE PRECISION array, dimension (N-1)* If FACT = 'F', then EF is an input argument and on entry* contains the (n-1) subdiagonal elements of the unit* bidiagonal factor L from the L*D*L**T factorization of A.* If FACT = 'N', then EF is an output argument and on exit* contains the (n-1) subdiagonal elements of the unit* bidiagonal factor L from the L*D*L**T factorization of A.** B (input) DOUBLE PRECISION array, dimension (LDB,NRHS)* The N-by-NRHS right hand side matrix B.** LDB (input) INTEGER* The leading dimension of the array B. LDB >= max(1,N).** X (output) DOUBLE PRECISION array, dimension (LDX,NRHS)* If INFO = 0 of INFO = N+1, the N-by-NRHS solution matrix X.** LDX (input) INTEGER* The leading dimension of the array X. LDX >= max(1,N).** RCOND (output) DOUBLE PRECISION* The reciprocal condition number of the matrix A. If RCOND* is less than the machine precision (in particular, if* RCOND = 0), the matrix is singular to working precision.* This condition is indicated by a return code of INFO > 0.** FERR (output) DOUBLE PRECISION array, dimension (NRHS)* The forward error bound for each solution vector* X(j) (the j-th column of the solution matrix X).* If XTRUE is the true solution corresponding to X(j), FERR(j)* is an estimated upper bound for the magnitude of the largest* element in (X(j) - XTRUE) divided by the magnitude of the* largest element in X(j).** BERR (output) DOUBLE PRECISION array, dimension (NRHS)* The componentwise relative backward error of each solution* vector X(j) (i.e., the smallest relative change in any* element of A or B that makes X(j) an exact solution).** WORK (workspace) DOUBLE PRECISION array, dimension (2*N)** INFO (output) INTEGER* = 0: successful exit* < 0: if INFO = -i, the i-th argument had an illegal value* > 0: if INFO = i, and i is* <= N: the leading minor of order i of A is* not positive definite, so the factorization* could not be completed, and the solution has not* been computed. RCOND = 0 is returned.* = N+1: U is nonsingular, but RCOND is less than machine* precision, meaning that the matrix is singular* to working precision. Nevertheless, the* solution and error bounds are computed because* there are a number of situations where the* computed solution can be more accurate than the* value of RCOND would suggest.** =====================================================================** .. Parameters ..DOUBLE PRECISION ZEROPARAMETER ( ZERO = 0.0D+0 )* ..* .. Local Scalars ..LOGICAL NOFACTDOUBLE PRECISION ANORM* ..* .. External Functions ..LOGICAL LSAMEDOUBLE PRECISION DLAMCH, DLANSTEXTERNAL LSAME, DLAMCH, DLANST* ..* .. External Subroutines ..EXTERNAL DCOPY, DLACPY, DPTCON, DPTRFS, DPTTRF, DPTTRS,$ XERBLA* ..* .. Intrinsic Functions ..INTRINSIC MAX* ..* .. Executable Statements ..** Test the input parameters.*INFO = 0NOFACT = LSAME( FACT, 'N' )IF( .NOT.NOFACT .AND. .NOT.LSAME( FACT, 'F' ) ) THENINFO = -1ELSE IF( N.LT.0 ) THENINFO = -2ELSE IF( NRHS.LT.0 ) THENINFO = -3ELSE IF( LDB.LT.MAX( 1, N ) ) THENINFO = -9ELSE IF( LDX.LT.MAX( 1, N ) ) THENINFO = -11END IFIF( INFO.NE.0 ) THENCALL XERBLA( 'DPTSVX', -INFO )RETURNEND IF*IF( NOFACT ) THEN** Compute the L*D*L' (or U'*D*U) factorization of A.*CALL DCOPY( N, D, 1, DF, 1 )IF( N.GT.1 )$ CALL DCOPY( N-1, E, 1, EF, 1 )CALL DPTTRF( N, DF, EF, INFO )** Return if INFO is non-zero.*IF( INFO.NE.0 ) THENIF( INFO.GT.0 )$ RCOND = ZERORETURNEND IFEND IF** Compute the norm of the matrix A.*ANORM = DLANST( '1', N, D, E )** Compute the reciprocal of the condition number of A.*CALL DPTCON( N, DF, EF, ANORM, RCOND, WORK, INFO )** Set INFO = N+1 if the matrix is singular to working precision.*IF( RCOND.LT.DLAMCH( 'Epsilon' ) )$ INFO = N + 1** Compute the solution vectors X.*CALL DLACPY( 'Full', N, NRHS, B, LDB, X, LDX )CALL DPTTRS( N, NRHS, DF, EF, X, LDX, INFO )** Use iterative refinement to improve the computed solutions and* compute error bounds and backward error estimates for them.*CALL DPTRFS( N, NRHS, D, E, DF, EF, B, LDB, X, LDX, FERR, BERR,$ WORK, INFO )*RETURN** End of DPTSVX*ENDSUBROUTINE DPTTRF( N, D, E, INFO )** -- LAPACK routine (version 3.0) --* Univ. of Tennessee, Univ. of California Berkeley, NAG Ltd.,* Courant Institute, Argonne National Lab, and Rice University* June 30, 1999** .. Scalar Arguments ..INTEGER INFO, N* ..* .. Array Arguments ..DOUBLE PRECISION D( * ), E( * )* ..** Purpose* =======** DPTTRF computes the L*D*L' factorization of a real symmetric* positive definite tridiagonal matrix A. The factorization may also* be regarded as having the form A = U'*D*U.** Arguments* =========** N (input) INTEGER* The order of the matrix A. N >= 0.** D (input/output) DOUBLE PRECISION array, dimension (N)* On entry, the n diagonal elements of the tridiagonal matrix* A. On exit, the n diagonal elements of the diagonal matrix* D from the L*D*L' factorization of A.** E (input/output) DOUBLE PRECISION array, dimension (N-1)* On entry, the (n-1) subdiagonal elements of the tridiagonal* matrix A. On exit, the (n-1) subdiagonal elements of the* unit bidiagonal factor L from the L*D*L' factorization of A.* E can also be regarded as the superdiagonal of the unit* bidiagonal factor U from the U'*D*U factorization of A.** INFO (output) INTEGER* = 0: successful exit* < 0: if INFO = -k, the k-th argument had an illegal value* > 0: if INFO = k, the leading minor of order k is not* positive definite; if k < N, the factorization could not* be completed, while if k = N, the factorization was* completed, but D(N) = 0.** =====================================================================** .. Parameters ..DOUBLE PRECISION ZEROPARAMETER ( ZERO = 0.0D+0 )* ..* .. Local Scalars ..INTEGER I, I4DOUBLE PRECISION EI* ..* .. External Subroutines ..EXTERNAL XERBLA* ..* .. Intrinsic Functions ..INTRINSIC MOD* ..* .. Executable Statements ..** Test the input parameters.*INFO = 0IF( N.LT.0 ) THENINFO = -1CALL XERBLA( 'DPTTRF', -INFO )RETURNEND IF** Quick return if possible*IF( N.EQ.0 )$ RETURN** Compute the L*D*L' (or U'*D*U) factorization of A.*I4 = MOD( N-1, 4 )DO 10 I = 1, I4IF( D( I ).LE.ZERO ) THENINFO = IGO TO 30END IFEI = E( I )E( I ) = EI / D( I )D( I+1 ) = D( I+1 ) - E( I )*EI10 CONTINUE*DO 20 I = I4 + 1, N - 4, 4** Drop out of the loop if d(i) <= 0: the matrix is not positive* definite.*IF( D( I ).LE.ZERO ) THENINFO = IGO TO 30END IF** Solve for e(i) and d(i+1).*EI = E( I )E( I ) = EI / D( I )D( I+1 ) = D( I+1 ) - E( I )*EI*IF( D( I+1 ).LE.ZERO ) THENINFO = I + 1GO TO 30END IF** Solve for e(i+1) and d(i+2).*EI = E( I+1 )E( I+1 ) = EI / D( I+1 )D( I+2 ) = D( I+2 ) - E( I+1 )*EI*IF( D( I+2 ).LE.ZERO ) THENINFO = I + 2GO TO 30END IF** Solve for e(i+2) and d(i+3).*EI = E( I+2 )E( I+2 ) = EI / D( I+2 )D( I+3 ) = D( I+3 ) - E( I+2 )*EI*IF( D( I+3 ).LE.ZERO ) THENINFO = I + 3GO TO 30END IF** Solve for e(i+3) and d(i+4).*EI = E( I+3 )E( I+3 ) = EI / D( I+3 )D( I+4 ) = D( I+4 ) - E( I+3 )*EI20 CONTINUE** Check d(n) for positive definiteness.*IF( D( N ).LE.ZERO )$ INFO = N*30 CONTINUERETURN** End of DPTTRF*ENDSUBROUTINE DPTTRS( N, NRHS, D, E, B, LDB, INFO )** -- LAPACK routine (version 3.0) --* Univ. of Tennessee, Univ. of California Berkeley, NAG Ltd.,* Courant Institute, Argonne National Lab, and Rice University* June 30, 1999** .. Scalar Arguments ..INTEGER INFO, LDB, N, NRHS* ..* .. Array Arguments ..DOUBLE PRECISION B( LDB, * ), D( * ), E( * )* ..** Purpose* =======** DPTTRS solves a tridiagonal system of the form* A * X = B* using the L*D*L' factorization of A computed by DPTTRF. D is a* diagonal matrix specified in the vector D, L is a unit bidiagonal* matrix whose subdiagonal is specified in the vector E, and X and B* are N by NRHS matrices.** Arguments* =========** N (input) INTEGER* The order of the tridiagonal 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.** D (input) DOUBLE PRECISION array, dimension (N)* The n diagonal elements of the diagonal matrix D from the* L*D*L' factorization of A.** E (input) DOUBLE PRECISION array, dimension (N-1)* The (n-1) subdiagonal elements of the unit bidiagonal factor* L from the L*D*L' factorization of A. E can also be regarded* as the superdiagonal of the unit bidiagonal factor U from the* factorization A = U'*D*U.** B (input/output) DOUBLE PRECISION array, dimension (LDB,NRHS)* On entry, the right hand side vectors B for the system of* linear equations.* On exit, the solution vectors, X.** LDB (input) INTEGER* The leading dimension of the array B. LDB >= max(1,N).** INFO (output) INTEGER* = 0: successful exit* < 0: if INFO = -k, the k-th argument had an illegal value** =====================================================================** .. Local Scalars ..INTEGER J, JB, NB* ..* .. External Functions ..INTEGER ILAENVEXTERNAL ILAENV* ..* .. External Subroutines ..EXTERNAL DPTTS2, XERBLA* ..* .. Intrinsic Functions ..INTRINSIC MAX, MIN* ..* .. Executable Statements ..** Test the input arguments.*INFO = 0IF( N.LT.0 ) THENINFO = -1ELSE IF( NRHS.LT.0 ) THENINFO = -2ELSE IF( LDB.LT.MAX( 1, N ) ) THENINFO = -6END IFIF( INFO.NE.0 ) THENCALL XERBLA( 'DPTTRS', -INFO )RETURNEND IF** Quick return if possible*IF( N.EQ.0 .OR. NRHS.EQ.0 )$ RETURN** Determine the number of right-hand sides to solve at a time.*IF( NRHS.EQ.1 ) THENNB = 1ELSENB = MAX( 1, ILAENV( 1, 'DPTTRS', ' ', N, NRHS, -1, -1 ) )END IF*IF( NB.GE.NRHS ) THENCALL DPTTS2( N, NRHS, D, E, B, LDB )ELSEDO 10 J = 1, NRHS, NBJB = MIN( NRHS-J+1, NB )CALL DPTTS2( N, JB, D, E, B( 1, J ), LDB )10 CONTINUEEND IF*RETURN** End of DPTTRS*ENDSUBROUTINE DPTTS2( N, NRHS, D, E, B, LDB )** -- LAPACK routine (version 3.0) --* Univ. of Tennessee, Univ. of California Berkeley, NAG Ltd.,* Courant Institute, Argonne National Lab, and Rice University* June 30, 1999** .. Scalar Arguments ..INTEGER LDB, N, NRHS* ..* .. Array Arguments ..DOUBLE PRECISION B( LDB, * ), D( * ), E( * )* ..** Purpose* =======** DPTTS2 solves a tridiagonal system of the form* A * X = B* using the L*D*L' factorization of A computed by DPTTRF. D is a* diagonal matrix specified in the vector D, L is a unit bidiagonal* matrix whose subdiagonal is specified in the vector E, and X and B* are N by NRHS matrices.** Arguments* =========** N (input) INTEGER* The order of the tridiagonal 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.** D (input) DOUBLE PRECISION array, dimension (N)* The n diagonal elements of the diagonal matrix D from the* L*D*L' factorization of A.** E (input) DOUBLE PRECISION array, dimension (N-1)* The (n-1) subdiagonal elements of the unit bidiagonal factor* L from the L*D*L' factorization of A. E can also be regarded* as the superdiagonal of the unit bidiagonal factor U from the* factorization A = U'*D*U.** B (input/output) DOUBLE PRECISION array, dimension (LDB,NRHS)* On entry, the right hand side vectors B for the system of* linear equations.* On exit, the solution vectors, X.** LDB (input) INTEGER* The leading dimension of the array B. LDB >= max(1,N).** =====================================================================** .. Local Scalars ..INTEGER I, J* ..* .. External Subroutines ..EXTERNAL DSCAL* ..* .. Executable Statements ..** Quick return if possible*IF( N.LE.1 ) THENIF( N.EQ.1 )$ CALL DSCAL( NRHS, 1.D0 / D( 1 ), B, LDB )RETURNEND IF** Solve A * X = B using the factorization A = L*D*L',* overwriting each right hand side vector with its solution.*DO 30 J = 1, NRHS** Solve L * x = b.*DO 10 I = 2, NB( I, J ) = B( I, J ) - B( I-1, J )*E( I-1 )10 CONTINUE** Solve D * L' * x = b.*B( N, J ) = B( N, J ) / D( N )DO 20 I = N - 1, 1, -1B( I, J ) = B( I, J ) / D( I ) - B( I+1, J )*E( I )20 CONTINUE30 CONTINUE*RETURN** End of DPTTS2*ENDSUBROUTINE DSBGST( VECT, UPLO, N, KA, KB, AB, LDAB, BB, LDBB, X,$ LDX, WORK, INFO )** -- LAPACK routine (version 3.0) --* Univ. of Tennessee, Univ. of California Berkeley, NAG Ltd.,* Courant Institute, Argonne National Lab, and Rice University* June 30, 1999** .. Scalar Arguments ..CHARACTER UPLO, VECTINTEGER INFO, KA, KB, LDAB, LDBB, LDX, N* ..* .. Array Arguments ..DOUBLE PRECISION AB( LDAB, * ), BB( LDBB, * ), WORK( * ),$ X( LDX, * )* ..** Purpose* =======** DSBGST reduces a real symmetric-definite banded generalized* eigenproblem A*x = lambda*B*x to standard form C*y = lambda*y,* such that C has the same bandwidth as A.** B must have been previously factorized as S**T*S by DPBSTF, using a* split Cholesky factorization. A is overwritten by C = X**T*A*X, where* X = S**(-1)*Q and Q is an orthogonal matrix chosen to preserve the* bandwidth of A.** Arguments* =========** VECT (input) CHARACTER*1* = 'N': do not form the transformation matrix X;* = 'V': form X.** 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 matrices A and B. N >= 0.** KA (input) INTEGER* The number of superdiagonals of the matrix A if UPLO = 'U',* or the number of subdiagonals if UPLO = 'L'. KA >= 0.** KB (input) INTEGER* The number of superdiagonals of the matrix B if UPLO = 'U',* or the number of subdiagonals if UPLO = 'L'. KA >= KB >= 0.** AB (input/output) DOUBLE PRECISION array, dimension (LDAB,N)* On entry, the upper or lower triangle of the symmetric band* matrix A, stored in the first ka+1 rows of the array. The* j-th column of A is stored in the j-th column of the array AB* as follows:* if UPLO = 'U', AB(ka+1+i-j,j) = A(i,j) for max(1,j-ka)<=i<=j;* if UPLO = 'L', AB(1+i-j,j) = A(i,j) for j<=i<=min(n,j+ka).** On exit, the transformed matrix X**T*A*X, stored in the same* format as A.** LDAB (input) INTEGER* The leading dimension of the array AB. LDAB >= KA+1.** BB (input) DOUBLE PRECISION array, dimension (LDBB,N)* The banded factor S from the split Cholesky factorization of* B, as returned by DPBSTF, stored in the first KB+1 rows of* the array.** LDBB (input) INTEGER* The leading dimension of the array BB. LDBB >= KB+1.** X (output) DOUBLE PRECISION array, dimension (LDX,N)* If VECT = 'V', the n-by-n matrix X.* If VECT = 'N', the array X is not referenced.** LDX (input) INTEGER* The leading dimension of the array X.* LDX >= max(1,N) if VECT = 'V'; LDX >= 1 otherwise.** WORK (workspace) DOUBLE PRECISION array, dimension (2*N)** INFO (output) INTEGER* = 0: successful exit* < 0: if INFO = -i, the i-th argument had an illegal value.** =====================================================================** .. Parameters ..DOUBLE PRECISION ZERO, ONEPARAMETER ( ZERO = 0.0D+0, ONE = 1.0D+0 )* ..* .. Local Scalars ..LOGICAL UPDATE, UPPER, WANTXINTEGER I, I0, I1, I2, INCA, J, J1, J1T, J2, J2T, K,$ KA1, KB1, KBT, L, M, NR, NRT, NXDOUBLE PRECISION BII, RA, RA1, T* ..* .. External Functions ..LOGICAL LSAMEEXTERNAL LSAME* ..* .. External Subroutines ..EXTERNAL DGER, DLAR2V, DLARGV, DLARTG, DLARTV, DLASET,$ DROT, DSCAL, XERBLA* ..* .. Intrinsic Functions ..INTRINSIC MAX, MIN* ..* .. Executable Statements ..** Test the input parameters*WANTX = LSAME( VECT, 'V' )UPPER = LSAME( UPLO, 'U' )KA1 = KA + 1KB1 = KB + 1INFO = 0IF( .NOT.WANTX .AND. .NOT.LSAME( VECT, 'N' ) ) THENINFO = -1ELSE IF( .NOT.UPPER .AND. .NOT.LSAME( UPLO, 'L' ) ) THENINFO = -2ELSE IF( N.LT.0 ) THENINFO = -3ELSE IF( KA.LT.0 ) THENINFO = -4ELSE IF( KB.LT.0 ) THENINFO = -5ELSE IF( LDAB.LT.KA+1 ) THENINFO = -7ELSE IF( LDBB.LT.KB+1 ) THENINFO = -9ELSE IF( LDX.LT.1 .OR. WANTX .AND. LDX.LT.MAX( 1, N ) ) THENINFO = -11END IFIF( INFO.NE.0 ) THENCALL XERBLA( 'DSBGST', -INFO )RETURNEND IF** Quick return if possible*IF( N.EQ.0 )$ RETURN*INCA = LDAB*KA1** Initialize X to the unit matrix, if needed*IF( WANTX )$ CALL DLASET( 'Full', N, N, ZERO, ONE, X, LDX )** Set M to the splitting point m. It must be the same value as is* used in DPBSTF. The chosen value allows the arrays WORK and RWORK* to be of dimension (N).*M = ( N+KB ) / 2** The routine works in two phases, corresponding to the two halves* of the split Cholesky factorization of B as S**T*S where** S = ( U )* ( M L )** with U upper triangular of order m, and L lower triangular of* order n-m. S has the same bandwidth as B.** S is treated as a product of elementary matrices:** S = S(m)*S(m-1)*...*S(2)*S(1)*S(m+1)*S(m+2)*...*S(n-1)*S(n)** where S(i) is determined by the i-th row of S.** In phase 1, the index i takes the values n, n-1, ... , m+1;* in phase 2, it takes the values 1, 2, ... , m.** For each value of i, the current matrix A is updated by forming* inv(S(i))**T*A*inv(S(i)). This creates a triangular bulge outside* the band of A. The bulge is then pushed down toward the bottom of* A in phase 1, and up toward the top of A in phase 2, by applying* plane rotations.** There are kb*(kb+1)/2 elements in the bulge, but at most 2*kb-1* of them are linearly independent, so annihilating a bulge requires* only 2*kb-1 plane rotations. The rotations are divided into a 1st* set of kb-1 rotations, and a 2nd set of kb rotations.** Wherever possible, rotations are generated and applied in vector* operations of length NR between the indices J1 and J2 (sometimes* replaced by modified values NRT, J1T or J2T).** The cosines and sines of the rotations are stored in the array* WORK. The cosines of the 1st set of rotations are stored in* elements n+2:n+m-kb-1 and the sines of the 1st set in elements* 2:m-kb-1; the cosines of the 2nd set are stored in elements* n+m-kb+1:2*n and the sines of the second set in elements m-kb+1:n.** The bulges are not formed explicitly; nonzero elements outside the* band are created only when they are required for generating new* rotations; they are stored in the array WORK, in positions where* they are later overwritten by the sines of the rotations which* annihilate them.** **************************** Phase 1 ******************************* The logical structure of this phase is:** UPDATE = .TRUE.* DO I = N, M + 1, -1* use S(i) to update A and create a new bulge* apply rotations to push all bulges KA positions downward* END DO* UPDATE = .FALSE.* DO I = M + KA + 1, N - 1* apply rotations to push all bulges KA positions downward* END DO** To avoid duplicating code, the two loops are merged.*UPDATE = .TRUE.I = N + 110 CONTINUEIF( UPDATE ) THENI = I - 1KBT = MIN( KB, I-1 )I0 = I - 1I1 = MIN( N, I+KA )I2 = I - KBT + KA1IF( I.LT.M+1 ) THENUPDATE = .FALSE.I = I + 1I0 = MIF( KA.EQ.0 )$ GO TO 480GO TO 10END IFELSEI = I + KAIF( I.GT.N-1 )$ GO TO 480END IF*IF( UPPER ) THEN** Transform A, working with the upper triangle*IF( UPDATE ) THEN** Form inv(S(i))**T * A * inv(S(i))*BII = BB( KB1, I )DO 20 J = I, I1AB( I-J+KA1, J ) = AB( I-J+KA1, J ) / BII20 CONTINUEDO 30 J = MAX( 1, I-KA ), IAB( J-I+KA1, I ) = AB( J-I+KA1, I ) / BII30 CONTINUEDO 60 K = I - KBT, I - 1DO 40 J = I - KBT, KAB( J-K+KA1, K ) = AB( J-K+KA1, K ) -$ BB( J-I+KB1, I )*AB( K-I+KA1, I ) -$ BB( K-I+KB1, I )*AB( J-I+KA1, I ) +$ AB( KA1, I )*BB( J-I+KB1, I )*$ BB( K-I+KB1, I )40 CONTINUEDO 50 J = MAX( 1, I-KA ), I - KBT - 1AB( J-K+KA1, K ) = AB( J-K+KA1, K ) -$ BB( K-I+KB1, I )*AB( J-I+KA1, I )50 CONTINUE60 CONTINUEDO 80 J = I, I1DO 70 K = MAX( J-KA, I-KBT ), I - 1AB( K-J+KA1, J ) = AB( K-J+KA1, J ) -$ BB( K-I+KB1, I )*AB( I-J+KA1, J )70 CONTINUE80 CONTINUE*IF( WANTX ) THEN** post-multiply X by inv(S(i))*CALL DSCAL( N-M, ONE / BII, X( M+1, I ), 1 )IF( KBT.GT.0 )$ CALL DGER( N-M, KBT, -ONE, X( M+1, I ), 1,$ BB( KB1-KBT, I ), 1, X( M+1, I-KBT ), LDX )END IF** store a(i,i1) in RA1 for use in next loop over K*RA1 = AB( I-I1+KA1, I1 )END IF** Generate and apply vectors of rotations to chase all the* existing bulges KA positions down toward the bottom of the* band*DO 130 K = 1, KB - 1IF( UPDATE ) THEN** Determine the rotations which would annihilate the bulge* which has in theory just been created*IF( I-K+KA.LT.N .AND. I-K.GT.1 ) THEN** generate rotation to annihilate a(i,i-k+ka+1)*CALL DLARTG( AB( K+1, I-K+KA ), RA1,$ WORK( N+I-K+KA-M ), WORK( I-K+KA-M ),$ RA )** create nonzero element a(i-k,i-k+ka+1) outside the* band and store it in WORK(i-k)*T = -BB( KB1-K, I )*RA1WORK( I-K ) = WORK( N+I-K+KA-M )*T -$ WORK( I-K+KA-M )*AB( 1, I-K+KA )AB( 1, I-K+KA ) = WORK( I-K+KA-M )*T +$ WORK( N+I-K+KA-M )*AB( 1, I-K+KA )RA1 = RAEND IFEND IFJ2 = I - K - 1 + MAX( 1, K-I0+2 )*KA1NR = ( N-J2+KA ) / KA1J1 = J2 + ( NR-1 )*KA1IF( UPDATE ) THENJ2T = MAX( J2, I+2*KA-K+1 )ELSEJ2T = J2END IFNRT = ( N-J2T+KA ) / KA1DO 90 J = J2T, J1, KA1** create nonzero element a(j-ka,j+1) outside the band* and store it in WORK(j-m)*WORK( J-M ) = WORK( J-M )*AB( 1, J+1 )AB( 1, J+1 ) = WORK( N+J-M )*AB( 1, J+1 )90 CONTINUE** generate rotations in 1st set to annihilate elements which* have been created outside the band*IF( NRT.GT.0 )$ CALL DLARGV( NRT, AB( 1, J2T ), INCA, WORK( J2T-M ), KA1,$ WORK( N+J2T-M ), KA1 )IF( NR.GT.0 ) THEN** apply rotations in 1st set from the right*DO 100 L = 1, KA - 1CALL DLARTV( NR, AB( KA1-L, J2 ), INCA,$ AB( KA-L, J2+1 ), INCA, WORK( N+J2-M ),$ WORK( J2-M ), KA1 )100 CONTINUE** apply rotations in 1st set from both sides to diagonal* blocks*CALL DLAR2V( NR, AB( KA1, J2 ), AB( KA1, J2+1 ),$ AB( KA, J2+1 ), INCA, WORK( N+J2-M ),$ WORK( J2-M ), KA1 )*END IF** start applying rotations in 1st set from the left*DO 110 L = KA - 1, KB - K + 1, -1NRT = ( N-J2+L ) / KA1IF( NRT.GT.0 )$ CALL DLARTV( NRT, AB( L, J2+KA1-L ), INCA,$ AB( L+1, J2+KA1-L ), INCA,$ WORK( N+J2-M ), WORK( J2-M ), KA1 )110 CONTINUE*IF( WANTX ) THEN** post-multiply X by product of rotations in 1st set*DO 120 J = J2, J1, KA1CALL DROT( N-M, X( M+1, J ), 1, X( M+1, J+1 ), 1,$ WORK( N+J-M ), WORK( J-M ) )120 CONTINUEEND IF130 CONTINUE*IF( UPDATE ) THENIF( I2.LE.N .AND. KBT.GT.0 ) THEN** create nonzero element a(i-kbt,i-kbt+ka+1) outside the* band and store it in WORK(i-kbt)*WORK( I-KBT ) = -BB( KB1-KBT, I )*RA1END IFEND IF*DO 170 K = KB, 1, -1IF( UPDATE ) THENJ2 = I - K - 1 + MAX( 2, K-I0+1 )*KA1ELSEJ2 = I - K - 1 + MAX( 1, K-I0+1 )*KA1END IF** finish applying rotations in 2nd set from the left*DO 140 L = KB - K, 1, -1NRT = ( N-J2+KA+L ) / KA1IF( NRT.GT.0 )$ CALL DLARTV( NRT, AB( L, J2-L+1 ), INCA,$ AB( L+1, J2-L+1 ), INCA, WORK( N+J2-KA ),$ WORK( J2-KA ), KA1 )140 CONTINUENR = ( N-J2+KA ) / KA1J1 = J2 + ( NR-1 )*KA1DO 150 J = J1, J2, -KA1WORK( J ) = WORK( J-KA )WORK( N+J ) = WORK( N+J-KA )150 CONTINUEDO 160 J = J2, J1, KA1** create nonzero element a(j-ka,j+1) outside the band* and store it in WORK(j)*WORK( J ) = WORK( J )*AB( 1, J+1 )AB( 1, J+1 ) = WORK( N+J )*AB( 1, J+1 )160 CONTINUEIF( UPDATE ) THENIF( I-K.LT.N-KA .AND. K.LE.KBT )$ WORK( I-K+KA ) = WORK( I-K )END IF170 CONTINUE*DO 210 K = KB, 1, -1J2 = I - K - 1 + MAX( 1, K-I0+1 )*KA1NR = ( N-J2+KA ) / KA1J1 = J2 + ( NR-1 )*KA1IF( NR.GT.0 ) THEN** generate rotations in 2nd set to annihilate elements* which have been created outside the band*CALL DLARGV( NR, AB( 1, J2 ), INCA, WORK( J2 ), KA1,$ WORK( N+J2 ), KA1 )** apply rotations in 2nd set from the right*DO 180 L = 1, KA - 1CALL DLARTV( NR, AB( KA1-L, J2 ), INCA,$ AB( KA-L, J2+1 ), INCA, WORK( N+J2 ),$ WORK( J2 ), KA1 )180 CONTINUE** apply rotations in 2nd set from both sides to diagonal* blocks*CALL DLAR2V( NR, AB( KA1, J2 ), AB( KA1, J2+1 ),$ AB( KA, J2+1 ), INCA, WORK( N+J2 ),$ WORK( J2 ), KA1 )*END IF** start applying rotations in 2nd set from the left*DO 190 L = KA - 1, KB - K + 1, -1NRT = ( N-J2+L ) / KA1IF( NRT.GT.0 )$ CALL DLARTV( NRT, AB( L, J2+KA1-L ), INCA,$ AB( L+1, J2+KA1-L ), INCA, WORK( N+J2 ),$ WORK( J2 ), KA1 )190 CONTINUE*IF( WANTX ) THEN** post-multiply X by product of rotations in 2nd set*DO 200 J = J2, J1, KA1CALL DROT( N-M, X( M+1, J ), 1, X( M+1, J+1 ), 1,$ WORK( N+J ), WORK( J ) )200 CONTINUEEND IF210 CONTINUE*DO 230 K = 1, KB - 1J2 = I - K - 1 + MAX( 1, K-I0+2 )*KA1** finish applying rotations in 1st set from the left*DO 220 L = KB - K, 1, -1NRT = ( N-J2+L ) / KA1IF( NRT.GT.0 )$ CALL DLARTV( NRT, AB( L, J2+KA1-L ), INCA,$ AB( L+1, J2+KA1-L ), INCA,$ WORK( N+J2-M ), WORK( J2-M ), KA1 )220 CONTINUE230 CONTINUE*IF( KB.GT.1 ) THENDO 240 J = N - 1, I - KB + 2*KA + 1, -1WORK( N+J-M ) = WORK( N+J-KA-M )WORK( J-M ) = WORK( J-KA-M )240 CONTINUEEND IF*ELSE** Transform A, working with the lower triangle*IF( UPDATE ) THEN** Form inv(S(i))**T * A * inv(S(i))*BII = BB( 1, I )DO 250 J = I, I1AB( J-I+1, I ) = AB( J-I+1, I ) / BII250 CONTINUEDO 260 J = MAX( 1, I-KA ), IAB( I-J+1, J ) = AB( I-J+1, J ) / BII260 CONTINUEDO 290 K = I - KBT, I - 1DO 270 J = I - KBT, KAB( K-J+1, J ) = AB( K-J+1, J ) -$ BB( I-J+1, J )*AB( I-K+1, K ) -$ BB( I-K+1, K )*AB( I-J+1, J ) +$ AB( 1, I )*BB( I-J+1, J )*$ BB( I-K+1, K )270 CONTINUEDO 280 J = MAX( 1, I-KA ), I - KBT - 1AB( K-J+1, J ) = AB( K-J+1, J ) -$ BB( I-K+1, K )*AB( I-J+1, J )280 CONTINUE290 CONTINUEDO 310 J = I, I1DO 300 K = MAX( J-KA, I-KBT ), I - 1AB( J-K+1, K ) = AB( J-K+1, K ) -$ BB( I-K+1, K )*AB( J-I+1, I )300 CONTINUE310 CONTINUE*IF( WANTX ) THEN** post-multiply X by inv(S(i))*CALL DSCAL( N-M, ONE / BII, X( M+1, I ), 1 )IF( KBT.GT.0 )$ CALL DGER( N-M, KBT, -ONE, X( M+1, I ), 1,$ BB( KBT+1, I-KBT ), LDBB-1,$ X( M+1, I-KBT ), LDX )END IF** store a(i1,i) in RA1 for use in next loop over K*RA1 = AB( I1-I+1, I )END IF** Generate and apply vectors of rotations to chase all the* existing bulges KA positions down toward the bottom of the* band*DO 360 K = 1, KB - 1IF( UPDATE ) THEN** Determine the rotations which would annihilate the bulge* which has in theory just been created*IF( I-K+KA.LT.N .AND. I-K.GT.1 ) THEN** generate rotation to annihilate a(i-k+ka+1,i)*CALL DLARTG( AB( KA1-K, I ), RA1, WORK( N+I-K+KA-M ),$ WORK( I-K+KA-M ), RA )** create nonzero element a(i-k+ka+1,i-k) outside the* band and store it in WORK(i-k)*T = -BB( K+1, I-K )*RA1WORK( I-K ) = WORK( N+I-K+KA-M )*T -$ WORK( I-K+KA-M )*AB( KA1, I-K )AB( KA1, I-K ) = WORK( I-K+KA-M )*T +$ WORK( N+I-K+KA-M )*AB( KA1, I-K )RA1 = RAEND IFEND IFJ2 = I - K - 1 + MAX( 1, K-I0+2 )*KA1NR = ( N-J2+KA ) / KA1J1 = J2 + ( NR-1 )*KA1IF( UPDATE ) THENJ2T = MAX( J2, I+2*KA-K+1 )ELSEJ2T = J2END IFNRT = ( N-J2T+KA ) / KA1DO 320 J = J2T, J1, KA1** create nonzero element a(j+1,j-ka) outside the band* and store it in WORK(j-m)*WORK( J-M ) = WORK( J-M )*AB( KA1, J-KA+1 )AB( KA1, J-KA+1 ) = WORK( N+J-M )*AB( KA1, J-KA+1 )320 CONTINUE** generate rotations in 1st set to annihilate elements which* have been created outside the band*IF( NRT.GT.0 )$ CALL DLARGV( NRT, AB( KA1, J2T-KA ), INCA, WORK( J2T-M ),$ KA1, WORK( N+J2T-M ), KA1 )IF( NR.GT.0 ) THEN** apply rotations in 1st set from the left*DO 330 L = 1, KA - 1CALL DLARTV( NR, AB( L+1, J2-L ), INCA,$ AB( L+2, J2-L ), INCA, WORK( N+J2-M ),$ WORK( J2-M ), KA1 )330 CONTINUE** apply rotations in 1st set from both sides to diagonal* blocks*CALL DLAR2V( NR, AB( 1, J2 ), AB( 1, J2+1 ), AB( 2, J2 ),$ INCA, WORK( N+J2-M ), WORK( J2-M ), KA1 )*END IF** start applying rotations in 1st set from the right*DO 340 L = KA - 1, KB - K + 1, -1NRT = ( N-J2+L ) / KA1IF( NRT.GT.0 )$ CALL DLARTV( NRT, AB( KA1-L+1, J2 ), INCA,$ AB( KA1-L, J2+1 ), INCA, WORK( N+J2-M ),$ WORK( J2-M ), KA1 )340 CONTINUE*IF( WANTX ) THEN** post-multiply X by product of rotations in 1st set*DO 350 J = J2, J1, KA1CALL DROT( N-M, X( M+1, J ), 1, X( M+1, J+1 ), 1,$ WORK( N+J-M ), WORK( J-M ) )350 CONTINUEEND IF360 CONTINUE*IF( UPDATE ) THENIF( I2.LE.N .AND. KBT.GT.0 ) THEN** create nonzero element a(i-kbt+ka+1,i-kbt) outside the* band and store it in WORK(i-kbt)*WORK( I-KBT ) = -BB( KBT+1, I-KBT )*RA1END IFEND IF*DO 400 K = KB, 1, -1IF( UPDATE ) THENJ2 = I - K - 1 + MAX( 2, K-I0+1 )*KA1ELSEJ2 = I - K - 1 + MAX( 1, K-I0+1 )*KA1END IF** finish applying rotations in 2nd set from the right*DO 370 L = KB - K, 1, -1NRT = ( N-J2+KA+L ) / KA1IF( NRT.GT.0 )$ CALL DLARTV( NRT, AB( KA1-L+1, J2-KA ), INCA,$ AB( KA1-L, J2-KA+1 ), INCA,$ WORK( N+J2-KA ), WORK( J2-KA ), KA1 )370 CONTINUENR = ( N-J2+KA ) / KA1J1 = J2 + ( NR-1 )*KA1DO 380 J = J1, J2, -KA1WORK( J ) = WORK( J-KA )WORK( N+J ) = WORK( N+J-KA )380 CONTINUEDO 390 J = J2, J1, KA1** create nonzero element a(j+1,j-ka) outside the band* and store it in WORK(j)*WORK( J ) = WORK( J )*AB( KA1, J-KA+1 )AB( KA1, J-KA+1 ) = WORK( N+J )*AB( KA1, J-KA+1 )390 CONTINUEIF( UPDATE ) THENIF( I-K.LT.N-KA .AND. K.LE.KBT )$ WORK( I-K+KA ) = WORK( I-K )END IF400 CONTINUE*DO 440 K = KB, 1, -1J2 = I - K - 1 + MAX( 1, K-I0+1 )*KA1NR = ( N-J2+KA ) / KA1J1 = J2 + ( NR-1 )*KA1IF( NR.GT.0 ) THEN** generate rotations in 2nd set to annihilate elements* which have been created outside the band*CALL DLARGV( NR, AB( KA1, J2-KA ), INCA, WORK( J2 ), KA1,$ WORK( N+J2 ), KA1 )** apply rotations in 2nd set from the left*DO 410 L = 1, KA - 1CALL DLARTV( NR, AB( L+1, J2-L ), INCA,$ AB( L+2, J2-L ), INCA, WORK( N+J2 ),$ WORK( J2 ), KA1 )410 CONTINUE** apply rotations in 2nd set from both sides to diagonal* blocks*CALL DLAR2V( NR, AB( 1, J2 ), AB( 1, J2+1 ), AB( 2, J2 ),$ INCA, WORK( N+J2 ), WORK( J2 ), KA1 )*END IF** start applying rotations in 2nd set from the right*DO 420 L = KA - 1, KB - K + 1, -1NRT = ( N-J2+L ) / KA1IF( NRT.GT.0 )$ CALL DLARTV( NRT, AB( KA1-L+1, J2 ), INCA,$ AB( KA1-L, J2+1 ), INCA, WORK( N+J2 ),$ WORK( J2 ), KA1 )420 CONTINUE*IF( WANTX ) THEN** post-multiply X by product of rotations in 2nd set*DO 430 J = J2, J1, KA1CALL DROT( N-M, X( M+1, J ), 1, X( M+1, J+1 ), 1,$ WORK( N+J ), WORK( J ) )430 CONTINUEEND IF440 CONTINUE*DO 460 K = 1, KB - 1J2 = I - K - 1 + MAX( 1, K-I0+2 )*KA1** finish applying rotations in 1st set from the right*DO 450 L = KB - K, 1, -1NRT = ( N-J2+L ) / KA1IF( NRT.GT.0 )$ CALL DLARTV( NRT, AB( KA1-L+1, J2 ), INCA,$ AB( KA1-L, J2+1 ), INCA, WORK( N+J2-M ),$ WORK( J2-M ), KA1 )450 CONTINUE460 CONTINUE*IF( KB.GT.1 ) THENDO 470 J = N - 1, I - KB + 2*KA + 1, -1WORK( N+J-M ) = WORK( N+J-KA-M )WORK( J-M ) = WORK( J-KA-M )470 CONTINUEEND IF*END IF*GO TO 10*480 CONTINUE** **************************** Phase 2 ******************************* The logical structure of this phase is:** UPDATE = .TRUE.* DO I = 1, M* use S(i) to update A and create a new bulge* apply rotations to push all bulges KA positions upward* END DO* UPDATE = .FALSE.* DO I = M - KA - 1, 2, -1* apply rotations to push all bulges KA positions upward* END DO** To avoid duplicating code, the two loops are merged.*UPDATE = .TRUE.I = 0490 CONTINUEIF( UPDATE ) THENI = I + 1KBT = MIN( KB, M-I )I0 = I + 1I1 = MAX( 1, I-KA )I2 = I + KBT - KA1IF( I.GT.M ) THENUPDATE = .FALSE.I = I - 1I0 = M + 1IF( KA.EQ.0 )$ RETURNGO TO 490END IFELSEI = I - KAIF( I.LT.2 )$ RETURNEND IF*IF( I.LT.M-KBT ) THENNX = MELSENX = NEND IF*IF( UPPER ) THEN** Transform A, working with the upper triangle*IF( UPDATE ) THEN** Form inv(S(i))**T * A * inv(S(i))*BII = BB( KB1, I )DO 500 J = I1, IAB( J-I+KA1, I ) = AB( J-I+KA1, I ) / BII500 CONTINUEDO 510 J = I, MIN( N, I+KA )AB( I-J+KA1, J ) = AB( I-J+KA1, J ) / BII510 CONTINUEDO 540 K = I + 1, I + KBTDO 520 J = K, I + KBTAB( K-J+KA1, J ) = AB( K-J+KA1, J ) -$ BB( I-J+KB1, J )*AB( I-K+KA1, K ) -$ BB( I-K+KB1, K )*AB( I-J+KA1, J ) +$ AB( KA1, I )*BB( I-J+KB1, J )*$ BB( I-K+KB1, K )520 CONTINUEDO 530 J = I + KBT + 1, MIN( N, I+KA )AB( K-J+KA1, J ) = AB( K-J+KA1, J ) -$ BB( I-K+KB1, K )*AB( I-J+KA1, J )530 CONTINUE540 CONTINUEDO 560 J = I1, IDO 550 K = I + 1, MIN( J+KA, I+KBT )AB( J-K+KA1, K ) = AB( J-K+KA1, K ) -$ BB( I-K+KB1, K )*AB( J-I+KA1, I )550 CONTINUE560 CONTINUE*IF( WANTX ) THEN** post-multiply X by inv(S(i))*CALL DSCAL( NX, ONE / BII, X( 1, I ), 1 )IF( KBT.GT.0 )$ CALL DGER( NX, KBT, -ONE, X( 1, I ), 1, BB( KB, I+1 ),$ LDBB-1, X( 1, I+1 ), LDX )END IF** store a(i1,i) in RA1 for use in next loop over K*RA1 = AB( I1-I+KA1, I )END IF** Generate and apply vectors of rotations to chase all the* existing bulges KA positions up toward the top of the band*DO 610 K = 1, KB - 1IF( UPDATE ) THEN** Determine the rotations which would annihilate the bulge* which has in theory just been created*IF( I+K-KA1.GT.0 .AND. I+K.LT.M ) THEN** generate rotation to annihilate a(i+k-ka-1,i)*CALL DLARTG( AB( K+1, I ), RA1, WORK( N+I+K-KA ),$ WORK( I+K-KA ), RA )** create nonzero element a(i+k-ka-1,i+k) outside the* band and store it in WORK(m-kb+i+k)*T = -BB( KB1-K, I+K )*RA1WORK( M-KB+I+K ) = WORK( N+I+K-KA )*T -$ WORK( I+K-KA )*AB( 1, I+K )AB( 1, I+K ) = WORK( I+K-KA )*T +$ WORK( N+I+K-KA )*AB( 1, I+K )RA1 = RAEND IFEND IFJ2 = I + K + 1 - MAX( 1, K+I0-M+1 )*KA1NR = ( J2+KA-1 ) / KA1J1 = J2 - ( NR-1 )*KA1IF( UPDATE ) THENJ2T = MIN( J2, I-2*KA+K-1 )ELSEJ2T = J2END IFNRT = ( J2T+KA-1 ) / KA1DO 570 J = J1, J2T, KA1** create nonzero element a(j-1,j+ka) outside the band* and store it in WORK(j)*WORK( J ) = WORK( J )*AB( 1, J+KA-1 )AB( 1, J+KA-1 ) = WORK( N+J )*AB( 1, J+KA-1 )570 CONTINUE** generate rotations in 1st set to annihilate elements which* have been created outside the band*IF( NRT.GT.0 )$ CALL DLARGV( NRT, AB( 1, J1+KA ), INCA, WORK( J1 ), KA1,$ WORK( N+J1 ), KA1 )IF( NR.GT.0 ) THEN** apply rotations in 1st set from the left*DO 580 L = 1, KA - 1CALL DLARTV( NR, AB( KA1-L, J1+L ), INCA,$ AB( KA-L, J1+L ), INCA, WORK( N+J1 ),$ WORK( J1 ), KA1 )580 CONTINUE** apply rotations in 1st set from both sides to diagonal* blocks*CALL DLAR2V( NR, AB( KA1, J1 ), AB( KA1, J1-1 ),$ AB( KA, J1 ), INCA, WORK( N+J1 ),$ WORK( J1 ), KA1 )*END IF** start applying rotations in 1st set from the right*DO 590 L = KA - 1, KB - K + 1, -1NRT = ( J2+L-1 ) / KA1J1T = J2 - ( NRT-1 )*KA1IF( NRT.GT.0 )$ CALL DLARTV( NRT, AB( L, J1T ), INCA,$ AB( L+1, J1T-1 ), INCA, WORK( N+J1T ),$ WORK( J1T ), KA1 )590 CONTINUE*IF( WANTX ) THEN** post-multiply X by product of rotations in 1st set*DO 600 J = J1, J2, KA1CALL DROT( NX, X( 1, J ), 1, X( 1, J-1 ), 1,$ WORK( N+J ), WORK( J ) )600 CONTINUEEND IF610 CONTINUE*IF( UPDATE ) THENIF( I2.GT.0 .AND. KBT.GT.0 ) THEN** create nonzero element a(i+kbt-ka-1,i+kbt) outside the* band and store it in WORK(m-kb+i+kbt)*WORK( M-KB+I+KBT ) = -BB( KB1-KBT, I+KBT )*RA1END IFEND IF*DO 650 K = KB, 1, -1IF( UPDATE ) THENJ2 = I + K + 1 - MAX( 2, K+I0-M )*KA1ELSEJ2 = I + K + 1 - MAX( 1, K+I0-M )*KA1END IF** finish applying rotations in 2nd set from the right*DO 620 L = KB - K, 1, -1NRT = ( J2+KA+L-1 ) / KA1J1T = J2 - ( NRT-1 )*KA1IF( NRT.GT.0 )$ CALL DLARTV( NRT, AB( L, J1T+KA ), INCA,$ AB( L+1, J1T+KA-1 ), INCA,$ WORK( N+M-KB+J1T+KA ),$ WORK( M-KB+J1T+KA ), KA1 )620 CONTINUENR = ( J2+KA-1 ) / KA1J1 = J2 - ( NR-1 )*KA1DO 630 J = J1, J2, KA1WORK( M-KB+J ) = WORK( M-KB+J+KA )WORK( N+M-KB+J ) = WORK( N+M-KB+J+KA )630 CONTINUEDO 640 J = J1, J2, KA1** create nonzero element a(j-1,j+ka) outside the band* and store it in WORK(m-kb+j)*WORK( M-KB+J ) = WORK( M-KB+J )*AB( 1, J+KA-1 )AB( 1, J+KA-1 ) = WORK( N+M-KB+J )*AB( 1, J+KA-1 )640 CONTINUEIF( UPDATE ) THENIF( I+K.GT.KA1 .AND. K.LE.KBT )$ WORK( M-KB+I+K-KA ) = WORK( M-KB+I+K )END IF650 CONTINUE*DO 690 K = KB, 1, -1J2 = I + K + 1 - MAX( 1, K+I0-M )*KA1NR = ( J2+KA-1 ) / KA1J1 = J2 - ( NR-1 )*KA1IF( NR.GT.0 ) THEN** generate rotations in 2nd set to annihilate elements* which have been created outside the band*CALL DLARGV( NR, AB( 1, J1+KA ), INCA, WORK( M-KB+J1 ),$ KA1, WORK( N+M-KB+J1 ), KA1 )** apply rotations in 2nd set from the left*DO 660 L = 1, KA - 1CALL DLARTV( NR, AB( KA1-L, J1+L ), INCA,$ AB( KA-L, J1+L ), INCA,$ WORK( N+M-KB+J1 ), WORK( M-KB+J1 ), KA1 )660 CONTINUE** apply rotations in 2nd set from both sides to diagonal* blocks*CALL DLAR2V( NR, AB( KA1, J1 ), AB( KA1, J1-1 ),$ AB( KA, J1 ), INCA, WORK( N+M-KB+J1 ),$ WORK( M-KB+J1 ), KA1 )*END IF** start applying rotations in 2nd set from the right*DO 670 L = KA - 1, KB - K + 1, -1NRT = ( J2+L-1 ) / KA1J1T = J2 - ( NRT-1 )*KA1IF( NRT.GT.0 )$ CALL DLARTV( NRT, AB( L, J1T ), INCA,$ AB( L+1, J1T-1 ), INCA,$ WORK( N+M-KB+J1T ), WORK( M-KB+J1T ),$ KA1 )670 CONTINUE*IF( WANTX ) THEN** post-multiply X by product of rotations in 2nd set*DO 680 J = J1, J2, KA1CALL DROT( NX, X( 1, J ), 1, X( 1, J-1 ), 1,$ WORK( N+M-KB+J ), WORK( M-KB+J ) )680 CONTINUEEND IF690 CONTINUE*DO 710 K = 1, KB - 1J2 = I + K + 1 - MAX( 1, K+I0-M+1 )*KA1** finish applying rotations in 1st set from the right*DO 700 L = KB - K, 1, -1NRT = ( J2+L-1 ) / KA1J1T = J2 - ( NRT-1 )*KA1IF( NRT.GT.0 )$ CALL DLARTV( NRT, AB( L, J1T ), INCA,$ AB( L+1, J1T-1 ), INCA, WORK( N+J1T ),$ WORK( J1T ), KA1 )700 CONTINUE710 CONTINUE*IF( KB.GT.1 ) THENDO 720 J = 2, MIN( I+KB, M ) - 2*KA - 1WORK( N+J ) = WORK( N+J+KA )WORK( J ) = WORK( J+KA )720 CONTINUEEND IF*ELSE** Transform A, working with the lower triangle*IF( UPDATE ) THEN** Form inv(S(i))**T * A * inv(S(i))*BII = BB( 1, I )DO 730 J = I1, IAB( I-J+1, J ) = AB( I-J+1, J ) / BII730 CONTINUEDO 740 J = I, MIN( N, I+KA )AB( J-I+1, I ) = AB( J-I+1, I ) / BII740 CONTINUEDO 770 K = I + 1, I + KBTDO 750 J = K, I + KBTAB( J-K+1, K ) = AB( J-K+1, K ) -$ BB( J-I+1, I )*AB( K-I+1, I ) -$ BB( K-I+1, I )*AB( J-I+1, I ) +$ AB( 1, I )*BB( J-I+1, I )*$ BB( K-I+1, I )750 CONTINUEDO 760 J = I + KBT + 1, MIN( N, I+KA )AB( J-K+1, K ) = AB( J-K+1, K ) -$ BB( K-I+1, I )*AB( J-I+1, I )760 CONTINUE770 CONTINUEDO 790 J = I1, IDO 780 K = I + 1, MIN( J+KA, I+KBT )AB( K-J+1, J ) = AB( K-J+1, J ) -$ BB( K-I+1, I )*AB( I-J+1, J )780 CONTINUE790 CONTINUE*IF( WANTX ) THEN** post-multiply X by inv(S(i))*CALL DSCAL( NX, ONE / BII, X( 1, I ), 1 )IF( KBT.GT.0 )$ CALL DGER( NX, KBT, -ONE, X( 1, I ), 1, BB( 2, I ), 1,$ X( 1, I+1 ), LDX )END IF** store a(i,i1) in RA1 for use in next loop over K*RA1 = AB( I-I1+1, I1 )END IF** Generate and apply vectors of rotations to chase all the* existing bulges KA positions up toward the top of the band*DO 840 K = 1, KB - 1IF( UPDATE ) THEN** Determine the rotations which would annihilate the bulge* which has in theory just been created*IF( I+K-KA1.GT.0 .AND. I+K.LT.M ) THEN** generate rotation to annihilate a(i,i+k-ka-1)*CALL DLARTG( AB( KA1-K, I+K-KA ), RA1,$ WORK( N+I+K-KA ), WORK( I+K-KA ), RA )** create nonzero element a(i+k,i+k-ka-1) outside the* band and store it in WORK(m-kb+i+k)*T = -BB( K+1, I )*RA1WORK( M-KB+I+K ) = WORK( N+I+K-KA )*T -$ WORK( I+K-KA )*AB( KA1, I+K-KA )AB( KA1, I+K-KA ) = WORK( I+K-KA )*T +$ WORK( N+I+K-KA )*AB( KA1, I+K-KA )RA1 = RAEND IFEND IFJ2 = I + K + 1 - MAX( 1, K+I0-M+1 )*KA1NR = ( J2+KA-1 ) / KA1J1 = J2 - ( NR-1 )*KA1IF( UPDATE ) THENJ2T = MIN( J2, I-2*KA+K-1 )ELSEJ2T = J2END IFNRT = ( J2T+KA-1 ) / KA1DO 800 J = J1, J2T, KA1** create nonzero element a(j+ka,j-1) outside the band* and store it in WORK(j)*WORK( J ) = WORK( J )*AB( KA1, J-1 )AB( KA1, J-1 ) = WORK( N+J )*AB( KA1, J-1 )800 CONTINUE** generate rotations in 1st set to annihilate elements which* have been created outside the band*IF( NRT.GT.0 )$ CALL DLARGV( NRT, AB( KA1, J1 ), INCA, WORK( J1 ), KA1,$ WORK( N+J1 ), KA1 )IF( NR.GT.0 ) THEN** apply rotations in 1st set from the right*DO 810 L = 1, KA - 1CALL DLARTV( NR, AB( L+1, J1 ), INCA, AB( L+2, J1-1 ),$ INCA, WORK( N+J1 ), WORK( J1 ), KA1 )810 CONTINUE** apply rotations in 1st set from both sides to diagonal* blocks*CALL DLAR2V( NR, AB( 1, J1 ), AB( 1, J1-1 ),$ AB( 2, J1-1 ), INCA, WORK( N+J1 ),$ WORK( J1 ), KA1 )*END IF** start applying rotations in 1st set from the left*DO 820 L = KA - 1, KB - K + 1, -1NRT = ( J2+L-1 ) / KA1J1T = J2 - ( NRT-1 )*KA1IF( NRT.GT.0 )$ CALL DLARTV( NRT, AB( KA1-L+1, J1T-KA1+L ), INCA,$ AB( KA1-L, J1T-KA1+L ), INCA,$ WORK( N+J1T ), WORK( J1T ), KA1 )820 CONTINUE*IF( WANTX ) THEN** post-multiply X by product of rotations in 1st set*DO 830 J = J1, J2, KA1CALL DROT( NX, X( 1, J ), 1, X( 1, J-1 ), 1,$ WORK( N+J ), WORK( J ) )830 CONTINUEEND IF840 CONTINUE*IF( UPDATE ) THENIF( I2.GT.0 .AND. KBT.GT.0 ) THEN** create nonzero element a(i+kbt,i+kbt-ka-1) outside the* band and store it in WORK(m-kb+i+kbt)*WORK( M-KB+I+KBT ) = -BB( KBT+1, I )*RA1END IFEND IF*DO 880 K = KB, 1, -1IF( UPDATE ) THENJ2 = I + K + 1 - MAX( 2, K+I0-M )*KA1ELSEJ2 = I + K + 1 - MAX( 1, K+I0-M )*KA1END IF** finish applying rotations in 2nd set from the left*DO 850 L = KB - K, 1, -1NRT = ( J2+KA+L-1 ) / KA1J1T = J2 - ( NRT-1 )*KA1IF( NRT.GT.0 )$ CALL DLARTV( NRT, AB( KA1-L+1, J1T+L-1 ), INCA,$ AB( KA1-L, J1T+L-1 ), INCA,$ WORK( N+M-KB+J1T+KA ),$ WORK( M-KB+J1T+KA ), KA1 )850 CONTINUENR = ( J2+KA-1 ) / KA1J1 = J2 - ( NR-1 )*KA1DO 860 J = J1, J2, KA1WORK( M-KB+J ) = WORK( M-KB+J+KA )WORK( N+M-KB+J ) = WORK( N+M-KB+J+KA )860 CONTINUEDO 870 J = J1, J2, KA1** create nonzero element a(j+ka,j-1) outside the band* and store it in WORK(m-kb+j)*WORK( M-KB+J ) = WORK( M-KB+J )*AB( KA1, J-1 )AB( KA1, J-1 ) = WORK( N+M-KB+J )*AB( KA1, J-1 )870 CONTINUEIF( UPDATE ) THENIF( I+K.GT.KA1 .AND. K.LE.KBT )$ WORK( M-KB+I+K-KA ) = WORK( M-KB+I+K )END IF880 CONTINUE*DO 920 K = KB, 1, -1J2 = I + K + 1 - MAX( 1, K+I0-M )*KA1NR = ( J2+KA-1 ) / KA1J1 = J2 - ( NR-1 )*KA1IF( NR.GT.0 ) THEN** generate rotations in 2nd set to annihilate elements* which have been created outside the band*CALL DLARGV( NR, AB( KA1, J1 ), INCA, WORK( M-KB+J1 ),$ KA1, WORK( N+M-KB+J1 ), KA1 )** apply rotations in 2nd set from the right*DO 890 L = 1, KA - 1CALL DLARTV( NR, AB( L+1, J1 ), INCA, AB( L+2, J1-1 ),$ INCA, WORK( N+M-KB+J1 ), WORK( M-KB+J1 ),$ KA1 )890 CONTINUE** apply rotations in 2nd set from both sides to diagonal* blocks*CALL DLAR2V( NR, AB( 1, J1 ), AB( 1, J1-1 ),$ AB( 2, J1-1 ), INCA, WORK( N+M-KB+J1 ),$ WORK( M-KB+J1 ), KA1 )*END IF** start applying rotations in 2nd set from the left*DO 900 L = KA - 1, KB - K + 1, -1NRT = ( J2+L-1 ) / KA1J1T = J2 - ( NRT-1 )*KA1IF( NRT.GT.0 )$ CALL DLARTV( NRT, AB( KA1-L+1, J1T-KA1+L ), INCA,$ AB( KA1-L, J1T-KA1+L ), INCA,$ WORK( N+M-KB+J1T ), WORK( M-KB+J1T ),$ KA1 )900 CONTINUE*IF( WANTX ) THEN** post-multiply X by product of rotations in 2nd set*DO 910 J = J1, J2, KA1CALL DROT( NX, X( 1, J ), 1, X( 1, J-1 ), 1,$ WORK( N+M-KB+J ), WORK( M-KB+J ) )910 CONTINUEEND IF920 CONTINUE*DO 940 K = 1, KB - 1J2 = I + K + 1 - MAX( 1, K+I0-M+1 )*KA1** finish applying rotations in 1st set from the left*DO 930 L = KB - K, 1, -1NRT = ( J2+L-1 ) / KA1J1T = J2 - ( NRT-1 )*KA1IF( NRT.GT.0 )$ CALL DLARTV( NRT, AB( KA1-L+1, J1T-KA1+L ), INCA,$ AB( KA1-L, J1T-KA1+L ), INCA,$ WORK( N+J1T ), WORK( J1T ), KA1 )930 CONTINUE940 CONTINUE*IF( KB.GT.1 ) THENDO 950 J = 2, MIN( I+KB, M ) - 2*KA - 1WORK( N+J ) = WORK( N+J+KA )WORK( J ) = WORK( J+KA )950 CONTINUEEND IF*END IF*GO TO 490** End of DSBGST*ENDSUBROUTINE DSBTRD( VECT, UPLO, N, KD, AB, LDAB, D, E, Q, LDQ,$ WORK, INFO )** -- LAPACK routine (version 3.0) --* Univ. of Tennessee, Univ. of California Berkeley, NAG Ltd.,* Courant Institute, Argonne National Lab, and Rice University* June 30, 1999** .. Scalar Arguments ..CHARACTER UPLO, VECTINTEGER INFO, KD, LDAB, LDQ, N* ..* .. Array Arguments ..DOUBLE PRECISION AB( LDAB, * ), D( * ), E( * ), Q( LDQ, * ),$ WORK( * )* ..** Purpose* =======** DSBTRD reduces a real symmetric band matrix A to symmetric* tridiagonal form T by an orthogonal similarity transformation:* Q**T * A * Q = T.** Arguments* =========** VECT (input) CHARACTER*1* = 'N': do not form Q;* = 'V': form Q;* = 'U': update a matrix X, by forming X*Q.** 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.** KD (input) INTEGER* The number of superdiagonals of the matrix A if UPLO = 'U',* or the number of subdiagonals if UPLO = 'L'. KD >= 0.** AB (input/output) DOUBLE PRECISION array, dimension (LDAB,N)* On entry, the upper or lower triangle of the symmetric band* matrix A, stored in the first KD+1 rows of the array. The* j-th column of A is stored in the j-th column of the array AB* as follows:* if UPLO = 'U', AB(kd+1+i-j,j) = A(i,j) for max(1,j-kd)<=i<=j;* if UPLO = 'L', AB(1+i-j,j) = A(i,j) for j<=i<=min(n,j+kd).* On exit, the diagonal elements of AB are overwritten by the* diagonal elements of the tridiagonal matrix T; if KD > 0, the* elements on the first superdiagonal (if UPLO = 'U') or the* first subdiagonal (if UPLO = 'L') are overwritten by the* off-diagonal elements of T; the rest of AB is overwritten by* values generated during the reduction.** LDAB (input) INTEGER* The leading dimension of the array AB. LDAB >= KD+1.** D (output) DOUBLE PRECISION array, dimension (N)* The diagonal elements of the tridiagonal matrix T.** E (output) DOUBLE PRECISION array, dimension (N-1)* The off-diagonal elements of the tridiagonal matrix T:* E(i) = T(i,i+1) if UPLO = 'U'; E(i) = T(i+1,i) if UPLO = 'L'.** Q (input/output) DOUBLE PRECISION array, dimension (LDQ,N)* On entry, if VECT = 'U', then Q must contain an N-by-N* matrix X; if VECT = 'N' or 'V', then Q need not be set.** On exit:* if VECT = 'V', Q contains the N-by-N orthogonal matrix Q;* if VECT = 'U', Q contains the product X*Q;* if VECT = 'N', the array Q is not referenced.** LDQ (input) INTEGER* The leading dimension of the array Q.* LDQ >= 1, and LDQ >= N if VECT = 'V' or 'U'.** WORK (workspace) DOUBLE PRECISION array, dimension (N)** INFO (output) INTEGER* = 0: successful exit* < 0: if INFO = -i, the i-th argument had an illegal value** Further Details* ===============** Modified by Linda Kaufman, Bell Labs.** =====================================================================** .. Parameters ..DOUBLE PRECISION ZERO, ONEPARAMETER ( ZERO = 0.0D+0, ONE = 1.0D+0 )* ..* .. Local Scalars ..LOGICAL INITQ, UPPER, WANTQINTEGER I, I2, IBL, INCA, INCX, IQAEND, IQB, IQEND, J,$ J1, J1END, J1INC, J2, JEND, JIN, JINC, K, KD1,$ KDM1, KDN, L, LAST, LEND, NQ, NR, NRTDOUBLE PRECISION TEMP* ..* .. External Subroutines ..EXTERNAL DLAR2V, DLARGV, DLARTG, DLARTV, DLASET, DROT,$ XERBLA* ..* .. Intrinsic Functions ..INTRINSIC MAX, MIN* ..* .. External Functions ..LOGICAL LSAMEEXTERNAL LSAME* ..* .. Executable Statements ..** Test the input parameters*INITQ = LSAME( VECT, 'V' )WANTQ = INITQ .OR. LSAME( VECT, 'U' )UPPER = LSAME( UPLO, 'U' )KD1 = KD + 1KDM1 = KD - 1INCX = LDAB - 1IQEND = 1*INFO = 0IF( .NOT.WANTQ .AND. .NOT.LSAME( VECT, 'N' ) ) THENINFO = -1ELSE IF( .NOT.UPPER .AND. .NOT.LSAME( UPLO, 'L' ) ) THENINFO = -2ELSE IF( N.LT.0 ) THENINFO = -3ELSE IF( KD.LT.0 ) THENINFO = -4ELSE IF( LDAB.LT.KD1 ) THENINFO = -6ELSE IF( LDQ.LT.MAX( 1, N ) .AND. WANTQ ) THENINFO = -10END IFIF( INFO.NE.0 ) THENCALL XERBLA( 'DSBTRD', -INFO )RETURNEND IF** Quick return if possible*IF( N.EQ.0 )$ RETURN** Initialize Q to the unit matrix, if needed*IF( INITQ )$ CALL DLASET( 'Full', N, N, ZERO, ONE, Q, LDQ )** Wherever possible, plane rotations are generated and applied in* vector operations of length NR over the index set J1:J2:KD1.** The cosines and sines of the plane rotations are stored in the* arrays D and WORK.*INCA = KD1*LDABKDN = MIN( N-1, KD )IF( UPPER ) THEN*IF( KD.GT.1 ) THEN** Reduce to tridiagonal form, working with upper triangle*NR = 0J1 = KDN + 2J2 = 1*DO 90 I = 1, N - 2** Reduce i-th row of matrix to tridiagonal form*DO 80 K = KDN + 1, 2, -1J1 = J1 + KDNJ2 = J2 + KDN*IF( NR.GT.0 ) THEN** generate plane rotations to annihilate nonzero* elements which have been created outside the band*CALL DLARGV( NR, AB( 1, J1-1 ), INCA, WORK( J1 ),$ KD1, D( J1 ), KD1 )** apply rotations from the right*** Dependent on the the number of diagonals either* DLARTV or DROT is used*IF( NR.GE.2*KD-1 ) THENDO 10 L = 1, KD - 1CALL DLARTV( NR, AB( L+1, J1-1 ), INCA,$ AB( L, J1 ), INCA, D( J1 ),$ WORK( J1 ), KD1 )10 CONTINUE*ELSEJEND = J1 + ( NR-1 )*KD1DO 20 JINC = J1, JEND, KD1CALL DROT( KDM1, AB( 2, JINC-1 ), 1,$ AB( 1, JINC ), 1, D( JINC ),$ WORK( JINC ) )20 CONTINUEEND IFEND IF**IF( K.GT.2 ) THENIF( K.LE.N-I+1 ) THEN** generate plane rotation to annihilate a(i,i+k-1)* within the band*CALL DLARTG( AB( KD-K+3, I+K-2 ),$ AB( KD-K+2, I+K-1 ), D( I+K-1 ),$ WORK( I+K-1 ), TEMP )AB( KD-K+3, I+K-2 ) = TEMP** apply rotation from the right*CALL DROT( K-3, AB( KD-K+4, I+K-2 ), 1,$ AB( KD-K+3, I+K-1 ), 1, D( I+K-1 ),$ WORK( I+K-1 ) )END IFNR = NR + 1J1 = J1 - KDN - 1END IF** apply plane rotations from both sides to diagonal* blocks*IF( NR.GT.0 )$ CALL DLAR2V( NR, AB( KD1, J1-1 ), AB( KD1, J1 ),$ AB( KD, J1 ), INCA, D( J1 ),$ WORK( J1 ), KD1 )** apply plane rotations from the left*IF( NR.GT.0 ) THENIF( 2*KD-1.LT.NR ) THEN** Dependent on the the number of diagonals either* DLARTV or DROT is used*DO 30 L = 1, KD - 1IF( J2+L.GT.N ) THENNRT = NR - 1ELSENRT = NREND IFIF( NRT.GT.0 )$ CALL DLARTV( NRT, AB( KD-L, J1+L ), INCA,$ AB( KD-L+1, J1+L ), INCA,$ D( J1 ), WORK( J1 ), KD1 )30 CONTINUEELSEJ1END = J1 + KD1*( NR-2 )IF( J1END.GE.J1 ) THENDO 40 JIN = J1, J1END, KD1CALL DROT( KD-1, AB( KD-1, JIN+1 ), INCX,$ AB( KD, JIN+1 ), INCX,$ D( JIN ), WORK( JIN ) )40 CONTINUEEND IFLEND = MIN( KDM1, N-J2 )LAST = J1END + KD1IF( LEND.GT.0 )$ CALL DROT( LEND, AB( KD-1, LAST+1 ), INCX,$ AB( KD, LAST+1 ), INCX, D( LAST ),$ WORK( LAST ) )END IFEND IF*IF( WANTQ ) THEN** accumulate product of plane rotations in Q*IF( INITQ ) THEN** take advantage of the fact that Q was* initially the Identity matrix*IQEND = MAX( IQEND, J2 )I2 = MAX( 0, K-3 )IQAEND = 1 + I*KDIF( K.EQ.2 )$ IQAEND = IQAEND + KDIQAEND = MIN( IQAEND, IQEND )DO 50 J = J1, J2, KD1IBL = I - I2 / KDM1I2 = I2 + 1IQB = MAX( 1, J-IBL )NQ = 1 + IQAEND - IQBIQAEND = MIN( IQAEND+KD, IQEND )CALL DROT( NQ, Q( IQB, J-1 ), 1, Q( IQB, J ),$ 1, D( J ), WORK( J ) )50 CONTINUEELSE*DO 60 J = J1, J2, KD1CALL DROT( N, Q( 1, J-1 ), 1, Q( 1, J ), 1,$ D( J ), WORK( J ) )60 CONTINUEEND IF*END IF*IF( J2+KDN.GT.N ) THEN** adjust J2 to keep within the bounds of the matrix*NR = NR - 1J2 = J2 - KDN - 1END IF*DO 70 J = J1, J2, KD1** create nonzero element a(j-1,j+kd) outside the band* and store it in WORK*WORK( J+KD ) = WORK( J )*AB( 1, J+KD )AB( 1, J+KD ) = D( J )*AB( 1, J+KD )70 CONTINUE80 CONTINUE90 CONTINUEEND IF*IF( KD.GT.0 ) THEN** copy off-diagonal elements to E*DO 100 I = 1, N - 1E( I ) = AB( KD, I+1 )100 CONTINUEELSE** set E to zero if original matrix was diagonal*DO 110 I = 1, N - 1E( I ) = ZERO110 CONTINUEEND IF** copy diagonal elements to D*DO 120 I = 1, ND( I ) = AB( KD1, I )120 CONTINUE*ELSE*IF( KD.GT.1 ) THEN** Reduce to tridiagonal form, working with lower triangle*NR = 0J1 = KDN + 2J2 = 1*DO 210 I = 1, N - 2** Reduce i-th column of matrix to tridiagonal form*DO 200 K = KDN + 1, 2, -1J1 = J1 + KDNJ2 = J2 + KDN*IF( NR.GT.0 ) THEN** generate plane rotations to annihilate nonzero* elements which have been created outside the band*CALL DLARGV( NR, AB( KD1, J1-KD1 ), INCA,$ WORK( J1 ), KD1, D( J1 ), KD1 )** apply plane rotations from one side*** Dependent on the the number of diagonals either* DLARTV or DROT is used*IF( NR.GT.2*KD-1 ) THENDO 130 L = 1, KD - 1CALL DLARTV( NR, AB( KD1-L, J1-KD1+L ), INCA,$ AB( KD1-L+1, J1-KD1+L ), INCA,$ D( J1 ), WORK( J1 ), KD1 )130 CONTINUEELSEJEND = J1 + KD1*( NR-1 )DO 140 JINC = J1, JEND, KD1CALL DROT( KDM1, AB( KD, JINC-KD ), INCX,$ AB( KD1, JINC-KD ), INCX,$ D( JINC ), WORK( JINC ) )140 CONTINUEEND IF*END IF*IF( K.GT.2 ) THENIF( K.LE.N-I+1 ) THEN** generate plane rotation to annihilate a(i+k-1,i)* within the band*CALL DLARTG( AB( K-1, I ), AB( K, I ),$ D( I+K-1 ), WORK( I+K-1 ), TEMP )AB( K-1, I ) = TEMP** apply rotation from the left*CALL DROT( K-3, AB( K-2, I+1 ), LDAB-1,$ AB( K-1, I+1 ), LDAB-1, D( I+K-1 ),$ WORK( I+K-1 ) )END IFNR = NR + 1J1 = J1 - KDN - 1END IF** apply plane rotations from both sides to diagonal* blocks*IF( NR.GT.0 )$ CALL DLAR2V( NR, AB( 1, J1-1 ), AB( 1, J1 ),$ AB( 2, J1-1 ), INCA, D( J1 ),$ WORK( J1 ), KD1 )** apply plane rotations from the right*** Dependent on the the number of diagonals either* DLARTV or DROT is used*IF( NR.GT.0 ) THENIF( NR.GT.2*KD-1 ) THENDO 150 L = 1, KD - 1IF( J2+L.GT.N ) THENNRT = NR - 1ELSENRT = NREND IFIF( NRT.GT.0 )$ CALL DLARTV( NRT, AB( L+2, J1-1 ), INCA,$ AB( L+1, J1 ), INCA, D( J1 ),$ WORK( J1 ), KD1 )150 CONTINUEELSEJ1END = J1 + KD1*( NR-2 )IF( J1END.GE.J1 ) THENDO 160 J1INC = J1, J1END, KD1CALL DROT( KDM1, AB( 3, J1INC-1 ), 1,$ AB( 2, J1INC ), 1, D( J1INC ),$ WORK( J1INC ) )160 CONTINUEEND IFLEND = MIN( KDM1, N-J2 )LAST = J1END + KD1IF( LEND.GT.0 )$ CALL DROT( LEND, AB( 3, LAST-1 ), 1,$ AB( 2, LAST ), 1, D( LAST ),$ WORK( LAST ) )END IFEND IF***IF( WANTQ ) THEN** accumulate product of plane rotations in Q*IF( INITQ ) THEN** take advantage of the fact that Q was* initially the Identity matrix*IQEND = MAX( IQEND, J2 )I2 = MAX( 0, K-3 )IQAEND = 1 + I*KDIF( K.EQ.2 )$ IQAEND = IQAEND + KDIQAEND = MIN( IQAEND, IQEND )DO 170 J = J1, J2, KD1IBL = I - I2 / KDM1I2 = I2 + 1IQB = MAX( 1, J-IBL )NQ = 1 + IQAEND - IQBIQAEND = MIN( IQAEND+KD, IQEND )CALL DROT( NQ, Q( IQB, J-1 ), 1, Q( IQB, J ),$ 1, D( J ), WORK( J ) )170 CONTINUEELSE*DO 180 J = J1, J2, KD1CALL DROT( N, Q( 1, J-1 ), 1, Q( 1, J ), 1,$ D( J ), WORK( J ) )180 CONTINUEEND IFEND IF*IF( J2+KDN.GT.N ) THEN** adjust J2 to keep within the bounds of the matrix*NR = NR - 1J2 = J2 - KDN - 1END IF*DO 190 J = J1, J2, KD1** create nonzero element a(j+kd,j-1) outside the* band and store it in WORK*WORK( J+KD ) = WORK( J )*AB( KD1, J )AB( KD1, J ) = D( J )*AB( KD1, J )190 CONTINUE200 CONTINUE210 CONTINUEEND IF*IF( KD.GT.0 ) THEN** copy off-diagonal elements to E*DO 220 I = 1, N - 1E( I ) = AB( 2, I )220 CONTINUEELSE** set E to zero if original matrix was diagonal*DO 230 I = 1, N - 1E( I ) = ZERO230 CONTINUEEND IF** copy diagonal elements to D*DO 240 I = 1, ND( I ) = AB( 1, I )240 CONTINUEEND IF*RETURN** End of DSBTRD*ENDSUBROUTINE DSPCON( UPLO, N, AP, IPIV, ANORM, RCOND, WORK, IWORK,$ INFO )** -- LAPACK routine (version 3.0) --* Univ. of Tennessee, Univ. of California Berkeley, NAG Ltd.,* Courant Institute, Argonne National Lab, and Rice University* March 31, 1993** .. Scalar Arguments ..CHARACTER UPLOINTEGER INFO, NDOUBLE PRECISION ANORM, RCOND* ..* .. Array Arguments ..INTEGER IPIV( * ), IWORK( * )DOUBLE PRECISION AP( * ), WORK( * )* ..** Purpose* =======** DSPCON estimates the reciprocal of the condition number (in the* 1-norm) of a real symmetric packed matrix A using the factorization* A = U*D*U**T or A = L*D*L**T computed by DSPTRF.** An estimate is obtained for norm(inv(A)), and the reciprocal of the* condition number is computed as RCOND = 1 / (ANORM * norm(inv(A))).** 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**T;* = 'L': Lower triangular, form is A = L*D*L**T.** N (input) INTEGER* The order of the matrix A. N >= 0.** AP (input) DOUBLE PRECISION array, dimension (N*(N+1)/2)* The block diagonal matrix D and the multipliers used to* obtain the factor U or L as computed by DSPTRF, stored as a* packed triangular matrix.** IPIV (input) INTEGER array, dimension (N)* Details of the interchanges and the block structure of D* as determined by DSPTRF.** ANORM (input) DOUBLE PRECISION* The 1-norm of the original matrix A.** RCOND (output) DOUBLE PRECISION* The reciprocal of the condition number of the matrix A,* computed as RCOND = 1/(ANORM * AINVNM), where AINVNM is an* estimate of the 1-norm of inv(A) computed in this routine.** WORK (workspace) DOUBLE PRECISION array, dimension (2*N)** IWORK (workspace) INTEGER array, dimension (N)** INFO (output) INTEGER* = 0: successful exit* < 0: if INFO = -i, the i-th argument had an illegal value** =====================================================================** .. Parameters ..DOUBLE PRECISION ONE, ZEROPARAMETER ( ONE = 1.0D+0, ZERO = 0.0D+0 )* ..* .. Local Scalars ..LOGICAL UPPERINTEGER I, IP, KASEDOUBLE PRECISION AINVNM* ..* .. External Functions ..LOGICAL LSAMEEXTERNAL LSAME* ..* .. External Subroutines ..EXTERNAL DLACON, DSPTRS, XERBLA* ..* .. Executable Statements ..** Test the input parameters.*INFO = 0UPPER = LSAME( UPLO, 'U' )IF( .NOT.UPPER .AND. .NOT.LSAME( UPLO, 'L' ) ) THENINFO = -1ELSE IF( N.LT.0 ) THENINFO = -2ELSE IF( ANORM.LT.ZERO ) THENINFO = -5END IFIF( INFO.NE.0 ) THENCALL XERBLA( 'DSPCON', -INFO )RETURNEND IF** Quick return if possible*RCOND = ZEROIF( N.EQ.0 ) THENRCOND = ONERETURNELSE IF( ANORM.LE.ZERO ) THENRETURNEND IF** Check that the diagonal matrix D is nonsingular.*IF( UPPER ) THEN** Upper triangular storage: examine D from bottom to top*IP = N*( N+1 ) / 2DO 10 I = N, 1, -1IF( IPIV( I ).GT.0 .AND. AP( IP ).EQ.ZERO )$ RETURNIP = IP - I10 CONTINUEELSE** Lower triangular storage: examine D from top to bottom.*IP = 1DO 20 I = 1, NIF( IPIV( I ).GT.0 .AND. AP( IP ).EQ.ZERO )$ RETURNIP = IP + N - I + 120 CONTINUEEND IF** Estimate the 1-norm of the inverse.*KASE = 030 CONTINUECALL DLACON( N, WORK( N+1 ), WORK, IWORK, AINVNM, KASE )IF( KASE.NE.0 ) THEN** Multiply by inv(L*D*L') or inv(U*D*U').*CALL DSPTRS( UPLO, N, 1, AP, IPIV, WORK, N, INFO )GO TO 30END IF** Compute the estimate of the reciprocal condition number.*IF( AINVNM.NE.ZERO )$ RCOND = ( ONE / AINVNM ) / ANORM*RETURN** End of DSPCON*ENDSUBROUTINE DSPGST( ITYPE, UPLO, N, AP, BP, INFO )** -- LAPACK routine (version 3.0) --* Univ. of Tennessee, Univ. of California Berkeley, NAG Ltd.,* Courant Institute, Argonne National Lab, and Rice University* March 31, 1993** .. Scalar Arguments ..CHARACTER UPLOINTEGER INFO, ITYPE, N* ..* .. Array Arguments ..DOUBLE PRECISION AP( * ), BP( * )* ..** Purpose* =======** DSPGST reduces a real symmetric-definite generalized eigenproblem* to standard form, using packed storage.** If ITYPE = 1, the problem is A*x = lambda*B*x,* and A is overwritten by inv(U**T)*A*inv(U) or inv(L)*A*inv(L**T)** If ITYPE = 2 or 3, the problem is A*B*x = lambda*x or* B*A*x = lambda*x, and A is overwritten by U*A*U**T or L**T*A*L.** B must have been previously factorized as U**T*U or L*L**T by DPPTRF.** Arguments* =========** ITYPE (input) INTEGER* = 1: compute inv(U**T)*A*inv(U) or inv(L)*A*inv(L**T);* = 2 or 3: compute U*A*U**T or L**T*A*L.** UPLO (input) CHARACTER* = 'U': Upper triangle of A is stored and B is factored as* U**T*U;* = 'L': Lower triangle of A is stored and B is factored as* L*L**T.** N (input) INTEGER* The order of the matrices A and B. N >= 0.** AP (input/output) DOUBLE PRECISION array, dimension (N*(N+1)/2)* On entry, the upper or lower triangle of the symmetric matrix* A, packed columnwise in a linear array. The j-th column of A* is stored in the array AP as follows:* if UPLO = 'U', AP(i + (j-1)*j/2) = A(i,j) for 1<=i<=j;* if UPLO = 'L', AP(i + (j-1)*(2n-j)/2) = A(i,j) for j<=i<=n.** On exit, if INFO = 0, the transformed matrix, stored in the* same format as A.** BP (input) DOUBLE PRECISION array, dimension (N*(N+1)/2)* The triangular factor from the Cholesky factorization of B,* stored in the same format as A, as returned by DPPTRF.** INFO (output) INTEGER* = 0: successful exit* < 0: if INFO = -i, the i-th argument had an illegal value** =====================================================================** .. Parameters ..DOUBLE PRECISION ONE, HALFPARAMETER ( ONE = 1.0D0, HALF = 0.5D0 )* ..* .. Local Scalars ..LOGICAL UPPERINTEGER J, J1, J1J1, JJ, K, K1, K1K1, KKDOUBLE PRECISION AJJ, AKK, BJJ, BKK, CT* ..* .. External Subroutines ..EXTERNAL DAXPY, DSCAL, DSPMV, DSPR2, DTPMV, DTPSV,$ XERBLA* ..* .. External Functions ..LOGICAL LSAMEDOUBLE PRECISION DDOTEXTERNAL LSAME, DDOT* ..* .. Executable Statements ..** Test the input parameters.*INFO = 0UPPER = LSAME( UPLO, 'U' )IF( ITYPE.LT.1 .OR. ITYPE.GT.3 ) THENINFO = -1ELSE IF( .NOT.UPPER .AND. .NOT.LSAME( UPLO, 'L' ) ) THENINFO = -2ELSE IF( N.LT.0 ) THENINFO = -3END IFIF( INFO.NE.0 ) THENCALL XERBLA( 'DSPGST', -INFO )RETURNEND IF*IF( ITYPE.EQ.1 ) THENIF( UPPER ) THEN** Compute inv(U')*A*inv(U)** J1 and JJ are the indices of A(1,j) and A(j,j)*JJ = 0DO 10 J = 1, NJ1 = JJ + 1JJ = JJ + J** Compute the j-th column of the upper triangle of A*BJJ = BP( JJ )CALL DTPSV( UPLO, 'Transpose', 'Nonunit', J, BP,$ AP( J1 ), 1 )CALL DSPMV( UPLO, J-1, -ONE, AP, BP( J1 ), 1, ONE,$ AP( J1 ), 1 )CALL DSCAL( J-1, ONE / BJJ, AP( J1 ), 1 )AP( JJ ) = ( AP( JJ )-DDOT( J-1, AP( J1 ), 1, BP( J1 ),$ 1 ) ) / BJJ10 CONTINUEELSE** Compute inv(L)*A*inv(L')** KK and K1K1 are the indices of A(k,k) and A(k+1,k+1)*KK = 1DO 20 K = 1, NK1K1 = KK + N - K + 1** Update the lower triangle of A(k:n,k:n)*AKK = AP( KK )BKK = BP( KK )AKK = AKK / BKK**2AP( KK ) = AKKIF( K.LT.N ) THENCALL DSCAL( N-K, ONE / BKK, AP( KK+1 ), 1 )CT = -HALF*AKKCALL DAXPY( N-K, CT, BP( KK+1 ), 1, AP( KK+1 ), 1 )CALL DSPR2( UPLO, N-K, -ONE, AP( KK+1 ), 1,$ BP( KK+1 ), 1, AP( K1K1 ) )CALL DAXPY( N-K, CT, BP( KK+1 ), 1, AP( KK+1 ), 1 )CALL DTPSV( UPLO, 'No transpose', 'Non-unit', N-K,$ BP( K1K1 ), AP( KK+1 ), 1 )END IFKK = K1K120 CONTINUEEND IFELSEIF( UPPER ) THEN** Compute U*A*U'** K1 and KK are the indices of A(1,k) and A(k,k)*KK = 0DO 30 K = 1, NK1 = KK + 1KK = KK + K** Update the upper triangle of A(1:k,1:k)*AKK = AP( KK )BKK = BP( KK )CALL DTPMV( UPLO, 'No transpose', 'Non-unit', K-1, BP,$ AP( K1 ), 1 )CT = HALF*AKKCALL DAXPY( K-1, CT, BP( K1 ), 1, AP( K1 ), 1 )CALL DSPR2( UPLO, K-1, ONE, AP( K1 ), 1, BP( K1 ), 1,$ AP )CALL DAXPY( K-1, CT, BP( K1 ), 1, AP( K1 ), 1 )CALL DSCAL( K-1, BKK, AP( K1 ), 1 )AP( KK ) = AKK*BKK**230 CONTINUEELSE** Compute L'*A*L** JJ and J1J1 are the indices of A(j,j) and A(j+1,j+1)*JJ = 1DO 40 J = 1, NJ1J1 = JJ + N - J + 1** Compute the j-th column of the lower triangle of A*AJJ = AP( JJ )BJJ = BP( JJ )AP( JJ ) = AJJ*BJJ + DDOT( N-J, AP( JJ+1 ), 1,$ BP( JJ+1 ), 1 )CALL DSCAL( N-J, BJJ, AP( JJ+1 ), 1 )CALL DSPMV( UPLO, N-J, ONE, AP( J1J1 ), BP( JJ+1 ), 1,$ ONE, AP( JJ+1 ), 1 )CALL DTPMV( UPLO, 'Transpose', 'Non-unit', N-J+1,$ BP( JJ ), AP( JJ ), 1 )JJ = J1J140 CONTINUEEND IFEND IFRETURN** End of DSPGST*ENDSUBROUTINE DSPRFS( UPLO, N, NRHS, AP, AFP, IPIV, B, LDB, X, LDX,$ FERR, BERR, WORK, IWORK, INFO )** -- LAPACK routine (version 3.0) --* Univ. of Tennessee, Univ. of California Berkeley, NAG Ltd.,* Courant Institute, Argonne National Lab, and Rice University* September 30, 1994** .. Scalar Arguments ..CHARACTER UPLOINTEGER INFO, LDB, LDX, N, NRHS* ..* .. Array Arguments ..INTEGER IPIV( * ), IWORK( * )DOUBLE PRECISION AFP( * ), AP( * ), B( LDB, * ), BERR( * ),$ FERR( * ), WORK( * ), X( LDX, * )* ..** Purpose* =======** DSPRFS improves the computed solution to a system of linear* equations when the coefficient matrix is symmetric indefinite* and packed, and provides error bounds and backward error estimates* for the solution.** 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.** NRHS (input) INTEGER* The number of right hand sides, i.e., the number of columns* of the matrices B and X. NRHS >= 0.** AP (input) DOUBLE PRECISION array, dimension (N*(N+1)/2)* The upper or lower triangle of the symmetric matrix A, packed* columnwise in a linear array. The j-th column of A is stored* in the array AP as follows:* if UPLO = 'U', AP(i + (j-1)*j/2) = A(i,j) for 1<=i<=j;* if UPLO = 'L', AP(i + (j-1)*(2*n-j)/2) = A(i,j) for j<=i<=n.** AFP (input) DOUBLE PRECISION array, dimension (N*(N+1)/2)* The factored form of the matrix A. AFP contains the block* diagonal matrix D and the multipliers used to obtain the* factor U or L from the factorization A = U*D*U**T or* A = L*D*L**T as computed by DSPTRF, stored as a packed* triangular matrix.** IPIV (input) INTEGER array, dimension (N)* Details of the interchanges and the block structure of D* as determined by DSPTRF.** B (input) DOUBLE PRECISION array, dimension (LDB,NRHS)* The right hand side matrix B.** LDB (input) INTEGER* The leading dimension of the array B. LDB >= max(1,N).** X (input/output) DOUBLE PRECISION array, dimension (LDX,NRHS)* On entry, the solution matrix X, as computed by DSPTRS.* On exit, the improved solution matrix X.** LDX (input) INTEGER* The leading dimension of the array X. LDX >= max(1,N).** FERR (output) DOUBLE PRECISION array, dimension (NRHS)* The estimated forward error bound for each solution vector* X(j) (the j-th column of the solution matrix X).* If XTRUE is the true solution corresponding to X(j), FERR(j)* is an estimated upper bound for the magnitude of the largest* element in (X(j) - XTRUE) divided by the magnitude of the* largest element in X(j). The estimate is as reliable as* the estimate for RCOND, and is almost always a slight* overestimate of the true error.** BERR (output) DOUBLE PRECISION array, dimension (NRHS)* The componentwise relative backward error of each solution* vector X(j) (i.e., the smallest relative change in* any element of A or B that makes X(j) an exact solution).** WORK (workspace) DOUBLE PRECISION array, dimension (3*N)** IWORK (workspace) INTEGER array, dimension (N)** INFO (output) INTEGER* = 0: successful exit* < 0: if INFO = -i, the i-th argument had an illegal value** Internal Parameters* ===================** ITMAX is the maximum number of steps of iterative refinement.** =====================================================================** .. Parameters ..INTEGER ITMAXPARAMETER ( ITMAX = 5 )DOUBLE PRECISION ZEROPARAMETER ( ZERO = 0.0D+0 )DOUBLE PRECISION ONEPARAMETER ( ONE = 1.0D+0 )DOUBLE PRECISION TWOPARAMETER ( TWO = 2.0D+0 )DOUBLE PRECISION THREEPARAMETER ( THREE = 3.0D+0 )* ..* .. Local Scalars ..LOGICAL UPPERINTEGER COUNT, I, IK, J, K, KASE, KK, NZDOUBLE PRECISION EPS, LSTRES, S, SAFE1, SAFE2, SAFMIN, XK* ..* .. External Subroutines ..EXTERNAL DAXPY, DCOPY, DLACON, DSPMV, DSPTRS, XERBLA* ..* .. Intrinsic Functions ..INTRINSIC ABS, MAX* ..* .. External Functions ..LOGICAL LSAMEDOUBLE PRECISION DLAMCHEXTERNAL LSAME, DLAMCH* ..* .. Executable Statements ..** Test the input parameters.*INFO = 0UPPER = LSAME( UPLO, 'U' )IF( .NOT.UPPER .AND. .NOT.LSAME( UPLO, 'L' ) ) THENINFO = -1ELSE IF( N.LT.0 ) THENINFO = -2ELSE IF( NRHS.LT.0 ) THENINFO = -3ELSE IF( LDB.LT.MAX( 1, N ) ) THENINFO = -8ELSE IF( LDX.LT.MAX( 1, N ) ) THENINFO = -10END IFIF( INFO.NE.0 ) THENCALL XERBLA( 'DSPRFS', -INFO )RETURNEND IF** Quick return if possible*IF( N.EQ.0 .OR. NRHS.EQ.0 ) THENDO 10 J = 1, NRHSFERR( J ) = ZEROBERR( J ) = ZERO10 CONTINUERETURNEND IF** NZ = maximum number of nonzero elements in each row of A, plus 1*NZ = N + 1EPS = DLAMCH( 'Epsilon' )SAFMIN = DLAMCH( 'Safe minimum' )SAFE1 = NZ*SAFMINSAFE2 = SAFE1 / EPS** Do for each right hand side*DO 140 J = 1, NRHS*COUNT = 1LSTRES = THREE20 CONTINUE** Loop until stopping criterion is satisfied.** Compute residual R = B - A * X*CALL DCOPY( N, B( 1, J ), 1, WORK( N+1 ), 1 )CALL DSPMV( UPLO, N, -ONE, AP, X( 1, J ), 1, ONE, WORK( N+1 ),$ 1 )** Compute componentwise relative backward error from formula** max(i) ( abs(R(i)) / ( abs(A)*abs(X) + abs(B) )(i) )** where abs(Z) is the componentwise absolute value of the matrix* or vector Z. If the i-th component of the denominator is less* than SAFE2, then SAFE1 is added to the i-th components of the* numerator and denominator before dividing.*DO 30 I = 1, NWORK( I ) = ABS( B( I, J ) )30 CONTINUE** Compute abs(A)*abs(X) + abs(B).*KK = 1IF( UPPER ) THENDO 50 K = 1, NS = ZEROXK = ABS( X( K, J ) )IK = KKDO 40 I = 1, K - 1WORK( I ) = WORK( I ) + ABS( AP( IK ) )*XKS = S + ABS( AP( IK ) )*ABS( X( I, J ) )IK = IK + 140 CONTINUEWORK( K ) = WORK( K ) + ABS( AP( KK+K-1 ) )*XK + SKK = KK + K50 CONTINUEELSEDO 70 K = 1, NS = ZEROXK = ABS( X( K, J ) )WORK( K ) = WORK( K ) + ABS( AP( KK ) )*XKIK = KK + 1DO 60 I = K + 1, NWORK( I ) = WORK( I ) + ABS( AP( IK ) )*XKS = S + ABS( AP( IK ) )*ABS( X( I, J ) )IK = IK + 160 CONTINUEWORK( K ) = WORK( K ) + SKK = KK + ( N-K+1 )70 CONTINUEEND IFS = ZERODO 80 I = 1, NIF( WORK( I ).GT.SAFE2 ) THENS = MAX( S, ABS( WORK( N+I ) ) / WORK( I ) )ELSES = MAX( S, ( ABS( WORK( N+I ) )+SAFE1 ) /$ ( WORK( I )+SAFE1 ) )END IF80 CONTINUEBERR( J ) = S** Test stopping criterion. Continue iterating if* 1) The residual BERR(J) is larger than machine epsilon, and* 2) BERR(J) decreased by at least a factor of 2 during the* last iteration, and* 3) At most ITMAX iterations tried.*IF( BERR( J ).GT.EPS .AND. TWO*BERR( J ).LE.LSTRES .AND.$ COUNT.LE.ITMAX ) THEN** Update solution and try again.*CALL DSPTRS( UPLO, N, 1, AFP, IPIV, WORK( N+1 ), N, INFO )CALL DAXPY( N, ONE, WORK( N+1 ), 1, X( 1, J ), 1 )LSTRES = BERR( J )COUNT = COUNT + 1GO TO 20END IF** Bound error from formula** norm(X - XTRUE) / norm(X) .le. FERR =* norm( abs(inv(A))** ( abs(R) + NZ*EPS*( abs(A)*abs(X)+abs(B) ))) / norm(X)** where* norm(Z) is the magnitude of the largest component of Z* inv(A) is the inverse of A* abs(Z) is the componentwise absolute value of the matrix or* vector Z* NZ is the maximum number of nonzeros in any row of A, plus 1* EPS is machine epsilon** The i-th component of abs(R)+NZ*EPS*(abs(A)*abs(X)+abs(B))* is incremented by SAFE1 if the i-th component of* abs(A)*abs(X) + abs(B) is less than SAFE2.** Use DLACON to estimate the infinity-norm of the matrix* inv(A) * diag(W),* where W = abs(R) + NZ*EPS*( abs(A)*abs(X)+abs(B) )))*DO 90 I = 1, NIF( WORK( I ).GT.SAFE2 ) THENWORK( I ) = ABS( WORK( N+I ) ) + NZ*EPS*WORK( I )ELSEWORK( I ) = ABS( WORK( N+I ) ) + NZ*EPS*WORK( I ) + SAFE1END IF90 CONTINUE*KASE = 0100 CONTINUECALL DLACON( N, WORK( 2*N+1 ), WORK( N+1 ), IWORK, FERR( J ),$ KASE )IF( KASE.NE.0 ) THENIF( KASE.EQ.1 ) THEN** Multiply by diag(W)*inv(A').*CALL DSPTRS( UPLO, N, 1, AFP, IPIV, WORK( N+1 ), N,$ INFO )DO 110 I = 1, NWORK( N+I ) = WORK( I )*WORK( N+I )110 CONTINUEELSE IF( KASE.EQ.2 ) THEN** Multiply by inv(A)*diag(W).*DO 120 I = 1, NWORK( N+I ) = WORK( I )*WORK( N+I )120 CONTINUECALL DSPTRS( UPLO, N, 1, AFP, IPIV, WORK( N+1 ), N,$ INFO )END IFGO TO 100END IF** Normalize error.*LSTRES = ZERODO 130 I = 1, NLSTRES = MAX( LSTRES, ABS( X( I, J ) ) )130 CONTINUEIF( LSTRES.NE.ZERO )$ FERR( J ) = FERR( J ) / LSTRES*140 CONTINUE*RETURN** End of DSPRFS*ENDSUBROUTINE DSPTRD( UPLO, N, AP, D, E, TAU, INFO )** -- LAPACK routine (version 3.0) --* Univ. of Tennessee, Univ. of California Berkeley, NAG Ltd.,* Courant Institute, Argonne National Lab, and Rice University* March 31, 1993** .. Scalar Arguments ..CHARACTER UPLOINTEGER INFO, N* ..* .. Array Arguments ..DOUBLE PRECISION AP( * ), D( * ), E( * ), TAU( * )* ..** Purpose* =======** DSPTRD reduces a real symmetric matrix A stored in packed form to* 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.** AP (input/output) DOUBLE PRECISION array, dimension (N*(N+1)/2)* On entry, the upper or lower triangle of the symmetric matrix* A, packed columnwise in a linear array. The j-th column of A* is stored in the array AP as follows:* if UPLO = 'U', AP(i + (j-1)*j/2) = A(i,j) for 1<=i<=j;* if UPLO = 'L', AP(i + (j-1)*(2*n-j)/2) = A(i,j) for j<=i<=n.* 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.** 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 AP,* overwriting A(1:i-1,i+1), and tau is stored 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 AP,* overwriting A(i+2:n,i), and tau is stored in TAU(i).** =====================================================================** .. Parameters ..DOUBLE PRECISION ONE, ZERO, HALFPARAMETER ( ONE = 1.0D0, ZERO = 0.0D0,$ HALF = 1.0D0 / 2.0D0 )* ..* .. Local Scalars ..LOGICAL UPPERINTEGER I, I1, I1I1, IIDOUBLE PRECISION ALPHA, TAUI* ..* .. External Subroutines ..EXTERNAL DAXPY, DLARFG, DSPMV, DSPR2, XERBLA* ..* .. External Functions ..LOGICAL LSAMEDOUBLE PRECISION DDOTEXTERNAL LSAME, DDOT* ..* .. Executable Statements ..** Test the input parameters*INFO = 0UPPER = LSAME( UPLO, 'U' )IF( .NOT.UPPER .AND. .NOT.LSAME( UPLO, 'L' ) ) THENINFO = -1ELSE IF( N.LT.0 ) THENINFO = -2END IFIF( INFO.NE.0 ) THENCALL XERBLA( 'DSPTRD', -INFO )RETURNEND IF** Quick return if possible*IF( N.LE.0 )$ RETURN*IF( UPPER ) THEN** Reduce the upper triangle of A.* I1 is the index in AP of A(1,I+1).*I1 = N*( N-1 ) / 2 + 1DO 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, AP( I1+I-1 ), AP( I1 ), 1, TAUI )E( I ) = AP( I1+I-1 )*IF( TAUI.NE.ZERO ) THEN** Apply H(i) from both sides to A(1:i,1:i)*AP( I1+I-1 ) = ONE** Compute y := tau * A * v storing y in TAU(1:i)*CALL DSPMV( UPLO, I, TAUI, AP, AP( I1 ), 1, ZERO, TAU,$ 1 )** Compute w := y - 1/2 * tau * (y'*v) * v*ALPHA = -HALF*TAUI*DDOT( I, TAU, 1, AP( I1 ), 1 )CALL DAXPY( I, ALPHA, AP( I1 ), 1, TAU, 1 )** Apply the transformation as a rank-2 update:* A := A - v * w' - w * v'*CALL DSPR2( UPLO, I, -ONE, AP( I1 ), 1, TAU, 1, AP )*AP( I1+I-1 ) = E( I )END IFD( I+1 ) = AP( I1+I )TAU( I ) = TAUII1 = I1 - I10 CONTINUED( 1 ) = AP( 1 )ELSE** Reduce the lower triangle of A. II is the index in AP of* A(i,i) and I1I1 is the index of A(i+1,i+1).*II = 1DO 20 I = 1, N - 1I1I1 = II + N - I + 1** Generate elementary reflector H(i) = I - tau * v * v'* to annihilate A(i+2:n,i)*CALL DLARFG( N-I, AP( II+1 ), AP( II+2 ), 1, TAUI )E( I ) = AP( II+1 )*IF( TAUI.NE.ZERO ) THEN** Apply H(i) from both sides to A(i+1:n,i+1:n)*AP( II+1 ) = ONE** Compute y := tau * A * v storing y in TAU(i:n-1)*CALL DSPMV( UPLO, N-I, TAUI, AP( I1I1 ), AP( II+1 ), 1,$ ZERO, TAU( I ), 1 )** Compute w := y - 1/2 * tau * (y'*v) * v*ALPHA = -HALF*TAUI*DDOT( N-I, TAU( I ), 1, AP( II+1 ),$ 1 )CALL DAXPY( N-I, ALPHA, AP( II+1 ), 1, TAU( I ), 1 )** Apply the transformation as a rank-2 update:* A := A - v * w' - w * v'*CALL DSPR2( UPLO, N-I, -ONE, AP( II+1 ), 1, TAU( I ), 1,$ AP( I1I1 ) )*AP( II+1 ) = E( I )END IFD( I ) = AP( II )TAU( I ) = TAUIII = I1I120 CONTINUED( N ) = AP( II )END IF*RETURN** End of DSPTRD*ENDSUBROUTINE DSPTRF( UPLO, N, AP, IPIV, INFO )** -- LAPACK routine (version 3.0) --* Univ. of Tennessee, Univ. of California Berkeley, NAG Ltd.,* Courant Institute, Argonne National Lab, and Rice University* June 30, 1999** .. Scalar Arguments ..CHARACTER UPLOINTEGER INFO, N* ..* .. Array Arguments ..INTEGER IPIV( * )DOUBLE PRECISION AP( * )* ..** Purpose* =======** DSPTRF computes the factorization of a real symmetric matrix A stored* in packed format using the Bunch-Kaufman diagonal pivoting method:** A = U*D*U**T or A = L*D*L**T** where U (or L) is a product of permutation and unit upper (lower)* triangular matrices, and D is symmetric and block diagonal with* 1-by-1 and 2-by-2 diagonal blocks.** 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.** AP (input/output) DOUBLE PRECISION array, dimension (N*(N+1)/2)* On entry, the upper or lower triangle of the symmetric matrix* A, packed columnwise in a linear array. The j-th column of A* is stored in the array AP as follows:* if UPLO = 'U', AP(i + (j-1)*j/2) = A(i,j) for 1<=i<=j;* if UPLO = 'L', AP(i + (j-1)*(2n-j)/2) = A(i,j) for j<=i<=n.** On exit, the block diagonal matrix D and the multipliers used* to obtain the factor U or L, stored as a packed triangular* matrix overwriting A (see below for further details).** 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 = -i, the i-th argument had an illegal value* > 0: if INFO = i, D(i,i) 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* ===============** 5-96 - Based on modifications by J. Lewis, Boeing Computer Services* Company** 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, ONEPARAMETER ( ZERO = 0.0D+0, ONE = 1.0D+0 )DOUBLE PRECISION EIGHT, SEVTENPARAMETER ( EIGHT = 8.0D+0, SEVTEN = 17.0D+0 )* ..* .. Local Scalars ..LOGICAL UPPERINTEGER I, IMAX, J, JMAX, K, KC, KK, KNC, KP, KPC,$ KSTEP, KX, NPPDOUBLE PRECISION ABSAKK, ALPHA, COLMAX, D11, D12, D21, D22, R1,$ ROWMAX, T, WK, WKM1, WKP1* ..* .. External Functions ..LOGICAL LSAMEINTEGER IDAMAXEXTERNAL LSAME, IDAMAX* ..* .. External Subroutines ..EXTERNAL DSCAL, DSPR, DSWAP, XERBLA* ..* .. Intrinsic Functions ..INTRINSIC ABS, MAX, SQRT* ..* .. Executable Statements ..** Test the input parameters.*INFO = 0UPPER = LSAME( UPLO, 'U' )IF( .NOT.UPPER .AND. .NOT.LSAME( UPLO, 'L' ) ) THENINFO = -1ELSE IF( N.LT.0 ) THENINFO = -2END IFIF( INFO.NE.0 ) THENCALL XERBLA( 'DSPTRF', -INFO )RETURNEND 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 = NKC = ( N-1 )*N / 2 + 110 CONTINUEKNC = KC** If K < 1, exit from loop*IF( K.LT.1 )$ GO TO 110KSTEP = 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( AP( KC+K-1 ) )** IMAX is the row-index of the largest off-diagonal element in* column K, and COLMAX is its absolute value*IF( K.GT.1 ) THENIMAX = IDAMAX( K-1, AP( KC ), 1 )COLMAX = ABS( AP( KC+IMAX-1 ) )ELSECOLMAX = ZEROEND IF*IF( MAX( ABSAKK, COLMAX ).EQ.ZERO ) THEN** Column K is zero: set INFO and continue*IF( INFO.EQ.0 )$ INFO = KKP = KELSEIF( ABSAKK.GE.ALPHA*COLMAX ) THEN** no interchange, use 1-by-1 pivot block*KP = KELSE** JMAX is the column-index of the largest off-diagonal* element in row IMAX, and ROWMAX is its absolute value*ROWMAX = ZEROJMAX = IMAXKX = IMAX*( IMAX+1 ) / 2 + IMAXDO 20 J = IMAX + 1, KIF( ABS( AP( KX ) ).GT.ROWMAX ) THENROWMAX = ABS( AP( KX ) )JMAX = JEND IFKX = KX + J20 CONTINUEKPC = ( IMAX-1 )*IMAX / 2 + 1IF( IMAX.GT.1 ) THENJMAX = IDAMAX( IMAX-1, AP( KPC ), 1 )ROWMAX = MAX( ROWMAX, ABS( AP( KPC+JMAX-1 ) ) )END IF*IF( ABSAKK.GE.ALPHA*COLMAX*( COLMAX / ROWMAX ) ) THEN** no interchange, use 1-by-1 pivot block*KP = KELSE IF( ABS( AP( KPC+IMAX-1 ) ).GE.ALPHA*ROWMAX ) THEN** interchange rows and columns K and IMAX, use 1-by-1* pivot block*KP = IMAXELSE** interchange rows and columns K-1 and IMAX, use 2-by-2* pivot block*KP = IMAXKSTEP = 2END IFEND IF*KK = K - KSTEP + 1IF( KSTEP.EQ.2 )$ KNC = KNC - K + 1IF( KP.NE.KK ) THEN** Interchange rows and columns KK and KP in the leading* submatrix A(1:k,1:k)*CALL DSWAP( KP-1, AP( KNC ), 1, AP( KPC ), 1 )KX = KPC + KP - 1DO 30 J = KP + 1, KK - 1KX = KX + J - 1T = AP( KNC+J-1 )AP( KNC+J-1 ) = AP( KX )AP( KX ) = T30 CONTINUET = AP( KNC+KK-1 )AP( KNC+KK-1 ) = AP( KPC+KP-1 )AP( KPC+KP-1 ) = TIF( KSTEP.EQ.2 ) THENT = AP( KC+K-2 )AP( KC+K-2 ) = AP( KC+KP-1 )AP( KC+KP-1 ) = TEND IFEND 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 / AP( KC+K-1 )CALL DSPR( UPLO, K-1, -R1, AP( KC ), 1, AP )** Store U(k) in column k*CALL DSCAL( K-1, R1, AP( KC ), 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) )'*IF( K.GT.2 ) THEN*D12 = AP( K-1+( K-1 )*K / 2 )D22 = AP( K-1+( K-2 )*( K-1 ) / 2 ) / D12D11 = AP( K+( K-1 )*K / 2 ) / D12T = ONE / ( D11*D22-ONE )D12 = T / D12*DO 50 J = K - 2, 1, -1WKM1 = D12*( D11*AP( J+( K-2 )*( K-1 ) / 2 )-$ AP( J+( K-1 )*K / 2 ) )WK = D12*( D22*AP( J+( K-1 )*K / 2 )-$ AP( J+( K-2 )*( K-1 ) / 2 ) )DO 40 I = J, 1, -1AP( I+( J-1 )*J / 2 ) = AP( I+( J-1 )*J / 2 ) -$ AP( I+( K-1 )*K / 2 )*WK -$ AP( I+( K-2 )*( K-1 ) / 2 )*WKM140 CONTINUEAP( J+( K-1 )*K / 2 ) = WKAP( J+( K-2 )*( K-1 ) / 2 ) = WKM150 CONTINUE*END IF*END IFEND IF** Store details of the interchanges in IPIV*IF( KSTEP.EQ.1 ) THENIPIV( K ) = KPELSEIPIV( K ) = -KPIPIV( K-1 ) = -KPEND IF** Decrease K and return to the start of the main loop*K = K - KSTEPKC = KNC - KGO 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 = 1KC = 1NPP = N*( N+1 ) / 260 CONTINUEKNC = KC** If K > N, exit from loop*IF( K.GT.N )$ GO TO 110KSTEP = 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( AP( KC ) )** IMAX is the row-index of the largest off-diagonal element in* column K, and COLMAX is its absolute value*IF( K.LT.N ) THENIMAX = K + IDAMAX( N-K, AP( KC+1 ), 1 )COLMAX = ABS( AP( KC+IMAX-K ) )ELSECOLMAX = ZEROEND IF*IF( MAX( ABSAKK, COLMAX ).EQ.ZERO ) THEN** Column K is zero: set INFO and continue*IF( INFO.EQ.0 )$ INFO = KKP = KELSEIF( ABSAKK.GE.ALPHA*COLMAX ) THEN** no interchange, use 1-by-1 pivot block*KP = KELSE** JMAX is the column-index of the largest off-diagonal* element in row IMAX, and ROWMAX is its absolute value*ROWMAX = ZEROKX = KC + IMAX - KDO 70 J = K, IMAX - 1IF( ABS( AP( KX ) ).GT.ROWMAX ) THENROWMAX = ABS( AP( KX ) )JMAX = JEND IFKX = KX + N - J70 CONTINUEKPC = NPP - ( N-IMAX+1 )*( N-IMAX+2 ) / 2 + 1IF( IMAX.LT.N ) THENJMAX = IMAX + IDAMAX( N-IMAX, AP( KPC+1 ), 1 )ROWMAX = MAX( ROWMAX, ABS( AP( KPC+JMAX-IMAX ) ) )END IF*IF( ABSAKK.GE.ALPHA*COLMAX*( COLMAX / ROWMAX ) ) THEN** no interchange, use 1-by-1 pivot block*KP = KELSE IF( ABS( AP( KPC ) ).GE.ALPHA*ROWMAX ) THEN** interchange rows and columns K and IMAX, use 1-by-1* pivot block*KP = IMAXELSE** interchange rows and columns K+1 and IMAX, use 2-by-2* pivot block*KP = IMAXKSTEP = 2END IFEND IF*KK = K + KSTEP - 1IF( KSTEP.EQ.2 )$ KNC = KNC + N - K + 1IF( 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, AP( KNC+KP-KK+1 ), 1, AP( KPC+1 ),$ 1 )KX = KNC + KP - KKDO 80 J = KK + 1, KP - 1KX = KX + N - J + 1T = AP( KNC+J-KK )AP( KNC+J-KK ) = AP( KX )AP( KX ) = T80 CONTINUET = AP( KNC )AP( KNC ) = AP( KPC )AP( KPC ) = TIF( KSTEP.EQ.2 ) THENT = AP( KC+1 )AP( KC+1 ) = AP( KC+KP-K )AP( KC+KP-K ) = TEND IFEND 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 / AP( KC )CALL DSPR( UPLO, N-K, -R1, AP( KC+1 ), 1,$ AP( KC+N-K+1 ) )** Store L(k) in column K*CALL DSCAL( N-K, R1, AP( KC+1 ), 1 )END IFELSE** 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) )'*D21 = AP( K+1+( K-1 )*( 2*N-K ) / 2 )D11 = AP( K+1+K*( 2*N-K-1 ) / 2 ) / D21D22 = AP( K+( K-1 )*( 2*N-K ) / 2 ) / D21T = ONE / ( D11*D22-ONE )D21 = T / D21*DO 100 J = K + 2, NWK = D21*( D11*AP( J+( K-1 )*( 2*N-K ) / 2 )-$ AP( J+K*( 2*N-K-1 ) / 2 ) )WKP1 = D21*( D22*AP( J+K*( 2*N-K-1 ) / 2 )-$ AP( J+( K-1 )*( 2*N-K ) / 2 ) )*DO 90 I = J, NAP( I+( J-1 )*( 2*N-J ) / 2 ) = AP( I+( J-1 )*$ ( 2*N-J ) / 2 ) - AP( I+( K-1 )*( 2*N-K ) /$ 2 )*WK - AP( I+K*( 2*N-K-1 ) / 2 )*WKP190 CONTINUE*AP( J+( K-1 )*( 2*N-K ) / 2 ) = WKAP( J+K*( 2*N-K-1 ) / 2 ) = WKP1*100 CONTINUEEND IFEND IFEND IF** Store details of the interchanges in IPIV*IF( KSTEP.EQ.1 ) THENIPIV( K ) = KPELSEIPIV( K ) = -KPIPIV( K+1 ) = -KPEND IF** Increase K and return to the start of the main loop*K = K + KSTEPKC = KNC + N - K + 2GO TO 60*END IF*110 CONTINUERETURN** End of DSPTRF*ENDSUBROUTINE DSPTRI( UPLO, N, AP, IPIV, WORK, INFO )** -- LAPACK routine (version 3.0) --* Univ. of Tennessee, Univ. of California Berkeley, NAG Ltd.,* Courant Institute, Argonne National Lab, and Rice University* March 31, 1993** .. Scalar Arguments ..CHARACTER UPLOINTEGER INFO, N* ..* .. Array Arguments ..INTEGER IPIV( * )DOUBLE PRECISION AP( * ), WORK( * )* ..** Purpose* =======** DSPTRI computes the inverse of a real symmetric indefinite matrix* A in packed storage using the factorization A = U*D*U**T or* A = L*D*L**T computed by DSPTRF.** 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**T;* = 'L': Lower triangular, form is A = L*D*L**T.** N (input) INTEGER* The order of the matrix A. N >= 0.** AP (input/output) DOUBLE PRECISION array, dimension (N*(N+1)/2)* On entry, the block diagonal matrix D and the multipliers* used to obtain the factor U or L as computed by DSPTRF,* stored as a packed triangular matrix.** On exit, if INFO = 0, the (symmetric) inverse of the original* matrix, stored as a packed triangular matrix. The j-th column* of inv(A) is stored in the array AP as follows:* if UPLO = 'U', AP(i + (j-1)*j/2) = inv(A)(i,j) for 1<=i<=j;* if UPLO = 'L',* AP(i + (j-1)*(2n-j)/2) = inv(A)(i,j) for j<=i<=n.** IPIV (input) INTEGER array, dimension (N)* Details of the interchanges and the block structure of D* as determined by DSPTRF.** WORK (workspace) DOUBLE PRECISION array, dimension (N)** INFO (output) INTEGER* = 0: successful exit* < 0: if INFO = -i, the i-th argument had an illegal value* > 0: if INFO = i, D(i,i) = 0; the matrix is singular and its* inverse could not be computed.** =====================================================================** .. Parameters ..DOUBLE PRECISION ONE, ZEROPARAMETER ( ONE = 1.0D+0, ZERO = 0.0D+0 )* ..* .. Local Scalars ..LOGICAL UPPERINTEGER J, K, KC, KCNEXT, KP, KPC, KSTEP, KX, NPPDOUBLE PRECISION AK, AKKP1, AKP1, D, T, TEMP* ..* .. External Functions ..LOGICAL LSAMEDOUBLE PRECISION DDOTEXTERNAL LSAME, DDOT* ..* .. External Subroutines ..EXTERNAL DCOPY, DSPMV, DSWAP, XERBLA* ..* .. Intrinsic Functions ..INTRINSIC ABS* ..* .. Executable Statements ..** Test the input parameters.*INFO = 0UPPER = LSAME( UPLO, 'U' )IF( .NOT.UPPER .AND. .NOT.LSAME( UPLO, 'L' ) ) THENINFO = -1ELSE IF( N.LT.0 ) THENINFO = -2END IFIF( INFO.NE.0 ) THENCALL XERBLA( 'DSPTRI', -INFO )RETURNEND 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*KP = N*( N+1 ) / 2DO 10 INFO = N, 1, -1IF( IPIV( INFO ).GT.0 .AND. AP( KP ).EQ.ZERO )$ RETURNKP = KP - INFO10 CONTINUEELSE** Lower triangular storage: examine D from top to bottom.*KP = 1DO 20 INFO = 1, NIF( IPIV( INFO ).GT.0 .AND. AP( KP ).EQ.ZERO )$ RETURNKP = KP + N - INFO + 120 CONTINUEEND IFINFO = 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 = 1KC = 130 CONTINUE** If K > N, exit from loop.*IF( K.GT.N )$ GO TO 50*KCNEXT = KC + KIF( IPIV( K ).GT.0 ) THEN** 1 x 1 diagonal block** Invert the diagonal block.*AP( KC+K-1 ) = ONE / AP( KC+K-1 )** Compute column K of the inverse.*IF( K.GT.1 ) THENCALL DCOPY( K-1, AP( KC ), 1, WORK, 1 )CALL DSPMV( UPLO, K-1, -ONE, AP, WORK, 1, ZERO, AP( KC ),$ 1 )AP( KC+K-1 ) = AP( KC+K-1 ) -$ DDOT( K-1, WORK, 1, AP( KC ), 1 )END IFKSTEP = 1ELSE** 2 x 2 diagonal block** Invert the diagonal block.*T = ABS( AP( KCNEXT+K-1 ) )AK = AP( KC+K-1 ) / TAKP1 = AP( KCNEXT+K ) / TAKKP1 = AP( KCNEXT+K-1 ) / TD = T*( AK*AKP1-ONE )AP( KC+K-1 ) = AKP1 / DAP( KCNEXT+K ) = AK / DAP( KCNEXT+K-1 ) = -AKKP1 / D** Compute columns K and K+1 of the inverse.*IF( K.GT.1 ) THENCALL DCOPY( K-1, AP( KC ), 1, WORK, 1 )CALL DSPMV( UPLO, K-1, -ONE, AP, WORK, 1, ZERO, AP( KC ),$ 1 )AP( KC+K-1 ) = AP( KC+K-1 ) -$ DDOT( K-1, WORK, 1, AP( KC ), 1 )AP( KCNEXT+K-1 ) = AP( KCNEXT+K-1 ) -$ DDOT( K-1, AP( KC ), 1, AP( KCNEXT ),$ 1 )CALL DCOPY( K-1, AP( KCNEXT ), 1, WORK, 1 )CALL DSPMV( UPLO, K-1, -ONE, AP, WORK, 1, ZERO,$ AP( KCNEXT ), 1 )AP( KCNEXT+K ) = AP( KCNEXT+K ) -$ DDOT( K-1, WORK, 1, AP( KCNEXT ), 1 )END IFKSTEP = 2KCNEXT = KCNEXT + K + 1END 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)*KPC = ( KP-1 )*KP / 2 + 1CALL DSWAP( KP-1, AP( KC ), 1, AP( KPC ), 1 )KX = KPC + KP - 1DO 40 J = KP + 1, K - 1KX = KX + J - 1TEMP = AP( KC+J-1 )AP( KC+J-1 ) = AP( KX )AP( KX ) = TEMP40 CONTINUETEMP = AP( KC+K-1 )AP( KC+K-1 ) = AP( KPC+KP-1 )AP( KPC+KP-1 ) = TEMPIF( KSTEP.EQ.2 ) THENTEMP = AP( KC+K+K-1 )AP( KC+K+K-1 ) = AP( KC+K+KP-1 )AP( KC+K+KP-1 ) = TEMPEND IFEND IF*K = K + KSTEPKC = KCNEXTGO TO 3050 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.*NPP = N*( N+1 ) / 2K = NKC = NPP60 CONTINUE** If K < 1, exit from loop.*IF( K.LT.1 )$ GO TO 80*KCNEXT = KC - ( N-K+2 )IF( IPIV( K ).GT.0 ) THEN** 1 x 1 diagonal block** Invert the diagonal block.*AP( KC ) = ONE / AP( KC )** Compute column K of the inverse.*IF( K.LT.N ) THENCALL DCOPY( N-K, AP( KC+1 ), 1, WORK, 1 )CALL DSPMV( UPLO, N-K, -ONE, AP( KC+N-K+1 ), WORK, 1,$ ZERO, AP( KC+1 ), 1 )AP( KC ) = AP( KC ) - DDOT( N-K, WORK, 1, AP( KC+1 ), 1 )END IFKSTEP = 1ELSE** 2 x 2 diagonal block** Invert the diagonal block.*T = ABS( AP( KCNEXT+1 ) )AK = AP( KCNEXT ) / TAKP1 = AP( KC ) / TAKKP1 = AP( KCNEXT+1 ) / TD = T*( AK*AKP1-ONE )AP( KCNEXT ) = AKP1 / DAP( KC ) = AK / DAP( KCNEXT+1 ) = -AKKP1 / D** Compute columns K-1 and K of the inverse.*IF( K.LT.N ) THENCALL DCOPY( N-K, AP( KC+1 ), 1, WORK, 1 )CALL DSPMV( UPLO, N-K, -ONE, AP( KC+( N-K+1 ) ), WORK, 1,$ ZERO, AP( KC+1 ), 1 )AP( KC ) = AP( KC ) - DDOT( N-K, WORK, 1, AP( KC+1 ), 1 )AP( KCNEXT+1 ) = AP( KCNEXT+1 ) -$ DDOT( N-K, AP( KC+1 ), 1,$ AP( KCNEXT+2 ), 1 )CALL DCOPY( N-K, AP( KCNEXT+2 ), 1, WORK, 1 )CALL DSPMV( UPLO, N-K, -ONE, AP( KC+( N-K+1 ) ), WORK, 1,$ ZERO, AP( KCNEXT+2 ), 1 )AP( KCNEXT ) = AP( KCNEXT ) -$ DDOT( N-K, WORK, 1, AP( KCNEXT+2 ), 1 )END IFKSTEP = 2KCNEXT = KCNEXT - ( N-K+3 )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)*KPC = NPP - ( N-KP+1 )*( N-KP+2 ) / 2 + 1IF( KP.LT.N )$ CALL DSWAP( N-KP, AP( KC+KP-K+1 ), 1, AP( KPC+1 ), 1 )KX = KC + KP - KDO 70 J = K + 1, KP - 1KX = KX + N - J + 1TEMP = AP( KC+J-K )AP( KC+J-K ) = AP( KX )AP( KX ) = TEMP70 CONTINUETEMP = AP( KC )AP( KC ) = AP( KPC )AP( KPC ) = TEMPIF( KSTEP.EQ.2 ) THENTEMP = AP( KC-N+K-1 )AP( KC-N+K-1 ) = AP( KC-N+KP-1 )AP( KC-N+KP-1 ) = TEMPEND IFEND IF*K = K - KSTEPKC = KCNEXTGO TO 6080 CONTINUEEND IF*RETURN** End of DSPTRI*ENDSUBROUTINE DSPTRS( UPLO, N, NRHS, AP, IPIV, B, LDB, INFO )** -- LAPACK routine (version 3.0) --* Univ. of Tennessee, Univ. of California Berkeley, NAG Ltd.,* Courant Institute, Argonne National Lab, and Rice University* March 31, 1993** .. Scalar Arguments ..CHARACTER UPLOINTEGER INFO, LDB, N, NRHS* ..* .. Array Arguments ..INTEGER IPIV( * )DOUBLE PRECISION AP( * ), B( LDB, * )* ..** Purpose* =======** DSPTRS solves a system of linear equations A*X = B with a real* symmetric matrix A stored in packed format using the factorization* A = U*D*U**T or A = L*D*L**T computed by DSPTRF.** 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**T;* = 'L': Lower triangular, form is A = L*D*L**T.** 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.** AP (input) DOUBLE PRECISION array, dimension (N*(N+1)/2)* The block diagonal matrix D and the multipliers used to* obtain the factor U or L as computed by DSPTRF, stored as a* packed triangular matrix.** IPIV (input) INTEGER array, dimension (N)* Details of the interchanges and the block structure of D* as determined by DSPTRF.** 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 ONEPARAMETER ( ONE = 1.0D+0 )* ..* .. Local Scalars ..LOGICAL UPPERINTEGER J, K, KC, KPDOUBLE PRECISION AK, AKM1, AKM1K, BK, BKM1, DENOM* ..* .. External Functions ..LOGICAL LSAMEEXTERNAL LSAME* ..* .. External Subroutines ..EXTERNAL DGEMV, DGER, DSCAL, DSWAP, XERBLA* ..* .. Intrinsic Functions ..INTRINSIC MAX* ..* .. Executable Statements ..*INFO = 0UPPER = LSAME( UPLO, 'U' )IF( .NOT.UPPER .AND. .NOT.LSAME( UPLO, 'L' ) ) THENINFO = -1ELSE IF( N.LT.0 ) THENINFO = -2ELSE IF( NRHS.LT.0 ) THENINFO = -3ELSE IF( LDB.LT.MAX( 1, N ) ) THENINFO = -7END IFIF( INFO.NE.0 ) THENCALL XERBLA( 'DSPTRS', -INFO )RETURNEND IF** Quick return if possible*IF( N.EQ.0 .OR. NRHS.EQ.0 )$ RETURN*IF( UPPER ) THEN** Solve A*X = B, where A = U*D*U'.** First solve U*D*X = B, overwriting B with X.** K is the main loop index, decreasing from N to 1 in steps of* 1 or 2, depending on the size of the diagonal blocks.*K = NKC = N*( N+1 ) / 2 + 110 CONTINUE** If K < 1, exit from loop.*IF( K.LT.1 )$ GO TO 30*KC = KC - KIF( IPIV( K ).GT.0 ) THEN** 1 x 1 diagonal block** Interchange rows K and IPIV(K).*KP = IPIV( K )IF( KP.NE.K )$ CALL DSWAP( NRHS, B( K, 1 ), LDB, B( KP, 1 ), LDB )** Multiply by inv(U(K)), where U(K) is the transformation* stored in column K of A.*CALL DGER( K-1, NRHS, -ONE, AP( KC ), 1, B( K, 1 ), LDB,$ B( 1, 1 ), LDB )** Multiply by the inverse of the diagonal block.*CALL DSCAL( NRHS, ONE / AP( KC+K-1 ), B( K, 1 ), LDB )K = K - 1ELSE** 2 x 2 diagonal block** Interchange rows K-1 and -IPIV(K).*KP = -IPIV( K )IF( KP.NE.K-1 )$ CALL DSWAP( NRHS, B( K-1, 1 ), LDB, B( KP, 1 ), LDB )** Multiply by inv(U(K)), where U(K) is the transformation* stored in columns K-1 and K of A.*CALL DGER( K-2, NRHS, -ONE, AP( KC ), 1, B( K, 1 ), LDB,$ B( 1, 1 ), LDB )CALL DGER( K-2, NRHS, -ONE, AP( KC-( K-1 ) ), 1,$ B( K-1, 1 ), LDB, B( 1, 1 ), LDB )** Multiply by the inverse of the diagonal block.*AKM1K = AP( KC+K-2 )AKM1 = AP( KC-1 ) / AKM1KAK = AP( KC+K-1 ) / AKM1KDENOM = AKM1*AK - ONEDO 20 J = 1, NRHSBKM1 = B( K-1, J ) / AKM1KBK = B( K, J ) / AKM1KB( K-1, J ) = ( AK*BKM1-BK ) / DENOMB( K, J ) = ( AKM1*BK-BKM1 ) / DENOM20 CONTINUEKC = KC - K + 1K = K - 2END IF*GO TO 1030 CONTINUE** Next solve U'*X = B, overwriting B with X.** 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 = 1KC = 140 CONTINUE** If K > N, exit from loop.*IF( K.GT.N )$ GO TO 50*IF( IPIV( K ).GT.0 ) THEN** 1 x 1 diagonal block** Multiply by inv(U'(K)), where U(K) is the transformation* stored in column K of A.*CALL DGEMV( 'Transpose', K-1, NRHS, -ONE, B, LDB, AP( KC ),$ 1, ONE, B( K, 1 ), LDB )** Interchange rows K and IPIV(K).*KP = IPIV( K )IF( KP.NE.K )$ CALL DSWAP( NRHS, B( K, 1 ), LDB, B( KP, 1 ), LDB )KC = KC + KK = K + 1ELSE** 2 x 2 diagonal block** Multiply by inv(U'(K+1)), where U(K+1) is the transformation* stored in columns K and K+1 of A.*CALL DGEMV( 'Transpose', K-1, NRHS, -ONE, B, LDB, AP( KC ),$ 1, ONE, B( K, 1 ), LDB )CALL DGEMV( 'Transpose', K-1, NRHS, -ONE, B, LDB,$ AP( KC+K ), 1, ONE, B( K+1, 1 ), LDB )** Interchange rows K and -IPIV(K).*KP = -IPIV( K )IF( KP.NE.K )$ CALL DSWAP( NRHS, B( K, 1 ), LDB, B( KP, 1 ), LDB )KC = KC + 2*K + 1K = K + 2END IF*GO TO 4050 CONTINUE*ELSE** Solve A*X = B, where A = L*D*L'.** First solve L*D*X = B, overwriting B with X.** 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 = 1KC = 160 CONTINUE** If K > N, exit from loop.*IF( K.GT.N )$ GO TO 80*IF( IPIV( K ).GT.0 ) THEN** 1 x 1 diagonal block** Interchange rows K and IPIV(K).*KP = IPIV( K )IF( KP.NE.K )$ CALL DSWAP( NRHS, B( K, 1 ), LDB, B( KP, 1 ), LDB )** Multiply by inv(L(K)), where L(K) is the transformation* stored in column K of A.*IF( K.LT.N )$ CALL DGER( N-K, NRHS, -ONE, AP( KC+1 ), 1, B( K, 1 ),$ LDB, B( K+1, 1 ), LDB )** Multiply by the inverse of the diagonal block.*CALL DSCAL( NRHS, ONE / AP( KC ), B( K, 1 ), LDB )KC = KC + N - K + 1K = K + 1ELSE** 2 x 2 diagonal block** Interchange rows K+1 and -IPIV(K).*KP = -IPIV( K )IF( KP.NE.K+1 )$ CALL DSWAP( NRHS, B( K+1, 1 ), LDB, B( KP, 1 ), LDB )** Multiply by inv(L(K)), where L(K) is the transformation* stored in columns K and K+1 of A.*IF( K.LT.N-1 ) THENCALL DGER( N-K-1, NRHS, -ONE, AP( KC+2 ), 1, B( K, 1 ),$ LDB, B( K+2, 1 ), LDB )CALL DGER( N-K-1, NRHS, -ONE, AP( KC+N-K+2 ), 1,$ B( K+1, 1 ), LDB, B( K+2, 1 ), LDB )END IF** Multiply by the inverse of the diagonal block.*AKM1K = AP( KC+1 )AKM1 = AP( KC ) / AKM1KAK = AP( KC+N-K+1 ) / AKM1KDENOM = AKM1*AK - ONEDO 70 J = 1, NRHSBKM1 = B( K, J ) / AKM1KBK = B( K+1, J ) / AKM1KB( K, J ) = ( AK*BKM1-BK ) / DENOMB( K+1, J ) = ( AKM1*BK-BKM1 ) / DENOM70 CONTINUEKC = KC + 2*( N-K ) + 1K = K + 2END IF*GO TO 6080 CONTINUE** Next solve L'*X = B, overwriting B with X.** K is the main loop index, decreasing from N to 1 in steps of* 1 or 2, depending on the size of the diagonal blocks.*K = NKC = N*( N+1 ) / 2 + 190 CONTINUE** If K < 1, exit from loop.*IF( K.LT.1 )$ GO TO 100*KC = KC - ( N-K+1 )IF( IPIV( K ).GT.0 ) THEN** 1 x 1 diagonal block** Multiply by inv(L'(K)), where L(K) is the transformation* stored in column K of A.*IF( K.LT.N )$ CALL DGEMV( 'Transpose', N-K, NRHS, -ONE, B( K+1, 1 ),$ LDB, AP( KC+1 ), 1, ONE, B( K, 1 ), LDB )** Interchange rows K and IPIV(K).*KP = IPIV( K )IF( KP.NE.K )$ CALL DSWAP( NRHS, B( K, 1 ), LDB, B( KP, 1 ), LDB )K = K - 1ELSE** 2 x 2 diagonal block** Multiply by inv(L'(K-1)), where L(K-1) is the transformation* stored in columns K-1 and K of A.*IF( K.LT.N ) THENCALL DGEMV( 'Transpose', N-K, NRHS, -ONE, B( K+1, 1 ),$ LDB, AP( KC+1 ), 1, ONE, B( K, 1 ), LDB )CALL DGEMV( 'Transpose', N-K, NRHS, -ONE, B( K+1, 1 ),$ LDB, AP( KC-( N-K ) ), 1, ONE, B( K-1, 1 ),$ LDB )END IF** Interchange rows K and -IPIV(K).*KP = -IPIV( K )IF( KP.NE.K )$ CALL DSWAP( NRHS, B( K, 1 ), LDB, B( KP, 1 ), LDB )KC = KC - ( N-K+2 )K = K - 2END IF*GO TO 90100 CONTINUEEND IF*RETURN** End of DSPTRS*ENDSUBROUTINE DSTEBZ( RANGE, ORDER, N, VL, VU, IL, IU, ABSTOL, D, E,$ M, NSPLIT, W, IBLOCK, ISPLIT, WORK, IWORK,$ INFO )** -- LAPACK routine (version 3.0) --* Univ. of Tennessee, Univ. of California Berkeley, NAG Ltd.,* Courant Institute, Argonne National Lab, and Rice University* June 30, 1999** .. Scalar Arguments ..CHARACTER ORDER, RANGEINTEGER IL, INFO, IU, M, N, NSPLITDOUBLE 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.** To avoid overflow, the matrix must be scaled so that its* largest element 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.** 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 order of the tridiagonal matrix T. N >= 0.** VL (input) DOUBLE PRECISION* VU (input) DOUBLE PRECISION* If RANGE='V', the lower and upper bounds of the interval to* be searched for eigenvalues. Eigenvalues less than or equal* to VL, or greater than VU, will not be returned. VL < VU.* Not referenced if RANGE = 'A' or 'I'.** IL (input) INTEGER* IU (input) INTEGER* If RANGE='I', the indices (in ascending order) of the* smallest and largest eigenvalues to be returned.* 1 <= IL <= IU <= N, if N > 0; IL = 1 and IU = 0 if N = 0.* 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.** Eigenvalues will be computed most accurately when ABSTOL is* set to twice the underflow threshold 2*DLAMCH('S'), not zero.** D (input) DOUBLE PRECISION array, dimension (N)* The n diagonal elements of the tridiagonal matrix T.** E (input) DOUBLE PRECISION array, dimension (N-1)* The (n-1) off-diagonal elements of the tridiagonal matrix T.** 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, if INFO = 0, IBLOCK(i) specifies to which* block (from 1 to the number of blocks) the eigenvalue W(i)* belongs. (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, HALFPARAMETER ( ZERO = 0.0D0, ONE = 1.0D0, TWO = 2.0D0,$ HALF = 1.0D0 / TWO )DOUBLE PRECISION FUDGE, RELFACPARAMETER ( FUDGE = 2.0D0, RELFAC = 2.0D0 )* ..* .. Local Scalars ..LOGICAL NCNVRG, TOOFEWINTEGER IB, IBEGIN, IDISCL, IDISCU, IE, IEND, IINFO,$ IM, IN, IOFF, IORDER, IOUT, IRANGE, ITMAX,$ ITMP1, IW, IWOFF, J, JB, JDISC, JE, NB, NWL,$ NWUDOUBLE 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 LSAMEINTEGER ILAENVDOUBLE PRECISION DLAMCHEXTERNAL 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' ) ) THENIRANGE = 1ELSE IF( LSAME( RANGE, 'V' ) ) THENIRANGE = 2ELSE IF( LSAME( RANGE, 'I' ) ) THENIRANGE = 3ELSEIRANGE = 0END IF** Decode ORDER*IF( LSAME( ORDER, 'B' ) ) THENIORDER = 2ELSE IF( LSAME( ORDER, 'E' ) ) THENIORDER = 1ELSEIORDER = 0END IF** Check for Errors*IF( IRANGE.LE.0 ) THENINFO = -1ELSE IF( IORDER.LE.0 ) THENINFO = -2ELSE IF( N.LT.0 ) THENINFO = -3ELSE IF( IRANGE.EQ.2 ) THENIF( VL.GE.VU )$ INFO = -5ELSE IF( IRANGE.EQ.3 .AND. ( IL.LT.1 .OR. IL.GT.MAX( 1, N ) ) )$ THENINFO = -6ELSE IF( IRANGE.EQ.3 .AND. ( IU.LT.MIN( N, IL ) .OR. IU.GT.N ) )$ THENINFO = -7END IF*IF( INFO.NE.0 ) THENCALL XERBLA( 'DSTEBZ', -INFO )RETURNEND IF** Initialize error flags*INFO = 0NCNVRG = .FALSE.TOOFEW = .FALSE.** Quick return if possible*M = 0IF( 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*RELFACNB = ILAENV( 1, 'DSTEBZ', ' ', N, -1, -1, -1 )IF( NB.LE.1 )$ NB = 0** Special Case when N=1*IF( N.EQ.1 ) THENNSPLIT = 1ISPLIT( 1 ) = 1IF( IRANGE.EQ.2 .AND. ( VL.GE.D( 1 ) .OR. VU.LT.D( 1 ) ) ) THENM = 0ELSEW( 1 ) = D( 1 )IBLOCK( 1 ) = 1M = 1END IFRETURNEND IF** Compute Splitting Points*NSPLIT = 1WORK( N ) = ZEROPIVMIN = ONE**DIR$ NOVECTORDO 10 J = 2, NTMP1 = E( J-1 )**2IF( ABS( D( J )*D( J-1 ) )*ULP**2+SAFEMN.GT.TMP1 ) THENISPLIT( NSPLIT ) = J - 1NSPLIT = NSPLIT + 1WORK( J-1 ) = ZEROELSEWORK( J-1 ) = TMP1PIVMIN = MAX( PIVMIN, TMP1 )END IF10 CONTINUEISPLIT( NSPLIT ) = NPIVMIN = 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 - 1TMP2 = SQRT( WORK( J ) )GU = MAX( GU, D( J )+TMP1+TMP2 )GL = MIN( GL, D( J )-TMP1-TMP2 )TMP1 = TMP220 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*PIVMINGU = GU + FUDGE*TNORM*ULP*N + FUDGE*PIVMIN** Compute Iteration parameters*ITMAX = INT( ( LOG( TNORM+PIVMIN )-LOG( PIVMIN ) ) /$ LOG( TWO ) ) + 2IF( ABSTOL.LE.ZERO ) THENATOLI = ULP*TNORMELSEATOLI = ABSTOLEND IF*WORK( N+1 ) = GLWORK( N+2 ) = GLWORK( N+3 ) = GUWORK( N+4 ) = GUWORK( N+5 ) = GLWORK( N+6 ) = GUIWORK( 1 ) = -1IWORK( 2 ) = -1IWORK( 3 ) = N + 1IWORK( 4 ) = N + 1IWORK( 5 ) = IL - 1IWORK( 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 ) THENWL = WORK( N+1 )WLU = WORK( N+3 )NWL = IWORK( 1 )WU = WORK( N+4 )WUL = WORK( N+2 )NWU = IWORK( 4 )ELSEWL = 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 ) THENINFO = 4RETURNEND IFELSE** 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 - 1TNORM = MAX( TNORM, ABS( D( J ) )+ABS( E( J-1 ) )+$ ABS( E( J ) ) )30 CONTINUE*IF( ABSTOL.LE.ZERO ) THENATOLI = ULP*TNORMELSEATOLI = ABSTOLEND IF*IF( IRANGE.EQ.2 ) THENWL = VLWU = VUELSEWL = ZEROWU = ZEROEND IFEND 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 = 0IEND = 0INFO = 0NWL = 0NWU = 0*DO 70 JB = 1, NSPLITIOFF = IENDIBEGIN = IOFF + 1IEND = 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 + 1IF( IRANGE.EQ.1 .OR. WU.GE.D( IBEGIN )-PIVMIN )$ NWU = NWU + 1IF( IRANGE.EQ.1 .OR. ( WL.LT.D( IBEGIN )-PIVMIN .AND. WU.GE.$ D( IBEGIN )-PIVMIN ) ) THENM = M + 1W( M ) = D( IBEGIN )IBLOCK( M ) = JBEND IFELSE** 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 - 1TMP2 = ABS( E( J ) )GU = MAX( GU, D( J )+TMP1+TMP2 )GL = MIN( GL, D( J )-TMP1-TMP2 )TMP1 = TMP240 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*PIVMINGU = GU + FUDGE*BNORM*ULP*IN + FUDGE*PIVMIN** Compute ATOLI for the current submatrix*IF( ABSTOL.LE.ZERO ) THENATOLI = ULP*MAX( ABS( GL ), ABS( GU ) )ELSEATOLI = ABSTOLEND IF*IF( IRANGE.GT.1 ) THENIF( GU.LT.WL ) THENNWL = NWL + INNWU = NWU + INGO TO 70END IFGL = MAX( GL, WL )GU = MIN( GU, WU )IF( GL.GE.GU )$ GO TO 70END IF** Set Up Initial Interval*WORK( N+1 ) = GLWORK( N+IN+1 ) = GUCALL 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 ) ) + 2CALL 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, IOUTTMP1 = HALF*( WORK( J+N )+WORK( J+IN+N ) )** Flag non-convergence.*IF( J.GT.IOUT-IINFO ) THENNCNVRG = .TRUE.IB = -JBELSEIB = JBEND IFDO 50 JE = IWORK( J ) + 1 + IWOFF,$ IWORK( J+IN ) + IWOFFW( JE ) = TMP1IBLOCK( JE ) = IB50 CONTINUE60 CONTINUE*M = M + IMEND IF70 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 ) THENIM = 0IDISCL = IL - 1 - NWLIDISCU = NWU - IU*IF( IDISCL.GT.0 .OR. IDISCU.GT.0 ) THENDO 80 JE = 1, MIF( W( JE ).LE.WLU .AND. IDISCL.GT.0 ) THENIDISCL = IDISCL - 1ELSE IF( W( JE ).GE.WUL .AND. IDISCU.GT.0 ) THENIDISCU = IDISCU - 1ELSEIM = IM + 1W( IM ) = W( JE )IBLOCK( IM ) = IBLOCK( JE )END IF80 CONTINUEM = IMEND IFIF( 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 ) THENWKILL = WUDO 100 JDISC = 1, IDISCLIW = 0DO 90 JE = 1, MIF( IBLOCK( JE ).NE.0 .AND.$ ( W( JE ).LT.WKILL .OR. IW.EQ.0 ) ) THENIW = JEWKILL = W( JE )END IF90 CONTINUEIBLOCK( IW ) = 0100 CONTINUEEND IFIF( IDISCU.GT.0 ) THEN*WKILL = WLDO 120 JDISC = 1, IDISCUIW = 0DO 110 JE = 1, MIF( IBLOCK( JE ).NE.0 .AND.$ ( W( JE ).GT.WKILL .OR. IW.EQ.0 ) ) THENIW = JEWKILL = W( JE )END IF110 CONTINUEIBLOCK( IW ) = 0120 CONTINUEEND IFIM = 0DO 130 JE = 1, MIF( IBLOCK( JE ).NE.0 ) THENIM = IM + 1W( IM ) = W( JE )IBLOCK( IM ) = IBLOCK( JE )END IF130 CONTINUEM = IMEND IFIF( IDISCL.LT.0 .OR. IDISCU.LT.0 ) THENTOOFEW = .TRUE.END IFEND IF** If ORDER='B', do nothing -- the eigenvalues are already sorted* by block.* If ORDER='E', sort the eigenvalues from smallest to largest*IF( IORDER.EQ.1 .AND. NSPLIT.GT.1 ) THENDO 150 JE = 1, M - 1IE = 0TMP1 = W( JE )DO 140 J = JE + 1, MIF( W( J ).LT.TMP1 ) THENIE = JTMP1 = W( J )END IF140 CONTINUE*IF( IE.NE.0 ) THENITMP1 = IBLOCK( IE )W( IE ) = W( JE )IBLOCK( IE ) = IBLOCK( JE )W( JE ) = TMP1IBLOCK( JE ) = ITMP1END IF150 CONTINUEEND IF*INFO = 0IF( NCNVRG )$ INFO = INFO + 1IF( TOOFEW )$ INFO = INFO + 2RETURN** End of DSTEBZ*ENDSUBROUTINE DSTEGR( JOBZ, RANGE, N, D, E, VL, VU, IL, IU, ABSTOL,$ M, W, Z, LDZ, ISUPPZ, WORK, LWORK, IWORK,$ LIWORK, INFO )** -- LAPACK computational routine (version 3.0) --* Univ. of Tennessee, Univ. of California Berkeley, NAG Ltd.,* Courant Institute, Argonne National Lab, and Rice University* June 30, 1999** .. Scalar Arguments ..CHARACTER JOBZ, RANGEINTEGER IL, INFO, IU, LDZ, LIWORK, LWORK, M, NDOUBLE PRECISION ABSTOL, VL, VU* ..* .. Array Arguments ..INTEGER ISUPPZ( * ), IWORK( * )DOUBLE PRECISION D( * ), E( * ), W( * ), WORK( * ), Z( LDZ, * )* ..** Purpose* =======** DSTEGR computes selected eigenvalues and, optionally, eigenvectors* of a real symmetric tridiagonal matrix T. Eigenvalues and* eigenvectors can be selected by specifying either a range of values* or a range of indices for the desired eigenvalues. The eigenvalues* are computed by the dqds algorithm, while orthogonal eigenvectors are* computed from various ``good'' L D L^T representations (also known as* Relatively Robust Representations). Gram-Schmidt orthogonalization is* avoided as far as possible. More specifically, the various steps of* the algorithm are as follows. For the i-th unreduced block of T,* (a) Compute T - sigma_i = L_i D_i L_i^T, such that L_i D_i L_i^T* is a relatively robust representation,* (b) Compute the eigenvalues, lambda_j, of L_i D_i L_i^T to high* relative accuracy by the dqds algorithm,* (c) If there is a cluster of close eigenvalues, "choose" sigma_i* close to the cluster, and go to step (a),* (d) Given the approximate eigenvalue lambda_j of L_i D_i L_i^T,* compute the corresponding eigenvector by forming a* rank-revealing twisted factorization.* The desired accuracy of the output can be specified by the input* parameter ABSTOL.** For more details, see "A new O(n^2) algorithm for the symmetric* tridiagonal eigenvalue/eigenvector problem", by Inderjit Dhillon,* Computer Science Division Technical Report No. UCB/CSD-97-971,* UC Berkeley, May 1997.** Note 1 : Currently DSTEGR is only set up to find ALL the n* eigenvalues and eigenvectors of T in O(n^2) time* Note 2 : Currently the routine DSTEIN is called when an appropriate* sigma_i cannot be chosen in step (c) above. DSTEIN invokes modified* Gram-Schmidt when eigenvalues are close.* Note 3 : DSTEGR works only on machines which follow ieee-754* floating-point standard in their handling of infinities and NaNs.* Normal execution of DSTEGR may create NaNs and infinities and hence* may abort due to a floating point exception in environments which* do not conform to the ieee standard.** 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.********** Only RANGE = 'A' is currently supported *********************** 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* T. On exit, D is overwritten.** E (input/output) DOUBLE PRECISION array, dimension (N)* On entry, the (n-1) subdiagonal elements of the tridiagonal* matrix T in elements 1 to N-1 of E; E(N) need not be set.* On exit, E is overwritten.** VL (input) DOUBLE PRECISION* VU (input) DOUBLE PRECISION* If RANGE='V', the lower and upper bounds of the interval to* be searched for eigenvalues. VL < VU.* Not referenced if RANGE = 'A' or 'I'.** IL (input) INTEGER* IU (input) INTEGER* If RANGE='I', the indices (in ascending order) of the* smallest and largest eigenvalues to be returned.* 1 <= IL <= IU <= N, if N > 0; IL = 1 and IU = 0 if N = 0.* Not referenced if RANGE = 'A' or 'V'.** ABSTOL (input) DOUBLE PRECISION* The absolute error tolerance for the* eigenvalues/eigenvectors. IF JOBZ = 'V', the eigenvalues and* eigenvectors output have residual norms bounded by ABSTOL,* and the dot products between different eigenvectors are* bounded by ABSTOL. If ABSTOL is less than N*EPS*|T|, then* N*EPS*|T| will be used in its place, where EPS is the* machine precision and |T| is the 1-norm of the tridiagonal* matrix. The eigenvalues are computed to an accuracy of* EPS*|T| irrespective of ABSTOL. If high relative accuracy* is important, set ABSTOL to DLAMCH( 'Safe minimum' ).* See Barlow and Demmel "Computing Accurate Eigensystems of* Scaled Diagonally Dominant Matrices", LAPACK Working Note #7* for a discussion of which matrices define their eigenvalues* to high relative accuracy.** 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)* The first M elements 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 T* corresponding to the selected eigenvalues, with the i-th* column of Z holding the eigenvector associated with W(i).* If JOBZ = 'N', then Z is not referenced.* Note: the user must ensure that at least max(1,M) columns are* supplied in the array Z; if RANGE = 'V', the exact value of M* is not known in advance and an upper bound must be used.** LDZ (input) INTEGER* The leading dimension of the array Z. LDZ >= 1, and if* JOBZ = 'V', LDZ >= max(1,N).** ISUPPZ (output) INTEGER ARRAY, dimension ( 2*max(1,M) )* The support of the eigenvectors in Z, i.e., the indices* indicating the nonzero elements in Z. The i-th eigenvector* is nonzero only in elements ISUPPZ( 2*i-1 ) through* ISUPPZ( 2*i ).** WORK (workspace/output) DOUBLE PRECISION array, dimension (LWORK)* On exit, if INFO = 0, WORK(1) returns the optimal* (and minimal) LWORK.** LWORK (input) INTEGER* The dimension of the array WORK. LWORK >= max(1,18*N)** If LWORK = -1, then a workspace query is assumed; the routine* only calculates the optimal size of the WORK array, returns* this value as the first entry of the WORK array, and no error* message related to LWORK is issued by XERBLA.** IWORK (workspace/output) INTEGER array, dimension (LIWORK)* On exit, if INFO = 0, IWORK(1) returns the optimal LIWORK.** LIWORK (input) INTEGER* The dimension of the array IWORK. LIWORK >= max(1,10*N)** If LIWORK = -1, then a workspace query is assumed; the* routine only calculates the optimal size of the IWORK array,* returns this value as the first entry of the IWORK array, and* no error message related to LIWORK is issued by XERBLA.** INFO (output) INTEGER* = 0: successful exit* < 0: if INFO = -i, the i-th argument had an illegal value* > 0: if INFO = 1, internal error in DLARRE,* if INFO = 2, internal error in DLARRV.** Further Details* ===============** Based on contributions by* Inderjit Dhillon, IBM Almaden, USA* Osni Marques, LBNL/NERSC, USA** =====================================================================** .. Parameters ..DOUBLE PRECISION ZERO, ONEPARAMETER ( ZERO = 0.0D0, ONE = 1.0D0 )* ..* .. Local Scalars ..LOGICAL ALLEIG, INDEIG, LQUERY, VALEIG, WANTZINTEGER I, IBEGIN, IEND, IINDBL, IINDWK, IINFO, IINSPL,$ INDGRS, INDWOF, INDWRK, ITMP, J, JJ, LIWMIN,$ LWMIN, NSPLITDOUBLE PRECISION BIGNUM, EPS, RMAX, RMIN, SAFMIN, SCALE, SMLNUM,$ THRESH, TMP, TNRM, TOL* ..* .. External Functions ..LOGICAL LSAMEDOUBLE PRECISION DLAMCH, DLANSTEXTERNAL LSAME, DLAMCH, DLANST* ..* .. External Subroutines ..EXTERNAL DLARRE, DLARRV, DLASET, DSCAL, DSWAP, XERBLA* ..* .. Intrinsic Functions ..INTRINSIC DBLE, MAX, MIN, SQRT* ..* .. Executable Statements ..** Test the input parameters.*WANTZ = LSAME( JOBZ, 'V' )ALLEIG = LSAME( RANGE, 'A' )VALEIG = LSAME( RANGE, 'V' )INDEIG = LSAME( RANGE, 'I' )*LQUERY = ( ( LWORK.EQ.-1 ) .OR. ( LIWORK.EQ.-1 ) )LWMIN = 18*NLIWMIN = 10*N*INFO = 0IF( .NOT.( WANTZ .OR. LSAME( JOBZ, 'N' ) ) ) THENINFO = -1ELSE IF( .NOT.( ALLEIG .OR. VALEIG .OR. INDEIG ) ) THENINFO = -2** The following two lines need to be removed once the* RANGE = 'V' and RANGE = 'I' options are provided.*ELSE IF( VALEIG .OR. INDEIG ) THENINFO = -2ELSE IF( N.LT.0 ) THENINFO = -3ELSE IF( VALEIG .AND. N.GT.0 .AND. VU.LE.VL ) THENINFO = -7ELSE IF( INDEIG .AND. IL.LT.1 ) THENINFO = -8* The following change should be made in DSTEVX also, otherwise* IL can be specified as N+1 and IU as N.* ELSE IF( INDEIG .AND. ( IU.LT.MIN( N, IL ) .OR. IU.GT.N ) ) THENELSE IF( INDEIG .AND. ( IU.LT.IL .OR. IU.GT.N ) ) THENINFO = -9ELSE IF( LDZ.LT.1 .OR. ( WANTZ .AND. LDZ.LT.N ) ) THENINFO = -14ELSE IF( LWORK.LT.LWMIN .AND. .NOT.LQUERY ) THENINFO = -17ELSE IF( LIWORK.LT.LIWMIN .AND. .NOT.LQUERY ) THENINFO = -19END IFIF( INFO.EQ.0 ) THENWORK( 1 ) = LWMINIWORK( 1 ) = LIWMINEND IF*IF( INFO.NE.0 ) THENCALL XERBLA( 'DSTEGR', -INFO )RETURNELSE IF( LQUERY ) THENRETURNEND IF** Quick return if possible*M = 0IF( N.EQ.0 )$ RETURN*IF( N.EQ.1 ) THENIF( ALLEIG .OR. INDEIG ) THENM = 1W( 1 ) = D( 1 )ELSEIF( VL.LT.D( 1 ) .AND. VU.GE.D( 1 ) ) THENM = 1W( 1 ) = D( 1 )END IFEND IFIF( WANTZ )$ Z( 1, 1 ) = ONERETURNEND IF** Get machine constants.*SAFMIN = DLAMCH( 'Safe minimum' )EPS = DLAMCH( 'Precision' )SMLNUM = SAFMIN / EPSBIGNUM = ONE / SMLNUMRMIN = SQRT( SMLNUM )RMAX = MIN( SQRT( BIGNUM ), ONE / SQRT( SQRT( SAFMIN ) ) )** Scale matrix to allowable range, if necessary.*SCALE = ONETNRM = DLANST( 'M', N, D, E )IF( TNRM.GT.ZERO .AND. TNRM.LT.RMIN ) THENSCALE = RMIN / TNRMELSE IF( TNRM.GT.RMAX ) THENSCALE = RMAX / TNRMEND IFIF( SCALE.NE.ONE ) THENCALL DSCAL( N, SCALE, D, 1 )CALL DSCAL( N-1, SCALE, E, 1 )TNRM = TNRM*SCALEEND IFINDGRS = 1INDWOF = 2*N + 1INDWRK = 3*N + 1*IINSPL = 1IINDBL = N + 1IINDWK = 2*N + 1*CALL DLASET( 'Full', N, N, ZERO, ZERO, Z, LDZ )** Compute the desired eigenvalues of the tridiagonal after splitting* into smaller subblocks if the corresponding of-diagonal elements* are small*THRESH = EPS*TNRMCALL DLARRE( N, D, E, THRESH, NSPLIT, IWORK( IINSPL ), M, W,$ WORK( INDWOF ), WORK( INDGRS ), WORK( INDWRK ),$ IINFO )IF( IINFO.NE.0 ) THENINFO = 1RETURNEND IF*IF( WANTZ ) THEN** Compute the desired eigenvectors corresponding to the computed* eigenvalues*TOL = MAX( ABSTOL, DBLE( N )*THRESH )IBEGIN = 1DO 20 I = 1, NSPLITIEND = IWORK( IINSPL+I-1 )DO 10 J = IBEGIN, IENDIWORK( IINDBL+J-1 ) = I10 CONTINUEIBEGIN = IEND + 120 CONTINUE*CALL DLARRV( N, D, E, IWORK( IINSPL ), M, W, IWORK( IINDBL ),$ WORK( INDGRS ), TOL, Z, LDZ, ISUPPZ,$ WORK( INDWRK ), IWORK( IINDWK ), IINFO )IF( IINFO.NE.0 ) THENINFO = 2RETURNEND IF*END IF*IBEGIN = 1DO 40 I = 1, NSPLITIEND = IWORK( IINSPL+I-1 )DO 30 J = IBEGIN, IENDW( J ) = W( J ) + WORK( INDWOF+I-1 )30 CONTINUEIBEGIN = IEND + 140 CONTINUE** If matrix was scaled, then rescale eigenvalues appropriately.*IF( SCALE.NE.ONE ) THENCALL DSCAL( M, ONE / SCALE, W, 1 )END IF** If eigenvalues are not in order, then sort them, along with* eigenvectors.*IF( NSPLIT.GT.1 ) THENDO 60 J = 1, M - 1I = 0TMP = W( J )DO 50 JJ = J + 1, MIF( W( JJ ).LT.TMP ) THENI = JJTMP = W( JJ )END IF50 CONTINUEIF( I.NE.0 ) THENW( I ) = W( J )W( J ) = TMPIF( WANTZ ) THENCALL DSWAP( N, Z( 1, I ), 1, Z( 1, J ), 1 )ITMP = ISUPPZ( 2*I-1 )ISUPPZ( 2*I-1 ) = ISUPPZ( 2*J-1 )ISUPPZ( 2*J-1 ) = ITMPITMP = ISUPPZ( 2*I )ISUPPZ( 2*I ) = ISUPPZ( 2*J )ISUPPZ( 2*J ) = ITMPEND IFEND IF60 CONTINUEEND IF*WORK( 1 ) = LWMINIWORK( 1 ) = LIWMINRETURN** End of DSTEGR*ENDSUBROUTINE DSTEIN( N, D, E, M, W, IBLOCK, ISPLIT, Z, LDZ, WORK,$ IWORK, IFAIL, INFO )** -- LAPACK routine (version 3.0) --* Univ. of Tennessee, Univ. of California Berkeley, NAG Ltd.,* Courant Institute, Argonne National Lab, and Rice University* September 30, 1994** .. 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, ODM1PARAMETER ( ZERO = 0.0D+0, ONE = 1.0D+0, TEN = 1.0D+1,$ ODM3 = 1.0D-3, ODM1 = 1.0D-1 )INTEGER MAXITS, EXTRAPARAMETER ( MAXITS = 5, EXTRA = 2 )* ..* .. Local Scalars ..INTEGER B1, BLKSIZ, BN, GPIND, I, IINFO, INDRV1,$ INDRV2, INDRV3, INDRV4, INDRV5, ITS, J, J1,$ JBLK, JMAX, NBLK, NRMCHKDOUBLE PRECISION DTPCRT, EPS, EPS1, NRM, ONENRM, ORTOL, PERTOL,$ SCL, SEP, TOL, XJ, XJM, ZTR* ..* .. Local Arrays ..INTEGER ISEED( 4 )* ..* .. External Functions ..INTEGER IDAMAXDOUBLE PRECISION DASUM, DDOT, DLAMCH, DNRM2EXTERNAL 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 = 0DO 10 I = 1, MIFAIL( I ) = 010 CONTINUE*IF( N.LT.0 ) THENINFO = -1ELSE IF( M.LT.0 .OR. M.GT.N ) THENINFO = -4ELSE IF( LDZ.LT.MAX( 1, N ) ) THENINFO = -9ELSEDO 20 J = 2, MIF( IBLOCK( J ).LT.IBLOCK( J-1 ) ) THENINFO = -6GO TO 30END IFIF( IBLOCK( J ).EQ.IBLOCK( J-1 ) .AND. W( J ).LT.W( J-1 ) )$ THENINFO = -5GO TO 30END IF20 CONTINUE30 CONTINUEEND IF*IF( INFO.NE.0 ) THENCALL XERBLA( 'DSTEIN', -INFO )RETURNEND IF** Quick return if possible*IF( N.EQ.0 .OR. M.EQ.0 ) THENRETURNELSE IF( N.EQ.1 ) THENZ( 1, 1 ) = ONERETURNEND IF** Get machine constants.*EPS = DLAMCH( 'Precision' )** Initialize seed for random number generator DLARNV.*DO 40 I = 1, 4ISEED( I ) = 140 CONTINUE** Initialize pointers.*INDRV1 = 0INDRV2 = INDRV1 + NINDRV3 = INDRV2 + NINDRV4 = INDRV3 + NINDRV5 = INDRV4 + N** Compute eigenvectors of matrix blocks.*J1 = 1DO 160 NBLK = 1, IBLOCK( M )** Find starting and ending indices of block nblk.*IF( NBLK.EQ.1 ) THENB1 = 1ELSEB1 = ISPLIT( NBLK-1 ) + 1END IFBN = ISPLIT( NBLK )BLKSIZ = BN - B1 + 1IF( BLKSIZ.EQ.1 )$ GO TO 60GPIND = B1** 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 - 1ONENRM = MAX( ONENRM, ABS( D( I ) )+ABS( E( I-1 ) )+$ ABS( E( I ) ) )50 CONTINUEORTOL = ODM3*ONENRM*DTPCRT = SQRT( ODM1 / BLKSIZ )** Loop through eigenvalues of block nblk.*60 CONTINUEJBLK = 0DO 150 J = J1, MIF( IBLOCK( J ).NE.NBLK ) THENJ1 = JGO TO 160END IFJBLK = JBLK + 1XJ = W( J )** Skip all the work if the block size is one.*IF( BLKSIZ.EQ.1 ) THENWORK( INDRV1+1 ) = ONEGO TO 120END IF** If eigenvalues j and j-1 are too close, add a relatively* small perturbation.*IF( JBLK.GT.1 ) THENEPS1 = ABS( EPS*XJ )PERTOL = TEN*EPS1SEP = XJ - XJMIF( SEP.LT.PERTOL )$ XJ = XJM + PERTOLEND IF*ITS = 0NRMCHK = 0** Get random starting vector.*CALL DLARNV( 2, 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 = ZEROCALL DLAGTF( BLKSIZ, WORK( INDRV4+1 ), XJ, WORK( INDRV2+2 ),$ WORK( INDRV3+1 ), TOL, WORK( INDRV5+1 ), IWORK,$ IINFO )** Update iteration count.*70 CONTINUEITS = ITS + 1IF( 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 90IF( ABS( XJ-XJM ).GT.ORTOL )$ GPIND = JIF( GPIND.NE.J ) THENDO 80 I = GPIND, J - 1ZTR = -DDOT( BLKSIZ, WORK( INDRV1+1 ), 1, Z( B1, I ),$ 1 )CALL DAXPY( BLKSIZ, ZTR, Z( B1, I ), 1,$ WORK( INDRV1+1 ), 1 )80 CONTINUEEND IF** Check the infinity norm of the iterate.*90 CONTINUEJMAX = 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 70NRMCHK = NRMCHK + 1IF( 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 CONTINUEINFO = INFO + 1IFAIL( INFO ) = J** Accept iterate as jth eigenvector.*110 CONTINUESCL = ONE / DNRM2( BLKSIZ, WORK( INDRV1+1 ), 1 )JMAX = IDAMAX( BLKSIZ, WORK( INDRV1+1 ), 1 )IF( WORK( INDRV1+JMAX ).LT.ZERO )$ SCL = -SCLCALL DSCAL( BLKSIZ, SCL, WORK( INDRV1+1 ), 1 )120 CONTINUEDO 130 I = 1, NZ( I, J ) = ZERO130 CONTINUEDO 140 I = 1, BLKSIZZ( B1+I-1, J ) = WORK( INDRV1+I )140 CONTINUE** Save the shift to check eigenvalue spacing at next* iteration.*XJM = XJ*150 CONTINUE160 CONTINUE*RETURN** End of DSTEIN*ENDSUBROUTINE DSTEQR( COMPZ, N, D, E, Z, LDZ, WORK, INFO )** -- LAPACK routine (version 3.0) --* Univ. of Tennessee, Univ. of California Berkeley, NAG Ltd.,* Courant Institute, Argonne National Lab, and Rice University* September 30, 1994** .. Scalar Arguments ..CHARACTER COMPZINTEGER 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 INFO = 0, then 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 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, THREEPARAMETER ( ZERO = 0.0D0, ONE = 1.0D0, TWO = 2.0D0,$ THREE = 3.0D0 )INTEGER MAXITPARAMETER ( MAXIT = 30 )* ..* .. Local Scalars ..INTEGER I, ICOMPZ, II, ISCALE, J, JTOT, K, L, L1, LEND,$ LENDM1, LENDP1, LENDSV, LM1, LSV, M, MM, MM1,$ NM1, NMAXITDOUBLE PRECISION ANORM, B, C, EPS, EPS2, F, G, P, R, RT1, RT2,$ S, SAFMAX, SAFMIN, SSFMAX, SSFMIN, TST* ..* .. External Functions ..LOGICAL LSAMEDOUBLE PRECISION DLAMCH, DLANST, DLAPY2EXTERNAL LSAME, DLAMCH, DLANST, DLAPY2* ..* .. External Subroutines ..EXTERNAL DLAE2, DLAEV2, DLARTG, DLASCL, DLASET, DLASR,$ DLASRT, DSWAP, XERBLA* ..* .. Intrinsic Functions ..INTRINSIC ABS, MAX, SIGN, SQRT* ..* .. Executable Statements ..** Test the input parameters.*INFO = 0*IF( LSAME( COMPZ, 'N' ) ) THENICOMPZ = 0ELSE IF( LSAME( COMPZ, 'V' ) ) THENICOMPZ = 1ELSE IF( LSAME( COMPZ, 'I' ) ) THENICOMPZ = 2ELSEICOMPZ = -1END IFIF( ICOMPZ.LT.0 ) THENINFO = -1ELSE IF( N.LT.0 ) THENINFO = -2ELSE IF( ( LDZ.LT.1 ) .OR. ( ICOMPZ.GT.0 .AND. LDZ.LT.MAX( 1,$ N ) ) ) THENINFO = -6END IFIF( INFO.NE.0 ) THENCALL XERBLA( 'DSTEQR', -INFO )RETURNEND IF** Quick return if possible*IF( N.EQ.0 )$ RETURN*IF( N.EQ.1 ) THENIF( ICOMPZ.EQ.2 )$ Z( 1, 1 ) = ONERETURNEND IF** Determine the unit roundoff and over/underflow thresholds.*EPS = DLAMCH( 'E' )EPS2 = EPS**2SAFMIN = DLAMCH( 'S' )SAFMAX = ONE / SAFMINSSFMAX = SQRT( SAFMAX ) / THREESSFMIN = SQRT( SAFMIN ) / EPS2** Compute the eigenvalues and eigenvectors of the tridiagonal* matrix.*IF( ICOMPZ.EQ.2 )$ CALL DLASET( 'Full', N, N, ZERO, ONE, Z, LDZ )*NMAXIT = N*MAXITJTOT = 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 = 1NM1 = N - 1*10 CONTINUEIF( L1.GT.N )$ GO TO 160IF( L1.GT.1 )$ E( L1-1 ) = ZEROIF( L1.LE.NM1 ) THENDO 20 M = L1, NM1TST = ABS( E( M ) )IF( TST.EQ.ZERO )$ GO TO 30IF( TST.LE.( SQRT( ABS( D( M ) ) )*SQRT( ABS( D( M+$ 1 ) ) ) )*EPS ) THENE( M ) = ZEROGO TO 30END IF20 CONTINUEEND IFM = N*30 CONTINUEL = L1LSV = LLEND = MLENDSV = LENDL1 = M + 1IF( LEND.EQ.L )$ GO TO 10** Scale submatrix in rows and columns L to LEND*ANORM = DLANST( 'I', LEND-L+1, D( L ), E( L ) )ISCALE = 0IF( ANORM.EQ.ZERO )$ GO TO 10IF( ANORM.GT.SSFMAX ) THENISCALE = 1CALL DLASCL( 'G', 0, 0, ANORM, SSFMAX, LEND-L+1, 1, D( L ), N,$ INFO )CALL DLASCL( 'G', 0, 0, ANORM, SSFMAX, LEND-L, 1, E( L ), N,$ INFO )ELSE IF( ANORM.LT.SSFMIN ) THENISCALE = 2CALL DLASCL( 'G', 0, 0, ANORM, SSFMIN, LEND-L+1, 1, D( L ), N,$ INFO )CALL DLASCL( 'G', 0, 0, ANORM, SSFMIN, LEND-L, 1, E( L ), N,$ INFO )END IF** Choose between QL and QR iteration*IF( ABS( D( LEND ) ).LT.ABS( D( L ) ) ) THENLEND = LSVL = LENDSVEND IF*IF( LEND.GT.L ) THEN** QL Iteration** Look for small subdiagonal element.*40 CONTINUEIF( L.NE.LEND ) THENLENDM1 = LEND - 1DO 50 M = L, LENDM1TST = ABS( E( M ) )**2IF( TST.LE.( EPS2*ABS( D( M ) ) )*ABS( D( M+1 ) )+$ SAFMIN )GO TO 6050 CONTINUEEND IF*M = LEND*60 CONTINUEIF( M.LT.LEND )$ E( M ) = ZEROP = D( L )IF( M.EQ.L )$ GO TO 80** If remaining matrix is 2-by-2, use DLAE2 or SLAEV2* to compute its eigensystem.*IF( M.EQ.L+1 ) THENIF( ICOMPZ.GT.0 ) THENCALL DLAEV2( D( L ), E( L ), D( L+1 ), RT1, RT2, C, S )WORK( L ) = CWORK( N-1+L ) = SCALL DLASR( 'R', 'V', 'B', N, 2, WORK( L ),$ WORK( N-1+L ), Z( 1, L ), LDZ )ELSECALL DLAE2( D( L ), E( L ), D( L+1 ), RT1, RT2 )END IFD( L ) = RT1D( L+1 ) = RT2E( L ) = ZEROL = L + 2IF( L.LE.LEND )$ GO TO 40GO TO 140END IF*IF( JTOT.EQ.NMAXIT )$ GO TO 140JTOT = 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 = ONEC = ONEP = ZERO** Inner loop*MM1 = M - 1DO 70 I = MM1, L, -1F = S*E( I )B = C*E( I )CALL DLARTG( G, F, C, S, R )IF( I.NE.M-1 )$ E( I+1 ) = RG = D( I+1 ) - PR = ( D( I )-G )*S + TWO*C*BP = S*RD( I+1 ) = G + PG = C*R - B** If eigenvectors are desired, then save rotations.*IF( ICOMPZ.GT.0 ) THENWORK( I ) = CWORK( N-1+I ) = -SEND IF*70 CONTINUE** If eigenvectors are desired, then apply saved rotations.*IF( ICOMPZ.GT.0 ) THENMM = M - L + 1CALL DLASR( 'R', 'V', 'B', N, MM, WORK( L ), WORK( N-1+L ),$ Z( 1, L ), LDZ )END IF*D( L ) = D( L ) - PE( L ) = GGO TO 40** Eigenvalue found.*80 CONTINUED( L ) = P*L = L + 1IF( L.LE.LEND )$ GO TO 40GO TO 140*ELSE** QR Iteration** Look for small superdiagonal element.*90 CONTINUEIF( L.NE.LEND ) THENLENDP1 = LEND + 1DO 100 M = L, LENDP1, -1TST = ABS( E( M-1 ) )**2IF( TST.LE.( EPS2*ABS( D( M ) ) )*ABS( D( M-1 ) )+$ SAFMIN )GO TO 110100 CONTINUEEND IF*M = LEND*110 CONTINUEIF( M.GT.LEND )$ E( M-1 ) = ZEROP = D( L )IF( M.EQ.L )$ GO TO 130** If remaining matrix is 2-by-2, use DLAE2 or SLAEV2* to compute its eigensystem.*IF( M.EQ.L-1 ) THENIF( ICOMPZ.GT.0 ) THENCALL DLAEV2( D( L-1 ), E( L-1 ), D( L ), RT1, RT2, C, S )WORK( M ) = CWORK( N-1+M ) = SCALL DLASR( 'R', 'V', 'F', N, 2, WORK( M ),$ WORK( N-1+M ), Z( 1, L-1 ), LDZ )ELSECALL DLAE2( D( L-1 ), E( L-1 ), D( L ), RT1, RT2 )END IFD( L-1 ) = RT1D( L ) = RT2E( L-1 ) = ZEROL = L - 2IF( L.GE.LEND )$ GO TO 90GO TO 140END IF*IF( JTOT.EQ.NMAXIT )$ GO TO 140JTOT = 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 = ONEC = ONEP = ZERO** Inner loop*LM1 = L - 1DO 120 I = M, LM1F = S*E( I )B = C*E( I )CALL DLARTG( G, F, C, S, R )IF( I.NE.M )$ E( I-1 ) = RG = D( I ) - PR = ( D( I+1 )-G )*S + TWO*C*BP = S*RD( I ) = G + PG = C*R - B** If eigenvectors are desired, then save rotations.*IF( ICOMPZ.GT.0 ) THENWORK( I ) = CWORK( N-1+I ) = SEND IF*120 CONTINUE** If eigenvectors are desired, then apply saved rotations.*IF( ICOMPZ.GT.0 ) THENMM = L - M + 1CALL DLASR( 'R', 'V', 'F', N, MM, WORK( M ), WORK( N-1+M ),$ Z( 1, M ), LDZ )END IF*D( L ) = D( L ) - PE( LM1 ) = GGO TO 90** Eigenvalue found.*130 CONTINUED( L ) = P*L = L - 1IF( L.GE.LEND )$ GO TO 90GO TO 140*END IF** Undo scaling if necessary*140 CONTINUEIF( ISCALE.EQ.1 ) THENCALL DLASCL( 'G', 0, 0, SSFMAX, ANORM, LENDSV-LSV+1, 1,$ D( LSV ), N, INFO )CALL DLASCL( 'G', 0, 0, SSFMAX, ANORM, LENDSV-LSV, 1, E( LSV ),$ N, INFO )ELSE IF( ISCALE.EQ.2 ) THENCALL DLASCL( 'G', 0, 0, SSFMIN, ANORM, LENDSV-LSV+1, 1,$ D( LSV ), N, INFO )CALL DLASCL( 'G', 0, 0, SSFMIN, ANORM, LENDSV-LSV, 1, E( LSV ),$ N, INFO )END IF** Check for no convergence to an eigenvalue after a total* of N*MAXIT iterations.*IF( JTOT.LT.NMAXIT )$ GO TO 10DO 150 I = 1, N - 1IF( E( I ).NE.ZERO )$ INFO = INFO + 1150 CONTINUEGO TO 190** Order eigenvalues and eigenvectors.*160 CONTINUEIF( ICOMPZ.EQ.0 ) THEN** Use Quick Sort*CALL DLASRT( 'I', N, D, INFO )*ELSE** Use Selection Sort to minimize swaps of eigenvectors*DO 180 II = 2, NI = II - 1K = IP = D( I )DO 170 J = II, NIF( D( J ).LT.P ) THENK = JP = D( J )END IF170 CONTINUEIF( K.NE.I ) THEND( K ) = D( I )D( I ) = PCALL DSWAP( N, Z( 1, I ), 1, Z( 1, K ), 1 )END IF180 CONTINUEEND IF*190 CONTINUERETURN** End of DSTEQR*ENDSUBROUTINE DSTERF( N, D, E, INFO )** -- LAPACK routine (version 3.0) --* Univ. of Tennessee, Univ. of California Berkeley, NAG Ltd.,* Courant Institute, Argonne National Lab, and Rice University* June 30, 1999** .. 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, THREEPARAMETER ( ZERO = 0.0D0, ONE = 1.0D0, TWO = 2.0D0,$ THREE = 3.0D0 )INTEGER MAXITPARAMETER ( MAXIT = 30 )* ..* .. Local Scalars ..INTEGER I, ISCALE, JTOT, L, L1, LEND, LENDSV, LSV, M,$ NMAXITDOUBLE PRECISION ALPHA, ANORM, BB, C, EPS, EPS2, GAMMA, OLDC,$ OLDGAM, P, R, RT1, RT2, RTE, S, SAFMAX, SAFMIN,$ SIGMA, SSFMAX, SSFMIN* ..* .. External Functions ..DOUBLE PRECISION DLAMCH, DLANST, DLAPY2EXTERNAL DLAMCH, DLANST, DLAPY2* ..* .. External Subroutines ..EXTERNAL DLAE2, DLASCL, DLASRT, XERBLA* ..* .. Intrinsic Functions ..INTRINSIC ABS, SIGN, SQRT* ..* .. Executable Statements ..** Test the input parameters.*INFO = 0** Quick return if possible*IF( N.LT.0 ) THENINFO = -1CALL XERBLA( 'DSTERF', -INFO )RETURNEND IFIF( N.LE.1 )$ RETURN** Determine the unit roundoff for this environment.*EPS = DLAMCH( 'E' )EPS2 = EPS**2SAFMIN = DLAMCH( 'S' )SAFMAX = ONE / SAFMINSSFMAX = SQRT( SAFMAX ) / THREESSFMIN = SQRT( SAFMIN ) / EPS2** Compute the eigenvalues of the tridiagonal matrix.*NMAXIT = N*MAXITSIGMA = ZEROJTOT = 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*10 CONTINUEIF( L1.GT.N )$ GO TO 170IF( L1.GT.1 )$ E( L1-1 ) = ZERODO 20 M = L1, N - 1IF( ABS( E( M ) ).LE.( SQRT( ABS( D( M ) ) )*SQRT( ABS( D( M+$ 1 ) ) ) )*EPS ) THENE( M ) = ZEROGO TO 30END IF20 CONTINUEM = N*30 CONTINUEL = L1LSV = LLEND = MLENDSV = LENDL1 = M + 1IF( LEND.EQ.L )$ GO TO 10** Scale submatrix in rows and columns L to LEND*ANORM = DLANST( 'I', LEND-L+1, D( L ), E( L ) )ISCALE = 0IF( ANORM.GT.SSFMAX ) THENISCALE = 1CALL DLASCL( 'G', 0, 0, ANORM, SSFMAX, LEND-L+1, 1, D( L ), N,$ INFO )CALL DLASCL( 'G', 0, 0, ANORM, SSFMAX, LEND-L, 1, E( L ), N,$ INFO )ELSE IF( ANORM.LT.SSFMIN ) THENISCALE = 2CALL DLASCL( 'G', 0, 0, ANORM, SSFMIN, LEND-L+1, 1, D( L ), N,$ INFO )CALL DLASCL( 'G', 0, 0, ANORM, SSFMIN, LEND-L, 1, E( L ), N,$ INFO )END IF*DO 40 I = L, LEND - 1E( I ) = E( I )**240 CONTINUE** Choose between QL and QR iteration*IF( ABS( D( LEND ) ).LT.ABS( D( L ) ) ) THENLEND = LSVL = LENDSVEND IF*IF( LEND.GE.L ) THEN** QL Iteration** Look for small subdiagonal element.*50 CONTINUEIF( L.NE.LEND ) THENDO 60 M = L, LEND - 1IF( ABS( E( M ) ).LE.EPS2*ABS( D( M )*D( M+1 ) ) )$ GO TO 7060 CONTINUEEND IFM = LEND*70 CONTINUEIF( M.LT.LEND )$ E( M ) = ZEROP = 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 ) THENRTE = SQRT( E( L ) )CALL DLAE2( D( L ), RTE, D( L+1 ), RT1, RT2 )D( L ) = RT1D( L+1 ) = RT2E( L ) = ZEROL = L + 2IF( L.LE.LEND )$ GO TO 50GO TO 150END IF*IF( JTOT.EQ.NMAXIT )$ GO TO 150JTOT = 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 = ONES = ZEROGAMMA = D( M ) - SIGMAP = GAMMA*GAMMA** Inner loop*DO 80 I = M - 1, L, -1BB = E( I )R = P + BBIF( I.NE.M-1 )$ E( I+1 ) = S*ROLDC = CC = P / RS = BB / ROLDGAM = GAMMAALPHA = D( I )GAMMA = C*( ALPHA-SIGMA ) - S*OLDGAMD( I+1 ) = OLDGAM + ( ALPHA-GAMMA )IF( C.NE.ZERO ) THENP = ( GAMMA*GAMMA ) / CELSEP = OLDC*BBEND IF80 CONTINUE*E( L ) = S*PD( L ) = SIGMA + GAMMAGO TO 50** Eigenvalue found.*90 CONTINUED( L ) = P*L = L + 1IF( L.LE.LEND )$ GO TO 50GO TO 150*ELSE** QR Iteration** Look for small superdiagonal element.*100 CONTINUEDO 110 M = L, LEND + 1, -1IF( ABS( E( M-1 ) ).LE.EPS2*ABS( D( M )*D( M-1 ) ) )$ GO TO 120110 CONTINUEM = LEND*120 CONTINUEIF( M.GT.LEND )$ E( M-1 ) = ZEROP = 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 ) THENRTE = SQRT( E( L-1 ) )CALL DLAE2( D( L ), RTE, D( L-1 ), RT1, RT2 )D( L ) = RT1D( L-1 ) = RT2E( L-1 ) = ZEROL = L - 2IF( L.GE.LEND )$ GO TO 100GO TO 150END IF*IF( JTOT.EQ.NMAXIT )$ GO TO 150JTOT = 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 = ONES = ZEROGAMMA = D( M ) - SIGMAP = GAMMA*GAMMA** Inner loop*DO 130 I = M, L - 1BB = E( I )R = P + BBIF( I.NE.M )$ E( I-1 ) = S*ROLDC = CC = P / RS = BB / ROLDGAM = GAMMAALPHA = D( I+1 )GAMMA = C*( ALPHA-SIGMA ) - S*OLDGAMD( I ) = OLDGAM + ( ALPHA-GAMMA )IF( C.NE.ZERO ) THENP = ( GAMMA*GAMMA ) / CELSEP = OLDC*BBEND IF130 CONTINUE*E( L-1 ) = S*PD( L ) = SIGMA + GAMMAGO TO 100** Eigenvalue found.*140 CONTINUED( L ) = P*L = L - 1IF( L.GE.LEND )$ GO TO 100GO TO 150*END IF** Undo scaling if necessary*150 CONTINUEIF( ISCALE.EQ.1 )$ CALL DLASCL( 'G', 0, 0, SSFMAX, ANORM, LENDSV-LSV+1, 1,$ D( LSV ), N, INFO )IF( ISCALE.EQ.2 )$ CALL DLASCL( 'G', 0, 0, SSFMIN, ANORM, LENDSV-LSV+1, 1,$ D( LSV ), N, INFO )** Check for no convergence to an eigenvalue after a total* of N*MAXIT iterations.*IF( JTOT.LT.NMAXIT )$ GO TO 10DO 160 I = 1, N - 1IF( E( I ).NE.ZERO )$ INFO = INFO + 1160 CONTINUEGO TO 180** Sort eigenvalues in increasing order.*170 CONTINUECALL DLASRT( 'I', N, D, INFO )*180 CONTINUERETURN** End of DSTERF*ENDSUBROUTINE DSYCON( UPLO, N, A, LDA, IPIV, ANORM, RCOND, WORK,$ IWORK, INFO )** -- LAPACK routine (version 3.0) --* Univ. of Tennessee, Univ. of California Berkeley, NAG Ltd.,* Courant Institute, Argonne National Lab, and Rice University* March 31, 1993** .. Scalar Arguments ..CHARACTER UPLOINTEGER INFO, LDA, NDOUBLE PRECISION ANORM, RCOND* ..* .. Array Arguments ..INTEGER IPIV( * ), IWORK( * )DOUBLE PRECISION A( LDA, * ), WORK( * )* ..** Purpose* =======** DSYCON estimates the reciprocal of the condition number (in the* 1-norm) of a real symmetric matrix A using the factorization* A = U*D*U**T or A = L*D*L**T computed by DSYTRF.** An estimate is obtained for norm(inv(A)), and the reciprocal of the* condition number is computed as RCOND = 1 / (ANORM * norm(inv(A))).** 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**T;* = 'L': Lower triangular, form is A = L*D*L**T.** N (input) INTEGER* The order of the matrix A. N >= 0.** A (input) DOUBLE PRECISION array, dimension (LDA,N)* The block diagonal matrix D and the multipliers used to* obtain the factor U or L as computed by DSYTRF.** 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.** ANORM (input) DOUBLE PRECISION* The 1-norm of the original matrix A.** RCOND (output) DOUBLE PRECISION* The reciprocal of the condition number of the matrix A,* computed as RCOND = 1/(ANORM * AINVNM), where AINVNM is an* estimate of the 1-norm of inv(A) computed in this routine.** WORK (workspace) DOUBLE PRECISION array, dimension (2*N)** IWORK (workspace) INTEGER array, dimension (N)** INFO (output) INTEGER* = 0: successful exit* < 0: if INFO = -i, the i-th argument had an illegal value** =====================================================================** .. Parameters ..DOUBLE PRECISION ONE, ZEROPARAMETER ( ONE = 1.0D+0, ZERO = 0.0D+0 )* ..* .. Local Scalars ..LOGICAL UPPERINTEGER I, KASEDOUBLE PRECISION AINVNM* ..* .. External Functions ..LOGICAL LSAMEEXTERNAL LSAME* ..* .. External Subroutines ..EXTERNAL DLACON, DSYTRS, XERBLA* ..* .. Intrinsic Functions ..INTRINSIC MAX* ..* .. Executable Statements ..** Test the input parameters.*INFO = 0UPPER = LSAME( UPLO, 'U' )IF( .NOT.UPPER .AND. .NOT.LSAME( UPLO, 'L' ) ) THENINFO = -1ELSE IF( N.LT.0 ) THENINFO = -2ELSE IF( LDA.LT.MAX( 1, N ) ) THENINFO = -4ELSE IF( ANORM.LT.ZERO ) THENINFO = -6END IFIF( INFO.NE.0 ) THENCALL XERBLA( 'DSYCON', -INFO )RETURNEND IF** Quick return if possible*RCOND = ZEROIF( N.EQ.0 ) THENRCOND = ONERETURNELSE IF( ANORM.LE.ZERO ) THENRETURNEND IF** Check that the diagonal matrix D is nonsingular.*IF( UPPER ) THEN** Upper triangular storage: examine D from bottom to top*DO 10 I = N, 1, -1IF( IPIV( I ).GT.0 .AND. A( I, I ).EQ.ZERO )$ RETURN10 CONTINUEELSE** Lower triangular storage: examine D from top to bottom.*DO 20 I = 1, NIF( IPIV( I ).GT.0 .AND. A( I, I ).EQ.ZERO )$ RETURN20 CONTINUEEND IF** Estimate the 1-norm of the inverse.*KASE = 030 CONTINUECALL DLACON( N, WORK( N+1 ), WORK, IWORK, AINVNM, KASE )IF( KASE.NE.0 ) THEN** Multiply by inv(L*D*L') or inv(U*D*U').*CALL DSYTRS( UPLO, N, 1, A, LDA, IPIV, WORK, N, INFO )GO TO 30END IF** Compute the estimate of the reciprocal condition number.*IF( AINVNM.NE.ZERO )$ RCOND = ( ONE / AINVNM ) / ANORM*RETURN** End of DSYCON*ENDSUBROUTINE DSYGS2( ITYPE, UPLO, N, A, LDA, B, LDB, INFO )** -- LAPACK routine (version 3.0) --* Univ. of Tennessee, Univ. of California Berkeley, NAG Ltd.,* Courant Institute, Argonne National Lab, and Rice University* February 29, 1992** .. Scalar Arguments ..CHARACTER UPLOINTEGER INFO, ITYPE, LDA, LDB, N* ..* .. Array Arguments ..DOUBLE PRECISION A( LDA, * ), B( LDB, * )* ..** Purpose* =======** DSYGS2 reduces a real symmetric-definite generalized eigenproblem* to standard form.** If ITYPE = 1, the problem is A*x = lambda*B*x,* and A is overwritten by inv(U')*A*inv(U) or inv(L)*A*inv(L')** If ITYPE = 2 or 3, the problem is A*B*x = lambda*x or* B*A*x = lambda*x, and A is overwritten by U*A*U` or L'*A*L.** B must have been previously factorized as U'*U or L*L' by DPOTRF.** Arguments* =========** ITYPE (input) INTEGER* = 1: compute inv(U')*A*inv(U) or inv(L)*A*inv(L');* = 2 or 3: compute U*A*U' or L'*A*L.** UPLO (input) CHARACTER* Specifies whether the upper or lower triangular part of the* symmetric matrix A is stored, and how B has been factorized.* = 'U': Upper triangular* = 'L': Lower triangular** N (input) INTEGER* The order of the matrices A and B. 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 INFO = 0, the transformed matrix, stored in the* same format as A.** LDA (input) INTEGER* The leading dimension of the array A. LDA >= max(1,N).** B (input) DOUBLE PRECISION array, dimension (LDB,N)* The triangular factor from the Cholesky factorization of B,* as returned by DPOTRF.** 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, HALFPARAMETER ( ONE = 1.0D0, HALF = 0.5D0 )* ..* .. Local Scalars ..LOGICAL UPPERINTEGER KDOUBLE PRECISION AKK, BKK, CT* ..* .. External Subroutines ..EXTERNAL DAXPY, DSCAL, DSYR2, DTRMV, DTRSV, XERBLA* ..* .. Intrinsic Functions ..INTRINSIC MAX* ..* .. External Functions ..LOGICAL LSAMEEXTERNAL LSAME* ..* .. Executable Statements ..** Test the input parameters.*INFO = 0UPPER = LSAME( UPLO, 'U' )IF( ITYPE.LT.1 .OR. ITYPE.GT.3 ) THENINFO = -1ELSE IF( .NOT.UPPER .AND. .NOT.LSAME( UPLO, 'L' ) ) THENINFO = -2ELSE IF( N.LT.0 ) THENINFO = -3ELSE IF( LDA.LT.MAX( 1, N ) ) THENINFO = -5ELSE IF( LDB.LT.MAX( 1, N ) ) THENINFO = -7END IFIF( INFO.NE.0 ) THENCALL XERBLA( 'DSYGS2', -INFO )RETURNEND IF*IF( ITYPE.EQ.1 ) THENIF( UPPER ) THEN** Compute inv(U')*A*inv(U)*DO 10 K = 1, N** Update the upper triangle of A(k:n,k:n)*AKK = A( K, K )BKK = B( K, K )AKK = AKK / BKK**2A( K, K ) = AKKIF( K.LT.N ) THENCALL DSCAL( N-K, ONE / BKK, A( K, K+1 ), LDA )CT = -HALF*AKKCALL DAXPY( N-K, CT, B( K, K+1 ), LDB, A( K, K+1 ),$ LDA )CALL DSYR2( UPLO, N-K, -ONE, A( K, K+1 ), LDA,$ B( K, K+1 ), LDB, A( K+1, K+1 ), LDA )CALL DAXPY( N-K, CT, B( K, K+1 ), LDB, A( K, K+1 ),$ LDA )CALL DTRSV( UPLO, 'Transpose', 'Non-unit', N-K,$ B( K+1, K+1 ), LDB, A( K, K+1 ), LDA )END IF10 CONTINUEELSE** Compute inv(L)*A*inv(L')*DO 20 K = 1, N** Update the lower triangle of A(k:n,k:n)*AKK = A( K, K )BKK = B( K, K )AKK = AKK / BKK**2A( K, K ) = AKKIF( K.LT.N ) THENCALL DSCAL( N-K, ONE / BKK, A( K+1, K ), 1 )CT = -HALF*AKKCALL DAXPY( N-K, CT, B( K+1, K ), 1, A( K+1, K ), 1 )CALL DSYR2( UPLO, N-K, -ONE, A( K+1, K ), 1,$ B( K+1, K ), 1, A( K+1, K+1 ), LDA )CALL DAXPY( N-K, CT, B( K+1, K ), 1, A( K+1, K ), 1 )CALL DTRSV( UPLO, 'No transpose', 'Non-unit', N-K,$ B( K+1, K+1 ), LDB, A( K+1, K ), 1 )END IF20 CONTINUEEND IFELSEIF( UPPER ) THEN** Compute U*A*U'*DO 30 K = 1, N** Update the upper triangle of A(1:k,1:k)*AKK = A( K, K )BKK = B( K, K )CALL DTRMV( UPLO, 'No transpose', 'Non-unit', K-1, B,$ LDB, A( 1, K ), 1 )CT = HALF*AKKCALL DAXPY( K-1, CT, B( 1, K ), 1, A( 1, K ), 1 )CALL DSYR2( UPLO, K-1, ONE, A( 1, K ), 1, B( 1, K ), 1,$ A, LDA )CALL DAXPY( K-1, CT, B( 1, K ), 1, A( 1, K ), 1 )CALL DSCAL( K-1, BKK, A( 1, K ), 1 )A( K, K ) = AKK*BKK**230 CONTINUEELSE** Compute L'*A*L*DO 40 K = 1, N** Update the lower triangle of A(1:k,1:k)*AKK = A( K, K )BKK = B( K, K )CALL DTRMV( UPLO, 'Transpose', 'Non-unit', K-1, B, LDB,$ A( K, 1 ), LDA )CT = HALF*AKKCALL DAXPY( K-1, CT, B( K, 1 ), LDB, A( K, 1 ), LDA )CALL DSYR2( UPLO, K-1, ONE, A( K, 1 ), LDA, B( K, 1 ),$ LDB, A, LDA )CALL DAXPY( K-1, CT, B( K, 1 ), LDB, A( K, 1 ), LDA )CALL DSCAL( K-1, BKK, A( K, 1 ), LDA )A( K, K ) = AKK*BKK**240 CONTINUEEND IFEND IFRETURN** End of DSYGS2*ENDSUBROUTINE DSYGST( ITYPE, UPLO, N, A, LDA, B, LDB, INFO )** -- LAPACK routine (version 3.0) --* Univ. of Tennessee, Univ. of California Berkeley, NAG Ltd.,* Courant Institute, Argonne National Lab, and Rice University* September 30, 1994** .. Scalar Arguments ..CHARACTER UPLOINTEGER INFO, ITYPE, LDA, LDB, N* ..* .. Array Arguments ..DOUBLE PRECISION A( LDA, * ), B( LDB, * )* ..** Purpose* =======** DSYGST reduces a real symmetric-definite generalized eigenproblem* to standard form.** If ITYPE = 1, the problem is A*x = lambda*B*x,* and A is overwritten by inv(U**T)*A*inv(U) or inv(L)*A*inv(L**T)** If ITYPE = 2 or 3, the problem is A*B*x = lambda*x or* B*A*x = lambda*x, and A is overwritten by U*A*U**T or L**T*A*L.** B must have been previously factorized as U**T*U or L*L**T by DPOTRF.** Arguments* =========** ITYPE (input) INTEGER* = 1: compute inv(U**T)*A*inv(U) or inv(L)*A*inv(L**T);* = 2 or 3: compute U*A*U**T or L**T*A*L.** UPLO (input) CHARACTER* = 'U': Upper triangle of A is stored and B is factored as* U**T*U;* = 'L': Lower triangle of A is stored and B is factored as* L*L**T.** N (input) INTEGER* The order of the matrices A and B. 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 INFO = 0, the transformed matrix, stored in the* same format as A.** LDA (input) INTEGER* The leading dimension of the array A. LDA >= max(1,N).** B (input) DOUBLE PRECISION array, dimension (LDB,N)* The triangular factor from the Cholesky factorization of B,* as returned by DPOTRF.** 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, HALFPARAMETER ( ONE = 1.0D0, HALF = 0.5D0 )* ..* .. Local Scalars ..LOGICAL UPPERINTEGER K, KB, NB* ..* .. External Subroutines ..EXTERNAL DSYGS2, DSYMM, DSYR2K, DTRMM, DTRSM, XERBLA* ..* .. Intrinsic Functions ..INTRINSIC MAX, MIN* ..* .. External Functions ..LOGICAL LSAMEINTEGER ILAENVEXTERNAL LSAME, ILAENV* ..* .. Executable Statements ..** Test the input parameters.*INFO = 0UPPER = LSAME( UPLO, 'U' )IF( ITYPE.LT.1 .OR. ITYPE.GT.3 ) THENINFO = -1ELSE IF( .NOT.UPPER .AND. .NOT.LSAME( UPLO, 'L' ) ) THENINFO = -2ELSE IF( N.LT.0 ) THENINFO = -3ELSE IF( LDA.LT.MAX( 1, N ) ) THENINFO = -5ELSE IF( LDB.LT.MAX( 1, N ) ) THENINFO = -7END IFIF( INFO.NE.0 ) THENCALL XERBLA( 'DSYGST', -INFO )RETURNEND IF** Quick return if possible*IF( N.EQ.0 )$ RETURN** Determine the block size for this environment.*NB = ILAENV( 1, 'DSYGST', UPLO, N, -1, -1, -1 )*IF( NB.LE.1 .OR. NB.GE.N ) THEN** Use unblocked code*CALL DSYGS2( ITYPE, UPLO, N, A, LDA, B, LDB, INFO )ELSE** Use blocked code*IF( ITYPE.EQ.1 ) THENIF( UPPER ) THEN** Compute inv(U')*A*inv(U)*DO 10 K = 1, N, NBKB = MIN( N-K+1, NB )** Update the upper triangle of A(k:n,k:n)*CALL DSYGS2( ITYPE, UPLO, KB, A( K, K ), LDA,$ B( K, K ), LDB, INFO )IF( K+KB.LE.N ) THENCALL DTRSM( 'Left', UPLO, 'Transpose', 'Non-unit',$ KB, N-K-KB+1, ONE, B( K, K ), LDB,$ A( K, K+KB ), LDA )CALL DSYMM( 'Left', UPLO, KB, N-K-KB+1, -HALF,$ A( K, K ), LDA, B( K, K+KB ), LDB, ONE,$ A( K, K+KB ), LDA )CALL DSYR2K( UPLO, 'Transpose', N-K-KB+1, KB, -ONE,$ A( K, K+KB ), LDA, B( K, K+KB ), LDB,$ ONE, A( K+KB, K+KB ), LDA )CALL DSYMM( 'Left', UPLO, KB, N-K-KB+1, -HALF,$ A( K, K ), LDA, B( K, K+KB ), LDB, ONE,$ A( K, K+KB ), LDA )CALL DTRSM( 'Right', UPLO, 'No transpose',$ 'Non-unit', KB, N-K-KB+1, ONE,$ B( K+KB, K+KB ), LDB, A( K, K+KB ),$ LDA )END IF10 CONTINUEELSE** Compute inv(L)*A*inv(L')*DO 20 K = 1, N, NBKB = MIN( N-K+1, NB )** Update the lower triangle of A(k:n,k:n)*CALL DSYGS2( ITYPE, UPLO, KB, A( K, K ), LDA,$ B( K, K ), LDB, INFO )IF( K+KB.LE.N ) THENCALL DTRSM( 'Right', UPLO, 'Transpose', 'Non-unit',$ N-K-KB+1, KB, ONE, B( K, K ), LDB,$ A( K+KB, K ), LDA )CALL DSYMM( 'Right', UPLO, N-K-KB+1, KB, -HALF,$ A( K, K ), LDA, B( K+KB, K ), LDB, ONE,$ A( K+KB, K ), LDA )CALL DSYR2K( UPLO, 'No transpose', N-K-KB+1, KB,$ -ONE, A( K+KB, K ), LDA, B( K+KB, K ),$ LDB, ONE, A( K+KB, K+KB ), LDA )CALL DSYMM( 'Right', UPLO, N-K-KB+1, KB, -HALF,$ A( K, K ), LDA, B( K+KB, K ), LDB, ONE,$ A( K+KB, K ), LDA )CALL DTRSM( 'Left', UPLO, 'No transpose',$ 'Non-unit', N-K-KB+1, KB, ONE,$ B( K+KB, K+KB ), LDB, A( K+KB, K ),$ LDA )END IF20 CONTINUEEND IFELSEIF( UPPER ) THEN** Compute U*A*U'*DO 30 K = 1, N, NBKB = MIN( N-K+1, NB )** Update the upper triangle of A(1:k+kb-1,1:k+kb-1)*CALL DTRMM( 'Left', UPLO, 'No transpose', 'Non-unit',$ K-1, KB, ONE, B, LDB, A( 1, K ), LDA )CALL DSYMM( 'Right', UPLO, K-1, KB, HALF, A( K, K ),$ LDA, B( 1, K ), LDB, ONE, A( 1, K ), LDA )CALL DSYR2K( UPLO, 'No transpose', K-1, KB, ONE,$ A( 1, K ), LDA, B( 1, K ), LDB, ONE, A,$ LDA )CALL DSYMM( 'Right', UPLO, K-1, KB, HALF, A( K, K ),$ LDA, B( 1, K ), LDB, ONE, A( 1, K ), LDA )CALL DTRMM( 'Right', UPLO, 'Transpose', 'Non-unit',$ K-1, KB, ONE, B( K, K ), LDB, A( 1, K ),$ LDA )CALL DSYGS2( ITYPE, UPLO, KB, A( K, K ), LDA,$ B( K, K ), LDB, INFO )30 CONTINUEELSE** Compute L'*A*L*DO 40 K = 1, N, NBKB = MIN( N-K+1, NB )** Update the lower triangle of A(1:k+kb-1,1:k+kb-1)*CALL DTRMM( 'Right', UPLO, 'No transpose', 'Non-unit',$ KB, K-1, ONE, B, LDB, A( K, 1 ), LDA )CALL DSYMM( 'Left', UPLO, KB, K-1, HALF, A( K, K ),$ LDA, B( K, 1 ), LDB, ONE, A( K, 1 ), LDA )CALL DSYR2K( UPLO, 'Transpose', K-1, KB, ONE,$ A( K, 1 ), LDA, B( K, 1 ), LDB, ONE, A,$ LDA )CALL DSYMM( 'Left', UPLO, KB, K-1, HALF, A( K, K ),$ LDA, B( K, 1 ), LDB, ONE, A( K, 1 ), LDA )CALL DTRMM( 'Left', UPLO, 'Transpose', 'Non-unit', KB,$ K-1, ONE, B( K, K ), LDB, A( K, 1 ), LDA )CALL DSYGS2( ITYPE, UPLO, KB, A( K, K ), LDA,$ B( K, K ), LDB, INFO )40 CONTINUEEND IFEND IFEND IFRETURN** End of DSYGST*ENDSUBROUTINE DSYRFS( UPLO, N, NRHS, A, LDA, AF, LDAF, IPIV, B, LDB,$ X, LDX, FERR, BERR, WORK, IWORK, INFO )** -- LAPACK routine (version 3.0) --* Univ. of Tennessee, Univ. of California Berkeley, NAG Ltd.,* Courant Institute, Argonne National Lab, and Rice University* September 30, 1994** .. Scalar Arguments ..CHARACTER UPLOINTEGER INFO, LDA, LDAF, LDB, LDX, N, NRHS* ..* .. Array Arguments ..INTEGER IPIV( * ), IWORK( * )DOUBLE PRECISION A( LDA, * ), AF( LDAF, * ), B( LDB, * ),$ BERR( * ), FERR( * ), WORK( * ), X( LDX, * )* ..** Purpose* =======** DSYRFS improves the computed solution to a system of linear* equations when the coefficient matrix is symmetric indefinite, and* provides error bounds and backward error estimates for the solution.** 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.** NRHS (input) INTEGER* The number of right hand sides, i.e., the number of columns* of the matrices B and X. NRHS >= 0.** 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(1,N).** AF (input) DOUBLE PRECISION array, dimension (LDAF,N)* The factored form of the matrix A. AF contains the block* diagonal matrix D and the multipliers used to obtain the* factor U or L from the factorization A = U*D*U**T or* A = L*D*L**T as computed by DSYTRF.** LDAF (input) INTEGER* The leading dimension of the array AF. LDAF >= max(1,N).** IPIV (input) INTEGER array, dimension (N)* Details of the interchanges and the block structure of D* as determined by DSYTRF.** B (input) DOUBLE PRECISION array, dimension (LDB,NRHS)* The right hand side matrix B.** LDB (input) INTEGER* The leading dimension of the array B. LDB >= max(1,N).** X (input/output) DOUBLE PRECISION array, dimension (LDX,NRHS)* On entry, the solution matrix X, as computed by DSYTRS.* On exit, the improved solution matrix X.** LDX (input) INTEGER* The leading dimension of the array X. LDX >= max(1,N).** FERR (output) DOUBLE PRECISION array, dimension (NRHS)* The estimated forward error bound for each solution vector* X(j) (the j-th column of the solution matrix X).* If XTRUE is the true solution corresponding to X(j), FERR(j)* is an estimated upper bound for the magnitude of the largest* element in (X(j) - XTRUE) divided by the magnitude of the* largest element in X(j). The estimate is as reliable as* the estimate for RCOND, and is almost always a slight* overestimate of the true error.** BERR (output) DOUBLE PRECISION array, dimension (NRHS)* The componentwise relative backward error of each solution* vector X(j) (i.e., the smallest relative change in* any element of A or B that makes X(j) an exact solution).** WORK (workspace) DOUBLE PRECISION array, dimension (3*N)** IWORK (workspace) INTEGER array, dimension (N)** INFO (output) INTEGER* = 0: successful exit* < 0: if INFO = -i, the i-th argument had an illegal value** Internal Parameters* ===================** ITMAX is the maximum number of steps of iterative refinement.** =====================================================================** .. Parameters ..INTEGER ITMAXPARAMETER ( ITMAX = 5 )DOUBLE PRECISION ZEROPARAMETER ( ZERO = 0.0D+0 )DOUBLE PRECISION ONEPARAMETER ( ONE = 1.0D+0 )DOUBLE PRECISION TWOPARAMETER ( TWO = 2.0D+0 )DOUBLE PRECISION THREEPARAMETER ( THREE = 3.0D+0 )* ..* .. Local Scalars ..LOGICAL UPPERINTEGER COUNT, I, J, K, KASE, NZDOUBLE PRECISION EPS, LSTRES, S, SAFE1, SAFE2, SAFMIN, XK* ..* .. External Subroutines ..EXTERNAL DAXPY, DCOPY, DLACON, DSYMV, DSYTRS, XERBLA* ..* .. Intrinsic Functions ..INTRINSIC ABS, MAX* ..* .. External Functions ..LOGICAL LSAMEDOUBLE PRECISION DLAMCHEXTERNAL LSAME, DLAMCH* ..* .. Executable Statements ..** Test the input parameters.*INFO = 0UPPER = LSAME( UPLO, 'U' )IF( .NOT.UPPER .AND. .NOT.LSAME( UPLO, 'L' ) ) THENINFO = -1ELSE IF( N.LT.0 ) THENINFO = -2ELSE IF( NRHS.LT.0 ) THENINFO = -3ELSE IF( LDA.LT.MAX( 1, N ) ) THENINFO = -5ELSE IF( LDAF.LT.MAX( 1, N ) ) THENINFO = -7ELSE IF( LDB.LT.MAX( 1, N ) ) THENINFO = -10ELSE IF( LDX.LT.MAX( 1, N ) ) THENINFO = -12END IFIF( INFO.NE.0 ) THENCALL XERBLA( 'DSYRFS', -INFO )RETURNEND IF** Quick return if possible*IF( N.EQ.0 .OR. NRHS.EQ.0 ) THENDO 10 J = 1, NRHSFERR( J ) = ZEROBERR( J ) = ZERO10 CONTINUERETURNEND IF** NZ = maximum number of nonzero elements in each row of A, plus 1*NZ = N + 1EPS = DLAMCH( 'Epsilon' )SAFMIN = DLAMCH( 'Safe minimum' )SAFE1 = NZ*SAFMINSAFE2 = SAFE1 / EPS** Do for each right hand side*DO 140 J = 1, NRHS*COUNT = 1LSTRES = THREE20 CONTINUE** Loop until stopping criterion is satisfied.** Compute residual R = B - A * X*CALL DCOPY( N, B( 1, J ), 1, WORK( N+1 ), 1 )CALL DSYMV( UPLO, N, -ONE, A, LDA, X( 1, J ), 1, ONE,$ WORK( N+1 ), 1 )** Compute componentwise relative backward error from formula** max(i) ( abs(R(i)) / ( abs(A)*abs(X) + abs(B) )(i) )** where abs(Z) is the componentwise absolute value of the matrix* or vector Z. If the i-th component of the denominator is less* than SAFE2, then SAFE1 is added to the i-th components of the* numerator and denominator before dividing.*DO 30 I = 1, NWORK( I ) = ABS( B( I, J ) )30 CONTINUE** Compute abs(A)*abs(X) + abs(B).*IF( UPPER ) THENDO 50 K = 1, NS = ZEROXK = ABS( X( K, J ) )DO 40 I = 1, K - 1WORK( I ) = WORK( I ) + ABS( A( I, K ) )*XKS = S + ABS( A( I, K ) )*ABS( X( I, J ) )40 CONTINUEWORK( K ) = WORK( K ) + ABS( A( K, K ) )*XK + S50 CONTINUEELSEDO 70 K = 1, NS = ZEROXK = ABS( X( K, J ) )WORK( K ) = WORK( K ) + ABS( A( K, K ) )*XKDO 60 I = K + 1, NWORK( I ) = WORK( I ) + ABS( A( I, K ) )*XKS = S + ABS( A( I, K ) )*ABS( X( I, J ) )60 CONTINUEWORK( K ) = WORK( K ) + S70 CONTINUEEND IFS = ZERODO 80 I = 1, NIF( WORK( I ).GT.SAFE2 ) THENS = MAX( S, ABS( WORK( N+I ) ) / WORK( I ) )ELSES = MAX( S, ( ABS( WORK( N+I ) )+SAFE1 ) /$ ( WORK( I )+SAFE1 ) )END IF80 CONTINUEBERR( J ) = S** Test stopping criterion. Continue iterating if* 1) The residual BERR(J) is larger than machine epsilon, and* 2) BERR(J) decreased by at least a factor of 2 during the* last iteration, and* 3) At most ITMAX iterations tried.*IF( BERR( J ).GT.EPS .AND. TWO*BERR( J ).LE.LSTRES .AND.$ COUNT.LE.ITMAX ) THEN** Update solution and try again.*CALL DSYTRS( UPLO, N, 1, AF, LDAF, IPIV, WORK( N+1 ), N,$ INFO )CALL DAXPY( N, ONE, WORK( N+1 ), 1, X( 1, J ), 1 )LSTRES = BERR( J )COUNT = COUNT + 1GO TO 20END IF** Bound error from formula** norm(X - XTRUE) / norm(X) .le. FERR =* norm( abs(inv(A))** ( abs(R) + NZ*EPS*( abs(A)*abs(X)+abs(B) ))) / norm(X)** where* norm(Z) is the magnitude of the largest component of Z* inv(A) is the inverse of A* abs(Z) is the componentwise absolute value of the matrix or* vector Z* NZ is the maximum number of nonzeros in any row of A, plus 1* EPS is machine epsilon** The i-th component of abs(R)+NZ*EPS*(abs(A)*abs(X)+abs(B))* is incremented by SAFE1 if the i-th component of* abs(A)*abs(X) + abs(B) is less than SAFE2.** Use DLACON to estimate the infinity-norm of the matrix* inv(A) * diag(W),* where W = abs(R) + NZ*EPS*( abs(A)*abs(X)+abs(B) )))*DO 90 I = 1, NIF( WORK( I ).GT.SAFE2 ) THENWORK( I ) = ABS( WORK( N+I ) ) + NZ*EPS*WORK( I )ELSEWORK( I ) = ABS( WORK( N+I ) ) + NZ*EPS*WORK( I ) + SAFE1END IF90 CONTINUE*KASE = 0100 CONTINUECALL DLACON( N, WORK( 2*N+1 ), WORK( N+1 ), IWORK, FERR( J ),$ KASE )IF( KASE.NE.0 ) THENIF( KASE.EQ.1 ) THEN** Multiply by diag(W)*inv(A').*CALL DSYTRS( UPLO, N, 1, AF, LDAF, IPIV, WORK( N+1 ), N,$ INFO )DO 110 I = 1, NWORK( N+I ) = WORK( I )*WORK( N+I )110 CONTINUEELSE IF( KASE.EQ.2 ) THEN** Multiply by inv(A)*diag(W).*DO 120 I = 1, NWORK( N+I ) = WORK( I )*WORK( N+I )120 CONTINUECALL DSYTRS( UPLO, N, 1, AF, LDAF, IPIV, WORK( N+1 ), N,$ INFO )END IFGO TO 100END IF** Normalize error.*LSTRES = ZERODO 130 I = 1, NLSTRES = MAX( LSTRES, ABS( X( I, J ) ) )130 CONTINUEIF( LSTRES.NE.ZERO )$ FERR( J ) = FERR( J ) / LSTRES*140 CONTINUE*RETURN** End of DSYRFS*ENDSUBROUTINE DSYTD2( UPLO, N, A, LDA, D, E, TAU, INFO )** -- LAPACK routine (version 3.0) --* Univ. of Tennessee, Univ. of California Berkeley, NAG Ltd.,* Courant Institute, Argonne National Lab, and Rice University* October 31, 1992** .. Scalar Arguments ..CHARACTER UPLOINTEGER 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, HALFPARAMETER ( ONE = 1.0D0, ZERO = 0.0D0,$ HALF = 1.0D0 / 2.0D0 )* ..* .. Local Scalars ..LOGICAL UPPERINTEGER IDOUBLE PRECISION ALPHA, TAUI* ..* .. External Subroutines ..EXTERNAL DAXPY, DLARFG, DSYMV, DSYR2, XERBLA* ..* .. External Functions ..LOGICAL LSAMEDOUBLE PRECISION DDOTEXTERNAL LSAME, DDOT* ..* .. Intrinsic Functions ..INTRINSIC MAX, MIN* ..* .. Executable Statements ..** Test the input parameters*INFO = 0UPPER = LSAME( UPLO, 'U' )IF( .NOT.UPPER .AND. .NOT.LSAME( UPLO, 'L' ) ) THENINFO = -1ELSE IF( N.LT.0 ) THENINFO = -2ELSE IF( LDA.LT.MAX( 1, N ) ) THENINFO = -4END IFIF( INFO.NE.0 ) THENCALL XERBLA( 'DSYTD2', -INFO )RETURNEND 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 IFD( I+1 ) = A( I+1, I+1 )TAU( I ) = TAUI10 CONTINUED( 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 IFD( I ) = A( I, I )TAU( I ) = TAUI20 CONTINUED( N ) = A( N, N )END IF*RETURN** End of DSYTD2*ENDSUBROUTINE DSYTF2( UPLO, N, A, LDA, IPIV, INFO )** -- LAPACK routine (version 3.0) --* Univ. of Tennessee, Univ. of California Berkeley, NAG Ltd.,* Courant Institute, Argonne National Lab, and Rice University* June 30, 1999** .. Scalar Arguments ..CHARACTER UPLOINTEGER 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* ===============** 1-96 - Based on modifications by J. Lewis, Boeing Computer Services* Company** 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, ONEPARAMETER ( ZERO = 0.0D+0, ONE = 1.0D+0 )DOUBLE PRECISION EIGHT, SEVTENPARAMETER ( EIGHT = 8.0D+0, SEVTEN = 17.0D+0 )* ..* .. Local Scalars ..LOGICAL UPPERINTEGER I, IMAX, J, JMAX, K, KK, KP, KSTEPDOUBLE PRECISION ABSAKK, ALPHA, COLMAX, D11, D12, D21, D22, R1,$ ROWMAX, T, WK, WKM1, WKP1* ..* .. External Functions ..LOGICAL LSAMEINTEGER IDAMAXEXTERNAL LSAME, IDAMAX* ..* .. External Subroutines ..EXTERNAL DSCAL, DSWAP, DSYR, XERBLA* ..* .. Intrinsic Functions ..INTRINSIC ABS, MAX, SQRT* ..* .. Executable Statements ..** Test the input parameters.*INFO = 0UPPER = LSAME( UPLO, 'U' )IF( .NOT.UPPER .AND. .NOT.LSAME( UPLO, 'L' ) ) THENINFO = -1ELSE IF( N.LT.0 ) THENINFO = -2ELSE IF( LDA.LT.MAX( 1, N ) ) THENINFO = -4END IFIF( INFO.NE.0 ) THENCALL XERBLA( 'DSYTF2', -INFO )RETURNEND 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 = N10 CONTINUE** If K < 1, exit from loop*IF( K.LT.1 )$ GO TO 70KSTEP = 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 ) THENIMAX = IDAMAX( K-1, A( 1, K ), 1 )COLMAX = ABS( A( IMAX, K ) )ELSECOLMAX = ZEROEND IF*IF( MAX( ABSAKK, COLMAX ).EQ.ZERO ) THEN** Column K is zero: set INFO and continue*IF( INFO.EQ.0 )$ INFO = KKP = KELSEIF( ABSAKK.GE.ALPHA*COLMAX ) THEN** no interchange, use 1-by-1 pivot block*KP = KELSE** 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 ) THENJMAX = 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 = KELSE IF( ABS( A( IMAX, IMAX ) ).GE.ALPHA*ROWMAX ) THEN** interchange rows and columns K and IMAX, use 1-by-1* pivot block*KP = IMAXELSE** interchange rows and columns K-1 and IMAX, use 2-by-2* pivot block*KP = IMAXKSTEP = 2END IFEND IF*KK = K - KSTEP + 1IF( 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 ) = TIF( KSTEP.EQ.2 ) THENT = A( K-1, K )A( K-1, K ) = A( KP, K )A( KP, K ) = TEND IFEND 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) )'*IF( K.GT.2 ) THEN*D12 = A( K-1, K )D22 = A( K-1, K-1 ) / D12D11 = A( K, K ) / D12T = ONE / ( D11*D22-ONE )D12 = T / D12*DO 30 J = K - 2, 1, -1WKM1 = D12*( D11*A( J, K-1 )-A( J, K ) )WK = D12*( D22*A( J, K )-A( J, K-1 ) )DO 20 I = J, 1, -1A( I, J ) = A( I, J ) - A( I, K )*WK -$ A( I, K-1 )*WKM120 CONTINUEA( J, K ) = WKA( J, K-1 ) = WKM130 CONTINUE*END IF*END IFEND IF** Store details of the interchanges in IPIV*IF( KSTEP.EQ.1 ) THENIPIV( K ) = KPELSEIPIV( K ) = -KPIPIV( K-1 ) = -KPEND IF** Decrease K and return to the start of the main loop*K = K - KSTEPGO 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 = 140 CONTINUE** If K > N, exit from loop*IF( K.GT.N )$ GO TO 70KSTEP = 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 ) THENIMAX = K + IDAMAX( N-K, A( K+1, K ), 1 )COLMAX = ABS( A( IMAX, K ) )ELSECOLMAX = ZEROEND IF*IF( MAX( ABSAKK, COLMAX ).EQ.ZERO ) THEN** Column K is zero: set INFO and continue*IF( INFO.EQ.0 )$ INFO = KKP = KELSEIF( ABSAKK.GE.ALPHA*COLMAX ) THEN** no interchange, use 1-by-1 pivot block*KP = KELSE** 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 ) THENJMAX = 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 = KELSE IF( ABS( A( IMAX, IMAX ) ).GE.ALPHA*ROWMAX ) THEN** interchange rows and columns K and IMAX, use 1-by-1* pivot block*KP = IMAXELSE** interchange rows and columns K+1 and IMAX, use 2-by-2* pivot block*KP = IMAXKSTEP = 2END IFEND IF*KK = K + KSTEP - 1IF( 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 ) = TIF( KSTEP.EQ.2 ) THENT = A( K+1, K )A( K+1, K ) = A( KP, K )A( KP, K ) = TEND IFEND 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)'*D11 = ONE / A( K, K )CALL DSYR( UPLO, N-K, -D11, A( K+1, K ), 1,$ A( K+1, K+1 ), LDA )** Store L(k) in column K*CALL DSCAL( N-K, D11, A( K+1, K ), 1 )END IFELSE** 2-by-2 pivot block D(k)*IF( K.LT.N-1 ) THEN** Perform a rank-2 update of A(k+2:n,k+2:n) as** A := A - ( (A(k) A(k+1))*D(k)**(-1) ) * (A(k) A(k+1))'** where L(k) and L(k+1) are the k-th and (k+1)-th* columns of L*D21 = A( K+1, K )D11 = A( K+1, K+1 ) / D21D22 = A( K, K ) / D21T = ONE / ( D11*D22-ONE )D21 = T / D21*DO 60 J = K + 2, N*WK = D21*( D11*A( J, K )-A( J, K+1 ) )WKP1 = D21*( D22*A( J, K+1 )-A( J, K ) )*DO 50 I = J, NA( I, J ) = A( I, J ) - A( I, K )*WK -$ A( I, K+1 )*WKP150 CONTINUE*A( J, K ) = WKA( J, K+1 ) = WKP1*60 CONTINUEEND IFEND IFEND IF** Store details of the interchanges in IPIV*IF( KSTEP.EQ.1 ) THENIPIV( K ) = KPELSEIPIV( K ) = -KPIPIV( K+1 ) = -KPEND IF** Increase K and return to the start of the main loop*K = K + KSTEPGO TO 40*END IF*70 CONTINUE*RETURN** End of DSYTF2*ENDSUBROUTINE DSYTRD( UPLO, N, A, LDA, D, E, TAU, WORK, LWORK, INFO )** -- LAPACK routine (version 3.0) --* Univ. of Tennessee, Univ. of California Berkeley, NAG Ltd.,* Courant Institute, Argonne National Lab, and Rice University* June 30, 1999** .. Scalar Arguments ..CHARACTER UPLOINTEGER 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/output) 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.** If LWORK = -1, then a workspace query is assumed; the routine* only calculates the optimal size of the WORK array, returns* this value as the first entry of the WORK array, and no error* message related to LWORK is issued by XERBLA.** 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 ONEPARAMETER ( ONE = 1.0D+0 )* ..* .. Local Scalars ..LOGICAL LQUERY, UPPERINTEGER I, IINFO, IWS, J, KK, LDWORK, LWKOPT, NB,$ NBMIN, NX* ..* .. External Subroutines ..EXTERNAL DLATRD, DSYR2K, DSYTD2, XERBLA* ..* .. Intrinsic Functions ..INTRINSIC MAX* ..* .. External Functions ..LOGICAL LSAMEINTEGER ILAENVEXTERNAL LSAME, ILAENV* ..* .. Executable Statements ..** Test the input parameters*INFO = 0UPPER = LSAME( UPLO, 'U' )LQUERY = ( LWORK.EQ.-1 )IF( .NOT.UPPER .AND. .NOT.LSAME( UPLO, 'L' ) ) THENINFO = -1ELSE IF( N.LT.0 ) THENINFO = -2ELSE IF( LDA.LT.MAX( 1, N ) ) THENINFO = -4ELSE IF( LWORK.LT.1 .AND. .NOT.LQUERY ) THENINFO = -9END IF*IF( INFO.EQ.0 ) THEN** Determine the block size.*NB = ILAENV( 1, 'DSYTRD', UPLO, N, -1, -1, -1 )LWKOPT = N*NBWORK( 1 ) = LWKOPTEND IF*IF( INFO.NE.0 ) THENCALL XERBLA( 'DSYTRD', -INFO )RETURNELSE IF( LQUERY ) THENRETURNEND IF** Quick return if possible*IF( N.EQ.0 ) THENWORK( 1 ) = 1RETURNEND IF*NX = NIWS = 1IF( 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 = NIWS = LDWORK*NBIF( 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 = MAX( LWORK / LDWORK, 1 )NBMIN = ILAENV( 2, 'DSYTRD', UPLO, N, -1, -1, -1 )IF( NB.LT.NBMIN )$ NX = NEND IFELSENX = NEND IFELSENB = 1END 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 )*NBDO 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 - 1A( J-1, J ) = E( J-1 )D( J ) = A( J, J )10 CONTINUE20 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 - 1A( J+1, J ) = E( J )D( J ) = A( J, J )30 CONTINUE40 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 ) = LWKOPTRETURN** End of DSYTRD*ENDSUBROUTINE DSYTRF( UPLO, N, A, LDA, IPIV, WORK, LWORK, INFO )** -- LAPACK routine (version 3.0) --* Univ. of Tennessee, Univ. of California Berkeley, NAG Ltd.,* Courant Institute, Argonne National Lab, and Rice University* June 30, 1999** .. Scalar Arguments ..CHARACTER UPLOINTEGER INFO, LDA, LWORK, N* ..* .. Array Arguments ..INTEGER IPIV( * )DOUBLE PRECISION A( LDA, * ), WORK( * )* ..** Purpose* =======** DSYTRF computes the factorization of a real symmetric matrix A using* the Bunch-Kaufman diagonal pivoting method. The form of the* factorization is** A = U*D*U**T or A = L*D*L**T** where U (or L) is a product of permutation and unit upper (lower)* triangular matrices, 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* = '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, 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/output) DOUBLE PRECISION array, dimension (LWORK)* On exit, if INFO = 0, WORK(1) returns the optimal LWORK.** LWORK (input) INTEGER* The length of WORK. LWORK >=1. For best performance* LWORK >= N*NB, where NB is the block size returned by ILAENV.** If LWORK = -1, then a workspace query is assumed; the routine* only calculates the optimal size of the WORK array, returns* this value as the first entry of the WORK array, and no error* message related to LWORK is issued by XERBLA.** INFO (output) INTEGER* = 0: successful exit* < 0: if INFO = -i, the i-th argument had an illegal value* > 0: if INFO = i, D(i,i) 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 LQUERY, UPPERINTEGER IINFO, IWS, J, K, KB, LDWORK, LWKOPT, NB, NBMIN* ..* .. External Functions ..LOGICAL LSAMEINTEGER ILAENVEXTERNAL LSAME, ILAENV* ..* .. External Subroutines ..EXTERNAL DLASYF, DSYTF2, XERBLA* ..* .. Intrinsic Functions ..INTRINSIC MAX* ..* .. Executable Statements ..** Test the input parameters.*INFO = 0UPPER = LSAME( UPLO, 'U' )LQUERY = ( LWORK.EQ.-1 )IF( .NOT.UPPER .AND. .NOT.LSAME( UPLO, 'L' ) ) THENINFO = -1ELSE IF( N.LT.0 ) THENINFO = -2ELSE IF( LDA.LT.MAX( 1, N ) ) THENINFO = -4ELSE IF( LWORK.LT.1 .AND. .NOT.LQUERY ) THENINFO = -7END IF*IF( INFO.EQ.0 ) THEN** Determine the block size*NB = ILAENV( 1, 'DSYTRF', UPLO, N, -1, -1, -1 )LWKOPT = N*NBWORK( 1 ) = LWKOPTEND IF*IF( INFO.NE.0 ) THENCALL XERBLA( 'DSYTRF', -INFO )RETURNELSE IF( LQUERY ) THENRETURNEND IF*NBMIN = 2LDWORK = NIF( NB.GT.1 .AND. NB.LT.N ) THENIWS = LDWORK*NBIF( LWORK.LT.IWS ) THENNB = MAX( LWORK / LDWORK, 1 )NBMIN = MAX( 2, ILAENV( 2, 'DSYTRF', UPLO, N, -1, -1, -1 ) )END IFELSEIWS = 1END IFIF( 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 = N10 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 = KEND 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 - KBGO 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 = 120 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 + 1END 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 - 1IF( IPIV( J ).GT.0 ) THENIPIV( J ) = IPIV( J ) + K - 1ELSEIPIV( J ) = IPIV( J ) - K + 1END IF30 CONTINUE** Increase K and return to the start of the main loop*K = K + KBGO TO 20*END IF*40 CONTINUEWORK( 1 ) = LWKOPTRETURN** End of DSYTRF*ENDSUBROUTINE DSYTRI( UPLO, N, A, LDA, IPIV, WORK, INFO )** -- LAPACK routine (version 3.0) --* Univ. of Tennessee, Univ. of California Berkeley, NAG Ltd.,* Courant Institute, Argonne National Lab, and Rice University* March 31, 1993** .. Scalar Arguments ..CHARACTER UPLOINTEGER 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**T or A = L*D*L**T 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**T;* = 'L': Lower triangular, form is A = L*D*L**T.** 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 = -i, the i-th argument had an illegal value* > 0: if INFO = i, D(i,i) = 0; the matrix is singular and its* inverse could not be computed.** =====================================================================** .. Parameters ..DOUBLE PRECISION ONE, ZEROPARAMETER ( ONE = 1.0D+0, ZERO = 0.0D+0 )* ..* .. Local Scalars ..LOGICAL UPPERINTEGER K, KP, KSTEPDOUBLE PRECISION AK, AKKP1, AKP1, D, T, TEMP* ..* .. External Functions ..LOGICAL LSAMEDOUBLE PRECISION DDOTEXTERNAL LSAME, DDOT* ..* .. External Subroutines ..EXTERNAL DCOPY, DSWAP, DSYMV, XERBLA* ..* .. Intrinsic Functions ..INTRINSIC ABS, MAX* ..* .. Executable Statements ..** Test the input parameters.*INFO = 0UPPER = LSAME( UPLO, 'U' )IF( .NOT.UPPER .AND. .NOT.LSAME( UPLO, 'L' ) ) THENINFO = -1ELSE IF( N.LT.0 ) THENINFO = -2ELSE IF( LDA.LT.MAX( 1, N ) ) THENINFO = -4END IFIF( INFO.NE.0 ) THENCALL XERBLA( 'DSYTRI', -INFO )RETURNEND 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, -1IF( IPIV( INFO ).GT.0 .AND. A( INFO, INFO ).EQ.ZERO )$ RETURN10 CONTINUEELSE** Lower triangular storage: examine D from top to bottom.*DO 20 INFO = 1, NIF( IPIV( INFO ).GT.0 .AND. A( INFO, INFO ).EQ.ZERO )$ RETURN20 CONTINUEEND IFINFO = 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 = 130 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 ) THENCALL 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 IFKSTEP = 1ELSE** 2 x 2 diagonal block** Invert the diagonal block.*T = ABS( A( K, K+1 ) )AK = A( K, K ) / TAKP1 = A( K+1, K+1 ) / TAKKP1 = A( K, K+1 ) / TD = T*( AK*AKP1-ONE )A( K, K ) = AKP1 / DA( K+1, K+1 ) = AK / DA( K, K+1 ) = -AKKP1 / D** Compute columns K and K+1 of the inverse.*IF( K.GT.1 ) THENCALL 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 IFKSTEP = 2END 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 ) = TEMPIF( KSTEP.EQ.2 ) THENTEMP = A( K, K+1 )A( K, K+1 ) = A( KP, K+1 )A( KP, K+1 ) = TEMPEND IFEND IF*K = K + KSTEPGO TO 3040 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 = N50 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 ) THENCALL 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 IFKSTEP = 1ELSE** 2 x 2 diagonal block** Invert the diagonal block.*T = ABS( A( K, K-1 ) )AK = A( K-1, K-1 ) / TAKP1 = A( K, K ) / TAKKP1 = A( K, K-1 ) / TD = T*( AK*AKP1-ONE )A( K-1, K-1 ) = AKP1 / DA( K, K ) = AK / DA( K, K-1 ) = -AKKP1 / D** Compute columns K-1 and K of the inverse.*IF( K.LT.N ) THENCALL 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 IFKSTEP = 2END 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 ) = TEMPIF( KSTEP.EQ.2 ) THENTEMP = A( K, K-1 )A( K, K-1 ) = A( KP, K-1 )A( KP, K-1 ) = TEMPEND IFEND IF*K = K - KSTEPGO TO 5060 CONTINUEEND IF*RETURN** End of DSYTRI*ENDSUBROUTINE DSYTRS( UPLO, N, NRHS, A, LDA, IPIV, B, LDB, INFO )** -- LAPACK routine (version 3.0) --* Univ. of Tennessee, Univ. of California Berkeley, NAG Ltd.,* Courant Institute, Argonne National Lab, and Rice University* March 31, 1993** .. Scalar Arguments ..CHARACTER UPLOINTEGER INFO, LDA, LDB, N, NRHS* ..* .. Array Arguments ..INTEGER IPIV( * )DOUBLE PRECISION A( LDA, * ), B( LDB, * )* ..** Purpose* =======** DSYTRS solves a system of linear equations A*X = B with a real* symmetric matrix A using the factorization A = U*D*U**T or* A = L*D*L**T 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**T;* = 'L': Lower triangular, form is A = L*D*L**T.** 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 block diagonal matrix D and the multipliers used to* obtain the factor U or L as computed by DSYTRF.** 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.** 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 ONEPARAMETER ( ONE = 1.0D+0 )* ..* .. Local Scalars ..LOGICAL UPPERINTEGER J, K, KPDOUBLE PRECISION AK, AKM1, AKM1K, BK, BKM1, DENOM* ..* .. External Functions ..LOGICAL LSAMEEXTERNAL LSAME* ..* .. External Subroutines ..EXTERNAL DGEMV, DGER, DSCAL, DSWAP, XERBLA* ..* .. Intrinsic Functions ..INTRINSIC MAX* ..* .. Executable Statements ..*INFO = 0UPPER = LSAME( UPLO, 'U' )IF( .NOT.UPPER .AND. .NOT.LSAME( UPLO, 'L' ) ) THENINFO = -1ELSE IF( N.LT.0 ) THENINFO = -2ELSE IF( NRHS.LT.0 ) THENINFO = -3ELSE IF( LDA.LT.MAX( 1, N ) ) THENINFO = -5ELSE IF( LDB.LT.MAX( 1, N ) ) THENINFO = -8END IFIF( INFO.NE.0 ) THENCALL XERBLA( 'DSYTRS', -INFO )RETURNEND IF** Quick return if possible*IF( N.EQ.0 .OR. NRHS.EQ.0 )$ RETURN*IF( UPPER ) THEN** Solve A*X = B, where A = U*D*U'.** First solve U*D*X = B, overwriting B with X.** K is the main loop index, decreasing from N to 1 in steps of* 1 or 2, depending on the size of the diagonal blocks.*K = N10 CONTINUE** If K < 1, exit from loop.*IF( K.LT.1 )$ GO TO 30*IF( IPIV( K ).GT.0 ) THEN** 1 x 1 diagonal block** Interchange rows K and IPIV(K).*KP = IPIV( K )IF( KP.NE.K )$ CALL DSWAP( NRHS, B( K, 1 ), LDB, B( KP, 1 ), LDB )** Multiply by inv(U(K)), where U(K) is the transformation* stored in column K of A.*CALL DGER( K-1, NRHS, -ONE, A( 1, K ), 1, B( K, 1 ), LDB,$ B( 1, 1 ), LDB )** Multiply by the inverse of the diagonal block.*CALL DSCAL( NRHS, ONE / A( K, K ), B( K, 1 ), LDB )K = K - 1ELSE** 2 x 2 diagonal block** Interchange rows K-1 and -IPIV(K).*KP = -IPIV( K )IF( KP.NE.K-1 )$ CALL DSWAP( NRHS, B( K-1, 1 ), LDB, B( KP, 1 ), LDB )** Multiply by inv(U(K)), where U(K) is the transformation* stored in columns K-1 and K of A.*CALL DGER( K-2, NRHS, -ONE, A( 1, K ), 1, B( K, 1 ), LDB,$ B( 1, 1 ), LDB )CALL DGER( K-2, NRHS, -ONE, A( 1, K-1 ), 1, B( K-1, 1 ),$ LDB, B( 1, 1 ), LDB )** Multiply by the inverse of the diagonal block.*AKM1K = A( K-1, K )AKM1 = A( K-1, K-1 ) / AKM1KAK = A( K, K ) / AKM1KDENOM = AKM1*AK - ONEDO 20 J = 1, NRHSBKM1 = B( K-1, J ) / AKM1KBK = B( K, J ) / AKM1KB( K-1, J ) = ( AK*BKM1-BK ) / DENOMB( K, J ) = ( AKM1*BK-BKM1 ) / DENOM20 CONTINUEK = K - 2END IF*GO TO 1030 CONTINUE** Next solve U'*X = B, overwriting B with X.** 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 = 140 CONTINUE** If K > N, exit from loop.*IF( K.GT.N )$ GO TO 50*IF( IPIV( K ).GT.0 ) THEN** 1 x 1 diagonal block** Multiply by inv(U'(K)), where U(K) is the transformation* stored in column K of A.*CALL DGEMV( 'Transpose', K-1, NRHS, -ONE, B, LDB, A( 1, K ),$ 1, ONE, B( K, 1 ), LDB )** Interchange rows K and IPIV(K).*KP = IPIV( K )IF( KP.NE.K )$ CALL DSWAP( NRHS, B( K, 1 ), LDB, B( KP, 1 ), LDB )K = K + 1ELSE** 2 x 2 diagonal block** Multiply by inv(U'(K+1)), where U(K+1) is the transformation* stored in columns K and K+1 of A.*CALL DGEMV( 'Transpose', K-1, NRHS, -ONE, B, LDB, A( 1, K ),$ 1, ONE, B( K, 1 ), LDB )CALL DGEMV( 'Transpose', K-1, NRHS, -ONE, B, LDB,$ A( 1, K+1 ), 1, ONE, B( K+1, 1 ), LDB )** Interchange rows K and -IPIV(K).*KP = -IPIV( K )IF( KP.NE.K )$ CALL DSWAP( NRHS, B( K, 1 ), LDB, B( KP, 1 ), LDB )K = K + 2END IF*GO TO 4050 CONTINUE*ELSE** Solve A*X = B, where A = L*D*L'.** First solve L*D*X = B, overwriting B with X.** 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 = 160 CONTINUE** If K > N, exit from loop.*IF( K.GT.N )$ GO TO 80*IF( IPIV( K ).GT.0 ) THEN** 1 x 1 diagonal block** Interchange rows K and IPIV(K).*KP = IPIV( K )IF( KP.NE.K )$ CALL DSWAP( NRHS, B( K, 1 ), LDB, B( KP, 1 ), LDB )** Multiply by inv(L(K)), where L(K) is the transformation* stored in column K of A.*IF( K.LT.N )$ CALL DGER( N-K, NRHS, -ONE, A( K+1, K ), 1, B( K, 1 ),$ LDB, B( K+1, 1 ), LDB )** Multiply by the inverse of the diagonal block.*CALL DSCAL( NRHS, ONE / A( K, K ), B( K, 1 ), LDB )K = K + 1ELSE** 2 x 2 diagonal block** Interchange rows K+1 and -IPIV(K).*KP = -IPIV( K )IF( KP.NE.K+1 )$ CALL DSWAP( NRHS, B( K+1, 1 ), LDB, B( KP, 1 ), LDB )** Multiply by inv(L(K)), where L(K) is the transformation* stored in columns K and K+1 of A.*IF( K.LT.N-1 ) THENCALL DGER( N-K-1, NRHS, -ONE, A( K+2, K ), 1, B( K, 1 ),$ LDB, B( K+2, 1 ), LDB )CALL DGER( N-K-1, NRHS, -ONE, A( K+2, K+1 ), 1,$ B( K+1, 1 ), LDB, B( K+2, 1 ), LDB )END IF** Multiply by the inverse of the diagonal block.*AKM1K = A( K+1, K )AKM1 = A( K, K ) / AKM1KAK = A( K+1, K+1 ) / AKM1KDENOM = AKM1*AK - ONEDO 70 J = 1, NRHSBKM1 = B( K, J ) / AKM1KBK = B( K+1, J ) / AKM1KB( K, J ) = ( AK*BKM1-BK ) / DENOMB( K+1, J ) = ( AKM1*BK-BKM1 ) / DENOM70 CONTINUEK = K + 2END IF*GO TO 6080 CONTINUE** Next solve L'*X = B, overwriting B with X.** K is the main loop index, decreasing from N to 1 in steps of* 1 or 2, depending on the size of the diagonal blocks.*K = N90 CONTINUE** If K < 1, exit from loop.*IF( K.LT.1 )$ GO TO 100*IF( IPIV( K ).GT.0 ) THEN** 1 x 1 diagonal block** Multiply by inv(L'(K)), where L(K) is the transformation* stored in column K of A.*IF( K.LT.N )$ CALL DGEMV( 'Transpose', N-K, NRHS, -ONE, B( K+1, 1 ),$ LDB, A( K+1, K ), 1, ONE, B( K, 1 ), LDB )** Interchange rows K and IPIV(K).*KP = IPIV( K )IF( KP.NE.K )$ CALL DSWAP( NRHS, B( K, 1 ), LDB, B( KP, 1 ), LDB )K = K - 1ELSE** 2 x 2 diagonal block** Multiply by inv(L'(K-1)), where L(K-1) is the transformation* stored in columns K-1 and K of A.*IF( K.LT.N ) THENCALL DGEMV( 'Transpose', N-K, NRHS, -ONE, B( K+1, 1 ),$ LDB, A( K+1, K ), 1, ONE, B( K, 1 ), LDB )CALL DGEMV( 'Transpose', N-K, NRHS, -ONE, B( K+1, 1 ),$ LDB, A( K+1, K-1 ), 1, ONE, B( K-1, 1 ),$ LDB )END IF** Interchange rows K and -IPIV(K).*KP = -IPIV( K )IF( KP.NE.K )$ CALL DSWAP( NRHS, B( K, 1 ), LDB, B( KP, 1 ), LDB )K = K - 2END IF*GO TO 90100 CONTINUEEND IF*RETURN** End of DSYTRS*ENDSUBROUTINE DTBCON( NORM, UPLO, DIAG, N, KD, AB, LDAB, RCOND, WORK,$ IWORK, INFO )** -- LAPACK routine (version 3.0) --* Univ. of Tennessee, Univ. of California Berkeley, NAG Ltd.,* Courant Institute, Argonne National Lab, and Rice University* March 31, 1993** .. Scalar Arguments ..CHARACTER DIAG, NORM, UPLOINTEGER INFO, KD, LDAB, NDOUBLE PRECISION RCOND* ..* .. Array Arguments ..INTEGER IWORK( * )DOUBLE PRECISION AB( LDAB, * ), WORK( * )* ..** Purpose* =======** DTBCON estimates the reciprocal of the condition number of a* triangular band matrix A, in either the 1-norm or the infinity-norm.** The norm of A is computed and an estimate is obtained for* norm(inv(A)), then the reciprocal of the condition number is* computed as* RCOND = 1 / ( norm(A) * norm(inv(A)) ).** Arguments* =========** NORM (input) CHARACTER*1* Specifies whether the 1-norm condition number or the* infinity-norm condition number is required:* = '1' or 'O': 1-norm;* = 'I': Infinity-norm.** UPLO (input) CHARACTER*1* = 'U': A is upper triangular;* = 'L': A is lower triangular.** DIAG (input) CHARACTER*1* = 'N': A is non-unit triangular;* = 'U': A is unit triangular.** N (input) INTEGER* The order of the matrix A. N >= 0.** KD (input) INTEGER* The number of superdiagonals or subdiagonals of the* triangular band matrix A. KD >= 0.** AB (input) DOUBLE PRECISION array, dimension (LDAB,N)* The upper or lower triangular band matrix A, stored in the* first kd+1 rows of the array. The j-th column of A is stored* in the j-th column of the array AB as follows:* if UPLO = 'U', AB(kd+1+i-j,j) = A(i,j) for max(1,j-kd)<=i<=j;* if UPLO = 'L', AB(1+i-j,j) = A(i,j) for j<=i<=min(n,j+kd).* If DIAG = 'U', the diagonal elements of A are not referenced* and are assumed to be 1.** LDAB (input) INTEGER* The leading dimension of the array AB. LDAB >= KD+1.** RCOND (output) DOUBLE PRECISION* The reciprocal of the condition number of the matrix A,* computed as RCOND = 1/(norm(A) * norm(inv(A))).** WORK (workspace) DOUBLE PRECISION array, dimension (3*N)** IWORK (workspace) INTEGER array, dimension (N)** INFO (output) INTEGER* = 0: successful exit* < 0: if INFO = -i, the i-th argument had an illegal value** =====================================================================** .. Parameters ..DOUBLE PRECISION ONE, ZEROPARAMETER ( ONE = 1.0D+0, ZERO = 0.0D+0 )* ..* .. Local Scalars ..LOGICAL NOUNIT, ONENRM, UPPERCHARACTER NORMININTEGER IX, KASE, KASE1DOUBLE PRECISION AINVNM, ANORM, SCALE, SMLNUM, XNORM* ..* .. External Functions ..LOGICAL LSAMEINTEGER IDAMAXDOUBLE PRECISION DLAMCH, DLANTBEXTERNAL LSAME, IDAMAX, DLAMCH, DLANTB* ..* .. External Subroutines ..EXTERNAL DLACON, DLATBS, DRSCL, XERBLA* ..* .. Intrinsic Functions ..INTRINSIC ABS, DBLE, MAX* ..* .. Executable Statements ..** Test the input parameters.*INFO = 0UPPER = LSAME( UPLO, 'U' )ONENRM = NORM.EQ.'1' .OR. LSAME( NORM, 'O' )NOUNIT = LSAME( DIAG, 'N' )*IF( .NOT.ONENRM .AND. .NOT.LSAME( NORM, 'I' ) ) THENINFO = -1ELSE IF( .NOT.UPPER .AND. .NOT.LSAME( UPLO, 'L' ) ) THENINFO = -2ELSE IF( .NOT.NOUNIT .AND. .NOT.LSAME( DIAG, 'U' ) ) THENINFO = -3ELSE IF( N.LT.0 ) THENINFO = -4ELSE IF( KD.LT.0 ) THENINFO = -5ELSE IF( LDAB.LT.KD+1 ) THENINFO = -7END IFIF( INFO.NE.0 ) THENCALL XERBLA( 'DTBCON', -INFO )RETURNEND IF** Quick return if possible*IF( N.EQ.0 ) THENRCOND = ONERETURNEND IF*RCOND = ZEROSMLNUM = DLAMCH( 'Safe minimum' )*DBLE( MAX( 1, N ) )** Compute the norm of the triangular matrix A.*ANORM = DLANTB( NORM, UPLO, DIAG, N, KD, AB, LDAB, WORK )** Continue only if ANORM > 0.*IF( ANORM.GT.ZERO ) THEN** Estimate the norm of the inverse of A.*AINVNM = ZERONORMIN = 'N'IF( ONENRM ) THENKASE1 = 1ELSEKASE1 = 2END IFKASE = 010 CONTINUECALL DLACON( N, WORK( N+1 ), WORK, IWORK, AINVNM, KASE )IF( KASE.NE.0 ) THENIF( KASE.EQ.KASE1 ) THEN** Multiply by inv(A).*CALL DLATBS( UPLO, 'No transpose', DIAG, NORMIN, N, KD,$ AB, LDAB, WORK, SCALE, WORK( 2*N+1 ), INFO )ELSE** Multiply by inv(A').*CALL DLATBS( UPLO, 'Transpose', DIAG, NORMIN, N, KD, AB,$ LDAB, WORK, SCALE, WORK( 2*N+1 ), INFO )END IFNORMIN = 'Y'** Multiply by 1/SCALE if doing so will not cause overflow.*IF( SCALE.NE.ONE ) THENIX = IDAMAX( N, WORK, 1 )XNORM = ABS( WORK( IX ) )IF( SCALE.LT.XNORM*SMLNUM .OR. SCALE.EQ.ZERO )$ GO TO 20CALL DRSCL( N, SCALE, WORK, 1 )END IFGO TO 10END IF** Compute the estimate of the reciprocal condition number.*IF( AINVNM.NE.ZERO )$ RCOND = ( ONE / ANORM ) / AINVNMEND IF*20 CONTINUERETURN** End of DTBCON*ENDSUBROUTINE DTBRFS( UPLO, TRANS, DIAG, N, KD, NRHS, AB, LDAB, B,$ LDB, X, LDX, FERR, BERR, WORK, IWORK, INFO )** -- LAPACK routine (version 3.0) --* Univ. of Tennessee, Univ. of California Berkeley, NAG Ltd.,* Courant Institute, Argonne National Lab, and Rice University* September 30, 1994** .. Scalar Arguments ..CHARACTER DIAG, TRANS, UPLOINTEGER INFO, KD, LDAB, LDB, LDX, N, NRHS* ..* .. Array Arguments ..INTEGER IWORK( * )DOUBLE PRECISION AB( LDAB, * ), B( LDB, * ), BERR( * ),$ FERR( * ), WORK( * ), X( LDX, * )* ..** Purpose* =======** DTBRFS provides error bounds and backward error estimates for the* solution to a system of linear equations with a triangular band* coefficient matrix.** The solution matrix X must be computed by DTBTRS or some other* means before entering this routine. DTBRFS does not do iterative* refinement because doing so cannot improve the backward error.** Arguments* =========** UPLO (input) CHARACTER*1* = 'U': A is upper triangular;* = 'L': A is lower triangular.** TRANS (input) CHARACTER*1* Specifies the form of the system of equations:* = 'N': A * X = B (No transpose)* = 'T': A**T * X = B (Transpose)* = 'C': A**H * X = B (Conjugate transpose = Transpose)** DIAG (input) CHARACTER*1* = 'N': A is non-unit triangular;* = 'U': A is unit triangular.** N (input) INTEGER* The order of the matrix A. N >= 0.** KD (input) INTEGER* The number of superdiagonals or subdiagonals of the* triangular band matrix A. KD >= 0.** NRHS (input) INTEGER* The number of right hand sides, i.e., the number of columns* of the matrices B and X. NRHS >= 0.** AB (input) DOUBLE PRECISION array, dimension (LDAB,N)* The upper or lower triangular band matrix A, stored in the* first kd+1 rows of the array. The j-th column of A is stored* in the j-th column of the array AB as follows:* if UPLO = 'U', AB(kd+1+i-j,j) = A(i,j) for max(1,j-kd)<=i<=j;* if UPLO = 'L', AB(1+i-j,j) = A(i,j) for j<=i<=min(n,j+kd).* If DIAG = 'U', the diagonal elements of A are not referenced* and are assumed to be 1.** LDAB (input) INTEGER* The leading dimension of the array AB. LDAB >= KD+1.** B (input) DOUBLE PRECISION array, dimension (LDB,NRHS)* The right hand side matrix B.** LDB (input) INTEGER* The leading dimension of the array B. LDB >= max(1,N).** X (input) DOUBLE PRECISION array, dimension (LDX,NRHS)* The solution matrix X.** LDX (input) INTEGER* The leading dimension of the array X. LDX >= max(1,N).** FERR (output) DOUBLE PRECISION array, dimension (NRHS)* The estimated forward error bound for each solution vector* X(j) (the j-th column of the solution matrix X).* If XTRUE is the true solution corresponding to X(j), FERR(j)* is an estimated upper bound for the magnitude of the largest* element in (X(j) - XTRUE) divided by the magnitude of the* largest element in X(j). The estimate is as reliable as* the estimate for RCOND, and is almost always a slight* overestimate of the true error.** BERR (output) DOUBLE PRECISION array, dimension (NRHS)* The componentwise relative backward error of each solution* vector X(j) (i.e., the smallest relative change in* any element of A or B that makes X(j) an exact solution).** WORK (workspace) DOUBLE PRECISION array, dimension (3*N)** IWORK (workspace) INTEGER array, dimension (N)** INFO (output) INTEGER* = 0: successful exit* < 0: if INFO = -i, the i-th argument had an illegal value** =====================================================================** .. Parameters ..DOUBLE PRECISION ZEROPARAMETER ( ZERO = 0.0D+0 )DOUBLE PRECISION ONEPARAMETER ( ONE = 1.0D+0 )* ..* .. Local Scalars ..LOGICAL NOTRAN, NOUNIT, UPPERCHARACTER TRANSTINTEGER I, J, K, KASE, NZDOUBLE PRECISION EPS, LSTRES, S, SAFE1, SAFE2, SAFMIN, XK* ..* .. External Subroutines ..EXTERNAL DAXPY, DCOPY, DLACON, DTBMV, DTBSV, XERBLA* ..* .. Intrinsic Functions ..INTRINSIC ABS, MAX, MIN* ..* .. External Functions ..LOGICAL LSAMEDOUBLE PRECISION DLAMCHEXTERNAL LSAME, DLAMCH* ..* .. Executable Statements ..** Test the input parameters.*INFO = 0UPPER = LSAME( UPLO, 'U' )NOTRAN = LSAME( TRANS, 'N' )NOUNIT = LSAME( DIAG, 'N' )*IF( .NOT.UPPER .AND. .NOT.LSAME( UPLO, 'L' ) ) THENINFO = -1ELSE IF( .NOT.NOTRAN .AND. .NOT.LSAME( TRANS, 'T' ) .AND. .NOT.$ LSAME( TRANS, 'C' ) ) THENINFO = -2ELSE IF( .NOT.NOUNIT .AND. .NOT.LSAME( DIAG, 'U' ) ) THENINFO = -3ELSE IF( N.LT.0 ) THENINFO = -4ELSE IF( KD.LT.0 ) THENINFO = -5ELSE IF( NRHS.LT.0 ) THENINFO = -6ELSE IF( LDAB.LT.KD+1 ) THENINFO = -8ELSE IF( LDB.LT.MAX( 1, N ) ) THENINFO = -10ELSE IF( LDX.LT.MAX( 1, N ) ) THENINFO = -12END IFIF( INFO.NE.0 ) THENCALL XERBLA( 'DTBRFS', -INFO )RETURNEND IF** Quick return if possible*IF( N.EQ.0 .OR. NRHS.EQ.0 ) THENDO 10 J = 1, NRHSFERR( J ) = ZEROBERR( J ) = ZERO10 CONTINUERETURNEND IF*IF( NOTRAN ) THENTRANST = 'T'ELSETRANST = 'N'END IF** NZ = maximum number of nonzero elements in each row of A, plus 1*NZ = KD + 2EPS = DLAMCH( 'Epsilon' )SAFMIN = DLAMCH( 'Safe minimum' )SAFE1 = NZ*SAFMINSAFE2 = SAFE1 / EPS** Do for each right hand side*DO 250 J = 1, NRHS** Compute residual R = B - op(A) * X,* where op(A) = A or A', depending on TRANS.*CALL DCOPY( N, X( 1, J ), 1, WORK( N+1 ), 1 )CALL DTBMV( UPLO, TRANS, DIAG, N, KD, AB, LDAB, WORK( N+1 ),$ 1 )CALL DAXPY( N, -ONE, B( 1, J ), 1, WORK( N+1 ), 1 )** Compute componentwise relative backward error from formula** max(i) ( abs(R(i)) / ( abs(op(A))*abs(X) + abs(B) )(i) )** where abs(Z) is the componentwise absolute value of the matrix* or vector Z. If the i-th component of the denominator is less* than SAFE2, then SAFE1 is added to the i-th components of the* numerator and denominator before dividing.*DO 20 I = 1, NWORK( I ) = ABS( B( I, J ) )20 CONTINUE*IF( NOTRAN ) THEN** Compute abs(A)*abs(X) + abs(B).*IF( UPPER ) THENIF( NOUNIT ) THENDO 40 K = 1, NXK = ABS( X( K, J ) )DO 30 I = MAX( 1, K-KD ), KWORK( I ) = WORK( I ) +$ ABS( AB( KD+1+I-K, K ) )*XK30 CONTINUE40 CONTINUEELSEDO 60 K = 1, NXK = ABS( X( K, J ) )DO 50 I = MAX( 1, K-KD ), K - 1WORK( I ) = WORK( I ) +$ ABS( AB( KD+1+I-K, K ) )*XK50 CONTINUEWORK( K ) = WORK( K ) + XK60 CONTINUEEND IFELSEIF( NOUNIT ) THENDO 80 K = 1, NXK = ABS( X( K, J ) )DO 70 I = K, MIN( N, K+KD )WORK( I ) = WORK( I ) + ABS( AB( 1+I-K, K ) )*XK70 CONTINUE80 CONTINUEELSEDO 100 K = 1, NXK = ABS( X( K, J ) )DO 90 I = K + 1, MIN( N, K+KD )WORK( I ) = WORK( I ) + ABS( AB( 1+I-K, K ) )*XK90 CONTINUEWORK( K ) = WORK( K ) + XK100 CONTINUEEND IFEND IFELSE** Compute abs(A')*abs(X) + abs(B).*IF( UPPER ) THENIF( NOUNIT ) THENDO 120 K = 1, NS = ZERODO 110 I = MAX( 1, K-KD ), KS = S + ABS( AB( KD+1+I-K, K ) )*$ ABS( X( I, J ) )110 CONTINUEWORK( K ) = WORK( K ) + S120 CONTINUEELSEDO 140 K = 1, NS = ABS( X( K, J ) )DO 130 I = MAX( 1, K-KD ), K - 1S = S + ABS( AB( KD+1+I-K, K ) )*$ ABS( X( I, J ) )130 CONTINUEWORK( K ) = WORK( K ) + S140 CONTINUEEND IFELSEIF( NOUNIT ) THENDO 160 K = 1, NS = ZERODO 150 I = K, MIN( N, K+KD )S = S + ABS( AB( 1+I-K, K ) )*ABS( X( I, J ) )150 CONTINUEWORK( K ) = WORK( K ) + S160 CONTINUEELSEDO 180 K = 1, NS = ABS( X( K, J ) )DO 170 I = K + 1, MIN( N, K+KD )S = S + ABS( AB( 1+I-K, K ) )*ABS( X( I, J ) )170 CONTINUEWORK( K ) = WORK( K ) + S180 CONTINUEEND IFEND IFEND IFS = ZERODO 190 I = 1, NIF( WORK( I ).GT.SAFE2 ) THENS = MAX( S, ABS( WORK( N+I ) ) / WORK( I ) )ELSES = MAX( S, ( ABS( WORK( N+I ) )+SAFE1 ) /$ ( WORK( I )+SAFE1 ) )END IF190 CONTINUEBERR( J ) = S** Bound error from formula** norm(X - XTRUE) / norm(X) .le. FERR =* norm( abs(inv(op(A)))** ( abs(R) + NZ*EPS*( abs(op(A))*abs(X)+abs(B) ))) / norm(X)** where* norm(Z) is the magnitude of the largest component of Z* inv(op(A)) is the inverse of op(A)* abs(Z) is the componentwise absolute value of the matrix or* vector Z* NZ is the maximum number of nonzeros in any row of A, plus 1* EPS is machine epsilon** The i-th component of abs(R)+NZ*EPS*(abs(op(A))*abs(X)+abs(B))* is incremented by SAFE1 if the i-th component of* abs(op(A))*abs(X) + abs(B) is less than SAFE2.** Use DLACON to estimate the infinity-norm of the matrix* inv(op(A)) * diag(W),* where W = abs(R) + NZ*EPS*( abs(op(A))*abs(X)+abs(B) )))*DO 200 I = 1, NIF( WORK( I ).GT.SAFE2 ) THENWORK( I ) = ABS( WORK( N+I ) ) + NZ*EPS*WORK( I )ELSEWORK( I ) = ABS( WORK( N+I ) ) + NZ*EPS*WORK( I ) + SAFE1END IF200 CONTINUE*KASE = 0210 CONTINUECALL DLACON( N, WORK( 2*N+1 ), WORK( N+1 ), IWORK, FERR( J ),$ KASE )IF( KASE.NE.0 ) THENIF( KASE.EQ.1 ) THEN** Multiply by diag(W)*inv(op(A)').*CALL DTBSV( UPLO, TRANST, DIAG, N, KD, AB, LDAB,$ WORK( N+1 ), 1 )DO 220 I = 1, NWORK( N+I ) = WORK( I )*WORK( N+I )220 CONTINUEELSE** Multiply by inv(op(A))*diag(W).*DO 230 I = 1, NWORK( N+I ) = WORK( I )*WORK( N+I )230 CONTINUECALL DTBSV( UPLO, TRANS, DIAG, N, KD, AB, LDAB,$ WORK( N+1 ), 1 )END IFGO TO 210END IF** Normalize error.*LSTRES = ZERODO 240 I = 1, NLSTRES = MAX( LSTRES, ABS( X( I, J ) ) )240 CONTINUEIF( LSTRES.NE.ZERO )$ FERR( J ) = FERR( J ) / LSTRES*250 CONTINUE*RETURN** End of DTBRFS*ENDSUBROUTINE DTBTRS( UPLO, TRANS, DIAG, N, KD, NRHS, AB, LDAB, B,$ LDB, INFO )** -- LAPACK routine (version 3.0) --* Univ. of Tennessee, Univ. of California Berkeley, NAG Ltd.,* Courant Institute, Argonne National Lab, and Rice University* March 31, 1993** .. Scalar Arguments ..CHARACTER DIAG, TRANS, UPLOINTEGER INFO, KD, LDAB, LDB, N, NRHS* ..* .. Array Arguments ..DOUBLE PRECISION AB( LDAB, * ), B( LDB, * )* ..** Purpose* =======** DTBTRS solves a triangular system of the form** A * X = B or A**T * X = B,** where A is a triangular band matrix of order N, and B is an* N-by NRHS matrix. A check is made to verify that A is nonsingular.** Arguments* =========** UPLO (input) CHARACTER*1* = 'U': A is upper triangular;* = 'L': A is lower triangular.** TRANS (input) CHARACTER*1* Specifies the form the system of equations:* = 'N': A * X = B (No transpose)* = 'T': A**T * X = B (Transpose)* = 'C': A**H * X = B (Conjugate transpose = Transpose)** DIAG (input) CHARACTER*1* = 'N': A is non-unit triangular;* = 'U': A is unit triangular.** N (input) INTEGER* The order of the matrix A. N >= 0.** KD (input) INTEGER* The number of superdiagonals or subdiagonals of the* triangular band matrix A. KD >= 0.** NRHS (input) INTEGER* The number of right hand sides, i.e., the number of columns* of the matrix B. NRHS >= 0.** AB (input) DOUBLE PRECISION array, dimension (LDAB,N)* The upper or lower triangular band matrix A, stored in the* first kd+1 rows of AB. The j-th column of A is stored* in the j-th column of the array AB as follows:* if UPLO = 'U', AB(kd+1+i-j,j) = A(i,j) for max(1,j-kd)<=i<=j;* if UPLO = 'L', AB(1+i-j,j) = A(i,j) for j<=i<=min(n,j+kd).* If DIAG = 'U', the diagonal elements of A are not referenced* and are assumed to be 1.** LDAB (input) INTEGER* The leading dimension of the array AB. LDAB >= KD+1.** B (input/output) DOUBLE PRECISION array, dimension (LDB,NRHS)* On entry, the right hand side matrix B.* On exit, if INFO = 0, 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* > 0: if INFO = i, the i-th diagonal element of A is zero,* indicating that the matrix is singular and the* solutions X have not been computed.** =====================================================================** .. Parameters ..DOUBLE PRECISION ZEROPARAMETER ( ZERO = 0.0D+0 )* ..* .. Local Scalars ..LOGICAL NOUNIT, UPPERINTEGER J* ..* .. External Functions ..LOGICAL LSAMEEXTERNAL LSAME* ..* .. External Subroutines ..EXTERNAL DTBSV, XERBLA* ..* .. Intrinsic Functions ..INTRINSIC MAX* ..* .. Executable Statements ..** Test the input parameters.*INFO = 0NOUNIT = LSAME( DIAG, 'N' )UPPER = LSAME( UPLO, 'U' )IF( .NOT.UPPER .AND. .NOT.LSAME( UPLO, 'L' ) ) THENINFO = -1ELSE IF( .NOT.LSAME( TRANS, 'N' ) .AND. .NOT.$ LSAME( TRANS, 'T' ) .AND. .NOT.LSAME( TRANS, 'C' ) ) THENINFO = -2ELSE IF( .NOT.NOUNIT .AND. .NOT.LSAME( DIAG, 'U' ) ) THENINFO = -3ELSE IF( N.LT.0 ) THENINFO = -4ELSE IF( KD.LT.0 ) THENINFO = -5ELSE IF( NRHS.LT.0 ) THENINFO = -6ELSE IF( LDAB.LT.KD+1 ) THENINFO = -8ELSE IF( LDB.LT.MAX( 1, N ) ) THENINFO = -10END IFIF( INFO.NE.0 ) THENCALL XERBLA( 'DTBTRS', -INFO )RETURNEND IF** Quick return if possible*IF( N.EQ.0 )$ RETURN** Check for singularity.*IF( NOUNIT ) THENIF( UPPER ) THENDO 10 INFO = 1, NIF( AB( KD+1, INFO ).EQ.ZERO )$ RETURN10 CONTINUEELSEDO 20 INFO = 1, NIF( AB( 1, INFO ).EQ.ZERO )$ RETURN20 CONTINUEEND IFEND IFINFO = 0** Solve A * X = B or A' * X = B.*DO 30 J = 1, NRHSCALL DTBSV( UPLO, TRANS, DIAG, N, KD, AB, LDAB, B( 1, J ), 1 )30 CONTINUE*RETURN** End of DTBTRS*ENDSUBROUTINE DTGEVC( SIDE, HOWMNY, SELECT, N, A, LDA, B, LDB, VL,$ LDVL, VR, LDVR, MM, M, WORK, INFO )** -- LAPACK routine (version 3.0) --* Univ. of Tennessee, Univ. of California Berkeley, NAG Ltd.,* Courant Institute, Argonne National Lab, and Rice University* June 30, 1999** .. Scalar Arguments ..CHARACTER HOWMNY, SIDEINTEGER INFO, LDA, LDB, LDVL, LDVR, M, MM, N* ..* .. Array Arguments ..LOGICAL SELECT( * )DOUBLE PRECISION A( LDA, * ), B( LDB, * ), VL( LDVL, * ),$ VR( LDVR, * ), WORK( * )* ..*** Purpose* =======** DTGEVC computes some or all of the right and/or left generalized* eigenvectors of a pair of real upper triangular matrices (A,B).** The right generalized eigenvector x and the left generalized* eigenvector y of (A,B) corresponding to a generalized eigenvalue* w are defined by:** (A - wB) * x = 0 and y**H * (A - wB) = 0** where y**H denotes the conjugate tranpose of y.** If an eigenvalue w is determined by zero diagonal elements of both A* and B, a unit vector is returned as the corresponding eigenvector.** If all eigenvectors are requested, the routine may either return* the matrices X and/or Y of right or left eigenvectors of (A,B), or* the products Z*X and/or Q*Y, where Z and Q are input orthogonal* matrices. If (A,B) was obtained from the generalized real-Schur* factorization of an original pair of matrices* (A0,B0) = (Q*A*Z**H,Q*B*Z**H),* then Z*X and Q*Y are the matrices of right or left eigenvectors of* A.** A must be block upper triangular, with 1-by-1 and 2-by-2 diagonal* blocks. Corresponding to each 2-by-2 diagonal block is a complex* conjugate pair of eigenvalues and eigenvectors; only one* eigenvector of the pair is computed, namely the one corresponding* to the eigenvalue with positive imaginary part.** Arguments* =========** SIDE (input) CHARACTER*1* = 'R': compute right eigenvectors only;* = 'L': compute left eigenvectors only;* = 'B': compute both right and left eigenvectors.** HOWMNY (input) CHARACTER*1* = 'A': compute all right and/or left eigenvectors;* = 'B': compute all right and/or left eigenvectors, and* backtransform them using the input matrices supplied* in VR and/or VL;* = 'S': compute selected right and/or left eigenvectors,* specified by the logical array SELECT.** SELECT (input) LOGICAL array, dimension (N)* If HOWMNY='S', SELECT specifies the eigenvectors to be* computed.* If HOWMNY='A' or 'B', SELECT is not referenced.* To select the real eigenvector corresponding to the real* eigenvalue w(j), SELECT(j) must be set to .TRUE. To select* the complex eigenvector corresponding to a complex conjugate* pair w(j) and w(j+1), either SELECT(j) or SELECT(j+1) must* be set to .TRUE..** N (input) INTEGER* The order of the matrices A and B. N >= 0.** A (input) DOUBLE PRECISION array, dimension (LDA,N)* The upper quasi-triangular matrix A.** LDA (input) INTEGER* The leading dimension of array A. LDA >= max(1, N).** B (input) DOUBLE PRECISION array, dimension (LDB,N)* The upper triangular matrix B. If A has a 2-by-2 diagonal* block, then the corresponding 2-by-2 block of B must be* diagonal with positive elements.** LDB (input) INTEGER* The leading dimension of array B. LDB >= max(1,N).** VL (input/output) DOUBLE PRECISION array, dimension (LDVL,MM)* On entry, if SIDE = 'L' or 'B' and HOWMNY = 'B', VL must* contain an N-by-N matrix Q (usually the orthogonal matrix Q* of left Schur vectors returned by DHGEQZ).* On exit, if SIDE = 'L' or 'B', VL contains:* if HOWMNY = 'A', the matrix Y of left eigenvectors of (A,B);* if HOWMNY = 'B', the matrix Q*Y;* if HOWMNY = 'S', the left eigenvectors of (A,B) specified by* SELECT, stored consecutively in the columns of* VL, in the same order as their eigenvalues.* If SIDE = 'R', VL is not referenced.** A complex eigenvector corresponding to a complex eigenvalue* is stored in two consecutive columns, the first holding the* real part, and the second the imaginary part.** LDVL (input) INTEGER* The leading dimension of array VL.* LDVL >= max(1,N) if SIDE = 'L' or 'B'; LDVL >= 1 otherwise.** VR (input/output) DOUBLE PRECISION array, dimension (LDVR,MM)* On entry, if SIDE = 'R' or 'B' and HOWMNY = 'B', VR must* contain an N-by-N matrix Q (usually the orthogonal matrix Z* of right Schur vectors returned by DHGEQZ).* On exit, if SIDE = 'R' or 'B', VR contains:* if HOWMNY = 'A', the matrix X of right eigenvectors of (A,B);* if HOWMNY = 'B', the matrix Z*X;* if HOWMNY = 'S', the right eigenvectors of (A,B) specified by* SELECT, stored consecutively in the columns of* VR, in the same order as their eigenvalues.* If SIDE = 'L', VR is not referenced.** A complex eigenvector corresponding to a complex eigenvalue* is stored in two consecutive columns, the first holding the* real part and the second the imaginary part.** LDVR (input) INTEGER* The leading dimension of the array VR.* LDVR >= max(1,N) if SIDE = 'R' or 'B'; LDVR >= 1 otherwise.** MM (input) INTEGER* The number of columns in the arrays VL and/or VR. MM >= M.** M (output) INTEGER* The number of columns in the arrays VL and/or VR actually* used to store the eigenvectors. If HOWMNY = 'A' or 'B', M* is set to N. Each selected real eigenvector occupies one* column and each selected complex eigenvector occupies two* columns.** WORK (workspace) DOUBLE PRECISION array, dimension (6*N)** INFO (output) INTEGER* = 0: successful exit.* < 0: if INFO = -i, the i-th argument had an illegal value.* > 0: the 2-by-2 block (INFO:INFO+1) does not have a complex* eigenvalue.** Further Details* ===============** Allocation of workspace:* ---------- -- ---------** WORK( j ) = 1-norm of j-th column of A, above the diagonal* WORK( N+j ) = 1-norm of j-th column of B, above the diagonal* WORK( 2*N+1:3*N ) = real part of eigenvector* WORK( 3*N+1:4*N ) = imaginary part of eigenvector* WORK( 4*N+1:5*N ) = real part of back-transformed eigenvector* WORK( 5*N+1:6*N ) = imaginary part of back-transformed eigenvector** Rowwise vs. columnwise solution methods:* ------- -- ---------- -------- -------** Finding a generalized eigenvector consists basically of solving the* singular triangular system** (A - w B) x = 0 (for right) or: (A - w B)**H y = 0 (for left)** Consider finding the i-th right eigenvector (assume all eigenvalues* are real). The equation to be solved is:* n i* 0 = sum C(j,k) v(k) = sum C(j,k) v(k) for j = i,. . .,1* k=j k=j** where C = (A - w B) (The components v(i+1:n) are 0.)** The "rowwise" method is:** (1) v(i) := 1* for j = i-1,. . .,1:* i* (2) compute s = - sum C(j,k) v(k) and* k=j+1** (3) v(j) := s / C(j,j)** Step 2 is sometimes called the "dot product" step, since it is an* inner product between the j-th row and the portion of the eigenvector* that has been computed so far.** The "columnwise" method consists basically in doing the sums* for all the rows in parallel. As each v(j) is computed, the* contribution of v(j) times the j-th column of C is added to the* partial sums. Since FORTRAN arrays are stored columnwise, this has* the advantage that at each step, the elements of C that are accessed* are adjacent to one another, whereas with the rowwise method, the* elements accessed at a step are spaced LDA (and LDB) words apart.** When finding left eigenvectors, the matrix in question is the* transpose of the one in storage, so the rowwise method then* actually accesses columns of A and B at each step, and so is the* preferred method.** =====================================================================** .. Parameters ..DOUBLE PRECISION ZERO, ONE, SAFETYPARAMETER ( ZERO = 0.0D+0, ONE = 1.0D+0,$ SAFETY = 1.0D+2 )* ..* .. Local Scalars ..LOGICAL COMPL, COMPR, IL2BY2, ILABAD, ILALL, ILBACK,$ ILBBAD, ILCOMP, ILCPLX, LSA, LSBINTEGER I, IBEG, IEIG, IEND, IHWMNY, IINFO, IM, ISIDE,$ J, JA, JC, JE, JR, JW, NA, NWDOUBLE PRECISION ACOEF, ACOEFA, ANORM, ASCALE, BCOEFA, BCOEFI,$ BCOEFR, BIG, BIGNUM, BNORM, BSCALE, CIM2A,$ CIM2B, CIMAGA, CIMAGB, CRE2A, CRE2B, CREALA,$ CREALB, DMIN, SAFMIN, SALFAR, SBETA, SCALE,$ SMALL, TEMP, TEMP2, TEMP2I, TEMP2R, ULP, XMAX,$ XSCALE* ..* .. Local Arrays ..DOUBLE PRECISION BDIAG( 2 ), SUM( 2, 2 ), SUMA( 2, 2 ),$ SUMB( 2, 2 )* ..* .. External Functions ..LOGICAL LSAMEDOUBLE PRECISION DLAMCHEXTERNAL LSAME, DLAMCH* ..* .. External Subroutines ..EXTERNAL DGEMV, DLACPY, DLAG2, DLALN2, XERBLA* ..* .. Intrinsic Functions ..INTRINSIC ABS, MAX, MIN* ..* .. Executable Statements ..** Decode and Test the input parameters*IF( LSAME( HOWMNY, 'A' ) ) THENIHWMNY = 1ILALL = .TRUE.ILBACK = .FALSE.ELSE IF( LSAME( HOWMNY, 'S' ) ) THENIHWMNY = 2ILALL = .FALSE.ILBACK = .FALSE.ELSE IF( LSAME( HOWMNY, 'B' ) .OR. LSAME( HOWMNY, 'T' ) ) THENIHWMNY = 3ILALL = .TRUE.ILBACK = .TRUE.ELSEIHWMNY = -1ILALL = .TRUE.END IF*IF( LSAME( SIDE, 'R' ) ) THENISIDE = 1COMPL = .FALSE.COMPR = .TRUE.ELSE IF( LSAME( SIDE, 'L' ) ) THENISIDE = 2COMPL = .TRUE.COMPR = .FALSE.ELSE IF( LSAME( SIDE, 'B' ) ) THENISIDE = 3COMPL = .TRUE.COMPR = .TRUE.ELSEISIDE = -1END IF*INFO = 0IF( ISIDE.LT.0 ) THENINFO = -1ELSE IF( IHWMNY.LT.0 ) THENINFO = -2ELSE IF( N.LT.0 ) THENINFO = -4ELSE IF( LDA.LT.MAX( 1, N ) ) THENINFO = -6ELSE IF( LDB.LT.MAX( 1, N ) ) THENINFO = -8END IFIF( INFO.NE.0 ) THENCALL XERBLA( 'DTGEVC', -INFO )RETURNEND IF** Count the number of eigenvectors to be computed*IF( .NOT.ILALL ) THENIM = 0ILCPLX = .FALSE.DO 10 J = 1, NIF( ILCPLX ) THENILCPLX = .FALSE.GO TO 10END IFIF( J.LT.N ) THENIF( A( J+1, J ).NE.ZERO )$ ILCPLX = .TRUE.END IFIF( ILCPLX ) THENIF( SELECT( J ) .OR. SELECT( J+1 ) )$ IM = IM + 2ELSEIF( SELECT( J ) )$ IM = IM + 1END IF10 CONTINUEELSEIM = NEND IF** Check 2-by-2 diagonal blocks of A, B*ILABAD = .FALSE.ILBBAD = .FALSE.DO 20 J = 1, N - 1IF( A( J+1, J ).NE.ZERO ) THENIF( B( J, J ).EQ.ZERO .OR. B( J+1, J+1 ).EQ.ZERO .OR.$ B( J, J+1 ).NE.ZERO )ILBBAD = .TRUE.IF( J.LT.N-1 ) THENIF( A( J+2, J+1 ).NE.ZERO )$ ILABAD = .TRUE.END IFEND IF20 CONTINUE*IF( ILABAD ) THENINFO = -5ELSE IF( ILBBAD ) THENINFO = -7ELSE IF( COMPL .AND. LDVL.LT.N .OR. LDVL.LT.1 ) THENINFO = -10ELSE IF( COMPR .AND. LDVR.LT.N .OR. LDVR.LT.1 ) THENINFO = -12ELSE IF( MM.LT.IM ) THENINFO = -13END IFIF( INFO.NE.0 ) THENCALL XERBLA( 'DTGEVC', -INFO )RETURNEND IF** Quick return if possible*M = IMIF( N.EQ.0 )$ RETURN** Machine Constants*SAFMIN = DLAMCH( 'Safe minimum' )BIG = ONE / SAFMINCALL DLABAD( SAFMIN, BIG )ULP = DLAMCH( 'Epsilon' )*DLAMCH( 'Base' )SMALL = SAFMIN*N / ULPBIG = ONE / SMALLBIGNUM = ONE / ( SAFMIN*N )** Compute the 1-norm of each column of the strictly upper triangular* part (i.e., excluding all elements belonging to the diagonal* blocks) of A and B to check for possible overflow in the* triangular solver.*ANORM = ABS( A( 1, 1 ) )IF( N.GT.1 )$ ANORM = ANORM + ABS( A( 2, 1 ) )BNORM = ABS( B( 1, 1 ) )WORK( 1 ) = ZEROWORK( N+1 ) = ZERO*DO 50 J = 2, NTEMP = ZEROTEMP2 = ZEROIF( A( J, J-1 ).EQ.ZERO ) THENIEND = J - 1ELSEIEND = J - 2END IFDO 30 I = 1, IENDTEMP = TEMP + ABS( A( I, J ) )TEMP2 = TEMP2 + ABS( B( I, J ) )30 CONTINUEWORK( J ) = TEMPWORK( N+J ) = TEMP2DO 40 I = IEND + 1, MIN( J+1, N )TEMP = TEMP + ABS( A( I, J ) )TEMP2 = TEMP2 + ABS( B( I, J ) )40 CONTINUEANORM = MAX( ANORM, TEMP )BNORM = MAX( BNORM, TEMP2 )50 CONTINUE*ASCALE = ONE / MAX( ANORM, SAFMIN )BSCALE = ONE / MAX( BNORM, SAFMIN )** Left eigenvectors*IF( COMPL ) THENIEIG = 0** Main loop over eigenvalues*ILCPLX = .FALSE.DO 220 JE = 1, N** Skip this iteration if (a) HOWMNY='S' and SELECT=.FALSE., or* (b) this would be the second of a complex pair.* Check for complex eigenvalue, so as to be sure of which* entry(-ies) of SELECT to look at.*IF( ILCPLX ) THENILCPLX = .FALSE.GO TO 220END IFNW = 1IF( JE.LT.N ) THENIF( A( JE+1, JE ).NE.ZERO ) THENILCPLX = .TRUE.NW = 2END IFEND IFIF( ILALL ) THENILCOMP = .TRUE.ELSE IF( ILCPLX ) THENILCOMP = SELECT( JE ) .OR. SELECT( JE+1 )ELSEILCOMP = SELECT( JE )END IFIF( .NOT.ILCOMP )$ GO TO 220** Decide if (a) singular pencil, (b) real eigenvalue, or* (c) complex eigenvalue.*IF( .NOT.ILCPLX ) THENIF( ABS( A( JE, JE ) ).LE.SAFMIN .AND.$ ABS( B( JE, JE ) ).LE.SAFMIN ) THEN** Singular matrix pencil -- return unit eigenvector*IEIG = IEIG + 1DO 60 JR = 1, NVL( JR, IEIG ) = ZERO60 CONTINUEVL( IEIG, IEIG ) = ONEGO TO 220END IFEND IF** Clear vector*DO 70 JR = 1, NW*NWORK( 2*N+JR ) = ZERO70 CONTINUE* T* Compute coefficients in ( a A - b B ) y = 0* a is ACOEF* b is BCOEFR + i*BCOEFI*IF( .NOT.ILCPLX ) THEN** Real eigenvalue*TEMP = ONE / MAX( ABS( A( JE, JE ) )*ASCALE,$ ABS( B( JE, JE ) )*BSCALE, SAFMIN )SALFAR = ( TEMP*A( JE, JE ) )*ASCALESBETA = ( TEMP*B( JE, JE ) )*BSCALEACOEF = SBETA*ASCALEBCOEFR = SALFAR*BSCALEBCOEFI = ZERO** Scale to avoid underflow*SCALE = ONELSA = ABS( SBETA ).GE.SAFMIN .AND. ABS( ACOEF ).LT.SMALLLSB = ABS( SALFAR ).GE.SAFMIN .AND. ABS( BCOEFR ).LT.$ SMALLIF( LSA )$ SCALE = ( SMALL / ABS( SBETA ) )*MIN( ANORM, BIG )IF( LSB )$ SCALE = MAX( SCALE, ( SMALL / ABS( SALFAR ) )*$ MIN( BNORM, BIG ) )IF( LSA .OR. LSB ) THENSCALE = MIN( SCALE, ONE /$ ( SAFMIN*MAX( ONE, ABS( ACOEF ),$ ABS( BCOEFR ) ) ) )IF( LSA ) THENACOEF = ASCALE*( SCALE*SBETA )ELSEACOEF = SCALE*ACOEFEND IFIF( LSB ) THENBCOEFR = BSCALE*( SCALE*SALFAR )ELSEBCOEFR = SCALE*BCOEFREND IFEND IFACOEFA = ABS( ACOEF )BCOEFA = ABS( BCOEFR )** First component is 1*WORK( 2*N+JE ) = ONEXMAX = ONEELSE** Complex eigenvalue*CALL DLAG2( A( JE, JE ), LDA, B( JE, JE ), LDB,$ SAFMIN*SAFETY, ACOEF, TEMP, BCOEFR, TEMP2,$ BCOEFI )BCOEFI = -BCOEFIIF( BCOEFI.EQ.ZERO ) THENINFO = JERETURNEND IF** Scale to avoid over/underflow*ACOEFA = ABS( ACOEF )BCOEFA = ABS( BCOEFR ) + ABS( BCOEFI )SCALE = ONEIF( ACOEFA*ULP.LT.SAFMIN .AND. ACOEFA.GE.SAFMIN )$ SCALE = ( SAFMIN / ULP ) / ACOEFAIF( BCOEFA*ULP.LT.SAFMIN .AND. BCOEFA.GE.SAFMIN )$ SCALE = MAX( SCALE, ( SAFMIN / ULP ) / BCOEFA )IF( SAFMIN*ACOEFA.GT.ASCALE )$ SCALE = ASCALE / ( SAFMIN*ACOEFA )IF( SAFMIN*BCOEFA.GT.BSCALE )$ SCALE = MIN( SCALE, BSCALE / ( SAFMIN*BCOEFA ) )IF( SCALE.NE.ONE ) THENACOEF = SCALE*ACOEFACOEFA = ABS( ACOEF )BCOEFR = SCALE*BCOEFRBCOEFI = SCALE*BCOEFIBCOEFA = ABS( BCOEFR ) + ABS( BCOEFI )END IF** Compute first two components of eigenvector*TEMP = ACOEF*A( JE+1, JE )TEMP2R = ACOEF*A( JE, JE ) - BCOEFR*B( JE, JE )TEMP2I = -BCOEFI*B( JE, JE )IF( ABS( TEMP ).GT.ABS( TEMP2R )+ABS( TEMP2I ) ) THENWORK( 2*N+JE ) = ONEWORK( 3*N+JE ) = ZEROWORK( 2*N+JE+1 ) = -TEMP2R / TEMPWORK( 3*N+JE+1 ) = -TEMP2I / TEMPELSEWORK( 2*N+JE+1 ) = ONEWORK( 3*N+JE+1 ) = ZEROTEMP = ACOEF*A( JE, JE+1 )WORK( 2*N+JE ) = ( BCOEFR*B( JE+1, JE+1 )-ACOEF*$ A( JE+1, JE+1 ) ) / TEMPWORK( 3*N+JE ) = BCOEFI*B( JE+1, JE+1 ) / TEMPEND IFXMAX = MAX( ABS( WORK( 2*N+JE ) )+ABS( WORK( 3*N+JE ) ),$ ABS( WORK( 2*N+JE+1 ) )+ABS( WORK( 3*N+JE+1 ) ) )END IF*DMIN = MAX( ULP*ACOEFA*ANORM, ULP*BCOEFA*BNORM, SAFMIN )** T* Triangular solve of (a A - b B) y = 0** T* (rowwise in (a A - b B) , or columnwise in (a A - b B) )*IL2BY2 = .FALSE.*DO 160 J = JE + NW, NIF( IL2BY2 ) THENIL2BY2 = .FALSE.GO TO 160END IF*NA = 1BDIAG( 1 ) = B( J, J )IF( J.LT.N ) THENIF( A( J+1, J ).NE.ZERO ) THENIL2BY2 = .TRUE.BDIAG( 2 ) = B( J+1, J+1 )NA = 2END IFEND IF** Check whether scaling is necessary for dot products*XSCALE = ONE / MAX( ONE, XMAX )TEMP = MAX( WORK( J ), WORK( N+J ),$ ACOEFA*WORK( J )+BCOEFA*WORK( N+J ) )IF( IL2BY2 )$ TEMP = MAX( TEMP, WORK( J+1 ), WORK( N+J+1 ),$ ACOEFA*WORK( J+1 )+BCOEFA*WORK( N+J+1 ) )IF( TEMP.GT.BIGNUM*XSCALE ) THENDO 90 JW = 0, NW - 1DO 80 JR = JE, J - 1WORK( ( JW+2 )*N+JR ) = XSCALE*$ WORK( ( JW+2 )*N+JR )80 CONTINUE90 CONTINUEXMAX = XMAX*XSCALEEND IF** Compute dot products** j-1* SUM = sum conjg( a*A(k,j) - b*B(k,j) )*x(k)* k=je** To reduce the op count, this is done as** _ j-1 _ j-1* a*conjg( sum A(k,j)*x(k) ) - b*conjg( sum B(k,j)*x(k) )* k=je k=je** which may cause underflow problems if A or B are close* to underflow. (E.g., less than SMALL.)*** A series of compiler directives to defeat vectorization* for the next loop**$PL$ CMCHAR=' 'CDIR$ NEXTSCALARC$DIR SCALARCDIR$ NEXT SCALARCVD$L NOVECTORCDEC$ NOVECTORCVD$ NOVECTOR*VDIR NOVECTOR*VOCL LOOP,SCALARCIBM PREFER SCALAR*$PL$ CMCHAR='*'*DO 120 JW = 1, NW**$PL$ CMCHAR=' 'CDIR$ NEXTSCALARC$DIR SCALARCDIR$ NEXT SCALARCVD$L NOVECTORCDEC$ NOVECTORCVD$ NOVECTOR*VDIR NOVECTOR*VOCL LOOP,SCALARCIBM PREFER SCALAR*$PL$ CMCHAR='*'*DO 110 JA = 1, NASUMA( JA, JW ) = ZEROSUMB( JA, JW ) = ZERO*DO 100 JR = JE, J - 1SUMA( JA, JW ) = SUMA( JA, JW ) +$ A( JR, J+JA-1 )*$ WORK( ( JW+1 )*N+JR )SUMB( JA, JW ) = SUMB( JA, JW ) +$ B( JR, J+JA-1 )*$ WORK( ( JW+1 )*N+JR )100 CONTINUE110 CONTINUE120 CONTINUE**$PL$ CMCHAR=' 'CDIR$ NEXTSCALARC$DIR SCALARCDIR$ NEXT SCALARCVD$L NOVECTORCDEC$ NOVECTORCVD$ NOVECTOR*VDIR NOVECTOR*VOCL LOOP,SCALARCIBM PREFER SCALAR*$PL$ CMCHAR='*'*DO 130 JA = 1, NAIF( ILCPLX ) THENSUM( JA, 1 ) = -ACOEF*SUMA( JA, 1 ) +$ BCOEFR*SUMB( JA, 1 ) -$ BCOEFI*SUMB( JA, 2 )SUM( JA, 2 ) = -ACOEF*SUMA( JA, 2 ) +$ BCOEFR*SUMB( JA, 2 ) +$ BCOEFI*SUMB( JA, 1 )ELSESUM( JA, 1 ) = -ACOEF*SUMA( JA, 1 ) +$ BCOEFR*SUMB( JA, 1 )END IF130 CONTINUE** T* Solve ( a A - b B ) y = SUM(,)* with scaling and perturbation of the denominator*CALL DLALN2( .TRUE., NA, NW, DMIN, ACOEF, A( J, J ), LDA,$ BDIAG( 1 ), BDIAG( 2 ), SUM, 2, BCOEFR,$ BCOEFI, WORK( 2*N+J ), N, SCALE, TEMP,$ IINFO )IF( SCALE.LT.ONE ) THENDO 150 JW = 0, NW - 1DO 140 JR = JE, J - 1WORK( ( JW+2 )*N+JR ) = SCALE*$ WORK( ( JW+2 )*N+JR )140 CONTINUE150 CONTINUEXMAX = SCALE*XMAXEND IFXMAX = MAX( XMAX, TEMP )160 CONTINUE** Copy eigenvector to VL, back transforming if* HOWMNY='B'.*IEIG = IEIG + 1IF( ILBACK ) THENDO 170 JW = 0, NW - 1CALL DGEMV( 'N', N, N+1-JE, ONE, VL( 1, JE ), LDVL,$ WORK( ( JW+2 )*N+JE ), 1, ZERO,$ WORK( ( JW+4 )*N+1 ), 1 )170 CONTINUECALL DLACPY( ' ', N, NW, WORK( 4*N+1 ), N, VL( 1, JE ),$ LDVL )IBEG = 1ELSECALL DLACPY( ' ', N, NW, WORK( 2*N+1 ), N, VL( 1, IEIG ),$ LDVL )IBEG = JEEND IF** Scale eigenvector*XMAX = ZEROIF( ILCPLX ) THENDO 180 J = IBEG, NXMAX = MAX( XMAX, ABS( VL( J, IEIG ) )+$ ABS( VL( J, IEIG+1 ) ) )180 CONTINUEELSEDO 190 J = IBEG, NXMAX = MAX( XMAX, ABS( VL( J, IEIG ) ) )190 CONTINUEEND IF*IF( XMAX.GT.SAFMIN ) THENXSCALE = ONE / XMAX*DO 210 JW = 0, NW - 1DO 200 JR = IBEG, NVL( JR, IEIG+JW ) = XSCALE*VL( JR, IEIG+JW )200 CONTINUE210 CONTINUEEND IFIEIG = IEIG + NW - 1*220 CONTINUEEND IF** Right eigenvectors*IF( COMPR ) THENIEIG = IM + 1** Main loop over eigenvalues*ILCPLX = .FALSE.DO 500 JE = N, 1, -1** Skip this iteration if (a) HOWMNY='S' and SELECT=.FALSE., or* (b) this would be the second of a complex pair.* Check for complex eigenvalue, so as to be sure of which* entry(-ies) of SELECT to look at -- if complex, SELECT(JE)* or SELECT(JE-1).* If this is a complex pair, the 2-by-2 diagonal block* corresponding to the eigenvalue is in rows/columns JE-1:JE*IF( ILCPLX ) THENILCPLX = .FALSE.GO TO 500END IFNW = 1IF( JE.GT.1 ) THENIF( A( JE, JE-1 ).NE.ZERO ) THENILCPLX = .TRUE.NW = 2END IFEND IFIF( ILALL ) THENILCOMP = .TRUE.ELSE IF( ILCPLX ) THENILCOMP = SELECT( JE ) .OR. SELECT( JE-1 )ELSEILCOMP = SELECT( JE )END IFIF( .NOT.ILCOMP )$ GO TO 500** Decide if (a) singular pencil, (b) real eigenvalue, or* (c) complex eigenvalue.*IF( .NOT.ILCPLX ) THENIF( ABS( A( JE, JE ) ).LE.SAFMIN .AND.$ ABS( B( JE, JE ) ).LE.SAFMIN ) THEN** Singular matrix pencil -- unit eigenvector*IEIG = IEIG - 1DO 230 JR = 1, NVR( JR, IEIG ) = ZERO230 CONTINUEVR( IEIG, IEIG ) = ONEGO TO 500END IFEND IF** Clear vector*DO 250 JW = 0, NW - 1DO 240 JR = 1, NWORK( ( JW+2 )*N+JR ) = ZERO240 CONTINUE250 CONTINUE** Compute coefficients in ( a A - b B ) x = 0* a is ACOEF* b is BCOEFR + i*BCOEFI*IF( .NOT.ILCPLX ) THEN** Real eigenvalue*TEMP = ONE / MAX( ABS( A( JE, JE ) )*ASCALE,$ ABS( B( JE, JE ) )*BSCALE, SAFMIN )SALFAR = ( TEMP*A( JE, JE ) )*ASCALESBETA = ( TEMP*B( JE, JE ) )*BSCALEACOEF = SBETA*ASCALEBCOEFR = SALFAR*BSCALEBCOEFI = ZERO** Scale to avoid underflow*SCALE = ONELSA = ABS( SBETA ).GE.SAFMIN .AND. ABS( ACOEF ).LT.SMALLLSB = ABS( SALFAR ).GE.SAFMIN .AND. ABS( BCOEFR ).LT.$ SMALLIF( LSA )$ SCALE = ( SMALL / ABS( SBETA ) )*MIN( ANORM, BIG )IF( LSB )$ SCALE = MAX( SCALE, ( SMALL / ABS( SALFAR ) )*$ MIN( BNORM, BIG ) )IF( LSA .OR. LSB ) THENSCALE = MIN( SCALE, ONE /$ ( SAFMIN*MAX( ONE, ABS( ACOEF ),$ ABS( BCOEFR ) ) ) )IF( LSA ) THENACOEF = ASCALE*( SCALE*SBETA )ELSEACOEF = SCALE*ACOEFEND IFIF( LSB ) THENBCOEFR = BSCALE*( SCALE*SALFAR )ELSEBCOEFR = SCALE*BCOEFREND IFEND IFACOEFA = ABS( ACOEF )BCOEFA = ABS( BCOEFR )** First component is 1*WORK( 2*N+JE ) = ONEXMAX = ONE** Compute contribution from column JE of A and B to sum* (See "Further Details", above.)*DO 260 JR = 1, JE - 1WORK( 2*N+JR ) = BCOEFR*B( JR, JE ) -$ ACOEF*A( JR, JE )260 CONTINUEELSE** Complex eigenvalue*CALL DLAG2( A( JE-1, JE-1 ), LDA, B( JE-1, JE-1 ), LDB,$ SAFMIN*SAFETY, ACOEF, TEMP, BCOEFR, TEMP2,$ BCOEFI )IF( BCOEFI.EQ.ZERO ) THENINFO = JE - 1RETURNEND IF** Scale to avoid over/underflow*ACOEFA = ABS( ACOEF )BCOEFA = ABS( BCOEFR ) + ABS( BCOEFI )SCALE = ONEIF( ACOEFA*ULP.LT.SAFMIN .AND. ACOEFA.GE.SAFMIN )$ SCALE = ( SAFMIN / ULP ) / ACOEFAIF( BCOEFA*ULP.LT.SAFMIN .AND. BCOEFA.GE.SAFMIN )$ SCALE = MAX( SCALE, ( SAFMIN / ULP ) / BCOEFA )IF( SAFMIN*ACOEFA.GT.ASCALE )$ SCALE = ASCALE / ( SAFMIN*ACOEFA )IF( SAFMIN*BCOEFA.GT.BSCALE )$ SCALE = MIN( SCALE, BSCALE / ( SAFMIN*BCOEFA ) )IF( SCALE.NE.ONE ) THENACOEF = SCALE*ACOEFACOEFA = ABS( ACOEF )BCOEFR = SCALE*BCOEFRBCOEFI = SCALE*BCOEFIBCOEFA = ABS( BCOEFR ) + ABS( BCOEFI )END IF** Compute first two components of eigenvector* and contribution to sums*TEMP = ACOEF*A( JE, JE-1 )TEMP2R = ACOEF*A( JE, JE ) - BCOEFR*B( JE, JE )TEMP2I = -BCOEFI*B( JE, JE )IF( ABS( TEMP ).GE.ABS( TEMP2R )+ABS( TEMP2I ) ) THENWORK( 2*N+JE ) = ONEWORK( 3*N+JE ) = ZEROWORK( 2*N+JE-1 ) = -TEMP2R / TEMPWORK( 3*N+JE-1 ) = -TEMP2I / TEMPELSEWORK( 2*N+JE-1 ) = ONEWORK( 3*N+JE-1 ) = ZEROTEMP = ACOEF*A( JE-1, JE )WORK( 2*N+JE ) = ( BCOEFR*B( JE-1, JE-1 )-ACOEF*$ A( JE-1, JE-1 ) ) / TEMPWORK( 3*N+JE ) = BCOEFI*B( JE-1, JE-1 ) / TEMPEND IF*XMAX = MAX( ABS( WORK( 2*N+JE ) )+ABS( WORK( 3*N+JE ) ),$ ABS( WORK( 2*N+JE-1 ) )+ABS( WORK( 3*N+JE-1 ) ) )** Compute contribution from columns JE and JE-1* of A and B to the sums.*CREALA = ACOEF*WORK( 2*N+JE-1 )CIMAGA = ACOEF*WORK( 3*N+JE-1 )CREALB = BCOEFR*WORK( 2*N+JE-1 ) -$ BCOEFI*WORK( 3*N+JE-1 )CIMAGB = BCOEFI*WORK( 2*N+JE-1 ) +$ BCOEFR*WORK( 3*N+JE-1 )CRE2A = ACOEF*WORK( 2*N+JE )CIM2A = ACOEF*WORK( 3*N+JE )CRE2B = BCOEFR*WORK( 2*N+JE ) - BCOEFI*WORK( 3*N+JE )CIM2B = BCOEFI*WORK( 2*N+JE ) + BCOEFR*WORK( 3*N+JE )DO 270 JR = 1, JE - 2WORK( 2*N+JR ) = -CREALA*A( JR, JE-1 ) +$ CREALB*B( JR, JE-1 ) -$ CRE2A*A( JR, JE ) + CRE2B*B( JR, JE )WORK( 3*N+JR ) = -CIMAGA*A( JR, JE-1 ) +$ CIMAGB*B( JR, JE-1 ) -$ CIM2A*A( JR, JE ) + CIM2B*B( JR, JE )270 CONTINUEEND IF*DMIN = MAX( ULP*ACOEFA*ANORM, ULP*BCOEFA*BNORM, SAFMIN )** Columnwise triangular solve of (a A - b B) x = 0*IL2BY2 = .FALSE.DO 370 J = JE - NW, 1, -1** If a 2-by-2 block, is in position j-1:j, wait until* next iteration to process it (when it will be j:j+1)*IF( .NOT.IL2BY2 .AND. J.GT.1 ) THENIF( A( J, J-1 ).NE.ZERO ) THENIL2BY2 = .TRUE.GO TO 370END IFEND IFBDIAG( 1 ) = B( J, J )IF( IL2BY2 ) THENNA = 2BDIAG( 2 ) = B( J+1, J+1 )ELSENA = 1END IF** Compute x(j) (and x(j+1), if 2-by-2 block)*CALL DLALN2( .FALSE., NA, NW, DMIN, ACOEF, A( J, J ),$ LDA, BDIAG( 1 ), BDIAG( 2 ), WORK( 2*N+J ),$ N, BCOEFR, BCOEFI, SUM, 2, SCALE, TEMP,$ IINFO )IF( SCALE.LT.ONE ) THEN*DO 290 JW = 0, NW - 1DO 280 JR = 1, JEWORK( ( JW+2 )*N+JR ) = SCALE*$ WORK( ( JW+2 )*N+JR )280 CONTINUE290 CONTINUEEND IFXMAX = MAX( SCALE*XMAX, TEMP )*DO 310 JW = 1, NWDO 300 JA = 1, NAWORK( ( JW+1 )*N+J+JA-1 ) = SUM( JA, JW )300 CONTINUE310 CONTINUE** w = w + x(j)*(a A(*,j) - b B(*,j) ) with scaling*IF( J.GT.1 ) THEN** Check whether scaling is necessary for sum.*XSCALE = ONE / MAX( ONE, XMAX )TEMP = ACOEFA*WORK( J ) + BCOEFA*WORK( N+J )IF( IL2BY2 )$ TEMP = MAX( TEMP, ACOEFA*WORK( J+1 )+BCOEFA*$ WORK( N+J+1 ) )TEMP = MAX( TEMP, ACOEFA, BCOEFA )IF( TEMP.GT.BIGNUM*XSCALE ) THEN*DO 330 JW = 0, NW - 1DO 320 JR = 1, JEWORK( ( JW+2 )*N+JR ) = XSCALE*$ WORK( ( JW+2 )*N+JR )320 CONTINUE330 CONTINUEXMAX = XMAX*XSCALEEND IF** Compute the contributions of the off-diagonals of* column j (and j+1, if 2-by-2 block) of A and B to the* sums.**DO 360 JA = 1, NAIF( ILCPLX ) THENCREALA = ACOEF*WORK( 2*N+J+JA-1 )CIMAGA = ACOEF*WORK( 3*N+J+JA-1 )CREALB = BCOEFR*WORK( 2*N+J+JA-1 ) -$ BCOEFI*WORK( 3*N+J+JA-1 )CIMAGB = BCOEFI*WORK( 2*N+J+JA-1 ) +$ BCOEFR*WORK( 3*N+J+JA-1 )DO 340 JR = 1, J - 1WORK( 2*N+JR ) = WORK( 2*N+JR ) -$ CREALA*A( JR, J+JA-1 ) +$ CREALB*B( JR, J+JA-1 )WORK( 3*N+JR ) = WORK( 3*N+JR ) -$ CIMAGA*A( JR, J+JA-1 ) +$ CIMAGB*B( JR, J+JA-1 )340 CONTINUEELSECREALA = ACOEF*WORK( 2*N+J+JA-1 )CREALB = BCOEFR*WORK( 2*N+J+JA-1 )DO 350 JR = 1, J - 1WORK( 2*N+JR ) = WORK( 2*N+JR ) -$ CREALA*A( JR, J+JA-1 ) +$ CREALB*B( JR, J+JA-1 )350 CONTINUEEND IF360 CONTINUEEND IF*IL2BY2 = .FALSE.370 CONTINUE** Copy eigenvector to VR, back transforming if* HOWMNY='B'.*IEIG = IEIG - NWIF( ILBACK ) THEN*DO 410 JW = 0, NW - 1DO 380 JR = 1, NWORK( ( JW+4 )*N+JR ) = WORK( ( JW+2 )*N+1 )*$ VR( JR, 1 )380 CONTINUE** A series of compiler directives to defeat* vectorization for the next loop**DO 400 JC = 2, JEDO 390 JR = 1, NWORK( ( JW+4 )*N+JR ) = WORK( ( JW+4 )*N+JR ) +$ WORK( ( JW+2 )*N+JC )*VR( JR, JC )390 CONTINUE400 CONTINUE410 CONTINUE*DO 430 JW = 0, NW - 1DO 420 JR = 1, NVR( JR, IEIG+JW ) = WORK( ( JW+4 )*N+JR )420 CONTINUE430 CONTINUE*IEND = NELSEDO 450 JW = 0, NW - 1DO 440 JR = 1, NVR( JR, IEIG+JW ) = WORK( ( JW+2 )*N+JR )440 CONTINUE450 CONTINUE*IEND = JEEND IF** Scale eigenvector*XMAX = ZEROIF( ILCPLX ) THENDO 460 J = 1, IENDXMAX = MAX( XMAX, ABS( VR( J, IEIG ) )+$ ABS( VR( J, IEIG+1 ) ) )460 CONTINUEELSEDO 470 J = 1, IENDXMAX = MAX( XMAX, ABS( VR( J, IEIG ) ) )470 CONTINUEEND IF*IF( XMAX.GT.SAFMIN ) THENXSCALE = ONE / XMAXDO 490 JW = 0, NW - 1DO 480 JR = 1, IENDVR( JR, IEIG+JW ) = XSCALE*VR( JR, IEIG+JW )480 CONTINUE490 CONTINUEEND IF500 CONTINUEEND IF*RETURN** End of DTGEVC*ENDSUBROUTINE DTGEXC( WANTQ, WANTZ, N, A, LDA, B, LDB, Q, LDQ, Z,$ LDZ, IFST, ILST, WORK, LWORK, INFO )** -- LAPACK routine (version 3.0) --* Univ. of Tennessee, Univ. of California Berkeley, NAG Ltd.,* Courant Institute, Argonne National Lab, and Rice University* June 30, 1999** .. Scalar Arguments ..LOGICAL WANTQ, WANTZINTEGER IFST, ILST, INFO, LDA, LDB, LDQ, LDZ, LWORK, N* ..* .. Array Arguments ..DOUBLE PRECISION A( LDA, * ), B( LDB, * ), Q( LDQ, * ),$ WORK( * ), Z( LDZ, * )* ..** Purpose* =======** DTGEXC reorders the generalized real Schur decomposition of a real* matrix pair (A,B) using an orthogonal equivalence transformation** (A, B) = Q * (A, B) * Z',** so that the diagonal block of (A, B) with row index IFST is moved* to row ILST.** (A, B) must be in generalized real Schur canonical form (as returned* by DGGES), i.e. A is block upper triangular with 1-by-1 and 2-by-2* diagonal blocks. B is upper triangular.** Optionally, the matrices Q and Z of generalized Schur vectors are* updated.** Q(in) * A(in) * Z(in)' = Q(out) * A(out) * Z(out)'* Q(in) * B(in) * Z(in)' = Q(out) * B(out) * Z(out)'*** Arguments* =========** WANTQ (input) LOGICAL* .TRUE. : update the left transformation matrix Q;* .FALSE.: do not update Q.** WANTZ (input) LOGICAL* .TRUE. : update the right transformation matrix Z;* .FALSE.: do not update Z.** N (input) INTEGER* The order of the matrices A and B. N >= 0.** A (input/output) DOUBLE PRECISION array, dimension (LDA,N)* On entry, the matrix A in generalized real Schur canonical* form.* On exit, the updated matrix A, again in generalized* real Schur canonical form.** LDA (input) INTEGER* The leading dimension of the array A. LDA >= max(1,N).** B (input/output) DOUBLE PRECISION array, dimension (LDB,N)* On entry, the matrix B in generalized real Schur canonical* form (A,B).* On exit, the updated matrix B, again in generalized* real Schur canonical form (A,B).** LDB (input) INTEGER* The leading dimension of the array B. LDB >= max(1,N).** Q (input/output) DOUBLE PRECISION array, dimension (LDZ,N)* On entry, if WANTQ = .TRUE., the orthogonal matrix Q.* On exit, the updated matrix Q.* If WANTQ = .FALSE., Q is not referenced.** LDQ (input) INTEGER* The leading dimension of the array Q. LDQ >= 1.* If WANTQ = .TRUE., LDQ >= N.** Z (input/output) DOUBLE PRECISION array, dimension (LDZ,N)* On entry, if WANTZ = .TRUE., the orthogonal matrix Z.* On exit, the updated matrix Z.* If WANTZ = .FALSE., Z is not referenced.** LDZ (input) INTEGER* The leading dimension of the array Z. LDZ >= 1.* If WANTZ = .TRUE., LDZ >= N.** IFST (input/output) INTEGER* ILST (input/output) INTEGER* Specify the reordering of the diagonal blocks of (A, B).* The block with row index IFST is moved to row ILST, by a* sequence of swapping between adjacent blocks.* On exit, if IFST pointed on entry to the second row of* a 2-by-2 block, it is changed to point to the first row;* ILST always points to the first row of the block in its* final position (which may differ from its input value by* +1 or -1). 1 <= IFST, ILST <= N.** WORK (workspace/output) 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 >= 4*N + 16.** If LWORK = -1, then a workspace query is assumed; the routine* only calculates the optimal size of the WORK array, returns* this value as the first entry of the WORK array, and no error* message related to LWORK is issued by XERBLA.** INFO (output) INTEGER* =0: successful exit.* <0: if INFO = -i, the i-th argument had an illegal value.* =1: The transformed matrix pair (A, B) would be too far* from generalized Schur form; the problem is ill-* conditioned. (A, B) may have been partially reordered,* and ILST points to the first row of the current* position of the block being moved.** Further Details* ===============** Based on contributions by* Bo Kagstrom and Peter Poromaa, Department of Computing Science,* Umea University, S-901 87 Umea, Sweden.** [1] B. Kagstrom; A Direct Method for Reordering Eigenvalues in the* Generalized Real Schur Form of a Regular Matrix Pair (A, B), in* M.S. Moonen et al (eds), Linear Algebra for Large Scale and* Real-Time Applications, Kluwer Academic Publ. 1993, pp 195-218.** =====================================================================** .. Parameters ..DOUBLE PRECISION ZEROPARAMETER ( ZERO = 0.0D+0 )* ..* .. Local Scalars ..LOGICAL LQUERYINTEGER HERE, LWMIN, NBF, NBL, NBNEXT* ..* .. External Subroutines ..EXTERNAL DTGEX2, XERBLA* ..* .. Intrinsic Functions ..INTRINSIC MAX* ..* .. Executable Statements ..** Decode and test input arguments.*INFO = 0LWMIN = MAX( 1, 4*N+16 )LQUERY = ( LWORK.EQ.-1 )IF( N.LT.0 ) THENINFO = -3ELSE IF( LDA.LT.MAX( 1, N ) ) THENINFO = -5ELSE IF( LDB.LT.MAX( 1, N ) ) THENINFO = -7ELSE IF( LDQ.LT.1 .OR. WANTQ .AND. ( LDQ.LT.MAX( 1, N ) ) ) THENINFO = -9ELSE IF( LDZ.LT.1 .OR. WANTZ .AND. ( LDZ.LT.MAX( 1, N ) ) ) THENINFO = -11ELSE IF( IFST.LT.1 .OR. IFST.GT.N ) THENINFO = -12ELSE IF( ILST.LT.1 .OR. ILST.GT.N ) THENINFO = -13ELSE IF( LWORK.LT.LWMIN .AND. .NOT.LQUERY ) THENINFO = -15END IF*IF( INFO.EQ.0 ) THENWORK( 1 ) = LWMINEND IF*IF( INFO.NE.0 ) THENCALL XERBLA( 'DTGEXC', -INFO )RETURNELSE IF( LQUERY ) THENRETURNEND IF** Quick return if possible*IF( N.LE.1 )$ RETURN** Determine the first row of the specified block and find out* if it is 1-by-1 or 2-by-2.*IF( IFST.GT.1 ) THENIF( A( IFST, IFST-1 ).NE.ZERO )$ IFST = IFST - 1END IFNBF = 1IF( IFST.LT.N ) THENIF( A( IFST+1, IFST ).NE.ZERO )$ NBF = 2END IF** Determine the first row of the final block* and find out if it is 1-by-1 or 2-by-2.*IF( ILST.GT.1 ) THENIF( A( ILST, ILST-1 ).NE.ZERO )$ ILST = ILST - 1END IFNBL = 1IF( ILST.LT.N ) THENIF( A( ILST+1, ILST ).NE.ZERO )$ NBL = 2END IFIF( IFST.EQ.ILST )$ RETURN*IF( IFST.LT.ILST ) THEN** Update ILST.*IF( NBF.EQ.2 .AND. NBL.EQ.1 )$ ILST = ILST - 1IF( NBF.EQ.1 .AND. NBL.EQ.2 )$ ILST = ILST + 1*HERE = IFST*10 CONTINUE** Swap with next one below.*IF( NBF.EQ.1 .OR. NBF.EQ.2 ) THEN** Current block either 1-by-1 or 2-by-2.*NBNEXT = 1IF( HERE+NBF+1.LE.N ) THENIF( A( HERE+NBF+1, HERE+NBF ).NE.ZERO )$ NBNEXT = 2END IFCALL DTGEX2( WANTQ, WANTZ, N, A, LDA, B, LDB, Q, LDQ, Z,$ LDZ, HERE, NBF, NBNEXT, WORK, LWORK, INFO )IF( INFO.NE.0 ) THENILST = HERERETURNEND IFHERE = HERE + NBNEXT** Test if 2-by-2 block breaks into two 1-by-1 blocks.*IF( NBF.EQ.2 ) THENIF( A( HERE+1, HERE ).EQ.ZERO )$ NBF = 3END IF*ELSE** Current block consists of two 1-by-1 blocks, each of which* must be swapped individually.*NBNEXT = 1IF( HERE+3.LE.N ) THENIF( A( HERE+3, HERE+2 ).NE.ZERO )$ NBNEXT = 2END IFCALL DTGEX2( WANTQ, WANTZ, N, A, LDA, B, LDB, Q, LDQ, Z,$ LDZ, HERE+1, 1, NBNEXT, WORK, LWORK, INFO )IF( INFO.NE.0 ) THENILST = HERERETURNEND IFIF( NBNEXT.EQ.1 ) THEN** Swap two 1-by-1 blocks.*CALL DTGEX2( WANTQ, WANTZ, N, A, LDA, B, LDB, Q, LDQ, Z,$ LDZ, HERE, 1, 1, WORK, LWORK, INFO )IF( INFO.NE.0 ) THENILST = HERERETURNEND IFHERE = HERE + 1*ELSE** Recompute NBNEXT in case of 2-by-2 split.*IF( A( HERE+2, HERE+1 ).EQ.ZERO )$ NBNEXT = 1IF( NBNEXT.EQ.2 ) THEN** 2-by-2 block did not split.*CALL DTGEX2( WANTQ, WANTZ, N, A, LDA, B, LDB, Q, LDQ,$ Z, LDZ, HERE, 1, NBNEXT, WORK, LWORK,$ INFO )IF( INFO.NE.0 ) THENILST = HERERETURNEND IFHERE = HERE + 2ELSE** 2-by-2 block did split.*CALL DTGEX2( WANTQ, WANTZ, N, A, LDA, B, LDB, Q, LDQ,$ Z, LDZ, HERE, 1, 1, WORK, LWORK, INFO )IF( INFO.NE.0 ) THENILST = HERERETURNEND IFHERE = HERE + 1CALL DTGEX2( WANTQ, WANTZ, N, A, LDA, B, LDB, Q, LDQ,$ Z, LDZ, HERE, 1, 1, WORK, LWORK, INFO )IF( INFO.NE.0 ) THENILST = HERERETURNEND IFHERE = HERE + 1END IF*END IFEND IFIF( HERE.LT.ILST )$ GO TO 10ELSEHERE = IFST*20 CONTINUE** Swap with next one below.*IF( NBF.EQ.1 .OR. NBF.EQ.2 ) THEN** Current block either 1-by-1 or 2-by-2.*NBNEXT = 1IF( HERE.GE.3 ) THENIF( A( HERE-1, HERE-2 ).NE.ZERO )$ NBNEXT = 2END IFCALL DTGEX2( WANTQ, WANTZ, N, A, LDA, B, LDB, Q, LDQ, Z,$ LDZ, HERE-NBNEXT, NBNEXT, NBF, WORK, LWORK,$ INFO )IF( INFO.NE.0 ) THENILST = HERERETURNEND IFHERE = HERE - NBNEXT** Test if 2-by-2 block breaks into two 1-by-1 blocks.*IF( NBF.EQ.2 ) THENIF( A( HERE+1, HERE ).EQ.ZERO )$ NBF = 3END IF*ELSE** Current block consists of two 1-by-1 blocks, each of which* must be swapped individually.*NBNEXT = 1IF( HERE.GE.3 ) THENIF( A( HERE-1, HERE-2 ).NE.ZERO )$ NBNEXT = 2END IFCALL DTGEX2( WANTQ, WANTZ, N, A, LDA, B, LDB, Q, LDQ, Z,$ LDZ, HERE-NBNEXT, NBNEXT, 1, WORK, LWORK,$ INFO )IF( INFO.NE.0 ) THENILST = HERERETURNEND IFIF( NBNEXT.EQ.1 ) THEN** Swap two 1-by-1 blocks.*CALL DTGEX2( WANTQ, WANTZ, N, A, LDA, B, LDB, Q, LDQ, Z,$ LDZ, HERE, NBNEXT, 1, WORK, LWORK, INFO )IF( INFO.NE.0 ) THENILST = HERERETURNEND IFHERE = HERE - 1ELSE** Recompute NBNEXT in case of 2-by-2 split.*IF( A( HERE, HERE-1 ).EQ.ZERO )$ NBNEXT = 1IF( NBNEXT.EQ.2 ) THEN** 2-by-2 block did not split.*CALL DTGEX2( WANTQ, WANTZ, N, A, LDA, B, LDB, Q, LDQ,$ Z, LDZ, HERE-1, 2, 1, WORK, LWORK, INFO )IF( INFO.NE.0 ) THENILST = HERERETURNEND IFHERE = HERE - 2ELSE** 2-by-2 block did split.*CALL DTGEX2( WANTQ, WANTZ, N, A, LDA, B, LDB, Q, LDQ,$ Z, LDZ, HERE, 1, 1, WORK, LWORK, INFO )IF( INFO.NE.0 ) THENILST = HERERETURNEND IFHERE = HERE - 1CALL DTGEX2( WANTQ, WANTZ, N, A, LDA, B, LDB, Q, LDQ,$ Z, LDZ, HERE, 1, 1, WORK, LWORK, INFO )IF( INFO.NE.0 ) THENILST = HERERETURNEND IFHERE = HERE - 1END IFEND IFEND IFIF( HERE.GT.ILST )$ GO TO 20END IFILST = HEREWORK( 1 ) = LWMINRETURN** End of DTGEXC*ENDSUBROUTINE DTGSEN( IJOB, WANTQ, WANTZ, SELECT, N, A, LDA, B, LDB,$ ALPHAR, ALPHAI, BETA, Q, LDQ, Z, LDZ, M, PL,$ PR, DIF, WORK, LWORK, IWORK, LIWORK, INFO )** -- LAPACK routine (version 3.0) --* Univ. of Tennessee, Univ. of California Berkeley, NAG Ltd.,* Courant Institute, Argonne National Lab, and Rice University* June 30, 1999** .. Scalar Arguments ..LOGICAL WANTQ, WANTZINTEGER IJOB, INFO, LDA, LDB, LDQ, LDZ, LIWORK, LWORK,$ M, NDOUBLE PRECISION PL, PR* ..* .. Array Arguments ..LOGICAL SELECT( * )INTEGER IWORK( * )DOUBLE PRECISION A( LDA, * ), ALPHAI( * ), ALPHAR( * ),$ B( LDB, * ), BETA( * ), DIF( * ), Q( LDQ, * ),$ WORK( * ), Z( LDZ, * )* ..** Purpose* =======** DTGSEN reorders the generalized real Schur decomposition of a real* matrix pair (A, B) (in terms of an orthonormal equivalence trans-* formation Q' * (A, B) * Z), so that a selected cluster of eigenvalues* appears in the leading diagonal blocks of the upper quasi-triangular* matrix A and the upper triangular B. The leading columns of Q and* Z form orthonormal bases of the corresponding left and right eigen-* spaces (deflating subspaces). (A, B) must be in generalized real* Schur canonical form (as returned by DGGES), i.e. A is block upper* triangular with 1-by-1 and 2-by-2 diagonal blocks. B is upper* triangular.** DTGSEN also computes the generalized eigenvalues** w(j) = (ALPHAR(j) + i*ALPHAI(j))/BETA(j)** of the reordered matrix pair (A, B).** Optionally, DTGSEN computes the estimates of reciprocal condition* numbers for eigenvalues and eigenspaces. These are Difu[(A11,B11),* (A22,B22)] and Difl[(A11,B11), (A22,B22)], i.e. the separation(s)* between the matrix pairs (A11, B11) and (A22,B22) that correspond to* the selected cluster and the eigenvalues outside the cluster, resp.,* and norms of "projections" onto left and right eigenspaces w.r.t.* the selected cluster in the (1,1)-block.** Arguments* =========** IJOB (input) INTEGER* Specifies whether condition numbers are required for the* cluster of eigenvalues (PL and PR) or the deflating subspaces* (Difu and Difl):* =0: Only reorder w.r.t. SELECT. No extras.* =1: Reciprocal of norms of "projections" onto left and right* eigenspaces w.r.t. the selected cluster (PL and PR).* =2: Upper bounds on Difu and Difl. F-norm-based estimate* (DIF(1:2)).* =3: Estimate of Difu and Difl. 1-norm-based estimate* (DIF(1:2)).* About 5 times as expensive as IJOB = 2.* =4: Compute PL, PR and DIF (i.e. 0, 1 and 2 above): Economic* version to get it all.* =5: Compute PL, PR and DIF (i.e. 0, 1 and 3 above)** WANTQ (input) LOGICAL* .TRUE. : update the left transformation matrix Q;* .FALSE.: do not update Q.** WANTZ (input) LOGICAL* .TRUE. : update the right transformation matrix Z;* .FALSE.: do not update Z.** SELECT (input) LOGICAL array, dimension (N)* SELECT specifies the eigenvalues in the selected cluster.* To select a real eigenvalue w(j), SELECT(j) must be set to* .TRUE.. To select a complex conjugate pair of eigenvalues* w(j) and w(j+1), corresponding to a 2-by-2 diagonal block,* either SELECT(j) or SELECT(j+1) or both must be set to* .TRUE.; a complex conjugate pair of eigenvalues must be* either both included in the cluster or both excluded.** N (input) INTEGER* The order of the matrices A and B. N >= 0.** A (input/output) DOUBLE PRECISION array, dimension(LDA,N)* On entry, the upper quasi-triangular matrix A, with (A, B) in* generalized real Schur canonical form.* On exit, A is overwritten by the reordered matrix A.** LDA (input) INTEGER* The leading dimension of the array A. LDA >= max(1,N).** B (input/output) DOUBLE PRECISION array, dimension(LDB,N)* On entry, the upper triangular matrix B, with (A, B) in* generalized real Schur canonical form.* On exit, B is overwritten by the reordered matrix B.** LDB (input) INTEGER* The leading dimension of the array B. LDB >= max(1,N).** ALPHAR (output) DOUBLE PRECISION array, dimension (N)* ALPHAI (output) DOUBLE PRECISION array, dimension (N)* BETA (output) DOUBLE PRECISION array, dimension (N)* On exit, (ALPHAR(j) + ALPHAI(j)*i)/BETA(j), j=1,...,N, will* be the generalized eigenvalues. ALPHAR(j) + ALPHAI(j)*i* and BETA(j),j=1,...,N are the diagonals of the complex Schur* form (S,T) that would result if the 2-by-2 diagonal blocks of* the real generalized Schur form of (A,B) were further reduced* to triangular form using complex unitary transformations.* If ALPHAI(j) is zero, then the j-th eigenvalue is real; if* positive, then the j-th and (j+1)-st eigenvalues are a* complex conjugate pair, with ALPHAI(j+1) negative.** Q (input/output) DOUBLE PRECISION array, dimension (LDQ,N)* On entry, if WANTQ = .TRUE., Q is an N-by-N matrix.* On exit, Q has been postmultiplied by the left orthogonal* transformation matrix which reorder (A, B); The leading M* columns of Q form orthonormal bases for the specified pair of* left eigenspaces (deflating subspaces).* If WANTQ = .FALSE., Q is not referenced.** LDQ (input) INTEGER* The leading dimension of the array Q. LDQ >= 1;* and if WANTQ = .TRUE., LDQ >= N.** Z (input/output) DOUBLE PRECISION array, dimension (LDZ,N)* On entry, if WANTZ = .TRUE., Z is an N-by-N matrix.* On exit, Z has been postmultiplied by the left orthogonal* transformation matrix which reorder (A, B); The leading M* columns of Z form orthonormal bases for the specified pair of* left eigenspaces (deflating subspaces).* If WANTZ = .FALSE., Z is not referenced.** LDZ (input) INTEGER* The leading dimension of the array Z. LDZ >= 1;* If WANTZ = .TRUE., LDZ >= N.** M (output) INTEGER* The dimension of the specified pair of left and right eigen-* spaces (deflating subspaces). 0 <= M <= N.** PL, PR (output) DOUBLE PRECISION* If IJOB = 1, 4 or 5, PL, PR are lower bounds on the* reciprocal of the norm of "projections" onto left and right* eigenspaces with respect to the selected cluster.* 0 < PL, PR <= 1.* If M = 0 or M = N, PL = PR = 1.* If IJOB = 0, 2 or 3, PL and PR are not referenced.** DIF (output) DOUBLE PRECISION array, dimension (2).* If IJOB >= 2, DIF(1:2) store the estimates of Difu and Difl.* If IJOB = 2 or 4, DIF(1:2) are F-norm-based upper bounds on* Difu and Difl. If IJOB = 3 or 5, DIF(1:2) are 1-norm-based* estimates of Difu and Difl.* If M = 0 or N, DIF(1:2) = F-norm([A, B]).* If IJOB = 0 or 1, DIF is not referenced.** WORK (workspace/output) DOUBLE PRECISION array, dimension (LWORK)* IF IJOB = 0, WORK is not referenced. Otherwise,* on exit, if INFO = 0, WORK(1) returns the optimal LWORK.** LWORK (input) INTEGER* The dimension of the array WORK. LWORK >= 4*N+16.* If IJOB = 1, 2 or 4, LWORK >= MAX(4*N+16, 2*M*(N-M)).* If IJOB = 3 or 5, LWORK >= MAX(4*N+16, 4*M*(N-M)).** If LWORK = -1, then a workspace query is assumed; the routine* only calculates the optimal size of the WORK array, returns* this value as the first entry of the WORK array, and no error* message related to LWORK is issued by XERBLA.** IWORK (workspace/output) INTEGER array, dimension (LIWORK)* IF IJOB = 0, IWORK is not referenced. Otherwise,* on exit, if INFO = 0, IWORK(1) returns the optimal LIWORK.** LIWORK (input) INTEGER* The dimension of the array IWORK. LIWORK >= 1.* If IJOB = 1, 2 or 4, LIWORK >= N+6.* If IJOB = 3 or 5, LIWORK >= MAX(2*M*(N-M), N+6).** If LIWORK = -1, then a workspace query is assumed; the* routine only calculates the optimal size of the IWORK array,* returns this value as the first entry of the IWORK array, and* no error message related to LIWORK is issued by XERBLA.** INFO (output) INTEGER* =0: Successful exit.* <0: If INFO = -i, the i-th argument had an illegal value.* =1: Reordering of (A, B) failed because the transformed* matrix pair (A, B) would be too far from generalized* Schur form; the problem is very ill-conditioned.* (A, B) may have been partially reordered.* If requested, 0 is returned in DIF(*), PL and PR.** Further Details* ===============** DTGSEN first collects the selected eigenvalues by computing* orthogonal U and W that move them to the top left corner of (A, B).* In other words, the selected eigenvalues are the eigenvalues of* (A11, B11) in:** U'*(A, B)*W = (A11 A12) (B11 B12) n1* ( 0 A22),( 0 B22) n2* n1 n2 n1 n2** where N = n1+n2 and U' means the transpose of U. The first n1 columns* of U and W span the specified pair of left and right eigenspaces* (deflating subspaces) of (A, B).** If (A, B) has been obtained from the generalized real Schur* decomposition of a matrix pair (C, D) = Q*(A, B)*Z', then the* reordered generalized real Schur form of (C, D) is given by** (C, D) = (Q*U)*(U'*(A, B)*W)*(Z*W)',** and the first n1 columns of Q*U and Z*W span the corresponding* deflating subspaces of (C, D) (Q and Z store Q*U and Z*W, resp.).** Note that if the selected eigenvalue is sufficiently ill-conditioned,* then its value may differ significantly from its value before* reordering.** The reciprocal condition numbers of the left and right eigenspaces* spanned by the first n1 columns of U and W (or Q*U and Z*W) may* be returned in DIF(1:2), corresponding to Difu and Difl, resp.** The Difu and Difl are defined as:** Difu[(A11, B11), (A22, B22)] = sigma-min( Zu )* and* Difl[(A11, B11), (A22, B22)] = Difu[(A22, B22), (A11, B11)],** where sigma-min(Zu) is the smallest singular value of the* (2*n1*n2)-by-(2*n1*n2) matrix** Zu = [ kron(In2, A11) -kron(A22', In1) ]* [ kron(In2, B11) -kron(B22', In1) ].** Here, Inx is the identity matrix of size nx and A22' is the* transpose of A22. kron(X, Y) is the Kronecker product between* the matrices X and Y.** When DIF(2) is small, small changes in (A, B) can cause large changes* in the deflating subspace. An approximate (asymptotic) bound on the* maximum angular error in the computed deflating subspaces is** EPS * norm((A, B)) / DIF(2),** where EPS is the machine precision.** The reciprocal norm of the projectors on the left and right* eigenspaces associated with (A11, B11) may be returned in PL and PR.* They are computed as follows. First we compute L and R so that* P*(A, B)*Q is block diagonal, where** P = ( I -L ) n1 Q = ( I R ) n1* ( 0 I ) n2 and ( 0 I ) n2* n1 n2 n1 n2** and (L, R) is the solution to the generalized Sylvester equation** A11*R - L*A22 = -A12* B11*R - L*B22 = -B12** Then PL = (F-norm(L)**2+1)**(-1/2) and PR = (F-norm(R)**2+1)**(-1/2).* An approximate (asymptotic) bound on the average absolute error of* the selected eigenvalues is** EPS * norm((A, B)) / PL.** There are also global error bounds which valid for perturbations up* to a certain restriction: A lower bound (x) on the smallest* F-norm(E,F) for which an eigenvalue of (A11, B11) may move and* coalesce with an eigenvalue of (A22, B22) under perturbation (E,F),* (i.e. (A + E, B + F), is** x = min(Difu,Difl)/((1/(PL*PL)+1/(PR*PR))**(1/2)+2*max(1/PL,1/PR)).** An approximate bound on x can be computed from DIF(1:2), PL and PR.** If y = ( F-norm(E,F) / x) <= 1, the angles between the perturbed* (L', R') and unperturbed (L, R) left and right deflating subspaces* associated with the selected cluster in the (1,1)-blocks can be* bounded as** max-angle(L, L') <= arctan( y * PL / (1 - y * (1 - PL * PL)**(1/2))* max-angle(R, R') <= arctan( y * PR / (1 - y * (1 - PR * PR)**(1/2))** See LAPACK User's Guide section 4.11 or the following references* for more information.** Note that if the default method for computing the Frobenius-norm-* based estimate DIF is not wanted (see DLATDF), then the parameter* IDIFJB (see below) should be changed from 3 to 4 (routine DLATDF* (IJOB = 2 will be used)). See DTGSYL for more details.** Based on contributions by* Bo Kagstrom and Peter Poromaa, Department of Computing Science,* Umea University, S-901 87 Umea, Sweden.** References* ==========** [1] B. Kagstrom; A Direct Method for Reordering Eigenvalues in the* Generalized Real Schur Form of a Regular Matrix Pair (A, B), in* M.S. Moonen et al (eds), Linear Algebra for Large Scale and* Real-Time Applications, Kluwer Academic Publ. 1993, pp 195-218.** [2] B. Kagstrom and P. Poromaa; Computing Eigenspaces with Specified* Eigenvalues of a Regular Matrix Pair (A, B) and Condition* Estimation: Theory, Algorithms and Software,* Report UMINF - 94.04, Department of Computing Science, Umea* University, S-901 87 Umea, Sweden, 1994. Also as LAPACK Working* Note 87. To appear in Numerical Algorithms, 1996.** [3] B. Kagstrom and P. Poromaa, LAPACK-Style Algorithms and Software* for Solving the Generalized Sylvester Equation and Estimating the* Separation between Regular Matrix Pairs, Report UMINF - 93.23,* Department of Computing Science, Umea University, S-901 87 Umea,* Sweden, December 1993, Revised April 1994, Also as LAPACK Working* Note 75. To appear in ACM Trans. on Math. Software, Vol 22, No 1,* 1996.** =====================================================================** .. Parameters ..INTEGER IDIFJBPARAMETER ( IDIFJB = 3 )DOUBLE PRECISION ZERO, ONEPARAMETER ( ZERO = 0.0D+0, ONE = 1.0D+0 )* ..* .. Local Scalars ..LOGICAL LQUERY, PAIR, SWAP, WANTD, WANTD1, WANTD2,$ WANTPINTEGER I, IERR, IJB, K, KASE, KK, KS, LIWMIN, LWMIN,$ MN2, N1, N2DOUBLE PRECISION DSCALE, DSUM, EPS, RDSCAL, SMLNUM* ..* .. External Subroutines ..EXTERNAL DLACON, DLACPY, DLAG2, DLASSQ, DTGEXC, DTGSYL,$ XERBLA* ..* .. External Functions ..DOUBLE PRECISION DLAMCHEXTERNAL DLAMCH* ..* .. Intrinsic Functions ..INTRINSIC MAX, SIGN, SQRT* ..* .. Executable Statements ..** Decode and test the input parameters*INFO = 0LQUERY = ( LWORK.EQ.-1 .OR. LIWORK.EQ.-1 )*IF( IJOB.LT.0 .OR. IJOB.GT.5 ) THENINFO = -1ELSE IF( N.LT.0 ) THENINFO = -5ELSE IF( LDA.LT.MAX( 1, N ) ) THENINFO = -7ELSE IF( LDB.LT.MAX( 1, N ) ) THENINFO = -9ELSE IF( LDQ.LT.1 .OR. ( WANTQ .AND. LDQ.LT.N ) ) THENINFO = -14ELSE IF( LDZ.LT.1 .OR. ( WANTZ .AND. LDZ.LT.N ) ) THENINFO = -16END IF*IF( INFO.NE.0 ) THENCALL XERBLA( 'DTGSEN', -INFO )RETURNEND IF** Get machine constants*EPS = DLAMCH( 'P' )SMLNUM = DLAMCH( 'S' ) / EPSIERR = 0*WANTP = IJOB.EQ.1 .OR. IJOB.GE.4WANTD1 = IJOB.EQ.2 .OR. IJOB.EQ.4WANTD2 = IJOB.EQ.3 .OR. IJOB.EQ.5WANTD = WANTD1 .OR. WANTD2** Set M to the dimension of the specified pair of deflating* subspaces.*M = 0PAIR = .FALSE.DO 10 K = 1, NIF( PAIR ) THENPAIR = .FALSE.ELSEIF( K.LT.N ) THENIF( A( K+1, K ).EQ.ZERO ) THENIF( SELECT( K ) )$ M = M + 1ELSEPAIR = .TRUE.IF( SELECT( K ) .OR. SELECT( K+1 ) )$ M = M + 2END IFELSEIF( SELECT( N ) )$ M = M + 1END IFEND IF10 CONTINUE*IF( IJOB.EQ.1 .OR. IJOB.EQ.2 .OR. IJOB.EQ.4 ) THENLWMIN = MAX( 1, 4*N+16, 2*M*( N-M ) )LIWMIN = MAX( 1, N+6 )ELSE IF( IJOB.EQ.3 .OR. IJOB.EQ.5 ) THENLWMIN = MAX( 1, 4*N+16, 4*M*( N-M ) )LIWMIN = MAX( 1, 2*M*( N-M ), N+6 )ELSELWMIN = MAX( 1, 4*N+16 )LIWMIN = 1END IF*WORK( 1 ) = LWMINIWORK( 1 ) = LIWMIN*IF( LWORK.LT.LWMIN .AND. .NOT.LQUERY ) THENINFO = -22ELSE IF( LIWORK.LT.LIWMIN .AND. .NOT.LQUERY ) THENINFO = -24END IF*IF( INFO.NE.0 ) THENCALL XERBLA( 'DTGSEN', -INFO )RETURNELSE IF( LQUERY ) THENRETURNEND IF** Quick return if possible.*IF( M.EQ.N .OR. M.EQ.0 ) THENIF( WANTP ) THENPL = ONEPR = ONEEND IFIF( WANTD ) THENDSCALE = ZERODSUM = ONEDO 20 I = 1, NCALL DLASSQ( N, A( 1, I ), 1, DSCALE, DSUM )CALL DLASSQ( N, B( 1, I ), 1, DSCALE, DSUM )20 CONTINUEDIF( 1 ) = DSCALE*SQRT( DSUM )DIF( 2 ) = DIF( 1 )END IFGO TO 60END IF** Collect the selected blocks at the top-left corner of (A, B).*KS = 0PAIR = .FALSE.DO 30 K = 1, NIF( PAIR ) THENPAIR = .FALSE.ELSE*SWAP = SELECT( K )IF( K.LT.N ) THENIF( A( K+1, K ).NE.ZERO ) THENPAIR = .TRUE.SWAP = SWAP .OR. SELECT( K+1 )END IFEND IF*IF( SWAP ) THENKS = KS + 1** Swap the K-th block to position KS.* Perform the reordering of diagonal blocks in (A, B)* by orthogonal transformation matrices and update* Q and Z accordingly (if requested):*KK = KIF( K.NE.KS )$ CALL DTGEXC( WANTQ, WANTZ, N, A, LDA, B, LDB, Q, LDQ,$ Z, LDZ, KK, KS, WORK, LWORK, IERR )*IF( IERR.GT.0 ) THEN** Swap is rejected: exit.*INFO = 1IF( WANTP ) THENPL = ZEROPR = ZEROEND IFIF( WANTD ) THENDIF( 1 ) = ZERODIF( 2 ) = ZEROEND IFGO TO 60END IF*IF( PAIR )$ KS = KS + 1END IFEND IF30 CONTINUEIF( WANTP ) THEN** Solve generalized Sylvester equation for R and L* and compute PL and PR.*N1 = MN2 = N - MI = N1 + 1IJB = 0CALL DLACPY( 'Full', N1, N2, A( 1, I ), LDA, WORK, N1 )CALL DLACPY( 'Full', N1, N2, B( 1, I ), LDB, WORK( N1*N2+1 ),$ N1 )CALL DTGSYL( 'N', IJB, N1, N2, A, LDA, A( I, I ), LDA, WORK,$ N1, B, LDB, B( I, I ), LDB, WORK( N1*N2+1 ), N1,$ DSCALE, DIF( 1 ), WORK( N1*N2*2+1 ),$ LWORK-2*N1*N2, IWORK, IERR )** Estimate the reciprocal of norms of "projections" onto left* and right eigenspaces.*RDSCAL = ZERODSUM = ONECALL DLASSQ( N1*N2, WORK, 1, RDSCAL, DSUM )PL = RDSCAL*SQRT( DSUM )IF( PL.EQ.ZERO ) THENPL = ONEELSEPL = DSCALE / ( SQRT( DSCALE*DSCALE / PL+PL )*SQRT( PL ) )END IFRDSCAL = ZERODSUM = ONECALL DLASSQ( N1*N2, WORK( N1*N2+1 ), 1, RDSCAL, DSUM )PR = RDSCAL*SQRT( DSUM )IF( PR.EQ.ZERO ) THENPR = ONEELSEPR = DSCALE / ( SQRT( DSCALE*DSCALE / PR+PR )*SQRT( PR ) )END IFEND IF*IF( WANTD ) THEN** Compute estimates of Difu and Difl.*IF( WANTD1 ) THENN1 = MN2 = N - MI = N1 + 1IJB = IDIFJB** Frobenius norm-based Difu-estimate.*CALL DTGSYL( 'N', IJB, N1, N2, A, LDA, A( I, I ), LDA, WORK,$ N1, B, LDB, B( I, I ), LDB, WORK( N1*N2+1 ),$ N1, DSCALE, DIF( 1 ), WORK( 2*N1*N2+1 ),$ LWORK-2*N1*N2, IWORK, IERR )** Frobenius norm-based Difl-estimate.*CALL DTGSYL( 'N', IJB, N2, N1, A( I, I ), LDA, A, LDA, WORK,$ N2, B( I, I ), LDB, B, LDB, WORK( N1*N2+1 ),$ N2, DSCALE, DIF( 2 ), WORK( 2*N1*N2+1 ),$ LWORK-2*N1*N2, IWORK, IERR )ELSE*** Compute 1-norm-based estimates of Difu and Difl using* reversed communication with DLACON. In each step a* generalized Sylvester equation or a transposed variant* is solved.*KASE = 0N1 = MN2 = N - MI = N1 + 1IJB = 0MN2 = 2*N1*N2** 1-norm-based estimate of Difu.*40 CONTINUECALL DLACON( MN2, WORK( MN2+1 ), WORK, IWORK, DIF( 1 ),$ KASE )IF( KASE.NE.0 ) THENIF( KASE.EQ.1 ) THEN** Solve generalized Sylvester equation.*CALL DTGSYL( 'N', IJB, N1, N2, A, LDA, A( I, I ), LDA,$ WORK, N1, B, LDB, B( I, I ), LDB,$ WORK( N1*N2+1 ), N1, DSCALE, DIF( 1 ),$ WORK( 2*N1*N2+1 ), LWORK-2*N1*N2, IWORK,$ IERR )ELSE** Solve the transposed variant.*CALL DTGSYL( 'T', IJB, N1, N2, A, LDA, A( I, I ), LDA,$ WORK, N1, B, LDB, B( I, I ), LDB,$ WORK( N1*N2+1 ), N1, DSCALE, DIF( 1 ),$ WORK( 2*N1*N2+1 ), LWORK-2*N1*N2, IWORK,$ IERR )END IFGO TO 40END IFDIF( 1 ) = DSCALE / DIF( 1 )** 1-norm-based estimate of Difl.*50 CONTINUECALL DLACON( MN2, WORK( MN2+1 ), WORK, IWORK, DIF( 2 ),$ KASE )IF( KASE.NE.0 ) THENIF( KASE.EQ.1 ) THEN** Solve generalized Sylvester equation.*CALL DTGSYL( 'N', IJB, N2, N1, A( I, I ), LDA, A, LDA,$ WORK, N2, B( I, I ), LDB, B, LDB,$ WORK( N1*N2+1 ), N2, DSCALE, DIF( 2 ),$ WORK( 2*N1*N2+1 ), LWORK-2*N1*N2, IWORK,$ IERR )ELSE** Solve the transposed variant.*CALL DTGSYL( 'T', IJB, N2, N1, A( I, I ), LDA, A, LDA,$ WORK, N2, B( I, I ), LDB, B, LDB,$ WORK( N1*N2+1 ), N2, DSCALE, DIF( 2 ),$ WORK( 2*N1*N2+1 ), LWORK-2*N1*N2, IWORK,$ IERR )END IFGO TO 50END IFDIF( 2 ) = DSCALE / DIF( 2 )*END IFEND IF*60 CONTINUE** Compute generalized eigenvalues of reordered pair (A, B) and* normalize the generalized Schur form.*PAIR = .FALSE.DO 80 K = 1, NIF( PAIR ) THENPAIR = .FALSE.ELSE*IF( K.LT.N ) THENIF( A( K+1, K ).NE.ZERO ) THENPAIR = .TRUE.END IFEND IF*IF( PAIR ) THEN** Compute the eigenvalue(s) at position K.*WORK( 1 ) = A( K, K )WORK( 2 ) = A( K+1, K )WORK( 3 ) = A( K, K+1 )WORK( 4 ) = A( K+1, K+1 )WORK( 5 ) = B( K, K )WORK( 6 ) = B( K+1, K )WORK( 7 ) = B( K, K+1 )WORK( 8 ) = B( K+1, K+1 )CALL DLAG2( WORK, 2, WORK( 5 ), 2, SMLNUM*EPS, BETA( K ),$ BETA( K+1 ), ALPHAR( K ), ALPHAR( K+1 ),$ ALPHAI( K ) )ALPHAI( K+1 ) = -ALPHAI( K )*ELSE*IF( SIGN( ONE, B( K, K ) ).LT.ZERO ) THEN** If B(K,K) is negative, make it positive*DO 70 I = 1, NA( K, I ) = -A( K, I )B( K, I ) = -B( K, I )Q( I, K ) = -Q( I, K )70 CONTINUEEND IF*ALPHAR( K ) = A( K, K )ALPHAI( K ) = ZEROBETA( K ) = B( K, K )*END IFEND IF80 CONTINUE*WORK( 1 ) = LWMINIWORK( 1 ) = LIWMIN*RETURN** End of DTGSEN*ENDSUBROUTINE DTGSJA( JOBU, JOBV, JOBQ, M, P, N, K, L, A, LDA, B,$ LDB, TOLA, TOLB, ALPHA, BETA, U, LDU, V, LDV,$ Q, LDQ, WORK, NCYCLE, INFO )** -- LAPACK routine (version 3.0) --* Univ. of Tennessee, Univ. of California Berkeley, NAG Ltd.,* Courant Institute, Argonne National Lab, and Rice University* June 30, 1999** .. Scalar Arguments ..CHARACTER JOBQ, JOBU, JOBVINTEGER INFO, K, L, LDA, LDB, LDQ, LDU, LDV, M, N,$ NCYCLE, PDOUBLE PRECISION TOLA, TOLB* ..* .. Array Arguments ..DOUBLE PRECISION A( LDA, * ), ALPHA( * ), B( LDB, * ),$ BETA( * ), Q( LDQ, * ), U( LDU, * ),$ V( LDV, * ), WORK( * )* ..** Purpose* =======** DTGSJA computes the generalized singular value decomposition (GSVD)* of two real upper triangular (or trapezoidal) matrices A and B.** On entry, it is assumed that matrices A and B have the following* forms, which may be obtained by the preprocessing subroutine DGGSVP* from a general M-by-N matrix A and P-by-N matrix B:** N-K-L K L* A = K ( 0 A12 A13 ) if M-K-L >= 0;* L ( 0 0 A23 )* M-K-L ( 0 0 0 )** N-K-L K L* A = K ( 0 A12 A13 ) if M-K-L < 0;* M-K ( 0 0 A23 )** N-K-L K L* B = L ( 0 0 B13 )* P-L ( 0 0 0 )** where the K-by-K matrix A12 and L-by-L matrix B13 are nonsingular* upper triangular; A23 is L-by-L upper triangular if M-K-L >= 0,* otherwise A23 is (M-K)-by-L upper trapezoidal.** On exit,** U'*A*Q = D1*( 0 R ), V'*B*Q = D2*( 0 R ),** where U, V and Q are orthogonal matrices, Z' denotes the transpose* of Z, R is a nonsingular upper triangular matrix, and D1 and D2 are* ``diagonal'' matrices, which are of the following structures:** If M-K-L >= 0,** K L* D1 = K ( I 0 )* L ( 0 C )* M-K-L ( 0 0 )** K L* D2 = L ( 0 S )* P-L ( 0 0 )** N-K-L K L* ( 0 R ) = K ( 0 R11 R12 ) K* L ( 0 0 R22 ) L** where** C = diag( ALPHA(K+1), ... , ALPHA(K+L) ),* S = diag( BETA(K+1), ... , BETA(K+L) ),* C**2 + S**2 = I.** R is stored in A(1:K+L,N-K-L+1:N) on exit.** If M-K-L < 0,** K M-K K+L-M* D1 = K ( I 0 0 )* M-K ( 0 C 0 )** K M-K K+L-M* D2 = M-K ( 0 S 0 )* K+L-M ( 0 0 I )* P-L ( 0 0 0 )** N-K-L K M-K K+L-M* ( 0 R ) = K ( 0 R11 R12 R13 )* M-K ( 0 0 R22 R23 )* K+L-M ( 0 0 0 R33 )** where* C = diag( ALPHA(K+1), ... , ALPHA(M) ),* S = diag( BETA(K+1), ... , BETA(M) ),* C**2 + S**2 = I.** R = ( R11 R12 R13 ) is stored in A(1:M, N-K-L+1:N) and R33 is stored* ( 0 R22 R23 )* in B(M-K+1:L,N+M-K-L+1:N) on exit.** The computation of the orthogonal transformation matrices U, V or Q* is optional. These matrices may either be formed explicitly, or they* may be postmultiplied into input matrices U1, V1, or Q1.** Arguments* =========** JOBU (input) CHARACTER*1* = 'U': U must contain an orthogonal matrix U1 on entry, and* the product U1*U is returned;* = 'I': U is initialized to the unit matrix, and the* orthogonal matrix U is returned;* = 'N': U is not computed.** JOBV (input) CHARACTER*1* = 'V': V must contain an orthogonal matrix V1 on entry, and* the product V1*V is returned;* = 'I': V is initialized to the unit matrix, and the* orthogonal matrix V is returned;* = 'N': V is not computed.** JOBQ (input) CHARACTER*1* = 'Q': Q must contain an orthogonal matrix Q1 on entry, and* the product Q1*Q is returned;* = 'I': Q is initialized to the unit matrix, and the* orthogonal matrix Q is returned;* = 'N': Q is not computed.** M (input) INTEGER* The number of rows of the matrix A. M >= 0.** P (input) INTEGER* The number of rows of the matrix B. P >= 0.** N (input) INTEGER* The number of columns of the matrices A and B. N >= 0.** K (input) INTEGER* L (input) INTEGER* K and L specify the subblocks in the input matrices A and B:* A23 = A(K+1:MIN(K+L,M),N-L+1:N) and B13 = B(1:L,N-L+1:N)* of A and B, whose GSVD is going to be computed by DTGSJA.* See Further details.** A (input/output) DOUBLE PRECISION array, dimension (LDA,N)* On entry, the M-by-N matrix A.* On exit, A(N-K+1:N,1:MIN(K+L,M) ) contains the triangular* matrix R or part of R. See Purpose for details.** LDA (input) INTEGER* The leading dimension of the array A. LDA >= max(1,M).** B (input/output) DOUBLE PRECISION array, dimension (LDB,N)* On entry, the P-by-N matrix B.* On exit, if necessary, B(M-K+1:L,N+M-K-L+1:N) contains* a part of R. See Purpose for details.** LDB (input) INTEGER* The leading dimension of the array B. LDB >= max(1,P).** TOLA (input) DOUBLE PRECISION* TOLB (input) DOUBLE PRECISION* TOLA and TOLB are the convergence criteria for the Jacobi-* Kogbetliantz iteration procedure. Generally, they are the* same as used in the preprocessing step, say* TOLA = max(M,N)*norm(A)*MAZHEPS,* TOLB = max(P,N)*norm(B)*MAZHEPS.** ALPHA (output) DOUBLE PRECISION array, dimension (N)* BETA (output) DOUBLE PRECISION array, dimension (N)* On exit, ALPHA and BETA contain the generalized singular* value pairs of A and B;* ALPHA(1:K) = 1,* BETA(1:K) = 0,* and if M-K-L >= 0,* ALPHA(K+1:K+L) = diag(C),* BETA(K+1:K+L) = diag(S),* or if M-K-L < 0,* ALPHA(K+1:M)= C, ALPHA(M+1:K+L)= 0* BETA(K+1:M) = S, BETA(M+1:K+L) = 1.* Furthermore, if K+L < N,* ALPHA(K+L+1:N) = 0 and* BETA(K+L+1:N) = 0.** U (input/output) DOUBLE PRECISION array, dimension (LDU,M)* On entry, if JOBU = 'U', U must contain a matrix U1 (usually* the orthogonal matrix returned by DGGSVP).* On exit,* if JOBU = 'I', U contains the orthogonal matrix U;* if JOBU = 'U', U contains the product U1*U.* If JOBU = 'N', U is not referenced.** LDU (input) INTEGER* The leading dimension of the array U. LDU >= max(1,M) if* JOBU = 'U'; LDU >= 1 otherwise.** V (input/output) DOUBLE PRECISION array, dimension (LDV,P)* On entry, if JOBV = 'V', V must contain a matrix V1 (usually* the orthogonal matrix returned by DGGSVP).* On exit,* if JOBV = 'I', V contains the orthogonal matrix V;* if JOBV = 'V', V contains the product V1*V.* If JOBV = 'N', V is not referenced.** LDV (input) INTEGER* The leading dimension of the array V. LDV >= max(1,P) if* JOBV = 'V'; LDV >= 1 otherwise.** Q (input/output) DOUBLE PRECISION array, dimension (LDQ,N)* On entry, if JOBQ = 'Q', Q must contain a matrix Q1 (usually* the orthogonal matrix returned by DGGSVP).* On exit,* if JOBQ = 'I', Q contains the orthogonal matrix Q;* if JOBQ = 'Q', Q contains the product Q1*Q.* If JOBQ = 'N', Q is not referenced.** LDQ (input) INTEGER* The leading dimension of the array Q. LDQ >= max(1,N) if* JOBQ = 'Q'; LDQ >= 1 otherwise.** WORK (workspace) DOUBLE PRECISION array, dimension (2*N)** NCYCLE (output) INTEGER* The number of cycles required for convergence.** INFO (output) INTEGER* = 0: successful exit* < 0: if INFO = -i, the i-th argument had an illegal value.* = 1: the procedure does not converge after MAXIT cycles.** Internal Parameters* ===================** MAXIT INTEGER* MAXIT specifies the total loops that the iterative procedure* may take. If after MAXIT cycles, the routine fails to* converge, we return INFO = 1.** Further Details* ===============** DTGSJA essentially uses a variant of Kogbetliantz algorithm to reduce* min(L,M-K)-by-L triangular (or trapezoidal) matrix A23 and L-by-L* matrix B13 to the form:** U1'*A13*Q1 = C1*R1; V1'*B13*Q1 = S1*R1,** where U1, V1 and Q1 are orthogonal matrix, and Z' is the transpose* of Z. C1 and S1 are diagonal matrices satisfying** C1**2 + S1**2 = I,** and R1 is an L-by-L nonsingular upper triangular matrix.** =====================================================================** .. Parameters ..INTEGER MAXITPARAMETER ( MAXIT = 40 )DOUBLE PRECISION ZERO, ONEPARAMETER ( ZERO = 0.0D+0, ONE = 1.0D+0 )* ..* .. Local Scalars ..*LOGICAL INITQ, INITU, INITV, UPPER, WANTQ, WANTU, WANTVINTEGER I, J, KCYCLEDOUBLE PRECISION A1, A2, A3, B1, B2, B3, CSQ, CSU, CSV, ERROR,$ GAMMA, RWK, SNQ, SNU, SNV, SSMIN* ..* .. External Functions ..LOGICAL LSAMEEXTERNAL LSAME* ..* .. External Subroutines ..EXTERNAL DCOPY, DLAGS2, DLAPLL, DLARTG, DLASET, DROT,$ DSCAL, XERBLA* ..* .. Intrinsic Functions ..INTRINSIC ABS, MAX, MIN* ..* .. Executable Statements ..** Decode and test the input parameters*INITU = LSAME( JOBU, 'I' )WANTU = INITU .OR. LSAME( JOBU, 'U' )*INITV = LSAME( JOBV, 'I' )WANTV = INITV .OR. LSAME( JOBV, 'V' )*INITQ = LSAME( JOBQ, 'I' )WANTQ = INITQ .OR. LSAME( JOBQ, 'Q' )*INFO = 0IF( .NOT.( INITU .OR. WANTU .OR. LSAME( JOBU, 'N' ) ) ) THENINFO = -1ELSE IF( .NOT.( INITV .OR. WANTV .OR. LSAME( JOBV, 'N' ) ) ) THENINFO = -2ELSE IF( .NOT.( INITQ .OR. WANTQ .OR. LSAME( JOBQ, 'N' ) ) ) THENINFO = -3ELSE IF( M.LT.0 ) THENINFO = -4ELSE IF( P.LT.0 ) THENINFO = -5ELSE IF( N.LT.0 ) THENINFO = -6ELSE IF( LDA.LT.MAX( 1, M ) ) THENINFO = -10ELSE IF( LDB.LT.MAX( 1, P ) ) THENINFO = -12ELSE IF( LDU.LT.1 .OR. ( WANTU .AND. LDU.LT.M ) ) THENINFO = -18ELSE IF( LDV.LT.1 .OR. ( WANTV .AND. LDV.LT.P ) ) THENINFO = -20ELSE IF( LDQ.LT.1 .OR. ( WANTQ .AND. LDQ.LT.N ) ) THENINFO = -22END IFIF( INFO.NE.0 ) THENCALL XERBLA( 'DTGSJA', -INFO )RETURNEND IF** Initialize U, V and Q, if necessary*IF( INITU )$ CALL DLASET( 'Full', M, M, ZERO, ONE, U, LDU )IF( INITV )$ CALL DLASET( 'Full', P, P, ZERO, ONE, V, LDV )IF( INITQ )$ CALL DLASET( 'Full', N, N, ZERO, ONE, Q, LDQ )** Loop until convergence*UPPER = .FALSE.DO 40 KCYCLE = 1, MAXIT*UPPER = .NOT.UPPER*DO 20 I = 1, L - 1DO 10 J = I + 1, L*A1 = ZEROA2 = ZEROA3 = ZEROIF( K+I.LE.M )$ A1 = A( K+I, N-L+I )IF( K+J.LE.M )$ A3 = A( K+J, N-L+J )*B1 = B( I, N-L+I )B3 = B( J, N-L+J )*IF( UPPER ) THENIF( K+I.LE.M )$ A2 = A( K+I, N-L+J )B2 = B( I, N-L+J )ELSEIF( K+J.LE.M )$ A2 = A( K+J, N-L+I )B2 = B( J, N-L+I )END IF*CALL DLAGS2( UPPER, A1, A2, A3, B1, B2, B3, CSU, SNU,$ CSV, SNV, CSQ, SNQ )** Update (K+I)-th and (K+J)-th rows of matrix A: U'*A*IF( K+J.LE.M )$ CALL DROT( L, A( K+J, N-L+1 ), LDA, A( K+I, N-L+1 ),$ LDA, CSU, SNU )** Update I-th and J-th rows of matrix B: V'*B*CALL DROT( L, B( J, N-L+1 ), LDB, B( I, N-L+1 ), LDB,$ CSV, SNV )** Update (N-L+I)-th and (N-L+J)-th columns of matrices* A and B: A*Q and B*Q*CALL DROT( MIN( K+L, M ), A( 1, N-L+J ), 1,$ A( 1, N-L+I ), 1, CSQ, SNQ )*CALL DROT( L, B( 1, N-L+J ), 1, B( 1, N-L+I ), 1, CSQ,$ SNQ )*IF( UPPER ) THENIF( K+I.LE.M )$ A( K+I, N-L+J ) = ZEROB( I, N-L+J ) = ZEROELSEIF( K+J.LE.M )$ A( K+J, N-L+I ) = ZEROB( J, N-L+I ) = ZEROEND IF** Update orthogonal matrices U, V, Q, if desired.*IF( WANTU .AND. K+J.LE.M )$ CALL DROT( M, U( 1, K+J ), 1, U( 1, K+I ), 1, CSU,$ SNU )*IF( WANTV )$ CALL DROT( P, V( 1, J ), 1, V( 1, I ), 1, CSV, SNV )*IF( WANTQ )$ CALL DROT( N, Q( 1, N-L+J ), 1, Q( 1, N-L+I ), 1, CSQ,$ SNQ )*10 CONTINUE20 CONTINUE*IF( .NOT.UPPER ) THEN** The matrices A13 and B13 were lower triangular at the start* of the cycle, and are now upper triangular.** Convergence test: test the parallelism of the corresponding* rows of A and B.*ERROR = ZERODO 30 I = 1, MIN( L, M-K )CALL DCOPY( L-I+1, A( K+I, N-L+I ), LDA, WORK, 1 )CALL DCOPY( L-I+1, B( I, N-L+I ), LDB, WORK( L+1 ), 1 )CALL DLAPLL( L-I+1, WORK, 1, WORK( L+1 ), 1, SSMIN )ERROR = MAX( ERROR, SSMIN )30 CONTINUE*IF( ABS( ERROR ).LE.MIN( TOLA, TOLB ) )$ GO TO 50END IF** End of cycle loop*40 CONTINUE** The algorithm has not converged after MAXIT cycles.*INFO = 1GO TO 100*50 CONTINUE** If ERROR <= MIN(TOLA,TOLB), then the algorithm has converged.* Compute the generalized singular value pairs (ALPHA, BETA), and* set the triangular matrix R to array A.*DO 60 I = 1, KALPHA( I ) = ONEBETA( I ) = ZERO60 CONTINUE*DO 70 I = 1, MIN( L, M-K )*A1 = A( K+I, N-L+I )B1 = B( I, N-L+I )*IF( A1.NE.ZERO ) THENGAMMA = B1 / A1** change sign if necessary*IF( GAMMA.LT.ZERO ) THENCALL DSCAL( L-I+1, -ONE, B( I, N-L+I ), LDB )IF( WANTV )$ CALL DSCAL( P, -ONE, V( 1, I ), 1 )END IF*CALL DLARTG( ABS( GAMMA ), ONE, BETA( K+I ), ALPHA( K+I ),$ RWK )*IF( ALPHA( K+I ).GE.BETA( K+I ) ) THENCALL DSCAL( L-I+1, ONE / ALPHA( K+I ), A( K+I, N-L+I ),$ LDA )ELSECALL DSCAL( L-I+1, ONE / BETA( K+I ), B( I, N-L+I ),$ LDB )CALL DCOPY( L-I+1, B( I, N-L+I ), LDB, A( K+I, N-L+I ),$ LDA )END IF*ELSE*ALPHA( K+I ) = ZEROBETA( K+I ) = ONECALL DCOPY( L-I+1, B( I, N-L+I ), LDB, A( K+I, N-L+I ),$ LDA )*END IF*70 CONTINUE** Post-assignment*DO 80 I = M + 1, K + LALPHA( I ) = ZEROBETA( I ) = ONE80 CONTINUE*IF( K+L.LT.N ) THENDO 90 I = K + L + 1, NALPHA( I ) = ZEROBETA( I ) = ZERO90 CONTINUEEND IF*100 CONTINUENCYCLE = KCYCLERETURN** End of DTGSJA*ENDSUBROUTINE DTGSNA( JOB, HOWMNY, SELECT, N, A, LDA, B, LDB, VL,$ LDVL, VR, LDVR, S, DIF, MM, M, WORK, LWORK,$ IWORK, INFO )** -- LAPACK routine (version 3.0) --* Univ. of Tennessee, Univ. of California Berkeley, NAG Ltd.,* Courant Institute, Argonne National Lab, and Rice University* June 30, 1999** .. Scalar Arguments ..CHARACTER HOWMNY, JOBINTEGER INFO, LDA, LDB, LDVL, LDVR, LWORK, M, MM, N* ..* .. Array Arguments ..LOGICAL SELECT( * )INTEGER IWORK( * )DOUBLE PRECISION A( LDA, * ), B( LDB, * ), DIF( * ), S( * ),$ VL( LDVL, * ), VR( LDVR, * ), WORK( * )* ..** Purpose* =======** DTGSNA estimates reciprocal condition numbers for specified* eigenvalues and/or eigenvectors of a matrix pair (A, B) in* generalized real Schur canonical form (or of any matrix pair* (Q*A*Z', Q*B*Z') with orthogonal matrices Q and Z, where* Z' denotes the transpose of Z.** (A, B) must be in generalized real Schur form (as returned by DGGES),* i.e. A is block upper triangular with 1-by-1 and 2-by-2 diagonal* blocks. B is upper triangular.*** Arguments* =========** JOB (input) CHARACTER*1* Specifies whether condition numbers are required for* eigenvalues (S) or eigenvectors (DIF):* = 'E': for eigenvalues only (S);* = 'V': for eigenvectors only (DIF);* = 'B': for both eigenvalues and eigenvectors (S and DIF).** HOWMNY (input) CHARACTER*1* = 'A': compute condition numbers for all eigenpairs;* = 'S': compute condition numbers for selected eigenpairs* specified by the array SELECT.** SELECT (input) LOGICAL array, dimension (N)* If HOWMNY = 'S', SELECT specifies the eigenpairs for which* condition numbers are required. To select condition numbers* for the eigenpair corresponding to a real eigenvalue w(j),* SELECT(j) must be set to .TRUE.. To select condition numbers* corresponding to a complex conjugate pair of eigenvalues w(j)* and w(j+1), either SELECT(j) or SELECT(j+1) or both, must be* set to .TRUE..* If HOWMNY = 'A', SELECT is not referenced.** N (input) INTEGER* The order of the square matrix pair (A, B). N >= 0.** A (input) DOUBLE PRECISION array, dimension (LDA,N)* The upper quasi-triangular matrix A in the pair (A,B).** LDA (input) INTEGER* The leading dimension of the array A. LDA >= max(1,N).** B (input) DOUBLE PRECISION array, dimension (LDB,N)* The upper triangular matrix B in the pair (A,B).** LDB (input) INTEGER* The leading dimension of the array B. LDB >= max(1,N).** VL (input) DOUBLE PRECISION array, dimension (LDVL,M)* If JOB = 'E' or 'B', VL must contain left eigenvectors of* (A, B), corresponding to the eigenpairs specified by HOWMNY* and SELECT. The eigenvectors must be stored in consecutive* columns of VL, as returned by DTGEVC.* If JOB = 'V', VL is not referenced.** LDVL (input) INTEGER* The leading dimension of the array VL. LDVL >= 1.* If JOB = 'E' or 'B', LDVL >= N.** VR (input) DOUBLE PRECISION array, dimension (LDVR,M)* If JOB = 'E' or 'B', VR must contain right eigenvectors of* (A, B), corresponding to the eigenpairs specified by HOWMNY* and SELECT. The eigenvectors must be stored in consecutive* columns ov VR, as returned by DTGEVC.* If JOB = 'V', VR is not referenced.** LDVR (input) INTEGER* The leading dimension of the array VR. LDVR >= 1.* If JOB = 'E' or 'B', LDVR >= N.** S (output) DOUBLE PRECISION array, dimension (MM)* If JOB = 'E' or 'B', the reciprocal condition numbers of the* selected eigenvalues, stored in consecutive elements of the* array. For a complex conjugate pair of eigenvalues two* consecutive elements of S are set to the same value. Thus* S(j), DIF(j), and the j-th columns of VL and VR all* correspond to the same eigenpair (but not in general the* j-th eigenpair, unless all eigenpairs are selected).* If JOB = 'V', S is not referenced.** DIF (output) DOUBLE PRECISION array, dimension (MM)* If JOB = 'V' or 'B', the estimated reciprocal condition* numbers of the selected eigenvectors, stored in consecutive* elements of the array. For a complex eigenvector two* consecutive elements of DIF are set to the same value. If* the eigenvalues cannot be reordered to compute DIF(j), DIF(j)* is set to 0; this can only occur when the true value would be* very small anyway.* If JOB = 'E', DIF is not referenced.** MM (input) INTEGER* The number of elements in the arrays S and DIF. MM >= M.** M (output) INTEGER* The number of elements of the arrays S and DIF used to store* the specified condition numbers; for each selected real* eigenvalue one element is used, and for each selected complex* conjugate pair of eigenvalues, two elements are used.* If HOWMNY = 'A', M is set to N.** WORK (workspace/output) DOUBLE PRECISION array, dimension (LWORK)* If JOB = 'E', WORK is not referenced. Otherwise,* on exit, if INFO = 0, WORK(1) returns the optimal LWORK.** LWORK (input) INTEGER* The dimension of the array WORK. LWORK >= N.* If JOB = 'V' or 'B' LWORK >= 2*N*(N+2)+16.** If LWORK = -1, then a workspace query is assumed; the routine* only calculates the optimal size of the WORK array, returns* this value as the first entry of the WORK array, and no error* message related to LWORK is issued by XERBLA.** IWORK (workspace) INTEGER array, dimension (N + 6)* If JOB = 'E', IWORK is not referenced.** INFO (output) INTEGER* =0: Successful exit* <0: If INFO = -i, the i-th argument had an illegal value*** Further Details* ===============** The reciprocal of the condition number of a generalized eigenvalue* w = (a, b) is defined as** S(w) = (|u'Av|**2 + |u'Bv|**2)**(1/2) / (norm(u)*norm(v))** where u and v are the left and right eigenvectors of (A, B)* corresponding to w; |z| denotes the absolute value of the complex* number, and norm(u) denotes the 2-norm of the vector u.* The pair (a, b) corresponds to an eigenvalue w = a/b (= u'Av/u'Bv)* of the matrix pair (A, B). If both a and b equal zero, then (A B) is* singular and S(I) = -1 is returned.** An approximate error bound on the chordal distance between the i-th* computed generalized eigenvalue w and the corresponding exact* eigenvalue lambda is** chord(w, lambda) <= EPS * norm(A, B) / S(I)** where EPS is the machine precision.** The reciprocal of the condition number DIF(i) of right eigenvector u* and left eigenvector v corresponding to the generalized eigenvalue w* is defined as follows:** a) If the i-th eigenvalue w = (a,b) is real** Suppose U and V are orthogonal transformations such that** U'*(A, B)*V = (S, T) = ( a * ) ( b * ) 1* ( 0 S22 ),( 0 T22 ) n-1* 1 n-1 1 n-1** Then the reciprocal condition number DIF(i) is** Difl((a, b), (S22, T22)) = sigma-min( Zl ),** where sigma-min(Zl) denotes the smallest singular value of the* 2(n-1)-by-2(n-1) matrix** Zl = [ kron(a, In-1) -kron(1, S22) ]* [ kron(b, In-1) -kron(1, T22) ] .** Here In-1 is the identity matrix of size n-1. kron(X, Y) is the* Kronecker product between the matrices X and Y.** Note that if the default method for computing DIF(i) is wanted* (see DLATDF), then the parameter DIFDRI (see below) should be* changed from 3 to 4 (routine DLATDF(IJOB = 2 will be used)).* See DTGSYL for more details.** b) If the i-th and (i+1)-th eigenvalues are complex conjugate pair,** Suppose U and V are orthogonal transformations such that** U'*(A, B)*V = (S, T) = ( S11 * ) ( T11 * ) 2* ( 0 S22 ),( 0 T22) n-2* 2 n-2 2 n-2** and (S11, T11) corresponds to the complex conjugate eigenvalue* pair (w, conjg(w)). There exist unitary matrices U1 and V1 such* that** U1'*S11*V1 = ( s11 s12 ) and U1'*T11*V1 = ( t11 t12 )* ( 0 s22 ) ( 0 t22 )** where the generalized eigenvalues w = s11/t11 and* conjg(w) = s22/t22.** Then the reciprocal condition number DIF(i) is bounded by** min( d1, max( 1, |real(s11)/real(s22)| )*d2 )** where, d1 = Difl((s11, t11), (s22, t22)) = sigma-min(Z1), where* Z1 is the complex 2-by-2 matrix** Z1 = [ s11 -s22 ]* [ t11 -t22 ],** This is done by computing (using real arithmetic) the* roots of the characteristical polynomial det(Z1' * Z1 - lambda I),* where Z1' denotes the conjugate transpose of Z1 and det(X) denotes* the determinant of X.** and d2 is an upper bound on Difl((S11, T11), (S22, T22)), i.e. an* upper bound on sigma-min(Z2), where Z2 is (2n-2)-by-(2n-2)** Z2 = [ kron(S11', In-2) -kron(I2, S22) ]* [ kron(T11', In-2) -kron(I2, T22) ]** Note that if the default method for computing DIF is wanted (see* DLATDF), then the parameter DIFDRI (see below) should be changed* from 3 to 4 (routine DLATDF(IJOB = 2 will be used)). See DTGSYL* for more details.** For each eigenvalue/vector specified by SELECT, DIF stores a* Frobenius norm-based estimate of Difl.** An approximate error bound for the i-th computed eigenvector VL(i) or* VR(i) is given by** EPS * norm(A, B) / DIF(i).** See ref. [2-3] for more details and further references.** Based on contributions by* Bo Kagstrom and Peter Poromaa, Department of Computing Science,* Umea University, S-901 87 Umea, Sweden.** References* ==========** [1] B. Kagstrom; A Direct Method for Reordering Eigenvalues in the* Generalized Real Schur Form of a Regular Matrix Pair (A, B), in* M.S. Moonen et al (eds), Linear Algebra for Large Scale and* Real-Time Applications, Kluwer Academic Publ. 1993, pp 195-218.** [2] B. Kagstrom and P. Poromaa; Computing Eigenspaces with Specified* Eigenvalues of a Regular Matrix Pair (A, B) and Condition* Estimation: Theory, Algorithms and Software,* Report UMINF - 94.04, Department of Computing Science, Umea* University, S-901 87 Umea, Sweden, 1994. Also as LAPACK Working* Note 87. To appear in Numerical Algorithms, 1996.** [3] B. Kagstrom and P. Poromaa, LAPACK-Style Algorithms and Software* for Solving the Generalized Sylvester Equation and Estimating the* Separation between Regular Matrix Pairs, Report UMINF - 93.23,* Department of Computing Science, Umea University, S-901 87 Umea,* Sweden, December 1993, Revised April 1994, Also as LAPACK Working* Note 75. To appear in ACM Trans. on Math. Software, Vol 22,* No 1, 1996.** =====================================================================** .. Parameters ..INTEGER DIFDRIPARAMETER ( DIFDRI = 3 )DOUBLE PRECISION ZERO, ONE, TWO, FOURPARAMETER ( ZERO = 0.0D+0, ONE = 1.0D+0, TWO = 2.0D+0,$ FOUR = 4.0D+0 )* ..* .. Local Scalars ..LOGICAL LQUERY, PAIR, SOMCON, WANTBH, WANTDF, WANTSINTEGER I, IERR, IFST, ILST, IZ, K, KS, LWMIN, N1, N2DOUBLE PRECISION ALPHAI, ALPHAR, ALPRQT, BETA, C1, C2, COND,$ EPS, LNRM, RNRM, ROOT1, ROOT2, SCALE, SMLNUM,$ TMPII, TMPIR, TMPRI, TMPRR, UHAV, UHAVI, UHBV,$ UHBVI* ..* .. Local Arrays ..DOUBLE PRECISION DUMMY( 1 ), DUMMY1( 1 )* ..* .. External Functions ..LOGICAL LSAMEDOUBLE PRECISION DDOT, DLAMCH, DLAPY2, DNRM2EXTERNAL LSAME, DDOT, DLAMCH, DLAPY2, DNRM2* ..* .. External Subroutines ..EXTERNAL DGEMV, DLACPY, DLAG2, DTGEXC, DTGSYL, XERBLA* ..* .. Intrinsic Functions ..INTRINSIC MAX, MIN, SQRT* ..* .. Executable Statements ..** Decode and test the input parameters*WANTBH = LSAME( JOB, 'B' )WANTS = LSAME( JOB, 'E' ) .OR. WANTBHWANTDF = LSAME( JOB, 'V' ) .OR. WANTBH*SOMCON = LSAME( HOWMNY, 'S' )*INFO = 0LQUERY = ( LWORK.EQ.-1 )*IF( LSAME( JOB, 'V' ) .OR. LSAME( JOB, 'B' ) ) THENLWMIN = MAX( 1, 2*N*( N+2 )+16 )ELSELWMIN = 1END IF*IF( .NOT.WANTS .AND. .NOT.WANTDF ) THENINFO = -1ELSE IF( .NOT.LSAME( HOWMNY, 'A' ) .AND. .NOT.SOMCON ) THENINFO = -2ELSE IF( N.LT.0 ) THENINFO = -4ELSE IF( LDA.LT.MAX( 1, N ) ) THENINFO = -6ELSE IF( LDB.LT.MAX( 1, N ) ) THENINFO = -8ELSE IF( WANTS .AND. LDVL.LT.N ) THENINFO = -10ELSE IF( WANTS .AND. LDVR.LT.N ) THENINFO = -12ELSE** Set M to the number of eigenpairs for which condition numbers* are required, and test MM.*IF( SOMCON ) THENM = 0PAIR = .FALSE.DO 10 K = 1, NIF( PAIR ) THENPAIR = .FALSE.ELSEIF( K.LT.N ) THENIF( A( K+1, K ).EQ.ZERO ) THENIF( SELECT( K ) )$ M = M + 1ELSEPAIR = .TRUE.IF( SELECT( K ) .OR. SELECT( K+1 ) )$ M = M + 2END IFELSEIF( SELECT( N ) )$ M = M + 1END IFEND IF10 CONTINUEELSEM = NEND IF*IF( MM.LT.M ) THENINFO = -15ELSE IF( LWORK.LT.LWMIN .AND. .NOT.LQUERY ) THENINFO = -18* ELSE IF( WANTDF .AND. LWORK.LT.2*N*( N+2 )+16 ) THEN* INFO = -18END IFEND IF*IF( INFO.EQ.0 ) THENWORK( 1 ) = LWMINEND IF*IF( INFO.NE.0 ) THENCALL XERBLA( 'DTGSNA', -INFO )RETURNELSE IF( LQUERY ) THENRETURNEND IF** Quick return if possible*IF( N.EQ.0 )$ RETURN** Get machine constants*EPS = DLAMCH( 'P' )SMLNUM = DLAMCH( 'S' ) / EPSKS = 0PAIR = .FALSE.*DO 20 K = 1, N** Determine whether A(k,k) begins a 1-by-1 or 2-by-2 block.*IF( PAIR ) THENPAIR = .FALSE.GO TO 20ELSEIF( K.LT.N )$ PAIR = A( K+1, K ).NE.ZEROEND IF** Determine whether condition numbers are required for the k-th* eigenpair.*IF( SOMCON ) THENIF( PAIR ) THENIF( .NOT.SELECT( K ) .AND. .NOT.SELECT( K+1 ) )$ GO TO 20ELSEIF( .NOT.SELECT( K ) )$ GO TO 20END IFEND IF*KS = KS + 1*IF( WANTS ) THEN** Compute the reciprocal condition number of the k-th* eigenvalue.*IF( PAIR ) THEN** Complex eigenvalue pair.*RNRM = DLAPY2( DNRM2( N, VR( 1, KS ), 1 ),$ DNRM2( N, VR( 1, KS+1 ), 1 ) )LNRM = DLAPY2( DNRM2( N, VL( 1, KS ), 1 ),$ DNRM2( N, VL( 1, KS+1 ), 1 ) )CALL DGEMV( 'N', N, N, ONE, A, LDA, VR( 1, KS ), 1, ZERO,$ WORK, 1 )TMPRR = DDOT( N, WORK, 1, VL( 1, KS ), 1 )TMPRI = DDOT( N, WORK, 1, VL( 1, KS+1 ), 1 )CALL DGEMV( 'N', N, N, ONE, A, LDA, VR( 1, KS+1 ), 1,$ ZERO, WORK, 1 )TMPII = DDOT( N, WORK, 1, VL( 1, KS+1 ), 1 )TMPIR = DDOT( N, WORK, 1, VL( 1, KS ), 1 )UHAV = TMPRR + TMPIIUHAVI = TMPIR - TMPRICALL DGEMV( 'N', N, N, ONE, B, LDB, VR( 1, KS ), 1, ZERO,$ WORK, 1 )TMPRR = DDOT( N, WORK, 1, VL( 1, KS ), 1 )TMPRI = DDOT( N, WORK, 1, VL( 1, KS+1 ), 1 )CALL DGEMV( 'N', N, N, ONE, B, LDB, VR( 1, KS+1 ), 1,$ ZERO, WORK, 1 )TMPII = DDOT( N, WORK, 1, VL( 1, KS+1 ), 1 )TMPIR = DDOT( N, WORK, 1, VL( 1, KS ), 1 )UHBV = TMPRR + TMPIIUHBVI = TMPIR - TMPRIUHAV = DLAPY2( UHAV, UHAVI )UHBV = DLAPY2( UHBV, UHBVI )COND = DLAPY2( UHAV, UHBV )S( KS ) = COND / ( RNRM*LNRM )S( KS+1 ) = S( KS )*ELSE** Real eigenvalue.*RNRM = DNRM2( N, VR( 1, KS ), 1 )LNRM = DNRM2( N, VL( 1, KS ), 1 )CALL DGEMV( 'N', N, N, ONE, A, LDA, VR( 1, KS ), 1, ZERO,$ WORK, 1 )UHAV = DDOT( N, WORK, 1, VL( 1, KS ), 1 )CALL DGEMV( 'N', N, N, ONE, B, LDB, VR( 1, KS ), 1, ZERO,$ WORK, 1 )UHBV = DDOT( N, WORK, 1, VL( 1, KS ), 1 )COND = DLAPY2( UHAV, UHBV )IF( COND.EQ.ZERO ) THENS( KS ) = -ONEELSES( KS ) = COND / ( RNRM*LNRM )END IFEND IFEND IF*IF( WANTDF ) THENIF( N.EQ.1 ) THENDIF( KS ) = DLAPY2( A( 1, 1 ), B( 1, 1 ) )GO TO 20END IF** Estimate the reciprocal condition number of the k-th* eigenvectors.IF( PAIR ) THEN** Copy the 2-by 2 pencil beginning at (A(k,k), B(k, k)).* Compute the eigenvalue(s) at position K.*WORK( 1 ) = A( K, K )WORK( 2 ) = A( K+1, K )WORK( 3 ) = A( K, K+1 )WORK( 4 ) = A( K+1, K+1 )WORK( 5 ) = B( K, K )WORK( 6 ) = B( K+1, K )WORK( 7 ) = B( K, K+1 )WORK( 8 ) = B( K+1, K+1 )CALL DLAG2( WORK, 2, WORK( 5 ), 2, SMLNUM*EPS, BETA,$ DUMMY1( 1 ), ALPHAR, DUMMY( 1 ), ALPHAI )ALPRQT = ONEC1 = TWO*( ALPHAR*ALPHAR+ALPHAI*ALPHAI+BETA*BETA )C2 = FOUR*BETA*BETA*ALPHAI*ALPHAIROOT1 = C1 + SQRT( C1*C1-4.0D0*C2 )ROOT2 = C2 / ROOT1ROOT1 = ROOT1 / TWOCOND = MIN( SQRT( ROOT1 ), SQRT( ROOT2 ) )END IF** Copy the matrix (A, B) to the array WORK and swap the* diagonal block beginning at A(k,k) to the (1,1) position.*CALL DLACPY( 'Full', N, N, A, LDA, WORK, N )CALL DLACPY( 'Full', N, N, B, LDB, WORK( N*N+1 ), N )IFST = KILST = 1*CALL DTGEXC( .FALSE., .FALSE., N, WORK, N, WORK( N*N+1 ), N,$ DUMMY, 1, DUMMY1, 1, IFST, ILST,$ WORK( N*N*2+1 ), LWORK-2*N*N, IERR )*IF( IERR.GT.0 ) THEN** Ill-conditioned problem - swap rejected.*DIF( KS ) = ZEROELSE** Reordering successful, solve generalized Sylvester* equation for R and L,* A22 * R - L * A11 = A12* B22 * R - L * B11 = B12,* and compute estimate of Difl((A11,B11), (A22, B22)).*N1 = 1IF( WORK( 2 ).NE.ZERO )$ N1 = 2N2 = N - N1IF( N2.EQ.0 ) THENDIF( KS ) = CONDELSEI = N*N + 1IZ = 2*N*N + 1CALL DTGSYL( 'N', DIFDRI, N2, N1, WORK( N*N1+N1+1 ),$ N, WORK, N, WORK( N1+1 ), N,$ WORK( N*N1+N1+I ), N, WORK( I ), N,$ WORK( N1+I ), N, SCALE, DIF( KS ),$ WORK( IZ+1 ), LWORK-2*N*N, IWORK, IERR )*IF( PAIR )$ DIF( KS ) = MIN( MAX( ONE, ALPRQT )*DIF( KS ),$ COND )END IFEND IFIF( PAIR )$ DIF( KS+1 ) = DIF( KS )END IFIF( PAIR )$ KS = KS + 1*20 CONTINUEWORK( 1 ) = LWMINRETURN** End of DTGSNA*ENDSUBROUTINE DTGSYL( TRANS, IJOB, M, N, A, LDA, B, LDB, C, LDC, D,$ LDD, E, LDE, F, LDF, SCALE, DIF, WORK, LWORK,$ IWORK, INFO )** -- LAPACK routine (version 3.0) --* Univ. of Tennessee, Univ. of California Berkeley, NAG Ltd.,* Courant Institute, Argonne National Lab, and Rice University* June 30, 1999** .. Scalar Arguments ..CHARACTER TRANSINTEGER IJOB, INFO, LDA, LDB, LDC, LDD, LDE, LDF,$ LWORK, M, NDOUBLE PRECISION DIF, SCALE* ..* .. Array Arguments ..INTEGER IWORK( * )DOUBLE PRECISION A( LDA, * ), B( LDB, * ), C( LDC, * ),$ D( LDD, * ), E( LDE, * ), F( LDF, * ),$ WORK( * )* ..** Purpose* =======** DTGSYL solves the generalized Sylvester equation:** A * R - L * B = scale * C (1)* D * R - L * E = scale * F** where R and L are unknown m-by-n matrices, (A, D), (B, E) and* (C, F) are given matrix pairs of size m-by-m, n-by-n and m-by-n,* respectively, with real entries. (A, D) and (B, E) must be in* generalized (real) Schur canonical form, i.e. A, B are upper quasi* triangular and D, E are upper triangular.** The solution (R, L) overwrites (C, F). 0 <= SCALE <= 1 is an output* scaling factor chosen to avoid overflow.** In matrix notation (1) is equivalent to solve Zx = scale b, where* Z is defined as** Z = [ kron(In, A) -kron(B', Im) ] (2)* [ kron(In, D) -kron(E', Im) ].** Here Ik is the identity matrix of size k and X' is the transpose of* X. kron(X, Y) is the Kronecker product between the matrices X and Y.** If TRANS = 'T', DTGSYL solves the transposed system Z'*y = scale*b,* which is equivalent to solve for R and L in** A' * R + D' * L = scale * C (3)* R * B' + L * E' = scale * (-F)** This case (TRANS = 'T') is used to compute an one-norm-based estimate* of Dif[(A,D), (B,E)], the separation between the matrix pairs (A,D)* and (B,E), using DLACON.** If IJOB >= 1, DTGSYL computes a Frobenius norm-based estimate* of Dif[(A,D),(B,E)]. That is, the reciprocal of a lower bound on the* reciprocal of the smallest singular value of Z. See [1-2] for more* information.** This is a level 3 BLAS algorithm.** Arguments* =========** TRANS (input) CHARACTER*1* = 'N', solve the generalized Sylvester equation (1).* = 'T', solve the 'transposed' system (3).** IJOB (input) INTEGER* Specifies what kind of functionality to be performed.* =0: solve (1) only.* =1: The functionality of 0 and 3.* =2: The functionality of 0 and 4.* =3: Only an estimate of Dif[(A,D), (B,E)] is computed.* (look ahead strategy IJOB = 1 is used).* =4: Only an estimate of Dif[(A,D), (B,E)] is computed.* ( DGECON on sub-systems is used ).* Not referenced if TRANS = 'T'.** M (input) INTEGER* The order of the matrices A and D, and the row dimension of* the matrices C, F, R and L.** N (input) INTEGER* The order of the matrices B and E, and the column dimension* of the matrices C, F, R and L.** A (input) DOUBLE PRECISION array, dimension (LDA, M)* The upper quasi triangular matrix A.** LDA (input) INTEGER* The leading dimension of the array A. LDA >= max(1, M).** B (input) DOUBLE PRECISION array, dimension (LDB, N)* The upper quasi triangular matrix B.** LDB (input) INTEGER* The leading dimension of the array B. LDB >= max(1, N).** C (input/output) DOUBLE PRECISION array, dimension (LDC, N)* On entry, C contains the right-hand-side of the first matrix* equation in (1) or (3).* On exit, if IJOB = 0, 1 or 2, C has been overwritten by* the solution R. If IJOB = 3 or 4 and TRANS = 'N', C holds R,* the solution achieved during the computation of the* Dif-estimate.** LDC (input) INTEGER* The leading dimension of the array C. LDC >= max(1, M).** D (input) DOUBLE PRECISION array, dimension (LDD, M)* The upper triangular matrix D.** LDD (input) INTEGER* The leading dimension of the array D. LDD >= max(1, M).** E (input) DOUBLE PRECISION array, dimension (LDE, N)* The upper triangular matrix E.** LDE (input) INTEGER* The leading dimension of the array E. LDE >= max(1, N).** F (input/output) DOUBLE PRECISION array, dimension (LDF, N)* On entry, F contains the right-hand-side of the second matrix* equation in (1) or (3).* On exit, if IJOB = 0, 1 or 2, F has been overwritten by* the solution L. If IJOB = 3 or 4 and TRANS = 'N', F holds L,* the solution achieved during the computation of the* Dif-estimate.** LDF (input) INTEGER* The leading dimension of the array F. LDF >= max(1, M).** DIF (output) DOUBLE PRECISION* On exit DIF is the reciprocal of a lower bound of the* reciprocal of the Dif-function, i.e. DIF is an upper bound of* Dif[(A,D), (B,E)] = sigma_min(Z), where Z as in (2).* IF IJOB = 0 or TRANS = 'T', DIF is not touched.** SCALE (output) DOUBLE PRECISION* On exit SCALE is the scaling factor in (1) or (3).* If 0 < SCALE < 1, C and F hold the solutions R and L, resp.,* to a slightly perturbed system but the input matrices A, B, D* and E have not been changed. If SCALE = 0, C and F hold the* solutions R and L, respectively, to the homogeneous system* with C = F = 0. Normally, SCALE = 1.** WORK (workspace/output) DOUBLE PRECISION array, dimension (LWORK)* If IJOB = 0, WORK is not referenced. Otherwise,* on exit, if INFO = 0, WORK(1) returns the optimal LWORK.** LWORK (input) INTEGER* The dimension of the array WORK. LWORK > = 1.* If IJOB = 1 or 2 and TRANS = 'N', LWORK >= 2*M*N.** If LWORK = -1, then a workspace query is assumed; the routine* only calculates the optimal size of the WORK array, returns* this value as the first entry of the WORK array, and no error* message related to LWORK is issued by XERBLA.** IWORK (workspace) INTEGER array, dimension (M+N+6)** INFO (output) INTEGER* =0: successful exit* <0: If INFO = -i, the i-th argument had an illegal value.* >0: (A, D) and (B, E) have common or close eigenvalues.** Further Details* ===============** Based on contributions by* Bo Kagstrom and Peter Poromaa, Department of Computing Science,* Umea University, S-901 87 Umea, Sweden.** [1] B. Kagstrom and P. Poromaa, LAPACK-Style Algorithms and Software* for Solving the Generalized Sylvester Equation and Estimating the* Separation between Regular Matrix Pairs, Report UMINF - 93.23,* Department of Computing Science, Umea University, S-901 87 Umea,* Sweden, December 1993, Revised April 1994, Also as LAPACK Working* Note 75. To appear in ACM Trans. on Math. Software, Vol 22,* No 1, 1996.** [2] B. Kagstrom, A Perturbation Analysis of the Generalized Sylvester* Equation (AR - LB, DR - LE ) = (C, F), SIAM J. Matrix Anal.* Appl., 15(4):1045-1060, 1994** [3] B. Kagstrom and L. Westin, Generalized Schur Methods with* Condition Estimators for Solving the Generalized Sylvester* Equation, IEEE Transactions on Automatic Control, Vol. 34, No. 7,* July 1989, pp 745-751.** =====================================================================** .. Parameters ..DOUBLE PRECISION ZERO, ONEPARAMETER ( ZERO = 0.0D+0, ONE = 1.0D+0 )* ..* .. Local Scalars ..LOGICAL LQUERY, NOTRANINTEGER I, IE, IFUNC, IROUND, IS, ISOLVE, J, JE, JS, K,$ LINFO, LWMIN, MB, NB, P, PPQQ, PQ, QDOUBLE PRECISION DSCALE, DSUM, SCALE2, SCALOC* ..* .. External Functions ..LOGICAL LSAMEINTEGER ILAENVEXTERNAL LSAME, ILAENV* ..* .. External Subroutines ..EXTERNAL DCOPY, DGEMM, DLACPY, DSCAL, DTGSY2, XERBLA* ..* .. Intrinsic Functions ..INTRINSIC DBLE, MAX, SQRT* ..* .. Executable Statements ..** Decode and test input parameters*INFO = 0NOTRAN = LSAME( TRANS, 'N' )LQUERY = ( LWORK.EQ.-1 )*IF( ( IJOB.EQ.1 .OR. IJOB.EQ.2 ) .AND. NOTRAN ) THENLWMIN = MAX( 1, 2*M*N )ELSELWMIN = 1END IF*IF( .NOT.NOTRAN .AND. .NOT.LSAME( TRANS, 'T' ) ) THENINFO = -1ELSE IF( ( IJOB.LT.0 ) .OR. ( IJOB.GT.4 ) ) THENINFO = -2ELSE IF( M.LE.0 ) THENINFO = -3ELSE IF( N.LE.0 ) THENINFO = -4ELSE IF( LDA.LT.MAX( 1, M ) ) THENINFO = -6ELSE IF( LDB.LT.MAX( 1, N ) ) THENINFO = -8ELSE IF( LDC.LT.MAX( 1, M ) ) THENINFO = -10ELSE IF( LDD.LT.MAX( 1, M ) ) THENINFO = -12ELSE IF( LDE.LT.MAX( 1, N ) ) THENINFO = -14ELSE IF( LDF.LT.MAX( 1, M ) ) THENINFO = -16ELSE IF( LWORK.LT.LWMIN .AND. .NOT.LQUERY ) THENINFO = -20END IF*IF( INFO.EQ.0 ) THENWORK( 1 ) = LWMINEND IF*IF( INFO.NE.0 ) THENCALL XERBLA( 'DTGSYL', -INFO )RETURNELSE IF( LQUERY ) THENRETURNEND IF** Determine optimal block sizes MB and NB*MB = ILAENV( 2, 'DTGSYL', TRANS, M, N, -1, -1 )NB = ILAENV( 5, 'DTGSYL', TRANS, M, N, -1, -1 )*ISOLVE = 1IFUNC = 0IF( IJOB.GE.3 .AND. NOTRAN ) THENIFUNC = IJOB - 2DO 10 J = 1, NCALL DCOPY( M, ZERO, 0, C( 1, J ), 1 )CALL DCOPY( M, ZERO, 0, F( 1, J ), 1 )10 CONTINUEELSE IF( IJOB.GE.1 .AND. NOTRAN ) THENISOLVE = 2END IF*IF( ( MB.LE.1 .AND. NB.LE.1 ) .OR. ( MB.GE.M .AND. NB.GE.N ) )$ THEN*DO 30 IROUND = 1, ISOLVE** Use unblocked Level 2 solver*DSCALE = ZERODSUM = ONEPQ = 0CALL DTGSY2( TRANS, IFUNC, M, N, A, LDA, B, LDB, C, LDC, D,$ LDD, E, LDE, F, LDF, SCALE, DSUM, DSCALE,$ IWORK, PQ, INFO )IF( DSCALE.NE.ZERO ) THENIF( IJOB.EQ.1 .OR. IJOB.EQ.3 ) THENDIF = SQRT( DBLE( 2*M*N ) ) / ( DSCALE*SQRT( DSUM ) )ELSEDIF = SQRT( DBLE( PQ ) ) / ( DSCALE*SQRT( DSUM ) )END IFEND IF*IF( ISOLVE.EQ.2 .AND. IROUND.EQ.1 ) THENIFUNC = IJOBSCALE2 = SCALECALL DLACPY( 'F', M, N, C, LDC, WORK, M )CALL DLACPY( 'F', M, N, F, LDF, WORK( M*N+1 ), M )DO 20 J = 1, NCALL DCOPY( M, ZERO, 0, C( 1, J ), 1 )CALL DCOPY( M, ZERO, 0, F( 1, J ), 1 )20 CONTINUEELSE IF( ISOLVE.EQ.2 .AND. IROUND.EQ.2 ) THENCALL DLACPY( 'F', M, N, WORK, M, C, LDC )CALL DLACPY( 'F', M, N, WORK( M*N+1 ), M, F, LDF )SCALE = SCALE2END IF30 CONTINUE*RETURNEND IF** Determine block structure of A*P = 0I = 140 CONTINUEIF( I.GT.M )$ GO TO 50P = P + 1IWORK( P ) = II = I + MBIF( I.GE.M )$ GO TO 50IF( A( I, I-1 ).NE.ZERO )$ I = I + 1GO TO 4050 CONTINUE*IWORK( P+1 ) = M + 1IF( IWORK( P ).EQ.IWORK( P+1 ) )$ P = P - 1** Determine block structure of B*Q = P + 1J = 160 CONTINUEIF( J.GT.N )$ GO TO 70Q = Q + 1IWORK( Q ) = JJ = J + NBIF( J.GE.N )$ GO TO 70IF( B( J, J-1 ).NE.ZERO )$ J = J + 1GO TO 6070 CONTINUE*IWORK( Q+1 ) = N + 1IF( IWORK( Q ).EQ.IWORK( Q+1 ) )$ Q = Q - 1*IF( NOTRAN ) THEN*DO 150 IROUND = 1, ISOLVE** Solve (I, J)-subsystem* A(I, I) * R(I, J) - L(I, J) * B(J, J) = C(I, J)* D(I, I) * R(I, J) - L(I, J) * E(J, J) = F(I, J)* for I = P, P - 1,..., 1; J = 1, 2,..., Q*DSCALE = ZERODSUM = ONEPQ = 0SCALE = ONEDO 130 J = P + 2, QJS = IWORK( J )JE = IWORK( J+1 ) - 1NB = JE - JS + 1DO 120 I = P, 1, -1IS = IWORK( I )IE = IWORK( I+1 ) - 1MB = IE - IS + 1PPQQ = 0CALL DTGSY2( TRANS, IFUNC, MB, NB, A( IS, IS ), LDA,$ B( JS, JS ), LDB, C( IS, JS ), LDC,$ D( IS, IS ), LDD, E( JS, JS ), LDE,$ F( IS, JS ), LDF, SCALOC, DSUM, DSCALE,$ IWORK( Q+2 ), PPQQ, LINFO )IF( LINFO.GT.0 )$ INFO = LINFO*PQ = PQ + PPQQIF( SCALOC.NE.ONE ) THENDO 80 K = 1, JS - 1CALL DSCAL( M, SCALOC, C( 1, K ), 1 )CALL DSCAL( M, SCALOC, F( 1, K ), 1 )80 CONTINUEDO 90 K = JS, JECALL DSCAL( IS-1, SCALOC, C( 1, K ), 1 )CALL DSCAL( IS-1, SCALOC, F( 1, K ), 1 )90 CONTINUEDO 100 K = JS, JECALL DSCAL( M-IE, SCALOC, C( IE+1, K ), 1 )CALL DSCAL( M-IE, SCALOC, F( IE+1, K ), 1 )100 CONTINUEDO 110 K = JE + 1, NCALL DSCAL( M, SCALOC, C( 1, K ), 1 )CALL DSCAL( M, SCALOC, F( 1, K ), 1 )110 CONTINUESCALE = SCALE*SCALOCEND IF** Substitute R(I, J) and L(I, J) into remaining* equation.*IF( I.GT.1 ) THENCALL DGEMM( 'N', 'N', IS-1, NB, MB, -ONE,$ A( 1, IS ), LDA, C( IS, JS ), LDC, ONE,$ C( 1, JS ), LDC )CALL DGEMM( 'N', 'N', IS-1, NB, MB, -ONE,$ D( 1, IS ), LDD, C( IS, JS ), LDC, ONE,$ F( 1, JS ), LDF )END IFIF( J.LT.Q ) THENCALL DGEMM( 'N', 'N', MB, N-JE, NB, ONE,$ F( IS, JS ), LDF, B( JS, JE+1 ), LDB,$ ONE, C( IS, JE+1 ), LDC )CALL DGEMM( 'N', 'N', MB, N-JE, NB, ONE,$ F( IS, JS ), LDF, E( JS, JE+1 ), LDE,$ ONE, F( IS, JE+1 ), LDF )END IF120 CONTINUE130 CONTINUEIF( DSCALE.NE.ZERO ) THENIF( IJOB.EQ.1 .OR. IJOB.EQ.3 ) THENDIF = SQRT( DBLE( 2*M*N ) ) / ( DSCALE*SQRT( DSUM ) )ELSEDIF = SQRT( DBLE( PQ ) ) / ( DSCALE*SQRT( DSUM ) )END IFEND IFIF( ISOLVE.EQ.2 .AND. IROUND.EQ.1 ) THENIFUNC = IJOBSCALE2 = SCALECALL DLACPY( 'F', M, N, C, LDC, WORK, M )CALL DLACPY( 'F', M, N, F, LDF, WORK( M*N+1 ), M )DO 140 J = 1, NCALL DCOPY( M, ZERO, 0, C( 1, J ), 1 )CALL DCOPY( M, ZERO, 0, F( 1, J ), 1 )140 CONTINUEELSE IF( ISOLVE.EQ.2 .AND. IROUND.EQ.2 ) THENCALL DLACPY( 'F', M, N, WORK, M, C, LDC )CALL DLACPY( 'F', M, N, WORK( M*N+1 ), M, F, LDF )SCALE = SCALE2END IF150 CONTINUE*ELSE** Solve transposed (I, J)-subsystem* A(I, I)' * R(I, J) + D(I, I)' * L(I, J) = C(I, J)* R(I, J) * B(J, J)' + L(I, J) * E(J, J)' = -F(I, J)* for I = 1,2,..., P; J = Q, Q-1,..., 1*SCALE = ONEDO 210 I = 1, PIS = IWORK( I )IE = IWORK( I+1 ) - 1MB = IE - IS + 1DO 200 J = Q, P + 2, -1JS = IWORK( J )JE = IWORK( J+1 ) - 1NB = JE - JS + 1CALL DTGSY2( TRANS, IFUNC, MB, NB, A( IS, IS ), LDA,$ B( JS, JS ), LDB, C( IS, JS ), LDC,$ D( IS, IS ), LDD, E( JS, JS ), LDE,$ F( IS, JS ), LDF, SCALOC, DSUM, DSCALE,$ IWORK( Q+2 ), PPQQ, LINFO )IF( LINFO.GT.0 )$ INFO = LINFOIF( SCALOC.NE.ONE ) THENDO 160 K = 1, JS - 1CALL DSCAL( M, SCALOC, C( 1, K ), 1 )CALL DSCAL( M, SCALOC, F( 1, K ), 1 )160 CONTINUEDO 170 K = JS, JECALL DSCAL( IS-1, SCALOC, C( 1, K ), 1 )CALL DSCAL( IS-1, SCALOC, F( 1, K ), 1 )170 CONTINUEDO 180 K = JS, JECALL DSCAL( M-IE, SCALOC, C( IE+1, K ), 1 )CALL DSCAL( M-IE, SCALOC, F( IE+1, K ), 1 )180 CONTINUEDO 190 K = JE + 1, NCALL DSCAL( M, SCALOC, C( 1, K ), 1 )CALL DSCAL( M, SCALOC, F( 1, K ), 1 )190 CONTINUESCALE = SCALE*SCALOCEND IF** Substitute R(I, J) and L(I, J) into remaining equation.*IF( J.GT.P+2 ) THENCALL DGEMM( 'N', 'T', MB, JS-1, NB, ONE, C( IS, JS ),$ LDC, B( 1, JS ), LDB, ONE, F( IS, 1 ),$ LDF )CALL DGEMM( 'N', 'T', MB, JS-1, NB, ONE, F( IS, JS ),$ LDF, E( 1, JS ), LDE, ONE, F( IS, 1 ),$ LDF )END IFIF( I.LT.P ) THENCALL DGEMM( 'T', 'N', M-IE, NB, MB, -ONE,$ A( IS, IE+1 ), LDA, C( IS, JS ), LDC, ONE,$ C( IE+1, JS ), LDC )CALL DGEMM( 'T', 'N', M-IE, NB, MB, -ONE,$ D( IS, IE+1 ), LDD, F( IS, JS ), LDF, ONE,$ C( IE+1, JS ), LDC )END IF200 CONTINUE210 CONTINUE*END IF*WORK( 1 ) = LWMIN*RETURN** End of DTGSYL*ENDSUBROUTINE DTPCON( NORM, UPLO, DIAG, N, AP, RCOND, WORK, IWORK,$ INFO )** -- LAPACK routine (version 3.0) --* Univ. of Tennessee, Univ. of California Berkeley, NAG Ltd.,* Courant Institute, Argonne National Lab, and Rice University* March 31, 1993** .. Scalar Arguments ..CHARACTER DIAG, NORM, UPLOINTEGER INFO, NDOUBLE PRECISION RCOND* ..* .. Array Arguments ..INTEGER IWORK( * )DOUBLE PRECISION AP( * ), WORK( * )* ..** Purpose* =======** DTPCON estimates the reciprocal of the condition number of a packed* triangular matrix A, in either the 1-norm or the infinity-norm.** The norm of A is computed and an estimate is obtained for* norm(inv(A)), then the reciprocal of the condition number is* computed as* RCOND = 1 / ( norm(A) * norm(inv(A)) ).** Arguments* =========** NORM (input) CHARACTER*1* Specifies whether the 1-norm condition number or the* infinity-norm condition number is required:* = '1' or 'O': 1-norm;* = 'I': Infinity-norm.** UPLO (input) CHARACTER*1* = 'U': A is upper triangular;* = 'L': A is lower triangular.** DIAG (input) CHARACTER*1* = 'N': A is non-unit triangular;* = 'U': A is unit triangular.** N (input) INTEGER* The order of the matrix A. N >= 0.** AP (input) DOUBLE PRECISION array, dimension (N*(N+1)/2)* The upper or lower triangular matrix A, packed columnwise in* a linear array. The j-th column of A is stored in the array* AP as follows:* if UPLO = 'U', AP(i + (j-1)*j/2) = A(i,j) for 1<=i<=j;* if UPLO = 'L', AP(i + (j-1)*(2n-j)/2) = A(i,j) for j<=i<=n.* If DIAG = 'U', the diagonal elements of A are not referenced* and are assumed to be 1.** RCOND (output) DOUBLE PRECISION* The reciprocal of the condition number of the matrix A,* computed as RCOND = 1/(norm(A) * norm(inv(A))).** WORK (workspace) DOUBLE PRECISION array, dimension (3*N)** IWORK (workspace) INTEGER array, dimension (N)** INFO (output) INTEGER* = 0: successful exit* < 0: if INFO = -i, the i-th argument had an illegal value** =====================================================================** .. Parameters ..DOUBLE PRECISION ONE, ZEROPARAMETER ( ONE = 1.0D+0, ZERO = 0.0D+0 )* ..* .. Local Scalars ..LOGICAL NOUNIT, ONENRM, UPPERCHARACTER NORMININTEGER IX, KASE, KASE1DOUBLE PRECISION AINVNM, ANORM, SCALE, SMLNUM, XNORM* ..* .. External Functions ..LOGICAL LSAMEINTEGER IDAMAXDOUBLE PRECISION DLAMCH, DLANTPEXTERNAL LSAME, IDAMAX, DLAMCH, DLANTP* ..* .. External Subroutines ..EXTERNAL DLACON, DLATPS, DRSCL, XERBLA* ..* .. Intrinsic Functions ..INTRINSIC ABS, DBLE, MAX* ..* .. Executable Statements ..** Test the input parameters.*INFO = 0UPPER = LSAME( UPLO, 'U' )ONENRM = NORM.EQ.'1' .OR. LSAME( NORM, 'O' )NOUNIT = LSAME( DIAG, 'N' )*IF( .NOT.ONENRM .AND. .NOT.LSAME( NORM, 'I' ) ) THENINFO = -1ELSE IF( .NOT.UPPER .AND. .NOT.LSAME( UPLO, 'L' ) ) THENINFO = -2ELSE IF( .NOT.NOUNIT .AND. .NOT.LSAME( DIAG, 'U' ) ) THENINFO = -3ELSE IF( N.LT.0 ) THENINFO = -4END IFIF( INFO.NE.0 ) THENCALL XERBLA( 'DTPCON', -INFO )RETURNEND IF** Quick return if possible*IF( N.EQ.0 ) THENRCOND = ONERETURNEND IF*RCOND = ZEROSMLNUM = DLAMCH( 'Safe minimum' )*DBLE( MAX( 1, N ) )** Compute the norm of the triangular matrix A.*ANORM = DLANTP( NORM, UPLO, DIAG, N, AP, WORK )** Continue only if ANORM > 0.*IF( ANORM.GT.ZERO ) THEN** Estimate the norm of the inverse of A.*AINVNM = ZERONORMIN = 'N'IF( ONENRM ) THENKASE1 = 1ELSEKASE1 = 2END IFKASE = 010 CONTINUECALL DLACON( N, WORK( N+1 ), WORK, IWORK, AINVNM, KASE )IF( KASE.NE.0 ) THENIF( KASE.EQ.KASE1 ) THEN** Multiply by inv(A).*CALL DLATPS( UPLO, 'No transpose', DIAG, NORMIN, N, AP,$ WORK, SCALE, WORK( 2*N+1 ), INFO )ELSE** Multiply by inv(A').*CALL DLATPS( UPLO, 'Transpose', DIAG, NORMIN, N, AP,$ WORK, SCALE, WORK( 2*N+1 ), INFO )END IFNORMIN = 'Y'** Multiply by 1/SCALE if doing so will not cause overflow.*IF( SCALE.NE.ONE ) THENIX = IDAMAX( N, WORK, 1 )XNORM = ABS( WORK( IX ) )IF( SCALE.LT.XNORM*SMLNUM .OR. SCALE.EQ.ZERO )$ GO TO 20CALL DRSCL( N, SCALE, WORK, 1 )END IFGO TO 10END IF** Compute the estimate of the reciprocal condition number.*IF( AINVNM.NE.ZERO )$ RCOND = ( ONE / ANORM ) / AINVNMEND IF*20 CONTINUERETURN** End of DTPCON*ENDSUBROUTINE DTPRFS( UPLO, TRANS, DIAG, N, NRHS, AP, B, LDB, X, LDX,$ FERR, BERR, WORK, IWORK, INFO )** -- LAPACK routine (version 3.0) --* Univ. of Tennessee, Univ. of California Berkeley, NAG Ltd.,* Courant Institute, Argonne National Lab, and Rice University* September 30, 1994** .. Scalar Arguments ..CHARACTER DIAG, TRANS, UPLOINTEGER INFO, LDB, LDX, N, NRHS* ..* .. Array Arguments ..INTEGER IWORK( * )DOUBLE PRECISION AP( * ), B( LDB, * ), BERR( * ), FERR( * ),$ WORK( * ), X( LDX, * )* ..** Purpose* =======** DTPRFS provides error bounds and backward error estimates for the* solution to a system of linear equations with a triangular packed* coefficient matrix.** The solution matrix X must be computed by DTPTRS or some other* means before entering this routine. DTPRFS does not do iterative* refinement because doing so cannot improve the backward error.** Arguments* =========** UPLO (input) CHARACTER*1* = 'U': A is upper triangular;* = 'L': A is lower triangular.** TRANS (input) CHARACTER*1* Specifies the form of the system of equations:* = 'N': A * X = B (No transpose)* = 'T': A**T * X = B (Transpose)* = 'C': A**H * X = B (Conjugate transpose = Transpose)** DIAG (input) CHARACTER*1* = 'N': A is non-unit triangular;* = 'U': A is unit triangular.** 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 matrices B and X. NRHS >= 0.** AP (input) DOUBLE PRECISION array, dimension (N*(N+1)/2)* The upper or lower triangular matrix A, packed columnwise in* a linear array. The j-th column of A is stored in the array* AP as follows:* if UPLO = 'U', AP(i + (j-1)*j/2) = A(i,j) for 1<=i<=j;* if UPLO = 'L', AP(i + (j-1)*(2*n-j)/2) = A(i,j) for j<=i<=n.* If DIAG = 'U', the diagonal elements of A are not referenced* and are assumed to be 1.** B (input) DOUBLE PRECISION array, dimension (LDB,NRHS)* The right hand side matrix B.** LDB (input) INTEGER* The leading dimension of the array B. LDB >= max(1,N).** X (input) DOUBLE PRECISION array, dimension (LDX,NRHS)* The solution matrix X.** LDX (input) INTEGER* The leading dimension of the array X. LDX >= max(1,N).** FERR (output) DOUBLE PRECISION array, dimension (NRHS)* The estimated forward error bound for each solution vector* X(j) (the j-th column of the solution matrix X).* If XTRUE is the true solution corresponding to X(j), FERR(j)* is an estimated upper bound for the magnitude of the largest* element in (X(j) - XTRUE) divided by the magnitude of the* largest element in X(j). The estimate is as reliable as* the estimate for RCOND, and is almost always a slight* overestimate of the true error.** BERR (output) DOUBLE PRECISION array, dimension (NRHS)* The componentwise relative backward error of each solution* vector X(j) (i.e., the smallest relative change in* any element of A or B that makes X(j) an exact solution).** WORK (workspace) DOUBLE PRECISION array, dimension (3*N)** IWORK (workspace) INTEGER array, dimension (N)** INFO (output) INTEGER* = 0: successful exit* < 0: if INFO = -i, the i-th argument had an illegal value** =====================================================================** .. Parameters ..DOUBLE PRECISION ZEROPARAMETER ( ZERO = 0.0D+0 )DOUBLE PRECISION ONEPARAMETER ( ONE = 1.0D+0 )* ..* .. Local Scalars ..LOGICAL NOTRAN, NOUNIT, UPPERCHARACTER TRANSTINTEGER I, J, K, KASE, KC, NZDOUBLE PRECISION EPS, LSTRES, S, SAFE1, SAFE2, SAFMIN, XK* ..* .. External Subroutines ..EXTERNAL DAXPY, DCOPY, DLACON, DTPMV, DTPSV, XERBLA* ..* .. Intrinsic Functions ..INTRINSIC ABS, MAX* ..* .. External Functions ..LOGICAL LSAMEDOUBLE PRECISION DLAMCHEXTERNAL LSAME, DLAMCH* ..* .. Executable Statements ..** Test the input parameters.*INFO = 0UPPER = LSAME( UPLO, 'U' )NOTRAN = LSAME( TRANS, 'N' )NOUNIT = LSAME( DIAG, 'N' )*IF( .NOT.UPPER .AND. .NOT.LSAME( UPLO, 'L' ) ) THENINFO = -1ELSE IF( .NOT.NOTRAN .AND. .NOT.LSAME( TRANS, 'T' ) .AND. .NOT.$ LSAME( TRANS, 'C' ) ) THENINFO = -2ELSE IF( .NOT.NOUNIT .AND. .NOT.LSAME( DIAG, 'U' ) ) THENINFO = -3ELSE IF( N.LT.0 ) THENINFO = -4ELSE IF( NRHS.LT.0 ) THENINFO = -5ELSE IF( LDB.LT.MAX( 1, N ) ) THENINFO = -8ELSE IF( LDX.LT.MAX( 1, N ) ) THENINFO = -10END IFIF( INFO.NE.0 ) THENCALL XERBLA( 'DTPRFS', -INFO )RETURNEND IF** Quick return if possible*IF( N.EQ.0 .OR. NRHS.EQ.0 ) THENDO 10 J = 1, NRHSFERR( J ) = ZEROBERR( J ) = ZERO10 CONTINUERETURNEND IF*IF( NOTRAN ) THENTRANST = 'T'ELSETRANST = 'N'END IF** NZ = maximum number of nonzero elements in each row of A, plus 1*NZ = N + 1EPS = DLAMCH( 'Epsilon' )SAFMIN = DLAMCH( 'Safe minimum' )SAFE1 = NZ*SAFMINSAFE2 = SAFE1 / EPS** Do for each right hand side*DO 250 J = 1, NRHS** Compute residual R = B - op(A) * X,* where op(A) = A or A', depending on TRANS.*CALL DCOPY( N, X( 1, J ), 1, WORK( N+1 ), 1 )CALL DTPMV( UPLO, TRANS, DIAG, N, AP, WORK( N+1 ), 1 )CALL DAXPY( N, -ONE, B( 1, J ), 1, WORK( N+1 ), 1 )** Compute componentwise relative backward error from formula** max(i) ( abs(R(i)) / ( abs(op(A))*abs(X) + abs(B) )(i) )** where abs(Z) is the componentwise absolute value of the matrix* or vector Z. If the i-th component of the denominator is less* than SAFE2, then SAFE1 is added to the i-th components of the* numerator and denominator before dividing.*DO 20 I = 1, NWORK( I ) = ABS( B( I, J ) )20 CONTINUE*IF( NOTRAN ) THEN** Compute abs(A)*abs(X) + abs(B).*IF( UPPER ) THENKC = 1IF( NOUNIT ) THENDO 40 K = 1, NXK = ABS( X( K, J ) )DO 30 I = 1, KWORK( I ) = WORK( I ) + ABS( AP( KC+I-1 ) )*XK30 CONTINUEKC = KC + K40 CONTINUEELSEDO 60 K = 1, NXK = ABS( X( K, J ) )DO 50 I = 1, K - 1WORK( I ) = WORK( I ) + ABS( AP( KC+I-1 ) )*XK50 CONTINUEWORK( K ) = WORK( K ) + XKKC = KC + K60 CONTINUEEND IFELSEKC = 1IF( NOUNIT ) THENDO 80 K = 1, NXK = ABS( X( K, J ) )DO 70 I = K, NWORK( I ) = WORK( I ) + ABS( AP( KC+I-K ) )*XK70 CONTINUEKC = KC + N - K + 180 CONTINUEELSEDO 100 K = 1, NXK = ABS( X( K, J ) )DO 90 I = K + 1, NWORK( I ) = WORK( I ) + ABS( AP( KC+I-K ) )*XK90 CONTINUEWORK( K ) = WORK( K ) + XKKC = KC + N - K + 1100 CONTINUEEND IFEND IFELSE** Compute abs(A')*abs(X) + abs(B).*IF( UPPER ) THENKC = 1IF( NOUNIT ) THENDO 120 K = 1, NS = ZERODO 110 I = 1, KS = S + ABS( AP( KC+I-1 ) )*ABS( X( I, J ) )110 CONTINUEWORK( K ) = WORK( K ) + SKC = KC + K120 CONTINUEELSEDO 140 K = 1, NS = ABS( X( K, J ) )DO 130 I = 1, K - 1S = S + ABS( AP( KC+I-1 ) )*ABS( X( I, J ) )130 CONTINUEWORK( K ) = WORK( K ) + SKC = KC + K140 CONTINUEEND IFELSEKC = 1IF( NOUNIT ) THENDO 160 K = 1, NS = ZERODO 150 I = K, NS = S + ABS( AP( KC+I-K ) )*ABS( X( I, J ) )150 CONTINUEWORK( K ) = WORK( K ) + SKC = KC + N - K + 1160 CONTINUEELSEDO 180 K = 1, NS = ABS( X( K, J ) )DO 170 I = K + 1, NS = S + ABS( AP( KC+I-K ) )*ABS( X( I, J ) )170 CONTINUEWORK( K ) = WORK( K ) + SKC = KC + N - K + 1180 CONTINUEEND IFEND IFEND IFS = ZERODO 190 I = 1, NIF( WORK( I ).GT.SAFE2 ) THENS = MAX( S, ABS( WORK( N+I ) ) / WORK( I ) )ELSES = MAX( S, ( ABS( WORK( N+I ) )+SAFE1 ) /$ ( WORK( I )+SAFE1 ) )END IF190 CONTINUEBERR( J ) = S** Bound error from formula** norm(X - XTRUE) / norm(X) .le. FERR =* norm( abs(inv(op(A)))** ( abs(R) + NZ*EPS*( abs(op(A))*abs(X)+abs(B) ))) / norm(X)** where* norm(Z) is the magnitude of the largest component of Z* inv(op(A)) is the inverse of op(A)* abs(Z) is the componentwise absolute value of the matrix or* vector Z* NZ is the maximum number of nonzeros in any row of A, plus 1* EPS is machine epsilon** The i-th component of abs(R)+NZ*EPS*(abs(op(A))*abs(X)+abs(B))* is incremented by SAFE1 if the i-th component of* abs(op(A))*abs(X) + abs(B) is less than SAFE2.** Use DLACON to estimate the infinity-norm of the matrix* inv(op(A)) * diag(W),* where W = abs(R) + NZ*EPS*( abs(op(A))*abs(X)+abs(B) )))*DO 200 I = 1, NIF( WORK( I ).GT.SAFE2 ) THENWORK( I ) = ABS( WORK( N+I ) ) + NZ*EPS*WORK( I )ELSEWORK( I ) = ABS( WORK( N+I ) ) + NZ*EPS*WORK( I ) + SAFE1END IF200 CONTINUE*KASE = 0210 CONTINUECALL DLACON( N, WORK( 2*N+1 ), WORK( N+1 ), IWORK, FERR( J ),$ KASE )IF( KASE.NE.0 ) THENIF( KASE.EQ.1 ) THEN** Multiply by diag(W)*inv(op(A)').*CALL DTPSV( UPLO, TRANST, DIAG, N, AP, WORK( N+1 ), 1 )DO 220 I = 1, NWORK( N+I ) = WORK( I )*WORK( N+I )220 CONTINUEELSE** Multiply by inv(op(A))*diag(W).*DO 230 I = 1, NWORK( N+I ) = WORK( I )*WORK( N+I )230 CONTINUECALL DTPSV( UPLO, TRANS, DIAG, N, AP, WORK( N+1 ), 1 )END IFGO TO 210END IF** Normalize error.*LSTRES = ZERODO 240 I = 1, NLSTRES = MAX( LSTRES, ABS( X( I, J ) ) )240 CONTINUEIF( LSTRES.NE.ZERO )$ FERR( J ) = FERR( J ) / LSTRES*250 CONTINUE*RETURN** End of DTPRFS*ENDSUBROUTINE DTPTRI( UPLO, DIAG, N, AP, INFO )** -- LAPACK routine (version 3.0) --* Univ. of Tennessee, Univ. of California Berkeley, NAG Ltd.,* Courant Institute, Argonne National Lab, and Rice University* September 30, 1994** .. Scalar Arguments ..CHARACTER DIAG, UPLOINTEGER INFO, N* ..* .. Array Arguments ..DOUBLE PRECISION AP( * )* ..** Purpose* =======** DTPTRI computes the inverse of a real upper or lower triangular* matrix A stored in packed format.** Arguments* =========** UPLO (input) CHARACTER*1* = 'U': A is upper triangular;* = 'L': A is lower triangular.** DIAG (input) CHARACTER*1* = 'N': A is non-unit triangular;* = 'U': A is unit triangular.** N (input) INTEGER* The order of the matrix A. N >= 0.** AP (input/output) DOUBLE PRECISION array, dimension (N*(N+1)/2)* On entry, the upper or lower triangular matrix A, stored* columnwise in a linear array. The j-th column of A is stored* in the array AP as follows:* if UPLO = 'U', AP(i + (j-1)*j/2) = A(i,j) for 1<=i<=j;* if UPLO = 'L', AP(i + (j-1)*((2*n-j)/2) = A(i,j) for j<=i<=n.* See below for further details.* On exit, the (triangular) inverse of the original matrix, in* the same packed storage format.** INFO (output) INTEGER* = 0: successful exit* < 0: if INFO = -i, the i-th argument had an illegal value* > 0: if INFO = i, A(i,i) is exactly zero. The triangular* matrix is singular and its inverse can not be computed.** Further Details* ===============** A triangular matrix A can be transferred to packed storage using one* of the following program segments:** UPLO = 'U': UPLO = 'L':** JC = 1 JC = 1* DO 2 J = 1, N DO 2 J = 1, N* DO 1 I = 1, J DO 1 I = J, N* AP(JC+I-1) = A(I,J) AP(JC+I-J) = A(I,J)* 1 CONTINUE 1 CONTINUE* JC = JC + J JC = JC + N - J + 1* 2 CONTINUE 2 CONTINUE** =====================================================================** .. Parameters ..DOUBLE PRECISION ONE, ZEROPARAMETER ( ONE = 1.0D+0, ZERO = 0.0D+0 )* ..* .. Local Scalars ..LOGICAL NOUNIT, UPPERINTEGER J, JC, JCLAST, JJDOUBLE PRECISION AJJ* ..* .. External Functions ..LOGICAL LSAMEEXTERNAL LSAME* ..* .. External Subroutines ..EXTERNAL DSCAL, DTPMV, XERBLA* ..* .. Executable Statements ..** Test the input parameters.*INFO = 0UPPER = LSAME( UPLO, 'U' )NOUNIT = LSAME( DIAG, 'N' )IF( .NOT.UPPER .AND. .NOT.LSAME( UPLO, 'L' ) ) THENINFO = -1ELSE IF( .NOT.NOUNIT .AND. .NOT.LSAME( DIAG, 'U' ) ) THENINFO = -2ELSE IF( N.LT.0 ) THENINFO = -3END IFIF( INFO.NE.0 ) THENCALL XERBLA( 'DTPTRI', -INFO )RETURNEND IF** Check for singularity if non-unit.*IF( NOUNIT ) THENIF( UPPER ) THENJJ = 0DO 10 INFO = 1, NJJ = JJ + INFOIF( AP( JJ ).EQ.ZERO )$ RETURN10 CONTINUEELSEJJ = 1DO 20 INFO = 1, NIF( AP( JJ ).EQ.ZERO )$ RETURNJJ = JJ + N - INFO + 120 CONTINUEEND IFINFO = 0END IF*IF( UPPER ) THEN** Compute inverse of upper triangular matrix.*JC = 1DO 30 J = 1, NIF( NOUNIT ) THENAP( JC+J-1 ) = ONE / AP( JC+J-1 )AJJ = -AP( JC+J-1 )ELSEAJJ = -ONEEND IF** Compute elements 1:j-1 of j-th column.*CALL DTPMV( 'Upper', 'No transpose', DIAG, J-1, AP,$ AP( JC ), 1 )CALL DSCAL( J-1, AJJ, AP( JC ), 1 )JC = JC + J30 CONTINUE*ELSE** Compute inverse of lower triangular matrix.*JC = N*( N+1 ) / 2DO 40 J = N, 1, -1IF( NOUNIT ) THENAP( JC ) = ONE / AP( JC )AJJ = -AP( JC )ELSEAJJ = -ONEEND IFIF( J.LT.N ) THEN** Compute elements j+1:n of j-th column.*CALL DTPMV( 'Lower', 'No transpose', DIAG, N-J,$ AP( JCLAST ), AP( JC+1 ), 1 )CALL DSCAL( N-J, AJJ, AP( JC+1 ), 1 )END IFJCLAST = JCJC = JC - N + J - 240 CONTINUEEND IF*RETURN** End of DTPTRI*ENDSUBROUTINE DTPTRS( UPLO, TRANS, DIAG, N, NRHS, AP, B, LDB, INFO )** -- LAPACK routine (version 3.0) --* Univ. of Tennessee, Univ. of California Berkeley, NAG Ltd.,* Courant Institute, Argonne National Lab, and Rice University* September 30, 1994** .. Scalar Arguments ..CHARACTER DIAG, TRANS, UPLOINTEGER INFO, LDB, N, NRHS* ..* .. Array Arguments ..DOUBLE PRECISION AP( * ), B( LDB, * )* ..** Purpose* =======** DTPTRS solves a triangular system of the form** A * X = B or A**T * X = B,** where A is a triangular matrix of order N stored in packed format,* and B is an N-by-NRHS matrix. A check is made to verify that A is* nonsingular.** Arguments* =========** UPLO (input) CHARACTER*1* = 'U': A is upper triangular;* = 'L': A is lower triangular.** TRANS (input) CHARACTER*1* Specifies the form of the system of equations:* = 'N': A * X = B (No transpose)* = 'T': A**T * X = B (Transpose)* = 'C': A**H * X = B (Conjugate transpose = Transpose)** DIAG (input) CHARACTER*1* = 'N': A is non-unit triangular;* = 'U': A is unit triangular.** 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.** AP (input) DOUBLE PRECISION array, dimension (N*(N+1)/2)* The upper or lower triangular matrix A, packed columnwise in* a linear array. The j-th column of A is stored in the array* AP as follows:* if UPLO = 'U', AP(i + (j-1)*j/2) = A(i,j) for 1<=i<=j;* if UPLO = 'L', AP(i + (j-1)*(2*n-j)/2) = A(i,j) for j<=i<=n.** B (input/output) DOUBLE PRECISION array, dimension (LDB,NRHS)* On entry, the right hand side matrix B.* On exit, if INFO = 0, 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* > 0: if INFO = i, the i-th diagonal element of A is zero,* indicating that the matrix is singular and the* solutions X have not been computed.** =====================================================================** .. Parameters ..DOUBLE PRECISION ZEROPARAMETER ( ZERO = 0.0D+0 )* ..* .. Local Scalars ..LOGICAL NOUNIT, UPPERINTEGER J, JC* ..* .. External Functions ..LOGICAL LSAMEEXTERNAL LSAME* ..* .. External Subroutines ..EXTERNAL DTPSV, XERBLA* ..* .. Intrinsic Functions ..INTRINSIC MAX* ..* .. Executable Statements ..** Test the input parameters.*INFO = 0UPPER = LSAME( UPLO, 'U' )NOUNIT = LSAME( DIAG, 'N' )IF( .NOT.UPPER .AND. .NOT.LSAME( UPLO, 'L' ) ) THENINFO = -1ELSE IF( .NOT.LSAME( TRANS, 'N' ) .AND. .NOT.$ LSAME( TRANS, 'T' ) .AND. .NOT.LSAME( TRANS, 'C' ) ) THENINFO = -2ELSE IF( .NOT.NOUNIT .AND. .NOT.LSAME( DIAG, 'U' ) ) THENINFO = -3ELSE IF( N.LT.0 ) THENINFO = -4ELSE IF( NRHS.LT.0 ) THENINFO = -5ELSE IF( LDB.LT.MAX( 1, N ) ) THENINFO = -8END IFIF( INFO.NE.0 ) THENCALL XERBLA( 'DTPTRS', -INFO )RETURNEND IF** Quick return if possible*IF( N.EQ.0 )$ RETURN** Check for singularity.*IF( NOUNIT ) THENIF( UPPER ) THENJC = 1DO 10 INFO = 1, NIF( AP( JC+INFO-1 ).EQ.ZERO )$ RETURNJC = JC + INFO10 CONTINUEELSEJC = 1DO 20 INFO = 1, NIF( AP( JC ).EQ.ZERO )$ RETURNJC = JC + N - INFO + 120 CONTINUEEND IFEND IFINFO = 0** Solve A * x = b or A' * x = b.*DO 30 J = 1, NRHSCALL DTPSV( UPLO, TRANS, DIAG, N, AP, B( 1, J ), 1 )30 CONTINUE*RETURN** End of DTPTRS*ENDSUBROUTINE DTRCON( NORM, UPLO, DIAG, N, A, LDA, RCOND, WORK,$ IWORK, INFO )** -- LAPACK routine (version 3.0) --* Univ. of Tennessee, Univ. of California Berkeley, NAG Ltd.,* Courant Institute, Argonne National Lab, and Rice University* March 31, 1993** .. Scalar Arguments ..CHARACTER DIAG, NORM, UPLOINTEGER INFO, LDA, NDOUBLE PRECISION RCOND* ..* .. Array Arguments ..INTEGER IWORK( * )DOUBLE PRECISION A( LDA, * ), WORK( * )* ..** Purpose* =======** DTRCON estimates the reciprocal of the condition number of a* triangular matrix A, in either the 1-norm or the infinity-norm.** The norm of A is computed and an estimate is obtained for* norm(inv(A)), then the reciprocal of the condition number is* computed as* RCOND = 1 / ( norm(A) * norm(inv(A)) ).** Arguments* =========** NORM (input) CHARACTER*1* Specifies whether the 1-norm condition number or the* infinity-norm condition number is required:* = '1' or 'O': 1-norm;* = 'I': Infinity-norm.** UPLO (input) CHARACTER*1* = 'U': A is upper triangular;* = 'L': A is lower triangular.** DIAG (input) CHARACTER*1* = 'N': A is non-unit triangular;* = 'U': A is unit triangular.** N (input) INTEGER* The order of the matrix A. N >= 0.** A (input) DOUBLE PRECISION array, dimension (LDA,N)* The triangular matrix A. If UPLO = 'U', the leading N-by-N* upper triangular part of the array A contains the upper* triangular matrix, and the strictly lower triangular part of* A is not referenced. If UPLO = 'L', the leading N-by-N lower* triangular part of the array A contains the lower triangular* matrix, and the strictly upper triangular part of A is not* referenced. If DIAG = 'U', the diagonal elements of A are* also not referenced and are assumed to be 1.** LDA (input) INTEGER* The leading dimension of the array A. LDA >= max(1,N).** RCOND (output) DOUBLE PRECISION* The reciprocal of the condition number of the matrix A,* computed as RCOND = 1/(norm(A) * norm(inv(A))).** WORK (workspace) DOUBLE PRECISION array, dimension (3*N)** IWORK (workspace) INTEGER array, dimension (N)** INFO (output) INTEGER* = 0: successful exit* < 0: if INFO = -i, the i-th argument had an illegal value** =====================================================================** .. Parameters ..DOUBLE PRECISION ONE, ZEROPARAMETER ( ONE = 1.0D+0, ZERO = 0.0D+0 )* ..* .. Local Scalars ..LOGICAL NOUNIT, ONENRM, UPPERCHARACTER NORMININTEGER IX, KASE, KASE1DOUBLE PRECISION AINVNM, ANORM, SCALE, SMLNUM, XNORM* ..* .. External Functions ..LOGICAL LSAMEINTEGER IDAMAXDOUBLE PRECISION DLAMCH, DLANTREXTERNAL LSAME, IDAMAX, DLAMCH, DLANTR* ..* .. External Subroutines ..EXTERNAL DLACON, DLATRS, DRSCL, XERBLA* ..* .. Intrinsic Functions ..INTRINSIC ABS, DBLE, MAX* ..* .. Executable Statements ..** Test the input parameters.*INFO = 0UPPER = LSAME( UPLO, 'U' )ONENRM = NORM.EQ.'1' .OR. LSAME( NORM, 'O' )NOUNIT = LSAME( DIAG, 'N' )*IF( .NOT.ONENRM .AND. .NOT.LSAME( NORM, 'I' ) ) THENINFO = -1ELSE IF( .NOT.UPPER .AND. .NOT.LSAME( UPLO, 'L' ) ) THENINFO = -2ELSE IF( .NOT.NOUNIT .AND. .NOT.LSAME( DIAG, 'U' ) ) THENINFO = -3ELSE IF( N.LT.0 ) THENINFO = -4ELSE IF( LDA.LT.MAX( 1, N ) ) THENINFO = -6END IFIF( INFO.NE.0 ) THENCALL XERBLA( 'DTRCON', -INFO )RETURNEND IF** Quick return if possible*IF( N.EQ.0 ) THENRCOND = ONERETURNEND IF*RCOND = ZEROSMLNUM = DLAMCH( 'Safe minimum' )*DBLE( MAX( 1, N ) )** Compute the norm of the triangular matrix A.*ANORM = DLANTR( NORM, UPLO, DIAG, N, N, A, LDA, WORK )** Continue only if ANORM > 0.*IF( ANORM.GT.ZERO ) THEN** Estimate the norm of the inverse of A.*AINVNM = ZERONORMIN = 'N'IF( ONENRM ) THENKASE1 = 1ELSEKASE1 = 2END IFKASE = 010 CONTINUECALL DLACON( N, WORK( N+1 ), WORK, IWORK, AINVNM, KASE )IF( KASE.NE.0 ) THENIF( KASE.EQ.KASE1 ) THEN** Multiply by inv(A).*CALL DLATRS( UPLO, 'No transpose', DIAG, NORMIN, N, A,$ LDA, WORK, SCALE, WORK( 2*N+1 ), INFO )ELSE** Multiply by inv(A').*CALL DLATRS( UPLO, 'Transpose', DIAG, NORMIN, N, A, LDA,$ WORK, SCALE, WORK( 2*N+1 ), INFO )END IFNORMIN = 'Y'** Multiply by 1/SCALE if doing so will not cause overflow.*IF( SCALE.NE.ONE ) THENIX = IDAMAX( N, WORK, 1 )XNORM = ABS( WORK( IX ) )IF( SCALE.LT.XNORM*SMLNUM .OR. SCALE.EQ.ZERO )$ GO TO 20CALL DRSCL( N, SCALE, WORK, 1 )END IFGO TO 10END IF** Compute the estimate of the reciprocal condition number.*IF( AINVNM.NE.ZERO )$ RCOND = ( ONE / ANORM ) / AINVNMEND IF*20 CONTINUERETURN** End of DTRCON*ENDSUBROUTINE DTREVC( SIDE, HOWMNY, SELECT, N, T, LDT, VL, LDVL, VR,$ LDVR, MM, M, WORK, INFO )** -- LAPACK routine (version 3.0) --* Univ. of Tennessee, Univ. of California Berkeley, NAG Ltd.,* Courant Institute, Argonne National Lab, and Rice University* June 30, 1999** .. Scalar Arguments ..CHARACTER HOWMNY, SIDEINTEGER INFO, LDT, LDVL, LDVR, M, MM, N* ..* .. Array Arguments ..LOGICAL SELECT( * )DOUBLE PRECISION T( LDT, * ), VL( LDVL, * ), VR( LDVR, * ),$ WORK( * )* ..** Purpose* =======** DTREVC computes some or all of the right and/or left eigenvectors of* a real upper quasi-triangular matrix T.** The right eigenvector x and the left eigenvector y of T corresponding* to an eigenvalue w are defined by:** T*x = w*x, y'*T = w*y'** where y' denotes the conjugate transpose of the vector y.** If all eigenvectors are requested, the routine may either return the* matrices X and/or Y of right or left eigenvectors of T, or the* products Q*X and/or Q*Y, where Q is an input orthogonal* matrix. If T was obtained from the real-Schur factorization of an* original matrix A = Q*T*Q', then Q*X and Q*Y are the matrices of* right or left eigenvectors of A.** T must be in Schur canonical form (as returned by DHSEQR), that is,* block upper triangular with 1-by-1 and 2-by-2 diagonal blocks; each* 2-by-2 diagonal block has its diagonal elements equal and its* off-diagonal elements of opposite sign. Corresponding to each 2-by-2* diagonal block is a complex conjugate pair of eigenvalues and* eigenvectors; only one eigenvector of the pair is computed, namely* the one corresponding to the eigenvalue with positive imaginary part.** Arguments* =========** SIDE (input) CHARACTER*1* = 'R': compute right eigenvectors only;* = 'L': compute left eigenvectors only;* = 'B': compute both right and left eigenvectors.** HOWMNY (input) CHARACTER*1* = 'A': compute all right and/or left eigenvectors;* = 'B': compute all right and/or left eigenvectors,* and backtransform them using the input matrices* supplied in VR and/or VL;* = 'S': compute selected right and/or left eigenvectors,* specified by the logical array SELECT.** SELECT (input/output) LOGICAL array, dimension (N)* If HOWMNY = 'S', SELECT specifies the eigenvectors to be* computed.* If HOWMNY = 'A' or 'B', SELECT is not referenced.* To select the real eigenvector corresponding to a real* eigenvalue w(j), SELECT(j) must be set to .TRUE.. To select* the complex eigenvector corresponding to a complex conjugate* pair w(j) and w(j+1), either SELECT(j) or SELECT(j+1) must be* set to .TRUE.; then on exit SELECT(j) is .TRUE. and* SELECT(j+1) is .FALSE..** N (input) INTEGER* The order of the matrix T. N >= 0.** T (input) DOUBLE PRECISION array, dimension (LDT,N)* The upper quasi-triangular matrix T in Schur canonical form.** LDT (input) INTEGER* The leading dimension of the array T. LDT >= max(1,N).** VL (input/output) DOUBLE PRECISION array, dimension (LDVL,MM)* On entry, if SIDE = 'L' or 'B' and HOWMNY = 'B', VL must* contain an N-by-N matrix Q (usually the orthogonal matrix Q* of Schur vectors returned by DHSEQR).* On exit, if SIDE = 'L' or 'B', VL contains:* if HOWMNY = 'A', the matrix Y of left eigenvectors of T;* VL has the same quasi-lower triangular form* as T'. If T(i,i) is a real eigenvalue, then* the i-th column VL(i) of VL is its* corresponding eigenvector. If T(i:i+1,i:i+1)* is a 2-by-2 block whose eigenvalues are* complex-conjugate eigenvalues of T, then* VL(i)+sqrt(-1)*VL(i+1) is the complex* eigenvector corresponding to the eigenvalue* with positive real part.* if HOWMNY = 'B', the matrix Q*Y;* if HOWMNY = 'S', the left eigenvectors of T specified by* SELECT, stored consecutively in the columns* of VL, in the same order as their* eigenvalues.* A complex eigenvector corresponding to a complex eigenvalue* is stored in two consecutive columns, the first holding the* real part, and the second the imaginary part.* If SIDE = 'R', VL is not referenced.** LDVL (input) INTEGER* The leading dimension of the array VL. LDVL >= max(1,N) if* SIDE = 'L' or 'B'; LDVL >= 1 otherwise.** VR (input/output) DOUBLE PRECISION array, dimension (LDVR,MM)* On entry, if SIDE = 'R' or 'B' and HOWMNY = 'B', VR must* contain an N-by-N matrix Q (usually the orthogonal matrix Q* of Schur vectors returned by DHSEQR).* On exit, if SIDE = 'R' or 'B', VR contains:* if HOWMNY = 'A', the matrix X of right eigenvectors of T;* VR has the same quasi-upper triangular form* as T. If T(i,i) is a real eigenvalue, then* the i-th column VR(i) of VR is its* corresponding eigenvector. If T(i:i+1,i:i+1)* is a 2-by-2 block whose eigenvalues are* complex-conjugate eigenvalues of T, then* VR(i)+sqrt(-1)*VR(i+1) is the complex* eigenvector corresponding to the eigenvalue* with positive real part.* if HOWMNY = 'B', the matrix Q*X;* if HOWMNY = 'S', the right eigenvectors of T specified by* SELECT, stored consecutively in the columns* of VR, in the same order as their* eigenvalues.* A complex eigenvector corresponding to a complex eigenvalue* is stored in two consecutive columns, the first holding the* real part and the second the imaginary part.* If SIDE = 'L', VR is not referenced.** LDVR (input) INTEGER* The leading dimension of the array VR. LDVR >= max(1,N) if* SIDE = 'R' or 'B'; LDVR >= 1 otherwise.** MM (input) INTEGER* The number of columns in the arrays VL and/or VR. MM >= M.** M (output) INTEGER* The number of columns in the arrays VL and/or VR actually* used to store the eigenvectors.* If HOWMNY = 'A' or 'B', M is set to N.* Each selected real eigenvector occupies one column and each* selected complex eigenvector occupies two columns.** WORK (workspace) DOUBLE PRECISION array, dimension (3*N)** INFO (output) INTEGER* = 0: successful exit* < 0: if INFO = -i, the i-th argument had an illegal value** Further Details* ===============** The algorithm used in this program is basically backward (forward)* substitution, with scaling to make the the code robust against* possible overflow.** Each eigenvector is normalized so that the element of largest* magnitude has magnitude 1; here the magnitude of a complex number* (x,y) is taken to be |x| + |y|.** =====================================================================** .. Parameters ..DOUBLE PRECISION ZERO, ONEPARAMETER ( ZERO = 0.0D+0, ONE = 1.0D+0 )* ..* .. Local Scalars ..LOGICAL ALLV, BOTHV, LEFTV, OVER, PAIR, RIGHTV, SOMEVINTEGER I, IERR, II, IP, IS, J, J1, J2, JNXT, K, KI, N2DOUBLE PRECISION BETA, BIGNUM, EMAX, OVFL, REC, REMAX, SCALE,$ SMIN, SMLNUM, ULP, UNFL, VCRIT, VMAX, WI, WR,$ XNORM* ..* .. External Functions ..LOGICAL LSAMEINTEGER IDAMAXDOUBLE PRECISION DDOT, DLAMCHEXTERNAL LSAME, IDAMAX, DDOT, DLAMCH* ..* .. External Subroutines ..EXTERNAL DAXPY, DCOPY, DGEMV, DLALN2, DSCAL, XERBLA* ..* .. Intrinsic Functions ..INTRINSIC ABS, MAX, SQRT* ..* .. Local Arrays ..DOUBLE PRECISION X( 2, 2 )* ..* .. Executable Statements ..** Decode and test the input parameters*BOTHV = LSAME( SIDE, 'B' )RIGHTV = LSAME( SIDE, 'R' ) .OR. BOTHVLEFTV = LSAME( SIDE, 'L' ) .OR. BOTHV*ALLV = LSAME( HOWMNY, 'A' )OVER = LSAME( HOWMNY, 'B' )SOMEV = LSAME( HOWMNY, 'S' )*INFO = 0IF( .NOT.RIGHTV .AND. .NOT.LEFTV ) THENINFO = -1ELSE IF( .NOT.ALLV .AND. .NOT.OVER .AND. .NOT.SOMEV ) THENINFO = -2ELSE IF( N.LT.0 ) THENINFO = -4ELSE IF( LDT.LT.MAX( 1, N ) ) THENINFO = -6ELSE IF( LDVL.LT.1 .OR. ( LEFTV .AND. LDVL.LT.N ) ) THENINFO = -8ELSE IF( LDVR.LT.1 .OR. ( RIGHTV .AND. LDVR.LT.N ) ) THENINFO = -10ELSE** Set M to the number of columns required to store the selected* eigenvectors, standardize the array SELECT if necessary, and* test MM.*IF( SOMEV ) THENM = 0PAIR = .FALSE.DO 10 J = 1, NIF( PAIR ) THENPAIR = .FALSE.SELECT( J ) = .FALSE.ELSEIF( J.LT.N ) THENIF( T( J+1, J ).EQ.ZERO ) THENIF( SELECT( J ) )$ M = M + 1ELSEPAIR = .TRUE.IF( SELECT( J ) .OR. SELECT( J+1 ) ) THENSELECT( J ) = .TRUE.M = M + 2END IFEND IFELSEIF( SELECT( N ) )$ M = M + 1END IFEND IF10 CONTINUEELSEM = NEND IF*IF( MM.LT.M ) THENINFO = -11END IFEND IFIF( INFO.NE.0 ) THENCALL XERBLA( 'DTREVC', -INFO )RETURNEND IF** Quick return if possible.*IF( N.EQ.0 )$ RETURN** Set the constants to control overflow.*UNFL = DLAMCH( 'Safe minimum' )OVFL = ONE / UNFLCALL DLABAD( UNFL, OVFL )ULP = DLAMCH( 'Precision' )SMLNUM = UNFL*( N / ULP )BIGNUM = ( ONE-ULP ) / SMLNUM** Compute 1-norm of each column of strictly upper triangular* part of T to control overflow in triangular solver.*WORK( 1 ) = ZERODO 30 J = 2, NWORK( J ) = ZERODO 20 I = 1, J - 1WORK( J ) = WORK( J ) + ABS( T( I, J ) )20 CONTINUE30 CONTINUE** Index IP is used to specify the real or complex eigenvalue:* IP = 0, real eigenvalue,* 1, first of conjugate complex pair: (wr,wi)* -1, second of conjugate complex pair: (wr,wi)*N2 = 2*N*IF( RIGHTV ) THEN** Compute right eigenvectors.*IP = 0IS = MDO 140 KI = N, 1, -1*IF( IP.EQ.1 )$ GO TO 130IF( KI.EQ.1 )$ GO TO 40IF( T( KI, KI-1 ).EQ.ZERO )$ GO TO 40IP = -1*40 CONTINUEIF( SOMEV ) THENIF( IP.EQ.0 ) THENIF( .NOT.SELECT( KI ) )$ GO TO 130ELSEIF( .NOT.SELECT( KI-1 ) )$ GO TO 130END IFEND IF** Compute the KI-th eigenvalue (WR,WI).*WR = T( KI, KI )WI = ZEROIF( IP.NE.0 )$ WI = SQRT( ABS( T( KI, KI-1 ) ) )*$ SQRT( ABS( T( KI-1, KI ) ) )SMIN = MAX( ULP*( ABS( WR )+ABS( WI ) ), SMLNUM )*IF( IP.EQ.0 ) THEN** Real right eigenvector*WORK( KI+N ) = ONE** Form right-hand side*DO 50 K = 1, KI - 1WORK( K+N ) = -T( K, KI )50 CONTINUE** Solve the upper quasi-triangular system:* (T(1:KI-1,1:KI-1) - WR)*X = SCALE*WORK.*JNXT = KI - 1DO 60 J = KI - 1, 1, -1IF( J.GT.JNXT )$ GO TO 60J1 = JJ2 = JJNXT = J - 1IF( J.GT.1 ) THENIF( T( J, J-1 ).NE.ZERO ) THENJ1 = J - 1JNXT = J - 2END IFEND IF*IF( J1.EQ.J2 ) THEN** 1-by-1 diagonal block*CALL DLALN2( .FALSE., 1, 1, SMIN, ONE, T( J, J ),$ LDT, ONE, ONE, WORK( J+N ), N, WR,$ ZERO, X, 2, SCALE, XNORM, IERR )** Scale X(1,1) to avoid overflow when updating* the right-hand side.*IF( XNORM.GT.ONE ) THENIF( WORK( J ).GT.BIGNUM / XNORM ) THENX( 1, 1 ) = X( 1, 1 ) / XNORMSCALE = SCALE / XNORMEND IFEND IF** Scale if necessary*IF( SCALE.NE.ONE )$ CALL DSCAL( KI, SCALE, WORK( 1+N ), 1 )WORK( J+N ) = X( 1, 1 )** Update right-hand side*CALL DAXPY( J-1, -X( 1, 1 ), T( 1, J ), 1,$ WORK( 1+N ), 1 )*ELSE** 2-by-2 diagonal block*CALL DLALN2( .FALSE., 2, 1, SMIN, ONE,$ T( J-1, J-1 ), LDT, ONE, ONE,$ WORK( J-1+N ), N, WR, ZERO, X, 2,$ SCALE, XNORM, IERR )** Scale X(1,1) and X(2,1) to avoid overflow when* updating the right-hand side.*IF( XNORM.GT.ONE ) THENBETA = MAX( WORK( J-1 ), WORK( J ) )IF( BETA.GT.BIGNUM / XNORM ) THENX( 1, 1 ) = X( 1, 1 ) / XNORMX( 2, 1 ) = X( 2, 1 ) / XNORMSCALE = SCALE / XNORMEND IFEND IF** Scale if necessary*IF( SCALE.NE.ONE )$ CALL DSCAL( KI, SCALE, WORK( 1+N ), 1 )WORK( J-1+N ) = X( 1, 1 )WORK( J+N ) = X( 2, 1 )** Update right-hand side*CALL DAXPY( J-2, -X( 1, 1 ), T( 1, J-1 ), 1,$ WORK( 1+N ), 1 )CALL DAXPY( J-2, -X( 2, 1 ), T( 1, J ), 1,$ WORK( 1+N ), 1 )END IF60 CONTINUE** Copy the vector x or Q*x to VR and normalize.*IF( .NOT.OVER ) THENCALL DCOPY( KI, WORK( 1+N ), 1, VR( 1, IS ), 1 )*II = IDAMAX( KI, VR( 1, IS ), 1 )REMAX = ONE / ABS( VR( II, IS ) )CALL DSCAL( KI, REMAX, VR( 1, IS ), 1 )*DO 70 K = KI + 1, NVR( K, IS ) = ZERO70 CONTINUEELSEIF( KI.GT.1 )$ CALL DGEMV( 'N', N, KI-1, ONE, VR, LDVR,$ WORK( 1+N ), 1, WORK( KI+N ),$ VR( 1, KI ), 1 )*II = IDAMAX( N, VR( 1, KI ), 1 )REMAX = ONE / ABS( VR( II, KI ) )CALL DSCAL( N, REMAX, VR( 1, KI ), 1 )END IF*ELSE** Complex right eigenvector.** Initial solve* [ (T(KI-1,KI-1) T(KI-1,KI) ) - (WR + I* WI)]*X = 0.* [ (T(KI,KI-1) T(KI,KI) ) ]*IF( ABS( T( KI-1, KI ) ).GE.ABS( T( KI, KI-1 ) ) ) THENWORK( KI-1+N ) = ONEWORK( KI+N2 ) = WI / T( KI-1, KI )ELSEWORK( KI-1+N ) = -WI / T( KI, KI-1 )WORK( KI+N2 ) = ONEEND IFWORK( KI+N ) = ZEROWORK( KI-1+N2 ) = ZERO** Form right-hand side*DO 80 K = 1, KI - 2WORK( K+N ) = -WORK( KI-1+N )*T( K, KI-1 )WORK( K+N2 ) = -WORK( KI+N2 )*T( K, KI )80 CONTINUE** Solve upper quasi-triangular system:* (T(1:KI-2,1:KI-2) - (WR+i*WI))*X = SCALE*(WORK+i*WORK2)*JNXT = KI - 2DO 90 J = KI - 2, 1, -1IF( J.GT.JNXT )$ GO TO 90J1 = JJ2 = JJNXT = J - 1IF( J.GT.1 ) THENIF( T( J, J-1 ).NE.ZERO ) THENJ1 = J - 1JNXT = J - 2END IFEND IF*IF( J1.EQ.J2 ) THEN** 1-by-1 diagonal block*CALL DLALN2( .FALSE., 1, 2, SMIN, ONE, T( J, J ),$ LDT, ONE, ONE, WORK( J+N ), N, WR, WI,$ X, 2, SCALE, XNORM, IERR )** Scale X(1,1) and X(1,2) to avoid overflow when* updating the right-hand side.*IF( XNORM.GT.ONE ) THENIF( WORK( J ).GT.BIGNUM / XNORM ) THENX( 1, 1 ) = X( 1, 1 ) / XNORMX( 1, 2 ) = X( 1, 2 ) / XNORMSCALE = SCALE / XNORMEND IFEND IF** Scale if necessary*IF( SCALE.NE.ONE ) THENCALL DSCAL( KI, SCALE, WORK( 1+N ), 1 )CALL DSCAL( KI, SCALE, WORK( 1+N2 ), 1 )END IFWORK( J+N ) = X( 1, 1 )WORK( J+N2 ) = X( 1, 2 )** Update the right-hand side*CALL DAXPY( J-1, -X( 1, 1 ), T( 1, J ), 1,$ WORK( 1+N ), 1 )CALL DAXPY( J-1, -X( 1, 2 ), T( 1, J ), 1,$ WORK( 1+N2 ), 1 )*ELSE** 2-by-2 diagonal block*CALL DLALN2( .FALSE., 2, 2, SMIN, ONE,$ T( J-1, J-1 ), LDT, ONE, ONE,$ WORK( J-1+N ), N, WR, WI, X, 2, SCALE,$ XNORM, IERR )** Scale X to avoid overflow when updating* the right-hand side.*IF( XNORM.GT.ONE ) THENBETA = MAX( WORK( J-1 ), WORK( J ) )IF( BETA.GT.BIGNUM / XNORM ) THENREC = ONE / XNORMX( 1, 1 ) = X( 1, 1 )*RECX( 1, 2 ) = X( 1, 2 )*RECX( 2, 1 ) = X( 2, 1 )*RECX( 2, 2 ) = X( 2, 2 )*RECSCALE = SCALE*RECEND IFEND IF** Scale if necessary*IF( SCALE.NE.ONE ) THENCALL DSCAL( KI, SCALE, WORK( 1+N ), 1 )CALL DSCAL( KI, SCALE, WORK( 1+N2 ), 1 )END IFWORK( J-1+N ) = X( 1, 1 )WORK( J+N ) = X( 2, 1 )WORK( J-1+N2 ) = X( 1, 2 )WORK( J+N2 ) = X( 2, 2 )** Update the right-hand side*CALL DAXPY( J-2, -X( 1, 1 ), T( 1, J-1 ), 1,$ WORK( 1+N ), 1 )CALL DAXPY( J-2, -X( 2, 1 ), T( 1, J ), 1,$ WORK( 1+N ), 1 )CALL DAXPY( J-2, -X( 1, 2 ), T( 1, J-1 ), 1,$ WORK( 1+N2 ), 1 )CALL DAXPY( J-2, -X( 2, 2 ), T( 1, J ), 1,$ WORK( 1+N2 ), 1 )END IF90 CONTINUE** Copy the vector x or Q*x to VR and normalize.*IF( .NOT.OVER ) THENCALL DCOPY( KI, WORK( 1+N ), 1, VR( 1, IS-1 ), 1 )CALL DCOPY( KI, WORK( 1+N2 ), 1, VR( 1, IS ), 1 )*EMAX = ZERODO 100 K = 1, KIEMAX = MAX( EMAX, ABS( VR( K, IS-1 ) )+$ ABS( VR( K, IS ) ) )100 CONTINUE*REMAX = ONE / EMAXCALL DSCAL( KI, REMAX, VR( 1, IS-1 ), 1 )CALL DSCAL( KI, REMAX, VR( 1, IS ), 1 )*DO 110 K = KI + 1, NVR( K, IS-1 ) = ZEROVR( K, IS ) = ZERO110 CONTINUE*ELSE*IF( KI.GT.2 ) THENCALL DGEMV( 'N', N, KI-2, ONE, VR, LDVR,$ WORK( 1+N ), 1, WORK( KI-1+N ),$ VR( 1, KI-1 ), 1 )CALL DGEMV( 'N', N, KI-2, ONE, VR, LDVR,$ WORK( 1+N2 ), 1, WORK( KI+N2 ),$ VR( 1, KI ), 1 )ELSECALL DSCAL( N, WORK( KI-1+N ), VR( 1, KI-1 ), 1 )CALL DSCAL( N, WORK( KI+N2 ), VR( 1, KI ), 1 )END IF*EMAX = ZERODO 120 K = 1, NEMAX = MAX( EMAX, ABS( VR( K, KI-1 ) )+$ ABS( VR( K, KI ) ) )120 CONTINUEREMAX = ONE / EMAXCALL DSCAL( N, REMAX, VR( 1, KI-1 ), 1 )CALL DSCAL( N, REMAX, VR( 1, KI ), 1 )END IFEND IF*IS = IS - 1IF( IP.NE.0 )$ IS = IS - 1130 CONTINUEIF( IP.EQ.1 )$ IP = 0IF( IP.EQ.-1 )$ IP = 1140 CONTINUEEND IF*IF( LEFTV ) THEN** Compute left eigenvectors.*IP = 0IS = 1DO 260 KI = 1, N*IF( IP.EQ.-1 )$ GO TO 250IF( KI.EQ.N )$ GO TO 150IF( T( KI+1, KI ).EQ.ZERO )$ GO TO 150IP = 1*150 CONTINUEIF( SOMEV ) THENIF( .NOT.SELECT( KI ) )$ GO TO 250END IF** Compute the KI-th eigenvalue (WR,WI).*WR = T( KI, KI )WI = ZEROIF( IP.NE.0 )$ WI = SQRT( ABS( T( KI, KI+1 ) ) )*$ SQRT( ABS( T( KI+1, KI ) ) )SMIN = MAX( ULP*( ABS( WR )+ABS( WI ) ), SMLNUM )*IF( IP.EQ.0 ) THEN** Real left eigenvector.*WORK( KI+N ) = ONE** Form right-hand side*DO 160 K = KI + 1, NWORK( K+N ) = -T( KI, K )160 CONTINUE** Solve the quasi-triangular system:* (T(KI+1:N,KI+1:N) - WR)'*X = SCALE*WORK*VMAX = ONEVCRIT = BIGNUM*JNXT = KI + 1DO 170 J = KI + 1, NIF( J.LT.JNXT )$ GO TO 170J1 = JJ2 = JJNXT = J + 1IF( J.LT.N ) THENIF( T( J+1, J ).NE.ZERO ) THENJ2 = J + 1JNXT = J + 2END IFEND IF*IF( J1.EQ.J2 ) THEN** 1-by-1 diagonal block** Scale if necessary to avoid overflow when forming* the right-hand side.*IF( WORK( J ).GT.VCRIT ) THENREC = ONE / VMAXCALL DSCAL( N-KI+1, REC, WORK( KI+N ), 1 )VMAX = ONEVCRIT = BIGNUMEND IF*WORK( J+N ) = WORK( J+N ) -$ DDOT( J-KI-1, T( KI+1, J ), 1,$ WORK( KI+1+N ), 1 )** Solve (T(J,J)-WR)'*X = WORK*CALL DLALN2( .FALSE., 1, 1, SMIN, ONE, T( J, J ),$ LDT, ONE, ONE, WORK( J+N ), N, WR,$ ZERO, X, 2, SCALE, XNORM, IERR )** Scale if necessary*IF( SCALE.NE.ONE )$ CALL DSCAL( N-KI+1, SCALE, WORK( KI+N ), 1 )WORK( J+N ) = X( 1, 1 )VMAX = MAX( ABS( WORK( J+N ) ), VMAX )VCRIT = BIGNUM / VMAX*ELSE** 2-by-2 diagonal block** Scale if necessary to avoid overflow when forming* the right-hand side.*BETA = MAX( WORK( J ), WORK( J+1 ) )IF( BETA.GT.VCRIT ) THENREC = ONE / VMAXCALL DSCAL( N-KI+1, REC, WORK( KI+N ), 1 )VMAX = ONEVCRIT = BIGNUMEND IF*WORK( J+N ) = WORK( J+N ) -$ DDOT( J-KI-1, T( KI+1, J ), 1,$ WORK( KI+1+N ), 1 )*WORK( J+1+N ) = WORK( J+1+N ) -$ DDOT( J-KI-1, T( KI+1, J+1 ), 1,$ WORK( KI+1+N ), 1 )** Solve* [T(J,J)-WR T(J,J+1) ]'* X = SCALE*( WORK1 )* [T(J+1,J) T(J+1,J+1)-WR] ( WORK2 )*CALL DLALN2( .TRUE., 2, 1, SMIN, ONE, T( J, J ),$ LDT, ONE, ONE, WORK( J+N ), N, WR,$ ZERO, X, 2, SCALE, XNORM, IERR )** Scale if necessary*IF( SCALE.NE.ONE )$ CALL DSCAL( N-KI+1, SCALE, WORK( KI+N ), 1 )WORK( J+N ) = X( 1, 1 )WORK( J+1+N ) = X( 2, 1 )*VMAX = MAX( ABS( WORK( J+N ) ),$ ABS( WORK( J+1+N ) ), VMAX )VCRIT = BIGNUM / VMAX*END IF170 CONTINUE** Copy the vector x or Q*x to VL and normalize.*IF( .NOT.OVER ) THENCALL DCOPY( N-KI+1, WORK( KI+N ), 1, VL( KI, IS ), 1 )*II = IDAMAX( N-KI+1, VL( KI, IS ), 1 ) + KI - 1REMAX = ONE / ABS( VL( II, IS ) )CALL DSCAL( N-KI+1, REMAX, VL( KI, IS ), 1 )*DO 180 K = 1, KI - 1VL( K, IS ) = ZERO180 CONTINUE*ELSE*IF( KI.LT.N )$ CALL DGEMV( 'N', N, N-KI, ONE, VL( 1, KI+1 ), LDVL,$ WORK( KI+1+N ), 1, WORK( KI+N ),$ VL( 1, KI ), 1 )*II = IDAMAX( N, VL( 1, KI ), 1 )REMAX = ONE / ABS( VL( II, KI ) )CALL DSCAL( N, REMAX, VL( 1, KI ), 1 )*END IF*ELSE** Complex left eigenvector.** Initial solve:* ((T(KI,KI) T(KI,KI+1) )' - (WR - I* WI))*X = 0.* ((T(KI+1,KI) T(KI+1,KI+1)) )*IF( ABS( T( KI, KI+1 ) ).GE.ABS( T( KI+1, KI ) ) ) THENWORK( KI+N ) = WI / T( KI, KI+1 )WORK( KI+1+N2 ) = ONEELSEWORK( KI+N ) = ONEWORK( KI+1+N2 ) = -WI / T( KI+1, KI )END IFWORK( KI+1+N ) = ZEROWORK( KI+N2 ) = ZERO** Form right-hand side*DO 190 K = KI + 2, NWORK( K+N ) = -WORK( KI+N )*T( KI, K )WORK( K+N2 ) = -WORK( KI+1+N2 )*T( KI+1, K )190 CONTINUE** Solve complex quasi-triangular system:* ( T(KI+2,N:KI+2,N) - (WR-i*WI) )*X = WORK1+i*WORK2*VMAX = ONEVCRIT = BIGNUM*JNXT = KI + 2DO 200 J = KI + 2, NIF( J.LT.JNXT )$ GO TO 200J1 = JJ2 = JJNXT = J + 1IF( J.LT.N ) THENIF( T( J+1, J ).NE.ZERO ) THENJ2 = J + 1JNXT = J + 2END IFEND IF*IF( J1.EQ.J2 ) THEN** 1-by-1 diagonal block** Scale if necessary to avoid overflow when* forming the right-hand side elements.*IF( WORK( J ).GT.VCRIT ) THENREC = ONE / VMAXCALL DSCAL( N-KI+1, REC, WORK( KI+N ), 1 )CALL DSCAL( N-KI+1, REC, WORK( KI+N2 ), 1 )VMAX = ONEVCRIT = BIGNUMEND IF*WORK( J+N ) = WORK( J+N ) -$ DDOT( J-KI-2, T( KI+2, J ), 1,$ WORK( KI+2+N ), 1 )WORK( J+N2 ) = WORK( J+N2 ) -$ DDOT( J-KI-2, T( KI+2, J ), 1,$ WORK( KI+2+N2 ), 1 )** Solve (T(J,J)-(WR-i*WI))*(X11+i*X12)= WK+I*WK2*CALL DLALN2( .FALSE., 1, 2, SMIN, ONE, T( J, J ),$ LDT, ONE, ONE, WORK( J+N ), N, WR,$ -WI, X, 2, SCALE, XNORM, IERR )** Scale if necessary*IF( SCALE.NE.ONE ) THENCALL DSCAL( N-KI+1, SCALE, WORK( KI+N ), 1 )CALL DSCAL( N-KI+1, SCALE, WORK( KI+N2 ), 1 )END IFWORK( J+N ) = X( 1, 1 )WORK( J+N2 ) = X( 1, 2 )VMAX = MAX( ABS( WORK( J+N ) ),$ ABS( WORK( J+N2 ) ), VMAX )VCRIT = BIGNUM / VMAX*ELSE** 2-by-2 diagonal block** Scale if necessary to avoid overflow when forming* the right-hand side elements.*BETA = MAX( WORK( J ), WORK( J+1 ) )IF( BETA.GT.VCRIT ) THENREC = ONE / VMAXCALL DSCAL( N-KI+1, REC, WORK( KI+N ), 1 )CALL DSCAL( N-KI+1, REC, WORK( KI+N2 ), 1 )VMAX = ONEVCRIT = BIGNUMEND IF*WORK( J+N ) = WORK( J+N ) -$ DDOT( J-KI-2, T( KI+2, J ), 1,$ WORK( KI+2+N ), 1 )*WORK( J+N2 ) = WORK( J+N2 ) -$ DDOT( J-KI-2, T( KI+2, J ), 1,$ WORK( KI+2+N2 ), 1 )*WORK( J+1+N ) = WORK( J+1+N ) -$ DDOT( J-KI-2, T( KI+2, J+1 ), 1,$ WORK( KI+2+N ), 1 )*WORK( J+1+N2 ) = WORK( J+1+N2 ) -$ DDOT( J-KI-2, T( KI+2, J+1 ), 1,$ WORK( KI+2+N2 ), 1 )** Solve 2-by-2 complex linear equation* ([T(j,j) T(j,j+1) ]'-(wr-i*wi)*I)*X = SCALE*B* ([T(j+1,j) T(j+1,j+1)] )*CALL DLALN2( .TRUE., 2, 2, SMIN, ONE, T( J, J ),$ LDT, ONE, ONE, WORK( J+N ), N, WR,$ -WI, X, 2, SCALE, XNORM, IERR )** Scale if necessary*IF( SCALE.NE.ONE ) THENCALL DSCAL( N-KI+1, SCALE, WORK( KI+N ), 1 )CALL DSCAL( N-KI+1, SCALE, WORK( KI+N2 ), 1 )END IFWORK( J+N ) = X( 1, 1 )WORK( J+N2 ) = X( 1, 2 )WORK( J+1+N ) = X( 2, 1 )WORK( J+1+N2 ) = X( 2, 2 )VMAX = MAX( ABS( X( 1, 1 ) ), ABS( X( 1, 2 ) ),$ ABS( X( 2, 1 ) ), ABS( X( 2, 2 ) ), VMAX )VCRIT = BIGNUM / VMAX*END IF200 CONTINUE** Copy the vector x or Q*x to VL and normalize.*210 CONTINUEIF( .NOT.OVER ) THENCALL DCOPY( N-KI+1, WORK( KI+N ), 1, VL( KI, IS ), 1 )CALL DCOPY( N-KI+1, WORK( KI+N2 ), 1, VL( KI, IS+1 ),$ 1 )*EMAX = ZERODO 220 K = KI, NEMAX = MAX( EMAX, ABS( VL( K, IS ) )+$ ABS( VL( K, IS+1 ) ) )220 CONTINUEREMAX = ONE / EMAXCALL DSCAL( N-KI+1, REMAX, VL( KI, IS ), 1 )CALL DSCAL( N-KI+1, REMAX, VL( KI, IS+1 ), 1 )*DO 230 K = 1, KI - 1VL( K, IS ) = ZEROVL( K, IS+1 ) = ZERO230 CONTINUEELSEIF( KI.LT.N-1 ) THENCALL DGEMV( 'N', N, N-KI-1, ONE, VL( 1, KI+2 ),$ LDVL, WORK( KI+2+N ), 1, WORK( KI+N ),$ VL( 1, KI ), 1 )CALL DGEMV( 'N', N, N-KI-1, ONE, VL( 1, KI+2 ),$ LDVL, WORK( KI+2+N2 ), 1,$ WORK( KI+1+N2 ), VL( 1, KI+1 ), 1 )ELSECALL DSCAL( N, WORK( KI+N ), VL( 1, KI ), 1 )CALL DSCAL( N, WORK( KI+1+N2 ), VL( 1, KI+1 ), 1 )END IF*EMAX = ZERODO 240 K = 1, NEMAX = MAX( EMAX, ABS( VL( K, KI ) )+$ ABS( VL( K, KI+1 ) ) )240 CONTINUEREMAX = ONE / EMAXCALL DSCAL( N, REMAX, VL( 1, KI ), 1 )CALL DSCAL( N, REMAX, VL( 1, KI+1 ), 1 )*END IF*END IF*IS = IS + 1IF( IP.NE.0 )$ IS = IS + 1250 CONTINUEIF( IP.EQ.-1 )$ IP = 0IF( IP.EQ.1 )$ IP = -1*260 CONTINUE*END IF*RETURN** End of DTREVC*ENDSUBROUTINE DTREXC( COMPQ, N, T, LDT, Q, LDQ, IFST, ILST, WORK,$ INFO )** -- LAPACK routine (version 3.0) --* Univ. of Tennessee, Univ. of California Berkeley, NAG Ltd.,* Courant Institute, Argonne National Lab, and Rice University* March 31, 1993** .. Scalar Arguments ..CHARACTER COMPQINTEGER IFST, ILST, INFO, LDQ, LDT, N* ..* .. Array Arguments ..DOUBLE PRECISION Q( LDQ, * ), T( LDT, * ), WORK( * )* ..** Purpose* =======** DTREXC reorders the real Schur factorization of a real matrix* A = Q*T*Q**T, so that the diagonal block of T with row index IFST is* moved to row ILST.** The real Schur form T is reordered by an orthogonal similarity* transformation Z**T*T*Z, and optionally the matrix Q of Schur vectors* is updated by postmultiplying it with Z.** T must be in Schur canonical form (as returned by DHSEQR), that is,* block upper triangular with 1-by-1 and 2-by-2 diagonal blocks; each* 2-by-2 diagonal block has its diagonal elements equal and its* off-diagonal elements of opposite sign.** Arguments* =========** COMPQ (input) CHARACTER*1* = 'V': update the matrix Q of Schur vectors;* = 'N': do not update Q.** N (input) INTEGER* The order of the matrix T. N >= 0.** T (input/output) DOUBLE PRECISION array, dimension (LDT,N)* On entry, the upper quasi-triangular matrix T, in Schur* Schur canonical form.* On exit, the reordered upper quasi-triangular matrix, again* in Schur canonical form.** LDT (input) INTEGER* The leading dimension of the array T. LDT >= max(1,N).** Q (input/output) DOUBLE PRECISION array, dimension (LDQ,N)* On entry, if COMPQ = 'V', the matrix Q of Schur vectors.* On exit, if COMPQ = 'V', Q has been postmultiplied by the* orthogonal transformation matrix Z which reorders T.* If COMPQ = 'N', Q is not referenced.** LDQ (input) INTEGER* The leading dimension of the array Q. LDQ >= max(1,N).** IFST (input/output) INTEGER* ILST (input/output) INTEGER* Specify the reordering of the diagonal blocks of T.* The block with row index IFST is moved to row ILST, by a* sequence of transpositions between adjacent blocks.* On exit, if IFST pointed on entry to the second row of a* 2-by-2 block, it is changed to point to the first row; ILST* always points to the first row of the block in its final* position (which may differ from its input value by +1 or -1).* 1 <= IFST <= N; 1 <= ILST <= N.** WORK (workspace) DOUBLE PRECISION array, dimension (N)** INFO (output) INTEGER* = 0: successful exit* < 0: if INFO = -i, the i-th argument had an illegal value* = 1: two adjacent blocks were too close to swap (the problem* is very ill-conditioned); T may have been partially* reordered, and ILST points to the first row of the* current position of the block being moved.** =====================================================================** .. Parameters ..DOUBLE PRECISION ZEROPARAMETER ( ZERO = 0.0D+0 )* ..* .. Local Scalars ..LOGICAL WANTQINTEGER HERE, NBF, NBL, NBNEXT* ..* .. External Functions ..LOGICAL LSAMEEXTERNAL LSAME* ..* .. External Subroutines ..EXTERNAL DLAEXC, XERBLA* ..* .. Intrinsic Functions ..INTRINSIC MAX* ..* .. Executable Statements ..** Decode and test the input arguments.*INFO = 0WANTQ = LSAME( COMPQ, 'V' )IF( .NOT.WANTQ .AND. .NOT.LSAME( COMPQ, 'N' ) ) THENINFO = -1ELSE IF( N.LT.0 ) THENINFO = -2ELSE IF( LDT.LT.MAX( 1, N ) ) THENINFO = -4ELSE IF( LDQ.LT.1 .OR. ( WANTQ .AND. LDQ.LT.MAX( 1, N ) ) ) THENINFO = -6ELSE IF( IFST.LT.1 .OR. IFST.GT.N ) THENINFO = -7ELSE IF( ILST.LT.1 .OR. ILST.GT.N ) THENINFO = -8END IFIF( INFO.NE.0 ) THENCALL XERBLA( 'DTREXC', -INFO )RETURNEND IF** Quick return if possible*IF( N.LE.1 )$ RETURN** Determine the first row of specified block* and find out it is 1 by 1 or 2 by 2.*IF( IFST.GT.1 ) THENIF( T( IFST, IFST-1 ).NE.ZERO )$ IFST = IFST - 1END IFNBF = 1IF( IFST.LT.N ) THENIF( T( IFST+1, IFST ).NE.ZERO )$ NBF = 2END IF** Determine the first row of the final block* and find out it is 1 by 1 or 2 by 2.*IF( ILST.GT.1 ) THENIF( T( ILST, ILST-1 ).NE.ZERO )$ ILST = ILST - 1END IFNBL = 1IF( ILST.LT.N ) THENIF( T( ILST+1, ILST ).NE.ZERO )$ NBL = 2END IF*IF( IFST.EQ.ILST )$ RETURN*IF( IFST.LT.ILST ) THEN** Update ILST*IF( NBF.EQ.2 .AND. NBL.EQ.1 )$ ILST = ILST - 1IF( NBF.EQ.1 .AND. NBL.EQ.2 )$ ILST = ILST + 1*HERE = IFST*10 CONTINUE** Swap block with next one below*IF( NBF.EQ.1 .OR. NBF.EQ.2 ) THEN** Current block either 1 by 1 or 2 by 2*NBNEXT = 1IF( HERE+NBF+1.LE.N ) THENIF( T( HERE+NBF+1, HERE+NBF ).NE.ZERO )$ NBNEXT = 2END IFCALL DLAEXC( WANTQ, N, T, LDT, Q, LDQ, HERE, NBF, NBNEXT,$ WORK, INFO )IF( INFO.NE.0 ) THENILST = HERERETURNEND IFHERE = HERE + NBNEXT** Test if 2 by 2 block breaks into two 1 by 1 blocks*IF( NBF.EQ.2 ) THENIF( T( HERE+1, HERE ).EQ.ZERO )$ NBF = 3END IF*ELSE** Current block consists of two 1 by 1 blocks each of which* must be swapped individually*NBNEXT = 1IF( HERE+3.LE.N ) THENIF( T( HERE+3, HERE+2 ).NE.ZERO )$ NBNEXT = 2END IFCALL DLAEXC( WANTQ, N, T, LDT, Q, LDQ, HERE+1, 1, NBNEXT,$ WORK, INFO )IF( INFO.NE.0 ) THENILST = HERERETURNEND IFIF( NBNEXT.EQ.1 ) THEN** Swap two 1 by 1 blocks, no problems possible*CALL DLAEXC( WANTQ, N, T, LDT, Q, LDQ, HERE, 1, NBNEXT,$ WORK, INFO )HERE = HERE + 1ELSE** Recompute NBNEXT in case 2 by 2 split*IF( T( HERE+2, HERE+1 ).EQ.ZERO )$ NBNEXT = 1IF( NBNEXT.EQ.2 ) THEN** 2 by 2 Block did not split*CALL DLAEXC( WANTQ, N, T, LDT, Q, LDQ, HERE, 1,$ NBNEXT, WORK, INFO )IF( INFO.NE.0 ) THENILST = HERERETURNEND IFHERE = HERE + 2ELSE** 2 by 2 Block did split*CALL DLAEXC( WANTQ, N, T, LDT, Q, LDQ, HERE, 1, 1,$ WORK, INFO )CALL DLAEXC( WANTQ, N, T, LDT, Q, LDQ, HERE+1, 1, 1,$ WORK, INFO )HERE = HERE + 2END IFEND IFEND IFIF( HERE.LT.ILST )$ GO TO 10*ELSE*HERE = IFST20 CONTINUE** Swap block with next one above*IF( NBF.EQ.1 .OR. NBF.EQ.2 ) THEN** Current block either 1 by 1 or 2 by 2*NBNEXT = 1IF( HERE.GE.3 ) THENIF( T( HERE-1, HERE-2 ).NE.ZERO )$ NBNEXT = 2END IFCALL DLAEXC( WANTQ, N, T, LDT, Q, LDQ, HERE-NBNEXT, NBNEXT,$ NBF, WORK, INFO )IF( INFO.NE.0 ) THENILST = HERERETURNEND IFHERE = HERE - NBNEXT** Test if 2 by 2 block breaks into two 1 by 1 blocks*IF( NBF.EQ.2 ) THENIF( T( HERE+1, HERE ).EQ.ZERO )$ NBF = 3END IF*ELSE** Current block consists of two 1 by 1 blocks each of which* must be swapped individually*NBNEXT = 1IF( HERE.GE.3 ) THENIF( T( HERE-1, HERE-2 ).NE.ZERO )$ NBNEXT = 2END IFCALL DLAEXC( WANTQ, N, T, LDT, Q, LDQ, HERE-NBNEXT, NBNEXT,$ 1, WORK, INFO )IF( INFO.NE.0 ) THENILST = HERERETURNEND IFIF( NBNEXT.EQ.1 ) THEN** Swap two 1 by 1 blocks, no problems possible*CALL DLAEXC( WANTQ, N, T, LDT, Q, LDQ, HERE, NBNEXT, 1,$ WORK, INFO )HERE = HERE - 1ELSE** Recompute NBNEXT in case 2 by 2 split*IF( T( HERE, HERE-1 ).EQ.ZERO )$ NBNEXT = 1IF( NBNEXT.EQ.2 ) THEN** 2 by 2 Block did not split*CALL DLAEXC( WANTQ, N, T, LDT, Q, LDQ, HERE-1, 2, 1,$ WORK, INFO )IF( INFO.NE.0 ) THENILST = HERERETURNEND IFHERE = HERE - 2ELSE** 2 by 2 Block did split*CALL DLAEXC( WANTQ, N, T, LDT, Q, LDQ, HERE, 1, 1,$ WORK, INFO )CALL DLAEXC( WANTQ, N, T, LDT, Q, LDQ, HERE-1, 1, 1,$ WORK, INFO )HERE = HERE - 2END IFEND IFEND IFIF( HERE.GT.ILST )$ GO TO 20END IFILST = HERE*RETURN** End of DTREXC*ENDSUBROUTINE DTRRFS( UPLO, TRANS, DIAG, N, NRHS, A, LDA, B, LDB, X,$ LDX, FERR, BERR, WORK, IWORK, INFO )** -- LAPACK routine (version 3.0) --* Univ. of Tennessee, Univ. of California Berkeley, NAG Ltd.,* Courant Institute, Argonne National Lab, and Rice University* September 30, 1994** .. Scalar Arguments ..CHARACTER DIAG, TRANS, UPLOINTEGER INFO, LDA, LDB, LDX, N, NRHS* ..* .. Array Arguments ..INTEGER IWORK( * )DOUBLE PRECISION A( LDA, * ), B( LDB, * ), BERR( * ), FERR( * ),$ WORK( * ), X( LDX, * )* ..** Purpose* =======** DTRRFS provides error bounds and backward error estimates for the* solution to a system of linear equations with a triangular* coefficient matrix.** The solution matrix X must be computed by DTRTRS or some other* means before entering this routine. DTRRFS does not do iterative* refinement because doing so cannot improve the backward error.** Arguments* =========** UPLO (input) CHARACTER*1* = 'U': A is upper triangular;* = 'L': A is lower triangular.** TRANS (input) CHARACTER*1* Specifies the form of the system of equations:* = 'N': A * X = B (No transpose)* = 'T': A**T * X = B (Transpose)* = 'C': A**H * X = B (Conjugate transpose = Transpose)** DIAG (input) CHARACTER*1* = 'N': A is non-unit triangular;* = 'U': A is unit triangular.** 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 matrices B and X. NRHS >= 0.** A (input) DOUBLE PRECISION array, dimension (LDA,N)* The triangular matrix A. If UPLO = 'U', the leading N-by-N* upper triangular part of the array A contains the upper* triangular matrix, and the strictly lower triangular part of* A is not referenced. If UPLO = 'L', the leading N-by-N lower* triangular part of the array A contains the lower triangular* matrix, and the strictly upper triangular part of A is not* referenced. If DIAG = 'U', the diagonal elements of A are* also not referenced and are assumed to be 1.** LDA (input) INTEGER* The leading dimension of the array A. LDA >= max(1,N).** B (input) DOUBLE PRECISION array, dimension (LDB,NRHS)* The right hand side matrix B.** LDB (input) INTEGER* The leading dimension of the array B. LDB >= max(1,N).** X (input) DOUBLE PRECISION array, dimension (LDX,NRHS)* The solution matrix X.** LDX (input) INTEGER* The leading dimension of the array X. LDX >= max(1,N).** FERR (output) DOUBLE PRECISION array, dimension (NRHS)* The estimated forward error bound for each solution vector* X(j) (the j-th column of the solution matrix X).* If XTRUE is the true solution corresponding to X(j), FERR(j)* is an estimated upper bound for the magnitude of the largest* element in (X(j) - XTRUE) divided by the magnitude of the* largest element in X(j). The estimate is as reliable as* the estimate for RCOND, and is almost always a slight* overestimate of the true error.** BERR (output) DOUBLE PRECISION array, dimension (NRHS)* The componentwise relative backward error of each solution* vector X(j) (i.e., the smallest relative change in* any element of A or B that makes X(j) an exact solution).** WORK (workspace) DOUBLE PRECISION array, dimension (3*N)** IWORK (workspace) INTEGER array, dimension (N)** INFO (output) INTEGER* = 0: successful exit* < 0: if INFO = -i, the i-th argument had an illegal value** =====================================================================** .. Parameters ..DOUBLE PRECISION ZEROPARAMETER ( ZERO = 0.0D+0 )DOUBLE PRECISION ONEPARAMETER ( ONE = 1.0D+0 )* ..* .. Local Scalars ..LOGICAL NOTRAN, NOUNIT, UPPERCHARACTER TRANSTINTEGER I, J, K, KASE, NZDOUBLE PRECISION EPS, LSTRES, S, SAFE1, SAFE2, SAFMIN, XK* ..* .. External Subroutines ..EXTERNAL DAXPY, DCOPY, DLACON, DTRMV, DTRSV, XERBLA* ..* .. Intrinsic Functions ..INTRINSIC ABS, MAX* ..* .. External Functions ..LOGICAL LSAMEDOUBLE PRECISION DLAMCHEXTERNAL LSAME, DLAMCH* ..* .. Executable Statements ..** Test the input parameters.*INFO = 0UPPER = LSAME( UPLO, 'U' )NOTRAN = LSAME( TRANS, 'N' )NOUNIT = LSAME( DIAG, 'N' )*IF( .NOT.UPPER .AND. .NOT.LSAME( UPLO, 'L' ) ) THENINFO = -1ELSE IF( .NOT.NOTRAN .AND. .NOT.LSAME( TRANS, 'T' ) .AND. .NOT.$ LSAME( TRANS, 'C' ) ) THENINFO = -2ELSE IF( .NOT.NOUNIT .AND. .NOT.LSAME( DIAG, 'U' ) ) THENINFO = -3ELSE IF( N.LT.0 ) THENINFO = -4ELSE IF( NRHS.LT.0 ) THENINFO = -5ELSE IF( LDA.LT.MAX( 1, N ) ) THENINFO = -7ELSE IF( LDB.LT.MAX( 1, N ) ) THENINFO = -9ELSE IF( LDX.LT.MAX( 1, N ) ) THENINFO = -11END IFIF( INFO.NE.0 ) THENCALL XERBLA( 'DTRRFS', -INFO )RETURNEND IF** Quick return if possible*IF( N.EQ.0 .OR. NRHS.EQ.0 ) THENDO 10 J = 1, NRHSFERR( J ) = ZEROBERR( J ) = ZERO10 CONTINUERETURNEND IF*IF( NOTRAN ) THENTRANST = 'T'ELSETRANST = 'N'END IF** NZ = maximum number of nonzero elements in each row of A, plus 1*NZ = N + 1EPS = DLAMCH( 'Epsilon' )SAFMIN = DLAMCH( 'Safe minimum' )SAFE1 = NZ*SAFMINSAFE2 = SAFE1 / EPS** Do for each right hand side*DO 250 J = 1, NRHS** Compute residual R = B - op(A) * X,* where op(A) = A or A', depending on TRANS.*CALL DCOPY( N, X( 1, J ), 1, WORK( N+1 ), 1 )CALL DTRMV( UPLO, TRANS, DIAG, N, A, LDA, WORK( N+1 ), 1 )CALL DAXPY( N, -ONE, B( 1, J ), 1, WORK( N+1 ), 1 )** Compute componentwise relative backward error from formula** max(i) ( abs(R(i)) / ( abs(op(A))*abs(X) + abs(B) )(i) )** where abs(Z) is the componentwise absolute value of the matrix* or vector Z. If the i-th component of the denominator is less* than SAFE2, then SAFE1 is added to the i-th components of the* numerator and denominator before dividing.*DO 20 I = 1, NWORK( I ) = ABS( B( I, J ) )20 CONTINUE*IF( NOTRAN ) THEN** Compute abs(A)*abs(X) + abs(B).*IF( UPPER ) THENIF( NOUNIT ) THENDO 40 K = 1, NXK = ABS( X( K, J ) )DO 30 I = 1, KWORK( I ) = WORK( I ) + ABS( A( I, K ) )*XK30 CONTINUE40 CONTINUEELSEDO 60 K = 1, NXK = ABS( X( K, J ) )DO 50 I = 1, K - 1WORK( I ) = WORK( I ) + ABS( A( I, K ) )*XK50 CONTINUEWORK( K ) = WORK( K ) + XK60 CONTINUEEND IFELSEIF( NOUNIT ) THENDO 80 K = 1, NXK = ABS( X( K, J ) )DO 70 I = K, NWORK( I ) = WORK( I ) + ABS( A( I, K ) )*XK70 CONTINUE80 CONTINUEELSEDO 100 K = 1, NXK = ABS( X( K, J ) )DO 90 I = K + 1, NWORK( I ) = WORK( I ) + ABS( A( I, K ) )*XK90 CONTINUEWORK( K ) = WORK( K ) + XK100 CONTINUEEND IFEND IFELSE** Compute abs(A')*abs(X) + abs(B).*IF( UPPER ) THENIF( NOUNIT ) THENDO 120 K = 1, NS = ZERODO 110 I = 1, KS = S + ABS( A( I, K ) )*ABS( X( I, J ) )110 CONTINUEWORK( K ) = WORK( K ) + S120 CONTINUEELSEDO 140 K = 1, NS = ABS( X( K, J ) )DO 130 I = 1, K - 1S = S + ABS( A( I, K ) )*ABS( X( I, J ) )130 CONTINUEWORK( K ) = WORK( K ) + S140 CONTINUEEND IFELSEIF( NOUNIT ) THENDO 160 K = 1, NS = ZERODO 150 I = K, NS = S + ABS( A( I, K ) )*ABS( X( I, J ) )150 CONTINUEWORK( K ) = WORK( K ) + S160 CONTINUEELSEDO 180 K = 1, NS = ABS( X( K, J ) )DO 170 I = K + 1, NS = S + ABS( A( I, K ) )*ABS( X( I, J ) )170 CONTINUEWORK( K ) = WORK( K ) + S180 CONTINUEEND IFEND IFEND IFS = ZERODO 190 I = 1, NIF( WORK( I ).GT.SAFE2 ) THENS = MAX( S, ABS( WORK( N+I ) ) / WORK( I ) )ELSES = MAX( S, ( ABS( WORK( N+I ) )+SAFE1 ) /$ ( WORK( I )+SAFE1 ) )END IF190 CONTINUEBERR( J ) = S** Bound error from formula** norm(X - XTRUE) / norm(X) .le. FERR =* norm( abs(inv(op(A)))** ( abs(R) + NZ*EPS*( abs(op(A))*abs(X)+abs(B) ))) / norm(X)** where* norm(Z) is the magnitude of the largest component of Z* inv(op(A)) is the inverse of op(A)* abs(Z) is the componentwise absolute value of the matrix or* vector Z* NZ is the maximum number of nonzeros in any row of A, plus 1* EPS is machine epsilon** The i-th component of abs(R)+NZ*EPS*(abs(op(A))*abs(X)+abs(B))* is incremented by SAFE1 if the i-th component of* abs(op(A))*abs(X) + abs(B) is less than SAFE2.** Use DLACON to estimate the infinity-norm of the matrix* inv(op(A)) * diag(W),* where W = abs(R) + NZ*EPS*( abs(op(A))*abs(X)+abs(B) )))*DO 200 I = 1, NIF( WORK( I ).GT.SAFE2 ) THENWORK( I ) = ABS( WORK( N+I ) ) + NZ*EPS*WORK( I )ELSEWORK( I ) = ABS( WORK( N+I ) ) + NZ*EPS*WORK( I ) + SAFE1END IF200 CONTINUE*KASE = 0210 CONTINUECALL DLACON( N, WORK( 2*N+1 ), WORK( N+1 ), IWORK, FERR( J ),$ KASE )IF( KASE.NE.0 ) THENIF( KASE.EQ.1 ) THEN** Multiply by diag(W)*inv(op(A)').*CALL DTRSV( UPLO, TRANST, DIAG, N, A, LDA, WORK( N+1 ),$ 1 )DO 220 I = 1, NWORK( N+I ) = WORK( I )*WORK( N+I )220 CONTINUEELSE** Multiply by inv(op(A))*diag(W).*DO 230 I = 1, NWORK( N+I ) = WORK( I )*WORK( N+I )230 CONTINUECALL DTRSV( UPLO, TRANS, DIAG, N, A, LDA, WORK( N+1 ),$ 1 )END IFGO TO 210END IF** Normalize error.*LSTRES = ZERODO 240 I = 1, NLSTRES = MAX( LSTRES, ABS( X( I, J ) ) )240 CONTINUEIF( LSTRES.NE.ZERO )$ FERR( J ) = FERR( J ) / LSTRES*250 CONTINUE*RETURN** End of DTRRFS*ENDSUBROUTINE DTRSEN( JOB, COMPQ, SELECT, N, T, LDT, Q, LDQ, WR, WI,$ M, S, SEP, WORK, LWORK, IWORK, LIWORK, INFO )** -- LAPACK routine (version 3.0) --* Univ. of Tennessee, Univ. of California Berkeley, NAG Ltd.,* Courant Institute, Argonne National Lab, and Rice University* June 30, 1999** .. Scalar Arguments ..CHARACTER COMPQ, JOBINTEGER INFO, LDQ, LDT, LIWORK, LWORK, M, NDOUBLE PRECISION S, SEP* ..* .. Array Arguments ..LOGICAL SELECT( * )INTEGER IWORK( * )DOUBLE PRECISION Q( LDQ, * ), T( LDT, * ), WI( * ), WORK( * ),$ WR( * )* ..** Purpose* =======** DTRSEN reorders the real Schur factorization of a real matrix* A = Q*T*Q**T, so that a selected cluster of eigenvalues appears in* the leading diagonal blocks of the upper quasi-triangular matrix T,* and the leading columns of Q form an orthonormal basis of the* corresponding right invariant subspace.** Optionally the routine computes the reciprocal condition numbers of* the cluster of eigenvalues and/or the invariant subspace.** T must be in Schur canonical form (as returned by DHSEQR), that is,* block upper triangular with 1-by-1 and 2-by-2 diagonal blocks; each* 2-by-2 diagonal block has its diagonal elemnts equal and its* off-diagonal elements of opposite sign.** Arguments* =========** JOB (input) CHARACTER*1* Specifies whether condition numbers are required for the* cluster of eigenvalues (S) or the invariant subspace (SEP):* = 'N': none;* = 'E': for eigenvalues only (S);* = 'V': for invariant subspace only (SEP);* = 'B': for both eigenvalues and invariant subspace (S and* SEP).** COMPQ (input) CHARACTER*1* = 'V': update the matrix Q of Schur vectors;* = 'N': do not update Q.** SELECT (input) LOGICAL array, dimension (N)* SELECT specifies the eigenvalues in the selected cluster. To* select a real eigenvalue w(j), SELECT(j) must be set to* .TRUE.. To select a complex conjugate pair of eigenvalues* w(j) and w(j+1), corresponding to a 2-by-2 diagonal block,* either SELECT(j) or SELECT(j+1) or both must be set to* .TRUE.; a complex conjugate pair of eigenvalues must be* either both included in the cluster or both excluded.** N (input) INTEGER* The order of the matrix T. N >= 0.** T (input/output) DOUBLE PRECISION array, dimension (LDT,N)* On entry, the upper quasi-triangular matrix T, in Schur* canonical form.* On exit, T is overwritten by the reordered matrix T, again in* Schur canonical form, with the selected eigenvalues in the* leading diagonal blocks.** LDT (input) INTEGER* The leading dimension of the array T. LDT >= max(1,N).** Q (input/output) DOUBLE PRECISION array, dimension (LDQ,N)* On entry, if COMPQ = 'V', the matrix Q of Schur vectors.* On exit, if COMPQ = 'V', Q has been postmultiplied by the* orthogonal transformation matrix which reorders T; the* leading M columns of Q form an orthonormal basis for the* specified invariant subspace.* If COMPQ = 'N', Q is not referenced.** LDQ (input) INTEGER* The leading dimension of the array Q.* LDQ >= 1; and if COMPQ = 'V', LDQ >= N.** WR (output) DOUBLE PRECISION array, dimension (N)* WI (output) DOUBLE PRECISION array, dimension (N)* The real and imaginary parts, respectively, of the reordered* eigenvalues of T. The eigenvalues are stored in the same* order as on the diagonal of T, with WR(i) = T(i,i) and, if* T(i:i+1,i:i+1) is a 2-by-2 diagonal block, WI(i) > 0 and* WI(i+1) = -WI(i). Note that if a complex eigenvalue is* sufficiently ill-conditioned, then its value may differ* significantly from its value before reordering.** M (output) INTEGER* The dimension of the specified invariant subspace.* 0 < = M <= N.** S (output) DOUBLE PRECISION* If JOB = 'E' or 'B', S is a lower bound on the reciprocal* condition number for the selected cluster of eigenvalues.* S cannot underestimate the true reciprocal condition number* by more than a factor of sqrt(N). If M = 0 or N, S = 1.* If JOB = 'N' or 'V', S is not referenced.** SEP (output) DOUBLE PRECISION* If JOB = 'V' or 'B', SEP is the estimated reciprocal* condition number of the specified invariant subspace. If* M = 0 or N, SEP = norm(T).* If JOB = 'N' or 'E', SEP is not referenced.** WORK (workspace/output) 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 JOB = 'N', LWORK >= max(1,N);* if JOB = 'E', LWORK >= M*(N-M);* if JOB = 'V' or 'B', LWORK >= 2*M*(N-M).** If LWORK = -1, then a workspace query is assumed; the routine* only calculates the optimal size of the WORK array, returns* this value as the first entry of the WORK array, and no error* message related to LWORK is issued by XERBLA.** IWORK (workspace) INTEGER array, dimension (LIWORK)* IF JOB = 'N' or 'E', IWORK is not referenced.** LIWORK (input) INTEGER* The dimension of the array IWORK.* If JOB = 'N' or 'E', LIWORK >= 1;* if JOB = 'V' or 'B', LIWORK >= M*(N-M).** If LIWORK = -1, then a workspace query is assumed; the* routine only calculates the optimal size of the IWORK array,* returns this value as the first entry of the IWORK array, and* no error message related to LIWORK is issued by XERBLA.** INFO (output) INTEGER* = 0: successful exit* < 0: if INFO = -i, the i-th argument had an illegal value* = 1: reordering of T failed because some eigenvalues are too* close to separate (the problem is very ill-conditioned);* T may have been partially reordered, and WR and WI* contain the eigenvalues in the same order as in T; S and* SEP (if requested) are set to zero.** Further Details* ===============** DTRSEN first collects the selected eigenvalues by computing an* orthogonal transformation Z to move them to the top left corner of T.* In other words, the selected eigenvalues are the eigenvalues of T11* in:** Z'*T*Z = ( T11 T12 ) n1* ( 0 T22 ) n2* n1 n2** where N = n1+n2 and Z' means the transpose of Z. The first n1 columns* of Z span the specified invariant subspace of T.** If T has been obtained from the real Schur factorization of a matrix* A = Q*T*Q', then the reordered real Schur factorization of A is given* by A = (Q*Z)*(Z'*T*Z)*(Q*Z)', and the first n1 columns of Q*Z span* the corresponding invariant subspace of A.** The reciprocal condition number of the average of the eigenvalues of* T11 may be returned in S. S lies between 0 (very badly conditioned)* and 1 (very well conditioned). It is computed as follows. First we* compute R so that** P = ( I R ) n1* ( 0 0 ) n2* n1 n2** is the projector on the invariant subspace associated with T11.* R is the solution of the Sylvester equation:** T11*R - R*T22 = T12.** Let F-norm(M) denote the Frobenius-norm of M and 2-norm(M) denote* the two-norm of M. Then S is computed as the lower bound** (1 + F-norm(R)**2)**(-1/2)** on the reciprocal of 2-norm(P), the true reciprocal condition number.* S cannot underestimate 1 / 2-norm(P) by more than a factor of* sqrt(N).** An approximate error bound for the computed average of the* eigenvalues of T11 is** EPS * norm(T) / S** where EPS is the machine precision.** The reciprocal condition number of the right invariant subspace* spanned by the first n1 columns of Z (or of Q*Z) is returned in SEP.* SEP is defined as the separation of T11 and T22:** sep( T11, T22 ) = sigma-min( C )** where sigma-min(C) is the smallest singular value of the* n1*n2-by-n1*n2 matrix** C = kprod( I(n2), T11 ) - kprod( transpose(T22), I(n1) )** I(m) is an m by m identity matrix, and kprod denotes the Kronecker* product. We estimate sigma-min(C) by the reciprocal of an estimate of* the 1-norm of inverse(C). The true reciprocal 1-norm of inverse(C)* cannot differ from sigma-min(C) by more than a factor of sqrt(n1*n2).** When SEP is small, small changes in T can cause large changes in* the invariant subspace. An approximate bound on the maximum angular* error in the computed right invariant subspace is** EPS * norm(T) / SEP** =====================================================================** .. Parameters ..DOUBLE PRECISION ZERO, ONEPARAMETER ( ZERO = 0.0D+0, ONE = 1.0D+0 )* ..* .. Local Scalars ..LOGICAL LQUERY, PAIR, SWAP, WANTBH, WANTQ, WANTS,$ WANTSPINTEGER IERR, K, KASE, KK, KS, LIWMIN, LWMIN, N1, N2,$ NNDOUBLE PRECISION EST, RNORM, SCALE* ..* .. External Functions ..LOGICAL LSAMEDOUBLE PRECISION DLANGEEXTERNAL LSAME, DLANGE* ..* .. External Subroutines ..EXTERNAL DLACON, DLACPY, DTREXC, DTRSYL, XERBLA* ..* .. Intrinsic Functions ..INTRINSIC ABS, MAX, SQRT* ..* .. Executable Statements ..** Decode and test the input parameters*WANTBH = LSAME( JOB, 'B' )WANTS = LSAME( JOB, 'E' ) .OR. WANTBHWANTSP = LSAME( JOB, 'V' ) .OR. WANTBHWANTQ = LSAME( COMPQ, 'V' )*INFO = 0LQUERY = ( LWORK.EQ.-1 )IF( .NOT.LSAME( JOB, 'N' ) .AND. .NOT.WANTS .AND. .NOT.WANTSP )$ THENINFO = -1ELSE IF( .NOT.LSAME( COMPQ, 'N' ) .AND. .NOT.WANTQ ) THENINFO = -2ELSE IF( N.LT.0 ) THENINFO = -4ELSE IF( LDT.LT.MAX( 1, N ) ) THENINFO = -6ELSE IF( LDQ.LT.1 .OR. ( WANTQ .AND. LDQ.LT.N ) ) THENINFO = -8ELSE** Set M to the dimension of the specified invariant subspace,* and test LWORK and LIWORK.*M = 0PAIR = .FALSE.DO 10 K = 1, NIF( PAIR ) THENPAIR = .FALSE.ELSEIF( K.LT.N ) THENIF( T( K+1, K ).EQ.ZERO ) THENIF( SELECT( K ) )$ M = M + 1ELSEPAIR = .TRUE.IF( SELECT( K ) .OR. SELECT( K+1 ) )$ M = M + 2END IFELSEIF( SELECT( N ) )$ M = M + 1END IFEND IF10 CONTINUE*N1 = MN2 = N - MNN = N1*N2*IF( WANTSP ) THENLWMIN = MAX( 1, 2*NN )LIWMIN = MAX( 1, NN )ELSE IF( LSAME( JOB, 'N' ) ) THENLWMIN = MAX( 1, N )LIWMIN = 1ELSE IF( LSAME( JOB, 'E' ) ) THENLWMIN = MAX( 1, NN )LIWMIN = 1END IF*IF( LWORK.LT.LWMIN .AND. .NOT.LQUERY ) THENINFO = -15ELSE IF( LIWORK.LT.LIWMIN .AND. .NOT.LQUERY ) THENINFO = -17END IFEND IF*IF( INFO.EQ.0 ) THENWORK( 1 ) = LWMINIWORK( 1 ) = LIWMINEND IF*IF( INFO.NE.0 ) THENCALL XERBLA( 'DTRSEN', -INFO )RETURNELSE IF( LQUERY ) THENRETURNEND IF** Quick return if possible.*IF( M.EQ.N .OR. M.EQ.0 ) THENIF( WANTS )$ S = ONEIF( WANTSP )$ SEP = DLANGE( '1', N, N, T, LDT, WORK )GO TO 40END IF** Collect the selected blocks at the top-left corner of T.*KS = 0PAIR = .FALSE.DO 20 K = 1, NIF( PAIR ) THENPAIR = .FALSE.ELSESWAP = SELECT( K )IF( K.LT.N ) THENIF( T( K+1, K ).NE.ZERO ) THENPAIR = .TRUE.SWAP = SWAP .OR. SELECT( K+1 )END IFEND IFIF( SWAP ) THENKS = KS + 1** Swap the K-th block to position KS.*IERR = 0KK = KIF( K.NE.KS )$ CALL DTREXC( COMPQ, N, T, LDT, Q, LDQ, KK, KS, WORK,$ IERR )IF( IERR.EQ.1 .OR. IERR.EQ.2 ) THEN** Blocks too close to swap: exit.*INFO = 1IF( WANTS )$ S = ZEROIF( WANTSP )$ SEP = ZEROGO TO 40END IFIF( PAIR )$ KS = KS + 1END IFEND IF20 CONTINUE*IF( WANTS ) THEN** Solve Sylvester equation for R:** T11*R - R*T22 = scale*T12*CALL DLACPY( 'F', N1, N2, T( 1, N1+1 ), LDT, WORK, N1 )CALL DTRSYL( 'N', 'N', -1, N1, N2, T, LDT, T( N1+1, N1+1 ),$ LDT, WORK, N1, SCALE, IERR )** Estimate the reciprocal of the condition number of the cluster* of eigenvalues.*RNORM = DLANGE( 'F', N1, N2, WORK, N1, WORK )IF( RNORM.EQ.ZERO ) THENS = ONEELSES = SCALE / ( SQRT( SCALE*SCALE / RNORM+RNORM )*$ SQRT( RNORM ) )END IFEND IF*IF( WANTSP ) THEN** Estimate sep(T11,T22).*EST = ZEROKASE = 030 CONTINUECALL DLACON( NN, WORK( NN+1 ), WORK, IWORK, EST, KASE )IF( KASE.NE.0 ) THENIF( KASE.EQ.1 ) THEN** Solve T11*R - R*T22 = scale*X.*CALL DTRSYL( 'N', 'N', -1, N1, N2, T, LDT,$ T( N1+1, N1+1 ), LDT, WORK, N1, SCALE,$ IERR )ELSE** Solve T11'*R - R*T22' = scale*X.*CALL DTRSYL( 'T', 'T', -1, N1, N2, T, LDT,$ T( N1+1, N1+1 ), LDT, WORK, N1, SCALE,$ IERR )END IFGO TO 30END IF*SEP = SCALE / ESTEND IF*40 CONTINUE** Store the output eigenvalues in WR and WI.*DO 50 K = 1, NWR( K ) = T( K, K )WI( K ) = ZERO50 CONTINUEDO 60 K = 1, N - 1IF( T( K+1, K ).NE.ZERO ) THENWI( K ) = SQRT( ABS( T( K, K+1 ) ) )*$ SQRT( ABS( T( K+1, K ) ) )WI( K+1 ) = -WI( K )END IF60 CONTINUE*WORK( 1 ) = LWMINIWORK( 1 ) = LIWMIN*RETURN** End of DTRSEN*ENDSUBROUTINE DTRSNA( JOB, HOWMNY, SELECT, N, T, LDT, VL, LDVL, VR,$ LDVR, S, SEP, MM, M, WORK, LDWORK, IWORK,$ INFO )** -- LAPACK routine (version 3.0) --* Univ. of Tennessee, Univ. of California Berkeley, NAG Ltd.,* Courant Institute, Argonne National Lab, and Rice University* September 30, 1994** .. Scalar Arguments ..CHARACTER HOWMNY, JOBINTEGER INFO, LDT, LDVL, LDVR, LDWORK, M, MM, N* ..* .. Array Arguments ..LOGICAL SELECT( * )INTEGER IWORK( * )DOUBLE PRECISION S( * ), SEP( * ), T( LDT, * ), VL( LDVL, * ),$ VR( LDVR, * ), WORK( LDWORK, * )* ..** Purpose* =======** DTRSNA estimates reciprocal condition numbers for specified* eigenvalues and/or right eigenvectors of a real upper* quasi-triangular matrix T (or of any matrix Q*T*Q**T with Q* orthogonal).** T must be in Schur canonical form (as returned by DHSEQR), that is,* block upper triangular with 1-by-1 and 2-by-2 diagonal blocks; each* 2-by-2 diagonal block has its diagonal elements equal and its* off-diagonal elements of opposite sign.** Arguments* =========** JOB (input) CHARACTER*1* Specifies whether condition numbers are required for* eigenvalues (S) or eigenvectors (SEP):* = 'E': for eigenvalues only (S);* = 'V': for eigenvectors only (SEP);* = 'B': for both eigenvalues and eigenvectors (S and SEP).** HOWMNY (input) CHARACTER*1* = 'A': compute condition numbers for all eigenpairs;* = 'S': compute condition numbers for selected eigenpairs* specified by the array SELECT.** SELECT (input) LOGICAL array, dimension (N)* If HOWMNY = 'S', SELECT specifies the eigenpairs for which* condition numbers are required. To select condition numbers* for the eigenpair corresponding to a real eigenvalue w(j),* SELECT(j) must be set to .TRUE.. To select condition numbers* corresponding to a complex conjugate pair of eigenvalues w(j)* and w(j+1), either SELECT(j) or SELECT(j+1) or both, must be* set to .TRUE..* If HOWMNY = 'A', SELECT is not referenced.** N (input) INTEGER* The order of the matrix T. N >= 0.** T (input) DOUBLE PRECISION array, dimension (LDT,N)* The upper quasi-triangular matrix T, in Schur canonical form.** LDT (input) INTEGER* The leading dimension of the array T. LDT >= max(1,N).** VL (input) DOUBLE PRECISION array, dimension (LDVL,M)* If JOB = 'E' or 'B', VL must contain left eigenvectors of T* (or of any Q*T*Q**T with Q orthogonal), corresponding to the* eigenpairs specified by HOWMNY and SELECT. The eigenvectors* must be stored in consecutive columns of VL, as returned by* DHSEIN or DTREVC.* If JOB = 'V', VL is not referenced.** LDVL (input) INTEGER* The leading dimension of the array VL.* LDVL >= 1; and if JOB = 'E' or 'B', LDVL >= N.** VR (input) DOUBLE PRECISION array, dimension (LDVR,M)* If JOB = 'E' or 'B', VR must contain right eigenvectors of T* (or of any Q*T*Q**T with Q orthogonal), corresponding to the* eigenpairs specified by HOWMNY and SELECT. The eigenvectors* must be stored in consecutive columns of VR, as returned by* DHSEIN or DTREVC.* If JOB = 'V', VR is not referenced.** LDVR (input) INTEGER* The leading dimension of the array VR.* LDVR >= 1; and if JOB = 'E' or 'B', LDVR >= N.** S (output) DOUBLE PRECISION array, dimension (MM)* If JOB = 'E' or 'B', the reciprocal condition numbers of the* selected eigenvalues, stored in consecutive elements of the* array. For a complex conjugate pair of eigenvalues two* consecutive elements of S are set to the same value. Thus* S(j), SEP(j), and the j-th columns of VL and VR all* correspond to the same eigenpair (but not in general the* j-th eigenpair, unless all eigenpairs are selected).* If JOB = 'V', S is not referenced.** SEP (output) DOUBLE PRECISION array, dimension (MM)* If JOB = 'V' or 'B', the estimated reciprocal condition* numbers of the selected eigenvectors, stored in consecutive* elements of the array. For a complex eigenvector two* consecutive elements of SEP are set to the same value. If* the eigenvalues cannot be reordered to compute SEP(j), SEP(j)* is set to 0; this can only occur when the true value would be* very small anyway.* If JOB = 'E', SEP is not referenced.** MM (input) INTEGER* The number of elements in the arrays S (if JOB = 'E' or 'B')* and/or SEP (if JOB = 'V' or 'B'). MM >= M.** M (output) INTEGER* The number of elements of the arrays S and/or SEP actually* used to store the estimated condition numbers.* If HOWMNY = 'A', M is set to N.** WORK (workspace) DOUBLE PRECISION array, dimension (LDWORK,N+1)* If JOB = 'E', WORK is not referenced.** LDWORK (input) INTEGER* The leading dimension of the array WORK.* LDWORK >= 1; and if JOB = 'V' or 'B', LDWORK >= N.** IWORK (workspace) INTEGER array, dimension (N)* If JOB = 'E', IWORK is not referenced.** INFO (output) INTEGER* = 0: successful exit* < 0: if INFO = -i, the i-th argument had an illegal value** Further Details* ===============** The reciprocal of the condition number of an eigenvalue lambda is* defined as** S(lambda) = |v'*u| / (norm(u)*norm(v))** where u and v are the right and left eigenvectors of T corresponding* to lambda; v' denotes the conjugate-transpose of v, and norm(u)* denotes the Euclidean norm. These reciprocal condition numbers always* lie between zero (very badly conditioned) and one (very well* conditioned). If n = 1, S(lambda) is defined to be 1.** An approximate error bound for a computed eigenvalue W(i) is given by** EPS * norm(T) / S(i)** where EPS is the machine precision.** The reciprocal of the condition number of the right eigenvector u* corresponding to lambda is defined as follows. Suppose** T = ( lambda c )* ( 0 T22 )** Then the reciprocal condition number is** SEP( lambda, T22 ) = sigma-min( T22 - lambda*I )** where sigma-min denotes the smallest singular value. We approximate* the smallest singular value by the reciprocal of an estimate of the* one-norm of the inverse of T22 - lambda*I. If n = 1, SEP(1) is* defined to be abs(T(1,1)).** An approximate error bound for a computed right eigenvector VR(i)* is given by** EPS * norm(T) / SEP(i)** =====================================================================** .. Parameters ..DOUBLE PRECISION ZERO, ONE, TWOPARAMETER ( ZERO = 0.0D+0, ONE = 1.0D+0, TWO = 2.0D+0 )* ..* .. Local Scalars ..LOGICAL PAIR, SOMCON, WANTBH, WANTS, WANTSPINTEGER I, IERR, IFST, ILST, J, K, KASE, KS, N2, NNDOUBLE PRECISION BIGNUM, COND, CS, DELTA, DUMM, EPS, EST, LNRM,$ MU, PROD, PROD1, PROD2, RNRM, SCALE, SMLNUM, SN* ..* .. Local Arrays ..DOUBLE PRECISION DUMMY( 1 )* ..* .. External Functions ..LOGICAL LSAMEDOUBLE PRECISION DDOT, DLAMCH, DLAPY2, DNRM2EXTERNAL LSAME, DDOT, DLAMCH, DLAPY2, DNRM2* ..* .. External Subroutines ..EXTERNAL DLACON, DLACPY, DLAQTR, DTREXC, XERBLA* ..* .. Intrinsic Functions ..INTRINSIC ABS, MAX, SQRT* ..* .. Executable Statements ..** Decode and test the input parameters*WANTBH = LSAME( JOB, 'B' )WANTS = LSAME( JOB, 'E' ) .OR. WANTBHWANTSP = LSAME( JOB, 'V' ) .OR. WANTBH*SOMCON = LSAME( HOWMNY, 'S' )*INFO = 0IF( .NOT.WANTS .AND. .NOT.WANTSP ) THENINFO = -1ELSE IF( .NOT.LSAME( HOWMNY, 'A' ) .AND. .NOT.SOMCON ) THENINFO = -2ELSE IF( N.LT.0 ) THENINFO = -4ELSE IF( LDT.LT.MAX( 1, N ) ) THENINFO = -6ELSE IF( LDVL.LT.1 .OR. ( WANTS .AND. LDVL.LT.N ) ) THENINFO = -8ELSE IF( LDVR.LT.1 .OR. ( WANTS .AND. LDVR.LT.N ) ) THENINFO = -10ELSE** Set M to the number of eigenpairs for which condition numbers* are required, and test MM.*IF( SOMCON ) THENM = 0PAIR = .FALSE.DO 10 K = 1, NIF( PAIR ) THENPAIR = .FALSE.ELSEIF( K.LT.N ) THENIF( T( K+1, K ).EQ.ZERO ) THENIF( SELECT( K ) )$ M = M + 1ELSEPAIR = .TRUE.IF( SELECT( K ) .OR. SELECT( K+1 ) )$ M = M + 2END IFELSEIF( SELECT( N ) )$ M = M + 1END IFEND IF10 CONTINUEELSEM = NEND IF*IF( MM.LT.M ) THENINFO = -13ELSE IF( LDWORK.LT.1 .OR. ( WANTSP .AND. LDWORK.LT.N ) ) THENINFO = -16END IFEND IFIF( INFO.NE.0 ) THENCALL XERBLA( 'DTRSNA', -INFO )RETURNEND IF** Quick return if possible*IF( N.EQ.0 )$ RETURN*IF( N.EQ.1 ) THENIF( SOMCON ) THENIF( .NOT.SELECT( 1 ) )$ RETURNEND IFIF( WANTS )$ S( 1 ) = ONEIF( WANTSP )$ SEP( 1 ) = ABS( T( 1, 1 ) )RETURNEND IF** Get machine constants*EPS = DLAMCH( 'P' )SMLNUM = DLAMCH( 'S' ) / EPSBIGNUM = ONE / SMLNUMCALL DLABAD( SMLNUM, BIGNUM )*KS = 0PAIR = .FALSE.DO 60 K = 1, N** Determine whether T(k,k) begins a 1-by-1 or 2-by-2 block.*IF( PAIR ) THENPAIR = .FALSE.GO TO 60ELSEIF( K.LT.N )$ PAIR = T( K+1, K ).NE.ZEROEND IF** Determine whether condition numbers are required for the k-th* eigenpair.*IF( SOMCON ) THENIF( PAIR ) THENIF( .NOT.SELECT( K ) .AND. .NOT.SELECT( K+1 ) )$ GO TO 60ELSEIF( .NOT.SELECT( K ) )$ GO TO 60END IFEND IF*KS = KS + 1*IF( WANTS ) THEN** Compute the reciprocal condition number of the k-th* eigenvalue.*IF( .NOT.PAIR ) THEN** Real eigenvalue.*PROD = DDOT( N, VR( 1, KS ), 1, VL( 1, KS ), 1 )RNRM = DNRM2( N, VR( 1, KS ), 1 )LNRM = DNRM2( N, VL( 1, KS ), 1 )S( KS ) = ABS( PROD ) / ( RNRM*LNRM )ELSE** Complex eigenvalue.*PROD1 = DDOT( N, VR( 1, KS ), 1, VL( 1, KS ), 1 )PROD1 = PROD1 + DDOT( N, VR( 1, KS+1 ), 1, VL( 1, KS+1 ),$ 1 )PROD2 = DDOT( N, VL( 1, KS ), 1, VR( 1, KS+1 ), 1 )PROD2 = PROD2 - DDOT( N, VL( 1, KS+1 ), 1, VR( 1, KS ),$ 1 )RNRM = DLAPY2( DNRM2( N, VR( 1, KS ), 1 ),$ DNRM2( N, VR( 1, KS+1 ), 1 ) )LNRM = DLAPY2( DNRM2( N, VL( 1, KS ), 1 ),$ DNRM2( N, VL( 1, KS+1 ), 1 ) )COND = DLAPY2( PROD1, PROD2 ) / ( RNRM*LNRM )S( KS ) = CONDS( KS+1 ) = CONDEND IFEND IF*IF( WANTSP ) THEN** Estimate the reciprocal condition number of the k-th* eigenvector.** Copy the matrix T to the array WORK and swap the diagonal* block beginning at T(k,k) to the (1,1) position.*CALL DLACPY( 'Full', N, N, T, LDT, WORK, LDWORK )IFST = KILST = 1CALL DTREXC( 'No Q', N, WORK, LDWORK, DUMMY, 1, IFST, ILST,$ WORK( 1, N+1 ), IERR )*IF( IERR.EQ.1 .OR. IERR.EQ.2 ) THEN** Could not swap because blocks not well separated*SCALE = ONEEST = BIGNUMELSE** Reordering successful*IF( WORK( 2, 1 ).EQ.ZERO ) THEN** Form C = T22 - lambda*I in WORK(2:N,2:N).*DO 20 I = 2, NWORK( I, I ) = WORK( I, I ) - WORK( 1, 1 )20 CONTINUEN2 = 1NN = N - 1ELSE** Triangularize the 2 by 2 block by unitary* transformation U = [ cs i*ss ]* [ i*ss cs ].* such that the (1,1) position of WORK is complex* eigenvalue lambda with positive imaginary part. (2,2)* position of WORK is the complex eigenvalue lambda* with negative imaginary part.*MU = SQRT( ABS( WORK( 1, 2 ) ) )*$ SQRT( ABS( WORK( 2, 1 ) ) )DELTA = DLAPY2( MU, WORK( 2, 1 ) )CS = MU / DELTASN = -WORK( 2, 1 ) / DELTA** Form** C' = WORK(2:N,2:N) + i*[rwork(1) ..... rwork(n-1) ]* [ mu ]* [ .. ]* [ .. ]* [ mu ]* where C' is conjugate transpose of complex matrix C,* and RWORK is stored starting in the N+1-st column of* WORK.*DO 30 J = 3, NWORK( 2, J ) = CS*WORK( 2, J )WORK( J, J ) = WORK( J, J ) - WORK( 1, 1 )30 CONTINUEWORK( 2, 2 ) = ZERO*WORK( 1, N+1 ) = TWO*MUDO 40 I = 2, N - 1WORK( I, N+1 ) = SN*WORK( 1, I+1 )40 CONTINUEN2 = 2NN = 2*( N-1 )END IF** Estimate norm(inv(C'))*EST = ZEROKASE = 050 CONTINUECALL DLACON( NN, WORK( 1, N+2 ), WORK( 1, N+4 ), IWORK,$ EST, KASE )IF( KASE.NE.0 ) THENIF( KASE.EQ.1 ) THENIF( N2.EQ.1 ) THEN** Real eigenvalue: solve C'*x = scale*c.*CALL DLAQTR( .TRUE., .TRUE., N-1, WORK( 2, 2 ),$ LDWORK, DUMMY, DUMM, SCALE,$ WORK( 1, N+4 ), WORK( 1, N+6 ),$ IERR )ELSE** Complex eigenvalue: solve* C'*(p+iq) = scale*(c+id) in real arithmetic.*CALL DLAQTR( .TRUE., .FALSE., N-1, WORK( 2, 2 ),$ LDWORK, WORK( 1, N+1 ), MU, SCALE,$ WORK( 1, N+4 ), WORK( 1, N+6 ),$ IERR )END IFELSEIF( N2.EQ.1 ) THEN** Real eigenvalue: solve C*x = scale*c.*CALL DLAQTR( .FALSE., .TRUE., N-1, WORK( 2, 2 ),$ LDWORK, DUMMY, DUMM, SCALE,$ WORK( 1, N+4 ), WORK( 1, N+6 ),$ IERR )ELSE** Complex eigenvalue: solve* C*(p+iq) = scale*(c+id) in real arithmetic.*CALL DLAQTR( .FALSE., .FALSE., N-1,$ WORK( 2, 2 ), LDWORK,$ WORK( 1, N+1 ), MU, SCALE,$ WORK( 1, N+4 ), WORK( 1, N+6 ),$ IERR )*END IFEND IF*GO TO 50END IFEND IF*SEP( KS ) = SCALE / MAX( EST, SMLNUM )IF( PAIR )$ SEP( KS+1 ) = SEP( KS )END IF*IF( PAIR )$ KS = KS + 1*60 CONTINUERETURN** End of DTRSNA*ENDSUBROUTINE DTRSYL( TRANA, TRANB, ISGN, M, N, A, LDA, B, LDB, C,$ LDC, SCALE, INFO )** -- LAPACK routine (version 3.0) --* Univ. of Tennessee, Univ. of California Berkeley, NAG Ltd.,* Courant Institute, Argonne National Lab, and Rice University* March 31, 1993** .. Scalar Arguments ..CHARACTER TRANA, TRANBINTEGER INFO, ISGN, LDA, LDB, LDC, M, NDOUBLE PRECISION SCALE* ..* .. Array Arguments ..DOUBLE PRECISION A( LDA, * ), B( LDB, * ), C( LDC, * )* ..** Purpose* =======** DTRSYL solves the real Sylvester matrix equation:** op(A)*X + X*op(B) = scale*C or* op(A)*X - X*op(B) = scale*C,** where op(A) = A or A**T, and A and B are both upper quasi-* triangular. A is M-by-M and B is N-by-N; the right hand side C and* the solution X are M-by-N; and scale is an output scale factor, set* <= 1 to avoid overflow in X.** A and B must be in Schur canonical form (as returned by DHSEQR), that* is, block upper triangular with 1-by-1 and 2-by-2 diagonal blocks;* each 2-by-2 diagonal block has its diagonal elements equal and its* off-diagonal elements of opposite sign.** Arguments* =========** TRANA (input) CHARACTER*1* Specifies the option op(A):* = 'N': op(A) = A (No transpose)* = 'T': op(A) = A**T (Transpose)* = 'C': op(A) = A**H (Conjugate transpose = Transpose)** TRANB (input) CHARACTER*1* Specifies the option op(B):* = 'N': op(B) = B (No transpose)* = 'T': op(B) = B**T (Transpose)* = 'C': op(B) = B**H (Conjugate transpose = Transpose)** ISGN (input) INTEGER* Specifies the sign in the equation:* = +1: solve op(A)*X + X*op(B) = scale*C* = -1: solve op(A)*X - X*op(B) = scale*C** M (input) INTEGER* The order of the matrix A, and the number of rows in the* matrices X and C. M >= 0.** N (input) INTEGER* The order of the matrix B, and the number of columns in the* matrices X and C. N >= 0.** A (input) DOUBLE PRECISION array, dimension (LDA,M)* The upper quasi-triangular matrix A, in Schur canonical form.** LDA (input) INTEGER* The leading dimension of the array A. LDA >= max(1,M).** B (input) DOUBLE PRECISION array, dimension (LDB,N)* The upper quasi-triangular matrix B, in Schur canonical form.** LDB (input) INTEGER* The leading dimension of the array B. LDB >= max(1,N).** C (input/output) DOUBLE PRECISION array, dimension (LDC,N)* On entry, the M-by-N right hand side matrix C.* On exit, C is overwritten by the solution matrix X.** LDC (input) INTEGER* The leading dimension of the array C. LDC >= max(1,M)** SCALE (output) DOUBLE PRECISION* The scale factor, scale, set <= 1 to avoid overflow in X.** INFO (output) INTEGER* = 0: successful exit* < 0: if INFO = -i, the i-th argument had an illegal value* = 1: A and B have common or very close eigenvalues; perturbed* values were used to solve the equation (but the matrices* A and B are unchanged).** =====================================================================** .. Parameters ..DOUBLE PRECISION ZERO, ONEPARAMETER ( ZERO = 0.0D+0, ONE = 1.0D+0 )* ..* .. Local Scalars ..LOGICAL NOTRNA, NOTRNBINTEGER IERR, J, K, K1, K2, KNEXT, L, L1, L2, LNEXTDOUBLE PRECISION A11, BIGNUM, DA11, DB, EPS, SCALOC, SGN, SMIN,$ SMLNUM, SUML, SUMR, XNORM* ..* .. Local Arrays ..DOUBLE PRECISION DUM( 1 ), VEC( 2, 2 ), X( 2, 2 )* ..* .. External Functions ..LOGICAL LSAMEDOUBLE PRECISION DDOT, DLAMCH, DLANGEEXTERNAL LSAME, DDOT, DLAMCH, DLANGE* ..* .. External Subroutines ..EXTERNAL DLALN2, DLASY2, DSCAL, XERBLA* ..* .. Intrinsic Functions ..INTRINSIC ABS, DBLE, MAX, MIN* ..* .. Executable Statements ..** Decode and Test input parameters*NOTRNA = LSAME( TRANA, 'N' )NOTRNB = LSAME( TRANB, 'N' )*INFO = 0IF( .NOT.NOTRNA .AND. .NOT.LSAME( TRANA, 'T' ) .AND. .NOT.$ LSAME( TRANA, 'C' ) ) THENINFO = -1ELSE IF( .NOT.NOTRNB .AND. .NOT.LSAME( TRANB, 'T' ) .AND. .NOT.$ LSAME( TRANB, 'C' ) ) THENINFO = -2ELSE IF( ISGN.NE.1 .AND. ISGN.NE.-1 ) THENINFO = -3ELSE IF( M.LT.0 ) THENINFO = -4ELSE IF( N.LT.0 ) THENINFO = -5ELSE IF( LDA.LT.MAX( 1, M ) ) THENINFO = -7ELSE IF( LDB.LT.MAX( 1, N ) ) THENINFO = -9ELSE IF( LDC.LT.MAX( 1, M ) ) THENINFO = -11END IFIF( INFO.NE.0 ) THENCALL XERBLA( 'DTRSYL', -INFO )RETURNEND IF** Quick return if possible*IF( M.EQ.0 .OR. N.EQ.0 )$ RETURN** Set constants to control overflow*EPS = DLAMCH( 'P' )SMLNUM = DLAMCH( 'S' )BIGNUM = ONE / SMLNUMCALL DLABAD( SMLNUM, BIGNUM )SMLNUM = SMLNUM*DBLE( M*N ) / EPSBIGNUM = ONE / SMLNUM*SMIN = MAX( SMLNUM, EPS*DLANGE( 'M', M, M, A, LDA, DUM ),$ EPS*DLANGE( 'M', N, N, B, LDB, DUM ) )*SCALE = ONESGN = ISGN*IF( NOTRNA .AND. NOTRNB ) THEN** Solve A*X + ISGN*X*B = scale*C.** The (K,L)th block of X is determined starting from* bottom-left corner column by column by** A(K,K)*X(K,L) + ISGN*X(K,L)*B(L,L) = C(K,L) - R(K,L)** Where* M L-1* R(K,L) = SUM [A(K,I)*X(I,L)] + ISGN*SUM [X(K,J)*B(J,L)].* I=K+1 J=1** Start column loop (index = L)* L1 (L2) : column index of the first (first) row of X(K,L).*LNEXT = 1DO 60 L = 1, NIF( L.LT.LNEXT )$ GO TO 60IF( L.EQ.N ) THENL1 = LL2 = LELSEIF( B( L+1, L ).NE.ZERO ) THENL1 = LL2 = L + 1LNEXT = L + 2ELSEL1 = LL2 = LLNEXT = L + 1END IFEND IF** Start row loop (index = K)* K1 (K2): row index of the first (last) row of X(K,L).*KNEXT = MDO 50 K = M, 1, -1IF( K.GT.KNEXT )$ GO TO 50IF( K.EQ.1 ) THENK1 = KK2 = KELSEIF( A( K, K-1 ).NE.ZERO ) THENK1 = K - 1K2 = KKNEXT = K - 2ELSEK1 = KK2 = KKNEXT = K - 1END IFEND IF*IF( L1.EQ.L2 .AND. K1.EQ.K2 ) THENSUML = DDOT( M-K1, A( K1, MIN( K1+1, M ) ), LDA,$ C( MIN( K1+1, M ), L1 ), 1 )SUMR = DDOT( L1-1, C( K1, 1 ), LDC, B( 1, L1 ), 1 )VEC( 1, 1 ) = C( K1, L1 ) - ( SUML+SGN*SUMR )SCALOC = ONE*A11 = A( K1, K1 ) + SGN*B( L1, L1 )DA11 = ABS( A11 )IF( DA11.LE.SMIN ) THENA11 = SMINDA11 = SMININFO = 1END IFDB = ABS( VEC( 1, 1 ) )IF( DA11.LT.ONE .AND. DB.GT.ONE ) THENIF( DB.GT.BIGNUM*DA11 )$ SCALOC = ONE / DBEND IFX( 1, 1 ) = ( VEC( 1, 1 )*SCALOC ) / A11*IF( SCALOC.NE.ONE ) THENDO 10 J = 1, NCALL DSCAL( M, SCALOC, C( 1, J ), 1 )10 CONTINUESCALE = SCALE*SCALOCEND IFC( K1, L1 ) = X( 1, 1 )*ELSE IF( L1.EQ.L2 .AND. K1.NE.K2 ) THEN*SUML = DDOT( M-K2, A( K1, MIN( K2+1, M ) ), LDA,$ C( MIN( K2+1, M ), L1 ), 1 )SUMR = DDOT( L1-1, C( K1, 1 ), LDC, B( 1, L1 ), 1 )VEC( 1, 1 ) = C( K1, L1 ) - ( SUML+SGN*SUMR )*SUML = DDOT( M-K2, A( K2, MIN( K2+1, M ) ), LDA,$ C( MIN( K2+1, M ), L1 ), 1 )SUMR = DDOT( L1-1, C( K2, 1 ), LDC, B( 1, L1 ), 1 )VEC( 2, 1 ) = C( K2, L1 ) - ( SUML+SGN*SUMR )*CALL DLALN2( .FALSE., 2, 1, SMIN, ONE, A( K1, K1 ),$ LDA, ONE, ONE, VEC, 2, -SGN*B( L1, L1 ),$ ZERO, X, 2, SCALOC, XNORM, IERR )IF( IERR.NE.0 )$ INFO = 1*IF( SCALOC.NE.ONE ) THENDO 20 J = 1, NCALL DSCAL( M, SCALOC, C( 1, J ), 1 )20 CONTINUESCALE = SCALE*SCALOCEND IFC( K1, L1 ) = X( 1, 1 )C( K2, L1 ) = X( 2, 1 )*ELSE IF( L1.NE.L2 .AND. K1.EQ.K2 ) THEN*SUML = DDOT( M-K1, A( K1, MIN( K1+1, M ) ), LDA,$ C( MIN( K1+1, M ), L1 ), 1 )SUMR = DDOT( L1-1, C( K1, 1 ), LDC, B( 1, L1 ), 1 )VEC( 1, 1 ) = SGN*( C( K1, L1 )-( SUML+SGN*SUMR ) )*SUML = DDOT( M-K1, A( K1, MIN( K1+1, M ) ), LDA,$ C( MIN( K1+1, M ), L2 ), 1 )SUMR = DDOT( L1-1, C( K1, 1 ), LDC, B( 1, L2 ), 1 )VEC( 2, 1 ) = SGN*( C( K1, L2 )-( SUML+SGN*SUMR ) )*CALL DLALN2( .TRUE., 2, 1, SMIN, ONE, B( L1, L1 ),$ LDB, ONE, ONE, VEC, 2, -SGN*A( K1, K1 ),$ ZERO, X, 2, SCALOC, XNORM, IERR )IF( IERR.NE.0 )$ INFO = 1*IF( SCALOC.NE.ONE ) THENDO 30 J = 1, NCALL DSCAL( M, SCALOC, C( 1, J ), 1 )30 CONTINUESCALE = SCALE*SCALOCEND IFC( K1, L1 ) = X( 1, 1 )C( K1, L2 ) = X( 2, 1 )*ELSE IF( L1.NE.L2 .AND. K1.NE.K2 ) THEN*SUML = DDOT( M-K2, A( K1, MIN( K2+1, M ) ), LDA,$ C( MIN( K2+1, M ), L1 ), 1 )SUMR = DDOT( L1-1, C( K1, 1 ), LDC, B( 1, L1 ), 1 )VEC( 1, 1 ) = C( K1, L1 ) - ( SUML+SGN*SUMR )*SUML = DDOT( M-K2, A( K1, MIN( K2+1, M ) ), LDA,$ C( MIN( K2+1, M ), L2 ), 1 )SUMR = DDOT( L1-1, C( K1, 1 ), LDC, B( 1, L2 ), 1 )VEC( 1, 2 ) = C( K1, L2 ) - ( SUML+SGN*SUMR )*SUML = DDOT( M-K2, A( K2, MIN( K2+1, M ) ), LDA,$ C( MIN( K2+1, M ), L1 ), 1 )SUMR = DDOT( L1-1, C( K2, 1 ), LDC, B( 1, L1 ), 1 )VEC( 2, 1 ) = C( K2, L1 ) - ( SUML+SGN*SUMR )*SUML = DDOT( M-K2, A( K2, MIN( K2+1, M ) ), LDA,$ C( MIN( K2+1, M ), L2 ), 1 )SUMR = DDOT( L1-1, C( K2, 1 ), LDC, B( 1, L2 ), 1 )VEC( 2, 2 ) = C( K2, L2 ) - ( SUML+SGN*SUMR )*CALL DLASY2( .FALSE., .FALSE., ISGN, 2, 2,$ A( K1, K1 ), LDA, B( L1, L1 ), LDB, VEC,$ 2, SCALOC, X, 2, XNORM, IERR )IF( IERR.NE.0 )$ INFO = 1*IF( SCALOC.NE.ONE ) THENDO 40 J = 1, NCALL DSCAL( M, SCALOC, C( 1, J ), 1 )40 CONTINUESCALE = SCALE*SCALOCEND IFC( K1, L1 ) = X( 1, 1 )C( K1, L2 ) = X( 1, 2 )C( K2, L1 ) = X( 2, 1 )C( K2, L2 ) = X( 2, 2 )END IF*50 CONTINUE*60 CONTINUE*ELSE IF( .NOT.NOTRNA .AND. NOTRNB ) THEN** Solve A' *X + ISGN*X*B = scale*C.** The (K,L)th block of X is determined starting from* upper-left corner column by column by** A(K,K)'*X(K,L) + ISGN*X(K,L)*B(L,L) = C(K,L) - R(K,L)** Where* K-1 L-1* R(K,L) = SUM [A(I,K)'*X(I,L)] +ISGN*SUM [X(K,J)*B(J,L)]* I=1 J=1** Start column loop (index = L)* L1 (L2): column index of the first (last) row of X(K,L)*LNEXT = 1DO 120 L = 1, NIF( L.LT.LNEXT )$ GO TO 120IF( L.EQ.N ) THENL1 = LL2 = LELSEIF( B( L+1, L ).NE.ZERO ) THENL1 = LL2 = L + 1LNEXT = L + 2ELSEL1 = LL2 = LLNEXT = L + 1END IFEND IF** Start row loop (index = K)* K1 (K2): row index of the first (last) row of X(K,L)*KNEXT = 1DO 110 K = 1, MIF( K.LT.KNEXT )$ GO TO 110IF( K.EQ.M ) THENK1 = KK2 = KELSEIF( A( K+1, K ).NE.ZERO ) THENK1 = KK2 = K + 1KNEXT = K + 2ELSEK1 = KK2 = KKNEXT = K + 1END IFEND IF*IF( L1.EQ.L2 .AND. K1.EQ.K2 ) THENSUML = DDOT( K1-1, A( 1, K1 ), 1, C( 1, L1 ), 1 )SUMR = DDOT( L1-1, C( K1, 1 ), LDC, B( 1, L1 ), 1 )VEC( 1, 1 ) = C( K1, L1 ) - ( SUML+SGN*SUMR )SCALOC = ONE*A11 = A( K1, K1 ) + SGN*B( L1, L1 )DA11 = ABS( A11 )IF( DA11.LE.SMIN ) THENA11 = SMINDA11 = SMININFO = 1END IFDB = ABS( VEC( 1, 1 ) )IF( DA11.LT.ONE .AND. DB.GT.ONE ) THENIF( DB.GT.BIGNUM*DA11 )$ SCALOC = ONE / DBEND IFX( 1, 1 ) = ( VEC( 1, 1 )*SCALOC ) / A11*IF( SCALOC.NE.ONE ) THENDO 70 J = 1, NCALL DSCAL( M, SCALOC, C( 1, J ), 1 )70 CONTINUESCALE = SCALE*SCALOCEND IFC( K1, L1 ) = X( 1, 1 )*ELSE IF( L1.EQ.L2 .AND. K1.NE.K2 ) THEN*SUML = DDOT( K1-1, A( 1, K1 ), 1, C( 1, L1 ), 1 )SUMR = DDOT( L1-1, C( K1, 1 ), LDC, B( 1, L1 ), 1 )VEC( 1, 1 ) = C( K1, L1 ) - ( SUML+SGN*SUMR )*SUML = DDOT( K1-1, A( 1, K2 ), 1, C( 1, L1 ), 1 )SUMR = DDOT( L1-1, C( K2, 1 ), LDC, B( 1, L1 ), 1 )VEC( 2, 1 ) = C( K2, L1 ) - ( SUML+SGN*SUMR )*CALL DLALN2( .TRUE., 2, 1, SMIN, ONE, A( K1, K1 ),$ LDA, ONE, ONE, VEC, 2, -SGN*B( L1, L1 ),$ ZERO, X, 2, SCALOC, XNORM, IERR )IF( IERR.NE.0 )$ INFO = 1*IF( SCALOC.NE.ONE ) THENDO 80 J = 1, NCALL DSCAL( M, SCALOC, C( 1, J ), 1 )80 CONTINUESCALE = SCALE*SCALOCEND IFC( K1, L1 ) = X( 1, 1 )C( K2, L1 ) = X( 2, 1 )*ELSE IF( L1.NE.L2 .AND. K1.EQ.K2 ) THEN*SUML = DDOT( K1-1, A( 1, K1 ), 1, C( 1, L1 ), 1 )SUMR = DDOT( L1-1, C( K1, 1 ), LDC, B( 1, L1 ), 1 )VEC( 1, 1 ) = SGN*( C( K1, L1 )-( SUML+SGN*SUMR ) )*SUML = DDOT( K1-1, A( 1, K1 ), 1, C( 1, L2 ), 1 )SUMR = DDOT( L1-1, C( K1, 1 ), LDC, B( 1, L2 ), 1 )VEC( 2, 1 ) = SGN*( C( K1, L2 )-( SUML+SGN*SUMR ) )*CALL DLALN2( .TRUE., 2, 1, SMIN, ONE, B( L1, L1 ),$ LDB, ONE, ONE, VEC, 2, -SGN*A( K1, K1 ),$ ZERO, X, 2, SCALOC, XNORM, IERR )IF( IERR.NE.0 )$ INFO = 1*IF( SCALOC.NE.ONE ) THENDO 90 J = 1, NCALL DSCAL( M, SCALOC, C( 1, J ), 1 )90 CONTINUESCALE = SCALE*SCALOCEND IFC( K1, L1 ) = X( 1, 1 )C( K1, L2 ) = X( 2, 1 )*ELSE IF( L1.NE.L2 .AND. K1.NE.K2 ) THEN*SUML = DDOT( K1-1, A( 1, K1 ), 1, C( 1, L1 ), 1 )SUMR = DDOT( L1-1, C( K1, 1 ), LDC, B( 1, L1 ), 1 )VEC( 1, 1 ) = C( K1, L1 ) - ( SUML+SGN*SUMR )*SUML = DDOT( K1-1, A( 1, K1 ), 1, C( 1, L2 ), 1 )SUMR = DDOT( L1-1, C( K1, 1 ), LDC, B( 1, L2 ), 1 )VEC( 1, 2 ) = C( K1, L2 ) - ( SUML+SGN*SUMR )*SUML = DDOT( K1-1, A( 1, K2 ), 1, C( 1, L1 ), 1 )SUMR = DDOT( L1-1, C( K2, 1 ), LDC, B( 1, L1 ), 1 )VEC( 2, 1 ) = C( K2, L1 ) - ( SUML+SGN*SUMR )*SUML = DDOT( K1-1, A( 1, K2 ), 1, C( 1, L2 ), 1 )SUMR = DDOT( L1-1, C( K2, 1 ), LDC, B( 1, L2 ), 1 )VEC( 2, 2 ) = C( K2, L2 ) - ( SUML+SGN*SUMR )*CALL DLASY2( .TRUE., .FALSE., ISGN, 2, 2, A( K1, K1 ),$ LDA, B( L1, L1 ), LDB, VEC, 2, SCALOC, X,$ 2, XNORM, IERR )IF( IERR.NE.0 )$ INFO = 1*IF( SCALOC.NE.ONE ) THENDO 100 J = 1, NCALL DSCAL( M, SCALOC, C( 1, J ), 1 )100 CONTINUESCALE = SCALE*SCALOCEND IFC( K1, L1 ) = X( 1, 1 )C( K1, L2 ) = X( 1, 2 )C( K2, L1 ) = X( 2, 1 )C( K2, L2 ) = X( 2, 2 )END IF*110 CONTINUE120 CONTINUE*ELSE IF( .NOT.NOTRNA .AND. .NOT.NOTRNB ) THEN** Solve A'*X + ISGN*X*B' = scale*C.** The (K,L)th block of X is determined starting from* top-right corner column by column by** A(K,K)'*X(K,L) + ISGN*X(K,L)*B(L,L)' = C(K,L) - R(K,L)** Where* K-1 N* R(K,L) = SUM [A(I,K)'*X(I,L)] + ISGN*SUM [X(K,J)*B(L,J)'].* I=1 J=L+1** Start column loop (index = L)* L1 (L2): column index of the first (last) row of X(K,L)*LNEXT = NDO 180 L = N, 1, -1IF( L.GT.LNEXT )$ GO TO 180IF( L.EQ.1 ) THENL1 = LL2 = LELSEIF( B( L, L-1 ).NE.ZERO ) THENL1 = L - 1L2 = LLNEXT = L - 2ELSEL1 = LL2 = LLNEXT = L - 1END IFEND IF** Start row loop (index = K)* K1 (K2): row index of the first (last) row of X(K,L)*KNEXT = 1DO 170 K = 1, MIF( K.LT.KNEXT )$ GO TO 170IF( K.EQ.M ) THENK1 = KK2 = KELSEIF( A( K+1, K ).NE.ZERO ) THENK1 = KK2 = K + 1KNEXT = K + 2ELSEK1 = KK2 = KKNEXT = K + 1END IFEND IF*IF( L1.EQ.L2 .AND. K1.EQ.K2 ) THENSUML = DDOT( K1-1, A( 1, K1 ), 1, C( 1, L1 ), 1 )SUMR = DDOT( N-L1, C( K1, MIN( L1+1, N ) ), LDC,$ B( L1, MIN( L1+1, N ) ), LDB )VEC( 1, 1 ) = C( K1, L1 ) - ( SUML+SGN*SUMR )SCALOC = ONE*A11 = A( K1, K1 ) + SGN*B( L1, L1 )DA11 = ABS( A11 )IF( DA11.LE.SMIN ) THENA11 = SMINDA11 = SMININFO = 1END IFDB = ABS( VEC( 1, 1 ) )IF( DA11.LT.ONE .AND. DB.GT.ONE ) THENIF( DB.GT.BIGNUM*DA11 )$ SCALOC = ONE / DBEND IFX( 1, 1 ) = ( VEC( 1, 1 )*SCALOC ) / A11*IF( SCALOC.NE.ONE ) THENDO 130 J = 1, NCALL DSCAL( M, SCALOC, C( 1, J ), 1 )130 CONTINUESCALE = SCALE*SCALOCEND IFC( K1, L1 ) = X( 1, 1 )*ELSE IF( L1.EQ.L2 .AND. K1.NE.K2 ) THEN*SUML = DDOT( K1-1, A( 1, K1 ), 1, C( 1, L1 ), 1 )SUMR = DDOT( N-L2, C( K1, MIN( L2+1, N ) ), LDC,$ B( L1, MIN( L2+1, N ) ), LDB )VEC( 1, 1 ) = C( K1, L1 ) - ( SUML+SGN*SUMR )*SUML = DDOT( K1-1, A( 1, K2 ), 1, C( 1, L1 ), 1 )SUMR = DDOT( N-L2, C( K2, MIN( L2+1, N ) ), LDC,$ B( L1, MIN( L2+1, N ) ), LDB )VEC( 2, 1 ) = C( K2, L1 ) - ( SUML+SGN*SUMR )*CALL DLALN2( .TRUE., 2, 1, SMIN, ONE, A( K1, K1 ),$ LDA, ONE, ONE, VEC, 2, -SGN*B( L1, L1 ),$ ZERO, X, 2, SCALOC, XNORM, IERR )IF( IERR.NE.0 )$ INFO = 1*IF( SCALOC.NE.ONE ) THENDO 140 J = 1, NCALL DSCAL( M, SCALOC, C( 1, J ), 1 )140 CONTINUESCALE = SCALE*SCALOCEND IFC( K1, L1 ) = X( 1, 1 )C( K2, L1 ) = X( 2, 1 )*ELSE IF( L1.NE.L2 .AND. K1.EQ.K2 ) THEN*SUML = DDOT( K1-1, A( 1, K1 ), 1, C( 1, L1 ), 1 )SUMR = DDOT( N-L2, C( K1, MIN( L2+1, N ) ), LDC,$ B( L1, MIN( L2+1, N ) ), LDB )VEC( 1, 1 ) = SGN*( C( K1, L1 )-( SUML+SGN*SUMR ) )*SUML = DDOT( K1-1, A( 1, K1 ), 1, C( 1, L2 ), 1 )SUMR = DDOT( N-L2, C( K1, MIN( L2+1, N ) ), LDC,$ B( L2, MIN( L2+1, N ) ), LDB )VEC( 2, 1 ) = SGN*( C( K1, L2 )-( SUML+SGN*SUMR ) )*CALL DLALN2( .FALSE., 2, 1, SMIN, ONE, B( L1, L1 ),$ LDB, ONE, ONE, VEC, 2, -SGN*A( K1, K1 ),$ ZERO, X, 2, SCALOC, XNORM, IERR )IF( IERR.NE.0 )$ INFO = 1*IF( SCALOC.NE.ONE ) THENDO 150 J = 1, NCALL DSCAL( M, SCALOC, C( 1, J ), 1 )150 CONTINUESCALE = SCALE*SCALOCEND IFC( K1, L1 ) = X( 1, 1 )C( K1, L2 ) = X( 2, 1 )*ELSE IF( L1.NE.L2 .AND. K1.NE.K2 ) THEN*SUML = DDOT( K1-1, A( 1, K1 ), 1, C( 1, L1 ), 1 )SUMR = DDOT( N-L2, C( K1, MIN( L2+1, N ) ), LDC,$ B( L1, MIN( L2+1, N ) ), LDB )VEC( 1, 1 ) = C( K1, L1 ) - ( SUML+SGN*SUMR )*SUML = DDOT( K1-1, A( 1, K1 ), 1, C( 1, L2 ), 1 )SUMR = DDOT( N-L2, C( K1, MIN( L2+1, N ) ), LDC,$ B( L2, MIN( L2+1, N ) ), LDB )VEC( 1, 2 ) = C( K1, L2 ) - ( SUML+SGN*SUMR )*SUML = DDOT( K1-1, A( 1, K2 ), 1, C( 1, L1 ), 1 )SUMR = DDOT( N-L2, C( K2, MIN( L2+1, N ) ), LDC,$ B( L1, MIN( L2+1, N ) ), LDB )VEC( 2, 1 ) = C( K2, L1 ) - ( SUML+SGN*SUMR )*SUML = DDOT( K1-1, A( 1, K2 ), 1, C( 1, L2 ), 1 )SUMR = DDOT( N-L2, C( K2, MIN( L2+1, N ) ), LDC,$ B( L2, MIN( L2+1, N ) ), LDB )VEC( 2, 2 ) = C( K2, L2 ) - ( SUML+SGN*SUMR )*CALL DLASY2( .TRUE., .TRUE., ISGN, 2, 2, A( K1, K1 ),$ LDA, B( L1, L1 ), LDB, VEC, 2, SCALOC, X,$ 2, XNORM, IERR )IF( IERR.NE.0 )$ INFO = 1*IF( SCALOC.NE.ONE ) THENDO 160 J = 1, NCALL DSCAL( M, SCALOC, C( 1, J ), 1 )160 CONTINUESCALE = SCALE*SCALOCEND IFC( K1, L1 ) = X( 1, 1 )C( K1, L2 ) = X( 1, 2 )C( K2, L1 ) = X( 2, 1 )C( K2, L2 ) = X( 2, 2 )END IF*170 CONTINUE180 CONTINUE*ELSE IF( NOTRNA .AND. .NOT.NOTRNB ) THEN** Solve A*X + ISGN*X*B' = scale*C.** The (K,L)th block of X is determined starting from* bottom-right corner column by column by** A(K,K)*X(K,L) + ISGN*X(K,L)*B(L,L)' = C(K,L) - R(K,L)** Where* M N* R(K,L) = SUM [A(K,I)*X(I,L)] + ISGN*SUM [X(K,J)*B(L,J)'].* I=K+1 J=L+1** Start column loop (index = L)* L1 (L2): column index of the first (last) row of X(K,L)*LNEXT = NDO 240 L = N, 1, -1IF( L.GT.LNEXT )$ GO TO 240IF( L.EQ.1 ) THENL1 = LL2 = LELSEIF( B( L, L-1 ).NE.ZERO ) THENL1 = L - 1L2 = LLNEXT = L - 2ELSEL1 = LL2 = LLNEXT = L - 1END IFEND IF** Start row loop (index = K)* K1 (K2): row index of the first (last) row of X(K,L)*KNEXT = MDO 230 K = M, 1, -1IF( K.GT.KNEXT )$ GO TO 230IF( K.EQ.1 ) THENK1 = KK2 = KELSEIF( A( K, K-1 ).NE.ZERO ) THENK1 = K - 1K2 = KKNEXT = K - 2ELSEK1 = KK2 = KKNEXT = K - 1END IFEND IF*IF( L1.EQ.L2 .AND. K1.EQ.K2 ) THENSUML = DDOT( M-K1, A( K1, MIN( K1+1, M ) ), LDA,$ C( MIN( K1+1, M ), L1 ), 1 )SUMR = DDOT( N-L1, C( K1, MIN( L1+1, N ) ), LDC,$ B( L1, MIN( L1+1, N ) ), LDB )VEC( 1, 1 ) = C( K1, L1 ) - ( SUML+SGN*SUMR )SCALOC = ONE*A11 = A( K1, K1 ) + SGN*B( L1, L1 )DA11 = ABS( A11 )IF( DA11.LE.SMIN ) THENA11 = SMINDA11 = SMININFO = 1END IFDB = ABS( VEC( 1, 1 ) )IF( DA11.LT.ONE .AND. DB.GT.ONE ) THENIF( DB.GT.BIGNUM*DA11 )$ SCALOC = ONE / DBEND IFX( 1, 1 ) = ( VEC( 1, 1 )*SCALOC ) / A11*IF( SCALOC.NE.ONE ) THENDO 190 J = 1, NCALL DSCAL( M, SCALOC, C( 1, J ), 1 )190 CONTINUESCALE = SCALE*SCALOCEND IFC( K1, L1 ) = X( 1, 1 )*ELSE IF( L1.EQ.L2 .AND. K1.NE.K2 ) THEN*SUML = DDOT( M-K2, A( K1, MIN( K2+1, M ) ), LDA,$ C( MIN( K2+1, M ), L1 ), 1 )SUMR = DDOT( N-L2, C( K1, MIN( L2+1, N ) ), LDC,$ B( L1, MIN( L2+1, N ) ), LDB )VEC( 1, 1 ) = C( K1, L1 ) - ( SUML+SGN*SUMR )*SUML = DDOT( M-K2, A( K2, MIN( K2+1, M ) ), LDA,$ C( MIN( K2+1, M ), L1 ), 1 )SUMR = DDOT( N-L2, C( K2, MIN( L2+1, N ) ), LDC,$ B( L1, MIN( L2+1, N ) ), LDB )VEC( 2, 1 ) = C( K2, L1 ) - ( SUML+SGN*SUMR )*CALL DLALN2( .FALSE., 2, 1, SMIN, ONE, A( K1, K1 ),$ LDA, ONE, ONE, VEC, 2, -SGN*B( L1, L1 ),$ ZERO, X, 2, SCALOC, XNORM, IERR )IF( IERR.NE.0 )$ INFO = 1*IF( SCALOC.NE.ONE ) THENDO 200 J = 1, NCALL DSCAL( M, SCALOC, C( 1, J ), 1 )200 CONTINUESCALE = SCALE*SCALOCEND IFC( K1, L1 ) = X( 1, 1 )C( K2, L1 ) = X( 2, 1 )*ELSE IF( L1.NE.L2 .AND. K1.EQ.K2 ) THEN*SUML = DDOT( M-K1, A( K1, MIN( K1+1, M ) ), LDA,$ C( MIN( K1+1, M ), L1 ), 1 )SUMR = DDOT( N-L2, C( K1, MIN( L2+1, N ) ), LDC,$ B( L1, MIN( L2+1, N ) ), LDB )VEC( 1, 1 ) = SGN*( C( K1, L1 )-( SUML+SGN*SUMR ) )*SUML = DDOT( M-K1, A( K1, MIN( K1+1, M ) ), LDA,$ C( MIN( K1+1, M ), L2 ), 1 )SUMR = DDOT( N-L2, C( K1, MIN( L2+1, N ) ), LDC,$ B( L2, MIN( L2+1, N ) ), LDB )VEC( 2, 1 ) = SGN*( C( K1, L2 )-( SUML+SGN*SUMR ) )*CALL DLALN2( .FALSE., 2, 1, SMIN, ONE, B( L1, L1 ),$ LDB, ONE, ONE, VEC, 2, -SGN*A( K1, K1 ),$ ZERO, X, 2, SCALOC, XNORM, IERR )IF( IERR.NE.0 )$ INFO = 1*IF( SCALOC.NE.ONE ) THENDO 210 J = 1, NCALL DSCAL( M, SCALOC, C( 1, J ), 1 )210 CONTINUESCALE = SCALE*SCALOCEND IFC( K1, L1 ) = X( 1, 1 )C( K1, L2 ) = X( 2, 1 )*ELSE IF( L1.NE.L2 .AND. K1.NE.K2 ) THEN*SUML = DDOT( M-K2, A( K1, MIN( K2+1, M ) ), LDA,$ C( MIN( K2+1, M ), L1 ), 1 )SUMR = DDOT( N-L2, C( K1, MIN( L2+1, N ) ), LDC,$ B( L1, MIN( L2+1, N ) ), LDB )VEC( 1, 1 ) = C( K1, L1 ) - ( SUML+SGN*SUMR )*SUML = DDOT( M-K2, A( K1, MIN( K2+1, M ) ), LDA,$ C( MIN( K2+1, M ), L2 ), 1 )SUMR = DDOT( N-L2, C( K1, MIN( L2+1, N ) ), LDC,$ B( L2, MIN( L2+1, N ) ), LDB )VEC( 1, 2 ) = C( K1, L2 ) - ( SUML+SGN*SUMR )*SUML = DDOT( M-K2, A( K2, MIN( K2+1, M ) ), LDA,$ C( MIN( K2+1, M ), L1 ), 1 )SUMR = DDOT( N-L2, C( K2, MIN( L2+1, N ) ), LDC,$ B( L1, MIN( L2+1, N ) ), LDB )VEC( 2, 1 ) = C( K2, L1 ) - ( SUML+SGN*SUMR )*SUML = DDOT( M-K2, A( K2, MIN( K2+1, M ) ), LDA,$ C( MIN( K2+1, M ), L2 ), 1 )SUMR = DDOT( N-L2, C( K2, MIN( L2+1, N ) ), LDC,$ B( L2, MIN( L2+1, N ) ), LDB )VEC( 2, 2 ) = C( K2, L2 ) - ( SUML+SGN*SUMR )*CALL DLASY2( .FALSE., .TRUE., ISGN, 2, 2, A( K1, K1 ),$ LDA, B( L1, L1 ), LDB, VEC, 2, SCALOC, X,$ 2, XNORM, IERR )IF( IERR.NE.0 )$ INFO = 1*IF( SCALOC.NE.ONE ) THENDO 220 J = 1, NCALL DSCAL( M, SCALOC, C( 1, J ), 1 )220 CONTINUESCALE = SCALE*SCALOCEND IFC( K1, L1 ) = X( 1, 1 )C( K1, L2 ) = X( 1, 2 )C( K2, L1 ) = X( 2, 1 )C( K2, L2 ) = X( 2, 2 )END IF*230 CONTINUE240 CONTINUE*END IF*RETURN** End of DTRSYL*ENDSUBROUTINE DTRTI2( UPLO, DIAG, N, A, LDA, INFO )** -- LAPACK routine (version 3.0) --* Univ. of Tennessee, Univ. of California Berkeley, NAG Ltd.,* Courant Institute, Argonne National Lab, and Rice University* February 29, 1992** .. Scalar Arguments ..CHARACTER DIAG, UPLOINTEGER INFO, LDA, N* ..* .. Array Arguments ..DOUBLE PRECISION A( LDA, * )* ..** Purpose* =======** DTRTI2 computes the inverse of a real upper or lower triangular* matrix.** This is the Level 2 BLAS version of the algorithm.** Arguments* =========** UPLO (input) CHARACTER*1* Specifies whether the matrix A is upper or lower triangular.* = 'U': Upper triangular* = 'L': Lower triangular** DIAG (input) CHARACTER*1* Specifies whether or not the matrix A is unit triangular.* = 'N': Non-unit triangular* = 'U': Unit triangular** N (input) INTEGER* The order of the matrix A. N >= 0.** A (input/output) DOUBLE PRECISION array, dimension (LDA,N)* On entry, the triangular matrix A. If UPLO = 'U', the* leading n by n upper triangular part of the array A contains* the upper triangular matrix, and the strictly lower* triangular part of A is not referenced. If UPLO = 'L', the* leading n by n lower triangular part of the array A contains* the lower triangular matrix, and the strictly upper* triangular part of A is not referenced. If DIAG = 'U', the* diagonal elements of A are also not referenced and are* assumed to be 1.** On exit, the (triangular) inverse of the original matrix, in* the same storage format.** LDA (input) INTEGER* The leading dimension of the array A. LDA >= max(1,N).** INFO (output) INTEGER* = 0: successful exit* < 0: if INFO = -k, the k-th argument had an illegal value** =====================================================================** .. Parameters ..DOUBLE PRECISION ONEPARAMETER ( ONE = 1.0D+0 )* ..* .. Local Scalars ..LOGICAL NOUNIT, UPPERINTEGER JDOUBLE PRECISION AJJ* ..* .. External Functions ..LOGICAL LSAMEEXTERNAL LSAME* ..* .. External Subroutines ..EXTERNAL DSCAL, DTRMV, XERBLA* ..* .. Intrinsic Functions ..INTRINSIC MAX* ..* .. Executable Statements ..** Test the input parameters.*INFO = 0UPPER = LSAME( UPLO, 'U' )NOUNIT = LSAME( DIAG, 'N' )IF( .NOT.UPPER .AND. .NOT.LSAME( UPLO, 'L' ) ) THENINFO = -1ELSE IF( .NOT.NOUNIT .AND. .NOT.LSAME( DIAG, 'U' ) ) THENINFO = -2ELSE IF( N.LT.0 ) THENINFO = -3ELSE IF( LDA.LT.MAX( 1, N ) ) THENINFO = -5END IFIF( INFO.NE.0 ) THENCALL XERBLA( 'DTRTI2', -INFO )RETURNEND IF*IF( UPPER ) THEN** Compute inverse of upper triangular matrix.*DO 10 J = 1, NIF( NOUNIT ) THENA( J, J ) = ONE / A( J, J )AJJ = -A( J, J )ELSEAJJ = -ONEEND IF** Compute elements 1:j-1 of j-th column.*CALL DTRMV( 'Upper', 'No transpose', DIAG, J-1, A, LDA,$ A( 1, J ), 1 )CALL DSCAL( J-1, AJJ, A( 1, J ), 1 )10 CONTINUEELSE** Compute inverse of lower triangular matrix.*DO 20 J = N, 1, -1IF( NOUNIT ) THENA( J, J ) = ONE / A( J, J )AJJ = -A( J, J )ELSEAJJ = -ONEEND IFIF( J.LT.N ) THEN** Compute elements j+1:n of j-th column.*CALL DTRMV( 'Lower', 'No transpose', DIAG, N-J,$ A( J+1, J+1 ), LDA, A( J+1, J ), 1 )CALL DSCAL( N-J, AJJ, A( J+1, J ), 1 )END IF20 CONTINUEEND IF*RETURN** End of DTRTI2*ENDSUBROUTINE DTRTRI( UPLO, DIAG, N, A, LDA, INFO )** -- LAPACK routine (version 3.0) --* Univ. of Tennessee, Univ. of California Berkeley, NAG Ltd.,* Courant Institute, Argonne National Lab, and Rice University* March 31, 1993** .. Scalar Arguments ..CHARACTER DIAG, UPLOINTEGER INFO, LDA, N* ..* .. Array Arguments ..DOUBLE PRECISION A( LDA, * )* ..** Purpose* =======** DTRTRI computes the inverse of a real upper or lower triangular* matrix A.** This is the Level 3 BLAS version of the algorithm.** Arguments* =========** UPLO (input) CHARACTER*1* = 'U': A is upper triangular;* = 'L': A is lower triangular.** DIAG (input) CHARACTER*1* = 'N': A is non-unit triangular;* = 'U': A is unit triangular.** N (input) INTEGER* The order of the matrix A. N >= 0.** A (input/output) DOUBLE PRECISION array, dimension (LDA,N)* On entry, the triangular matrix A. If UPLO = 'U', the* leading N-by-N upper triangular part of the array A contains* the upper triangular matrix, and the strictly lower* triangular part of A is not referenced. If UPLO = 'L', the* leading N-by-N lower triangular part of the array A contains* the lower triangular matrix, and the strictly upper* triangular part of A is not referenced. If DIAG = 'U', the* diagonal elements of A are also not referenced and are* assumed to be 1.* On exit, the (triangular) inverse of the original matrix, in* the same storage format.** LDA (input) INTEGER* The leading dimension of the array A. LDA >= 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, A(i,i) is exactly zero. The triangular* matrix is singular and its inverse can not be computed.** =====================================================================** .. Parameters ..DOUBLE PRECISION ONE, ZEROPARAMETER ( ONE = 1.0D+0, ZERO = 0.0D+0 )* ..* .. Local Scalars ..LOGICAL NOUNIT, UPPERINTEGER J, JB, NB, NN* ..* .. External Functions ..LOGICAL LSAMEINTEGER ILAENVEXTERNAL LSAME, ILAENV* ..* .. External Subroutines ..EXTERNAL DTRMM, DTRSM, DTRTI2, XERBLA* ..* .. Intrinsic Functions ..INTRINSIC MAX, MIN* ..* .. Executable Statements ..** Test the input parameters.*INFO = 0UPPER = LSAME( UPLO, 'U' )NOUNIT = LSAME( DIAG, 'N' )IF( .NOT.UPPER .AND. .NOT.LSAME( UPLO, 'L' ) ) THENINFO = -1ELSE IF( .NOT.NOUNIT .AND. .NOT.LSAME( DIAG, 'U' ) ) THENINFO = -2ELSE IF( N.LT.0 ) THENINFO = -3ELSE IF( LDA.LT.MAX( 1, N ) ) THENINFO = -5END IFIF( INFO.NE.0 ) THENCALL XERBLA( 'DTRTRI', -INFO )RETURNEND IF** Quick return if possible*IF( N.EQ.0 )$ RETURN** Check for singularity if non-unit.*IF( NOUNIT ) THENDO 10 INFO = 1, NIF( A( INFO, INFO ).EQ.ZERO )$ RETURN10 CONTINUEINFO = 0END IF** Determine the block size for this environment.*NB = ILAENV( 1, 'DTRTRI', UPLO // DIAG, N, -1, -1, -1 )IF( NB.LE.1 .OR. NB.GE.N ) THEN** Use unblocked code*CALL DTRTI2( UPLO, DIAG, N, A, LDA, INFO )ELSE** Use blocked code*IF( UPPER ) THEN** Compute inverse of upper triangular matrix*DO 20 J = 1, N, NBJB = MIN( NB, N-J+1 )** Compute rows 1:j-1 of current block column*CALL DTRMM( 'Left', 'Upper', 'No transpose', DIAG, J-1,$ JB, ONE, A, LDA, A( 1, J ), LDA )CALL DTRSM( 'Right', 'Upper', 'No transpose', DIAG, J-1,$ JB, -ONE, A( J, J ), LDA, A( 1, J ), LDA )** Compute inverse of current diagonal block*CALL DTRTI2( 'Upper', DIAG, JB, A( J, J ), LDA, INFO )20 CONTINUEELSE** Compute inverse of lower triangular matrix*NN = ( ( N-1 ) / NB )*NB + 1DO 30 J = NN, 1, -NBJB = MIN( NB, N-J+1 )IF( J+JB.LE.N ) THEN** Compute rows j+jb:n of current block column*CALL DTRMM( 'Left', 'Lower', 'No transpose', DIAG,$ N-J-JB+1, JB, ONE, A( J+JB, J+JB ), LDA,$ A( J+JB, J ), LDA )CALL DTRSM( 'Right', 'Lower', 'No transpose', DIAG,$ N-J-JB+1, JB, -ONE, A( J, J ), LDA,$ A( J+JB, J ), LDA )END IF** Compute inverse of current diagonal block*CALL DTRTI2( 'Lower', DIAG, JB, A( J, J ), LDA, INFO )30 CONTINUEEND IFEND IF*RETURN** End of DTRTRI*ENDSUBROUTINE DTRTRS( UPLO, TRANS, DIAG, N, NRHS, A, LDA, B, LDB,$ INFO )** -- LAPACK routine (version 3.0) --* Univ. of Tennessee, Univ. of California Berkeley, NAG Ltd.,* Courant Institute, Argonne National Lab, and Rice University* March 31, 1993** .. Scalar Arguments ..CHARACTER DIAG, TRANS, UPLOINTEGER INFO, LDA, LDB, N, NRHS* ..* .. Array Arguments ..DOUBLE PRECISION A( LDA, * ), B( LDB, * )* ..** Purpose* =======** DTRTRS solves a triangular system of the form** A * X = B or A**T * X = B,** where A is a triangular matrix of order N, and B is an N-by-NRHS* matrix. A check is made to verify that A is nonsingular.** Arguments* =========** UPLO (input) CHARACTER*1* = 'U': A is upper triangular;* = 'L': A is lower triangular.** TRANS (input) CHARACTER*1* Specifies the form of the system of equations:* = 'N': A * X = B (No transpose)* = 'T': A**T * X = B (Transpose)* = 'C': A**H * X = B (Conjugate transpose = Transpose)** DIAG (input) CHARACTER*1* = 'N': A is non-unit triangular;* = 'U': A is unit triangular.** 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 triangular matrix A. If UPLO = 'U', the leading N-by-N* upper triangular part of the array A contains the upper* triangular matrix, and the strictly lower triangular part of* A is not referenced. If UPLO = 'L', the leading N-by-N lower* triangular part of the array A contains the lower triangular* matrix, and the strictly upper triangular part of A is not* referenced. If DIAG = 'U', the diagonal elements of A are* also not referenced and are assumed to be 1.** LDA (input) INTEGER* The leading dimension of the array A. LDA >= max(1,N).** B (input/output) DOUBLE PRECISION array, dimension (LDB,NRHS)* On entry, the right hand side matrix B.* On exit, if INFO = 0, 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* > 0: if INFO = i, the i-th diagonal element of A is zero,* indicating that the matrix is singular and the solutions* X have not been computed.** =====================================================================** .. Parameters ..DOUBLE PRECISION ZERO, ONEPARAMETER ( ZERO = 0.0D+0, ONE = 1.0D+0 )* ..* .. Local Scalars ..LOGICAL NOUNIT* ..* .. External Functions ..LOGICAL LSAMEEXTERNAL LSAME* ..* .. External Subroutines ..EXTERNAL DTRSM, XERBLA* ..* .. Intrinsic Functions ..INTRINSIC MAX* ..* .. Executable Statements ..** Test the input parameters.*INFO = 0NOUNIT = LSAME( DIAG, 'N' )IF( .NOT.LSAME( UPLO, 'U' ) .AND. .NOT.LSAME( UPLO, 'L' ) ) THENINFO = -1ELSE IF( .NOT.LSAME( TRANS, 'N' ) .AND. .NOT.$ LSAME( TRANS, 'T' ) .AND. .NOT.LSAME( TRANS, 'C' ) ) THENINFO = -2ELSE IF( .NOT.NOUNIT .AND. .NOT.LSAME( DIAG, 'U' ) ) THENINFO = -3ELSE IF( N.LT.0 ) THENINFO = -4ELSE IF( NRHS.LT.0 ) THENINFO = -5ELSE IF( LDA.LT.MAX( 1, N ) ) THENINFO = -7ELSE IF( LDB.LT.MAX( 1, N ) ) THENINFO = -9END IFIF( INFO.NE.0 ) THENCALL XERBLA( 'DTRTRS', -INFO )RETURNEND IF** Quick return if possible*IF( N.EQ.0 )$ RETURN** Check for singularity.*IF( NOUNIT ) THENDO 10 INFO = 1, NIF( A( INFO, INFO ).EQ.ZERO )$ RETURN10 CONTINUEEND IFINFO = 0** Solve A * x = b or A' * x = b.*CALL DTRSM( 'Left', UPLO, TRANS, DIAG, N, NRHS, ONE, A, LDA, B,$ LDB )*RETURN** End of DTRTRS*ENDSUBROUTINE DTZRQF( M, N, A, LDA, TAU, INFO )** -- LAPACK routine (version 3.0) --* Univ. of Tennessee, Univ. of California Berkeley, NAG Ltd.,* Courant Institute, Argonne National Lab, and Rice University* September 30, 1994** .. Scalar Arguments ..INTEGER INFO, LDA, M, N* ..* .. Array Arguments ..DOUBLE PRECISION A( LDA, * ), TAU( * )* ..** Purpose* =======** This routine is deprecated and has been replaced by routine DTZRZF.** DTZRQF reduces the M-by-N ( M<=N ) real upper trapezoidal matrix A* to upper triangular form by means of orthogonal transformations.** The upper trapezoidal matrix A is factored as** A = ( R 0 ) * Z,** where Z is an N-by-N orthogonal matrix and R is an M-by-M upper* triangular matrix.** 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 >= M.** A (input/output) DOUBLE PRECISION array, dimension (LDA,N)* On entry, the leading M-by-N upper trapezoidal part of the* array A must contain the matrix to be factorized.* On exit, the leading M-by-M upper triangular part of A* contains the upper triangular matrix R, and elements M+1 to* N of the first M rows of A, with the array TAU, represent the* orthogonal matrix Z as a product of M elementary reflectors.** LDA (input) INTEGER* The leading dimension of the array A. LDA >= max(1,M).** TAU (output) DOUBLE PRECISION array, dimension (M)* The scalar factors of the elementary reflectors.** INFO (output) INTEGER* = 0: successful exit* < 0: if INFO = -i, the i-th argument had an illegal value** Further Details* ===============** The factorization is obtained by Householder's method. The kth* transformation matrix, Z( k ), which is used to introduce zeros into* the ( m - k + 1 )th row of A, is given in the form** Z( k ) = ( I 0 ),* ( 0 T( k ) )** where** T( k ) = I - tau*u( k )*u( k )', u( k ) = ( 1 ),* ( 0 )* ( z( k ) )** tau is a scalar and z( k ) is an ( n - m ) element vector.* tau and z( k ) are chosen to annihilate the elements of the kth row* of X.** The scalar tau is returned in the kth element of TAU and the vector* u( k ) in the kth row of A, such that the elements of z( k ) are* in a( k, m + 1 ), ..., a( k, n ). The elements of R are returned in* the upper triangular part of A.** Z is given by** Z = Z( 1 ) * Z( 2 ) * ... * Z( m ).** =====================================================================** .. Parameters ..DOUBLE PRECISION ONE, ZEROPARAMETER ( ONE = 1.0D+0, ZERO = 0.0D+0 )* ..* .. Local Scalars ..INTEGER I, K, M1* ..* .. Intrinsic Functions ..INTRINSIC MAX, MIN* ..* .. External Subroutines ..EXTERNAL DAXPY, DCOPY, DGEMV, DGER, DLARFG, XERBLA* ..* .. Executable Statements ..** Test the input parameters.*INFO = 0IF( M.LT.0 ) THENINFO = -1ELSE IF( N.LT.M ) THENINFO = -2ELSE IF( LDA.LT.MAX( 1, M ) ) THENINFO = -4END IFIF( INFO.NE.0 ) THENCALL XERBLA( 'DTZRQF', -INFO )RETURNEND IF** Perform the factorization.*IF( M.EQ.0 )$ RETURNIF( M.EQ.N ) THENDO 10 I = 1, NTAU( I ) = ZERO10 CONTINUEELSEM1 = MIN( M+1, N )DO 20 K = M, 1, -1** Use a Householder reflection to zero the kth row of A.* First set up the reflection.*CALL DLARFG( N-M+1, A( K, K ), A( K, M1 ), LDA, TAU( K ) )*IF( ( TAU( K ).NE.ZERO ) .AND. ( K.GT.1 ) ) THEN** We now perform the operation A := A*P( k ).** Use the first ( k - 1 ) elements of TAU to store a( k ),* where a( k ) consists of the first ( k - 1 ) elements of* the kth column of A. Also let B denote the first* ( k - 1 ) rows of the last ( n - m ) columns of A.*CALL DCOPY( K-1, A( 1, K ), 1, TAU, 1 )** Form w = a( k ) + B*z( k ) in TAU.*CALL DGEMV( 'No transpose', K-1, N-M, ONE, A( 1, M1 ),$ LDA, A( K, M1 ), LDA, ONE, TAU, 1 )** Now form a( k ) := a( k ) - tau*w* and B := B - tau*w*z( k )'.*CALL DAXPY( K-1, -TAU( K ), TAU, 1, A( 1, K ), 1 )CALL DGER( K-1, N-M, -TAU( K ), TAU, 1, A( K, M1 ), LDA,$ A( 1, M1 ), LDA )END IF20 CONTINUEEND IF*RETURN** End of DTZRQF*ENDSUBROUTINE DTZRZF( M, N, A, LDA, TAU, WORK, LWORK, INFO )** -- LAPACK routine (version 3.0) --* Univ. of Tennessee, Univ. of California Berkeley, NAG Ltd.,* Courant Institute, Argonne National Lab, and Rice University* June 30, 1999** .. Scalar Arguments ..INTEGER INFO, LDA, LWORK, M, N* ..* .. Array Arguments ..DOUBLE PRECISION A( LDA, * ), TAU( * ), WORK( * )* ..** Purpose* =======** DTZRZF reduces the M-by-N ( M<=N ) real upper trapezoidal matrix A* to upper triangular form by means of orthogonal transformations.** The upper trapezoidal matrix A is factored as** A = ( R 0 ) * Z,** where Z is an N-by-N orthogonal matrix and R is an M-by-M upper* triangular matrix.** 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 leading M-by-N upper trapezoidal part of the* array A must contain the matrix to be factorized.* On exit, the leading M-by-M upper triangular part of A* contains the upper triangular matrix R, and elements M+1 to* N of the first M rows of A, with the array TAU, represent the* orthogonal matrix Z as a product of M elementary reflectors.** LDA (input) INTEGER* The leading dimension of the array A. LDA >= max(1,M).** TAU (output) DOUBLE PRECISION array, dimension (M)* The scalar factors of the elementary reflectors.** WORK (workspace/output) 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,M).* For optimum performance LWORK >= M*NB, where NB is* the optimal blocksize.** If LWORK = -1, then a workspace query is assumed; the routine* only calculates the optimal size of the WORK array, returns* this value as the first entry of the WORK array, and no error* message related to LWORK is issued by XERBLA.** INFO (output) INTEGER* = 0: successful exit* < 0: if INFO = -i, the i-th argument had an illegal value** Further Details* ===============** Based on contributions by* A. Petitet, Computer Science Dept., Univ. of Tenn., Knoxville, USA** The factorization is obtained by Householder's method. The kth* transformation matrix, Z( k ), which is used to introduce zeros into* the ( m - k + 1 )th row of A, is given in the form** Z( k ) = ( I 0 ),* ( 0 T( k ) )** where** T( k ) = I - tau*u( k )*u( k )', u( k ) = ( 1 ),* ( 0 )* ( z( k ) )** tau is a scalar and z( k ) is an ( n - m ) element vector.* tau and z( k ) are chosen to annihilate the elements of the kth row* of X.** The scalar tau is returned in the kth element of TAU and the vector* u( k ) in the kth row of A, such that the elements of z( k ) are* in a( k, m + 1 ), ..., a( k, n ). The elements of R are returned in* the upper triangular part of A.** Z is given by** Z = Z( 1 ) * Z( 2 ) * ... * Z( m ).** =====================================================================** .. Parameters ..DOUBLE PRECISION ZEROPARAMETER ( ZERO = 0.0D+0 )* ..* .. Local Scalars ..LOGICAL LQUERYINTEGER I, IB, IWS, KI, KK, LDWORK, LWKOPT, M1, MU, NB,$ NBMIN, NX* ..* .. External Subroutines ..EXTERNAL DLARZB, DLARZT, DLATRZ, XERBLA* ..* .. Intrinsic Functions ..INTRINSIC MAX, MIN* ..* .. External Functions ..INTEGER ILAENVEXTERNAL ILAENV* ..* .. Executable Statements ..** Test the input arguments*INFO = 0LQUERY = ( LWORK.EQ.-1 )IF( M.LT.0 ) THENINFO = -1ELSE IF( N.LT.M ) THENINFO = -2ELSE IF( LDA.LT.MAX( 1, M ) ) THENINFO = -4ELSE IF( LWORK.LT.MAX( 1, M ) .AND. .NOT.LQUERY ) THENINFO = -7END IF*IF( INFO.EQ.0 ) THEN** Determine the block size.*NB = ILAENV( 1, 'DGERQF', ' ', M, N, -1, -1 )LWKOPT = M*NBWORK( 1 ) = LWKOPTEND IF*IF( INFO.NE.0 ) THENCALL XERBLA( 'DTZRZF', -INFO )RETURNELSE IF( LQUERY ) THENRETURNEND IF** Quick return if possible*IF( M.EQ.0 ) THENWORK( 1 ) = 1RETURNELSE IF( M.EQ.N ) THENDO 10 I = 1, NTAU( I ) = ZERO10 CONTINUEWORK( 1 ) = 1RETURNEND IF*NBMIN = 2NX = 1IWS = MIF( NB.GT.1 .AND. NB.LT.M ) THEN** Determine when to cross over from blocked to unblocked code.*NX = MAX( 0, ILAENV( 3, 'DGERQF', ' ', M, N, -1, -1 ) )IF( NX.LT.M ) THEN** Determine if workspace is large enough for blocked code.*LDWORK = MIWS = LDWORK*NBIF( LWORK.LT.IWS ) THEN** Not enough workspace to use optimal NB: reduce NB and* determine the minimum value of NB.*NB = LWORK / LDWORKNBMIN = MAX( 2, ILAENV( 2, 'DGERQF', ' ', M, N, -1,$ -1 ) )END IFEND IFEND IF*IF( NB.GE.NBMIN .AND. NB.LT.M .AND. NX.LT.M ) THEN** Use blocked code initially.* The last kk rows are handled by the block method.*M1 = MIN( M+1, N )KI = ( ( M-NX-1 ) / NB )*NBKK = MIN( M, KI+NB )*DO 20 I = M - KK + KI + 1, M - KK + 1, -NBIB = MIN( M-I+1, NB )** Compute the TZ factorization of the current block* A(i:i+ib-1,i:n)*CALL DLATRZ( IB, N-I+1, N-M, A( I, I ), LDA, TAU( I ),$ WORK )IF( I.GT.1 ) THEN** Form the triangular factor of the block reflector* H = H(i+ib-1) . . . H(i+1) H(i)*CALL DLARZT( 'Backward', 'Rowwise', N-M, IB, A( I, M1 ),$ LDA, TAU( I ), WORK, LDWORK )** Apply H to A(1:i-1,i:n) from the right*CALL DLARZB( 'Right', 'No transpose', 'Backward',$ 'Rowwise', I-1, N-I+1, IB, N-M, A( I, M1 ),$ LDA, WORK, LDWORK, A( 1, I ), LDA,$ WORK( IB+1 ), LDWORK )END IF20 CONTINUEMU = I + NB - 1ELSEMU = MEND IF** Use unblocked code to factor the last or only block*IF( MU.GT.0 )$ CALL DLATRZ( MU, N, N-M, A, LDA, TAU, WORK )*WORK( 1 ) = LWKOPT*RETURN** End of DTZRZF*END