Rev 22546 | Blame | Compare with Previous | Last modification | View Log | Download | RSS feed
SUBROUTINE DGBSV( N, KL, KU, NRHS, AB, LDAB, IPIV, B, LDB, INFO )** -- LAPACK driver 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, KL, KU, LDAB, LDB, N, NRHS* ..* .. Array Arguments ..INTEGER IPIV( * )DOUBLE PRECISION AB( LDAB, * ), B( LDB, * )* ..** Purpose* =======** DGBSV computes the solution to a real system of linear equations* A * X = B, where A is a band matrix of order N with KL subdiagonals* and KU superdiagonals, and X and B are N-by-NRHS matrices.** The LU decomposition with partial pivoting and row interchanges is* used to factor A as A = L * U, where L is a product of permutation* and unit lower triangular matrices with KL subdiagonals, and U is* upper triangular with KL+KU superdiagonals. The factored form of A* is then used to solve the system of equations A * X = B.** Arguments* =========** N (input) INTEGER* The number of linear equations, i.e., the order of the* matrix A. N >= 0.** KL (input) INTEGER* The number of subdiagonals within the band of A. KL >= 0.** KU (input) INTEGER* The number of superdiagonals within the band of A. KU >= 0.** NRHS (input) INTEGER* The number of right hand sides, i.e., the number of columns* of the matrix B. NRHS >= 0.** AB (input/output) DOUBLE PRECISION array, dimension (LDAB,N)* On entry, the matrix A in band storage, in rows KL+1 to* 2*KL+KU+1; rows 1 to KL of the array need not be set.* The j-th column of A is stored in the j-th column of the* array AB as follows:* AB(KL+KU+1+i-j,j) = A(i,j) for max(1,j-KU)<=i<=min(N,j+KL)* On exit, details of the factorization: U is stored as an* upper triangular band matrix with KL+KU superdiagonals in* rows 1 to KL+KU+1, and the multipliers used during the* factorization are stored in rows KL+KU+2 to 2*KL+KU+1.* See below for further details.** LDAB (input) INTEGER* The leading dimension of the array AB. LDAB >= 2*KL+KU+1.** IPIV (output) INTEGER array, dimension (N)* The pivot indices that define the permutation matrix P;* row i of the matrix was interchanged with row IPIV(i).** B (input/output) DOUBLE PRECISION array, dimension (LDB,NRHS)* On entry, the N-by-NRHS right hand side matrix B.* On exit, if INFO = 0, the N-by-NRHS solution matrix X.** LDB (input) INTEGER* The leading dimension of the array B. LDB >= max(1,N).** INFO (output) INTEGER* = 0: successful exit* < 0: if INFO = -i, the i-th argument had an illegal value* > 0: if INFO = i, U(i,i) is exactly zero. The factorization* has been completed, but the factor U is exactly* singular, and the solution has not been computed.** Further Details* ===============** The band storage scheme is illustrated by the following example, when* M = N = 6, KL = 2, KU = 1:** On entry: On exit:** * * * + + + * * * u14 u25 u36* * * + + + + * * 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* a21 a32 a43 a54 a65 * m21 m32 m43 m54 m65 ** a31 a42 a53 a64 * * m31 m42 m53 m64 * *** Array elements marked * are not used by the routine; elements marked* + need not be set on entry, but are required by the routine to store* elements of U because of fill-in resulting from the row interchanges.** =====================================================================** .. External Subroutines ..EXTERNAL DGBTRF, DGBTRS, XERBLA* ..* .. Intrinsic Functions ..INTRINSIC MAX* ..* .. Executable Statements ..** Test the input parameters.*INFO = 0IF( N.LT.0 ) THENINFO = -1ELSE IF( KL.LT.0 ) THENINFO = -2ELSE IF( KU.LT.0 ) THENINFO = -3ELSE IF( NRHS.LT.0 ) THENINFO = -4ELSE IF( LDAB.LT.2*KL+KU+1 ) THENINFO = -6ELSE IF( LDB.LT.MAX( N, 1 ) ) THENINFO = -9END IFIF( INFO.NE.0 ) THENCALL XERBLA( 'DGBSV ', -INFO )RETURNEND IF** Compute the LU factorization of the band matrix A.*CALL DGBTRF( N, N, KL, KU, AB, LDAB, IPIV, INFO )IF( INFO.EQ.0 ) THEN** Solve the system A*X = B, overwriting B with X.*CALL DGBTRS( 'No transpose', N, KL, KU, NRHS, AB, LDAB, IPIV,$ B, LDB, INFO )END IFRETURN** End of DGBSV*ENDSUBROUTINE DGBSVX( FACT, TRANS, N, KL, KU, NRHS, AB, LDAB, AFB,$ LDAFB, IPIV, EQUED, R, C, B, LDB, X, LDX,$ RCOND, FERR, BERR, WORK, IWORK, INFO )** -- LAPACK driver 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 EQUED, FACT, TRANSINTEGER INFO, KL, KU, LDAB, LDAFB, LDB, LDX, N, NRHSDOUBLE PRECISION RCOND* ..* .. Array Arguments ..INTEGER IPIV( * ), IWORK( * )DOUBLE PRECISION AB( LDAB, * ), AFB( LDAFB, * ), B( LDB, * ),$ BERR( * ), C( * ), FERR( * ), R( * ),$ WORK( * ), X( LDX, * )* ..** Purpose* =======** DGBSVX uses the LU factorization to compute the solution to a real* system of linear equations A * X = B, A**T * X = B, or A**H * X = B,* where A is a band matrix of order N with KL subdiagonals and KU* superdiagonals, 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 by this subroutine:** 1. If FACT = 'E', real scaling factors are computed to equilibrate* the system:* TRANS = 'N': diag(R)*A*diag(C) *inv(diag(C))*X = diag(R)*B* TRANS = 'T': (diag(R)*A*diag(C))**T *inv(diag(R))*X = diag(C)*B* TRANS = 'C': (diag(R)*A*diag(C))**H *inv(diag(R))*X = diag(C)*B* Whether or not the system will be equilibrated depends on the* scaling of the matrix A, but if equilibration is used, A is* overwritten by diag(R)*A*diag(C) and B by diag(R)*B (if TRANS='N')* or diag(C)*B (if TRANS = 'T' or 'C').** 2. If FACT = 'N' or 'E', the LU decomposition is used to factor the* matrix A (after equilibration if FACT = 'E') as* A = L * U,* where L is a product of permutation and unit lower triangular* matrices with KL subdiagonals, and U is upper triangular with* KL+KU superdiagonals.** 3. If some U(i,i)=0, so that U is exactly singular, 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.** 4. The system of equations is solved for X using the factored form* of A.** 5. Iterative refinement is applied to improve the computed solution* matrix and calculate error bounds and backward error estimates* for it.** 6. If equilibration was used, the matrix X is premultiplied by* diag(C) (if TRANS = 'N') or diag(R) (if TRANS = 'T' or 'C') so* that it solves the original system before equilibration.** Arguments* =========** FACT (input) CHARACTER*1* Specifies whether or not the factored form of the matrix A is* supplied on entry, and if not, whether the matrix A should be* equilibrated before it is factored.* = 'F': On entry, AFB and IPIV contain the factored form of* A. If EQUED is not 'N', the matrix A has been* equilibrated with scaling factors given by R and C.* AB, AFB, and IPIV are not modified.* = 'N': The matrix A will be copied to AFB and factored.* = 'E': The matrix A will be equilibrated if necessary, then* copied to AFB and factored.** 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 (Transpose)** N (input) INTEGER* The number of linear equations, i.e., the order of the* matrix A. N >= 0.** KL (input) INTEGER* The number of subdiagonals within the band of A. KL >= 0.** KU (input) INTEGER* The number of superdiagonals within the band of A. KU >= 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/output) DOUBLE PRECISION array, dimension (LDAB,N)* On entry, the matrix A in band storage, in rows 1 to KL+KU+1.* The j-th column of A is stored in the j-th column of the* array AB as follows:* AB(KU+1+i-j,j) = A(i,j) for max(1,j-KU)<=i<=min(N,j+kl)** If FACT = 'F' and EQUED is not 'N', then A must have been* equilibrated by the scaling factors in R and/or C. AB is not* modified if FACT = 'F' or 'N', or if FACT = 'E' and* EQUED = 'N' on exit.** On exit, if EQUED .ne. 'N', A is scaled as follows:* EQUED = 'R': A := diag(R) * A* EQUED = 'C': A := A * diag(C)* EQUED = 'B': A := diag(R) * A * diag(C).** LDAB (input) INTEGER* The leading dimension of the array AB. LDAB >= KL+KU+1.** AFB (input or output) DOUBLE PRECISION array, dimension (LDAFB,N)* If FACT = 'F', then AFB is an input argument and on entry* contains details of the LU factorization of the band matrix* A, as computed by DGBTRF. U is stored as an upper triangular* band matrix with KL+KU superdiagonals in rows 1 to KL+KU+1,* and the multipliers used during the factorization are stored* in rows KL+KU+2 to 2*KL+KU+1. If EQUED .ne. 'N', then AFB is* the factored form of the equilibrated matrix A.** If FACT = 'N', then AFB is an output argument and on exit* returns details of the LU factorization of A.** If FACT = 'E', then AFB is an output argument and on exit* returns details of the LU factorization of the equilibrated* matrix A (see the description of AB for the form of the* equilibrated matrix).** LDAFB (input) INTEGER* The leading dimension of the array AFB. LDAFB >= 2*KL+KU+1.** IPIV (input or output) INTEGER array, dimension (N)* If FACT = 'F', then IPIV is an input argument and on entry* contains the pivot indices from the factorization A = L*U* as computed by DGBTRF; row i of the matrix was interchanged* with row IPIV(i).** If FACT = 'N', then IPIV is an output argument and on exit* contains the pivot indices from the factorization A = L*U* of the original matrix A.** If FACT = 'E', then IPIV is an output argument and on exit* contains the pivot indices from the factorization A = L*U* of the equilibrated matrix A.** EQUED (input or output) CHARACTER*1* Specifies the form of equilibration that was done.* = 'N': No equilibration (always true if FACT = 'N').* = 'R': Row equilibration, i.e., A has been premultiplied by* diag(R).* = 'C': Column equilibration, i.e., A has been postmultiplied* by diag(C).* = 'B': Both row and column equilibration, i.e., A has been* replaced by diag(R) * A * diag(C).* EQUED is an input argument if FACT = 'F'; otherwise, it is an* output argument.** R (input or output) DOUBLE PRECISION array, dimension (N)* The row scale factors for A. If EQUED = 'R' or 'B', A is* multiplied on the left by diag(R); if EQUED = 'N' or 'C', R* is not accessed. R is an input argument if FACT = 'F';* otherwise, R is an output argument. If FACT = 'F' and* EQUED = 'R' or 'B', each element of R must be positive.** C (input or output) DOUBLE PRECISION array, dimension (N)* The column scale factors for A. If EQUED = 'C' or 'B', A is* multiplied on the right by diag(C); if EQUED = 'N' or 'R', C* is not accessed. C is an input argument if FACT = 'F';* otherwise, C is an output argument. If FACT = 'F' and* EQUED = 'C' or 'B', each element of C must be positive.** B (input/output) DOUBLE PRECISION array, dimension (LDB,NRHS)* On entry, the right hand side matrix B.* On exit,* if EQUED = 'N', B is not modified;* if TRANS = 'N' and EQUED = 'R' or 'B', B is overwritten by* diag(R)*B;* if TRANS = 'T' or 'C' and EQUED = 'C' or 'B', B is* overwritten by diag(C)*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 or INFO = N+1, the N-by-NRHS solution matrix X* to the original system of equations. Note that A and B are* modified on exit if EQUED .ne. 'N', and the solution to the* equilibrated system is inv(diag(C))*X if TRANS = 'N' and* EQUED = 'C' or 'B', or inv(diag(R))*X if TRANS = 'T' or 'C'* and EQUED = 'R' or 'B'.** LDX (input) INTEGER* The leading dimension of the array X. LDX >= max(1,N).** RCOND (output) DOUBLE PRECISION* The estimate of the reciprocal condition number of the matrix* A after equilibration (if done). 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 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/output) DOUBLE PRECISION array, dimension (3*N)* On exit, WORK(1) contains the reciprocal pivot growth* factor norm(A)/norm(U). The "max absolute element" norm is* used. If WORK(1) is much less than 1, then the stability* of the LU factorization of the (equilibrated) matrix A* could be poor. This also means that the solution X, condition* estimator RCOND, and forward error bound FERR could be* unreliable. If factorization fails with 0<INFO<=N, then* WORK(1) contains the reciprocal pivot growth factor for the* leading INFO columns of A.** IWORK (workspace) INTEGER 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, and i is* <= N: U(i,i) is exactly zero. The factorization* has been completed, but the factor U is exactly* singular, so the solution and error bounds* could not be 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 ZERO, ONEPARAMETER ( ZERO = 0.0D+0, ONE = 1.0D+0 )* ..* .. Local Scalars ..LOGICAL COLEQU, EQUIL, NOFACT, NOTRAN, ROWEQUCHARACTER NORMINTEGER I, INFEQU, J, J1, J2DOUBLE PRECISION AMAX, ANORM, BIGNUM, COLCND, RCMAX, RCMIN,$ ROWCND, RPVGRW, SMLNUM* ..* .. External Functions ..LOGICAL LSAMEDOUBLE PRECISION DLAMCH, DLANGB, DLANTBEXTERNAL LSAME, DLAMCH, DLANGB, DLANTB* ..* .. External Subroutines ..EXTERNAL DCOPY, DGBCON, DGBEQU, DGBRFS, DGBTRF, DGBTRS,$ DLACPY, DLAQGB, XERBLA* ..* .. Intrinsic Functions ..INTRINSIC ABS, MAX, MIN* ..* .. Executable Statements ..*INFO = 0NOFACT = LSAME( FACT, 'N' )EQUIL = LSAME( FACT, 'E' )NOTRAN = LSAME( TRANS, 'N' )IF( NOFACT .OR. EQUIL ) THENEQUED = 'N'ROWEQU = .FALSE.COLEQU = .FALSE.ELSEROWEQU = LSAME( EQUED, 'R' ) .OR. LSAME( EQUED, 'B' )COLEQU = LSAME( EQUED, 'C' ) .OR. LSAME( EQUED, 'B' )SMLNUM = DLAMCH( 'Safe minimum' )BIGNUM = ONE / SMLNUMEND IF** Test the input parameters.*IF( .NOT.NOFACT .AND. .NOT.EQUIL .AND. .NOT.LSAME( FACT, 'F' ) )$ THENINFO = -1ELSE IF( .NOT.NOTRAN .AND. .NOT.LSAME( TRANS, 'T' ) .AND. .NOT.$ LSAME( TRANS, 'C' ) ) THENINFO = -2ELSE IF( N.LT.0 ) THENINFO = -3ELSE IF( KL.LT.0 ) THENINFO = -4ELSE IF( KU.LT.0 ) THENINFO = -5ELSE IF( NRHS.LT.0 ) THENINFO = -6ELSE IF( LDAB.LT.KL+KU+1 ) THENINFO = -8ELSE IF( LDAFB.LT.2*KL+KU+1 ) THENINFO = -10ELSE IF( LSAME( FACT, 'F' ) .AND. .NOT.$ ( ROWEQU .OR. COLEQU .OR. LSAME( EQUED, 'N' ) ) ) THENINFO = -12ELSEIF( ROWEQU ) THENRCMIN = BIGNUMRCMAX = ZERODO 10 J = 1, NRCMIN = MIN( RCMIN, R( J ) )RCMAX = MAX( RCMAX, R( J ) )10 CONTINUEIF( RCMIN.LE.ZERO ) THENINFO = -13ELSE IF( N.GT.0 ) THENROWCND = MAX( RCMIN, SMLNUM ) / MIN( RCMAX, BIGNUM )ELSEROWCND = ONEEND IFEND IFIF( COLEQU .AND. INFO.EQ.0 ) THENRCMIN = BIGNUMRCMAX = ZERODO 20 J = 1, NRCMIN = MIN( RCMIN, C( J ) )RCMAX = MAX( RCMAX, C( J ) )20 CONTINUEIF( RCMIN.LE.ZERO ) THENINFO = -14ELSE IF( N.GT.0 ) THENCOLCND = MAX( RCMIN, SMLNUM ) / MIN( RCMAX, BIGNUM )ELSECOLCND = ONEEND IFEND IFIF( INFO.EQ.0 ) THENIF( LDB.LT.MAX( 1, N ) ) THENINFO = -16ELSE IF( LDX.LT.MAX( 1, N ) ) THENINFO = -18END IFEND IFEND IF*IF( INFO.NE.0 ) THENCALL XERBLA( 'DGBSVX', -INFO )RETURNEND IF*IF( EQUIL ) THEN** Compute row and column scalings to equilibrate the matrix A.*CALL DGBEQU( N, N, KL, KU, AB, LDAB, R, C, ROWCND, COLCND,$ AMAX, INFEQU )IF( INFEQU.EQ.0 ) THEN** Equilibrate the matrix.*CALL DLAQGB( N, N, KL, KU, AB, LDAB, R, C, ROWCND, COLCND,$ AMAX, EQUED )ROWEQU = LSAME( EQUED, 'R' ) .OR. LSAME( EQUED, 'B' )COLEQU = LSAME( EQUED, 'C' ) .OR. LSAME( EQUED, 'B' )END IFEND IF** Scale the right hand side.*IF( NOTRAN ) THENIF( ROWEQU ) THENDO 40 J = 1, NRHSDO 30 I = 1, NB( I, J ) = R( I )*B( I, J )30 CONTINUE40 CONTINUEEND IFELSE IF( COLEQU ) THENDO 60 J = 1, NRHSDO 50 I = 1, NB( I, J ) = C( I )*B( I, J )50 CONTINUE60 CONTINUEEND IF*IF( NOFACT .OR. EQUIL ) THEN** Compute the LU factorization of the band matrix A.*DO 70 J = 1, NJ1 = MAX( J-KU, 1 )J2 = MIN( J+KL, N )CALL DCOPY( J2-J1+1, AB( KU+1-J+J1, J ), 1,$ AFB( KL+KU+1-J+J1, J ), 1 )70 CONTINUE*CALL DGBTRF( N, N, KL, KU, AFB, LDAFB, IPIV, INFO )** Return if INFO is non-zero.*IF( INFO.NE.0 ) THENIF( INFO.GT.0 ) THEN** Compute the reciprocal pivot growth factor of the* leading rank-deficient INFO columns of A.*ANORM = ZERODO 90 J = 1, INFODO 80 I = MAX( KU+2-J, 1 ),$ MIN( N+KU+1-J, KL+KU+1 )ANORM = MAX( ANORM, ABS( AB( I, J ) ) )80 CONTINUE90 CONTINUERPVGRW = DLANTB( 'M', 'U', 'N', INFO,$ MIN( INFO-1, KL+KU ), AFB( MAX( 1,$ KL+KU+2-INFO ), 1 ), LDAFB, WORK )IF( RPVGRW.EQ.ZERO ) THENRPVGRW = ONEELSERPVGRW = ANORM / RPVGRWEND IFWORK( 1 ) = RPVGRWRCOND = ZEROEND IFRETURNEND IFEND IF** Compute the norm of the matrix A and the* reciprocal pivot growth factor RPVGRW.*IF( NOTRAN ) THENNORM = '1'ELSENORM = 'I'END IFANORM = DLANGB( NORM, N, KL, KU, AB, LDAB, WORK )RPVGRW = DLANTB( 'M', 'U', 'N', N, KL+KU, AFB, LDAFB, WORK )IF( RPVGRW.EQ.ZERO ) THENRPVGRW = ONEELSERPVGRW = DLANGB( 'M', N, KL, KU, AB, LDAB, WORK ) / RPVGRWEND IF** Compute the reciprocal of the condition number of A.*CALL DGBCON( NORM, N, KL, KU, AFB, LDAFB, IPIV, ANORM, RCOND,$ WORK, IWORK, INFO )** Set INFO = N+1 if the matrix is singular to working precision.*IF( RCOND.LT.DLAMCH( 'Epsilon' ) )$ INFO = N + 1** Compute the solution matrix X.*CALL DLACPY( 'Full', N, NRHS, B, LDB, X, LDX )CALL DGBTRS( TRANS, N, KL, KU, NRHS, AFB, LDAFB, IPIV, X, LDX,$ INFO )** Use iterative refinement to improve the computed solution and* compute error bounds and backward error estimates for it.*CALL DGBRFS( TRANS, N, KL, KU, NRHS, AB, LDAB, AFB, LDAFB, IPIV,$ B, LDB, X, LDX, FERR, BERR, WORK, IWORK, INFO )** Transform the solution matrix X to a solution of the original* system.*IF( NOTRAN ) THENIF( COLEQU ) THENDO 110 J = 1, NRHSDO 100 I = 1, NX( I, J ) = C( I )*X( I, J )100 CONTINUE110 CONTINUEDO 120 J = 1, NRHSFERR( J ) = FERR( J ) / COLCND120 CONTINUEEND IFELSE IF( ROWEQU ) THENDO 140 J = 1, NRHSDO 130 I = 1, NX( I, J ) = R( I )*X( I, J )130 CONTINUE140 CONTINUEDO 150 J = 1, NRHSFERR( J ) = FERR( J ) / ROWCND150 CONTINUEEND IF*WORK( 1 ) = RPVGRWRETURN** End of DGBSVX*ENDSUBROUTINE DGEES( JOBVS, SORT, SELECT, N, A, LDA, SDIM, WR, WI,$ VS, LDVS, WORK, LWORK, BWORK, INFO )** -- LAPACK driver 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 JOBVS, SORTINTEGER INFO, LDA, LDVS, LWORK, N, SDIM* ..* .. Array Arguments ..LOGICAL BWORK( * )DOUBLE PRECISION A( LDA, * ), VS( LDVS, * ), WI( * ), WORK( * ),$ WR( * )* ..* .. Function Arguments ..LOGICAL SELECTEXTERNAL SELECT* ..** Purpose* =======** DGEES computes for an N-by-N real nonsymmetric matrix A, the* eigenvalues, the real Schur form T, and, optionally, the matrix of* Schur vectors Z. This gives the Schur factorization A = Z*T*(Z**T).** Optionally, it also orders the eigenvalues on the diagonal of the* real Schur form so that selected eigenvalues are at the top left.* The leading columns of Z then form an orthonormal basis for the* invariant subspace corresponding to the selected eigenvalues.** A matrix is in real Schur form if it is upper quasi-triangular with* 1-by-1 and 2-by-2 blocks. 2-by-2 blocks will be standardized in the* form* [ a b ]* [ c a ]** where b*c < 0. The eigenvalues of such a block are a +- sqrt(bc).** Arguments* =========** JOBVS (input) CHARACTER*1* = 'N': Schur vectors are not computed;* = 'V': Schur vectors are computed.** SORT (input) CHARACTER*1* Specifies whether or not to order the eigenvalues on the* diagonal of the Schur form.* = 'N': Eigenvalues are not ordered;* = 'S': Eigenvalues are ordered (see SELECT).** SELECT (input) LOGICAL FUNCTION of two DOUBLE PRECISION arguments* SELECT must be declared EXTERNAL in the calling subroutine.* If SORT = 'S', SELECT is used to select eigenvalues to sort* to the top left of the Schur form.* If SORT = 'N', SELECT is not referenced.* An eigenvalue WR(j)+sqrt(-1)*WI(j) is selected if* SELECT(WR(j),WI(j)) is true; i.e., if either one of a complex* conjugate pair of eigenvalues is selected, then both complex* eigenvalues are selected.* Note that a selected complex eigenvalue may no longer* satisfy SELECT(WR(j),WI(j)) = .TRUE. after ordering, since* ordering may change the value of complex eigenvalues* (especially if the eigenvalue is ill-conditioned); in this* case INFO is set to N+2 (see INFO below).** N (input) INTEGER* The order of the matrix A. N >= 0.** A (input/output) DOUBLE PRECISION array, dimension (LDA,N)* On entry, the N-by-N matrix A.* On exit, A has been overwritten by its real Schur form T.** LDA (input) INTEGER* The leading dimension of the array A. LDA >= max(1,N).** SDIM (output) INTEGER* If SORT = 'N', SDIM = 0.* If SORT = 'S', SDIM = number of eigenvalues (after sorting)* for which SELECT is true. (Complex conjugate* pairs for which SELECT is true for either* eigenvalue count as 2.)** WR (output) DOUBLE PRECISION array, dimension (N)* WI (output) DOUBLE PRECISION array, dimension (N)* WR and WI contain the real and imaginary parts,* respectively, of the computed eigenvalues in the same order* that they appear on the diagonal of the output Schur form T.* Complex conjugate pairs of eigenvalues will appear* consecutively with the eigenvalue having the positive* imaginary part first.** VS (output) DOUBLE PRECISION array, dimension (LDVS,N)* If JOBVS = 'V', VS contains the orthogonal matrix Z of Schur* vectors.* If JOBVS = 'N', VS is not referenced.** LDVS (input) INTEGER* The leading dimension of the array VS. LDVS >= 1; if* JOBVS = 'V', LDVS >= N.** WORK (workspace/output) DOUBLE PRECISION array, dimension (LWORK)* On exit, if INFO = 0, WORK(1) contains the optimal LWORK.** LWORK (input) INTEGER* The dimension of the array WORK. LWORK >= max(1,3*N).* For good performance, LWORK must generally be larger.** 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.** BWORK (workspace) LOGICAL array, dimension (N)* Not referenced if SORT = '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 QR algorithm failed to compute all the* eigenvalues; elements 1:ILO-1 and i+1:N of WR and WI* contain those eigenvalues which have converged; if* JOBVS = 'V', VS contains the matrix which reduces A* to its partially converged Schur form.* = N+1: the eigenvalues could not be reordered because some* eigenvalues were too close to separate (the problem* is very ill-conditioned);* = N+2: after reordering, roundoff changed values of some* complex eigenvalues so that leading eigenvalues in* the Schur form no longer satisfy SELECT=.TRUE. This* could also be caused by underflow due to scaling.** =====================================================================** .. Parameters ..DOUBLE PRECISION ZERO, ONEPARAMETER ( ZERO = 0.0D0, ONE = 1.0D0 )* ..* .. Local Scalars ..LOGICAL CURSL, LASTSL, LQUERY, LST2SL, SCALEA, WANTST,$ WANTVSINTEGER HSWORK, I, I1, I2, IBAL, ICOND, IERR, IEVAL,$ IHI, ILO, INXT, IP, ITAU, IWRK, K, MAXB,$ MAXWRK, MINWRKDOUBLE PRECISION ANRM, BIGNUM, CSCALE, EPS, S, SEP, SMLNUM* ..* .. Local Arrays ..INTEGER IDUM( 1 )DOUBLE PRECISION DUM( 1 )* ..* .. External Subroutines ..EXTERNAL DCOPY, DGEBAK, DGEBAL, DGEHRD, DHSEQR, DLACPY,$ DLASCL, DORGHR, DSWAP, DTRSEN, XERBLA* ..* .. External Functions ..LOGICAL LSAMEINTEGER ILAENVDOUBLE PRECISION DLAMCH, DLANGEEXTERNAL LSAME, ILAENV, DLAMCH, DLANGE* ..* .. Intrinsic Functions ..INTRINSIC MAX, MIN, SQRT* ..* .. Executable Statements ..** Test the input arguments*INFO = 0LQUERY = ( LWORK.EQ.-1 )WANTVS = LSAME( JOBVS, 'V' )WANTST = LSAME( SORT, 'S' )IF( ( .NOT.WANTVS ) .AND. ( .NOT.LSAME( JOBVS, 'N' ) ) ) THENINFO = -1ELSE IF( ( .NOT.WANTST ) .AND. ( .NOT.LSAME( SORT, 'N' ) ) ) THENINFO = -2ELSE IF( N.LT.0 ) THENINFO = -4ELSE IF( LDA.LT.MAX( 1, N ) ) THENINFO = -6ELSE IF( LDVS.LT.1 .OR. ( WANTVS .AND. LDVS.LT.N ) ) THENINFO = -11END IF** Compute workspace* (Note: Comments in the code beginning "Workspace:" describe the* minimal amount of workspace needed at that point in the code,* as well as the preferred amount for good performance.* NB refers to the optimal block size for the immediately* following subroutine, as returned by ILAENV.* HSWORK refers to the workspace preferred by DHSEQR, as* calculated below. HSWORK is computed assuming ILO=1 and IHI=N,* the worst case.)*MINWRK = 1IF( INFO.EQ.0 .AND. ( LWORK.GE.1 .OR. LQUERY ) ) THENMAXWRK = 2*N + N*ILAENV( 1, 'DGEHRD', ' ', N, 1, N, 0 )MINWRK = MAX( 1, 3*N )IF( .NOT.WANTVS ) THENMAXB = MAX( ILAENV( 8, 'DHSEQR', 'SN', N, 1, N, -1 ), 2 )K = MIN( MAXB, N, MAX( 2, ILAENV( 4, 'DHSEQR', 'SN', N, 1,$ N, -1 ) ) )HSWORK = MAX( K*( K+2 ), 2*N )MAXWRK = MAX( MAXWRK, N+HSWORK, 1 )ELSEMAXWRK = MAX( MAXWRK, 2*N+( N-1 )*$ ILAENV( 1, 'DORGHR', ' ', N, 1, N, -1 ) )MAXB = MAX( ILAENV( 8, 'DHSEQR', 'EN', N, 1, N, -1 ), 2 )K = MIN( MAXB, N, MAX( 2, ILAENV( 4, 'DHSEQR', 'EN', N, 1,$ N, -1 ) ) )HSWORK = MAX( K*( K+2 ), 2*N )MAXWRK = MAX( MAXWRK, N+HSWORK, 1 )END IFWORK( 1 ) = MAXWRKEND IFIF( LWORK.LT.MINWRK .AND. .NOT.LQUERY ) THENINFO = -13END IFIF( INFO.NE.0 ) THENCALL XERBLA( 'DGEES ', -INFO )RETURNELSE IF( LQUERY ) THENRETURNEND IF** Quick return if possible*IF( N.EQ.0 ) THENSDIM = 0RETURNEND IF** Get machine constants*EPS = DLAMCH( 'P' )SMLNUM = DLAMCH( 'S' )BIGNUM = ONE / SMLNUMCALL DLABAD( SMLNUM, BIGNUM )SMLNUM = SQRT( SMLNUM ) / EPSBIGNUM = ONE / SMLNUM** Scale A if max element outside range [SMLNUM,BIGNUM]*ANRM = DLANGE( 'M', N, N, A, LDA, DUM )SCALEA = .FALSE.IF( ANRM.GT.ZERO .AND. ANRM.LT.SMLNUM ) THENSCALEA = .TRUE.CSCALE = SMLNUMELSE IF( ANRM.GT.BIGNUM ) THENSCALEA = .TRUE.CSCALE = BIGNUMEND IFIF( SCALEA )$ CALL DLASCL( 'G', 0, 0, ANRM, CSCALE, N, N, A, LDA, IERR )** Permute the matrix to make it more nearly triangular* (Workspace: need N)*IBAL = 1CALL DGEBAL( 'P', N, A, LDA, ILO, IHI, WORK( IBAL ), IERR )** Reduce to upper Hessenberg form* (Workspace: need 3*N, prefer 2*N+N*NB)*ITAU = N + IBALIWRK = N + ITAUCALL DGEHRD( N, ILO, IHI, A, LDA, WORK( ITAU ), WORK( IWRK ),$ LWORK-IWRK+1, IERR )*IF( WANTVS ) THEN** Copy Householder vectors to VS*CALL DLACPY( 'L', N, N, A, LDA, VS, LDVS )** Generate orthogonal matrix in VS* (Workspace: need 3*N-1, prefer 2*N+(N-1)*NB)*CALL DORGHR( N, ILO, IHI, VS, LDVS, WORK( ITAU ), WORK( IWRK ),$ LWORK-IWRK+1, IERR )END IF*SDIM = 0** Perform QR iteration, accumulating Schur vectors in VS if desired* (Workspace: need N+1, prefer N+HSWORK (see comments) )*IWRK = ITAUCALL DHSEQR( 'S', JOBVS, N, ILO, IHI, A, LDA, WR, WI, VS, LDVS,$ WORK( IWRK ), LWORK-IWRK+1, IEVAL )IF( IEVAL.GT.0 )$ INFO = IEVAL** Sort eigenvalues if desired*IF( WANTST .AND. INFO.EQ.0 ) THENIF( SCALEA ) THENCALL DLASCL( 'G', 0, 0, CSCALE, ANRM, N, 1, WR, N, IERR )CALL DLASCL( 'G', 0, 0, CSCALE, ANRM, N, 1, WI, N, IERR )END IFDO 10 I = 1, NBWORK( I ) = SELECT( WR( I ), WI( I ) )10 CONTINUE** Reorder eigenvalues and transform Schur vectors* (Workspace: none needed)*CALL DTRSEN( 'N', JOBVS, BWORK, N, A, LDA, VS, LDVS, WR, WI,$ SDIM, S, SEP, WORK( IWRK ), LWORK-IWRK+1, IDUM, 1,$ ICOND )IF( ICOND.GT.0 )$ INFO = N + ICONDEND IF*IF( WANTVS ) THEN** Undo balancing* (Workspace: need N)*CALL DGEBAK( 'P', 'R', N, ILO, IHI, WORK( IBAL ), N, VS, LDVS,$ IERR )END IF*IF( SCALEA ) THEN** Undo scaling for the Schur form of A*CALL DLASCL( 'H', 0, 0, CSCALE, ANRM, N, N, A, LDA, IERR )CALL DCOPY( N, A, LDA+1, WR, 1 )IF( CSCALE.EQ.SMLNUM ) THEN** If scaling back towards underflow, adjust WI if an* offdiagonal element of a 2-by-2 block in the Schur form* underflows.*IF( IEVAL.GT.0 ) THENI1 = IEVAL + 1I2 = IHI - 1CALL DLASCL( 'G', 0, 0, CSCALE, ANRM, ILO-1, 1, WI,$ MAX( ILO-1, 1 ), IERR )ELSE IF( WANTST ) THENI1 = 1I2 = N - 1ELSEI1 = ILOI2 = IHI - 1END IFINXT = I1 - 1DO 20 I = I1, I2IF( I.LT.INXT )$ GO TO 20IF( WI( I ).EQ.ZERO ) THENINXT = I + 1ELSEIF( A( I+1, I ).EQ.ZERO ) THENWI( I ) = ZEROWI( I+1 ) = ZEROELSE IF( A( I+1, I ).NE.ZERO .AND. A( I, I+1 ).EQ.$ ZERO ) THENWI( I ) = ZEROWI( I+1 ) = ZEROIF( I.GT.1 )$ CALL DSWAP( I-1, A( 1, I ), 1, A( 1, I+1 ), 1 )IF( N.GT.I+1 )$ CALL DSWAP( N-I-1, A( I, I+2 ), LDA,$ A( I+1, I+2 ), LDA )CALL DSWAP( N, VS( 1, I ), 1, VS( 1, I+1 ), 1 )A( I, I+1 ) = A( I+1, I )A( I+1, I ) = ZEROEND IFINXT = I + 2END IF20 CONTINUEEND IF** Undo scaling for the imaginary part of the eigenvalues*CALL DLASCL( 'G', 0, 0, CSCALE, ANRM, N-IEVAL, 1,$ WI( IEVAL+1 ), MAX( N-IEVAL, 1 ), IERR )END IF*IF( WANTST .AND. INFO.EQ.0 ) THEN** Check if reordering successful*LASTSL = .TRUE.LST2SL = .TRUE.SDIM = 0IP = 0DO 30 I = 1, NCURSL = SELECT( WR( I ), WI( I ) )IF( WI( I ).EQ.ZERO ) THENIF( CURSL )$ SDIM = SDIM + 1IP = 0IF( CURSL .AND. .NOT.LASTSL )$ INFO = N + 2ELSEIF( IP.EQ.1 ) THEN** Last eigenvalue of conjugate pair*CURSL = CURSL .OR. LASTSLLASTSL = CURSLIF( CURSL )$ SDIM = SDIM + 2IP = -1IF( CURSL .AND. .NOT.LST2SL )$ INFO = N + 2ELSE** First eigenvalue of conjugate pair*IP = 1END IFEND IFLST2SL = LASTSLLASTSL = CURSL30 CONTINUEEND IF*WORK( 1 ) = MAXWRKRETURN** End of DGEES*ENDSUBROUTINE DGEESX( JOBVS, SORT, SELECT, SENSE, N, A, LDA, SDIM,$ WR, WI, VS, LDVS, RCONDE, RCONDV, WORK, LWORK,$ IWORK, LIWORK, BWORK, INFO )** -- LAPACK driver 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 JOBVS, SENSE, SORTINTEGER INFO, LDA, LDVS, LIWORK, LWORK, N, SDIMDOUBLE PRECISION RCONDE, RCONDV* ..* .. Array Arguments ..LOGICAL BWORK( * )INTEGER IWORK( * )DOUBLE PRECISION A( LDA, * ), VS( LDVS, * ), WI( * ), WORK( * ),$ WR( * )* ..* .. Function Arguments ..LOGICAL SELECTEXTERNAL SELECT* ..** Purpose* =======** DGEESX computes for an N-by-N real nonsymmetric matrix A, the* eigenvalues, the real Schur form T, and, optionally, the matrix of* Schur vectors Z. This gives the Schur factorization A = Z*T*(Z**T).** Optionally, it also orders the eigenvalues on the diagonal of the* real Schur form so that selected eigenvalues are at the top left;* computes a reciprocal condition number for the average of the* selected eigenvalues (RCONDE); and computes a reciprocal condition* number for the right invariant subspace corresponding to the* selected eigenvalues (RCONDV). The leading columns of Z form an* orthonormal basis for this invariant subspace.** For further explanation of the reciprocal condition numbers RCONDE* and RCONDV, see Section 4.10 of the LAPACK Users' Guide (where* these quantities are called s and sep respectively).** A real matrix is in real Schur form if it is upper quasi-triangular* with 1-by-1 and 2-by-2 blocks. 2-by-2 blocks will be standardized in* the form* [ a b ]* [ c a ]** where b*c < 0. The eigenvalues of such a block are a +- sqrt(bc).** Arguments* =========** JOBVS (input) CHARACTER*1* = 'N': Schur vectors are not computed;* = 'V': Schur vectors are computed.** SORT (input) CHARACTER*1* Specifies whether or not to order the eigenvalues on the* diagonal of the Schur form.* = 'N': Eigenvalues are not ordered;* = 'S': Eigenvalues are ordered (see SELECT).** SELECT (input) LOGICAL FUNCTION of two DOUBLE PRECISION arguments* SELECT must be declared EXTERNAL in the calling subroutine.* If SORT = 'S', SELECT is used to select eigenvalues to sort* to the top left of the Schur form.* If SORT = 'N', SELECT is not referenced.* An eigenvalue WR(j)+sqrt(-1)*WI(j) is selected if* SELECT(WR(j),WI(j)) is true; i.e., if either one of a* complex conjugate pair of eigenvalues is selected, then both* are. Note that a selected complex eigenvalue may no longer* satisfy SELECT(WR(j),WI(j)) = .TRUE. after ordering, since* ordering may change the value of complex eigenvalues* (especially if the eigenvalue is ill-conditioned); in this* case INFO may be set to N+3 (see INFO below).** SENSE (input) CHARACTER*1* Determines which reciprocal condition numbers are computed.* = 'N': None are computed;* = 'E': Computed for average of selected eigenvalues only;* = 'V': Computed for selected right invariant subspace only;* = 'B': Computed for both.* If SENSE = 'E', 'V' or 'B', SORT must equal 'S'.** N (input) INTEGER* The order of the matrix A. N >= 0.** A (input/output) DOUBLE PRECISION array, dimension (LDA, N)* On entry, the N-by-N matrix A.* On exit, A is overwritten by its real Schur form T.** LDA (input) INTEGER* The leading dimension of the array A. LDA >= max(1,N).** SDIM (output) INTEGER* If SORT = 'N', SDIM = 0.* If SORT = 'S', SDIM = number of eigenvalues (after sorting)* for which SELECT is true. (Complex conjugate* pairs for which SELECT is true for either* eigenvalue count as 2.)** WR (output) DOUBLE PRECISION array, dimension (N)* WI (output) DOUBLE PRECISION array, dimension (N)* WR and WI contain the real and imaginary parts, respectively,* of the computed eigenvalues, in the same order that they* appear on the diagonal of the output Schur form T. Complex* conjugate pairs of eigenvalues appear consecutively with the* eigenvalue having the positive imaginary part first.** VS (output) DOUBLE PRECISION array, dimension (LDVS,N)* If JOBVS = 'V', VS contains the orthogonal matrix Z of Schur* vectors.* If JOBVS = 'N', VS is not referenced.** LDVS (input) INTEGER* The leading dimension of the array VS. LDVS >= 1, and if* JOBVS = 'V', LDVS >= N.** RCONDE (output) DOUBLE PRECISION* If SENSE = 'E' or 'B', RCONDE contains the reciprocal* condition number for the average of the selected eigenvalues.* Not referenced if SENSE = 'N' or 'V'.** RCONDV (output) DOUBLE PRECISION* If SENSE = 'V' or 'B', RCONDV contains the reciprocal* condition number for the selected right invariant subspace.* Not referenced if SENSE = 'N' or 'E'.** 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,3*N).* Also, if SENSE = 'E' or 'V' or 'B',* LWORK >= N+2*SDIM*(N-SDIM), where SDIM is the number of* selected eigenvalues computed by this routine. Note that* N+2*SDIM*(N-SDIM) <= N+N*N/2.* For good performance, LWORK must generally be larger.** IWORK (workspace/output) INTEGER array, dimension (LIWORK)* Not referenced if SENSE = 'N' or 'E'.* On exit, if INFO = 0, IWORK(1) returns the optimal LIWORK.** LIWORK (input) INTEGER* The dimension of the array IWORK.* LIWORK >= 1; if SENSE = 'V' or 'B', LIWORK >= SDIM*(N-SDIM).** BWORK (workspace) LOGICAL array, dimension (N)* Not referenced if SORT = '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 QR algorithm failed to compute all the* eigenvalues; elements 1:ILO-1 and i+1:N of WR and WI* contain those eigenvalues which have converged; if* JOBVS = 'V', VS contains the transformation which* reduces A to its partially converged Schur form.* = N+1: the eigenvalues could not be reordered because some* eigenvalues were too close to separate (the problem* is very ill-conditioned);* = N+2: after reordering, roundoff changed values of some* complex eigenvalues so that leading eigenvalues in* the Schur form no longer satisfy SELECT=.TRUE. This* could also be caused by underflow due to scaling.** =====================================================================** .. Parameters ..DOUBLE PRECISION ZERO, ONEPARAMETER ( ZERO = 0.0D0, ONE = 1.0D0 )* ..* .. Local Scalars ..LOGICAL CURSL, LASTSL, LST2SL, SCALEA, WANTSB, WANTSE,$ WANTSN, WANTST, WANTSV, WANTVSINTEGER HSWORK, I, I1, I2, IBAL, ICOND, IERR, IEVAL,$ IHI, ILO, INXT, IP, ITAU, IWRK, K, MAXB,$ MAXWRK, MINWRKDOUBLE PRECISION ANRM, BIGNUM, CSCALE, EPS, SMLNUM* ..* .. Local Arrays ..DOUBLE PRECISION DUM( 1 )* ..* .. External Subroutines ..EXTERNAL DCOPY, DGEBAK, DGEBAL, DGEHRD, DHSEQR, DLACPY,$ DLASCL, DORGHR, DSWAP, DTRSEN, XERBLA* ..* .. External Functions ..LOGICAL LSAMEINTEGER ILAENVDOUBLE PRECISION DLAMCH, DLANGEEXTERNAL LSAME, ILAENV, DLAMCH, DLANGE* ..* .. Intrinsic Functions ..INTRINSIC MAX, MIN, SQRT* ..* .. Executable Statements ..** Test the input arguments*INFO = 0WANTVS = LSAME( JOBVS, 'V' )WANTST = LSAME( SORT, 'S' )WANTSN = LSAME( SENSE, 'N' )WANTSE = LSAME( SENSE, 'E' )WANTSV = LSAME( SENSE, 'V' )WANTSB = LSAME( SENSE, 'B' )IF( ( .NOT.WANTVS ) .AND. ( .NOT.LSAME( JOBVS, 'N' ) ) ) THENINFO = -1ELSE IF( ( .NOT.WANTST ) .AND. ( .NOT.LSAME( SORT, 'N' ) ) ) THENINFO = -2ELSE IF( .NOT.( WANTSN .OR. WANTSE .OR. WANTSV .OR. WANTSB ) .OR.$ ( .NOT.WANTST .AND. .NOT.WANTSN ) ) THENINFO = -4ELSE IF( N.LT.0 ) THENINFO = -5ELSE IF( LDA.LT.MAX( 1, N ) ) THENINFO = -7ELSE IF( LDVS.LT.1 .OR. ( WANTVS .AND. LDVS.LT.N ) ) THENINFO = -12END IF** Compute workspace* (Note: Comments in the code beginning "RWorkspace:" describe the* minimal amount of real workspace needed at that point in the* code, as well as the preferred amount for good performance.* IWorkspace refers to integer workspace.* NB refers to the optimal block size for the immediately* following subroutine, as returned by ILAENV.* HSWORK refers to the workspace preferred by DHSEQR, as* calculated below. HSWORK is computed assuming ILO=1 and IHI=N,* the worst case.* If SENSE = 'E', 'V' or 'B', then the amount of workspace needed* depends on SDIM, which is computed by the routine DTRSEN later* in the code.)*MINWRK = 1IF( INFO.EQ.0 .AND. LWORK.GE.1 ) THENMAXWRK = 2*N + N*ILAENV( 1, 'DGEHRD', ' ', N, 1, N, 0 )MINWRK = MAX( 1, 3*N )IF( .NOT.WANTVS ) THENMAXB = MAX( ILAENV( 8, 'DHSEQR', 'SN', N, 1, N, -1 ), 2 )K = MIN( MAXB, N, MAX( 2, ILAENV( 4, 'DHSEQR', 'SN', N, 1,$ N, -1 ) ) )HSWORK = MAX( K*( K+2 ), 2*N )MAXWRK = MAX( MAXWRK, N+HSWORK, 1 )ELSEMAXWRK = MAX( MAXWRK, 2*N+( N-1 )*$ ILAENV( 1, 'DORGHR', ' ', N, 1, N, -1 ) )MAXB = MAX( ILAENV( 8, 'DHSEQR', 'SV', N, 1, N, -1 ), 2 )K = MIN( MAXB, N, MAX( 2, ILAENV( 4, 'DHSEQR', 'SV', N, 1,$ N, -1 ) ) )HSWORK = MAX( K*( K+2 ), 2*N )MAXWRK = MAX( MAXWRK, N+HSWORK, 1 )END IFWORK( 1 ) = MAXWRKEND IFIF( LWORK.LT.MINWRK ) THENINFO = -16END IFIF( LIWORK.LT.1 ) THENINFO = -18END IFIF( INFO.NE.0 ) THENCALL XERBLA( 'DGEESX', -INFO )RETURNEND IF** Quick return if possible*IF( N.EQ.0 ) THENSDIM = 0RETURNEND IF** Get machine constants*EPS = DLAMCH( 'P' )SMLNUM = DLAMCH( 'S' )BIGNUM = ONE / SMLNUMCALL DLABAD( SMLNUM, BIGNUM )SMLNUM = SQRT( SMLNUM ) / EPSBIGNUM = ONE / SMLNUM** Scale A if max element outside range [SMLNUM,BIGNUM]*ANRM = DLANGE( 'M', N, N, A, LDA, DUM )SCALEA = .FALSE.IF( ANRM.GT.ZERO .AND. ANRM.LT.SMLNUM ) THENSCALEA = .TRUE.CSCALE = SMLNUMELSE IF( ANRM.GT.BIGNUM ) THENSCALEA = .TRUE.CSCALE = BIGNUMEND IFIF( SCALEA )$ CALL DLASCL( 'G', 0, 0, ANRM, CSCALE, N, N, A, LDA, IERR )** Permute the matrix to make it more nearly triangular* (RWorkspace: need N)*IBAL = 1CALL DGEBAL( 'P', N, A, LDA, ILO, IHI, WORK( IBAL ), IERR )** Reduce to upper Hessenberg form* (RWorkspace: need 3*N, prefer 2*N+N*NB)*ITAU = N + IBALIWRK = N + ITAUCALL DGEHRD( N, ILO, IHI, A, LDA, WORK( ITAU ), WORK( IWRK ),$ LWORK-IWRK+1, IERR )*IF( WANTVS ) THEN** Copy Householder vectors to VS*CALL DLACPY( 'L', N, N, A, LDA, VS, LDVS )** Generate orthogonal matrix in VS* (RWorkspace: need 3*N-1, prefer 2*N+(N-1)*NB)*CALL DORGHR( N, ILO, IHI, VS, LDVS, WORK( ITAU ), WORK( IWRK ),$ LWORK-IWRK+1, IERR )END IF*SDIM = 0** Perform QR iteration, accumulating Schur vectors in VS if desired* (RWorkspace: need N+1, prefer N+HSWORK (see comments) )*IWRK = ITAUCALL DHSEQR( 'S', JOBVS, N, ILO, IHI, A, LDA, WR, WI, VS, LDVS,$ WORK( IWRK ), LWORK-IWRK+1, IEVAL )IF( IEVAL.GT.0 )$ INFO = IEVAL** Sort eigenvalues if desired*IF( WANTST .AND. INFO.EQ.0 ) THENIF( SCALEA ) THENCALL DLASCL( 'G', 0, 0, CSCALE, ANRM, N, 1, WR, N, IERR )CALL DLASCL( 'G', 0, 0, CSCALE, ANRM, N, 1, WI, N, IERR )END IFDO 10 I = 1, NBWORK( I ) = SELECT( WR( I ), WI( I ) )10 CONTINUE** Reorder eigenvalues, transform Schur vectors, and compute* reciprocal condition numbers* (RWorkspace: if SENSE is not 'N', need N+2*SDIM*(N-SDIM)* otherwise, need N )* (IWorkspace: if SENSE is 'V' or 'B', need SDIM*(N-SDIM)* otherwise, need 0 )*CALL DTRSEN( SENSE, JOBVS, BWORK, N, A, LDA, VS, LDVS, WR, WI,$ SDIM, RCONDE, RCONDV, WORK( IWRK ), LWORK-IWRK+1,$ IWORK, LIWORK, ICOND )IF( .NOT.WANTSN )$ MAXWRK = MAX( MAXWRK, N+2*SDIM*( N-SDIM ) )IF( ICOND.EQ.-15 ) THEN** Not enough real workspace*INFO = -16ELSE IF( ICOND.EQ.-17 ) THEN** Not enough integer workspace*INFO = -18ELSE IF( ICOND.GT.0 ) THEN** DTRSEN failed to reorder or to restore standard Schur form*INFO = ICOND + NEND IFEND IF*IF( WANTVS ) THEN** Undo balancing* (RWorkspace: need N)*CALL DGEBAK( 'P', 'R', N, ILO, IHI, WORK( IBAL ), N, VS, LDVS,$ IERR )END IF*IF( SCALEA ) THEN** Undo scaling for the Schur form of A*CALL DLASCL( 'H', 0, 0, CSCALE, ANRM, N, N, A, LDA, IERR )CALL DCOPY( N, A, LDA+1, WR, 1 )IF( ( WANTSV .OR. WANTSB ) .AND. INFO.EQ.0 ) THENDUM( 1 ) = RCONDVCALL DLASCL( 'G', 0, 0, CSCALE, ANRM, 1, 1, DUM, 1, IERR )RCONDV = DUM( 1 )END IFIF( CSCALE.EQ.SMLNUM ) THEN** If scaling back towards underflow, adjust WI if an* offdiagonal element of a 2-by-2 block in the Schur form* underflows.*IF( IEVAL.GT.0 ) THENI1 = IEVAL + 1I2 = IHI - 1CALL DLASCL( 'G', 0, 0, CSCALE, ANRM, ILO-1, 1, WI, N,$ IERR )ELSE IF( WANTST ) THENI1 = 1I2 = N - 1ELSEI1 = ILOI2 = IHI - 1END IFINXT = I1 - 1DO 20 I = I1, I2IF( I.LT.INXT )$ GO TO 20IF( WI( I ).EQ.ZERO ) THENINXT = I + 1ELSEIF( A( I+1, I ).EQ.ZERO ) THENWI( I ) = ZEROWI( I+1 ) = ZEROELSE IF( A( I+1, I ).NE.ZERO .AND. A( I, I+1 ).EQ.$ ZERO ) THENWI( I ) = ZEROWI( I+1 ) = ZEROIF( I.GT.1 )$ CALL DSWAP( I-1, A( 1, I ), 1, A( 1, I+1 ), 1 )IF( N.GT.I+1 )$ CALL DSWAP( N-I-1, A( I, I+2 ), LDA,$ A( I+1, I+2 ), LDA )CALL DSWAP( N, VS( 1, I ), 1, VS( 1, I+1 ), 1 )A( I, I+1 ) = A( I+1, I )A( I+1, I ) = ZEROEND IFINXT = I + 2END IF20 CONTINUEEND IFCALL DLASCL( 'G', 0, 0, CSCALE, ANRM, N-IEVAL, 1,$ WI( IEVAL+1 ), MAX( N-IEVAL, 1 ), IERR )END IF*IF( WANTST .AND. INFO.EQ.0 ) THEN** Check if reordering successful*LASTSL = .TRUE.LST2SL = .TRUE.SDIM = 0IP = 0DO 30 I = 1, NCURSL = SELECT( WR( I ), WI( I ) )IF( WI( I ).EQ.ZERO ) THENIF( CURSL )$ SDIM = SDIM + 1IP = 0IF( CURSL .AND. .NOT.LASTSL )$ INFO = N + 2ELSEIF( IP.EQ.1 ) THEN** Last eigenvalue of conjugate pair*CURSL = CURSL .OR. LASTSLLASTSL = CURSLIF( CURSL )$ SDIM = SDIM + 2IP = -1IF( CURSL .AND. .NOT.LST2SL )$ INFO = N + 2ELSE** First eigenvalue of conjugate pair*IP = 1END IFEND IFLST2SL = LASTSLLASTSL = CURSL30 CONTINUEEND IF*WORK( 1 ) = MAXWRKIF( WANTSV .OR. WANTSB ) THENIWORK( 1 ) = SDIM*( N-SDIM )ELSEIWORK( 1 ) = 1END IF*RETURN** End of DGEESX*ENDSUBROUTINE DGEEV( JOBVL, JOBVR, N, A, LDA, WR, WI, VL, LDVL, VR,$ LDVR, WORK, LWORK, INFO )** -- LAPACK driver routine (version 3.0) --* Univ. of Tennessee, Univ. of California Berkeley, NAG Ltd.,* Courant Institute, Argonne National Lab, and Rice University* December 8, 1999** .. Scalar Arguments ..CHARACTER JOBVL, JOBVRINTEGER INFO, LDA, LDVL, LDVR, LWORK, N* ..* .. Array Arguments ..DOUBLE PRECISION A( LDA, * ), VL( LDVL, * ), VR( LDVR, * ),$ WI( * ), WORK( * ), WR( * )* ..** Purpose* =======** DGEEV computes for an N-by-N real nonsymmetric matrix A, the* eigenvalues and, optionally, the left and/or right eigenvectors.** The right eigenvector v(j) of A satisfies* A * v(j) = lambda(j) * v(j)* where lambda(j) is its eigenvalue.* The left eigenvector u(j) of A satisfies* u(j)**H * A = lambda(j) * u(j)**H* where u(j)**H denotes the conjugate transpose of u(j).** The computed eigenvectors are normalized to have Euclidean norm* equal to 1 and largest component real.** Arguments* =========** JOBVL (input) CHARACTER*1* = 'N': left eigenvectors of A are not computed;* = 'V': left eigenvectors of A are computed.** JOBVR (input) CHARACTER*1* = 'N': right eigenvectors of A are not computed;* = 'V': right eigenvectors of A are computed.** N (input) INTEGER* The order of the matrix A. N >= 0.** A (input/output) DOUBLE PRECISION array, dimension (LDA,N)* On entry, the N-by-N matrix A.* On exit, A has been overwritten.** LDA (input) INTEGER* The leading dimension of the array A. LDA >= max(1,N).** WR (output) DOUBLE PRECISION array, dimension (N)* WI (output) DOUBLE PRECISION array, dimension (N)* WR and WI contain the real and imaginary parts,* respectively, of the computed eigenvalues. Complex* conjugate pairs of eigenvalues appear consecutively* with the eigenvalue having the positive imaginary part* first.** VL (output) DOUBLE PRECISION array, dimension (LDVL,N)* If JOBVL = 'V', the left eigenvectors u(j) are stored one* after another in the columns of VL, in the same order* as their eigenvalues.* If JOBVL = 'N', VL is not referenced.* If the j-th eigenvalue is real, then u(j) = VL(:,j),* the j-th column of VL.* If the j-th and (j+1)-st eigenvalues form a complex* conjugate pair, then u(j) = VL(:,j) + i*VL(:,j+1) and* u(j+1) = VL(:,j) - i*VL(:,j+1).** LDVL (input) INTEGER* The leading dimension of the array VL. LDVL >= 1; if* JOBVL = 'V', LDVL >= N.** VR (output) DOUBLE PRECISION array, dimension (LDVR,N)* If JOBVR = 'V', the right eigenvectors v(j) are stored one* after another in the columns of VR, in the same order* as their eigenvalues.* If JOBVR = 'N', VR is not referenced.* If the j-th eigenvalue is real, then v(j) = VR(:,j),* the j-th column of VR.* If the j-th and (j+1)-st eigenvalues form a complex* conjugate pair, then v(j) = VR(:,j) + i*VR(:,j+1) and* v(j+1) = VR(:,j) - i*VR(:,j+1).** LDVR (input) INTEGER* The leading dimension of the array VR. LDVR >= 1; if* JOBVR = 'V', LDVR >= 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 >= max(1,3*N), and* if JOBVL = 'V' or JOBVR = 'V', LWORK >= 4*N. For good* performance, LWORK must generally be larger.** 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, the QR algorithm failed to compute all the* eigenvalues, and no eigenvectors have been computed;* elements i+1:N of WR and WI contain eigenvalues which* have converged.** =====================================================================** .. Parameters ..DOUBLE PRECISION ZERO, ONEPARAMETER ( ZERO = 0.0D0, ONE = 1.0D0 )* ..* .. Local Scalars ..LOGICAL LQUERY, SCALEA, WANTVL, WANTVRCHARACTER SIDEINTEGER HSWORK, I, IBAL, IERR, IHI, ILO, ITAU, IWRK, K,$ MAXB, MAXWRK, MINWRK, NOUTDOUBLE PRECISION ANRM, BIGNUM, CS, CSCALE, EPS, R, SCL, SMLNUM,$ SN* ..* .. Local Arrays ..LOGICAL SELECT( 1 )DOUBLE PRECISION DUM( 1 )* ..* .. External Subroutines ..EXTERNAL DGEBAK, DGEBAL, DGEHRD, DHSEQR, DLACPY, DLARTG,$ DLASCL, DORGHR, DROT, DSCAL, DTREVC, XERBLA* ..* .. External Functions ..LOGICAL LSAMEINTEGER IDAMAX, ILAENVDOUBLE PRECISION DLAMCH, DLANGE, DLAPY2, DNRM2EXTERNAL LSAME, IDAMAX, ILAENV, DLAMCH, DLANGE, DLAPY2,$ DNRM2* ..* .. Intrinsic Functions ..INTRINSIC MAX, MIN, SQRT* ..* .. Executable Statements ..** Test the input arguments*INFO = 0LQUERY = ( LWORK.EQ.-1 )WANTVL = LSAME( JOBVL, 'V' )WANTVR = LSAME( JOBVR, 'V' )IF( ( .NOT.WANTVL ) .AND. ( .NOT.LSAME( JOBVL, 'N' ) ) ) THENINFO = -1ELSE IF( ( .NOT.WANTVR ) .AND. ( .NOT.LSAME( JOBVR, 'N' ) ) ) THENINFO = -2ELSE IF( N.LT.0 ) THENINFO = -3ELSE IF( LDA.LT.MAX( 1, N ) ) THENINFO = -5ELSE IF( LDVL.LT.1 .OR. ( WANTVL .AND. LDVL.LT.N ) ) THENINFO = -9ELSE IF( LDVR.LT.1 .OR. ( WANTVR .AND. LDVR.LT.N ) ) THENINFO = -11END IF** Compute workspace* (Note: Comments in the code beginning "Workspace:" describe the* minimal amount of workspace needed at that point in the code,* as well as the preferred amount for good performance.* NB refers to the optimal block size for the immediately* following subroutine, as returned by ILAENV.* HSWORK refers to the workspace preferred by DHSEQR, as* calculated below. HSWORK is computed assuming ILO=1 and IHI=N,* the worst case.)*MINWRK = 1IF( INFO.EQ.0 .AND. ( LWORK.GE.1 .OR. LQUERY ) ) THENMAXWRK = 2*N + N*ILAENV( 1, 'DGEHRD', ' ', N, 1, N, 0 )IF( ( .NOT.WANTVL ) .AND. ( .NOT.WANTVR ) ) THENMINWRK = MAX( 1, 3*N )MAXB = MAX( ILAENV( 8, 'DHSEQR', 'EN', N, 1, N, -1 ), 2 )K = MIN( MAXB, N, MAX( 2, ILAENV( 4, 'DHSEQR', 'EN', N, 1,$ N, -1 ) ) )HSWORK = MAX( K*( K+2 ), 2*N )MAXWRK = MAX( MAXWRK, N+1, N+HSWORK )ELSEMINWRK = MAX( 1, 4*N )MAXWRK = MAX( MAXWRK, 2*N+( N-1 )*$ ILAENV( 1, 'DORGHR', ' ', N, 1, N, -1 ) )MAXB = MAX( ILAENV( 8, 'DHSEQR', 'SV', N, 1, N, -1 ), 2 )K = MIN( MAXB, N, MAX( 2, ILAENV( 4, 'DHSEQR', 'SV', N, 1,$ N, -1 ) ) )HSWORK = MAX( K*( K+2 ), 2*N )MAXWRK = MAX( MAXWRK, N+1, N+HSWORK )MAXWRK = MAX( MAXWRK, 4*N )END IFWORK( 1 ) = MAXWRKEND IFIF( LWORK.LT.MINWRK .AND. .NOT.LQUERY ) THENINFO = -13END IFIF( INFO.NE.0 ) THENCALL XERBLA( 'DGEEV ', -INFO )RETURNELSE IF( LQUERY ) THENRETURNEND IF** Quick return if possible*IF( N.EQ.0 )$ RETURN** Get machine constants*EPS = DLAMCH( 'P' )SMLNUM = DLAMCH( 'S' )BIGNUM = ONE / SMLNUMCALL DLABAD( SMLNUM, BIGNUM )SMLNUM = SQRT( SMLNUM ) / EPSBIGNUM = ONE / SMLNUM** Scale A if max element outside range [SMLNUM,BIGNUM]*ANRM = DLANGE( 'M', N, N, A, LDA, DUM )SCALEA = .FALSE.IF( ANRM.GT.ZERO .AND. ANRM.LT.SMLNUM ) THENSCALEA = .TRUE.CSCALE = SMLNUMELSE IF( ANRM.GT.BIGNUM ) THENSCALEA = .TRUE.CSCALE = BIGNUMEND IFIF( SCALEA )$ CALL DLASCL( 'G', 0, 0, ANRM, CSCALE, N, N, A, LDA, IERR )** Balance the matrix* (Workspace: need N)*IBAL = 1CALL DGEBAL( 'B', N, A, LDA, ILO, IHI, WORK( IBAL ), IERR )** Reduce to upper Hessenberg form* (Workspace: need 3*N, prefer 2*N+N*NB)*ITAU = IBAL + NIWRK = ITAU + NCALL DGEHRD( N, ILO, IHI, A, LDA, WORK( ITAU ), WORK( IWRK ),$ LWORK-IWRK+1, IERR )*IF( WANTVL ) THEN** Want left eigenvectors* Copy Householder vectors to VL*SIDE = 'L'CALL DLACPY( 'L', N, N, A, LDA, VL, LDVL )** Generate orthogonal matrix in VL* (Workspace: need 3*N-1, prefer 2*N+(N-1)*NB)*CALL DORGHR( N, ILO, IHI, VL, LDVL, WORK( ITAU ), WORK( IWRK ),$ LWORK-IWRK+1, IERR )** Perform QR iteration, accumulating Schur vectors in VL* (Workspace: need N+1, prefer N+HSWORK (see comments) )*IWRK = ITAUCALL DHSEQR( 'S', 'V', N, ILO, IHI, A, LDA, WR, WI, VL, LDVL,$ WORK( IWRK ), LWORK-IWRK+1, INFO )*IF( WANTVR ) THEN** Want left and right eigenvectors* Copy Schur vectors to VR*SIDE = 'B'CALL DLACPY( 'F', N, N, VL, LDVL, VR, LDVR )END IF*ELSE IF( WANTVR ) THEN** Want right eigenvectors* Copy Householder vectors to VR*SIDE = 'R'CALL DLACPY( 'L', N, N, A, LDA, VR, LDVR )** Generate orthogonal matrix in VR* (Workspace: need 3*N-1, prefer 2*N+(N-1)*NB)*CALL DORGHR( N, ILO, IHI, VR, LDVR, WORK( ITAU ), WORK( IWRK ),$ LWORK-IWRK+1, IERR )** Perform QR iteration, accumulating Schur vectors in VR* (Workspace: need N+1, prefer N+HSWORK (see comments) )*IWRK = ITAUCALL DHSEQR( 'S', 'V', N, ILO, IHI, A, LDA, WR, WI, VR, LDVR,$ WORK( IWRK ), LWORK-IWRK+1, INFO )*ELSE** Compute eigenvalues only* (Workspace: need N+1, prefer N+HSWORK (see comments) )*IWRK = ITAUCALL DHSEQR( 'E', 'N', N, ILO, IHI, A, LDA, WR, WI, VR, LDVR,$ WORK( IWRK ), LWORK-IWRK+1, INFO )END IF** If INFO > 0 from DHSEQR, then quit*IF( INFO.GT.0 )$ GO TO 50*IF( WANTVL .OR. WANTVR ) THEN** Compute left and/or right eigenvectors* (Workspace: need 4*N)*CALL DTREVC( SIDE, 'B', SELECT, N, A, LDA, VL, LDVL, VR, LDVR,$ N, NOUT, WORK( IWRK ), IERR )END IF*IF( WANTVL ) THEN** Undo balancing of left eigenvectors* (Workspace: need N)*CALL DGEBAK( 'B', 'L', N, ILO, IHI, WORK( IBAL ), N, VL, LDVL,$ IERR )** Normalize left eigenvectors and make largest component real*DO 20 I = 1, NIF( WI( I ).EQ.ZERO ) THENSCL = ONE / DNRM2( N, VL( 1, I ), 1 )CALL DSCAL( N, SCL, VL( 1, I ), 1 )ELSE IF( WI( I ).GT.ZERO ) THENSCL = ONE / DLAPY2( DNRM2( N, VL( 1, I ), 1 ),$ DNRM2( N, VL( 1, I+1 ), 1 ) )CALL DSCAL( N, SCL, VL( 1, I ), 1 )CALL DSCAL( N, SCL, VL( 1, I+1 ), 1 )DO 10 K = 1, NWORK( IWRK+K-1 ) = VL( K, I )**2 + VL( K, I+1 )**210 CONTINUEK = IDAMAX( N, WORK( IWRK ), 1 )CALL DLARTG( VL( K, I ), VL( K, I+1 ), CS, SN, R )CALL DROT( N, VL( 1, I ), 1, VL( 1, I+1 ), 1, CS, SN )VL( K, I+1 ) = ZEROEND IF20 CONTINUEEND IF*IF( WANTVR ) THEN** Undo balancing of right eigenvectors* (Workspace: need N)*CALL DGEBAK( 'B', 'R', N, ILO, IHI, WORK( IBAL ), N, VR, LDVR,$ IERR )** Normalize right eigenvectors and make largest component real*DO 40 I = 1, NIF( WI( I ).EQ.ZERO ) THENSCL = ONE / DNRM2( N, VR( 1, I ), 1 )CALL DSCAL( N, SCL, VR( 1, I ), 1 )ELSE IF( WI( I ).GT.ZERO ) THENSCL = ONE / DLAPY2( DNRM2( N, VR( 1, I ), 1 ),$ DNRM2( N, VR( 1, I+1 ), 1 ) )CALL DSCAL( N, SCL, VR( 1, I ), 1 )CALL DSCAL( N, SCL, VR( 1, I+1 ), 1 )DO 30 K = 1, NWORK( IWRK+K-1 ) = VR( K, I )**2 + VR( K, I+1 )**230 CONTINUEK = IDAMAX( N, WORK( IWRK ), 1 )CALL DLARTG( VR( K, I ), VR( K, I+1 ), CS, SN, R )CALL DROT( N, VR( 1, I ), 1, VR( 1, I+1 ), 1, CS, SN )VR( K, I+1 ) = ZEROEND IF40 CONTINUEEND IF** Undo scaling if necessary*50 CONTINUEIF( SCALEA ) THENCALL DLASCL( 'G', 0, 0, CSCALE, ANRM, N-INFO, 1, WR( INFO+1 ),$ MAX( N-INFO, 1 ), IERR )CALL DLASCL( 'G', 0, 0, CSCALE, ANRM, N-INFO, 1, WI( INFO+1 ),$ MAX( N-INFO, 1 ), IERR )IF( INFO.GT.0 ) THENCALL DLASCL( 'G', 0, 0, CSCALE, ANRM, ILO-1, 1, WR, N,$ IERR )CALL DLASCL( 'G', 0, 0, CSCALE, ANRM, ILO-1, 1, WI, N,$ IERR )END IFEND IF*WORK( 1 ) = MAXWRKRETURN** End of DGEEV*ENDSUBROUTINE DGEEVX( BALANC, JOBVL, JOBVR, SENSE, N, A, LDA, WR, WI,$ VL, LDVL, VR, LDVR, ILO, IHI, SCALE, ABNRM,$ RCONDE, RCONDV, WORK, LWORK, IWORK, INFO )** -- LAPACK driver 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 BALANC, JOBVL, JOBVR, SENSEINTEGER IHI, ILO, INFO, LDA, LDVL, LDVR, LWORK, NDOUBLE PRECISION ABNRM* ..* .. Array Arguments ..INTEGER IWORK( * )DOUBLE PRECISION A( LDA, * ), RCONDE( * ), RCONDV( * ),$ SCALE( * ), VL( LDVL, * ), VR( LDVR, * ),$ WI( * ), WORK( * ), WR( * )* ..** Purpose* =======** DGEEVX computes for an N-by-N real nonsymmetric matrix A, the* eigenvalues and, optionally, the left and/or right eigenvectors.** Optionally also, it computes a balancing transformation to improve* the conditioning of the eigenvalues and eigenvectors (ILO, IHI,* SCALE, and ABNRM), reciprocal condition numbers for the eigenvalues* (RCONDE), and reciprocal condition numbers for the right* eigenvectors (RCONDV).** The right eigenvector v(j) of A satisfies* A * v(j) = lambda(j) * v(j)* where lambda(j) is its eigenvalue.* The left eigenvector u(j) of A satisfies* u(j)**H * A = lambda(j) * u(j)**H* where u(j)**H denotes the conjugate transpose of u(j).** The computed eigenvectors are normalized to have Euclidean norm* equal to 1 and largest component real.** Balancing a matrix means permuting the rows and columns to make it* more nearly upper triangular, and applying a diagonal similarity* transformation D * A * D**(-1), where D is a diagonal matrix, to* make its rows and columns closer in norm and the condition numbers* of its eigenvalues and eigenvectors smaller. The computed* reciprocal condition numbers correspond to the balanced matrix.* Permuting rows and columns will not change the condition numbers* (in exact arithmetic) but diagonal scaling will. For further* explanation of balancing, see section 4.10.2 of the LAPACK* Users' Guide.** Arguments* =========** BALANC (input) CHARACTER*1* Indicates how the input matrix should be diagonally scaled* and/or permuted to improve the conditioning of its* eigenvalues.* = 'N': Do not diagonally scale or permute;* = 'P': Perform permutations to make the matrix more nearly* upper triangular. Do not diagonally scale;* = 'S': Diagonally scale the matrix, i.e. replace A by* D*A*D**(-1), where D is a diagonal matrix chosen* to make the rows and columns of A more equal in* norm. Do not permute;* = 'B': Both diagonally scale and permute A.** Computed reciprocal condition numbers will be for the matrix* after balancing and/or permuting. Permuting does not change* condition numbers (in exact arithmetic), but balancing does.** JOBVL (input) CHARACTER*1* = 'N': left eigenvectors of A are not computed;* = 'V': left eigenvectors of A are computed.* If SENSE = 'E' or 'B', JOBVL must = 'V'.** JOBVR (input) CHARACTER*1* = 'N': right eigenvectors of A are not computed;* = 'V': right eigenvectors of A are computed.* If SENSE = 'E' or 'B', JOBVR must = 'V'.** SENSE (input) CHARACTER*1* Determines which reciprocal condition numbers are computed.* = 'N': None are computed;* = 'E': Computed for eigenvalues only;* = 'V': Computed for right eigenvectors only;* = 'B': Computed for eigenvalues and right eigenvectors.** If SENSE = 'E' or 'B', both left and right eigenvectors* must also be computed (JOBVL = 'V' and JOBVR = 'V').** N (input) INTEGER* The order of the matrix A. N >= 0.** A (input/output) DOUBLE PRECISION array, dimension (LDA,N)* On entry, the N-by-N matrix A.* On exit, A has been overwritten. If JOBVL = 'V' or* JOBVR = 'V', A contains the real Schur form of the balanced* version of the input matrix A.** LDA (input) INTEGER* The leading dimension of the array A. LDA >= max(1,N).** WR (output) DOUBLE PRECISION array, dimension (N)* WI (output) DOUBLE PRECISION array, dimension (N)* WR and WI contain the real and imaginary parts,* respectively, of the computed eigenvalues. Complex* conjugate pairs of eigenvalues will appear consecutively* with the eigenvalue having the positive imaginary part* first.** VL (output) DOUBLE PRECISION array, dimension (LDVL,N)* If JOBVL = 'V', the left eigenvectors u(j) are stored one* after another in the columns of VL, in the same order* as their eigenvalues.* If JOBVL = 'N', VL is not referenced.* If the j-th eigenvalue is real, then u(j) = VL(:,j),* the j-th column of VL.* If the j-th and (j+1)-st eigenvalues form a complex* conjugate pair, then u(j) = VL(:,j) + i*VL(:,j+1) and* u(j+1) = VL(:,j) - i*VL(:,j+1).** LDVL (input) INTEGER* The leading dimension of the array VL. LDVL >= 1; if* JOBVL = 'V', LDVL >= N.** VR (output) DOUBLE PRECISION array, dimension (LDVR,N)* If JOBVR = 'V', the right eigenvectors v(j) are stored one* after another in the columns of VR, in the same order* as their eigenvalues.* If JOBVR = 'N', VR is not referenced.* If the j-th eigenvalue is real, then v(j) = VR(:,j),* the j-th column of VR.* If the j-th and (j+1)-st eigenvalues form a complex* conjugate pair, then v(j) = VR(:,j) + i*VR(:,j+1) and* v(j+1) = VR(:,j) - i*VR(:,j+1).** LDVR (input) INTEGER* The leading dimension of the array VR. LDVR >= 1, and if* JOBVR = 'V', LDVR >= N.** ILO,IHI (output) INTEGER* ILO and IHI are integer values determined when A was* balanced. The balanced A(i,j) = 0 if I > J and* J = 1,...,ILO-1 or I = IHI+1,...,N.** SCALE (output) DOUBLE PRECISION array, dimension (N)* Details of the permutations and scaling factors applied* when balancing A. If P(j) is the index of the row and column* interchanged with row and column j, and D(j) is the scaling* factor applied to row and column j, then* SCALE(J) = P(J), for J = 1,...,ILO-1* = D(J), for J = ILO,...,IHI* = P(J) for J = IHI+1,...,N.* The order in which the interchanges are made is N to IHI+1,* then 1 to ILO-1.** ABNRM (output) DOUBLE PRECISION* The one-norm of the balanced matrix (the maximum* of the sum of absolute values of elements of any column).** RCONDE (output) DOUBLE PRECISION array, dimension (N)* RCONDE(j) is the reciprocal condition number of the j-th* eigenvalue.** RCONDV (output) DOUBLE PRECISION array, dimension (N)* RCONDV(j) is the reciprocal condition number of the j-th* right eigenvector.** 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 SENSE = 'N' or 'E',* LWORK >= max(1,2*N), and if JOBVL = 'V' or JOBVR = 'V',* LWORK >= 3*N. If SENSE = 'V' or 'B', LWORK >= N*(N+6).* For good performance, LWORK must generally be larger.** 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 (2*N-2)* If SENSE = 'N' or 'E', not referenced.** INFO (output) INTEGER* = 0: successful exit* < 0: if INFO = -i, the i-th argument had an illegal value.* > 0: if INFO = i, the QR algorithm failed to compute all the* eigenvalues, and no eigenvectors or condition numbers* have been computed; elements 1:ILO-1 and i+1:N of WR* and WI contain eigenvalues which have converged.** =====================================================================** .. Parameters ..DOUBLE PRECISION ZERO, ONEPARAMETER ( ZERO = 0.0D0, ONE = 1.0D0 )* ..* .. Local Scalars ..LOGICAL LQUERY, SCALEA, WANTVL, WANTVR, WNTSNB, WNTSNE,$ WNTSNN, WNTSNVCHARACTER JOB, SIDEINTEGER HSWORK, I, ICOND, IERR, ITAU, IWRK, K, MAXB,$ MAXWRK, MINWRK, NOUTDOUBLE PRECISION ANRM, BIGNUM, CS, CSCALE, EPS, R, SCL, SMLNUM,$ SN* ..* .. Local Arrays ..LOGICAL SELECT( 1 )DOUBLE PRECISION DUM( 1 )* ..* .. External Subroutines ..EXTERNAL DGEBAK, DGEBAL, DGEHRD, DHSEQR, DLACPY, DLARTG,$ DLASCL, DORGHR, DROT, DSCAL, DTREVC, DTRSNA,$ XERBLA* ..* .. External Functions ..LOGICAL LSAMEINTEGER IDAMAX, ILAENVDOUBLE PRECISION DLAMCH, DLANGE, DLAPY2, DNRM2EXTERNAL LSAME, IDAMAX, ILAENV, DLAMCH, DLANGE, DLAPY2,$ DNRM2* ..* .. Intrinsic Functions ..INTRINSIC MAX, MIN, SQRT* ..* .. Executable Statements ..** Test the input arguments*INFO = 0LQUERY = ( LWORK.EQ.-1 )WANTVL = LSAME( JOBVL, 'V' )WANTVR = LSAME( JOBVR, 'V' )WNTSNN = LSAME( SENSE, 'N' )WNTSNE = LSAME( SENSE, 'E' )WNTSNV = LSAME( SENSE, 'V' )WNTSNB = LSAME( SENSE, 'B' )IF( .NOT.( LSAME( BALANC, 'N' ) .OR. LSAME( BALANC,$ 'S' ) .OR. LSAME( BALANC, 'P' ) .OR. LSAME( BALANC, 'B' ) ) )$ THENINFO = -1ELSE IF( ( .NOT.WANTVL ) .AND. ( .NOT.LSAME( JOBVL, 'N' ) ) ) THENINFO = -2ELSE IF( ( .NOT.WANTVR ) .AND. ( .NOT.LSAME( JOBVR, 'N' ) ) ) THENINFO = -3ELSE IF( .NOT.( WNTSNN .OR. WNTSNE .OR. WNTSNB .OR. WNTSNV ) .OR.$ ( ( WNTSNE .OR. WNTSNB ) .AND. .NOT.( WANTVL .AND.$ WANTVR ) ) ) THENINFO = -4ELSE IF( N.LT.0 ) THENINFO = -5ELSE IF( LDA.LT.MAX( 1, N ) ) THENINFO = -7ELSE IF( LDVL.LT.1 .OR. ( WANTVL .AND. LDVL.LT.N ) ) THENINFO = -11ELSE IF( LDVR.LT.1 .OR. ( WANTVR .AND. LDVR.LT.N ) ) THENINFO = -13END IF** Compute workspace* (Note: Comments in the code beginning "Workspace:" describe the* minimal amount of workspace needed at that point in the code,* as well as the preferred amount for good performance.* NB refers to the optimal block size for the immediately* following subroutine, as returned by ILAENV.* HSWORK refers to the workspace preferred by DHSEQR, as* calculated below. HSWORK is computed assuming ILO=1 and IHI=N,* the worst case.)*MINWRK = 1IF( INFO.EQ.0 .AND. ( LWORK.GE.1 .OR. LQUERY ) ) THENMAXWRK = N + N*ILAENV( 1, 'DGEHRD', ' ', N, 1, N, 0 )IF( ( .NOT.WANTVL ) .AND. ( .NOT.WANTVR ) ) THENMINWRK = MAX( 1, 2*N )IF( .NOT.WNTSNN )$ MINWRK = MAX( MINWRK, N*N+6*N )MAXB = MAX( ILAENV( 8, 'DHSEQR', 'SN', N, 1, N, -1 ), 2 )IF( WNTSNN ) THENK = MIN( MAXB, N, MAX( 2, ILAENV( 4, 'DHSEQR', 'EN', N,$ 1, N, -1 ) ) )ELSEK = MIN( MAXB, N, MAX( 2, ILAENV( 4, 'DHSEQR', 'SN', N,$ 1, N, -1 ) ) )END IFHSWORK = MAX( K*( K+2 ), 2*N )MAXWRK = MAX( MAXWRK, 1, HSWORK )IF( .NOT.WNTSNN )$ MAXWRK = MAX( MAXWRK, N*N+6*N )ELSEMINWRK = MAX( 1, 3*N )IF( ( .NOT.WNTSNN ) .AND. ( .NOT.WNTSNE ) )$ MINWRK = MAX( MINWRK, N*N+6*N )MAXB = MAX( ILAENV( 8, 'DHSEQR', 'SN', N, 1, N, -1 ), 2 )K = MIN( MAXB, N, MAX( 2, ILAENV( 4, 'DHSEQR', 'EN', N, 1,$ N, -1 ) ) )HSWORK = MAX( K*( K+2 ), 2*N )MAXWRK = MAX( MAXWRK, 1, HSWORK )MAXWRK = MAX( MAXWRK, N+( N-1 )*$ ILAENV( 1, 'DORGHR', ' ', N, 1, N, -1 ) )IF( ( .NOT.WNTSNN ) .AND. ( .NOT.WNTSNE ) )$ MAXWRK = MAX( MAXWRK, N*N+6*N )MAXWRK = MAX( MAXWRK, 3*N, 1 )END IFWORK( 1 ) = MAXWRKEND IFIF( LWORK.LT.MINWRK .AND. .NOT.LQUERY ) THENINFO = -21END IFIF( INFO.NE.0 ) THENCALL XERBLA( 'DGEEVX', -INFO )RETURNELSE IF( LQUERY ) THENRETURNEND IF** Quick return if possible*IF( N.EQ.0 )$ RETURN** Get machine constants*EPS = DLAMCH( 'P' )SMLNUM = DLAMCH( 'S' )BIGNUM = ONE / SMLNUMCALL DLABAD( SMLNUM, BIGNUM )SMLNUM = SQRT( SMLNUM ) / EPSBIGNUM = ONE / SMLNUM** Scale A if max element outside range [SMLNUM,BIGNUM]*ICOND = 0ANRM = DLANGE( 'M', N, N, A, LDA, DUM )SCALEA = .FALSE.IF( ANRM.GT.ZERO .AND. ANRM.LT.SMLNUM ) THENSCALEA = .TRUE.CSCALE = SMLNUMELSE IF( ANRM.GT.BIGNUM ) THENSCALEA = .TRUE.CSCALE = BIGNUMEND IFIF( SCALEA )$ CALL DLASCL( 'G', 0, 0, ANRM, CSCALE, N, N, A, LDA, IERR )** Balance the matrix and compute ABNRM*CALL DGEBAL( BALANC, N, A, LDA, ILO, IHI, SCALE, IERR )ABNRM = DLANGE( '1', N, N, A, LDA, DUM )IF( SCALEA ) THENDUM( 1 ) = ABNRMCALL DLASCL( 'G', 0, 0, CSCALE, ANRM, 1, 1, DUM, 1, IERR )ABNRM = DUM( 1 )END IF** Reduce to upper Hessenberg form* (Workspace: need 2*N, prefer N+N*NB)*ITAU = 1IWRK = ITAU + NCALL DGEHRD( N, ILO, IHI, A, LDA, WORK( ITAU ), WORK( IWRK ),$ LWORK-IWRK+1, IERR )*IF( WANTVL ) THEN** Want left eigenvectors* Copy Householder vectors to VL*SIDE = 'L'CALL DLACPY( 'L', N, N, A, LDA, VL, LDVL )** Generate orthogonal matrix in VL* (Workspace: need 2*N-1, prefer N+(N-1)*NB)*CALL DORGHR( N, ILO, IHI, VL, LDVL, WORK( ITAU ), WORK( IWRK ),$ LWORK-IWRK+1, IERR )** Perform QR iteration, accumulating Schur vectors in VL* (Workspace: need 1, prefer HSWORK (see comments) )*IWRK = ITAUCALL DHSEQR( 'S', 'V', N, ILO, IHI, A, LDA, WR, WI, VL, LDVL,$ WORK( IWRK ), LWORK-IWRK+1, INFO )*IF( WANTVR ) THEN** Want left and right eigenvectors* Copy Schur vectors to VR*SIDE = 'B'CALL DLACPY( 'F', N, N, VL, LDVL, VR, LDVR )END IF*ELSE IF( WANTVR ) THEN** Want right eigenvectors* Copy Householder vectors to VR*SIDE = 'R'CALL DLACPY( 'L', N, N, A, LDA, VR, LDVR )** Generate orthogonal matrix in VR* (Workspace: need 2*N-1, prefer N+(N-1)*NB)*CALL DORGHR( N, ILO, IHI, VR, LDVR, WORK( ITAU ), WORK( IWRK ),$ LWORK-IWRK+1, IERR )** Perform QR iteration, accumulating Schur vectors in VR* (Workspace: need 1, prefer HSWORK (see comments) )*IWRK = ITAUCALL DHSEQR( 'S', 'V', N, ILO, IHI, A, LDA, WR, WI, VR, LDVR,$ WORK( IWRK ), LWORK-IWRK+1, INFO )*ELSE** Compute eigenvalues only* If condition numbers desired, compute Schur form*IF( WNTSNN ) THENJOB = 'E'ELSEJOB = 'S'END IF** (Workspace: need 1, prefer HSWORK (see comments) )*IWRK = ITAUCALL DHSEQR( JOB, 'N', N, ILO, IHI, A, LDA, WR, WI, VR, LDVR,$ WORK( IWRK ), LWORK-IWRK+1, INFO )END IF** If INFO > 0 from DHSEQR, then quit*IF( INFO.GT.0 )$ GO TO 50*IF( WANTVL .OR. WANTVR ) THEN** Compute left and/or right eigenvectors* (Workspace: need 3*N)*CALL DTREVC( SIDE, 'B', SELECT, N, A, LDA, VL, LDVL, VR, LDVR,$ N, NOUT, WORK( IWRK ), IERR )END IF** Compute condition numbers if desired* (Workspace: need N*N+6*N unless SENSE = 'E')*IF( .NOT.WNTSNN ) THENCALL DTRSNA( SENSE, 'A', SELECT, N, A, LDA, VL, LDVL, VR, LDVR,$ RCONDE, RCONDV, N, NOUT, WORK( IWRK ), N, IWORK,$ ICOND )END IF*IF( WANTVL ) THEN** Undo balancing of left eigenvectors*CALL DGEBAK( BALANC, 'L', N, ILO, IHI, SCALE, N, VL, LDVL,$ IERR )** Normalize left eigenvectors and make largest component real*DO 20 I = 1, NIF( WI( I ).EQ.ZERO ) THENSCL = ONE / DNRM2( N, VL( 1, I ), 1 )CALL DSCAL( N, SCL, VL( 1, I ), 1 )ELSE IF( WI( I ).GT.ZERO ) THENSCL = ONE / DLAPY2( DNRM2( N, VL( 1, I ), 1 ),$ DNRM2( N, VL( 1, I+1 ), 1 ) )CALL DSCAL( N, SCL, VL( 1, I ), 1 )CALL DSCAL( N, SCL, VL( 1, I+1 ), 1 )DO 10 K = 1, NWORK( K ) = VL( K, I )**2 + VL( K, I+1 )**210 CONTINUEK = IDAMAX( N, WORK, 1 )CALL DLARTG( VL( K, I ), VL( K, I+1 ), CS, SN, R )CALL DROT( N, VL( 1, I ), 1, VL( 1, I+1 ), 1, CS, SN )VL( K, I+1 ) = ZEROEND IF20 CONTINUEEND IF*IF( WANTVR ) THEN** Undo balancing of right eigenvectors*CALL DGEBAK( BALANC, 'R', N, ILO, IHI, SCALE, N, VR, LDVR,$ IERR )** Normalize right eigenvectors and make largest component real*DO 40 I = 1, NIF( WI( I ).EQ.ZERO ) THENSCL = ONE / DNRM2( N, VR( 1, I ), 1 )CALL DSCAL( N, SCL, VR( 1, I ), 1 )ELSE IF( WI( I ).GT.ZERO ) THENSCL = ONE / DLAPY2( DNRM2( N, VR( 1, I ), 1 ),$ DNRM2( N, VR( 1, I+1 ), 1 ) )CALL DSCAL( N, SCL, VR( 1, I ), 1 )CALL DSCAL( N, SCL, VR( 1, I+1 ), 1 )DO 30 K = 1, NWORK( K ) = VR( K, I )**2 + VR( K, I+1 )**230 CONTINUEK = IDAMAX( N, WORK, 1 )CALL DLARTG( VR( K, I ), VR( K, I+1 ), CS, SN, R )CALL DROT( N, VR( 1, I ), 1, VR( 1, I+1 ), 1, CS, SN )VR( K, I+1 ) = ZEROEND IF40 CONTINUEEND IF** Undo scaling if necessary*50 CONTINUEIF( SCALEA ) THENCALL DLASCL( 'G', 0, 0, CSCALE, ANRM, N-INFO, 1, WR( INFO+1 ),$ MAX( N-INFO, 1 ), IERR )CALL DLASCL( 'G', 0, 0, CSCALE, ANRM, N-INFO, 1, WI( INFO+1 ),$ MAX( N-INFO, 1 ), IERR )IF( INFO.EQ.0 ) THENIF( ( WNTSNV .OR. WNTSNB ) .AND. ICOND.EQ.0 )$ CALL DLASCL( 'G', 0, 0, CSCALE, ANRM, N, 1, RCONDV, N,$ IERR )ELSECALL DLASCL( 'G', 0, 0, CSCALE, ANRM, ILO-1, 1, WR, N,$ IERR )CALL DLASCL( 'G', 0, 0, CSCALE, ANRM, ILO-1, 1, WI, N,$ IERR )END IFEND IF*WORK( 1 ) = MAXWRKRETURN** End of DGEEVX*ENDSUBROUTINE DGEGS( JOBVSL, JOBVSR, N, A, LDA, B, LDB, ALPHAR,$ ALPHAI, BETA, VSL, LDVSL, VSR, LDVSR, WORK,$ LWORK, INFO )** -- LAPACK driver 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 JOBVSL, JOBVSRINTEGER INFO, LDA, LDB, LDVSL, LDVSR, LWORK, N* ..* .. Array Arguments ..DOUBLE PRECISION A( LDA, * ), ALPHAI( * ), ALPHAR( * ),$ B( LDB, * ), BETA( * ), VSL( LDVSL, * ),$ VSR( LDVSR, * ), WORK( * )* ..** Purpose* =======** This routine is deprecated and has been replaced by routine DGGES.** DGEGS computes for a pair of N-by-N real nonsymmetric matrices A, B:* the generalized eigenvalues (alphar +/- alphai*i, beta), the real* Schur form (A, B), and optionally left and/or right Schur vectors* (VSL and VSR).** (If only the generalized eigenvalues are needed, use the driver DGEGV* instead.)** A generalized eigenvalue for a pair of matrices (A,B) is, roughly* speaking, a scalar w or a ratio alpha/beta = w, such that A - w*B* is singular. It is usually represented as the pair (alpha,beta),* as there is a reasonable interpretation for beta=0, and even for* both being zero. A good beginning reference is the book, "Matrix* Computations", by G. Golub & C. van Loan (Johns Hopkins U. Press)** The (generalized) Schur form of a pair of matrices is the result of* multiplying both matrices on the left by one orthogonal matrix and* both on the right by another orthogonal matrix, these two orthogonal* matrices being chosen so as to bring the pair of matrices into* (real) Schur form.** A pair of matrices A, B is in generalized real Schur form if B is* upper triangular with non-negative diagonal and A is block upper* triangular with 1-by-1 and 2-by-2 blocks. 1-by-1 blocks correspond* to real generalized eigenvalues, while 2-by-2 blocks of A will be* "standardized" by making the corresponding elements of B have the* form:* [ a 0 ]* [ 0 b ]** and the pair of corresponding 2-by-2 blocks in A and B will* have a complex conjugate pair of generalized eigenvalues.** The left and right Schur vectors are the columns of VSL and VSR,* respectively, where VSL and VSR are the orthogonal matrices* which reduce A and B to Schur form:** Schur form of (A,B) = ( (VSL)**T A (VSR), (VSL)**T B (VSR) )** Arguments* =========** JOBVSL (input) CHARACTER*1* = 'N': do not compute the left Schur vectors;* = 'V': compute the left Schur vectors.** JOBVSR (input) CHARACTER*1* = 'N': do not compute the right Schur vectors;* = 'V': compute the right Schur vectors.** N (input) INTEGER* The order of the matrices A, B, VSL, and VSR. N >= 0.** A (input/output) DOUBLE PRECISION array, dimension (LDA, N)* On entry, the first of the pair of matrices whose generalized* eigenvalues and (optionally) Schur vectors are to be* computed.* On exit, the generalized Schur form of A.* Note: to avoid overflow, the Frobenius norm of the matrix* A should be less than the overflow threshold.** LDA (input) INTEGER* The leading dimension of A. LDA >= max(1,N).** B (input/output) DOUBLE PRECISION array, dimension (LDB, N)* On entry, the second of the pair of matrices whose* generalized eigenvalues and (optionally) Schur vectors are* to be computed.* On exit, the generalized Schur form of B.* Note: to avoid overflow, the Frobenius norm of the matrix* B should be less than the overflow threshold.** LDB (input) INTEGER* The leading dimension of 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,* j=1,...,N and BETA(j),j=1,...,N are the diagonals of the* complex Schur form (A,B) that would result if the 2-by-2* diagonal blocks of the real Schur form of (A,B) were further* reduced to triangular form using 2-by-2 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.** Note: the quotients ALPHAR(j)/BETA(j) and ALPHAI(j)/BETA(j)* may easily over- or underflow, and BETA(j) may even be zero.* Thus, the user should avoid naively computing the ratio* alpha/beta. However, ALPHAR and ALPHAI will be always less* than and usually comparable with norm(A) in magnitude, and* BETA always less than and usually comparable with norm(B).** VSL (output) DOUBLE PRECISION array, dimension (LDVSL,N)* If JOBVSL = 'V', VSL will contain the left Schur vectors.* (See "Purpose", above.)* Not referenced if JOBVSL = 'N'.** LDVSL (input) INTEGER* The leading dimension of the matrix VSL. LDVSL >=1, and* if JOBVSL = 'V', LDVSL >= N.** VSR (output) DOUBLE PRECISION array, dimension (LDVSR,N)* If JOBVSR = 'V', VSR will contain the right Schur vectors.* (See "Purpose", above.)* Not referenced if JOBVSR = 'N'.** LDVSR (input) INTEGER* The leading dimension of the matrix VSR. LDVSR >= 1, and* if JOBVSR = 'V', LDVSR >= 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 >= max(1,4*N).* For good performance, LWORK must generally be larger.* To compute the optimal value of LWORK, call ILAENV to get* blocksizes (for DGEQRF, DORMQR, and DORGQR.) Then compute:* NB -- MAX of the blocksizes for DGEQRF, DORMQR, and DORGQR* The optimal LWORK is 2*N + N*(NB+1).** 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,...,N:* The QZ iteration failed. (A,B) are not in Schur* form, but ALPHAR(j), ALPHAI(j), and BETA(j) should* be correct for j=INFO+1,...,N.* > N: errors that usually indicate LAPACK problems:* =N+1: error return from DGGBAL* =N+2: error return from DGEQRF* =N+3: error return from DORMQR* =N+4: error return from DORGQR* =N+5: error return from DGGHRD* =N+6: error return from DHGEQZ (other than failed* iteration)* =N+7: error return from DGGBAK (computing VSL)* =N+8: error return from DGGBAK (computing VSR)* =N+9: error return from DLASCL (various places)** =====================================================================** .. Parameters ..DOUBLE PRECISION ZERO, ONEPARAMETER ( ZERO = 0.0D0, ONE = 1.0D0 )* ..* .. Local Scalars ..LOGICAL ILASCL, ILBSCL, ILVSL, ILVSR, LQUERYINTEGER ICOLS, IHI, IINFO, IJOBVL, IJOBVR, ILEFT, ILO,$ IRIGHT, IROWS, ITAU, IWORK, LOPT, LWKMIN,$ LWKOPT, NB, NB1, NB2, NB3DOUBLE PRECISION ANRM, ANRMTO, BIGNUM, BNRM, BNRMTO, EPS,$ SAFMIN, SMLNUM* ..* .. External Subroutines ..EXTERNAL DGEQRF, DGGBAK, DGGBAL, DGGHRD, DHGEQZ, DLACPY,$ DLASCL, DLASET, DORGQR, DORMQR, XERBLA* ..* .. External Functions ..LOGICAL LSAMEINTEGER ILAENVDOUBLE PRECISION DLAMCH, DLANGEEXTERNAL LSAME, ILAENV, DLAMCH, DLANGE* ..* .. Intrinsic Functions ..INTRINSIC INT, MAX* ..* .. Executable Statements ..** Decode the input arguments*IF( LSAME( JOBVSL, 'N' ) ) THENIJOBVL = 1ILVSL = .FALSE.ELSE IF( LSAME( JOBVSL, 'V' ) ) THENIJOBVL = 2ILVSL = .TRUE.ELSEIJOBVL = -1ILVSL = .FALSE.END IF*IF( LSAME( JOBVSR, 'N' ) ) THENIJOBVR = 1ILVSR = .FALSE.ELSE IF( LSAME( JOBVSR, 'V' ) ) THENIJOBVR = 2ILVSR = .TRUE.ELSEIJOBVR = -1ILVSR = .FALSE.END IF** Test the input arguments*LWKMIN = MAX( 4*N, 1 )LWKOPT = LWKMINWORK( 1 ) = LWKOPTLQUERY = ( LWORK.EQ.-1 )INFO = 0IF( IJOBVL.LE.0 ) THENINFO = -1ELSE IF( IJOBVR.LE.0 ) THENINFO = -2ELSE IF( N.LT.0 ) THENINFO = -3ELSE IF( LDA.LT.MAX( 1, N ) ) THENINFO = -5ELSE IF( LDB.LT.MAX( 1, N ) ) THENINFO = -7ELSE IF( LDVSL.LT.1 .OR. ( ILVSL .AND. LDVSL.LT.N ) ) THENINFO = -12ELSE IF( LDVSR.LT.1 .OR. ( ILVSR .AND. LDVSR.LT.N ) ) THENINFO = -14ELSE IF( LWORK.LT.LWKMIN .AND. .NOT.LQUERY ) THENINFO = -16END IF*IF( INFO.EQ.0 ) THENNB1 = ILAENV( 1, 'DGEQRF', ' ', N, N, -1, -1 )NB2 = ILAENV( 1, 'DORMQR', ' ', N, N, N, -1 )NB3 = ILAENV( 1, 'DORGQR', ' ', N, N, N, -1 )NB = MAX( NB1, NB2, NB3 )LOPT = 2*N + N*( NB+1 )WORK( 1 ) = LOPTEND IF*IF( INFO.NE.0 ) THENCALL XERBLA( 'DGEGS ', -INFO )RETURNELSE IF( LQUERY ) THENRETURNEND IF** Quick return if possible*IF( N.EQ.0 )$ RETURN** Get machine constants*EPS = DLAMCH( 'E' )*DLAMCH( 'B' )SAFMIN = DLAMCH( 'S' )SMLNUM = N*SAFMIN / EPSBIGNUM = ONE / SMLNUM** Scale A if max element outside range [SMLNUM,BIGNUM]*ANRM = DLANGE( 'M', N, N, A, LDA, WORK )ILASCL = .FALSE.IF( ANRM.GT.ZERO .AND. ANRM.LT.SMLNUM ) THENANRMTO = SMLNUMILASCL = .TRUE.ELSE IF( ANRM.GT.BIGNUM ) THENANRMTO = BIGNUMILASCL = .TRUE.END IF*IF( ILASCL ) THENCALL DLASCL( 'G', -1, -1, ANRM, ANRMTO, N, N, A, LDA, IINFO )IF( IINFO.NE.0 ) THENINFO = N + 9RETURNEND IFEND IF** Scale B if max element outside range [SMLNUM,BIGNUM]*BNRM = DLANGE( 'M', N, N, B, LDB, WORK )ILBSCL = .FALSE.IF( BNRM.GT.ZERO .AND. BNRM.LT.SMLNUM ) THENBNRMTO = SMLNUMILBSCL = .TRUE.ELSE IF( BNRM.GT.BIGNUM ) THENBNRMTO = BIGNUMILBSCL = .TRUE.END IF*IF( ILBSCL ) THENCALL DLASCL( 'G', -1, -1, BNRM, BNRMTO, N, N, B, LDB, IINFO )IF( IINFO.NE.0 ) THENINFO = N + 9RETURNEND IFEND IF** Permute the matrix to make it more nearly triangular* Workspace layout: (2*N words -- "work..." not actually used)* left_permutation, right_permutation, work...*ILEFT = 1IRIGHT = N + 1IWORK = IRIGHT + NCALL DGGBAL( 'P', N, A, LDA, B, LDB, ILO, IHI, WORK( ILEFT ),$ WORK( IRIGHT ), WORK( IWORK ), IINFO )IF( IINFO.NE.0 ) THENINFO = N + 1GO TO 10END IF** Reduce B to triangular form, and initialize VSL and/or VSR* Workspace layout: ("work..." must have at least N words)* left_permutation, right_permutation, tau, work...*IROWS = IHI + 1 - ILOICOLS = N + 1 - ILOITAU = IWORKIWORK = ITAU + IROWSCALL DGEQRF( IROWS, ICOLS, B( ILO, ILO ), LDB, WORK( ITAU ),$ WORK( IWORK ), LWORK+1-IWORK, IINFO )IF( IINFO.GE.0 )$ LWKOPT = MAX( LWKOPT, INT( WORK( IWORK ) )+IWORK-1 )IF( IINFO.NE.0 ) THENINFO = N + 2GO TO 10END IF*CALL DORMQR( 'L', 'T', IROWS, ICOLS, IROWS, B( ILO, ILO ), LDB,$ WORK( ITAU ), A( ILO, ILO ), LDA, WORK( IWORK ),$ LWORK+1-IWORK, IINFO )IF( IINFO.GE.0 )$ LWKOPT = MAX( LWKOPT, INT( WORK( IWORK ) )+IWORK-1 )IF( IINFO.NE.0 ) THENINFO = N + 3GO TO 10END IF*IF( ILVSL ) THENCALL DLASET( 'Full', N, N, ZERO, ONE, VSL, LDVSL )CALL DLACPY( 'L', IROWS-1, IROWS-1, B( ILO+1, ILO ), LDB,$ VSL( ILO+1, ILO ), LDVSL )CALL DORGQR( IROWS, IROWS, IROWS, VSL( ILO, ILO ), LDVSL,$ WORK( ITAU ), WORK( IWORK ), LWORK+1-IWORK,$ IINFO )IF( IINFO.GE.0 )$ LWKOPT = MAX( LWKOPT, INT( WORK( IWORK ) )+IWORK-1 )IF( IINFO.NE.0 ) THENINFO = N + 4GO TO 10END IFEND IF*IF( ILVSR )$ CALL DLASET( 'Full', N, N, ZERO, ONE, VSR, LDVSR )** Reduce to generalized Hessenberg form*CALL DGGHRD( JOBVSL, JOBVSR, N, ILO, IHI, A, LDA, B, LDB, VSL,$ LDVSL, VSR, LDVSR, IINFO )IF( IINFO.NE.0 ) THENINFO = N + 5GO TO 10END IF** Perform QZ algorithm, computing Schur vectors if desired* Workspace layout: ("work..." must have at least 1 word)* left_permutation, right_permutation, work...*IWORK = ITAUCALL DHGEQZ( 'S', JOBVSL, JOBVSR, N, ILO, IHI, A, LDA, B, LDB,$ ALPHAR, ALPHAI, BETA, VSL, LDVSL, VSR, LDVSR,$ WORK( IWORK ), LWORK+1-IWORK, IINFO )IF( IINFO.GE.0 )$ LWKOPT = MAX( LWKOPT, INT( WORK( IWORK ) )+IWORK-1 )IF( IINFO.NE.0 ) THENIF( IINFO.GT.0 .AND. IINFO.LE.N ) THENINFO = IINFOELSE IF( IINFO.GT.N .AND. IINFO.LE.2*N ) THENINFO = IINFO - NELSEINFO = N + 6END IFGO TO 10END IF** Apply permutation to VSL and VSR*IF( ILVSL ) THENCALL DGGBAK( 'P', 'L', N, ILO, IHI, WORK( ILEFT ),$ WORK( IRIGHT ), N, VSL, LDVSL, IINFO )IF( IINFO.NE.0 ) THENINFO = N + 7GO TO 10END IFEND IFIF( ILVSR ) THENCALL DGGBAK( 'P', 'R', N, ILO, IHI, WORK( ILEFT ),$ WORK( IRIGHT ), N, VSR, LDVSR, IINFO )IF( IINFO.NE.0 ) THENINFO = N + 8GO TO 10END IFEND IF** Undo scaling*IF( ILASCL ) THENCALL DLASCL( 'H', -1, -1, ANRMTO, ANRM, N, N, A, LDA, IINFO )IF( IINFO.NE.0 ) THENINFO = N + 9RETURNEND IFCALL DLASCL( 'G', -1, -1, ANRMTO, ANRM, N, 1, ALPHAR, N,$ IINFO )IF( IINFO.NE.0 ) THENINFO = N + 9RETURNEND IFCALL DLASCL( 'G', -1, -1, ANRMTO, ANRM, N, 1, ALPHAI, N,$ IINFO )IF( IINFO.NE.0 ) THENINFO = N + 9RETURNEND IFEND IF*IF( ILBSCL ) THENCALL DLASCL( 'U', -1, -1, BNRMTO, BNRM, N, N, B, LDB, IINFO )IF( IINFO.NE.0 ) THENINFO = N + 9RETURNEND IFCALL DLASCL( 'G', -1, -1, BNRMTO, BNRM, N, 1, BETA, N, IINFO )IF( IINFO.NE.0 ) THENINFO = N + 9RETURNEND IFEND IF*10 CONTINUEWORK( 1 ) = LWKOPT*RETURN** End of DGEGS*ENDSUBROUTINE DGEGV( JOBVL, JOBVR, N, A, LDA, B, LDB, ALPHAR, ALPHAI,$ BETA, VL, LDVL, VR, LDVR, WORK, LWORK, INFO )** -- LAPACK driver 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 JOBVL, JOBVRINTEGER INFO, LDA, LDB, LDVL, LDVR, LWORK, N* ..* .. Array Arguments ..DOUBLE PRECISION A( LDA, * ), ALPHAI( * ), ALPHAR( * ),$ B( LDB, * ), BETA( * ), VL( LDVL, * ),$ VR( LDVR, * ), WORK( * )* ..** Purpose* =======** This routine is deprecated and has been replaced by routine DGGEV.** DGEGV computes for a pair of n-by-n real nonsymmetric matrices A and* B, the generalized eigenvalues (alphar +/- alphai*i, beta), and* optionally, the left and/or right generalized eigenvectors (VL and* VR).** A generalized eigenvalue for a pair of matrices (A,B) is, roughly* speaking, a scalar w or a ratio alpha/beta = w, such that A - w*B* is singular. It is usually represented as the pair (alpha,beta),* as there is a reasonable interpretation for beta=0, and even for* both being zero. A good beginning reference is the book, "Matrix* Computations", by G. Golub & C. van Loan (Johns Hopkins U. Press)** A right generalized eigenvector corresponding to a generalized* eigenvalue w for a pair of matrices (A,B) is a vector r such* that (A - w B) r = 0 . A left generalized eigenvector is a vector* l such that l**H * (A - w B) = 0, where l**H is the* conjugate-transpose of l.** Note: this routine performs "full balancing" on A and B -- see* "Further Details", below.** Arguments* =========** JOBVL (input) CHARACTER*1* = 'N': do not compute the left generalized eigenvectors;* = 'V': compute the left generalized eigenvectors.** JOBVR (input) CHARACTER*1* = 'N': do not compute the right generalized eigenvectors;* = 'V': compute the right generalized eigenvectors.** N (input) INTEGER* The order of the matrices A, B, VL, and VR. N >= 0.** A (input/output) DOUBLE PRECISION array, dimension (LDA, N)* On entry, the first of the pair of matrices whose* generalized eigenvalues and (optionally) generalized* eigenvectors are to be computed.* On exit, the contents will have been destroyed. (For a* description of the contents of A on exit, see "Further* Details", below.)** LDA (input) INTEGER* The leading dimension of A. LDA >= max(1,N).** B (input/output) DOUBLE PRECISION array, dimension (LDB, N)* On entry, the second of the pair of matrices whose* generalized eigenvalues and (optionally) generalized* eigenvectors are to be computed.* On exit, the contents will have been destroyed. (For a* description of the contents of B on exit, see "Further* Details", below.)** LDB (input) INTEGER* The leading dimension of 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. 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.** Note: the quotients ALPHAR(j)/BETA(j) and ALPHAI(j)/BETA(j)* may easily over- or underflow, and BETA(j) may even be zero.* Thus, the user should avoid naively computing the ratio* alpha/beta. However, ALPHAR and ALPHAI will be always less* than and usually comparable with norm(A) in magnitude, and* BETA always less than and usually comparable with norm(B).** VL (output) DOUBLE PRECISION array, dimension (LDVL,N)* If JOBVL = 'V', the left generalized eigenvectors. (See* "Purpose", above.) Real eigenvectors take one column,* complex take two columns, the first for the real part and* the second for the imaginary part. Complex eigenvectors* correspond to an eigenvalue with positive imaginary part.* Each eigenvector will be scaled so the largest component* will have abs(real part) + abs(imag. part) = 1, *except** that for eigenvalues with alpha=beta=0, a zero vector will* be returned as the corresponding eigenvector.* Not referenced if JOBVL = 'N'.** LDVL (input) INTEGER* The leading dimension of the matrix VL. LDVL >= 1, and* if JOBVL = 'V', LDVL >= N.** VR (output) DOUBLE PRECISION array, dimension (LDVR,N)* If JOBVR = 'V', the right generalized eigenvectors. (See* "Purpose", above.) Real eigenvectors take one column,* complex take two columns, the first for the real part and* the second for the imaginary part. Complex eigenvectors* correspond to an eigenvalue with positive imaginary part.* Each eigenvector will be scaled so the largest component* will have abs(real part) + abs(imag. part) = 1, *except** that for eigenvalues with alpha=beta=0, a zero vector will* be returned as the corresponding eigenvector.* Not referenced if JOBVR = 'N'.** LDVR (input) INTEGER* The leading dimension of the matrix VR. LDVR >= 1, and* if JOBVR = 'V', LDVR >= 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 >= max(1,8*N).* For good performance, LWORK must generally be larger.* To compute the optimal value of LWORK, call ILAENV to get* blocksizes (for DGEQRF, DORMQR, and DORGQR.) Then compute:* NB -- MAX of the blocksizes for DGEQRF, DORMQR, and DORGQR;* The optimal LWORK is:* 2*N + MAX( 6*N, N*(NB+1) ).** 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,...,N:* The QZ iteration failed. No eigenvectors have been* calculated, but ALPHAR(j), ALPHAI(j), and BETA(j)* should be correct for j=INFO+1,...,N.* > N: errors that usually indicate LAPACK problems:* =N+1: error return from DGGBAL* =N+2: error return from DGEQRF* =N+3: error return from DORMQR* =N+4: error return from DORGQR* =N+5: error return from DGGHRD* =N+6: error return from DHGEQZ (other than failed* iteration)* =N+7: error return from DTGEVC* =N+8: error return from DGGBAK (computing VL)* =N+9: error return from DGGBAK (computing VR)* =N+10: error return from DLASCL (various calls)** Further Details* ===============** Balancing* ---------** This driver calls DGGBAL to both permute and scale rows and columns* of A and B. The permutations PL and PR are chosen so that PL*A*PR* and PL*B*R will be upper triangular except for the diagonal blocks* A(i:j,i:j) and B(i:j,i:j), with i and j as close together as* possible. The diagonal scaling matrices DL and DR are chosen so* that the pair DL*PL*A*PR*DR, DL*PL*B*PR*DR have elements close to* one (except for the elements that start out zero.)** After the eigenvalues and eigenvectors of the balanced matrices* have been computed, DGGBAK transforms the eigenvectors back to what* they would have been (in perfect arithmetic) if they had not been* balanced.** Contents of A and B on Exit* -------- -- - --- - -- ----** If any eigenvectors are computed (either JOBVL='V' or JOBVR='V' or* both), then on exit the arrays A and B will contain the real Schur* form[*] of the "balanced" versions of A and B. If no eigenvectors* are computed, then only the diagonal blocks will be correct.** [*] See DHGEQZ, DGEGS, or read the book "Matrix Computations",* by Golub & van Loan, pub. by Johns Hopkins U. Press.** =====================================================================** .. Parameters ..DOUBLE PRECISION ZERO, ONEPARAMETER ( ZERO = 0.0D0, ONE = 1.0D0 )* ..* .. Local Scalars ..LOGICAL ILIMIT, ILV, ILVL, ILVR, LQUERYCHARACTER CHTEMPINTEGER ICOLS, IHI, IINFO, IJOBVL, IJOBVR, ILEFT, ILO,$ IN, IRIGHT, IROWS, ITAU, IWORK, JC, JR, LOPT,$ LWKMIN, LWKOPT, NB, NB1, NB2, NB3DOUBLE PRECISION ABSAI, ABSAR, ABSB, ANRM, ANRM1, ANRM2, BNRM,$ BNRM1, BNRM2, EPS, ONEPLS, SAFMAX, SAFMIN,$ SALFAI, SALFAR, SBETA, SCALE, TEMP* ..* .. Local Arrays ..LOGICAL LDUMMA( 1 )* ..* .. External Subroutines ..EXTERNAL DGEQRF, DGGBAK, DGGBAL, DGGHRD, DHGEQZ, DLACPY,$ DLASCL, DLASET, DORGQR, DORMQR, DTGEVC, XERBLA* ..* .. External Functions ..LOGICAL LSAMEINTEGER ILAENVDOUBLE PRECISION DLAMCH, DLANGEEXTERNAL LSAME, ILAENV, DLAMCH, DLANGE* ..* .. Intrinsic Functions ..INTRINSIC ABS, INT, MAX* ..* .. Executable Statements ..** Decode the input arguments*IF( LSAME( JOBVL, 'N' ) ) THENIJOBVL = 1ILVL = .FALSE.ELSE IF( LSAME( JOBVL, 'V' ) ) THENIJOBVL = 2ILVL = .TRUE.ELSEIJOBVL = -1ILVL = .FALSE.END IF*IF( LSAME( JOBVR, 'N' ) ) THENIJOBVR = 1ILVR = .FALSE.ELSE IF( LSAME( JOBVR, 'V' ) ) THENIJOBVR = 2ILVR = .TRUE.ELSEIJOBVR = -1ILVR = .FALSE.END IFILV = ILVL .OR. ILVR** Test the input arguments*LWKMIN = MAX( 8*N, 1 )LWKOPT = LWKMINWORK( 1 ) = LWKOPTLQUERY = ( LWORK.EQ.-1 )INFO = 0IF( IJOBVL.LE.0 ) THENINFO = -1ELSE IF( IJOBVR.LE.0 ) THENINFO = -2ELSE IF( N.LT.0 ) THENINFO = -3ELSE IF( LDA.LT.MAX( 1, N ) ) THENINFO = -5ELSE IF( LDB.LT.MAX( 1, N ) ) THENINFO = -7ELSE IF( LDVL.LT.1 .OR. ( ILVL .AND. LDVL.LT.N ) ) THENINFO = -12ELSE IF( LDVR.LT.1 .OR. ( ILVR .AND. LDVR.LT.N ) ) THENINFO = -14ELSE IF( LWORK.LT.LWKMIN .AND. .NOT.LQUERY ) THENINFO = -16END IF*IF( INFO.EQ.0 ) THENNB1 = ILAENV( 1, 'DGEQRF', ' ', N, N, -1, -1 )NB2 = ILAENV( 1, 'DORMQR', ' ', N, N, N, -1 )NB3 = ILAENV( 1, 'DORGQR', ' ', N, N, N, -1 )NB = MAX( NB1, NB2, NB3 )LOPT = 2*N + MAX( 6*N, N*( NB+1 ) )WORK( 1 ) = LOPTEND IF*IF( INFO.NE.0 ) THENCALL XERBLA( 'DGEGV ', -INFO )RETURNELSE IF( LQUERY ) THENRETURNEND IF** Quick return if possible*IF( N.EQ.0 )$ RETURN** Get machine constants*EPS = DLAMCH( 'E' )*DLAMCH( 'B' )SAFMIN = DLAMCH( 'S' )SAFMIN = SAFMIN + SAFMINSAFMAX = ONE / SAFMINONEPLS = ONE + ( 4*EPS )** Scale A*ANRM = DLANGE( 'M', N, N, A, LDA, WORK )ANRM1 = ANRMANRM2 = ONEIF( ANRM.LT.ONE ) THENIF( SAFMAX*ANRM.LT.ONE ) THENANRM1 = SAFMINANRM2 = SAFMAX*ANRMEND IFEND IF*IF( ANRM.GT.ZERO ) THENCALL DLASCL( 'G', -1, -1, ANRM, ONE, N, N, A, LDA, IINFO )IF( IINFO.NE.0 ) THENINFO = N + 10RETURNEND IFEND IF** Scale B*BNRM = DLANGE( 'M', N, N, B, LDB, WORK )BNRM1 = BNRMBNRM2 = ONEIF( BNRM.LT.ONE ) THENIF( SAFMAX*BNRM.LT.ONE ) THENBNRM1 = SAFMINBNRM2 = SAFMAX*BNRMEND IFEND IF*IF( BNRM.GT.ZERO ) THENCALL DLASCL( 'G', -1, -1, BNRM, ONE, N, N, B, LDB, IINFO )IF( IINFO.NE.0 ) THENINFO = N + 10RETURNEND IFEND IF** Permute the matrix to make it more nearly triangular* Workspace layout: (8*N words -- "work" requires 6*N words)* left_permutation, right_permutation, work...*ILEFT = 1IRIGHT = N + 1IWORK = IRIGHT + NCALL DGGBAL( 'P', N, A, LDA, B, LDB, ILO, IHI, WORK( ILEFT ),$ WORK( IRIGHT ), WORK( IWORK ), IINFO )IF( IINFO.NE.0 ) THENINFO = N + 1GO TO 120END IF** Reduce B to triangular form, and initialize VL and/or VR* Workspace layout: ("work..." must have at least N words)* left_permutation, right_permutation, tau, work...*IROWS = IHI + 1 - ILOIF( ILV ) THENICOLS = N + 1 - ILOELSEICOLS = IROWSEND IFITAU = IWORKIWORK = ITAU + IROWSCALL DGEQRF( IROWS, ICOLS, B( ILO, ILO ), LDB, WORK( ITAU ),$ WORK( IWORK ), LWORK+1-IWORK, IINFO )IF( IINFO.GE.0 )$ LWKOPT = MAX( LWKOPT, INT( WORK( IWORK ) )+IWORK-1 )IF( IINFO.NE.0 ) THENINFO = N + 2GO TO 120END IF*CALL DORMQR( 'L', 'T', IROWS, ICOLS, IROWS, B( ILO, ILO ), LDB,$ WORK( ITAU ), A( ILO, ILO ), LDA, WORK( IWORK ),$ LWORK+1-IWORK, IINFO )IF( IINFO.GE.0 )$ LWKOPT = MAX( LWKOPT, INT( WORK( IWORK ) )+IWORK-1 )IF( IINFO.NE.0 ) THENINFO = N + 3GO TO 120END IF*IF( ILVL ) THENCALL DLASET( 'Full', N, N, ZERO, ONE, VL, LDVL )CALL DLACPY( 'L', IROWS-1, IROWS-1, B( ILO+1, ILO ), LDB,$ VL( ILO+1, ILO ), LDVL )CALL DORGQR( IROWS, IROWS, IROWS, VL( ILO, ILO ), LDVL,$ WORK( ITAU ), WORK( IWORK ), LWORK+1-IWORK,$ IINFO )IF( IINFO.GE.0 )$ LWKOPT = MAX( LWKOPT, INT( WORK( IWORK ) )+IWORK-1 )IF( IINFO.NE.0 ) THENINFO = N + 4GO TO 120END IFEND IF*IF( ILVR )$ CALL DLASET( 'Full', N, N, ZERO, ONE, VR, LDVR )** Reduce to generalized Hessenberg form*IF( ILV ) THEN** Eigenvectors requested -- work on whole matrix.*CALL DGGHRD( JOBVL, JOBVR, N, ILO, IHI, A, LDA, B, LDB, VL,$ LDVL, VR, LDVR, IINFO )ELSECALL DGGHRD( 'N', 'N', IROWS, 1, IROWS, A( ILO, ILO ), LDA,$ B( ILO, ILO ), LDB, VL, LDVL, VR, LDVR, IINFO )END IFIF( IINFO.NE.0 ) THENINFO = N + 5GO TO 120END IF** Perform QZ algorithm* Workspace layout: ("work..." must have at least 1 word)* left_permutation, right_permutation, work...*IWORK = ITAUIF( ILV ) THENCHTEMP = 'S'ELSECHTEMP = 'E'END IFCALL DHGEQZ( CHTEMP, JOBVL, JOBVR, N, ILO, IHI, A, LDA, B, LDB,$ ALPHAR, ALPHAI, BETA, VL, LDVL, VR, LDVR,$ WORK( IWORK ), LWORK+1-IWORK, IINFO )IF( IINFO.GE.0 )$ LWKOPT = MAX( LWKOPT, INT( WORK( IWORK ) )+IWORK-1 )IF( IINFO.NE.0 ) THENIF( IINFO.GT.0 .AND. IINFO.LE.N ) THENINFO = IINFOELSE IF( IINFO.GT.N .AND. IINFO.LE.2*N ) THENINFO = IINFO - NELSEINFO = N + 6END IFGO TO 120END IF*IF( ILV ) THEN** Compute Eigenvectors (DTGEVC requires 6*N words of workspace)*IF( ILVL ) THENIF( ILVR ) THENCHTEMP = 'B'ELSECHTEMP = 'L'END IFELSECHTEMP = 'R'END IF*CALL DTGEVC( CHTEMP, 'B', LDUMMA, N, A, LDA, B, LDB, VL, LDVL,$ VR, LDVR, N, IN, WORK( IWORK ), IINFO )IF( IINFO.NE.0 ) THENINFO = N + 7GO TO 120END IF** Undo balancing on VL and VR, rescale*IF( ILVL ) THENCALL DGGBAK( 'P', 'L', N, ILO, IHI, WORK( ILEFT ),$ WORK( IRIGHT ), N, VL, LDVL, IINFO )IF( IINFO.NE.0 ) THENINFO = N + 8GO TO 120END IFDO 50 JC = 1, NIF( ALPHAI( JC ).LT.ZERO )$ GO TO 50TEMP = ZEROIF( ALPHAI( JC ).EQ.ZERO ) THENDO 10 JR = 1, NTEMP = MAX( TEMP, ABS( VL( JR, JC ) ) )10 CONTINUEELSEDO 20 JR = 1, NTEMP = MAX( TEMP, ABS( VL( JR, JC ) )+$ ABS( VL( JR, JC+1 ) ) )20 CONTINUEEND IFIF( TEMP.LT.SAFMIN )$ GO TO 50TEMP = ONE / TEMPIF( ALPHAI( JC ).EQ.ZERO ) THENDO 30 JR = 1, NVL( JR, JC ) = VL( JR, JC )*TEMP30 CONTINUEELSEDO 40 JR = 1, NVL( JR, JC ) = VL( JR, JC )*TEMPVL( JR, JC+1 ) = VL( JR, JC+1 )*TEMP40 CONTINUEEND IF50 CONTINUEEND IFIF( ILVR ) THENCALL DGGBAK( 'P', 'R', N, ILO, IHI, WORK( ILEFT ),$ WORK( IRIGHT ), N, VR, LDVR, IINFO )IF( IINFO.NE.0 ) THENINFO = N + 9GO TO 120END IFDO 100 JC = 1, NIF( ALPHAI( JC ).LT.ZERO )$ GO TO 100TEMP = ZEROIF( ALPHAI( JC ).EQ.ZERO ) THENDO 60 JR = 1, NTEMP = MAX( TEMP, ABS( VR( JR, JC ) ) )60 CONTINUEELSEDO 70 JR = 1, NTEMP = MAX( TEMP, ABS( VR( JR, JC ) )+$ ABS( VR( JR, JC+1 ) ) )70 CONTINUEEND IFIF( TEMP.LT.SAFMIN )$ GO TO 100TEMP = ONE / TEMPIF( ALPHAI( JC ).EQ.ZERO ) THENDO 80 JR = 1, NVR( JR, JC ) = VR( JR, JC )*TEMP80 CONTINUEELSEDO 90 JR = 1, NVR( JR, JC ) = VR( JR, JC )*TEMPVR( JR, JC+1 ) = VR( JR, JC+1 )*TEMP90 CONTINUEEND IF100 CONTINUEEND IF** End of eigenvector calculation*END IF** Undo scaling in alpha, beta** Note: this does not give the alpha and beta for the unscaled* problem.** Un-scaling is limited to avoid underflow in alpha and beta* if they are significant.*DO 110 JC = 1, NABSAR = ABS( ALPHAR( JC ) )ABSAI = ABS( ALPHAI( JC ) )ABSB = ABS( BETA( JC ) )SALFAR = ANRM*ALPHAR( JC )SALFAI = ANRM*ALPHAI( JC )SBETA = BNRM*BETA( JC )ILIMIT = .FALSE.SCALE = ONE** Check for significant underflow in ALPHAI*IF( ABS( SALFAI ).LT.SAFMIN .AND. ABSAI.GE.$ MAX( SAFMIN, EPS*ABSAR, EPS*ABSB ) ) THENILIMIT = .TRUE.SCALE = ( ONEPLS*SAFMIN / ANRM1 ) /$ MAX( ONEPLS*SAFMIN, ANRM2*ABSAI )*ELSE IF( SALFAI.EQ.ZERO ) THEN** If insignificant underflow in ALPHAI, then make the* conjugate eigenvalue real.*IF( ALPHAI( JC ).LT.ZERO .AND. JC.GT.1 ) THENALPHAI( JC-1 ) = ZEROELSE IF( ALPHAI( JC ).GT.ZERO .AND. JC.LT.N ) THENALPHAI( JC+1 ) = ZEROEND IFEND IF** Check for significant underflow in ALPHAR*IF( ABS( SALFAR ).LT.SAFMIN .AND. ABSAR.GE.$ MAX( SAFMIN, EPS*ABSAI, EPS*ABSB ) ) THENILIMIT = .TRUE.SCALE = MAX( SCALE, ( ONEPLS*SAFMIN / ANRM1 ) /$ MAX( ONEPLS*SAFMIN, ANRM2*ABSAR ) )END IF** Check for significant underflow in BETA*IF( ABS( SBETA ).LT.SAFMIN .AND. ABSB.GE.$ MAX( SAFMIN, EPS*ABSAR, EPS*ABSAI ) ) THENILIMIT = .TRUE.SCALE = MAX( SCALE, ( ONEPLS*SAFMIN / BNRM1 ) /$ MAX( ONEPLS*SAFMIN, BNRM2*ABSB ) )END IF** Check for possible overflow when limiting scaling*IF( ILIMIT ) THENTEMP = ( SCALE*SAFMIN )*MAX( ABS( SALFAR ), ABS( SALFAI ),$ ABS( SBETA ) )IF( TEMP.GT.ONE )$ SCALE = SCALE / TEMPIF( SCALE.LT.ONE )$ ILIMIT = .FALSE.END IF** Recompute un-scaled ALPHAR, ALPHAI, BETA if necessary.*IF( ILIMIT ) THENSALFAR = ( SCALE*ALPHAR( JC ) )*ANRMSALFAI = ( SCALE*ALPHAI( JC ) )*ANRMSBETA = ( SCALE*BETA( JC ) )*BNRMEND IFALPHAR( JC ) = SALFARALPHAI( JC ) = SALFAIBETA( JC ) = SBETA110 CONTINUE*120 CONTINUEWORK( 1 ) = LWKOPT*RETURN** End of DGEGV*ENDSUBROUTINE DGELS( TRANS, M, N, NRHS, A, LDA, B, LDB, WORK, LWORK,$ INFO )** -- LAPACK driver 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 INFO, LDA, LDB, LWORK, M, N, NRHS* ..* .. Array Arguments ..DOUBLE PRECISION A( LDA, * ), B( LDB, * ), WORK( * )* ..** Purpose* =======** DGELS solves overdetermined or underdetermined real linear systems* involving an M-by-N matrix A, or its transpose, using a QR or LQ* factorization of A. It is assumed that A has full rank.** The following options are provided:** 1. If TRANS = 'N' and m >= n: find the least squares solution of* an overdetermined system, i.e., solve the least squares problem* minimize || B - A*X ||.** 2. If TRANS = 'N' and m < n: find the minimum norm solution of* an underdetermined system A * X = B.** 3. If TRANS = 'T' and m >= n: find the minimum norm solution of* an undetermined system A**T * X = B.** 4. If TRANS = 'T' and m < n: find the least squares solution of* an overdetermined system, i.e., solve the least squares problem* minimize || B - A**T * X ||.** Several right hand side vectors b and solution vectors x can be* handled in a single call; they are stored as the columns of the* M-by-NRHS right hand side matrix B and the N-by-NRHS solution* matrix X.** Arguments* =========** TRANS (input) CHARACTER* = 'N': the linear system involves A;* = 'T': the linear system involves A**T.** 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.** 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/output) DOUBLE PRECISION array, dimension (LDA,N)* On entry, the M-by-N matrix A.* On exit,* if M >= N, A is overwritten by details of its QR* factorization as returned by DGEQRF;* if M < N, A is overwritten by details of its LQ* factorization as returned by DGELQF.** LDA (input) INTEGER* The leading dimension of the array A. LDA >= max(1,M).** B (input/output) DOUBLE PRECISION array, dimension (LDB,NRHS)* On entry, the matrix B of right hand side vectors, stored* columnwise; B is M-by-NRHS if TRANS = 'N', or N-by-NRHS* if TRANS = 'T'.* On exit, B is overwritten by the solution vectors, stored* columnwise:* if TRANS = 'N' and m >= n, rows 1 to n of B contain the least* squares solution vectors; the residual sum of squares for the* solution in each column is given by the sum of squares of* elements N+1 to M in that column;* if TRANS = 'N' and m < n, rows 1 to N of B contain the* minimum norm solution vectors;* if TRANS = 'T' and m >= n, rows 1 to M of B contain the* minimum norm solution vectors;* if TRANS = 'T' and m < n, rows 1 to M of B contain the* least squares solution vectors; the residual sum of squares* for the solution in each column is given by the sum of* squares of elements M+1 to N in that column.** LDB (input) INTEGER* The leading dimension of the array B. LDB >= MAX(1,M,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 >= max( 1, MN + max( MN, NRHS ) ).* For optimal performance,* LWORK >= max( 1, MN + max( MN, NRHS )*NB ).* where MN = min(M,N) and NB is the optimum block size.** 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.0D0, ONE = 1.0D0 )* ..* .. Local Scalars ..LOGICAL LQUERY, TPSDINTEGER BROW, I, IASCL, IBSCL, J, MN, NB, SCLLEN, WSIZEDOUBLE PRECISION ANRM, BIGNUM, BNRM, SMLNUM* ..* .. Local Arrays ..DOUBLE PRECISION RWORK( 1 )* ..* .. External Functions ..LOGICAL LSAMEINTEGER ILAENVDOUBLE PRECISION DLAMCH, DLANGEEXTERNAL LSAME, ILAENV, DLAMCH, DLANGE* ..* .. External Subroutines ..EXTERNAL DGELQF, DGEQRF, DLASCL, DLASET, DORMLQ, DORMQR,$ DTRSM, XERBLA* ..* .. Intrinsic Functions ..INTRINSIC DBLE, MAX, MIN* ..* .. Executable Statements ..** Test the input arguments.*INFO = 0MN = MIN( M, N )LQUERY = ( LWORK.EQ.-1 )IF( .NOT.( LSAME( TRANS, 'N' ) .OR. LSAME( TRANS, 'T' ) ) ) THENINFO = -1ELSE IF( M.LT.0 ) THENINFO = -2ELSE IF( N.LT.0 ) THENINFO = -3ELSE IF( NRHS.LT.0 ) THENINFO = -4ELSE IF( LDA.LT.MAX( 1, M ) ) THENINFO = -6ELSE IF( LDB.LT.MAX( 1, M, N ) ) THENINFO = -8ELSE IF( LWORK.LT.MAX( 1, MN+MAX( MN, NRHS ) ) .AND. .NOT.LQUERY )$ THENINFO = -10END IF** Figure out optimal block size*IF( INFO.EQ.0 .OR. INFO.EQ.-10 ) THEN*TPSD = .TRUE.IF( LSAME( TRANS, 'N' ) )$ TPSD = .FALSE.*IF( M.GE.N ) THENNB = ILAENV( 1, 'DGEQRF', ' ', M, N, -1, -1 )IF( TPSD ) THENNB = MAX( NB, ILAENV( 1, 'DORMQR', 'LN', M, NRHS, N,$ -1 ) )ELSENB = MAX( NB, ILAENV( 1, 'DORMQR', 'LT', M, NRHS, N,$ -1 ) )END IFELSENB = ILAENV( 1, 'DGELQF', ' ', M, N, -1, -1 )IF( TPSD ) THENNB = MAX( NB, ILAENV( 1, 'DORMLQ', 'LT', N, NRHS, M,$ -1 ) )ELSENB = MAX( NB, ILAENV( 1, 'DORMLQ', 'LN', N, NRHS, M,$ -1 ) )END IFEND IF*WSIZE = MAX( 1, MN+MAX( MN, NRHS )*NB )WORK( 1 ) = DBLE( WSIZE )*END IF*IF( INFO.NE.0 ) THENCALL XERBLA( 'DGELS ', -INFO )RETURNELSE IF( LQUERY ) THENRETURNEND IF** Quick return if possible*IF( MIN( M, N, NRHS ).EQ.0 ) THENCALL DLASET( 'Full', MAX( M, N ), NRHS, ZERO, ZERO, B, LDB )RETURNEND IF** Get machine parameters*SMLNUM = DLAMCH( 'S' ) / DLAMCH( 'P' )BIGNUM = ONE / SMLNUMCALL DLABAD( SMLNUM, BIGNUM )** Scale A, B if max element outside range [SMLNUM,BIGNUM]*ANRM = DLANGE( 'M', M, N, A, LDA, RWORK )IASCL = 0IF( ANRM.GT.ZERO .AND. ANRM.LT.SMLNUM ) THEN** Scale matrix norm up to SMLNUM*CALL DLASCL( 'G', 0, 0, ANRM, SMLNUM, M, N, A, LDA, INFO )IASCL = 1ELSE IF( ANRM.GT.BIGNUM ) THEN** Scale matrix norm down to BIGNUM*CALL DLASCL( 'G', 0, 0, ANRM, BIGNUM, M, N, A, LDA, INFO )IASCL = 2ELSE IF( ANRM.EQ.ZERO ) THEN** Matrix all zero. Return zero solution.*CALL DLASET( 'F', MAX( M, N ), NRHS, ZERO, ZERO, B, LDB )GO TO 50END IF*BROW = MIF( TPSD )$ BROW = NBNRM = DLANGE( 'M', BROW, NRHS, B, LDB, RWORK )IBSCL = 0IF( BNRM.GT.ZERO .AND. BNRM.LT.SMLNUM ) THEN** Scale matrix norm up to SMLNUM*CALL DLASCL( 'G', 0, 0, BNRM, SMLNUM, BROW, NRHS, B, LDB,$ INFO )IBSCL = 1ELSE IF( BNRM.GT.BIGNUM ) THEN** Scale matrix norm down to BIGNUM*CALL DLASCL( 'G', 0, 0, BNRM, BIGNUM, BROW, NRHS, B, LDB,$ INFO )IBSCL = 2END IF*IF( M.GE.N ) THEN** compute QR factorization of A*CALL DGEQRF( M, N, A, LDA, WORK( 1 ), WORK( MN+1 ), LWORK-MN,$ INFO )** workspace at least N, optimally N*NB*IF( .NOT.TPSD ) THEN** Least-Squares Problem min || A * X - B ||** B(1:M,1:NRHS) := Q' * B(1:M,1:NRHS)*CALL DORMQR( 'Left', 'Transpose', M, NRHS, N, A, LDA,$ WORK( 1 ), B, LDB, WORK( MN+1 ), LWORK-MN,$ INFO )** workspace at least NRHS, optimally NRHS*NB** B(1:N,1:NRHS) := inv(R) * B(1:N,1:NRHS)*CALL DTRSM( 'Left', 'Upper', 'No transpose', 'Non-unit', N,$ NRHS, ONE, A, LDA, B, LDB )*SCLLEN = N*ELSE** Overdetermined system of equations A' * X = B** B(1:N,1:NRHS) := inv(R') * B(1:N,1:NRHS)*CALL DTRSM( 'Left', 'Upper', 'Transpose', 'Non-unit', N,$ NRHS, ONE, A, LDA, B, LDB )** B(N+1:M,1:NRHS) = ZERO*DO 20 J = 1, NRHSDO 10 I = N + 1, MB( I, J ) = ZERO10 CONTINUE20 CONTINUE** B(1:M,1:NRHS) := Q(1:N,:) * B(1:N,1:NRHS)*CALL DORMQR( 'Left', 'No transpose', M, NRHS, N, A, LDA,$ WORK( 1 ), B, LDB, WORK( MN+1 ), LWORK-MN,$ INFO )** workspace at least NRHS, optimally NRHS*NB*SCLLEN = M*END IF*ELSE** Compute LQ factorization of A*CALL DGELQF( M, N, A, LDA, WORK( 1 ), WORK( MN+1 ), LWORK-MN,$ INFO )** workspace at least M, optimally M*NB.*IF( .NOT.TPSD ) THEN** underdetermined system of equations A * X = B** B(1:M,1:NRHS) := inv(L) * B(1:M,1:NRHS)*CALL DTRSM( 'Left', 'Lower', 'No transpose', 'Non-unit', M,$ NRHS, ONE, A, LDA, B, LDB )** B(M+1:N,1:NRHS) = 0*DO 40 J = 1, NRHSDO 30 I = M + 1, NB( I, J ) = ZERO30 CONTINUE40 CONTINUE** B(1:N,1:NRHS) := Q(1:N,:)' * B(1:M,1:NRHS)*CALL DORMLQ( 'Left', 'Transpose', N, NRHS, M, A, LDA,$ WORK( 1 ), B, LDB, WORK( MN+1 ), LWORK-MN,$ INFO )** workspace at least NRHS, optimally NRHS*NB*SCLLEN = N*ELSE** overdetermined system min || A' * X - B ||** B(1:N,1:NRHS) := Q * B(1:N,1:NRHS)*CALL DORMLQ( 'Left', 'No transpose', N, NRHS, M, A, LDA,$ WORK( 1 ), B, LDB, WORK( MN+1 ), LWORK-MN,$ INFO )** workspace at least NRHS, optimally NRHS*NB** B(1:M,1:NRHS) := inv(L') * B(1:M,1:NRHS)*CALL DTRSM( 'Left', 'Lower', 'Transpose', 'Non-unit', M,$ NRHS, ONE, A, LDA, B, LDB )*SCLLEN = M*END IF*END IF** Undo scaling*IF( IASCL.EQ.1 ) THENCALL DLASCL( 'G', 0, 0, ANRM, SMLNUM, SCLLEN, NRHS, B, LDB,$ INFO )ELSE IF( IASCL.EQ.2 ) THENCALL DLASCL( 'G', 0, 0, ANRM, BIGNUM, SCLLEN, NRHS, B, LDB,$ INFO )END IFIF( IBSCL.EQ.1 ) THENCALL DLASCL( 'G', 0, 0, SMLNUM, BNRM, SCLLEN, NRHS, B, LDB,$ INFO )ELSE IF( IBSCL.EQ.2 ) THENCALL DLASCL( 'G', 0, 0, BIGNUM, BNRM, SCLLEN, NRHS, B, LDB,$ INFO )END IF*50 CONTINUEWORK( 1 ) = DBLE( WSIZE )*RETURN** End of DGELS*ENDSUBROUTINE DGELSD( M, N, NRHS, A, LDA, B, LDB, S, RCOND, RANK,$ WORK, LWORK, IWORK, INFO )** -- LAPACK driver 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 ..INTEGER INFO, LDA, LDB, LWORK, M, N, NRHS, RANKDOUBLE PRECISION RCOND* ..* .. Array Arguments ..INTEGER IWORK( * )DOUBLE PRECISION A( LDA, * ), B( LDB, * ), S( * ), WORK( * )* ..** Purpose* =======** DGELSD computes the minimum-norm solution to a real linear least* squares problem:* minimize 2-norm(| b - A*x |)* using the singular value decomposition (SVD) of A. A is an M-by-N* matrix which may be rank-deficient.** Several right hand side vectors b and solution vectors x can be* handled in a single call; they are stored as the columns of the* M-by-NRHS right hand side matrix B and the N-by-NRHS solution* matrix X.** The problem is solved in three steps:* (1) Reduce the coefficient matrix A to bidiagonal form with* Householder transformations, reducing the original problem* into a "bidiagonal least squares problem" (BLS)* (2) Solve the BLS using a divide and conquer approach.* (3) Apply back all the Householder tranformations to solve* the original least squares problem.** The effective rank of A is determined by treating as zero those* singular values which are less than RCOND times the largest singular* value.** The divide and conquer algorithm makes very mild assumptions about* floating point arithmetic. It will work on machines with a guard* digit in add/subtract, or on those binary machines without guard* digits which subtract like the Cray X-MP, Cray Y-MP, Cray C-90, or* Cray-2. It could conceivably fail on hexadecimal or decimal machines* without guard digits, but we know of none.** Arguments* =========** M (input) INTEGER* The number of rows of A. M >= 0.** N (input) INTEGER* The number of columns of 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)* On entry, the M-by-N matrix A.* On exit, A has been destroyed.** LDA (input) INTEGER* The leading dimension of the array A. LDA >= max(1,M).** B (input/output) DOUBLE PRECISION array, dimension (LDB,NRHS)* On entry, the M-by-NRHS right hand side matrix B.* On exit, B is overwritten by the N-by-NRHS solution* matrix X. If m >= n and RANK = n, the residual* sum-of-squares for the solution in the i-th column is given* by the sum of squares of elements n+1:m in that column.** LDB (input) INTEGER* The leading dimension of the array B. LDB >= max(1,max(M,N)).** S (output) DOUBLE PRECISION array, dimension (min(M,N))* The singular values of A in decreasing order.* The condition number of A in the 2-norm = S(1)/S(min(m,n)).** RCOND (input) DOUBLE PRECISION* RCOND is used to determine the effective rank of A.* Singular values S(i) <= RCOND*S(1) are treated as zero.* If RCOND < 0, machine precision is used instead.** RANK (output) INTEGER* The effective rank of A, i.e., the number of singular values* which are greater than RCOND*S(1).** 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 must be at least 1.* The exact minimum amount of workspace needed depends on M,* N and NRHS. As long as LWORK is at least* 12*N + 2*N*SMLSIZ + 8*N*NLVL + N*NRHS + (SMLSIZ+1)**2,* if M is greater than or equal to N or* 12*M + 2*M*SMLSIZ + 8*M*NLVL + M*NRHS + (SMLSIZ+1)**2,* if M is less than N, the code will execute correctly.* SMLSIZ is returned by ILAENV and is equal to the maximum* size of the subproblems at the bottom of the computation* tree (usually about 25), and* NLVL = MAX( 0, INT( LOG_2( MIN( M,N )/(SMLSIZ+1) ) ) + 1 )* For good performance, LWORK should generally be larger.** 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)* LIWORK >= 3 * MINMN * NLVL + 11 * MINMN,* where MINMN = MIN( M,N ).** INFO (output) INTEGER* = 0: successful exit* < 0: if INFO = -i, the i-th argument had an illegal value.* > 0: the algorithm for computing the SVD failed to converge;* if INFO = i, i off-diagonal elements of an intermediate* bidiagonal form did not converge to zero.** Further Details* ===============** Based on contributions by* Ming Gu and Ren-Cang Li, Computer Science Division, University of* California at Berkeley, USA* Osni Marques, LBNL/NERSC, USA** =====================================================================** .. Parameters ..DOUBLE PRECISION ZERO, ONE, TWOPARAMETER ( ZERO = 0.0D0, ONE = 1.0D0, TWO = 2.0D0 )* ..* .. Local Scalars ..LOGICAL LQUERYINTEGER IASCL, IBSCL, IE, IL, ITAU, ITAUP, ITAUQ,$ LDWORK, MAXMN, MAXWRK, MINMN, MINWRK, MM,$ MNTHR, NLVL, NWORK, SMLSIZ, WLALSDDOUBLE PRECISION ANRM, BIGNUM, BNRM, EPS, SFMIN, SMLNUM* ..* .. External Subroutines ..EXTERNAL DGEBRD, DGELQF, DGEQRF, DLABAD, DLACPY, DLALSD,$ DLASCL, DLASET, DORMBR, DORMLQ, DORMQR, XERBLA* ..* .. External Functions ..INTEGER ILAENVDOUBLE PRECISION DLAMCH, DLANGEEXTERNAL ILAENV, DLAMCH, DLANGE* ..* .. Intrinsic Functions ..INTRINSIC DBLE, INT, LOG, MAX, MIN* ..* .. Executable Statements ..** Test the input arguments.*INFO = 0MINMN = MIN( M, N )MAXMN = MAX( M, N )MNTHR = ILAENV( 6, 'DGELSD', ' ', M, N, NRHS, -1 )LQUERY = ( LWORK.EQ.-1 )IF( M.LT.0 ) THENINFO = -1ELSE IF( N.LT.0 ) THENINFO = -2ELSE IF( NRHS.LT.0 ) THENINFO = -3ELSE IF( LDA.LT.MAX( 1, M ) ) THENINFO = -5ELSE IF( LDB.LT.MAX( 1, MAXMN ) ) THENINFO = -7END IF*SMLSIZ = ILAENV( 9, 'DGELSD', ' ', 0, 0, 0, 0 )** Compute workspace.* (Note: Comments in the code beginning "Workspace:" describe the* minimal amount of workspace needed at that point in the code,* as well as the preferred amount for good performance.* NB refers to the optimal block size for the immediately* following subroutine, as returned by ILAENV.)*MINWRK = 1MINMN = MAX( 1, MINMN )NLVL = MAX( INT( LOG( DBLE( MINMN ) / DBLE( SMLSIZ+1 ) ) /$ LOG( TWO ) ) + 1, 0 )*IF( INFO.EQ.0 ) THENMAXWRK = 0MM = MIF( M.GE.N .AND. M.GE.MNTHR ) THEN** Path 1a - overdetermined, with many more rows than columns.*MM = NMAXWRK = MAX( MAXWRK, N+N*ILAENV( 1, 'DGEQRF', ' ', M, N,$ -1, -1 ) )MAXWRK = MAX( MAXWRK, N+NRHS*$ ILAENV( 1, 'DORMQR', 'LT', M, NRHS, N, -1 ) )END IFIF( M.GE.N ) THEN** Path 1 - overdetermined or exactly determined.*MAXWRK = MAX( MAXWRK, 3*N+( MM+N )*$ ILAENV( 1, 'DGEBRD', ' ', MM, N, -1, -1 ) )MAXWRK = MAX( MAXWRK, 3*N+NRHS*$ ILAENV( 1, 'DORMBR', 'QLT', MM, NRHS, N, -1 ) )MAXWRK = MAX( MAXWRK, 3*N+( N-1 )*$ ILAENV( 1, 'DORMBR', 'PLN', N, NRHS, N, -1 ) )WLALSD = 9*N+2*N*SMLSIZ+8*N*NLVL+N*NRHS+(SMLSIZ+1)**2MAXWRK = MAX( MAXWRK, 3*N+WLALSD )MINWRK = MAX( 3*N+MM, 3*N+NRHS, 3*N+WLALSD )END IFIF( N.GT.M ) THENWLALSD = 9*M+2*M*SMLSIZ+8*M*NLVL+M*NRHS+(SMLSIZ+1)**2IF( N.GE.MNTHR ) THEN** Path 2a - underdetermined, with many more columns* than rows.*MAXWRK = M + M*ILAENV( 1, 'DGELQF', ' ', M, N, -1, -1 )MAXWRK = MAX( MAXWRK, M*M+4*M+2*M*$ ILAENV( 1, 'DGEBRD', ' ', M, M, -1, -1 ) )MAXWRK = MAX( MAXWRK, M*M+4*M+NRHS*$ ILAENV( 1, 'DORMBR', 'QLT', M, NRHS, M, -1 ) )MAXWRK = MAX( MAXWRK, M*M+4*M+( M-1 )*$ ILAENV( 1, 'DORMBR', 'PLN', M, NRHS, M, -1 ) )IF( NRHS.GT.1 ) THENMAXWRK = MAX( MAXWRK, M*M+M+M*NRHS )ELSEMAXWRK = MAX( MAXWRK, M*M+2*M )END IFMAXWRK = MAX( MAXWRK, M+NRHS*$ ILAENV( 1, 'DORMLQ', 'LT', N, NRHS, M, -1 ) )MAXWRK = MAX( MAXWRK, M*M+4*M+WLALSD )ELSE** Path 2 - remaining underdetermined cases.*MAXWRK = 3*M + ( N+M )*ILAENV( 1, 'DGEBRD', ' ', M, N,$ -1, -1 )MAXWRK = MAX( MAXWRK, 3*M+NRHS*$ ILAENV( 1, 'DORMBR', 'QLT', M, NRHS, N, -1 ) )MAXWRK = MAX( MAXWRK, 3*M+M*$ ILAENV( 1, 'DORMBR', 'PLN', N, NRHS, M, -1 ) )MAXWRK = MAX( MAXWRK, 3*M+WLALSD )END IFMINWRK = MAX( 3*M+NRHS, 3*M+M, 3*M+WLALSD )END IFMINWRK = MIN( MINWRK, MAXWRK )WORK( 1 ) = MAXWRKIF( LWORK.LT.MINWRK .AND. .NOT.LQUERY ) THENINFO = -12END IFEND IF*IF( INFO.NE.0 ) THENCALL XERBLA( 'DGELSD', -INFO )RETURNELSE IF( LQUERY ) THENGO TO 10END IF** Quick return if possible.*IF( M.EQ.0 .OR. N.EQ.0 ) THENRANK = 0RETURNEND IF** Get machine parameters.*EPS = DLAMCH( 'P' )SFMIN = DLAMCH( 'S' )SMLNUM = SFMIN / EPSBIGNUM = ONE / SMLNUMCALL DLABAD( SMLNUM, BIGNUM )** Scale A if max entry outside range [SMLNUM,BIGNUM].*ANRM = DLANGE( 'M', M, N, A, LDA, WORK )IASCL = 0IF( ANRM.GT.ZERO .AND. ANRM.LT.SMLNUM ) THEN** Scale matrix norm up to SMLNUM.*CALL DLASCL( 'G', 0, 0, ANRM, SMLNUM, M, N, A, LDA, INFO )IASCL = 1ELSE IF( ANRM.GT.BIGNUM ) THEN** Scale matrix norm down to BIGNUM.*CALL DLASCL( 'G', 0, 0, ANRM, BIGNUM, M, N, A, LDA, INFO )IASCL = 2ELSE IF( ANRM.EQ.ZERO ) THEN** Matrix all zero. Return zero solution.*CALL DLASET( 'F', MAX( M, N ), NRHS, ZERO, ZERO, B, LDB )CALL DLASET( 'F', MINMN, 1, ZERO, ZERO, S, 1 )RANK = 0GO TO 10END IF** Scale B if max entry outside range [SMLNUM,BIGNUM].*BNRM = DLANGE( 'M', M, NRHS, B, LDB, WORK )IBSCL = 0IF( BNRM.GT.ZERO .AND. BNRM.LT.SMLNUM ) THEN** Scale matrix norm up to SMLNUM.*CALL DLASCL( 'G', 0, 0, BNRM, SMLNUM, M, NRHS, B, LDB, INFO )IBSCL = 1ELSE IF( BNRM.GT.BIGNUM ) THEN** Scale matrix norm down to BIGNUM.*CALL DLASCL( 'G', 0, 0, BNRM, BIGNUM, M, NRHS, B, LDB, INFO )IBSCL = 2END IF** If M < N make sure certain entries of B are zero.*IF( M.LT.N )$ CALL DLASET( 'F', N-M, NRHS, ZERO, ZERO, B( M+1, 1 ), LDB )** Overdetermined case.*IF( M.GE.N ) THEN** Path 1 - overdetermined or exactly determined.*MM = MIF( M.GE.MNTHR ) THEN** Path 1a - overdetermined, with many more rows than columns.*MM = NITAU = 1NWORK = ITAU + N** Compute A=Q*R.* (Workspace: need 2*N, prefer N+N*NB)*CALL DGEQRF( M, N, A, LDA, WORK( ITAU ), WORK( NWORK ),$ LWORK-NWORK+1, INFO )** Multiply B by transpose(Q).* (Workspace: need N+NRHS, prefer N+NRHS*NB)*CALL DORMQR( 'L', 'T', M, NRHS, N, A, LDA, WORK( ITAU ), B,$ LDB, WORK( NWORK ), LWORK-NWORK+1, INFO )** Zero out below R.*IF( N.GT.1 ) THENCALL DLASET( 'L', N-1, N-1, ZERO, ZERO, A( 2, 1 ), LDA )END IFEND IF*IE = 1ITAUQ = IE + NITAUP = ITAUQ + NNWORK = ITAUP + N** Bidiagonalize R in A.* (Workspace: need 3*N+MM, prefer 3*N+(MM+N)*NB)*CALL DGEBRD( MM, N, A, LDA, S, WORK( IE ), WORK( ITAUQ ),$ WORK( ITAUP ), WORK( NWORK ), LWORK-NWORK+1,$ INFO )** Multiply B by transpose of left bidiagonalizing vectors of R.* (Workspace: need 3*N+NRHS, prefer 3*N+NRHS*NB)*CALL DORMBR( 'Q', 'L', 'T', MM, NRHS, N, A, LDA, WORK( ITAUQ ),$ B, LDB, WORK( NWORK ), LWORK-NWORK+1, INFO )** Solve the bidiagonal least squares problem.*CALL DLALSD( 'U', SMLSIZ, N, NRHS, S, WORK( IE ), B, LDB,$ RCOND, RANK, WORK( NWORK ), IWORK, INFO )IF( INFO.NE.0 ) THENGO TO 10END IF** Multiply B by right bidiagonalizing vectors of R.*CALL DORMBR( 'P', 'L', 'N', N, NRHS, N, A, LDA, WORK( ITAUP ),$ B, LDB, WORK( NWORK ), LWORK-NWORK+1, INFO )*ELSE IF( N.GE.MNTHR .AND. LWORK.GE.4*M+M*M+$ MAX( M, 2*M-4, NRHS, N-3*M ) ) THEN** Path 2a - underdetermined, with many more columns than rows* and sufficient workspace for an efficient algorithm.*LDWORK = MIF( LWORK.GE.MAX( 4*M+M*LDA+MAX( M, 2*M-4, NRHS, N-3*M ),$ M*LDA+M+M*NRHS ) )LDWORK = LDAITAU = 1NWORK = M + 1** Compute A=L*Q.* (Workspace: need 2*M, prefer M+M*NB)*CALL DGELQF( M, N, A, LDA, WORK( ITAU ), WORK( NWORK ),$ LWORK-NWORK+1, INFO )IL = NWORK** Copy L to WORK(IL), zeroing out above its diagonal.*CALL DLACPY( 'L', M, M, A, LDA, WORK( IL ), LDWORK )CALL DLASET( 'U', M-1, M-1, ZERO, ZERO, WORK( IL+LDWORK ),$ LDWORK )IE = IL + LDWORK*MITAUQ = IE + MITAUP = ITAUQ + MNWORK = ITAUP + M** Bidiagonalize L in WORK(IL).* (Workspace: need M*M+5*M, prefer M*M+4*M+2*M*NB)*CALL DGEBRD( M, M, WORK( IL ), LDWORK, S, WORK( IE ),$ WORK( ITAUQ ), WORK( ITAUP ), WORK( NWORK ),$ LWORK-NWORK+1, INFO )** Multiply B by transpose of left bidiagonalizing vectors of L.* (Workspace: need M*M+4*M+NRHS, prefer M*M+4*M+NRHS*NB)*CALL DORMBR( 'Q', 'L', 'T', M, NRHS, M, WORK( IL ), LDWORK,$ WORK( ITAUQ ), B, LDB, WORK( NWORK ),$ LWORK-NWORK+1, INFO )** Solve the bidiagonal least squares problem.*CALL DLALSD( 'U', SMLSIZ, M, NRHS, S, WORK( IE ), B, LDB,$ RCOND, RANK, WORK( NWORK ), IWORK, INFO )IF( INFO.NE.0 ) THENGO TO 10END IF** Multiply B by right bidiagonalizing vectors of L.*CALL DORMBR( 'P', 'L', 'N', M, NRHS, M, WORK( IL ), LDWORK,$ WORK( ITAUP ), B, LDB, WORK( NWORK ),$ LWORK-NWORK+1, INFO )** Zero out below first M rows of B.*CALL DLASET( 'F', N-M, NRHS, ZERO, ZERO, B( M+1, 1 ), LDB )NWORK = ITAU + M** Multiply transpose(Q) by B.* (Workspace: need M+NRHS, prefer M+NRHS*NB)*CALL DORMLQ( 'L', 'T', N, NRHS, M, A, LDA, WORK( ITAU ), B,$ LDB, WORK( NWORK ), LWORK-NWORK+1, INFO )*ELSE** Path 2 - remaining underdetermined cases.*IE = 1ITAUQ = IE + MITAUP = ITAUQ + MNWORK = ITAUP + M** Bidiagonalize A.* (Workspace: need 3*M+N, prefer 3*M+(M+N)*NB)*CALL DGEBRD( M, N, A, LDA, S, WORK( IE ), WORK( ITAUQ ),$ WORK( ITAUP ), WORK( NWORK ), LWORK-NWORK+1,$ INFO )** Multiply B by transpose of left bidiagonalizing vectors.* (Workspace: need 3*M+NRHS, prefer 3*M+NRHS*NB)*CALL DORMBR( 'Q', 'L', 'T', M, NRHS, N, A, LDA, WORK( ITAUQ ),$ B, LDB, WORK( NWORK ), LWORK-NWORK+1, INFO )** Solve the bidiagonal least squares problem.*CALL DLALSD( 'L', SMLSIZ, M, NRHS, S, WORK( IE ), B, LDB,$ RCOND, RANK, WORK( NWORK ), IWORK, INFO )IF( INFO.NE.0 ) THENGO TO 10END IF** Multiply B by right bidiagonalizing vectors of A.*CALL DORMBR( 'P', 'L', 'N', N, NRHS, M, A, LDA, WORK( ITAUP ),$ B, LDB, WORK( NWORK ), LWORK-NWORK+1, INFO )*END IF** Undo scaling.*IF( IASCL.EQ.1 ) THENCALL DLASCL( 'G', 0, 0, ANRM, SMLNUM, N, NRHS, B, LDB, INFO )CALL DLASCL( 'G', 0, 0, SMLNUM, ANRM, MINMN, 1, S, MINMN,$ INFO )ELSE IF( IASCL.EQ.2 ) THENCALL DLASCL( 'G', 0, 0, ANRM, BIGNUM, N, NRHS, B, LDB, INFO )CALL DLASCL( 'G', 0, 0, BIGNUM, ANRM, MINMN, 1, S, MINMN,$ INFO )END IFIF( IBSCL.EQ.1 ) THENCALL DLASCL( 'G', 0, 0, SMLNUM, BNRM, N, NRHS, B, LDB, INFO )ELSE IF( IBSCL.EQ.2 ) THENCALL DLASCL( 'G', 0, 0, BIGNUM, BNRM, N, NRHS, B, LDB, INFO )END IF*10 CONTINUEWORK( 1 ) = MAXWRKRETURN** End of DGELSD*ENDSUBROUTINE DGELSS( M, N, NRHS, A, LDA, B, LDB, S, RCOND, RANK,$ WORK, LWORK, INFO )** -- LAPACK driver 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 ..INTEGER INFO, LDA, LDB, LWORK, M, N, NRHS, RANKDOUBLE PRECISION RCOND* ..* .. Array Arguments ..DOUBLE PRECISION A( LDA, * ), B( LDB, * ), S( * ), WORK( * )* ..** Purpose* =======** DGELSS computes the minimum norm solution to a real linear least* squares problem:** Minimize 2-norm(| b - A*x |).** using the singular value decomposition (SVD) of A. A is an M-by-N* matrix which may be rank-deficient.** Several right hand side vectors b and solution vectors x can be* handled in a single call; they are stored as the columns of the* M-by-NRHS right hand side matrix B and the N-by-NRHS solution matrix* X.** The effective rank of A is determined by treating as zero those* singular values which are less than RCOND times the largest singular* value.** 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.** 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/output) DOUBLE PRECISION array, dimension (LDA,N)* On entry, the M-by-N matrix A.* On exit, the first min(m,n) rows of A are overwritten with* its right singular vectors, stored rowwise.** LDA (input) INTEGER* The leading dimension of the array A. LDA >= max(1,M).** B (input/output) DOUBLE PRECISION array, dimension (LDB,NRHS)* On entry, the M-by-NRHS right hand side matrix B.* On exit, B is overwritten by the N-by-NRHS solution* matrix X. If m >= n and RANK = n, the residual* sum-of-squares for the solution in the i-th column is given* by the sum of squares of elements n+1:m in that column.** LDB (input) INTEGER* The leading dimension of the array B. LDB >= max(1,max(M,N)).** S (output) DOUBLE PRECISION array, dimension (min(M,N))* The singular values of A in decreasing order.* The condition number of A in the 2-norm = S(1)/S(min(m,n)).** RCOND (input) DOUBLE PRECISION* RCOND is used to determine the effective rank of A.* Singular values S(i) <= RCOND*S(1) are treated as zero.* If RCOND < 0, machine precision is used instead.** RANK (output) INTEGER* The effective rank of A, i.e., the number of singular values* which are greater than RCOND*S(1).** 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, and also:* LWORK >= 3*min(M,N) + max( 2*min(M,N), max(M,N), NRHS )* For good performance, LWORK should generally be larger.** 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: the algorithm for computing the SVD failed to converge;* if INFO = i, i off-diagonal elements of an intermediate* bidiagonal form did not converge to zero.** =====================================================================** .. Parameters ..DOUBLE PRECISION ZERO, ONEPARAMETER ( ZERO = 0.0D+0, ONE = 1.0D+0 )* ..* .. Local Scalars ..LOGICAL LQUERYINTEGER BDSPAC, BL, CHUNK, I, IASCL, IBSCL, IE, IL,$ ITAU, ITAUP, ITAUQ, IWORK, LDWORK, MAXMN,$ MAXWRK, MINMN, MINWRK, MM, MNTHRDOUBLE PRECISION ANRM, BIGNUM, BNRM, EPS, SFMIN, SMLNUM, THR* ..* .. Local Arrays ..DOUBLE PRECISION VDUM( 1 )* ..* .. External Subroutines ..EXTERNAL DBDSQR, DCOPY, DGEBRD, DGELQF, DGEMM, DGEMV,$ DGEQRF, DLABAD, DLACPY, DLASCL, DLASET, DORGBR,$ DORMBR, DORMLQ, DORMQR, DRSCL, XERBLA* ..* .. External Functions ..INTEGER ILAENVDOUBLE PRECISION DLAMCH, DLANGEEXTERNAL ILAENV, DLAMCH, DLANGE* ..* .. Intrinsic Functions ..INTRINSIC MAX, MIN* ..* .. Executable Statements ..** Test the input arguments*INFO = 0MINMN = MIN( M, N )MAXMN = MAX( M, N )MNTHR = ILAENV( 6, 'DGELSS', ' ', M, N, NRHS, -1 )LQUERY = ( LWORK.EQ.-1 )IF( M.LT.0 ) THENINFO = -1ELSE IF( N.LT.0 ) THENINFO = -2ELSE IF( NRHS.LT.0 ) THENINFO = -3ELSE IF( LDA.LT.MAX( 1, M ) ) THENINFO = -5ELSE IF( LDB.LT.MAX( 1, MAXMN ) ) THENINFO = -7END IF** Compute workspace* (Note: Comments in the code beginning "Workspace:" describe the* minimal amount of workspace needed at that point in the code,* as well as the preferred amount for good performance.* NB refers to the optimal block size for the immediately* following subroutine, as returned by ILAENV.)*MINWRK = 1IF( INFO.EQ.0 .AND. ( LWORK.GE.1 .OR. LQUERY ) ) THENMAXWRK = 0MM = MIF( M.GE.N .AND. M.GE.MNTHR ) THEN** Path 1a - overdetermined, with many more rows than columns*MM = NMAXWRK = MAX( MAXWRK, N+N*ILAENV( 1, 'DGEQRF', ' ', M, N,$ -1, -1 ) )MAXWRK = MAX( MAXWRK, N+NRHS*$ ILAENV( 1, 'DORMQR', 'LT', M, NRHS, N, -1 ) )END IFIF( M.GE.N ) THEN** Path 1 - overdetermined or exactly determined** Compute workspace needed for DBDSQR*BDSPAC = MAX( 1, 5*N )MAXWRK = MAX( MAXWRK, 3*N+( MM+N )*$ ILAENV( 1, 'DGEBRD', ' ', MM, N, -1, -1 ) )MAXWRK = MAX( MAXWRK, 3*N+NRHS*$ ILAENV( 1, 'DORMBR', 'QLT', MM, NRHS, N, -1 ) )MAXWRK = MAX( MAXWRK, 3*N+( N-1 )*$ ILAENV( 1, 'DORGBR', 'P', N, N, N, -1 ) )MAXWRK = MAX( MAXWRK, BDSPAC )MAXWRK = MAX( MAXWRK, N*NRHS )MINWRK = MAX( 3*N+MM, 3*N+NRHS, BDSPAC )MAXWRK = MAX( MINWRK, MAXWRK )END IFIF( N.GT.M ) THEN** Compute workspace needed for DBDSQR*BDSPAC = MAX( 1, 5*M )MINWRK = MAX( 3*M+NRHS, 3*M+N, BDSPAC )IF( N.GE.MNTHR ) THEN** Path 2a - underdetermined, with many more columns* than rows*MAXWRK = M + M*ILAENV( 1, 'DGELQF', ' ', M, N, -1, -1 )MAXWRK = MAX( MAXWRK, M*M+4*M+2*M*$ ILAENV( 1, 'DGEBRD', ' ', M, M, -1, -1 ) )MAXWRK = MAX( MAXWRK, M*M+4*M+NRHS*$ ILAENV( 1, 'DORMBR', 'QLT', M, NRHS, M, -1 ) )MAXWRK = MAX( MAXWRK, M*M+4*M+( M-1 )*$ ILAENV( 1, 'DORGBR', 'P', M, M, M, -1 ) )MAXWRK = MAX( MAXWRK, M*M+M+BDSPAC )IF( NRHS.GT.1 ) THENMAXWRK = MAX( MAXWRK, M*M+M+M*NRHS )ELSEMAXWRK = MAX( MAXWRK, M*M+2*M )END IFMAXWRK = MAX( MAXWRK, M+NRHS*$ ILAENV( 1, 'DORMLQ', 'LT', N, NRHS, M, -1 ) )ELSE** Path 2 - underdetermined*MAXWRK = 3*M + ( N+M )*ILAENV( 1, 'DGEBRD', ' ', M, N,$ -1, -1 )MAXWRK = MAX( MAXWRK, 3*M+NRHS*$ ILAENV( 1, 'DORMBR', 'QLT', M, NRHS, M, -1 ) )MAXWRK = MAX( MAXWRK, 3*M+M*$ ILAENV( 1, 'DORGBR', 'P', M, N, M, -1 ) )MAXWRK = MAX( MAXWRK, BDSPAC )MAXWRK = MAX( MAXWRK, N*NRHS )END IFEND IFMAXWRK = MAX( MINWRK, MAXWRK )WORK( 1 ) = MAXWRKEND IF*MINWRK = MAX( MINWRK, 1 )IF( LWORK.LT.MINWRK .AND. .NOT.LQUERY )$ INFO = -12IF( INFO.NE.0 ) THENCALL XERBLA( 'DGELSS', -INFO )RETURNELSE IF( LQUERY ) THENRETURNEND IF** Quick return if possible*IF( M.EQ.0 .OR. N.EQ.0 ) THENRANK = 0RETURNEND IF** Get machine parameters*EPS = DLAMCH( 'P' )SFMIN = DLAMCH( 'S' )SMLNUM = SFMIN / EPSBIGNUM = ONE / SMLNUMCALL DLABAD( SMLNUM, BIGNUM )** Scale A if max element outside range [SMLNUM,BIGNUM]*ANRM = DLANGE( 'M', M, N, A, LDA, WORK )IASCL = 0IF( ANRM.GT.ZERO .AND. ANRM.LT.SMLNUM ) THEN** Scale matrix norm up to SMLNUM*CALL DLASCL( 'G', 0, 0, ANRM, SMLNUM, M, N, A, LDA, INFO )IASCL = 1ELSE IF( ANRM.GT.BIGNUM ) THEN** Scale matrix norm down to BIGNUM*CALL DLASCL( 'G', 0, 0, ANRM, BIGNUM, M, N, A, LDA, INFO )IASCL = 2ELSE IF( ANRM.EQ.ZERO ) THEN** Matrix all zero. Return zero solution.*CALL DLASET( 'F', MAX( M, N ), NRHS, ZERO, ZERO, B, LDB )CALL DLASET( 'F', MINMN, 1, ZERO, ZERO, S, 1 )RANK = 0GO TO 70END IF** Scale B if max element outside range [SMLNUM,BIGNUM]*BNRM = DLANGE( 'M', M, NRHS, B, LDB, WORK )IBSCL = 0IF( BNRM.GT.ZERO .AND. BNRM.LT.SMLNUM ) THEN** Scale matrix norm up to SMLNUM*CALL DLASCL( 'G', 0, 0, BNRM, SMLNUM, M, NRHS, B, LDB, INFO )IBSCL = 1ELSE IF( BNRM.GT.BIGNUM ) THEN** Scale matrix norm down to BIGNUM*CALL DLASCL( 'G', 0, 0, BNRM, BIGNUM, M, NRHS, B, LDB, INFO )IBSCL = 2END IF** Overdetermined case*IF( M.GE.N ) THEN** Path 1 - overdetermined or exactly determined*MM = MIF( M.GE.MNTHR ) THEN** Path 1a - overdetermined, with many more rows than columns*MM = NITAU = 1IWORK = ITAU + N** Compute A=Q*R* (Workspace: need 2*N, prefer N+N*NB)*CALL DGEQRF( M, N, A, LDA, WORK( ITAU ), WORK( IWORK ),$ LWORK-IWORK+1, INFO )** Multiply B by transpose(Q)* (Workspace: need N+NRHS, prefer N+NRHS*NB)*CALL DORMQR( 'L', 'T', M, NRHS, N, A, LDA, WORK( ITAU ), B,$ LDB, WORK( IWORK ), LWORK-IWORK+1, INFO )** Zero out below R*IF( N.GT.1 )$ CALL DLASET( 'L', N-1, N-1, ZERO, ZERO, A( 2, 1 ), LDA )END IF*IE = 1ITAUQ = IE + NITAUP = ITAUQ + NIWORK = ITAUP + N** Bidiagonalize R in A* (Workspace: need 3*N+MM, prefer 3*N+(MM+N)*NB)*CALL DGEBRD( MM, N, A, LDA, S, WORK( IE ), WORK( ITAUQ ),$ WORK( ITAUP ), WORK( IWORK ), LWORK-IWORK+1,$ INFO )** Multiply B by transpose of left bidiagonalizing vectors of R* (Workspace: need 3*N+NRHS, prefer 3*N+NRHS*NB)*CALL DORMBR( 'Q', 'L', 'T', MM, NRHS, N, A, LDA, WORK( ITAUQ ),$ B, LDB, WORK( IWORK ), LWORK-IWORK+1, INFO )** Generate right bidiagonalizing vectors of R in A* (Workspace: need 4*N-1, prefer 3*N+(N-1)*NB)*CALL DORGBR( 'P', N, N, N, A, LDA, WORK( ITAUP ),$ WORK( IWORK ), LWORK-IWORK+1, INFO )IWORK = IE + N** Perform bidiagonal QR iteration* multiply B by transpose of left singular vectors* compute right singular vectors in A* (Workspace: need BDSPAC)*CALL DBDSQR( 'U', N, N, 0, NRHS, S, WORK( IE ), A, LDA, VDUM,$ 1, B, LDB, WORK( IWORK ), INFO )IF( INFO.NE.0 )$ GO TO 70** Multiply B by reciprocals of singular values*THR = MAX( RCOND*S( 1 ), SFMIN )IF( RCOND.LT.ZERO )$ THR = MAX( EPS*S( 1 ), SFMIN )RANK = 0DO 10 I = 1, NIF( S( I ).GT.THR ) THENCALL DRSCL( NRHS, S( I ), B( I, 1 ), LDB )RANK = RANK + 1ELSECALL DLASET( 'F', 1, NRHS, ZERO, ZERO, B( I, 1 ), LDB )END IF10 CONTINUE** Multiply B by right singular vectors* (Workspace: need N, prefer N*NRHS)*IF( LWORK.GE.LDB*NRHS .AND. NRHS.GT.1 ) THENCALL DGEMM( 'T', 'N', N, NRHS, N, ONE, A, LDA, B, LDB, ZERO,$ WORK, LDB )CALL DLACPY( 'G', N, NRHS, WORK, LDB, B, LDB )ELSE IF( NRHS.GT.1 ) THENCHUNK = LWORK / NDO 20 I = 1, NRHS, CHUNKBL = MIN( NRHS-I+1, CHUNK )CALL DGEMM( 'T', 'N', N, BL, N, ONE, A, LDA, B( 1, I ),$ LDB, ZERO, WORK, N )CALL DLACPY( 'G', N, BL, WORK, N, B( 1, I ), LDB )20 CONTINUEELSECALL DGEMV( 'T', N, N, ONE, A, LDA, B, 1, ZERO, WORK, 1 )CALL DCOPY( N, WORK, 1, B, 1 )END IF*ELSE IF( N.GE.MNTHR .AND. LWORK.GE.4*M+M*M+$ MAX( M, 2*M-4, NRHS, N-3*M ) ) THEN** Path 2a - underdetermined, with many more columns than rows* and sufficient workspace for an efficient algorithm*LDWORK = MIF( LWORK.GE.MAX( 4*M+M*LDA+MAX( M, 2*M-4, NRHS, N-3*M ),$ M*LDA+M+M*NRHS ) )LDWORK = LDAITAU = 1IWORK = M + 1** Compute A=L*Q* (Workspace: need 2*M, prefer M+M*NB)*CALL DGELQF( M, N, A, LDA, WORK( ITAU ), WORK( IWORK ),$ LWORK-IWORK+1, INFO )IL = IWORK** Copy L to WORK(IL), zeroing out above it*CALL DLACPY( 'L', M, M, A, LDA, WORK( IL ), LDWORK )CALL DLASET( 'U', M-1, M-1, ZERO, ZERO, WORK( IL+LDWORK ),$ LDWORK )IE = IL + LDWORK*MITAUQ = IE + MITAUP = ITAUQ + MIWORK = ITAUP + M** Bidiagonalize L in WORK(IL)* (Workspace: need M*M+5*M, prefer M*M+4*M+2*M*NB)*CALL DGEBRD( M, M, WORK( IL ), LDWORK, S, WORK( IE ),$ WORK( ITAUQ ), WORK( ITAUP ), WORK( IWORK ),$ LWORK-IWORK+1, INFO )** Multiply B by transpose of left bidiagonalizing vectors of L* (Workspace: need M*M+4*M+NRHS, prefer M*M+4*M+NRHS*NB)*CALL DORMBR( 'Q', 'L', 'T', M, NRHS, M, WORK( IL ), LDWORK,$ WORK( ITAUQ ), B, LDB, WORK( IWORK ),$ LWORK-IWORK+1, INFO )** Generate right bidiagonalizing vectors of R in WORK(IL)* (Workspace: need M*M+5*M-1, prefer M*M+4*M+(M-1)*NB)*CALL DORGBR( 'P', M, M, M, WORK( IL ), LDWORK, WORK( ITAUP ),$ WORK( IWORK ), LWORK-IWORK+1, INFO )IWORK = IE + M** Perform bidiagonal QR iteration,* computing right singular vectors of L in WORK(IL) and* multiplying B by transpose of left singular vectors* (Workspace: need M*M+M+BDSPAC)*CALL DBDSQR( 'U', M, M, 0, NRHS, S, WORK( IE ), WORK( IL ),$ LDWORK, A, LDA, B, LDB, WORK( IWORK ), INFO )IF( INFO.NE.0 )$ GO TO 70** Multiply B by reciprocals of singular values*THR = MAX( RCOND*S( 1 ), SFMIN )IF( RCOND.LT.ZERO )$ THR = MAX( EPS*S( 1 ), SFMIN )RANK = 0DO 30 I = 1, MIF( S( I ).GT.THR ) THENCALL DRSCL( NRHS, S( I ), B( I, 1 ), LDB )RANK = RANK + 1ELSECALL DLASET( 'F', 1, NRHS, ZERO, ZERO, B( I, 1 ), LDB )END IF30 CONTINUEIWORK = IE** Multiply B by right singular vectors of L in WORK(IL)* (Workspace: need M*M+2*M, prefer M*M+M+M*NRHS)*IF( LWORK.GE.LDB*NRHS+IWORK-1 .AND. NRHS.GT.1 ) THENCALL DGEMM( 'T', 'N', M, NRHS, M, ONE, WORK( IL ), LDWORK,$ B, LDB, ZERO, WORK( IWORK ), LDB )CALL DLACPY( 'G', M, NRHS, WORK( IWORK ), LDB, B, LDB )ELSE IF( NRHS.GT.1 ) THENCHUNK = ( LWORK-IWORK+1 ) / MDO 40 I = 1, NRHS, CHUNKBL = MIN( NRHS-I+1, CHUNK )CALL DGEMM( 'T', 'N', M, BL, M, ONE, WORK( IL ), LDWORK,$ B( 1, I ), LDB, ZERO, WORK( IWORK ), N )CALL DLACPY( 'G', M, BL, WORK( IWORK ), N, B( 1, I ),$ LDB )40 CONTINUEELSECALL DGEMV( 'T', M, M, ONE, WORK( IL ), LDWORK, B( 1, 1 ),$ 1, ZERO, WORK( IWORK ), 1 )CALL DCOPY( M, WORK( IWORK ), 1, B( 1, 1 ), 1 )END IF** Zero out below first M rows of B*CALL DLASET( 'F', N-M, NRHS, ZERO, ZERO, B( M+1, 1 ), LDB )IWORK = ITAU + M** Multiply transpose(Q) by B* (Workspace: need M+NRHS, prefer M+NRHS*NB)*CALL DORMLQ( 'L', 'T', N, NRHS, M, A, LDA, WORK( ITAU ), B,$ LDB, WORK( IWORK ), LWORK-IWORK+1, INFO )*ELSE** Path 2 - remaining underdetermined cases*IE = 1ITAUQ = IE + MITAUP = ITAUQ + MIWORK = ITAUP + M** Bidiagonalize A* (Workspace: need 3*M+N, prefer 3*M+(M+N)*NB)*CALL DGEBRD( M, N, A, LDA, S, WORK( IE ), WORK( ITAUQ ),$ WORK( ITAUP ), WORK( IWORK ), LWORK-IWORK+1,$ INFO )** Multiply B by transpose of left bidiagonalizing vectors* (Workspace: need 3*M+NRHS, prefer 3*M+NRHS*NB)*CALL DORMBR( 'Q', 'L', 'T', M, NRHS, N, A, LDA, WORK( ITAUQ ),$ B, LDB, WORK( IWORK ), LWORK-IWORK+1, INFO )** Generate right bidiagonalizing vectors in A* (Workspace: need 4*M, prefer 3*M+M*NB)*CALL DORGBR( 'P', M, N, M, A, LDA, WORK( ITAUP ),$ WORK( IWORK ), LWORK-IWORK+1, INFO )IWORK = IE + M** Perform bidiagonal QR iteration,* computing right singular vectors of A in A and* multiplying B by transpose of left singular vectors* (Workspace: need BDSPAC)*CALL DBDSQR( 'L', M, N, 0, NRHS, S, WORK( IE ), A, LDA, VDUM,$ 1, B, LDB, WORK( IWORK ), INFO )IF( INFO.NE.0 )$ GO TO 70** Multiply B by reciprocals of singular values*THR = MAX( RCOND*S( 1 ), SFMIN )IF( RCOND.LT.ZERO )$ THR = MAX( EPS*S( 1 ), SFMIN )RANK = 0DO 50 I = 1, MIF( S( I ).GT.THR ) THENCALL DRSCL( NRHS, S( I ), B( I, 1 ), LDB )RANK = RANK + 1ELSECALL DLASET( 'F', 1, NRHS, ZERO, ZERO, B( I, 1 ), LDB )END IF50 CONTINUE** Multiply B by right singular vectors of A* (Workspace: need N, prefer N*NRHS)*IF( LWORK.GE.LDB*NRHS .AND. NRHS.GT.1 ) THENCALL DGEMM( 'T', 'N', N, NRHS, M, ONE, A, LDA, B, LDB, ZERO,$ WORK, LDB )CALL DLACPY( 'F', N, NRHS, WORK, LDB, B, LDB )ELSE IF( NRHS.GT.1 ) THENCHUNK = LWORK / NDO 60 I = 1, NRHS, CHUNKBL = MIN( NRHS-I+1, CHUNK )CALL DGEMM( 'T', 'N', N, BL, M, ONE, A, LDA, B( 1, I ),$ LDB, ZERO, WORK, N )CALL DLACPY( 'F', N, BL, WORK, N, B( 1, I ), LDB )60 CONTINUEELSECALL DGEMV( 'T', M, N, ONE, A, LDA, B, 1, ZERO, WORK, 1 )CALL DCOPY( N, WORK, 1, B, 1 )END IFEND IF** Undo scaling*IF( IASCL.EQ.1 ) THENCALL DLASCL( 'G', 0, 0, ANRM, SMLNUM, N, NRHS, B, LDB, INFO )CALL DLASCL( 'G', 0, 0, SMLNUM, ANRM, MINMN, 1, S, MINMN,$ INFO )ELSE IF( IASCL.EQ.2 ) THENCALL DLASCL( 'G', 0, 0, ANRM, BIGNUM, N, NRHS, B, LDB, INFO )CALL DLASCL( 'G', 0, 0, BIGNUM, ANRM, MINMN, 1, S, MINMN,$ INFO )END IFIF( IBSCL.EQ.1 ) THENCALL DLASCL( 'G', 0, 0, SMLNUM, BNRM, N, NRHS, B, LDB, INFO )ELSE IF( IBSCL.EQ.2 ) THENCALL DLASCL( 'G', 0, 0, BIGNUM, BNRM, N, NRHS, B, LDB, INFO )END IF*70 CONTINUEWORK( 1 ) = MAXWRKRETURN** End of DGELSS*ENDSUBROUTINE DGELSX( M, N, NRHS, A, LDA, B, LDB, JPVT, RCOND, RANK,$ WORK, INFO )** -- LAPACK driver 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, LDB, M, N, NRHS, RANKDOUBLE PRECISION RCOND* ..* .. Array Arguments ..INTEGER JPVT( * )DOUBLE PRECISION A( LDA, * ), B( LDB, * ), WORK( * )* ..** Purpose* =======** This routine is deprecated and has been replaced by routine DGELSY.** DGELSX computes the minimum-norm solution to a real linear least* squares problem:* minimize || A * X - B ||* using a complete orthogonal factorization of A. A is an M-by-N* matrix which may be rank-deficient.** Several right hand side vectors b and solution vectors x can be* handled in a single call; they are stored as the columns of the* M-by-NRHS right hand side matrix B and the N-by-NRHS solution* matrix X.** The routine first computes a QR factorization with column pivoting:* A * P = Q * [ R11 R12 ]* [ 0 R22 ]* with R11 defined as the largest leading submatrix whose estimated* condition number is less than 1/RCOND. The order of R11, RANK,* is the effective rank of A.** Then, R22 is considered to be negligible, and R12 is annihilated* by orthogonal transformations from the right, arriving at the* complete orthogonal factorization:* A * P = Q * [ T11 0 ] * Z* [ 0 0 ]* The minimum-norm solution is then* X = P * Z' [ inv(T11)*Q1'*B ]* [ 0 ]* where Q1 consists of the first RANK columns of Q.** 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.** NRHS (input) INTEGER* The number of right hand sides, i.e., the number of* columns of matrices B and X. NRHS >= 0.** A (input/output) DOUBLE PRECISION array, dimension (LDA,N)* On entry, the M-by-N matrix A.* On exit, A has been overwritten by details of its* complete orthogonal factorization.** LDA (input) INTEGER* The leading dimension of the array A. LDA >= max(1,M).** B (input/output) DOUBLE PRECISION array, dimension (LDB,NRHS)* On entry, the M-by-NRHS right hand side matrix B.* On exit, the N-by-NRHS solution matrix X.* If m >= n and RANK = n, the residual sum-of-squares for* the solution in the i-th column is given by the sum of* squares of elements N+1:M in that column.** LDB (input) INTEGER* The leading dimension of the array B. LDB >= max(1,M,N).** JPVT (input/output) INTEGER array, dimension (N)* On entry, if JPVT(i) .ne. 0, the i-th column of A is an* initial column, otherwise it is a free column. Before* the QR factorization of A, all initial columns are* permuted to the leading positions; only the remaining* free columns are moved as a result of column pivoting* during the factorization.* On exit, if JPVT(i) = k, then the i-th column of A*P* was the k-th column of A.** RCOND (input) DOUBLE PRECISION* RCOND is used to determine the effective rank of A, which* is defined as the order of the largest leading triangular* submatrix R11 in the QR factorization with pivoting of A,* whose estimated condition number < 1/RCOND.** RANK (output) INTEGER* The effective rank of A, i.e., the order of the submatrix* R11. This is the same as the order of the submatrix T11* in the complete orthogonal factorization of A.** WORK (workspace) DOUBLE PRECISION array, dimension* (max( min(M,N)+3*N, 2*min(M,N)+NRHS )),** INFO (output) INTEGER* = 0: successful exit* < 0: if INFO = -i, the i-th argument had an illegal value** =====================================================================** .. Parameters ..INTEGER IMAX, IMINPARAMETER ( IMAX = 1, IMIN = 2 )DOUBLE PRECISION ZERO, ONE, DONE, NTDONEPARAMETER ( ZERO = 0.0D0, ONE = 1.0D0, DONE = ZERO,$ NTDONE = ONE )* ..* .. Local Scalars ..INTEGER I, IASCL, IBSCL, ISMAX, ISMIN, J, K, MNDOUBLE PRECISION ANRM, BIGNUM, BNRM, C1, C2, S1, S2, SMAX,$ SMAXPR, SMIN, SMINPR, SMLNUM, T1, T2* ..* .. External Functions ..DOUBLE PRECISION DLAMCH, DLANGEEXTERNAL DLAMCH, DLANGE* ..* .. External Subroutines ..EXTERNAL DGEQPF, DLAIC1, DLASCL, DLASET, DLATZM, DORM2R,$ DTRSM, DTZRQF, XERBLA* ..* .. Intrinsic Functions ..INTRINSIC ABS, MAX, MIN* ..* .. Executable Statements ..*MN = MIN( M, N )ISMIN = MN + 1ISMAX = 2*MN + 1** Test the input arguments.*INFO = 0IF( M.LT.0 ) THENINFO = -1ELSE IF( N.LT.0 ) THENINFO = -2ELSE IF( NRHS.LT.0 ) THENINFO = -3ELSE IF( LDA.LT.MAX( 1, M ) ) THENINFO = -5ELSE IF( LDB.LT.MAX( 1, M, N ) ) THENINFO = -7END IF*IF( INFO.NE.0 ) THENCALL XERBLA( 'DGELSX', -INFO )RETURNEND IF** Quick return if possible*IF( MIN( M, N, NRHS ).EQ.0 ) THENRANK = 0RETURNEND IF** Get machine parameters*SMLNUM = DLAMCH( 'S' ) / DLAMCH( 'P' )BIGNUM = ONE / SMLNUMCALL DLABAD( SMLNUM, BIGNUM )** Scale A, B if max elements outside range [SMLNUM,BIGNUM]*ANRM = DLANGE( 'M', M, N, A, LDA, WORK )IASCL = 0IF( ANRM.GT.ZERO .AND. ANRM.LT.SMLNUM ) THEN** Scale matrix norm up to SMLNUM*CALL DLASCL( 'G', 0, 0, ANRM, SMLNUM, M, N, A, LDA, INFO )IASCL = 1ELSE IF( ANRM.GT.BIGNUM ) THEN** Scale matrix norm down to BIGNUM*CALL DLASCL( 'G', 0, 0, ANRM, BIGNUM, M, N, A, LDA, INFO )IASCL = 2ELSE IF( ANRM.EQ.ZERO ) THEN** Matrix all zero. Return zero solution.*CALL DLASET( 'F', MAX( M, N ), NRHS, ZERO, ZERO, B, LDB )RANK = 0GO TO 100END IF*BNRM = DLANGE( 'M', M, NRHS, B, LDB, WORK )IBSCL = 0IF( BNRM.GT.ZERO .AND. BNRM.LT.SMLNUM ) THEN** Scale matrix norm up to SMLNUM*CALL DLASCL( 'G', 0, 0, BNRM, SMLNUM, M, NRHS, B, LDB, INFO )IBSCL = 1ELSE IF( BNRM.GT.BIGNUM ) THEN** Scale matrix norm down to BIGNUM*CALL DLASCL( 'G', 0, 0, BNRM, BIGNUM, M, NRHS, B, LDB, INFO )IBSCL = 2END IF** Compute QR factorization with column pivoting of A:* A * P = Q * R*CALL DGEQPF( M, N, A, LDA, JPVT, WORK( 1 ), WORK( MN+1 ), INFO )** workspace 3*N. Details of Householder rotations stored* in WORK(1:MN).** Determine RANK using incremental condition estimation*WORK( ISMIN ) = ONEWORK( ISMAX ) = ONESMAX = ABS( A( 1, 1 ) )SMIN = SMAXIF( ABS( A( 1, 1 ) ).EQ.ZERO ) THENRANK = 0CALL DLASET( 'F', MAX( M, N ), NRHS, ZERO, ZERO, B, LDB )GO TO 100ELSERANK = 1END IF*10 CONTINUEIF( RANK.LT.MN ) THENI = RANK + 1CALL DLAIC1( IMIN, RANK, WORK( ISMIN ), SMIN, A( 1, I ),$ A( I, I ), SMINPR, S1, C1 )CALL DLAIC1( IMAX, RANK, WORK( ISMAX ), SMAX, A( 1, I ),$ A( I, I ), SMAXPR, S2, C2 )*IF( SMAXPR*RCOND.LE.SMINPR ) THENDO 20 I = 1, RANKWORK( ISMIN+I-1 ) = S1*WORK( ISMIN+I-1 )WORK( ISMAX+I-1 ) = S2*WORK( ISMAX+I-1 )20 CONTINUEWORK( ISMIN+RANK ) = C1WORK( ISMAX+RANK ) = C2SMIN = SMINPRSMAX = SMAXPRRANK = RANK + 1GO TO 10END IFEND IF** Logically partition R = [ R11 R12 ]* [ 0 R22 ]* where R11 = R(1:RANK,1:RANK)** [R11,R12] = [ T11, 0 ] * Y*IF( RANK.LT.N )$ CALL DTZRQF( RANK, N, A, LDA, WORK( MN+1 ), INFO )** Details of Householder rotations stored in WORK(MN+1:2*MN)** B(1:M,1:NRHS) := Q' * B(1:M,1:NRHS)*CALL DORM2R( 'Left', 'Transpose', M, NRHS, MN, A, LDA, WORK( 1 ),$ B, LDB, WORK( 2*MN+1 ), INFO )** workspace NRHS** B(1:RANK,1:NRHS) := inv(T11) * B(1:RANK,1:NRHS)*CALL DTRSM( 'Left', 'Upper', 'No transpose', 'Non-unit', RANK,$ NRHS, ONE, A, LDA, B, LDB )*DO 40 I = RANK + 1, NDO 30 J = 1, NRHSB( I, J ) = ZERO30 CONTINUE40 CONTINUE** B(1:N,1:NRHS) := Y' * B(1:N,1:NRHS)*IF( RANK.LT.N ) THENDO 50 I = 1, RANKCALL DLATZM( 'Left', N-RANK+1, NRHS, A( I, RANK+1 ), LDA,$ WORK( MN+I ), B( I, 1 ), B( RANK+1, 1 ), LDB,$ WORK( 2*MN+1 ) )50 CONTINUEEND IF** workspace NRHS** B(1:N,1:NRHS) := P * B(1:N,1:NRHS)*DO 90 J = 1, NRHSDO 60 I = 1, NWORK( 2*MN+I ) = NTDONE60 CONTINUEDO 80 I = 1, NIF( WORK( 2*MN+I ).EQ.NTDONE ) THENIF( JPVT( I ).NE.I ) THENK = IT1 = B( K, J )T2 = B( JPVT( K ), J )70 CONTINUEB( JPVT( K ), J ) = T1WORK( 2*MN+K ) = DONET1 = T2K = JPVT( K )T2 = B( JPVT( K ), J )IF( JPVT( K ).NE.I )$ GO TO 70B( I, J ) = T1WORK( 2*MN+K ) = DONEEND IFEND IF80 CONTINUE90 CONTINUE** Undo scaling*IF( IASCL.EQ.1 ) THENCALL DLASCL( 'G', 0, 0, ANRM, SMLNUM, N, NRHS, B, LDB, INFO )CALL DLASCL( 'U', 0, 0, SMLNUM, ANRM, RANK, RANK, A, LDA,$ INFO )ELSE IF( IASCL.EQ.2 ) THENCALL DLASCL( 'G', 0, 0, ANRM, BIGNUM, N, NRHS, B, LDB, INFO )CALL DLASCL( 'U', 0, 0, BIGNUM, ANRM, RANK, RANK, A, LDA,$ INFO )END IFIF( IBSCL.EQ.1 ) THENCALL DLASCL( 'G', 0, 0, SMLNUM, BNRM, N, NRHS, B, LDB, INFO )ELSE IF( IBSCL.EQ.2 ) THENCALL DLASCL( 'G', 0, 0, BIGNUM, BNRM, N, NRHS, B, LDB, INFO )END IF*100 CONTINUE*RETURN** End of DGELSX*ENDSUBROUTINE DGELSY( M, N, NRHS, A, LDA, B, LDB, JPVT, RCOND, RANK,$ WORK, LWORK, INFO )** -- LAPACK driver 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, LDB, LWORK, M, N, NRHS, RANKDOUBLE PRECISION RCOND* ..* .. Array Arguments ..INTEGER JPVT( * )DOUBLE PRECISION A( LDA, * ), B( LDB, * ), WORK( * )* ..** Purpose* =======** DGELSY computes the minimum-norm solution to a real linear least* squares problem:* minimize || A * X - B ||* using a complete orthogonal factorization of A. A is an M-by-N* matrix which may be rank-deficient.** Several right hand side vectors b and solution vectors x can be* handled in a single call; they are stored as the columns of the* M-by-NRHS right hand side matrix B and the N-by-NRHS solution* matrix X.** The routine first computes a QR factorization with column pivoting:* A * P = Q * [ R11 R12 ]* [ 0 R22 ]* with R11 defined as the largest leading submatrix whose estimated* condition number is less than 1/RCOND. The order of R11, RANK,* is the effective rank of A.** Then, R22 is considered to be negligible, and R12 is annihilated* by orthogonal transformations from the right, arriving at the* complete orthogonal factorization:* A * P = Q * [ T11 0 ] * Z* [ 0 0 ]* The minimum-norm solution is then* X = P * Z' [ inv(T11)*Q1'*B ]* [ 0 ]* where Q1 consists of the first RANK columns of Q.** This routine is basically identical to the original xGELSX except* three differences:* o The call to the subroutine xGEQPF has been substituted by the* the call to the subroutine xGEQP3. This subroutine is a Blas-3* version of the QR factorization with column pivoting.* o Matrix B (the right hand side) is updated with Blas-3.* o The permutation of matrix B (the right hand side) is faster and* more simple.** 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.** NRHS (input) INTEGER* The number of right hand sides, i.e., the number of* columns of matrices B and X. NRHS >= 0.** A (input/output) DOUBLE PRECISION array, dimension (LDA,N)* On entry, the M-by-N matrix A.* On exit, A has been overwritten by details of its* complete orthogonal factorization.** LDA (input) INTEGER* The leading dimension of the array A. LDA >= max(1,M).** B (input/output) DOUBLE PRECISION array, dimension (LDB,NRHS)* On entry, the M-by-NRHS right hand side matrix B.* On exit, the N-by-NRHS solution matrix X.** LDB (input) INTEGER* The leading dimension of the array B. LDB >= max(1,M,N).** JPVT (input/output) INTEGER array, dimension (N)* On entry, if JPVT(i) .ne. 0, the i-th column of A is permuted* to the front of AP, otherwise column i is a free column.* On exit, if JPVT(i) = k, then the i-th column of AP* was the k-th column of A.** RCOND (input) DOUBLE PRECISION* RCOND is used to determine the effective rank of A, which* is defined as the order of the largest leading triangular* submatrix R11 in the QR factorization with pivoting of A,* whose estimated condition number < 1/RCOND.** RANK (output) INTEGER* The effective rank of A, i.e., the order of the submatrix* R11. This is the same as the order of the submatrix T11* in the complete orthogonal factorization of A.** 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.* The unblocked strategy requires that:* LWORK >= MAX( MN+3*N+1, 2*MN+NRHS ),* where MN = min( M, N ).* The block algorithm requires that:* LWORK >= MAX( MN+2*N+NB*(N+1), 2*MN+NB*NRHS ),* where NB is an upper bound on the blocksize returned* by ILAENV for the routines DGEQP3, DTZRZF, STZRQF, DORMQR,* and DORMRZ.** 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* E. Quintana-Orti, Depto. de Informatica, Universidad Jaime I, Spain* G. Quintana-Orti, Depto. de Informatica, Universidad Jaime I, Spain** =====================================================================** .. Parameters ..INTEGER IMAX, IMINPARAMETER ( IMAX = 1, IMIN = 2 )DOUBLE PRECISION ZERO, ONEPARAMETER ( ZERO = 0.0D+0, ONE = 1.0D+0 )* ..* .. Local Scalars ..LOGICAL LQUERYINTEGER I, IASCL, IBSCL, ISMAX, ISMIN, J, LWKOPT, MN,$ NB, NB1, NB2, NB3, NB4DOUBLE PRECISION ANRM, BIGNUM, BNRM, C1, C2, S1, S2, SMAX,$ SMAXPR, SMIN, SMINPR, SMLNUM, WSIZE* ..* .. External Functions ..INTEGER ILAENVDOUBLE PRECISION DLAMCH, DLANGEEXTERNAL ILAENV, DLAMCH, DLANGE* ..* .. External Subroutines ..EXTERNAL DCOPY, DGEQP3, DLABAD, DLAIC1, DLASCL, DLASET,$ DORMQR, DORMRZ, DTRSM, DTZRZF, XERBLA* ..* .. Intrinsic Functions ..INTRINSIC ABS, DBLE, MAX, MIN* ..* .. Executable Statements ..*MN = MIN( M, N )ISMIN = MN + 1ISMAX = 2*MN + 1** Test the input arguments.*INFO = 0NB1 = ILAENV( 1, 'DGEQRF', ' ', M, N, -1, -1 )NB2 = ILAENV( 1, 'DGERQF', ' ', M, N, -1, -1 )NB3 = ILAENV( 1, 'DORMQR', ' ', M, N, NRHS, -1 )NB4 = ILAENV( 1, 'DORMRQ', ' ', M, N, NRHS, -1 )NB = MAX( NB1, NB2, NB3, NB4 )LWKOPT = MAX( 1, MN+2*N+NB*( N+1 ), 2*MN+NB*NRHS )WORK( 1 ) = DBLE( LWKOPT )LQUERY = ( LWORK.EQ.-1 )IF( M.LT.0 ) THENINFO = -1ELSE IF( N.LT.0 ) THENINFO = -2ELSE IF( NRHS.LT.0 ) THENINFO = -3ELSE IF( LDA.LT.MAX( 1, M ) ) THENINFO = -5ELSE IF( LDB.LT.MAX( 1, M, N ) ) THENINFO = -7ELSE IF( LWORK.LT.MAX( 1, MN+3*N+1, 2*MN+NRHS ) .AND. .NOT.$ LQUERY ) THENINFO = -12END IF*IF( INFO.NE.0 ) THENCALL XERBLA( 'DGELSY', -INFO )RETURNELSE IF( LQUERY ) THENRETURNEND IF** Quick return if possible*IF( MIN( M, N, NRHS ).EQ.0 ) THENRANK = 0RETURNEND IF** Get machine parameters*SMLNUM = DLAMCH( 'S' ) / DLAMCH( 'P' )BIGNUM = ONE / SMLNUMCALL DLABAD( SMLNUM, BIGNUM )** Scale A, B if max entries outside range [SMLNUM,BIGNUM]*ANRM = DLANGE( 'M', M, N, A, LDA, WORK )IASCL = 0IF( ANRM.GT.ZERO .AND. ANRM.LT.SMLNUM ) THEN** Scale matrix norm up to SMLNUM*CALL DLASCL( 'G', 0, 0, ANRM, SMLNUM, M, N, A, LDA, INFO )IASCL = 1ELSE IF( ANRM.GT.BIGNUM ) THEN** Scale matrix norm down to BIGNUM*CALL DLASCL( 'G', 0, 0, ANRM, BIGNUM, M, N, A, LDA, INFO )IASCL = 2ELSE IF( ANRM.EQ.ZERO ) THEN** Matrix all zero. Return zero solution.*CALL DLASET( 'F', MAX( M, N ), NRHS, ZERO, ZERO, B, LDB )RANK = 0GO TO 70END IF*BNRM = DLANGE( 'M', M, NRHS, B, LDB, WORK )IBSCL = 0IF( BNRM.GT.ZERO .AND. BNRM.LT.SMLNUM ) THEN** Scale matrix norm up to SMLNUM*CALL DLASCL( 'G', 0, 0, BNRM, SMLNUM, M, NRHS, B, LDB, INFO )IBSCL = 1ELSE IF( BNRM.GT.BIGNUM ) THEN** Scale matrix norm down to BIGNUM*CALL DLASCL( 'G', 0, 0, BNRM, BIGNUM, M, NRHS, B, LDB, INFO )IBSCL = 2END IF** Compute QR factorization with column pivoting of A:* A * P = Q * R*CALL DGEQP3( M, N, A, LDA, JPVT, WORK( 1 ), WORK( MN+1 ),$ LWORK-MN, INFO )WSIZE = MN + WORK( MN+1 )** workspace: MN+2*N+NB*(N+1).* Details of Householder rotations stored in WORK(1:MN).** Determine RANK using incremental condition estimation*WORK( ISMIN ) = ONEWORK( ISMAX ) = ONESMAX = ABS( A( 1, 1 ) )SMIN = SMAXIF( ABS( A( 1, 1 ) ).EQ.ZERO ) THENRANK = 0CALL DLASET( 'F', MAX( M, N ), NRHS, ZERO, ZERO, B, LDB )GO TO 70ELSERANK = 1END IF*10 CONTINUEIF( RANK.LT.MN ) THENI = RANK + 1CALL DLAIC1( IMIN, RANK, WORK( ISMIN ), SMIN, A( 1, I ),$ A( I, I ), SMINPR, S1, C1 )CALL DLAIC1( IMAX, RANK, WORK( ISMAX ), SMAX, A( 1, I ),$ A( I, I ), SMAXPR, S2, C2 )*IF( SMAXPR*RCOND.LE.SMINPR ) THENDO 20 I = 1, RANKWORK( ISMIN+I-1 ) = S1*WORK( ISMIN+I-1 )WORK( ISMAX+I-1 ) = S2*WORK( ISMAX+I-1 )20 CONTINUEWORK( ISMIN+RANK ) = C1WORK( ISMAX+RANK ) = C2SMIN = SMINPRSMAX = SMAXPRRANK = RANK + 1GO TO 10END IFEND IF** workspace: 3*MN.** Logically partition R = [ R11 R12 ]* [ 0 R22 ]* where R11 = R(1:RANK,1:RANK)** [R11,R12] = [ T11, 0 ] * Y*IF( RANK.LT.N )$ CALL DTZRZF( RANK, N, A, LDA, WORK( MN+1 ), WORK( 2*MN+1 ),$ LWORK-2*MN, INFO )** workspace: 2*MN.* Details of Householder rotations stored in WORK(MN+1:2*MN)** B(1:M,1:NRHS) := Q' * B(1:M,1:NRHS)*CALL DORMQR( 'Left', 'Transpose', M, NRHS, MN, A, LDA, WORK( 1 ),$ B, LDB, WORK( 2*MN+1 ), LWORK-2*MN, INFO )WSIZE = MAX( WSIZE, 2*MN+WORK( 2*MN+1 ) )** workspace: 2*MN+NB*NRHS.** B(1:RANK,1:NRHS) := inv(T11) * B(1:RANK,1:NRHS)*CALL DTRSM( 'Left', 'Upper', 'No transpose', 'Non-unit', RANK,$ NRHS, ONE, A, LDA, B, LDB )*DO 40 J = 1, NRHSDO 30 I = RANK + 1, NB( I, J ) = ZERO30 CONTINUE40 CONTINUE** B(1:N,1:NRHS) := Y' * B(1:N,1:NRHS)*IF( RANK.LT.N ) THENCALL DORMRZ( 'Left', 'Transpose', N, NRHS, RANK, N-RANK, A,$ LDA, WORK( MN+1 ), B, LDB, WORK( 2*MN+1 ),$ LWORK-2*MN, INFO )END IF** workspace: 2*MN+NRHS.** B(1:N,1:NRHS) := P * B(1:N,1:NRHS)*DO 60 J = 1, NRHSDO 50 I = 1, NWORK( JPVT( I ) ) = B( I, J )50 CONTINUECALL DCOPY( N, WORK( 1 ), 1, B( 1, J ), 1 )60 CONTINUE** workspace: N.** Undo scaling*IF( IASCL.EQ.1 ) THENCALL DLASCL( 'G', 0, 0, ANRM, SMLNUM, N, NRHS, B, LDB, INFO )CALL DLASCL( 'U', 0, 0, SMLNUM, ANRM, RANK, RANK, A, LDA,$ INFO )ELSE IF( IASCL.EQ.2 ) THENCALL DLASCL( 'G', 0, 0, ANRM, BIGNUM, N, NRHS, B, LDB, INFO )CALL DLASCL( 'U', 0, 0, BIGNUM, ANRM, RANK, RANK, A, LDA,$ INFO )END IFIF( IBSCL.EQ.1 ) THENCALL DLASCL( 'G', 0, 0, SMLNUM, BNRM, N, NRHS, B, LDB, INFO )ELSE IF( IBSCL.EQ.2 ) THENCALL DLASCL( 'G', 0, 0, BIGNUM, BNRM, N, NRHS, B, LDB, INFO )END IF*70 CONTINUEWORK( 1 ) = DBLE( LWKOPT )*RETURN** End of DGELSY*ENDSUBROUTINE DGESDD( JOBZ, M, N, A, LDA, S, U, LDU, VT, LDVT, WORK,$ LWORK, IWORK, INFO )** -- LAPACK driver 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 JOBZINTEGER INFO, LDA, LDU, LDVT, LWORK, M, N* ..* .. Array Arguments ..INTEGER IWORK( * )DOUBLE PRECISION A( LDA, * ), S( * ), U( LDU, * ),$ VT( LDVT, * ), WORK( * )* ..** Purpose* =======** DGESDD computes the singular value decomposition (SVD) of a real* M-by-N matrix A, optionally computing the left and right singular* vectors. If singular vectors are desired, it uses a* divide-and-conquer algorithm.** The SVD is written** A = U * SIGMA * transpose(V)** where SIGMA is an M-by-N matrix which is zero except for its* min(m,n) diagonal elements, U is an M-by-M orthogonal matrix, and* V is an N-by-N orthogonal matrix. The diagonal elements of SIGMA* are the singular values of A; they are real and non-negative, and* are returned in descending order. The first min(m,n) columns of* U and V are the left and right singular vectors of A.** Note that the routine returns VT = V**T, not V.** The divide and conquer algorithm makes very mild assumptions about* floating point arithmetic. It will work on machines with a guard* digit in add/subtract, or on those binary machines without guard* digits which subtract like the Cray X-MP, Cray Y-MP, Cray C-90, or* Cray-2. It could conceivably fail on hexadecimal or decimal machines* without guard digits, but we know of none.** Arguments* =========** JOBZ (input) CHARACTER*1* Specifies options for computing all or part of the matrix U:* = 'A': all M columns of U and all N rows of V**T are* returned in the arrays U and VT;* = 'S': the first min(M,N) columns of U and the first* min(M,N) rows of V**T are returned in the arrays U* and VT;* = 'O': If M >= N, the first N columns of U are overwritten* on the array A and all rows of V**T are returned in* the array VT;* otherwise, all columns of U are returned in the* array U and the first M rows of V**T are overwritten* in the array VT;* = 'N': no columns of U or rows of V**T are computed.** M (input) INTEGER* The number of rows of the input matrix A. M >= 0.** N (input) INTEGER* The number of columns of the input matrix A. N >= 0.** A (input/output) DOUBLE PRECISION array, dimension (LDA,N)* On entry, the M-by-N matrix A.* On exit,* if JOBZ = 'O', A is overwritten with the first N columns* of U (the left singular vectors, stored* columnwise) if M >= N;* A is overwritten with the first M rows* of V**T (the right singular vectors, stored* rowwise) otherwise.* if JOBZ .ne. 'O', the contents of A are destroyed.** LDA (input) INTEGER* The leading dimension of the array A. LDA >= max(1,M).** S (output) DOUBLE PRECISION array, dimension (min(M,N))* The singular values of A, sorted so that S(i) >= S(i+1).** U (output) DOUBLE PRECISION array, dimension (LDU,UCOL)* UCOL = M if JOBZ = 'A' or JOBZ = 'O' and M < N;* UCOL = min(M,N) if JOBZ = 'S'.* If JOBZ = 'A' or JOBZ = 'O' and M < N, U contains the M-by-M* orthogonal matrix U;* if JOBZ = 'S', U contains the first min(M,N) columns of U* (the left singular vectors, stored columnwise);* if JOBZ = 'O' and M >= N, or JOBZ = 'N', U is not referenced.** LDU (input) INTEGER* The leading dimension of the array U. LDU >= 1; if* JOBZ = 'S' or 'A' or JOBZ = 'O' and M < N, LDU >= M.** VT (output) DOUBLE PRECISION array, dimension (LDVT,N)* If JOBZ = 'A' or JOBZ = 'O' and M >= N, VT contains the* N-by-N orthogonal matrix V**T;* if JOBZ = 'S', VT contains the first min(M,N) rows of* V**T (the right singular vectors, stored rowwise);* if JOBZ = 'O' and M < N, or JOBZ = 'N', VT is not referenced.** LDVT (input) INTEGER* The leading dimension of the array VT. LDVT >= 1; if* JOBZ = 'A' or JOBZ = 'O' and M >= N, LDVT >= N;* if JOBZ = 'S', LDVT >= min(M,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 >= 1.* If JOBZ = 'N',* LWORK >= 3*min(M,N) + max(max(M,N),6*min(M,N)).* If JOBZ = 'O',* LWORK >= 3*min(M,N)*min(M,N) +* max(max(M,N),5*min(M,N)*min(M,N)+4*min(M,N)).* If JOBZ = 'S' or 'A'* LWORK >= 3*min(M,N)*min(M,N) +* max(max(M,N),4*min(M,N)*min(M,N)+4*min(M,N)).* For good performance, LWORK should generally be larger.* If LWORK < 0 but other input arguments are legal, WORK(1)* returns the optimal LWORK.** IWORK (workspace) INTEGER array, dimension (8*min(M,N))** INFO (output) INTEGER* = 0: successful exit.* < 0: if INFO = -i, the i-th argument had an illegal value.* > 0: DBDSDC did not converge, updating process failed.** Further Details* ===============** Based on contributions by* Ming Gu and Huan Ren, Computer Science Division, University of* California at Berkeley, USA** =====================================================================** .. Parameters ..DOUBLE PRECISION ZERO, ONEPARAMETER ( ZERO = 0.0D0, ONE = 1.0D0 )* ..* .. Local Scalars ..LOGICAL LQUERY, WNTQA, WNTQAS, WNTQN, WNTQO, WNTQSINTEGER BDSPAC, BLK, CHUNK, I, IE, IERR, IL,$ IR, ISCL, ITAU, ITAUP, ITAUQ, IU, IVT, LDWKVT,$ LDWRKL, LDWRKR, LDWRKU, MAXWRK, MINMN, MINWRK,$ MNTHR, NWORK, WRKBLDOUBLE PRECISION ANRM, BIGNUM, EPS, SMLNUM* ..* .. Local Arrays ..INTEGER IDUM( 1 )DOUBLE PRECISION DUM( 1 )* ..* .. External Subroutines ..EXTERNAL DBDSDC, DGEBRD, DGELQF, DGEMM, DGEQRF, DLACPY,$ DLASCL, DLASET, DORGBR, DORGLQ, DORGQR, DORMBR,$ XERBLA* ..* .. External Functions ..LOGICAL LSAMEINTEGER ILAENVDOUBLE PRECISION DLAMCH, DLANGEEXTERNAL DLAMCH, DLANGE, ILAENV, LSAME* ..* .. Intrinsic Functions ..INTRINSIC DBLE, INT, MAX, MIN, SQRT* ..* .. Executable Statements ..** Test the input arguments*INFO = 0MINMN = MIN( M, N )MNTHR = INT( MINMN*11.0D0 / 6.0D0 )WNTQA = LSAME( JOBZ, 'A' )WNTQS = LSAME( JOBZ, 'S' )WNTQAS = WNTQA .OR. WNTQSWNTQO = LSAME( JOBZ, 'O' )WNTQN = LSAME( JOBZ, 'N' )MINWRK = 1MAXWRK = 1LQUERY = ( LWORK.EQ.-1 )*IF( .NOT.( WNTQA .OR. WNTQS .OR. WNTQO .OR. WNTQN ) ) THENINFO = -1ELSE IF( M.LT.0 ) THENINFO = -2ELSE IF( N.LT.0 ) THENINFO = -3ELSE IF( LDA.LT.MAX( 1, M ) ) THENINFO = -5ELSE IF( LDU.LT.1 .OR. ( WNTQAS .AND. LDU.LT.M ) .OR.$ ( WNTQO .AND. M.LT.N .AND. LDU.LT.M ) ) THENINFO = -8ELSE IF( LDVT.LT.1 .OR. ( WNTQA .AND. LDVT.LT.N ) .OR.$ ( WNTQS .AND. LDVT.LT.MINMN ) .OR.$ ( WNTQO .AND. M.GE.N .AND. LDVT.LT.N ) ) THENINFO = -10END IF** Compute workspace* (Note: Comments in the code beginning "Workspace:" describe the* minimal amount of workspace needed at that point in the code,* as well as the preferred amount for good performance.* NB refers to the optimal block size for the immediately* following subroutine, as returned by ILAENV.)*IF( INFO.EQ.0 .AND. M.GT.0 .AND. N.GT.0 ) THENIF( M.GE.N ) THEN** Compute space needed for DBDSDC*IF( WNTQN ) THENBDSPAC = 7*NELSEBDSPAC = 3*N*N + 4*NEND IFIF( M.GE.MNTHR ) THENIF( WNTQN ) THEN** Path 1 (M much larger than N, JOBZ='N')*WRKBL = N + N*ILAENV( 1, 'DGEQRF', ' ', M, N, -1,$ -1 )WRKBL = MAX( WRKBL, 3*N+2*N*$ ILAENV( 1, 'DGEBRD', ' ', N, N, -1, -1 ) )MAXWRK = MAX( WRKBL, BDSPAC+N )MINWRK = BDSPAC + NELSE IF( WNTQO ) THEN** Path 2 (M much larger than N, JOBZ='O')*WRKBL = N + N*ILAENV( 1, 'DGEQRF', ' ', M, N, -1, -1 )WRKBL = MAX( WRKBL, N+N*ILAENV( 1, 'DORGQR', ' ', M,$ N, N, -1 ) )WRKBL = MAX( WRKBL, 3*N+2*N*$ ILAENV( 1, 'DGEBRD', ' ', N, N, -1, -1 ) )WRKBL = MAX( WRKBL, 3*N+N*$ ILAENV( 1, 'DORMBR', 'QLN', N, N, N, -1 ) )WRKBL = MAX( WRKBL, 3*N+N*$ ILAENV( 1, 'DORMBR', 'PRT', N, N, N, -1 ) )WRKBL = MAX( WRKBL, BDSPAC+3*N )MAXWRK = WRKBL + 2*N*NMINWRK = BDSPAC + 2*N*N + 3*NELSE IF( WNTQS ) THEN** Path 3 (M much larger than N, JOBZ='S')*WRKBL = N + N*ILAENV( 1, 'DGEQRF', ' ', M, N, -1, -1 )WRKBL = MAX( WRKBL, N+N*ILAENV( 1, 'DORGQR', ' ', M,$ N, N, -1 ) )WRKBL = MAX( WRKBL, 3*N+2*N*$ ILAENV( 1, 'DGEBRD', ' ', N, N, -1, -1 ) )WRKBL = MAX( WRKBL, 3*N+N*$ ILAENV( 1, 'DORMBR', 'QLN', N, N, N, -1 ) )WRKBL = MAX( WRKBL, 3*N+N*$ ILAENV( 1, 'DORMBR', 'PRT', N, N, N, -1 ) )WRKBL = MAX( WRKBL, BDSPAC+3*N )MAXWRK = WRKBL + N*NMINWRK = BDSPAC + N*N + 3*NELSE IF( WNTQA ) THEN** Path 4 (M much larger than N, JOBZ='A')*WRKBL = N + N*ILAENV( 1, 'DGEQRF', ' ', M, N, -1, -1 )WRKBL = MAX( WRKBL, N+M*ILAENV( 1, 'DORGQR', ' ', M,$ M, N, -1 ) )WRKBL = MAX( WRKBL, 3*N+2*N*$ ILAENV( 1, 'DGEBRD', ' ', N, N, -1, -1 ) )WRKBL = MAX( WRKBL, 3*N+N*$ ILAENV( 1, 'DORMBR', 'QLN', N, N, N, -1 ) )WRKBL = MAX( WRKBL, 3*N+N*$ ILAENV( 1, 'DORMBR', 'PRT', N, N, N, -1 ) )WRKBL = MAX( WRKBL, BDSPAC+3*N )MAXWRK = WRKBL + N*NMINWRK = BDSPAC + N*N + 3*NEND IFELSE** Path 5 (M at least N, but not much larger)*WRKBL = 3*N + ( M+N )*ILAENV( 1, 'DGEBRD', ' ', M, N, -1,$ -1 )IF( WNTQN ) THENMAXWRK = MAX( WRKBL, BDSPAC+3*N )MINWRK = 3*N + MAX( M, BDSPAC )ELSE IF( WNTQO ) THENWRKBL = MAX( WRKBL, 3*N+N*$ ILAENV( 1, 'DORMBR', 'QLN', M, N, N, -1 ) )WRKBL = MAX( WRKBL, 3*N+N*$ ILAENV( 1, 'DORMBR', 'PRT', N, N, N, -1 ) )WRKBL = MAX( WRKBL, BDSPAC+3*N )MAXWRK = WRKBL + M*NMINWRK = 3*N + MAX( M, N*N+BDSPAC )ELSE IF( WNTQS ) THENWRKBL = MAX( WRKBL, 3*N+N*$ ILAENV( 1, 'DORMBR', 'QLN', M, N, N, -1 ) )WRKBL = MAX( WRKBL, 3*N+N*$ ILAENV( 1, 'DORMBR', 'PRT', N, N, N, -1 ) )MAXWRK = MAX( WRKBL, BDSPAC+3*N )MINWRK = 3*N + MAX( M, BDSPAC )ELSE IF( WNTQA ) THENWRKBL = MAX( WRKBL, 3*N+M*$ ILAENV( 1, 'DORMBR', 'QLN', M, M, N, -1 ) )WRKBL = MAX( WRKBL, 3*N+N*$ ILAENV( 1, 'DORMBR', 'PRT', N, N, N, -1 ) )MAXWRK = MAX( MAXWRK, BDSPAC+3*N )MINWRK = 3*N + MAX( M, BDSPAC )END IFEND IFELSE** Compute space needed for DBDSDC*IF( WNTQN ) THENBDSPAC = 7*MELSEBDSPAC = 3*M*M + 4*MEND IFIF( N.GE.MNTHR ) THENIF( WNTQN ) THEN** Path 1t (N much larger than M, JOBZ='N')*WRKBL = M + M*ILAENV( 1, 'DGELQF', ' ', M, N, -1,$ -1 )WRKBL = MAX( WRKBL, 3*M+2*M*$ ILAENV( 1, 'DGEBRD', ' ', M, M, -1, -1 ) )MAXWRK = MAX( WRKBL, BDSPAC+M )MINWRK = BDSPAC + MELSE IF( WNTQO ) THEN** Path 2t (N much larger than M, JOBZ='O')*WRKBL = M + M*ILAENV( 1, 'DGELQF', ' ', M, N, -1, -1 )WRKBL = MAX( WRKBL, M+M*ILAENV( 1, 'DORGLQ', ' ', M,$ N, M, -1 ) )WRKBL = MAX( WRKBL, 3*M+2*M*$ ILAENV( 1, 'DGEBRD', ' ', M, M, -1, -1 ) )WRKBL = MAX( WRKBL, 3*M+M*$ ILAENV( 1, 'DORMBR', 'QLN', M, M, M, -1 ) )WRKBL = MAX( WRKBL, 3*M+M*$ ILAENV( 1, 'DORMBR', 'PRT', M, M, M, -1 ) )WRKBL = MAX( WRKBL, BDSPAC+3*M )MAXWRK = WRKBL + 2*M*MMINWRK = BDSPAC + 2*M*M + 3*MELSE IF( WNTQS ) THEN** Path 3t (N much larger than M, JOBZ='S')*WRKBL = M + M*ILAENV( 1, 'DGELQF', ' ', M, N, -1, -1 )WRKBL = MAX( WRKBL, M+M*ILAENV( 1, 'DORGLQ', ' ', M,$ N, M, -1 ) )WRKBL = MAX( WRKBL, 3*M+2*M*$ ILAENV( 1, 'DGEBRD', ' ', M, M, -1, -1 ) )WRKBL = MAX( WRKBL, 3*M+M*$ ILAENV( 1, 'DORMBR', 'QLN', M, M, M, -1 ) )WRKBL = MAX( WRKBL, 3*M+M*$ ILAENV( 1, 'DORMBR', 'PRT', M, M, M, -1 ) )WRKBL = MAX( WRKBL, BDSPAC+3*M )MAXWRK = WRKBL + M*MMINWRK = BDSPAC + M*M + 3*MELSE IF( WNTQA ) THEN** Path 4t (N much larger than M, JOBZ='A')*WRKBL = M + M*ILAENV( 1, 'DGELQF', ' ', M, N, -1, -1 )WRKBL = MAX( WRKBL, M+N*ILAENV( 1, 'DORGLQ', ' ', N,$ N, M, -1 ) )WRKBL = MAX( WRKBL, 3*M+2*M*$ ILAENV( 1, 'DGEBRD', ' ', M, M, -1, -1 ) )WRKBL = MAX( WRKBL, 3*M+M*$ ILAENV( 1, 'DORMBR', 'QLN', M, M, M, -1 ) )WRKBL = MAX( WRKBL, 3*M+M*$ ILAENV( 1, 'DORMBR', 'PRT', M, M, M, -1 ) )WRKBL = MAX( WRKBL, BDSPAC+3*M )MAXWRK = WRKBL + M*MMINWRK = BDSPAC + M*M + 3*MEND IFELSE** Path 5t (N greater than M, but not much larger)*WRKBL = 3*M + ( M+N )*ILAENV( 1, 'DGEBRD', ' ', M, N, -1,$ -1 )IF( WNTQN ) THENMAXWRK = MAX( WRKBL, BDSPAC+3*M )MINWRK = 3*M + MAX( N, BDSPAC )ELSE IF( WNTQO ) THENWRKBL = MAX( WRKBL, 3*M+M*$ ILAENV( 1, 'DORMBR', 'QLN', M, M, N, -1 ) )WRKBL = MAX( WRKBL, 3*M+M*$ ILAENV( 1, 'DORMBR', 'PRT', M, N, M, -1 ) )WRKBL = MAX( WRKBL, BDSPAC+3*M )MAXWRK = WRKBL + M*NMINWRK = 3*M + MAX( N, M*M+BDSPAC )ELSE IF( WNTQS ) THENWRKBL = MAX( WRKBL, 3*M+M*$ ILAENV( 1, 'DORMBR', 'QLN', M, M, N, -1 ) )WRKBL = MAX( WRKBL, 3*M+M*$ ILAENV( 1, 'DORMBR', 'PRT', M, N, M, -1 ) )MAXWRK = MAX( WRKBL, BDSPAC+3*M )MINWRK = 3*M + MAX( N, BDSPAC )ELSE IF( WNTQA ) THENWRKBL = MAX( WRKBL, 3*M+M*$ ILAENV( 1, 'DORMBR', 'QLN', M, M, N, -1 ) )WRKBL = MAX( WRKBL, 3*M+M*$ ILAENV( 1, 'DORMBR', 'PRT', N, N, M, -1 ) )MAXWRK = MAX( WRKBL, BDSPAC+3*M )MINWRK = 3*M + MAX( N, BDSPAC )END IFEND IFEND IFWORK( 1 ) = MAXWRKEND IF*IF( LWORK.LT.MINWRK .AND. .NOT.LQUERY ) THENINFO = -12END IFIF( INFO.NE.0 ) THENCALL XERBLA( 'DGESDD', -INFO )RETURNELSE IF( LQUERY ) THENRETURNEND IF** Quick return if possible*IF( M.EQ.0 .OR. N.EQ.0 ) THENIF( LWORK.GE.1 )$ WORK( 1 ) = ONERETURNEND IF** Get machine constants*EPS = DLAMCH( 'P' )SMLNUM = SQRT( DLAMCH( 'S' ) ) / EPSBIGNUM = ONE / SMLNUM** Scale A if max element outside range [SMLNUM,BIGNUM]*ANRM = DLANGE( 'M', M, N, A, LDA, DUM )ISCL = 0IF( ANRM.GT.ZERO .AND. ANRM.LT.SMLNUM ) THENISCL = 1CALL DLASCL( 'G', 0, 0, ANRM, SMLNUM, M, N, A, LDA, IERR )ELSE IF( ANRM.GT.BIGNUM ) THENISCL = 1CALL DLASCL( 'G', 0, 0, ANRM, BIGNUM, M, N, A, LDA, IERR )END IF*IF( M.GE.N ) THEN** A has at least as many rows as columns. If A has sufficiently* more rows than columns, first reduce using the QR* decomposition (if sufficient workspace available)*IF( M.GE.MNTHR ) THEN*IF( WNTQN ) THEN** Path 1 (M much larger than N, JOBZ='N')* No singular vectors to be computed*ITAU = 1NWORK = ITAU + N** Compute A=Q*R* (Workspace: need 2*N, prefer N+N*NB)*CALL DGEQRF( M, N, A, LDA, WORK( ITAU ), WORK( NWORK ),$ LWORK-NWORK+1, IERR )** Zero out below R*CALL DLASET( 'L', N-1, N-1, ZERO, ZERO, A( 2, 1 ), LDA )IE = 1ITAUQ = IE + NITAUP = ITAUQ + NNWORK = ITAUP + N** Bidiagonalize R in A* (Workspace: need 4*N, prefer 3*N+2*N*NB)*CALL DGEBRD( N, N, A, LDA, S, WORK( IE ), WORK( ITAUQ ),$ WORK( ITAUP ), WORK( NWORK ), LWORK-NWORK+1,$ IERR )NWORK = IE + N** Perform bidiagonal SVD, computing singular values only* (Workspace: need N+BDSPAC)*CALL DBDSDC( 'U', 'N', N, S, WORK( IE ), DUM, 1, DUM, 1,$ DUM, IDUM, WORK( NWORK ), IWORK, INFO )*ELSE IF( WNTQO ) THEN** Path 2 (M much larger than N, JOBZ = 'O')* N left singular vectors to be overwritten on A and* N right singular vectors to be computed in VT*IR = 1** WORK(IR) is LDWRKR by N*IF( LWORK.GE.LDA*N+N*N+3*N+BDSPAC ) THENLDWRKR = LDAELSELDWRKR = ( LWORK-N*N-3*N-BDSPAC ) / NEND IFITAU = IR + LDWRKR*NNWORK = ITAU + N** Compute A=Q*R* (Workspace: need N*N+2*N, prefer N*N+N+N*NB)*CALL DGEQRF( M, N, A, LDA, WORK( ITAU ), WORK( NWORK ),$ LWORK-NWORK+1, IERR )** Copy R to WORK(IR), zeroing out below it*CALL DLACPY( 'U', N, N, A, LDA, WORK( IR ), LDWRKR )CALL DLASET( 'L', N-1, N-1, ZERO, ZERO, WORK( IR+1 ),$ LDWRKR )** Generate Q in A* (Workspace: need N*N+2*N, prefer N*N+N+N*NB)*CALL DORGQR( M, N, N, A, LDA, WORK( ITAU ),$ WORK( NWORK ), LWORK-NWORK+1, IERR )IE = ITAUITAUQ = IE + NITAUP = ITAUQ + NNWORK = ITAUP + N** Bidiagonalize R in VT, copying result to WORK(IR)* (Workspace: need N*N+4*N, prefer N*N+3*N+2*N*NB)*CALL DGEBRD( N, N, WORK( IR ), LDWRKR, S, WORK( IE ),$ WORK( ITAUQ ), WORK( ITAUP ), WORK( NWORK ),$ LWORK-NWORK+1, IERR )** WORK(IU) is N by N*IU = NWORKNWORK = IU + N*N** Perform bidiagonal SVD, computing left singular vectors* of bidiagonal matrix in WORK(IU) and computing right* singular vectors of bidiagonal matrix in VT* (Workspace: need N+N*N+BDSPAC)*CALL DBDSDC( 'U', 'I', N, S, WORK( IE ), WORK( IU ), N,$ VT, LDVT, DUM, IDUM, WORK( NWORK ), IWORK,$ INFO )** Overwrite WORK(IU) by left singular vectors of R* and VT by right singular vectors of R* (Workspace: need 2*N*N+3*N, prefer 2*N*N+2*N+N*NB)*CALL DORMBR( 'Q', 'L', 'N', N, N, N, WORK( IR ), LDWRKR,$ WORK( ITAUQ ), WORK( IU ), N, WORK( NWORK ),$ LWORK-NWORK+1, IERR )CALL DORMBR( 'P', 'R', 'T', N, N, N, WORK( IR ), LDWRKR,$ WORK( ITAUP ), VT, LDVT, WORK( NWORK ),$ LWORK-NWORK+1, IERR )** Multiply Q in A by left singular vectors of R in* WORK(IU), storing result in WORK(IR) and copying to A* (Workspace: need 2*N*N, prefer N*N+M*N)*DO 10 I = 1, M, LDWRKRCHUNK = MIN( M-I+1, LDWRKR )CALL DGEMM( 'N', 'N', CHUNK, N, N, ONE, A( I, 1 ),$ LDA, WORK( IU ), N, ZERO, WORK( IR ),$ LDWRKR )CALL DLACPY( 'F', CHUNK, N, WORK( IR ), LDWRKR,$ A( I, 1 ), LDA )10 CONTINUE*ELSE IF( WNTQS ) THEN** Path 3 (M much larger than N, JOBZ='S')* N left singular vectors to be computed in U and* N right singular vectors to be computed in VT*IR = 1** WORK(IR) is N by N*LDWRKR = NITAU = IR + LDWRKR*NNWORK = ITAU + N** Compute A=Q*R* (Workspace: need N*N+2*N, prefer N*N+N+N*NB)*CALL DGEQRF( M, N, A, LDA, WORK( ITAU ), WORK( NWORK ),$ LWORK-NWORK+1, IERR )** Copy R to WORK(IR), zeroing out below it*CALL DLACPY( 'U', N, N, A, LDA, WORK( IR ), LDWRKR )CALL DLASET( 'L', N-1, N-1, ZERO, ZERO, WORK( IR+1 ),$ LDWRKR )** Generate Q in A* (Workspace: need N*N+2*N, prefer N*N+N+N*NB)*CALL DORGQR( M, N, N, A, LDA, WORK( ITAU ),$ WORK( NWORK ), LWORK-NWORK+1, IERR )IE = ITAUITAUQ = IE + NITAUP = ITAUQ + NNWORK = ITAUP + N** Bidiagonalize R in WORK(IR)* (Workspace: need N*N+4*N, prefer N*N+3*N+2*N*NB)*CALL DGEBRD( N, N, WORK( IR ), LDWRKR, S, WORK( IE ),$ WORK( ITAUQ ), WORK( ITAUP ), WORK( NWORK ),$ LWORK-NWORK+1, IERR )** Perform bidiagonal SVD, computing left singular vectors* of bidiagoal matrix in U and computing right singular* vectors of bidiagonal matrix in VT* (Workspace: need N+BDSPAC)*CALL DBDSDC( 'U', 'I', N, S, WORK( IE ), U, LDU, VT,$ LDVT, DUM, IDUM, WORK( NWORK ), IWORK,$ INFO )** Overwrite U by left singular vectors of R and VT* by right singular vectors of R* (Workspace: need N*N+3*N, prefer N*N+2*N+N*NB)*CALL DORMBR( 'Q', 'L', 'N', N, N, N, WORK( IR ), LDWRKR,$ WORK( ITAUQ ), U, LDU, WORK( NWORK ),$ LWORK-NWORK+1, IERR )*CALL DORMBR( 'P', 'R', 'T', N, N, N, WORK( IR ), LDWRKR,$ WORK( ITAUP ), VT, LDVT, WORK( NWORK ),$ LWORK-NWORK+1, IERR )** Multiply Q in A by left singular vectors of R in* WORK(IR), storing result in U* (Workspace: need N*N)*CALL DLACPY( 'F', N, N, U, LDU, WORK( IR ), LDWRKR )CALL DGEMM( 'N', 'N', M, N, N, ONE, A, LDA, WORK( IR ),$ LDWRKR, ZERO, U, LDU )*ELSE IF( WNTQA ) THEN** Path 4 (M much larger than N, JOBZ='A')* M left singular vectors to be computed in U and* N right singular vectors to be computed in VT*IU = 1** WORK(IU) is N by N*LDWRKU = NITAU = IU + LDWRKU*NNWORK = ITAU + N** Compute A=Q*R, copying result to U* (Workspace: need N*N+2*N, prefer N*N+N+N*NB)*CALL DGEQRF( M, N, A, LDA, WORK( ITAU ), WORK( NWORK ),$ LWORK-NWORK+1, IERR )CALL DLACPY( 'L', M, N, A, LDA, U, LDU )** Generate Q in U* (Workspace: need N*N+2*N, prefer N*N+N+N*NB)CALL DORGQR( M, M, N, U, LDU, WORK( ITAU ),$ WORK( NWORK ), LWORK-NWORK+1, IERR )** Produce R in A, zeroing out other entries*CALL DLASET( 'L', N-1, N-1, ZERO, ZERO, A( 2, 1 ), LDA )IE = ITAUITAUQ = IE + NITAUP = ITAUQ + NNWORK = ITAUP + N** Bidiagonalize R in A* (Workspace: need N*N+4*N, prefer N*N+3*N+2*N*NB)*CALL DGEBRD( N, N, A, LDA, S, WORK( IE ), WORK( ITAUQ ),$ WORK( ITAUP ), WORK( NWORK ), LWORK-NWORK+1,$ IERR )** Perform bidiagonal SVD, computing left singular vectors* of bidiagonal matrix in WORK(IU) and computing right* singular vectors of bidiagonal matrix in VT* (Workspace: need N+N*N+BDSPAC)*CALL DBDSDC( 'U', 'I', N, S, WORK( IE ), WORK( IU ), N,$ VT, LDVT, DUM, IDUM, WORK( NWORK ), IWORK,$ INFO )** Overwrite WORK(IU) by left singular vectors of R and VT* by right singular vectors of R* (Workspace: need N*N+3*N, prefer N*N+2*N+N*NB)*CALL DORMBR( 'Q', 'L', 'N', N, N, N, A, LDA,$ WORK( ITAUQ ), WORK( IU ), LDWRKU,$ WORK( NWORK ), LWORK-NWORK+1, IERR )CALL DORMBR( 'P', 'R', 'T', N, N, N, A, LDA,$ WORK( ITAUP ), VT, LDVT, WORK( NWORK ),$ LWORK-NWORK+1, IERR )** Multiply Q in U by left singular vectors of R in* WORK(IU), storing result in A* (Workspace: need N*N)*CALL DGEMM( 'N', 'N', M, N, N, ONE, U, LDU, WORK( IU ),$ LDWRKU, ZERO, A, LDA )** Copy left singular vectors of A from A to U*CALL DLACPY( 'F', M, N, A, LDA, U, LDU )*END IF*ELSE** M .LT. MNTHR** Path 5 (M at least N, but not much larger)* Reduce to bidiagonal form without QR decomposition*IE = 1ITAUQ = IE + NITAUP = ITAUQ + NNWORK = ITAUP + N** Bidiagonalize A* (Workspace: need 3*N+M, prefer 3*N+(M+N)*NB)*CALL DGEBRD( M, N, A, LDA, S, WORK( IE ), WORK( ITAUQ ),$ WORK( ITAUP ), WORK( NWORK ), LWORK-NWORK+1,$ IERR )IF( WNTQN ) THEN** Perform bidiagonal SVD, only computing singular values* (Workspace: need N+BDSPAC)*CALL DBDSDC( 'U', 'N', N, S, WORK( IE ), DUM, 1, DUM, 1,$ DUM, IDUM, WORK( NWORK ), IWORK, INFO )ELSE IF( WNTQO ) THENIU = NWORKIF( LWORK.GE.M*N+3*N+BDSPAC ) THEN** WORK( IU ) is M by N*LDWRKU = MNWORK = IU + LDWRKU*NCALL DLASET( 'F', M, N, ZERO, ZERO, WORK( IU ),$ LDWRKU )ELSE** WORK( IU ) is N by N*LDWRKU = NNWORK = IU + LDWRKU*N** WORK(IR) is LDWRKR by N*IR = NWORKLDWRKR = ( LWORK-N*N-3*N ) / NEND IFNWORK = IU + LDWRKU*N** Perform bidiagonal SVD, computing left singular vectors* of bidiagonal matrix in WORK(IU) and computing right* singular vectors of bidiagonal matrix in VT* (Workspace: need N+N*N+BDSPAC)*CALL DBDSDC( 'U', 'I', N, S, WORK( IE ), WORK( IU ),$ LDWRKU, VT, LDVT, DUM, IDUM, WORK( NWORK ),$ IWORK, INFO )** Overwrite VT by right singular vectors of A* (Workspace: need N*N+2*N, prefer N*N+N+N*NB)*CALL DORMBR( 'P', 'R', 'T', N, N, N, A, LDA,$ WORK( ITAUP ), VT, LDVT, WORK( NWORK ),$ LWORK-NWORK+1, IERR )*IF( LWORK.GE.M*N+3*N+BDSPAC ) THEN** Overwrite WORK(IU) by left singular vectors of A* (Workspace: need N*N+2*N, prefer N*N+N+N*NB)*CALL DORMBR( 'Q', 'L', 'N', M, N, N, A, LDA,$ WORK( ITAUQ ), WORK( IU ), LDWRKU,$ WORK( NWORK ), LWORK-NWORK+1, IERR )** Copy left singular vectors of A from WORK(IU) to A*CALL DLACPY( 'F', M, N, WORK( IU ), LDWRKU, A, LDA )ELSE** Generate Q in A* (Workspace: need N*N+2*N, prefer N*N+N+N*NB)*CALL DORGBR( 'Q', M, N, N, A, LDA, WORK( ITAUQ ),$ WORK( NWORK ), LWORK-NWORK+1, IERR )** Multiply Q in A by left singular vectors of* bidiagonal matrix in WORK(IU), storing result in* WORK(IR) and copying to A* (Workspace: need 2*N*N, prefer N*N+M*N)*DO 20 I = 1, M, LDWRKRCHUNK = MIN( M-I+1, LDWRKR )CALL DGEMM( 'N', 'N', CHUNK, N, N, ONE, A( I, 1 ),$ LDA, WORK( IU ), LDWRKU, ZERO,$ WORK( IR ), LDWRKR )CALL DLACPY( 'F', CHUNK, N, WORK( IR ), LDWRKR,$ A( I, 1 ), LDA )20 CONTINUEEND IF*ELSE IF( WNTQS ) THEN** Perform bidiagonal SVD, computing left singular vectors* of bidiagonal matrix in U and computing right singular* vectors of bidiagonal matrix in VT* (Workspace: need N+BDSPAC)*CALL DLASET( 'F', M, N, ZERO, ZERO, U, LDU )CALL DBDSDC( 'U', 'I', N, S, WORK( IE ), U, LDU, VT,$ LDVT, DUM, IDUM, WORK( NWORK ), IWORK,$ INFO )** Overwrite U by left singular vectors of A and VT* by right singular vectors of A* (Workspace: need 3*N, prefer 2*N+N*NB)*CALL DORMBR( 'Q', 'L', 'N', M, N, N, A, LDA,$ WORK( ITAUQ ), U, LDU, WORK( NWORK ),$ LWORK-NWORK+1, IERR )CALL DORMBR( 'P', 'R', 'T', N, N, N, A, LDA,$ WORK( ITAUP ), VT, LDVT, WORK( NWORK ),$ LWORK-NWORK+1, IERR )ELSE IF( WNTQA ) THEN** Perform bidiagonal SVD, computing left singular vectors* of bidiagonal matrix in U and computing right singular* vectors of bidiagonal matrix in VT* (Workspace: need N+BDSPAC)*CALL DLASET( 'F', M, M, ZERO, ZERO, U, LDU )CALL DBDSDC( 'U', 'I', N, S, WORK( IE ), U, LDU, VT,$ LDVT, DUM, IDUM, WORK( NWORK ), IWORK,$ INFO )** Set the right corner of U to identity matrix*CALL DLASET( 'F', M-N, M-N, ZERO, ONE, U( N+1, N+1 ),$ LDU )** Overwrite U by left singular vectors of A and VT* by right singular vectors of A* (Workspace: need N*N+2*N+M, prefer N*N+2*N+M*NB)*CALL DORMBR( 'Q', 'L', 'N', M, M, N, A, LDA,$ WORK( ITAUQ ), U, LDU, WORK( NWORK ),$ LWORK-NWORK+1, IERR )CALL DORMBR( 'P', 'R', 'T', N, N, M, A, LDA,$ WORK( ITAUP ), VT, LDVT, WORK( NWORK ),$ LWORK-NWORK+1, IERR )END IF*END IF*ELSE** A has more columns than rows. If A has sufficiently more* columns than rows, first reduce using the LQ decomposition (if* sufficient workspace available)*IF( N.GE.MNTHR ) THEN*IF( WNTQN ) THEN** Path 1t (N much larger than M, JOBZ='N')* No singular vectors to be computed*ITAU = 1NWORK = ITAU + M** Compute A=L*Q* (Workspace: need 2*M, prefer M+M*NB)*CALL DGELQF( M, N, A, LDA, WORK( ITAU ), WORK( NWORK ),$ LWORK-NWORK+1, IERR )** Zero out above L*CALL DLASET( 'U', M-1, M-1, ZERO, ZERO, A( 1, 2 ), LDA )IE = 1ITAUQ = IE + MITAUP = ITAUQ + MNWORK = ITAUP + M** Bidiagonalize L in A* (Workspace: need 4*M, prefer 3*M+2*M*NB)*CALL DGEBRD( M, M, A, LDA, S, WORK( IE ), WORK( ITAUQ ),$ WORK( ITAUP ), WORK( NWORK ), LWORK-NWORK+1,$ IERR )NWORK = IE + M** Perform bidiagonal SVD, computing singular values only* (Workspace: need M+BDSPAC)*CALL DBDSDC( 'U', 'N', M, S, WORK( IE ), DUM, 1, DUM, 1,$ DUM, IDUM, WORK( NWORK ), IWORK, INFO )*ELSE IF( WNTQO ) THEN** Path 2t (N much larger than M, JOBZ='O')* M right singular vectors to be overwritten on A and* M left singular vectors to be computed in U*IVT = 1** IVT is M by M*IL = IVT + M*MIF( LWORK.GE.M*N+M*M+3*M+BDSPAC ) THEN** WORK(IL) is M by N*LDWRKL = MCHUNK = NELSELDWRKL = MCHUNK = ( LWORK-M*M ) / MEND IFITAU = IL + LDWRKL*MNWORK = ITAU + M** Compute A=L*Q* (Workspace: need M*M+2*M, prefer M*M+M+M*NB)*CALL DGELQF( M, N, A, LDA, WORK( ITAU ), WORK( NWORK ),$ LWORK-NWORK+1, IERR )** Copy L to WORK(IL), zeroing about above it*CALL DLACPY( 'L', M, M, A, LDA, WORK( IL ), LDWRKL )CALL DLASET( 'U', M-1, M-1, ZERO, ZERO,$ WORK( IL+LDWRKL ), LDWRKL )** Generate Q in A* (Workspace: need M*M+2*M, prefer M*M+M+M*NB)*CALL DORGLQ( M, N, M, A, LDA, WORK( ITAU ),$ WORK( NWORK ), LWORK-NWORK+1, IERR )IE = ITAUITAUQ = IE + MITAUP = ITAUQ + MNWORK = ITAUP + M** Bidiagonalize L in WORK(IL)* (Workspace: need M*M+4*M, prefer M*M+3*M+2*M*NB)*CALL DGEBRD( M, M, WORK( IL ), LDWRKL, S, WORK( IE ),$ WORK( ITAUQ ), WORK( ITAUP ), WORK( NWORK ),$ LWORK-NWORK+1, IERR )** Perform bidiagonal SVD, computing left singular vectors* of bidiagonal matrix in U, and computing right singular* vectors of bidiagonal matrix in WORK(IVT)* (Workspace: need M+M*M+BDSPAC)*CALL DBDSDC( 'U', 'I', M, S, WORK( IE ), U, LDU,$ WORK( IVT ), M, DUM, IDUM, WORK( NWORK ),$ IWORK, INFO )** Overwrite U by left singular vectors of L and WORK(IVT)* by right singular vectors of L* (Workspace: need 2*M*M+3*M, prefer 2*M*M+2*M+M*NB)*CALL DORMBR( 'Q', 'L', 'N', M, M, M, WORK( IL ), LDWRKL,$ WORK( ITAUQ ), U, LDU, WORK( NWORK ),$ LWORK-NWORK+1, IERR )CALL DORMBR( 'P', 'R', 'T', M, M, M, WORK( IL ), LDWRKL,$ WORK( ITAUP ), WORK( IVT ), M,$ WORK( NWORK ), LWORK-NWORK+1, IERR )** Multiply right singular vectors of L in WORK(IVT) by Q* in A, storing result in WORK(IL) and copying to A* (Workspace: need 2*M*M, prefer M*M+M*N)*DO 30 I = 1, N, CHUNKBLK = MIN( N-I+1, CHUNK )CALL DGEMM( 'N', 'N', M, BLK, M, ONE, WORK( IVT ), M,$ A( 1, I ), LDA, ZERO, WORK( IL ), LDWRKL )CALL DLACPY( 'F', M, BLK, WORK( IL ), LDWRKL,$ A( 1, I ), LDA )30 CONTINUE*ELSE IF( WNTQS ) THEN** Path 3t (N much larger than M, JOBZ='S')* M right singular vectors to be computed in VT and* M left singular vectors to be computed in U*IL = 1** WORK(IL) is M by M*LDWRKL = MITAU = IL + LDWRKL*MNWORK = ITAU + M** Compute A=L*Q* (Workspace: need M*M+2*M, prefer M*M+M+M*NB)*CALL DGELQF( M, N, A, LDA, WORK( ITAU ), WORK( NWORK ),$ LWORK-NWORK+1, IERR )** Copy L to WORK(IL), zeroing out above it*CALL DLACPY( 'L', M, M, A, LDA, WORK( IL ), LDWRKL )CALL DLASET( 'U', M-1, M-1, ZERO, ZERO,$ WORK( IL+LDWRKL ), LDWRKL )** Generate Q in A* (Workspace: need M*M+2*M, prefer M*M+M+M*NB)*CALL DORGLQ( M, N, M, A, LDA, WORK( ITAU ),$ WORK( NWORK ), LWORK-NWORK+1, IERR )IE = ITAUITAUQ = IE + MITAUP = ITAUQ + MNWORK = ITAUP + M** Bidiagonalize L in WORK(IU), copying result to U* (Workspace: need M*M+4*M, prefer M*M+3*M+2*M*NB)*CALL DGEBRD( M, M, WORK( IL ), LDWRKL, S, WORK( IE ),$ WORK( ITAUQ ), WORK( ITAUP ), WORK( NWORK ),$ LWORK-NWORK+1, IERR )** Perform bidiagonal SVD, computing left singular vectors* of bidiagonal matrix in U and computing right singular* vectors of bidiagonal matrix in VT* (Workspace: need M+BDSPAC)*CALL DBDSDC( 'U', 'I', M, S, WORK( IE ), U, LDU, VT,$ LDVT, DUM, IDUM, WORK( NWORK ), IWORK,$ INFO )** Overwrite U by left singular vectors of L and VT* by right singular vectors of L* (Workspace: need M*M+3*M, prefer M*M+2*M+M*NB)*CALL DORMBR( 'Q', 'L', 'N', M, M, M, WORK( IL ), LDWRKL,$ WORK( ITAUQ ), U, LDU, WORK( NWORK ),$ LWORK-NWORK+1, IERR )CALL DORMBR( 'P', 'R', 'T', M, M, M, WORK( IL ), LDWRKL,$ WORK( ITAUP ), VT, LDVT, WORK( NWORK ),$ LWORK-NWORK+1, IERR )** Multiply right singular vectors of L in WORK(IL) by* Q in A, storing result in VT* (Workspace: need M*M)*CALL DLACPY( 'F', M, M, VT, LDVT, WORK( IL ), LDWRKL )CALL DGEMM( 'N', 'N', M, N, M, ONE, WORK( IL ), LDWRKL,$ A, LDA, ZERO, VT, LDVT )*ELSE IF( WNTQA ) THEN** Path 4t (N much larger than M, JOBZ='A')* N right singular vectors to be computed in VT and* M left singular vectors to be computed in U*IVT = 1** WORK(IVT) is M by M*LDWKVT = MITAU = IVT + LDWKVT*MNWORK = ITAU + M** Compute A=L*Q, copying result to VT* (Workspace: need M*M+2*M, prefer M*M+M+M*NB)*CALL DGELQF( M, N, A, LDA, WORK( ITAU ), WORK( NWORK ),$ LWORK-NWORK+1, IERR )CALL DLACPY( 'U', M, N, A, LDA, VT, LDVT )** Generate Q in VT* (Workspace: need M*M+2*M, prefer M*M+M+M*NB)*CALL DORGLQ( N, N, M, VT, LDVT, WORK( ITAU ),$ WORK( NWORK ), LWORK-NWORK+1, IERR )** Produce L in A, zeroing out other entries*CALL DLASET( 'U', M-1, M-1, ZERO, ZERO, A( 1, 2 ), LDA )IE = ITAUITAUQ = IE + MITAUP = ITAUQ + MNWORK = ITAUP + M** Bidiagonalize L in A* (Workspace: need M*M+4*M, prefer M*M+3*M+2*M*NB)*CALL DGEBRD( M, M, A, LDA, S, WORK( IE ), WORK( ITAUQ ),$ WORK( ITAUP ), WORK( NWORK ), LWORK-NWORK+1,$ IERR )** Perform bidiagonal SVD, computing left singular vectors* of bidiagonal matrix in U and computing right singular* vectors of bidiagonal matrix in WORK(IVT)* (Workspace: need M+M*M+BDSPAC)*CALL DBDSDC( 'U', 'I', M, S, WORK( IE ), U, LDU,$ WORK( IVT ), LDWKVT, DUM, IDUM,$ WORK( NWORK ), IWORK, INFO )** Overwrite U by left singular vectors of L and WORK(IVT)* by right singular vectors of L* (Workspace: need M*M+3*M, prefer M*M+2*M+M*NB)*CALL DORMBR( 'Q', 'L', 'N', M, M, M, A, LDA,$ WORK( ITAUQ ), U, LDU, WORK( NWORK ),$ LWORK-NWORK+1, IERR )CALL DORMBR( 'P', 'R', 'T', M, M, M, A, LDA,$ WORK( ITAUP ), WORK( IVT ), LDWKVT,$ WORK( NWORK ), LWORK-NWORK+1, IERR )** Multiply right singular vectors of L in WORK(IVT) by* Q in VT, storing result in A* (Workspace: need M*M)*CALL DGEMM( 'N', 'N', M, N, M, ONE, WORK( IVT ), LDWKVT,$ VT, LDVT, ZERO, A, LDA )** Copy right singular vectors of A from A to VT*CALL DLACPY( 'F', M, N, A, LDA, VT, LDVT )*END IF*ELSE** N .LT. MNTHR** Path 5t (N greater than M, but not much larger)* Reduce to bidiagonal form without LQ decomposition*IE = 1ITAUQ = IE + MITAUP = ITAUQ + MNWORK = ITAUP + M** Bidiagonalize A* (Workspace: need 3*M+N, prefer 3*M+(M+N)*NB)*CALL DGEBRD( M, N, A, LDA, S, WORK( IE ), WORK( ITAUQ ),$ WORK( ITAUP ), WORK( NWORK ), LWORK-NWORK+1,$ IERR )IF( WNTQN ) THEN** Perform bidiagonal SVD, only computing singular values* (Workspace: need M+BDSPAC)*CALL DBDSDC( 'L', 'N', M, S, WORK( IE ), DUM, 1, DUM, 1,$ DUM, IDUM, WORK( NWORK ), IWORK, INFO )ELSE IF( WNTQO ) THENLDWKVT = MIVT = NWORKIF( LWORK.GE.M*N+3*M+BDSPAC ) THEN** WORK( IVT ) is M by N*CALL DLASET( 'F', M, N, ZERO, ZERO, WORK( IVT ),$ LDWKVT )NWORK = IVT + LDWKVT*NELSE** WORK( IVT ) is M by M*NWORK = IVT + LDWKVT*MIL = NWORK** WORK(IL) is M by CHUNK*CHUNK = ( LWORK-M*M-3*M ) / MEND IF** Perform bidiagonal SVD, computing left singular vectors* of bidiagonal matrix in U and computing right singular* vectors of bidiagonal matrix in WORK(IVT)* (Workspace: need M*M+BDSPAC)*CALL DBDSDC( 'L', 'I', M, S, WORK( IE ), U, LDU,$ WORK( IVT ), LDWKVT, DUM, IDUM,$ WORK( NWORK ), IWORK, INFO )** Overwrite U by left singular vectors of A* (Workspace: need M*M+2*M, prefer M*M+M+M*NB)*CALL DORMBR( 'Q', 'L', 'N', M, M, N, A, LDA,$ WORK( ITAUQ ), U, LDU, WORK( NWORK ),$ LWORK-NWORK+1, IERR )*IF( LWORK.GE.M*N+3*M+BDSPAC ) THEN** Overwrite WORK(IVT) by left singular vectors of A* (Workspace: need M*M+2*M, prefer M*M+M+M*NB)*CALL DORMBR( 'P', 'R', 'T', M, N, M, A, LDA,$ WORK( ITAUP ), WORK( IVT ), LDWKVT,$ WORK( NWORK ), LWORK-NWORK+1, IERR )** Copy right singular vectors of A from WORK(IVT) to A*CALL DLACPY( 'F', M, N, WORK( IVT ), LDWKVT, A, LDA )ELSE** Generate P**T in A* (Workspace: need M*M+2*M, prefer M*M+M+M*NB)*CALL DORGBR( 'P', M, N, M, A, LDA, WORK( ITAUP ),$ WORK( NWORK ), LWORK-NWORK+1, IERR )** Multiply Q in A by right singular vectors of* bidiagonal matrix in WORK(IVT), storing result in* WORK(IL) and copying to A* (Workspace: need 2*M*M, prefer M*M+M*N)*DO 40 I = 1, N, CHUNKBLK = MIN( N-I+1, CHUNK )CALL DGEMM( 'N', 'N', M, BLK, M, ONE, WORK( IVT ),$ LDWKVT, A( 1, I ), LDA, ZERO,$ WORK( IL ), M )CALL DLACPY( 'F', M, BLK, WORK( IL ), M, A( 1, I ),$ LDA )40 CONTINUEEND IFELSE IF( WNTQS ) THEN** Perform bidiagonal SVD, computing left singular vectors* of bidiagonal matrix in U and computing right singular* vectors of bidiagonal matrix in VT* (Workspace: need M+BDSPAC)*CALL DLASET( 'F', M, N, ZERO, ZERO, VT, LDVT )CALL DBDSDC( 'L', 'I', M, S, WORK( IE ), U, LDU, VT,$ LDVT, DUM, IDUM, WORK( NWORK ), IWORK,$ INFO )** Overwrite U by left singular vectors of A and VT* by right singular vectors of A* (Workspace: need 3*M, prefer 2*M+M*NB)*CALL DORMBR( 'Q', 'L', 'N', M, M, N, A, LDA,$ WORK( ITAUQ ), U, LDU, WORK( NWORK ),$ LWORK-NWORK+1, IERR )CALL DORMBR( 'P', 'R', 'T', M, N, M, A, LDA,$ WORK( ITAUP ), VT, LDVT, WORK( NWORK ),$ LWORK-NWORK+1, IERR )ELSE IF( WNTQA ) THEN** Perform bidiagonal SVD, computing left singular vectors* of bidiagonal matrix in U and computing right singular* vectors of bidiagonal matrix in VT* (Workspace: need M+BDSPAC)*CALL DLASET( 'F', N, N, ZERO, ZERO, VT, LDVT )CALL DBDSDC( 'L', 'I', M, S, WORK( IE ), U, LDU, VT,$ LDVT, DUM, IDUM, WORK( NWORK ), IWORK,$ INFO )** Set the right corner of VT to identity matrix*CALL DLASET( 'F', N-M, N-M, ZERO, ONE, VT( M+1, M+1 ),$ LDVT )** Overwrite U by left singular vectors of A and VT* by right singular vectors of A* (Workspace: need 2*M+N, prefer 2*M+N*NB)*CALL DORMBR( 'Q', 'L', 'N', M, M, N, A, LDA,$ WORK( ITAUQ ), U, LDU, WORK( NWORK ),$ LWORK-NWORK+1, IERR )CALL DORMBR( 'P', 'R', 'T', N, N, M, A, LDA,$ WORK( ITAUP ), VT, LDVT, WORK( NWORK ),$ LWORK-NWORK+1, IERR )END IF*END IF*END IF** Undo scaling if necessary*IF( ISCL.EQ.1 ) THENIF( ANRM.GT.BIGNUM )$ CALL DLASCL( 'G', 0, 0, BIGNUM, ANRM, MINMN, 1, S, MINMN,$ IERR )IF( ANRM.LT.SMLNUM )$ CALL DLASCL( 'G', 0, 0, SMLNUM, ANRM, MINMN, 1, S, MINMN,$ IERR )END IF** Return optimal workspace in WORK(1)*WORK( 1 ) = DBLE( MAXWRK )*RETURN** End of DGESDD*ENDSUBROUTINE DGESV( N, NRHS, A, LDA, IPIV, B, LDB, INFO )** -- LAPACK driver 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, LDB, N, NRHS* ..* .. Array Arguments ..INTEGER IPIV( * )DOUBLE PRECISION A( LDA, * ), B( LDB, * )* ..** Purpose* =======** DGESV computes the solution to a real system of linear equations* A * X = B,* where A is an N-by-N matrix and X and B are N-by-NRHS matrices.** The LU decomposition with partial pivoting and row interchanges is* used to factor A as* A = P * L * U,* where P is a permutation matrix, L is unit lower triangular, and U is* upper triangular. The factored form of A is then used to solve the* system of equations A * X = B.** Arguments* =========** N (input) INTEGER* The number of linear equations, i.e., the order of the* matrix A. N >= 0.** NRHS (input) INTEGER* The number of right hand sides, i.e., the number of columns* of the matrix B. NRHS >= 0.** A (input/output) DOUBLE PRECISION array, dimension (LDA,N)* On entry, the N-by-N coefficient matrix A.* On exit, the factors L and U from the factorization* A = P*L*U; the unit diagonal elements of L are not stored.** LDA (input) INTEGER* The leading dimension of the array A. LDA >= max(1,N).** IPIV (output) INTEGER array, dimension (N)* The pivot indices that define the permutation matrix P;* row i of the matrix was interchanged with row IPIV(i).** B (input/output) DOUBLE PRECISION array, dimension (LDB,NRHS)* On entry, the N-by-NRHS matrix of right hand side matrix B.* On exit, if INFO = 0, the N-by-NRHS solution matrix X.** LDB (input) INTEGER* The leading dimension of the array B. LDB >= max(1,N).** INFO (output) INTEGER* = 0: successful exit* < 0: if INFO = -i, the i-th argument had an illegal value* > 0: if INFO = i, U(i,i) is exactly zero. The factorization* has been completed, but the factor U is exactly* singular, so the solution could not be computed.** =====================================================================** .. External Subroutines ..EXTERNAL DGETRF, DGETRS, XERBLA* ..* .. Intrinsic Functions ..INTRINSIC MAX* ..* .. Executable Statements ..** Test the input parameters.*INFO = 0IF( N.LT.0 ) THENINFO = -1ELSE IF( NRHS.LT.0 ) THENINFO = -2ELSE IF( LDA.LT.MAX( 1, N ) ) THENINFO = -4ELSE IF( LDB.LT.MAX( 1, N ) ) THENINFO = -7END IFIF( INFO.NE.0 ) THENCALL XERBLA( 'DGESV ', -INFO )RETURNEND IF** Compute the LU factorization of A.*CALL DGETRF( N, N, A, LDA, IPIV, INFO )IF( INFO.EQ.0 ) THEN** Solve the system A*X = B, overwriting B with X.*CALL DGETRS( 'No transpose', N, NRHS, A, LDA, IPIV, B, LDB,$ INFO )END IFRETURN** End of DGESV*ENDSUBROUTINE DGESVD( JOBU, JOBVT, M, N, A, LDA, S, U, LDU, VT, LDVT,$ WORK, LWORK, INFO )** -- LAPACK driver 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 JOBU, JOBVTINTEGER INFO, LDA, LDU, LDVT, LWORK, M, N* ..* .. Array Arguments ..DOUBLE PRECISION A( LDA, * ), S( * ), U( LDU, * ),$ VT( LDVT, * ), WORK( * )* ..** Purpose* =======** DGESVD computes the singular value decomposition (SVD) of a real* M-by-N matrix A, optionally computing the left and/or right singular* vectors. The SVD is written** A = U * SIGMA * transpose(V)** where SIGMA is an M-by-N matrix which is zero except for its* min(m,n) diagonal elements, U is an M-by-M orthogonal matrix, and* V is an N-by-N orthogonal matrix. The diagonal elements of SIGMA* are the singular values of A; they are real and non-negative, and* are returned in descending order. The first min(m,n) columns of* U and V are the left and right singular vectors of A.** Note that the routine returns V**T, not V.** Arguments* =========** JOBU (input) CHARACTER*1* Specifies options for computing all or part of the matrix U:* = 'A': all M columns of U are returned in array U:* = 'S': the first min(m,n) columns of U (the left singular* vectors) are returned in the array U;* = 'O': the first min(m,n) columns of U (the left singular* vectors) are overwritten on the array A;* = 'N': no columns of U (no left singular vectors) are* computed.** JOBVT (input) CHARACTER*1* Specifies options for computing all or part of the matrix* V**T:* = 'A': all N rows of V**T are returned in the array VT;* = 'S': the first min(m,n) rows of V**T (the right singular* vectors) are returned in the array VT;* = 'O': the first min(m,n) rows of V**T (the right singular* vectors) are overwritten on the array A;* = 'N': no rows of V**T (no right singular vectors) are* computed.** JOBVT and JOBU cannot both be 'O'.** M (input) INTEGER* The number of rows of the input matrix A. M >= 0.** N (input) INTEGER* The number of columns of the input matrix A. N >= 0.** A (input/output) DOUBLE PRECISION array, dimension (LDA,N)* On entry, the M-by-N matrix A.* On exit,* if JOBU = 'O', A is overwritten with the first min(m,n)* columns of U (the left singular vectors,* stored columnwise);* if JOBVT = 'O', A is overwritten with the first min(m,n)* rows of V**T (the right singular vectors,* stored rowwise);* if JOBU .ne. 'O' and JOBVT .ne. 'O', the contents of A* are destroyed.** LDA (input) INTEGER* The leading dimension of the array A. LDA >= max(1,M).** S (output) DOUBLE PRECISION array, dimension (min(M,N))* The singular values of A, sorted so that S(i) >= S(i+1).** U (output) DOUBLE PRECISION array, dimension (LDU,UCOL)* (LDU,M) if JOBU = 'A' or (LDU,min(M,N)) if JOBU = 'S'.* If JOBU = 'A', U contains the M-by-M orthogonal matrix U;* if JOBU = 'S', U contains the first min(m,n) columns of U* (the left singular vectors, stored columnwise);* if JOBU = 'N' or 'O', U is not referenced.** LDU (input) INTEGER* The leading dimension of the array U. LDU >= 1; if* JOBU = 'S' or 'A', LDU >= M.** VT (output) DOUBLE PRECISION array, dimension (LDVT,N)* If JOBVT = 'A', VT contains the N-by-N orthogonal matrix* V**T;* if JOBVT = 'S', VT contains the first min(m,n) rows of* V**T (the right singular vectors, stored rowwise);* if JOBVT = 'N' or 'O', VT is not referenced.** LDVT (input) INTEGER* The leading dimension of the array VT. LDVT >= 1; if* JOBVT = 'A', LDVT >= N; if JOBVT = 'S', LDVT >= min(M,N).** WORK (workspace/output) DOUBLE PRECISION array, dimension (LWORK)* On exit, if INFO = 0, WORK(1) returns the optimal LWORK;* if INFO > 0, WORK(2:MIN(M,N)) contains the unconverged* superdiagonal elements of an upper bidiagonal matrix B* whose diagonal is in S (not necessarily sorted). B* satisfies A = U * B * VT, so it has the same singular values* as A, and singular vectors related by U and VT.** LWORK (input) INTEGER* The dimension of the array WORK. LWORK >= 1.* LWORK >= MAX(3*MIN(M,N)+MAX(M,N),5*MIN(M,N)).* For good performance, LWORK should generally be larger.** 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 DBDSQR did not converge, INFO specifies how many* superdiagonals of an intermediate bidiagonal form B* did not converge to zero. See the description of WORK* above for details.** =====================================================================** .. Parameters ..DOUBLE PRECISION ZERO, ONEPARAMETER ( ZERO = 0.0D0, ONE = 1.0D0 )* ..* .. Local Scalars ..LOGICAL LQUERY, WNTUA, WNTUAS, WNTUN, WNTUO, WNTUS,$ WNTVA, WNTVAS, WNTVN, WNTVO, WNTVSINTEGER BDSPAC, BLK, CHUNK, I, IE, IERR, IR, ISCL,$ ITAU, ITAUP, ITAUQ, IU, IWORK, LDWRKR, LDWRKU,$ MAXWRK, MINMN, MINWRK, MNTHR, NCU, NCVT, NRU,$ NRVT, WRKBLDOUBLE PRECISION ANRM, BIGNUM, EPS, SMLNUM* ..* .. Local Arrays ..DOUBLE PRECISION DUM( 1 )* ..* .. External Subroutines ..EXTERNAL DBDSQR, DGEBRD, DGELQF, DGEMM, DGEQRF, DLACPY,$ DLASCL, DLASET, DORGBR, DORGLQ, DORGQR, DORMBR,$ XERBLA* ..* .. External Functions ..LOGICAL LSAMEINTEGER ILAENVDOUBLE PRECISION DLAMCH, DLANGEEXTERNAL LSAME, ILAENV, DLAMCH, DLANGE* ..* .. Intrinsic Functions ..INTRINSIC MAX, MIN, SQRT* ..* .. Executable Statements ..** Test the input arguments*INFO = 0MINMN = MIN( M, N )MNTHR = ILAENV( 6, 'DGESVD', JOBU // JOBVT, M, N, 0, 0 )WNTUA = LSAME( JOBU, 'A' )WNTUS = LSAME( JOBU, 'S' )WNTUAS = WNTUA .OR. WNTUSWNTUO = LSAME( JOBU, 'O' )WNTUN = LSAME( JOBU, 'N' )WNTVA = LSAME( JOBVT, 'A' )WNTVS = LSAME( JOBVT, 'S' )WNTVAS = WNTVA .OR. WNTVSWNTVO = LSAME( JOBVT, 'O' )WNTVN = LSAME( JOBVT, 'N' )MINWRK = 1LQUERY = ( LWORK.EQ.-1 )*IF( .NOT.( WNTUA .OR. WNTUS .OR. WNTUO .OR. WNTUN ) ) THENINFO = -1ELSE IF( .NOT.( WNTVA .OR. WNTVS .OR. WNTVO .OR. WNTVN ) .OR.$ ( WNTVO .AND. WNTUO ) ) THENINFO = -2ELSE IF( M.LT.0 ) THENINFO = -3ELSE IF( N.LT.0 ) THENINFO = -4ELSE IF( LDA.LT.MAX( 1, M ) ) THENINFO = -6ELSE IF( LDU.LT.1 .OR. ( WNTUAS .AND. LDU.LT.M ) ) THENINFO = -9ELSE IF( LDVT.LT.1 .OR. ( WNTVA .AND. LDVT.LT.N ) .OR.$ ( WNTVS .AND. LDVT.LT.MINMN ) ) THENINFO = -11END IF** Compute workspace* (Note: Comments in the code beginning "Workspace:" describe the* minimal amount of workspace needed at that point in the code,* as well as the preferred amount for good performance.* NB refers to the optimal block size for the immediately* following subroutine, as returned by ILAENV.)*IF( INFO.EQ.0 .AND. ( LWORK.GE.1 .OR. LQUERY ) .AND. M.GT.0 .AND.$ N.GT.0 ) THENIF( M.GE.N ) THEN** Compute space needed for DBDSQR*BDSPAC = 5*NIF( M.GE.MNTHR ) THENIF( WNTUN ) THEN** Path 1 (M much larger than N, JOBU='N')*MAXWRK = N + N*ILAENV( 1, 'DGEQRF', ' ', M, N, -1,$ -1 )MAXWRK = MAX( MAXWRK, 3*N+2*N*$ ILAENV( 1, 'DGEBRD', ' ', N, N, -1, -1 ) )IF( WNTVO .OR. WNTVAS )$ MAXWRK = MAX( MAXWRK, 3*N+( N-1 )*$ ILAENV( 1, 'DORGBR', 'P', N, N, N, -1 ) )MAXWRK = MAX( MAXWRK, BDSPAC )MINWRK = MAX( 4*N, BDSPAC )MAXWRK = MAX( MAXWRK, MINWRK )ELSE IF( WNTUO .AND. WNTVN ) THEN** Path 2 (M much larger than N, JOBU='O', JOBVT='N')*WRKBL = N + N*ILAENV( 1, 'DGEQRF', ' ', M, N, -1, -1 )WRKBL = MAX( WRKBL, N+N*ILAENV( 1, 'DORGQR', ' ', M,$ N, N, -1 ) )WRKBL = MAX( WRKBL, 3*N+2*N*$ ILAENV( 1, 'DGEBRD', ' ', N, N, -1, -1 ) )WRKBL = MAX( WRKBL, 3*N+N*$ ILAENV( 1, 'DORGBR', 'Q', N, N, N, -1 ) )WRKBL = MAX( WRKBL, BDSPAC )MAXWRK = MAX( N*N+WRKBL, N*N+M*N+N )MINWRK = MAX( 3*N+M, BDSPAC )MAXWRK = MAX( MAXWRK, MINWRK )ELSE IF( WNTUO .AND. WNTVAS ) THEN** Path 3 (M much larger than N, JOBU='O', JOBVT='S' or* 'A')*WRKBL = N + N*ILAENV( 1, 'DGEQRF', ' ', M, N, -1, -1 )WRKBL = MAX( WRKBL, N+N*ILAENV( 1, 'DORGQR', ' ', M,$ N, N, -1 ) )WRKBL = MAX( WRKBL, 3*N+2*N*$ ILAENV( 1, 'DGEBRD', ' ', N, N, -1, -1 ) )WRKBL = MAX( WRKBL, 3*N+N*$ ILAENV( 1, 'DORGBR', 'Q', N, N, N, -1 ) )WRKBL = MAX( WRKBL, 3*N+( N-1 )*$ ILAENV( 1, 'DORGBR', 'P', N, N, N, -1 ) )WRKBL = MAX( WRKBL, BDSPAC )MAXWRK = MAX( N*N+WRKBL, N*N+M*N+N )MINWRK = MAX( 3*N+M, BDSPAC )MAXWRK = MAX( MAXWRK, MINWRK )ELSE IF( WNTUS .AND. WNTVN ) THEN** Path 4 (M much larger than N, JOBU='S', JOBVT='N')*WRKBL = N + N*ILAENV( 1, 'DGEQRF', ' ', M, N, -1, -1 )WRKBL = MAX( WRKBL, N+N*ILAENV( 1, 'DORGQR', ' ', M,$ N, N, -1 ) )WRKBL = MAX( WRKBL, 3*N+2*N*$ ILAENV( 1, 'DGEBRD', ' ', N, N, -1, -1 ) )WRKBL = MAX( WRKBL, 3*N+N*$ ILAENV( 1, 'DORGBR', 'Q', N, N, N, -1 ) )WRKBL = MAX( WRKBL, BDSPAC )MAXWRK = N*N + WRKBLMINWRK = MAX( 3*N+M, BDSPAC )MAXWRK = MAX( MAXWRK, MINWRK )ELSE IF( WNTUS .AND. WNTVO ) THEN** Path 5 (M much larger than N, JOBU='S', JOBVT='O')*WRKBL = N + N*ILAENV( 1, 'DGEQRF', ' ', M, N, -1, -1 )WRKBL = MAX( WRKBL, N+N*ILAENV( 1, 'DORGQR', ' ', M,$ N, N, -1 ) )WRKBL = MAX( WRKBL, 3*N+2*N*$ ILAENV( 1, 'DGEBRD', ' ', N, N, -1, -1 ) )WRKBL = MAX( WRKBL, 3*N+N*$ ILAENV( 1, 'DORGBR', 'Q', N, N, N, -1 ) )WRKBL = MAX( WRKBL, 3*N+( N-1 )*$ ILAENV( 1, 'DORGBR', 'P', N, N, N, -1 ) )WRKBL = MAX( WRKBL, BDSPAC )MAXWRK = 2*N*N + WRKBLMINWRK = MAX( 3*N+M, BDSPAC )MAXWRK = MAX( MAXWRK, MINWRK )ELSE IF( WNTUS .AND. WNTVAS ) THEN** Path 6 (M much larger than N, JOBU='S', JOBVT='S' or* 'A')*WRKBL = N + N*ILAENV( 1, 'DGEQRF', ' ', M, N, -1, -1 )WRKBL = MAX( WRKBL, N+N*ILAENV( 1, 'DORGQR', ' ', M,$ N, N, -1 ) )WRKBL = MAX( WRKBL, 3*N+2*N*$ ILAENV( 1, 'DGEBRD', ' ', N, N, -1, -1 ) )WRKBL = MAX( WRKBL, 3*N+N*$ ILAENV( 1, 'DORGBR', 'Q', N, N, N, -1 ) )WRKBL = MAX( WRKBL, 3*N+( N-1 )*$ ILAENV( 1, 'DORGBR', 'P', N, N, N, -1 ) )WRKBL = MAX( WRKBL, BDSPAC )MAXWRK = N*N + WRKBLMINWRK = MAX( 3*N+M, BDSPAC )MAXWRK = MAX( MAXWRK, MINWRK )ELSE IF( WNTUA .AND. WNTVN ) THEN** Path 7 (M much larger than N, JOBU='A', JOBVT='N')*WRKBL = N + N*ILAENV( 1, 'DGEQRF', ' ', M, N, -1, -1 )WRKBL = MAX( WRKBL, N+M*ILAENV( 1, 'DORGQR', ' ', M,$ M, N, -1 ) )WRKBL = MAX( WRKBL, 3*N+2*N*$ ILAENV( 1, 'DGEBRD', ' ', N, N, -1, -1 ) )WRKBL = MAX( WRKBL, 3*N+N*$ ILAENV( 1, 'DORGBR', 'Q', N, N, N, -1 ) )WRKBL = MAX( WRKBL, BDSPAC )MAXWRK = N*N + WRKBLMINWRK = MAX( 3*N+M, BDSPAC )MAXWRK = MAX( MAXWRK, MINWRK )ELSE IF( WNTUA .AND. WNTVO ) THEN** Path 8 (M much larger than N, JOBU='A', JOBVT='O')*WRKBL = N + N*ILAENV( 1, 'DGEQRF', ' ', M, N, -1, -1 )WRKBL = MAX( WRKBL, N+M*ILAENV( 1, 'DORGQR', ' ', M,$ M, N, -1 ) )WRKBL = MAX( WRKBL, 3*N+2*N*$ ILAENV( 1, 'DGEBRD', ' ', N, N, -1, -1 ) )WRKBL = MAX( WRKBL, 3*N+N*$ ILAENV( 1, 'DORGBR', 'Q', N, N, N, -1 ) )WRKBL = MAX( WRKBL, 3*N+( N-1 )*$ ILAENV( 1, 'DORGBR', 'P', N, N, N, -1 ) )WRKBL = MAX( WRKBL, BDSPAC )MAXWRK = 2*N*N + WRKBLMINWRK = MAX( 3*N+M, BDSPAC )MAXWRK = MAX( MAXWRK, MINWRK )ELSE IF( WNTUA .AND. WNTVAS ) THEN** Path 9 (M much larger than N, JOBU='A', JOBVT='S' or* 'A')*WRKBL = N + N*ILAENV( 1, 'DGEQRF', ' ', M, N, -1, -1 )WRKBL = MAX( WRKBL, N+M*ILAENV( 1, 'DORGQR', ' ', M,$ M, N, -1 ) )WRKBL = MAX( WRKBL, 3*N+2*N*$ ILAENV( 1, 'DGEBRD', ' ', N, N, -1, -1 ) )WRKBL = MAX( WRKBL, 3*N+N*$ ILAENV( 1, 'DORGBR', 'Q', N, N, N, -1 ) )WRKBL = MAX( WRKBL, 3*N+( N-1 )*$ ILAENV( 1, 'DORGBR', 'P', N, N, N, -1 ) )WRKBL = MAX( WRKBL, BDSPAC )MAXWRK = N*N + WRKBLMINWRK = MAX( 3*N+M, BDSPAC )MAXWRK = MAX( MAXWRK, MINWRK )END IFELSE** Path 10 (M at least N, but not much larger)*MAXWRK = 3*N + ( M+N )*ILAENV( 1, 'DGEBRD', ' ', M, N,$ -1, -1 )IF( WNTUS .OR. WNTUO )$ MAXWRK = MAX( MAXWRK, 3*N+N*$ ILAENV( 1, 'DORGBR', 'Q', M, N, N, -1 ) )IF( WNTUA )$ MAXWRK = MAX( MAXWRK, 3*N+M*$ ILAENV( 1, 'DORGBR', 'Q', M, M, N, -1 ) )IF( .NOT.WNTVN )$ MAXWRK = MAX( MAXWRK, 3*N+( N-1 )*$ ILAENV( 1, 'DORGBR', 'P', N, N, N, -1 ) )MAXWRK = MAX( MAXWRK, BDSPAC )MINWRK = MAX( 3*N+M, BDSPAC )MAXWRK = MAX( MAXWRK, MINWRK )END IFELSE** Compute space needed for DBDSQR*BDSPAC = 5*MIF( N.GE.MNTHR ) THENIF( WNTVN ) THEN** Path 1t(N much larger than M, JOBVT='N')*MAXWRK = M + M*ILAENV( 1, 'DGELQF', ' ', M, N, -1,$ -1 )MAXWRK = MAX( MAXWRK, 3*M+2*M*$ ILAENV( 1, 'DGEBRD', ' ', M, M, -1, -1 ) )IF( WNTUO .OR. WNTUAS )$ MAXWRK = MAX( MAXWRK, 3*M+M*$ ILAENV( 1, 'DORGBR', 'Q', M, M, M, -1 ) )MAXWRK = MAX( MAXWRK, BDSPAC )MINWRK = MAX( 4*M, BDSPAC )MAXWRK = MAX( MAXWRK, MINWRK )ELSE IF( WNTVO .AND. WNTUN ) THEN** Path 2t(N much larger than M, JOBU='N', JOBVT='O')*WRKBL = M + M*ILAENV( 1, 'DGELQF', ' ', M, N, -1, -1 )WRKBL = MAX( WRKBL, M+M*ILAENV( 1, 'DORGLQ', ' ', M,$ N, M, -1 ) )WRKBL = MAX( WRKBL, 3*M+2*M*$ ILAENV( 1, 'DGEBRD', ' ', M, M, -1, -1 ) )WRKBL = MAX( WRKBL, 3*M+( M-1 )*$ ILAENV( 1, 'DORGBR', 'P', M, M, M, -1 ) )WRKBL = MAX( WRKBL, BDSPAC )MAXWRK = MAX( M*M+WRKBL, M*M+M*N+M )MINWRK = MAX( 3*M+N, BDSPAC )MAXWRK = MAX( MAXWRK, MINWRK )ELSE IF( WNTVO .AND. WNTUAS ) THEN** Path 3t(N much larger than M, JOBU='S' or 'A',* JOBVT='O')*WRKBL = M + M*ILAENV( 1, 'DGELQF', ' ', M, N, -1, -1 )WRKBL = MAX( WRKBL, M+M*ILAENV( 1, 'DORGLQ', ' ', M,$ N, M, -1 ) )WRKBL = MAX( WRKBL, 3*M+2*M*$ ILAENV( 1, 'DGEBRD', ' ', M, M, -1, -1 ) )WRKBL = MAX( WRKBL, 3*M+( M-1 )*$ ILAENV( 1, 'DORGBR', 'P', M, M, M, -1 ) )WRKBL = MAX( WRKBL, 3*M+M*$ ILAENV( 1, 'DORGBR', 'Q', M, M, M, -1 ) )WRKBL = MAX( WRKBL, BDSPAC )MAXWRK = MAX( M*M+WRKBL, M*M+M*N+M )MINWRK = MAX( 3*M+N, BDSPAC )MAXWRK = MAX( MAXWRK, MINWRK )ELSE IF( WNTVS .AND. WNTUN ) THEN** Path 4t(N much larger than M, JOBU='N', JOBVT='S')*WRKBL = M + M*ILAENV( 1, 'DGELQF', ' ', M, N, -1, -1 )WRKBL = MAX( WRKBL, M+M*ILAENV( 1, 'DORGLQ', ' ', M,$ N, M, -1 ) )WRKBL = MAX( WRKBL, 3*M+2*M*$ ILAENV( 1, 'DGEBRD', ' ', M, M, -1, -1 ) )WRKBL = MAX( WRKBL, 3*M+( M-1 )*$ ILAENV( 1, 'DORGBR', 'P', M, M, M, -1 ) )WRKBL = MAX( WRKBL, BDSPAC )MAXWRK = M*M + WRKBLMINWRK = MAX( 3*M+N, BDSPAC )MAXWRK = MAX( MAXWRK, MINWRK )ELSE IF( WNTVS .AND. WNTUO ) THEN** Path 5t(N much larger than M, JOBU='O', JOBVT='S')*WRKBL = M + M*ILAENV( 1, 'DGELQF', ' ', M, N, -1, -1 )WRKBL = MAX( WRKBL, M+M*ILAENV( 1, 'DORGLQ', ' ', M,$ N, M, -1 ) )WRKBL = MAX( WRKBL, 3*M+2*M*$ ILAENV( 1, 'DGEBRD', ' ', M, M, -1, -1 ) )WRKBL = MAX( WRKBL, 3*M+( M-1 )*$ ILAENV( 1, 'DORGBR', 'P', M, M, M, -1 ) )WRKBL = MAX( WRKBL, 3*M+M*$ ILAENV( 1, 'DORGBR', 'Q', M, M, M, -1 ) )WRKBL = MAX( WRKBL, BDSPAC )MAXWRK = 2*M*M + WRKBLMINWRK = MAX( 3*M+N, BDSPAC )MAXWRK = MAX( MAXWRK, MINWRK )ELSE IF( WNTVS .AND. WNTUAS ) THEN** Path 6t(N much larger than M, JOBU='S' or 'A',* JOBVT='S')*WRKBL = M + M*ILAENV( 1, 'DGELQF', ' ', M, N, -1, -1 )WRKBL = MAX( WRKBL, M+M*ILAENV( 1, 'DORGLQ', ' ', M,$ N, M, -1 ) )WRKBL = MAX( WRKBL, 3*M+2*M*$ ILAENV( 1, 'DGEBRD', ' ', M, M, -1, -1 ) )WRKBL = MAX( WRKBL, 3*M+( M-1 )*$ ILAENV( 1, 'DORGBR', 'P', M, M, M, -1 ) )WRKBL = MAX( WRKBL, 3*M+M*$ ILAENV( 1, 'DORGBR', 'Q', M, M, M, -1 ) )WRKBL = MAX( WRKBL, BDSPAC )MAXWRK = M*M + WRKBLMINWRK = MAX( 3*M+N, BDSPAC )MAXWRK = MAX( MAXWRK, MINWRK )ELSE IF( WNTVA .AND. WNTUN ) THEN** Path 7t(N much larger than M, JOBU='N', JOBVT='A')*WRKBL = M + M*ILAENV( 1, 'DGELQF', ' ', M, N, -1, -1 )WRKBL = MAX( WRKBL, M+N*ILAENV( 1, 'DORGLQ', ' ', N,$ N, M, -1 ) )WRKBL = MAX( WRKBL, 3*M+2*M*$ ILAENV( 1, 'DGEBRD', ' ', M, M, -1, -1 ) )WRKBL = MAX( WRKBL, 3*M+( M-1 )*$ ILAENV( 1, 'DORGBR', 'P', M, M, M, -1 ) )WRKBL = MAX( WRKBL, BDSPAC )MAXWRK = M*M + WRKBLMINWRK = MAX( 3*M+N, BDSPAC )MAXWRK = MAX( MAXWRK, MINWRK )ELSE IF( WNTVA .AND. WNTUO ) THEN** Path 8t(N much larger than M, JOBU='O', JOBVT='A')*WRKBL = M + M*ILAENV( 1, 'DGELQF', ' ', M, N, -1, -1 )WRKBL = MAX( WRKBL, M+N*ILAENV( 1, 'DORGLQ', ' ', N,$ N, M, -1 ) )WRKBL = MAX( WRKBL, 3*M+2*M*$ ILAENV( 1, 'DGEBRD', ' ', M, M, -1, -1 ) )WRKBL = MAX( WRKBL, 3*M+( M-1 )*$ ILAENV( 1, 'DORGBR', 'P', M, M, M, -1 ) )WRKBL = MAX( WRKBL, 3*M+M*$ ILAENV( 1, 'DORGBR', 'Q', M, M, M, -1 ) )WRKBL = MAX( WRKBL, BDSPAC )MAXWRK = 2*M*M + WRKBLMINWRK = MAX( 3*M+N, BDSPAC )MAXWRK = MAX( MAXWRK, MINWRK )ELSE IF( WNTVA .AND. WNTUAS ) THEN** Path 9t(N much larger than M, JOBU='S' or 'A',* JOBVT='A')*WRKBL = M + M*ILAENV( 1, 'DGELQF', ' ', M, N, -1, -1 )WRKBL = MAX( WRKBL, M+N*ILAENV( 1, 'DORGLQ', ' ', N,$ N, M, -1 ) )WRKBL = MAX( WRKBL, 3*M+2*M*$ ILAENV( 1, 'DGEBRD', ' ', M, M, -1, -1 ) )WRKBL = MAX( WRKBL, 3*M+( M-1 )*$ ILAENV( 1, 'DORGBR', 'P', M, M, M, -1 ) )WRKBL = MAX( WRKBL, 3*M+M*$ ILAENV( 1, 'DORGBR', 'Q', M, M, M, -1 ) )WRKBL = MAX( WRKBL, BDSPAC )MAXWRK = M*M + WRKBLMINWRK = MAX( 3*M+N, BDSPAC )MAXWRK = MAX( MAXWRK, MINWRK )END IFELSE** Path 10t(N greater than M, but not much larger)*MAXWRK = 3*M + ( M+N )*ILAENV( 1, 'DGEBRD', ' ', M, N,$ -1, -1 )IF( WNTVS .OR. WNTVO )$ MAXWRK = MAX( MAXWRK, 3*M+M*$ ILAENV( 1, 'DORGBR', 'P', M, N, M, -1 ) )IF( WNTVA )$ MAXWRK = MAX( MAXWRK, 3*M+N*$ ILAENV( 1, 'DORGBR', 'P', N, N, M, -1 ) )IF( .NOT.WNTUN )$ MAXWRK = MAX( MAXWRK, 3*M+( M-1 )*$ ILAENV( 1, 'DORGBR', 'Q', M, M, M, -1 ) )MAXWRK = MAX( MAXWRK, BDSPAC )MINWRK = MAX( 3*M+N, BDSPAC )MAXWRK = MAX( MAXWRK, MINWRK )END IFEND IFWORK( 1 ) = MAXWRKEND IF*IF( LWORK.LT.MINWRK .AND. .NOT.LQUERY ) THENINFO = -13END IFIF( INFO.NE.0 ) THENCALL XERBLA( 'DGESVD', -INFO )RETURNELSE IF( LQUERY ) THENRETURNEND IF** Quick return if possible*IF( M.EQ.0 .OR. N.EQ.0 ) THENIF( LWORK.GE.1 )$ WORK( 1 ) = ONERETURNEND IF** Get machine constants*EPS = DLAMCH( 'P' )SMLNUM = SQRT( DLAMCH( 'S' ) ) / EPSBIGNUM = ONE / SMLNUM** Scale A if max element outside range [SMLNUM,BIGNUM]*ANRM = DLANGE( 'M', M, N, A, LDA, DUM )ISCL = 0IF( ANRM.GT.ZERO .AND. ANRM.LT.SMLNUM ) THENISCL = 1CALL DLASCL( 'G', 0, 0, ANRM, SMLNUM, M, N, A, LDA, IERR )ELSE IF( ANRM.GT.BIGNUM ) THENISCL = 1CALL DLASCL( 'G', 0, 0, ANRM, BIGNUM, M, N, A, LDA, IERR )END IF*IF( M.GE.N ) THEN** A has at least as many rows as columns. If A has sufficiently* more rows than columns, first reduce using the QR* decomposition (if sufficient workspace available)*IF( M.GE.MNTHR ) THEN*IF( WNTUN ) THEN** Path 1 (M much larger than N, JOBU='N')* No left singular vectors to be computed*ITAU = 1IWORK = ITAU + N** Compute A=Q*R* (Workspace: need 2*N, prefer N+N*NB)*CALL DGEQRF( M, N, A, LDA, WORK( ITAU ), WORK( IWORK ),$ LWORK-IWORK+1, IERR )** Zero out below R*CALL DLASET( 'L', N-1, N-1, ZERO, ZERO, A( 2, 1 ), LDA )IE = 1ITAUQ = IE + NITAUP = ITAUQ + NIWORK = ITAUP + N** Bidiagonalize R in A* (Workspace: need 4*N, prefer 3*N+2*N*NB)*CALL DGEBRD( N, N, A, LDA, S, WORK( IE ), WORK( ITAUQ ),$ WORK( ITAUP ), WORK( IWORK ), LWORK-IWORK+1,$ IERR )NCVT = 0IF( WNTVO .OR. WNTVAS ) THEN** If right singular vectors desired, generate P'.* (Workspace: need 4*N-1, prefer 3*N+(N-1)*NB)*CALL DORGBR( 'P', N, N, N, A, LDA, WORK( ITAUP ),$ WORK( IWORK ), LWORK-IWORK+1, IERR )NCVT = NEND IFIWORK = IE + N** Perform bidiagonal QR iteration, computing right* singular vectors of A in A if desired* (Workspace: need BDSPAC)*CALL DBDSQR( 'U', N, NCVT, 0, 0, S, WORK( IE ), A, LDA,$ DUM, 1, DUM, 1, WORK( IWORK ), INFO )** If right singular vectors desired in VT, copy them there*IF( WNTVAS )$ CALL DLACPY( 'F', N, N, A, LDA, VT, LDVT )*ELSE IF( WNTUO .AND. WNTVN ) THEN** Path 2 (M much larger than N, JOBU='O', JOBVT='N')* N left singular vectors to be overwritten on A and* no right singular vectors to be computed*IF( LWORK.GE.N*N+MAX( 4*N, BDSPAC ) ) THEN** Sufficient workspace for a fast algorithm*IR = 1IF( LWORK.GE.MAX( WRKBL, LDA*N+N )+LDA*N ) THEN** WORK(IU) is LDA by N, WORK(IR) is LDA by N*LDWRKU = LDALDWRKR = LDAELSE IF( LWORK.GE.MAX( WRKBL, LDA*N+N )+N*N ) THEN** WORK(IU) is LDA by N, WORK(IR) is N by N*LDWRKU = LDALDWRKR = NELSE** WORK(IU) is LDWRKU by N, WORK(IR) is N by N*LDWRKU = ( LWORK-N*N-N ) / NLDWRKR = NEND IFITAU = IR + LDWRKR*NIWORK = ITAU + N** Compute A=Q*R* (Workspace: need N*N+2*N, prefer N*N+N+N*NB)*CALL DGEQRF( M, N, A, LDA, WORK( ITAU ),$ WORK( IWORK ), LWORK-IWORK+1, IERR )** Copy R to WORK(IR) and zero out below it*CALL DLACPY( 'U', N, N, A, LDA, WORK( IR ), LDWRKR )CALL DLASET( 'L', N-1, N-1, ZERO, ZERO, WORK( IR+1 ),$ LDWRKR )** Generate Q in A* (Workspace: need N*N+2*N, prefer N*N+N+N*NB)*CALL DORGQR( M, N, N, A, LDA, WORK( ITAU ),$ WORK( IWORK ), LWORK-IWORK+1, IERR )IE = ITAUITAUQ = IE + NITAUP = ITAUQ + NIWORK = ITAUP + N** Bidiagonalize R in WORK(IR)* (Workspace: need N*N+4*N, prefer N*N+3*N+2*N*NB)*CALL DGEBRD( N, N, WORK( IR ), LDWRKR, S, WORK( IE ),$ WORK( ITAUQ ), WORK( ITAUP ),$ WORK( IWORK ), LWORK-IWORK+1, IERR )** Generate left vectors bidiagonalizing R* (Workspace: need N*N+4*N, prefer N*N+3*N+N*NB)*CALL DORGBR( 'Q', N, N, N, WORK( IR ), LDWRKR,$ WORK( ITAUQ ), WORK( IWORK ),$ LWORK-IWORK+1, IERR )IWORK = IE + N** Perform bidiagonal QR iteration, computing left* singular vectors of R in WORK(IR)* (Workspace: need N*N+BDSPAC)*CALL DBDSQR( 'U', N, 0, N, 0, S, WORK( IE ), DUM, 1,$ WORK( IR ), LDWRKR, DUM, 1,$ WORK( IWORK ), INFO )IU = IE + N** Multiply Q in A by left singular vectors of R in* WORK(IR), storing result in WORK(IU) and copying to A* (Workspace: need N*N+2*N, prefer N*N+M*N+N)*DO 10 I = 1, M, LDWRKUCHUNK = MIN( M-I+1, LDWRKU )CALL DGEMM( 'N', 'N', CHUNK, N, N, ONE, A( I, 1 ),$ LDA, WORK( IR ), LDWRKR, ZERO,$ WORK( IU ), LDWRKU )CALL DLACPY( 'F', CHUNK, N, WORK( IU ), LDWRKU,$ A( I, 1 ), LDA )10 CONTINUE*ELSE** Insufficient workspace for a fast algorithm*IE = 1ITAUQ = IE + NITAUP = ITAUQ + NIWORK = ITAUP + N** Bidiagonalize A* (Workspace: need 3*N+M, prefer 3*N+(M+N)*NB)*CALL DGEBRD( M, N, A, LDA, S, WORK( IE ),$ WORK( ITAUQ ), WORK( ITAUP ),$ WORK( IWORK ), LWORK-IWORK+1, IERR )** Generate left vectors bidiagonalizing A* (Workspace: need 4*N, prefer 3*N+N*NB)*CALL DORGBR( 'Q', M, N, N, A, LDA, WORK( ITAUQ ),$ WORK( IWORK ), LWORK-IWORK+1, IERR )IWORK = IE + N** Perform bidiagonal QR iteration, computing left* singular vectors of A in A* (Workspace: need BDSPAC)*CALL DBDSQR( 'U', N, 0, M, 0, S, WORK( IE ), DUM, 1,$ A, LDA, DUM, 1, WORK( IWORK ), INFO )*END IF*ELSE IF( WNTUO .AND. WNTVAS ) THEN** Path 3 (M much larger than N, JOBU='O', JOBVT='S' or 'A')* N left singular vectors to be overwritten on A and* N right singular vectors to be computed in VT*IF( LWORK.GE.N*N+MAX( 4*N, BDSPAC ) ) THEN** Sufficient workspace for a fast algorithm*IR = 1IF( LWORK.GE.MAX( WRKBL, LDA*N+N )+LDA*N ) THEN** WORK(IU) is LDA by N and WORK(IR) is LDA by N*LDWRKU = LDALDWRKR = LDAELSE IF( LWORK.GE.MAX( WRKBL, LDA*N+N )+N*N ) THEN** WORK(IU) is LDA by N and WORK(IR) is N by N*LDWRKU = LDALDWRKR = NELSE** WORK(IU) is LDWRKU by N and WORK(IR) is N by N*LDWRKU = ( LWORK-N*N-N ) / NLDWRKR = NEND IFITAU = IR + LDWRKR*NIWORK = ITAU + N** Compute A=Q*R* (Workspace: need N*N+2*N, prefer N*N+N+N*NB)*CALL DGEQRF( M, N, A, LDA, WORK( ITAU ),$ WORK( IWORK ), LWORK-IWORK+1, IERR )** Copy R to VT, zeroing out below it*CALL DLACPY( 'U', N, N, A, LDA, VT, LDVT )CALL DLASET( 'L', N-1, N-1, ZERO, ZERO, VT( 2, 1 ),$ LDVT )** Generate Q in A* (Workspace: need N*N+2*N, prefer N*N+N+N*NB)*CALL DORGQR( M, N, N, A, LDA, WORK( ITAU ),$ WORK( IWORK ), LWORK-IWORK+1, IERR )IE = ITAUITAUQ = IE + NITAUP = ITAUQ + NIWORK = ITAUP + N** Bidiagonalize R in VT, copying result to WORK(IR)* (Workspace: need N*N+4*N, prefer N*N+3*N+2*N*NB)*CALL DGEBRD( N, N, VT, LDVT, S, WORK( IE ),$ WORK( ITAUQ ), WORK( ITAUP ),$ WORK( IWORK ), LWORK-IWORK+1, IERR )CALL DLACPY( 'L', N, N, VT, LDVT, WORK( IR ), LDWRKR )** Generate left vectors bidiagonalizing R in WORK(IR)* (Workspace: need N*N+4*N, prefer N*N+3*N+N*NB)*CALL DORGBR( 'Q', N, N, N, WORK( IR ), LDWRKR,$ WORK( ITAUQ ), WORK( IWORK ),$ LWORK-IWORK+1, IERR )** Generate right vectors bidiagonalizing R in VT* (Workspace: need N*N+4*N-1, prefer N*N+3*N+(N-1)*NB)*CALL DORGBR( 'P', N, N, N, VT, LDVT, WORK( ITAUP ),$ WORK( IWORK ), LWORK-IWORK+1, IERR )IWORK = IE + N** Perform bidiagonal QR iteration, computing left* singular vectors of R in WORK(IR) and computing right* singular vectors of R in VT* (Workspace: need N*N+BDSPAC)*CALL DBDSQR( 'U', N, N, N, 0, S, WORK( IE ), VT, LDVT,$ WORK( IR ), LDWRKR, DUM, 1,$ WORK( IWORK ), INFO )IU = IE + N** Multiply Q in A by left singular vectors of R in* WORK(IR), storing result in WORK(IU) and copying to A* (Workspace: need N*N+2*N, prefer N*N+M*N+N)*DO 20 I = 1, M, LDWRKUCHUNK = MIN( M-I+1, LDWRKU )CALL DGEMM( 'N', 'N', CHUNK, N, N, ONE, A( I, 1 ),$ LDA, WORK( IR ), LDWRKR, ZERO,$ WORK( IU ), LDWRKU )CALL DLACPY( 'F', CHUNK, N, WORK( IU ), LDWRKU,$ A( I, 1 ), LDA )20 CONTINUE*ELSE** Insufficient workspace for a fast algorithm*ITAU = 1IWORK = ITAU + N** Compute A=Q*R* (Workspace: need 2*N, prefer N+N*NB)*CALL DGEQRF( M, N, A, LDA, WORK( ITAU ),$ WORK( IWORK ), LWORK-IWORK+1, IERR )** Copy R to VT, zeroing out below it*CALL DLACPY( 'U', N, N, A, LDA, VT, LDVT )CALL DLASET( 'L', N-1, N-1, ZERO, ZERO, VT( 2, 1 ),$ LDVT )** Generate Q in A* (Workspace: need 2*N, prefer N+N*NB)*CALL DORGQR( M, N, N, A, LDA, WORK( ITAU ),$ WORK( IWORK ), LWORK-IWORK+1, IERR )IE = ITAUITAUQ = IE + NITAUP = ITAUQ + NIWORK = ITAUP + N** Bidiagonalize R in VT* (Workspace: need 4*N, prefer 3*N+2*N*NB)*CALL DGEBRD( N, N, VT, LDVT, S, WORK( IE ),$ WORK( ITAUQ ), WORK( ITAUP ),$ WORK( IWORK ), LWORK-IWORK+1, IERR )** Multiply Q in A by left vectors bidiagonalizing R* (Workspace: need 3*N+M, prefer 3*N+M*NB)*CALL DORMBR( 'Q', 'R', 'N', M, N, N, VT, LDVT,$ WORK( ITAUQ ), A, LDA, WORK( IWORK ),$ LWORK-IWORK+1, IERR )** Generate right vectors bidiagonalizing R in VT* (Workspace: need 4*N-1, prefer 3*N+(N-1)*NB)*CALL DORGBR( 'P', N, N, N, VT, LDVT, WORK( ITAUP ),$ WORK( IWORK ), LWORK-IWORK+1, IERR )IWORK = IE + N** Perform bidiagonal QR iteration, computing left* singular vectors of A in A and computing right* singular vectors of A in VT* (Workspace: need BDSPAC)*CALL DBDSQR( 'U', N, N, M, 0, S, WORK( IE ), VT, LDVT,$ A, LDA, DUM, 1, WORK( IWORK ), INFO )*END IF*ELSE IF( WNTUS ) THEN*IF( WNTVN ) THEN** Path 4 (M much larger than N, JOBU='S', JOBVT='N')* N left singular vectors to be computed in U and* no right singular vectors to be computed*IF( LWORK.GE.N*N+MAX( 4*N, BDSPAC ) ) THEN** Sufficient workspace for a fast algorithm*IR = 1IF( LWORK.GE.WRKBL+LDA*N ) THEN** WORK(IR) is LDA by N*LDWRKR = LDAELSE** WORK(IR) is N by N*LDWRKR = NEND IFITAU = IR + LDWRKR*NIWORK = ITAU + N** Compute A=Q*R* (Workspace: need N*N+2*N, prefer N*N+N+N*NB)*CALL DGEQRF( M, N, A, LDA, WORK( ITAU ),$ WORK( IWORK ), LWORK-IWORK+1, IERR )** Copy R to WORK(IR), zeroing out below it*CALL DLACPY( 'U', N, N, A, LDA, WORK( IR ),$ LDWRKR )CALL DLASET( 'L', N-1, N-1, ZERO, ZERO,$ WORK( IR+1 ), LDWRKR )** Generate Q in A* (Workspace: need N*N+2*N, prefer N*N+N+N*NB)*CALL DORGQR( M, N, N, A, LDA, WORK( ITAU ),$ WORK( IWORK ), LWORK-IWORK+1, IERR )IE = ITAUITAUQ = IE + NITAUP = ITAUQ + NIWORK = ITAUP + N** Bidiagonalize R in WORK(IR)* (Workspace: need N*N+4*N, prefer N*N+3*N+2*N*NB)*CALL DGEBRD( N, N, WORK( IR ), LDWRKR, S,$ WORK( IE ), WORK( ITAUQ ),$ WORK( ITAUP ), WORK( IWORK ),$ LWORK-IWORK+1, IERR )** Generate left vectors bidiagonalizing R in WORK(IR)* (Workspace: need N*N+4*N, prefer N*N+3*N+N*NB)*CALL DORGBR( 'Q', N, N, N, WORK( IR ), LDWRKR,$ WORK( ITAUQ ), WORK( IWORK ),$ LWORK-IWORK+1, IERR )IWORK = IE + N** Perform bidiagonal QR iteration, computing left* singular vectors of R in WORK(IR)* (Workspace: need N*N+BDSPAC)*CALL DBDSQR( 'U', N, 0, N, 0, S, WORK( IE ), DUM,$ 1, WORK( IR ), LDWRKR, DUM, 1,$ WORK( IWORK ), INFO )** Multiply Q in A by left singular vectors of R in* WORK(IR), storing result in U* (Workspace: need N*N)*CALL DGEMM( 'N', 'N', M, N, N, ONE, A, LDA,$ WORK( IR ), LDWRKR, ZERO, U, LDU )*ELSE** Insufficient workspace for a fast algorithm*ITAU = 1IWORK = ITAU + N** Compute A=Q*R, copying result to U* (Workspace: need 2*N, prefer N+N*NB)*CALL DGEQRF( M, N, A, LDA, WORK( ITAU ),$ WORK( IWORK ), LWORK-IWORK+1, IERR )CALL DLACPY( 'L', M, N, A, LDA, U, LDU )** Generate Q in U* (Workspace: need 2*N, prefer N+N*NB)*CALL DORGQR( M, N, N, U, LDU, WORK( ITAU ),$ WORK( IWORK ), LWORK-IWORK+1, IERR )IE = ITAUITAUQ = IE + NITAUP = ITAUQ + NIWORK = ITAUP + N** Zero out below R in A*CALL DLASET( 'L', N-1, N-1, ZERO, ZERO, A( 2, 1 ),$ LDA )** Bidiagonalize R in A* (Workspace: need 4*N, prefer 3*N+2*N*NB)*CALL DGEBRD( N, N, A, LDA, S, WORK( IE ),$ WORK( ITAUQ ), WORK( ITAUP ),$ WORK( IWORK ), LWORK-IWORK+1, IERR )** Multiply Q in U by left vectors bidiagonalizing R* (Workspace: need 3*N+M, prefer 3*N+M*NB)*CALL DORMBR( 'Q', 'R', 'N', M, N, N, A, LDA,$ WORK( ITAUQ ), U, LDU, WORK( IWORK ),$ LWORK-IWORK+1, IERR )IWORK = IE + N** Perform bidiagonal QR iteration, computing left* singular vectors of A in U* (Workspace: need BDSPAC)*CALL DBDSQR( 'U', N, 0, M, 0, S, WORK( IE ), DUM,$ 1, U, LDU, DUM, 1, WORK( IWORK ),$ INFO )*END IF*ELSE IF( WNTVO ) THEN** Path 5 (M much larger than N, JOBU='S', JOBVT='O')* N left singular vectors to be computed in U and* N right singular vectors to be overwritten on A*IF( LWORK.GE.2*N*N+MAX( 4*N, BDSPAC ) ) THEN** Sufficient workspace for a fast algorithm*IU = 1IF( LWORK.GE.WRKBL+2*LDA*N ) THEN** WORK(IU) is LDA by N and WORK(IR) is LDA by N*LDWRKU = LDAIR = IU + LDWRKU*NLDWRKR = LDAELSE IF( LWORK.GE.WRKBL+( LDA+N )*N ) THEN** WORK(IU) is LDA by N and WORK(IR) is N by N*LDWRKU = LDAIR = IU + LDWRKU*NLDWRKR = NELSE** WORK(IU) is N by N and WORK(IR) is N by N*LDWRKU = NIR = IU + LDWRKU*NLDWRKR = NEND IFITAU = IR + LDWRKR*NIWORK = ITAU + N** Compute A=Q*R* (Workspace: need 2*N*N+2*N, prefer 2*N*N+N+N*NB)*CALL DGEQRF( M, N, A, LDA, WORK( ITAU ),$ WORK( IWORK ), LWORK-IWORK+1, IERR )** Copy R to WORK(IU), zeroing out below it*CALL DLACPY( 'U', N, N, A, LDA, WORK( IU ),$ LDWRKU )CALL DLASET( 'L', N-1, N-1, ZERO, ZERO,$ WORK( IU+1 ), LDWRKU )** Generate Q in A* (Workspace: need 2*N*N+2*N, prefer 2*N*N+N+N*NB)*CALL DORGQR( M, N, N, A, LDA, WORK( ITAU ),$ WORK( IWORK ), LWORK-IWORK+1, IERR )IE = ITAUITAUQ = IE + NITAUP = ITAUQ + NIWORK = ITAUP + N** Bidiagonalize R in WORK(IU), copying result to* WORK(IR)* (Workspace: need 2*N*N+4*N,* prefer 2*N*N+3*N+2*N*NB)*CALL DGEBRD( N, N, WORK( IU ), LDWRKU, S,$ WORK( IE ), WORK( ITAUQ ),$ WORK( ITAUP ), WORK( IWORK ),$ LWORK-IWORK+1, IERR )CALL DLACPY( 'U', N, N, WORK( IU ), LDWRKU,$ WORK( IR ), LDWRKR )** Generate left bidiagonalizing vectors in WORK(IU)* (Workspace: need 2*N*N+4*N, prefer 2*N*N+3*N+N*NB)*CALL DORGBR( 'Q', N, N, N, WORK( IU ), LDWRKU,$ WORK( ITAUQ ), WORK( IWORK ),$ LWORK-IWORK+1, IERR )** Generate right bidiagonalizing vectors in WORK(IR)* (Workspace: need 2*N*N+4*N-1,* prefer 2*N*N+3*N+(N-1)*NB)*CALL DORGBR( 'P', N, N, N, WORK( IR ), LDWRKR,$ WORK( ITAUP ), WORK( IWORK ),$ LWORK-IWORK+1, IERR )IWORK = IE + N** Perform bidiagonal QR iteration, computing left* singular vectors of R in WORK(IU) and computing* right singular vectors of R in WORK(IR)* (Workspace: need 2*N*N+BDSPAC)*CALL DBDSQR( 'U', N, N, N, 0, S, WORK( IE ),$ WORK( IR ), LDWRKR, WORK( IU ),$ LDWRKU, DUM, 1, WORK( IWORK ), INFO )** Multiply Q in A by left singular vectors of R in* WORK(IU), storing result in U* (Workspace: need N*N)*CALL DGEMM( 'N', 'N', M, N, N, ONE, A, LDA,$ WORK( IU ), LDWRKU, ZERO, U, LDU )** Copy right singular vectors of R to A* (Workspace: need N*N)*CALL DLACPY( 'F', N, N, WORK( IR ), LDWRKR, A,$ LDA )*ELSE** Insufficient workspace for a fast algorithm*ITAU = 1IWORK = ITAU + N** Compute A=Q*R, copying result to U* (Workspace: need 2*N, prefer N+N*NB)*CALL DGEQRF( M, N, A, LDA, WORK( ITAU ),$ WORK( IWORK ), LWORK-IWORK+1, IERR )CALL DLACPY( 'L', M, N, A, LDA, U, LDU )** Generate Q in U* (Workspace: need 2*N, prefer N+N*NB)*CALL DORGQR( M, N, N, U, LDU, WORK( ITAU ),$ WORK( IWORK ), LWORK-IWORK+1, IERR )IE = ITAUITAUQ = IE + NITAUP = ITAUQ + NIWORK = ITAUP + N** Zero out below R in A*CALL DLASET( 'L', N-1, N-1, ZERO, ZERO, A( 2, 1 ),$ LDA )** Bidiagonalize R in A* (Workspace: need 4*N, prefer 3*N+2*N*NB)*CALL DGEBRD( N, N, A, LDA, S, WORK( IE ),$ WORK( ITAUQ ), WORK( ITAUP ),$ WORK( IWORK ), LWORK-IWORK+1, IERR )** Multiply Q in U by left vectors bidiagonalizing R* (Workspace: need 3*N+M, prefer 3*N+M*NB)*CALL DORMBR( 'Q', 'R', 'N', M, N, N, A, LDA,$ WORK( ITAUQ ), U, LDU, WORK( IWORK ),$ LWORK-IWORK+1, IERR )** Generate right vectors bidiagonalizing R in A* (Workspace: need 4*N-1, prefer 3*N+(N-1)*NB)*CALL DORGBR( 'P', N, N, N, A, LDA, WORK( ITAUP ),$ WORK( IWORK ), LWORK-IWORK+1, IERR )IWORK = IE + N** Perform bidiagonal QR iteration, computing left* singular vectors of A in U and computing right* singular vectors of A in A* (Workspace: need BDSPAC)*CALL DBDSQR( 'U', N, N, M, 0, S, WORK( IE ), A,$ LDA, U, LDU, DUM, 1, WORK( IWORK ),$ INFO )*END IF*ELSE IF( WNTVAS ) THEN** Path 6 (M much larger than N, JOBU='S', JOBVT='S'* or 'A')* N left singular vectors to be computed in U and* N right singular vectors to be computed in VT*IF( LWORK.GE.N*N+MAX( 4*N, BDSPAC ) ) THEN** Sufficient workspace for a fast algorithm*IU = 1IF( LWORK.GE.WRKBL+LDA*N ) THEN** WORK(IU) is LDA by N*LDWRKU = LDAELSE** WORK(IU) is N by N*LDWRKU = NEND IFITAU = IU + LDWRKU*NIWORK = ITAU + N** Compute A=Q*R* (Workspace: need N*N+2*N, prefer N*N+N+N*NB)*CALL DGEQRF( M, N, A, LDA, WORK( ITAU ),$ WORK( IWORK ), LWORK-IWORK+1, IERR )** Copy R to WORK(IU), zeroing out below it*CALL DLACPY( 'U', N, N, A, LDA, WORK( IU ),$ LDWRKU )CALL DLASET( 'L', N-1, N-1, ZERO, ZERO,$ WORK( IU+1 ), LDWRKU )** Generate Q in A* (Workspace: need N*N+2*N, prefer N*N+N+N*NB)*CALL DORGQR( M, N, N, A, LDA, WORK( ITAU ),$ WORK( IWORK ), LWORK-IWORK+1, IERR )IE = ITAUITAUQ = IE + NITAUP = ITAUQ + NIWORK = ITAUP + N** Bidiagonalize R in WORK(IU), copying result to VT* (Workspace: need N*N+4*N, prefer N*N+3*N+2*N*NB)*CALL DGEBRD( N, N, WORK( IU ), LDWRKU, S,$ WORK( IE ), WORK( ITAUQ ),$ WORK( ITAUP ), WORK( IWORK ),$ LWORK-IWORK+1, IERR )CALL DLACPY( 'U', N, N, WORK( IU ), LDWRKU, VT,$ LDVT )** Generate left bidiagonalizing vectors in WORK(IU)* (Workspace: need N*N+4*N, prefer N*N+3*N+N*NB)*CALL DORGBR( 'Q', N, N, N, WORK( IU ), LDWRKU,$ WORK( ITAUQ ), WORK( IWORK ),$ LWORK-IWORK+1, IERR )** Generate right bidiagonalizing vectors in VT* (Workspace: need N*N+4*N-1,* prefer N*N+3*N+(N-1)*NB)*CALL DORGBR( 'P', N, N, N, VT, LDVT, WORK( ITAUP ),$ WORK( IWORK ), LWORK-IWORK+1, IERR )IWORK = IE + N** Perform bidiagonal QR iteration, computing left* singular vectors of R in WORK(IU) and computing* right singular vectors of R in VT* (Workspace: need N*N+BDSPAC)*CALL DBDSQR( 'U', N, N, N, 0, S, WORK( IE ), VT,$ LDVT, WORK( IU ), LDWRKU, DUM, 1,$ WORK( IWORK ), INFO )** Multiply Q in A by left singular vectors of R in* WORK(IU), storing result in U* (Workspace: need N*N)*CALL DGEMM( 'N', 'N', M, N, N, ONE, A, LDA,$ WORK( IU ), LDWRKU, ZERO, U, LDU )*ELSE** Insufficient workspace for a fast algorithm*ITAU = 1IWORK = ITAU + N** Compute A=Q*R, copying result to U* (Workspace: need 2*N, prefer N+N*NB)*CALL DGEQRF( M, N, A, LDA, WORK( ITAU ),$ WORK( IWORK ), LWORK-IWORK+1, IERR )CALL DLACPY( 'L', M, N, A, LDA, U, LDU )** Generate Q in U* (Workspace: need 2*N, prefer N+N*NB)*CALL DORGQR( M, N, N, U, LDU, WORK( ITAU ),$ WORK( IWORK ), LWORK-IWORK+1, IERR )** Copy R to VT, zeroing out below it*CALL DLACPY( 'U', N, N, A, LDA, VT, LDVT )CALL DLASET( 'L', N-1, N-1, ZERO, ZERO, VT( 2, 1 ),$ LDVT )IE = ITAUITAUQ = IE + NITAUP = ITAUQ + NIWORK = ITAUP + N** Bidiagonalize R in VT* (Workspace: need 4*N, prefer 3*N+2*N*NB)*CALL DGEBRD( N, N, VT, LDVT, S, WORK( IE ),$ WORK( ITAUQ ), WORK( ITAUP ),$ WORK( IWORK ), LWORK-IWORK+1, IERR )** Multiply Q in U by left bidiagonalizing vectors* in VT* (Workspace: need 3*N+M, prefer 3*N+M*NB)*CALL DORMBR( 'Q', 'R', 'N', M, N, N, VT, LDVT,$ WORK( ITAUQ ), U, LDU, WORK( IWORK ),$ LWORK-IWORK+1, IERR )** Generate right bidiagonalizing vectors in VT* (Workspace: need 4*N-1, prefer 3*N+(N-1)*NB)*CALL DORGBR( 'P', N, N, N, VT, LDVT, WORK( ITAUP ),$ WORK( IWORK ), LWORK-IWORK+1, IERR )IWORK = IE + N** Perform bidiagonal QR iteration, computing left* singular vectors of A in U and computing right* singular vectors of A in VT* (Workspace: need BDSPAC)*CALL DBDSQR( 'U', N, N, M, 0, S, WORK( IE ), VT,$ LDVT, U, LDU, DUM, 1, WORK( IWORK ),$ INFO )*END IF*END IF*ELSE IF( WNTUA ) THEN*IF( WNTVN ) THEN** Path 7 (M much larger than N, JOBU='A', JOBVT='N')* M left singular vectors to be computed in U and* no right singular vectors to be computed*IF( LWORK.GE.N*N+MAX( N+M, 4*N, BDSPAC ) ) THEN** Sufficient workspace for a fast algorithm*IR = 1IF( LWORK.GE.WRKBL+LDA*N ) THEN** WORK(IR) is LDA by N*LDWRKR = LDAELSE** WORK(IR) is N by N*LDWRKR = NEND IFITAU = IR + LDWRKR*NIWORK = ITAU + N** Compute A=Q*R, copying result to U* (Workspace: need N*N+2*N, prefer N*N+N+N*NB)*CALL DGEQRF( M, N, A, LDA, WORK( ITAU ),$ WORK( IWORK ), LWORK-IWORK+1, IERR )CALL DLACPY( 'L', M, N, A, LDA, U, LDU )** Copy R to WORK(IR), zeroing out below it*CALL DLACPY( 'U', N, N, A, LDA, WORK( IR ),$ LDWRKR )CALL DLASET( 'L', N-1, N-1, ZERO, ZERO,$ WORK( IR+1 ), LDWRKR )** Generate Q in U* (Workspace: need N*N+N+M, prefer N*N+N+M*NB)*CALL DORGQR( M, M, N, U, LDU, WORK( ITAU ),$ WORK( IWORK ), LWORK-IWORK+1, IERR )IE = ITAUITAUQ = IE + NITAUP = ITAUQ + NIWORK = ITAUP + N** Bidiagonalize R in WORK(IR)* (Workspace: need N*N+4*N, prefer N*N+3*N+2*N*NB)*CALL DGEBRD( N, N, WORK( IR ), LDWRKR, S,$ WORK( IE ), WORK( ITAUQ ),$ WORK( ITAUP ), WORK( IWORK ),$ LWORK-IWORK+1, IERR )** Generate left bidiagonalizing vectors in WORK(IR)* (Workspace: need N*N+4*N, prefer N*N+3*N+N*NB)*CALL DORGBR( 'Q', N, N, N, WORK( IR ), LDWRKR,$ WORK( ITAUQ ), WORK( IWORK ),$ LWORK-IWORK+1, IERR )IWORK = IE + N** Perform bidiagonal QR iteration, computing left* singular vectors of R in WORK(IR)* (Workspace: need N*N+BDSPAC)*CALL DBDSQR( 'U', N, 0, N, 0, S, WORK( IE ), DUM,$ 1, WORK( IR ), LDWRKR, DUM, 1,$ WORK( IWORK ), INFO )** Multiply Q in U by left singular vectors of R in* WORK(IR), storing result in A* (Workspace: need N*N)*CALL DGEMM( 'N', 'N', M, N, N, ONE, U, LDU,$ WORK( IR ), LDWRKR, ZERO, A, LDA )** Copy left singular vectors of A from A to U*CALL DLACPY( 'F', M, N, A, LDA, U, LDU )*ELSE** Insufficient workspace for a fast algorithm*ITAU = 1IWORK = ITAU + N** Compute A=Q*R, copying result to U* (Workspace: need 2*N, prefer N+N*NB)*CALL DGEQRF( M, N, A, LDA, WORK( ITAU ),$ WORK( IWORK ), LWORK-IWORK+1, IERR )CALL DLACPY( 'L', M, N, A, LDA, U, LDU )** Generate Q in U* (Workspace: need N+M, prefer N+M*NB)*CALL DORGQR( M, M, N, U, LDU, WORK( ITAU ),$ WORK( IWORK ), LWORK-IWORK+1, IERR )IE = ITAUITAUQ = IE + NITAUP = ITAUQ + NIWORK = ITAUP + N** Zero out below R in A*CALL DLASET( 'L', N-1, N-1, ZERO, ZERO, A( 2, 1 ),$ LDA )** Bidiagonalize R in A* (Workspace: need 4*N, prefer 3*N+2*N*NB)*CALL DGEBRD( N, N, A, LDA, S, WORK( IE ),$ WORK( ITAUQ ), WORK( ITAUP ),$ WORK( IWORK ), LWORK-IWORK+1, IERR )** Multiply Q in U by left bidiagonalizing vectors* in A* (Workspace: need 3*N+M, prefer 3*N+M*NB)*CALL DORMBR( 'Q', 'R', 'N', M, N, N, A, LDA,$ WORK( ITAUQ ), U, LDU, WORK( IWORK ),$ LWORK-IWORK+1, IERR )IWORK = IE + N** Perform bidiagonal QR iteration, computing left* singular vectors of A in U* (Workspace: need BDSPAC)*CALL DBDSQR( 'U', N, 0, M, 0, S, WORK( IE ), DUM,$ 1, U, LDU, DUM, 1, WORK( IWORK ),$ INFO )*END IF*ELSE IF( WNTVO ) THEN** Path 8 (M much larger than N, JOBU='A', JOBVT='O')* M left singular vectors to be computed in U and* N right singular vectors to be overwritten on A*IF( LWORK.GE.2*N*N+MAX( N+M, 4*N, BDSPAC ) ) THEN** Sufficient workspace for a fast algorithm*IU = 1IF( LWORK.GE.WRKBL+2*LDA*N ) THEN** WORK(IU) is LDA by N and WORK(IR) is LDA by N*LDWRKU = LDAIR = IU + LDWRKU*NLDWRKR = LDAELSE IF( LWORK.GE.WRKBL+( LDA+N )*N ) THEN** WORK(IU) is LDA by N and WORK(IR) is N by N*LDWRKU = LDAIR = IU + LDWRKU*NLDWRKR = NELSE** WORK(IU) is N by N and WORK(IR) is N by N*LDWRKU = NIR = IU + LDWRKU*NLDWRKR = NEND IFITAU = IR + LDWRKR*NIWORK = ITAU + N** Compute A=Q*R, copying result to U* (Workspace: need 2*N*N+2*N, prefer 2*N*N+N+N*NB)*CALL DGEQRF( M, N, A, LDA, WORK( ITAU ),$ WORK( IWORK ), LWORK-IWORK+1, IERR )CALL DLACPY( 'L', M, N, A, LDA, U, LDU )** Generate Q in U* (Workspace: need 2*N*N+N+M, prefer 2*N*N+N+M*NB)*CALL DORGQR( M, M, N, U, LDU, WORK( ITAU ),$ WORK( IWORK ), LWORK-IWORK+1, IERR )** Copy R to WORK(IU), zeroing out below it*CALL DLACPY( 'U', N, N, A, LDA, WORK( IU ),$ LDWRKU )CALL DLASET( 'L', N-1, N-1, ZERO, ZERO,$ WORK( IU+1 ), LDWRKU )IE = ITAUITAUQ = IE + NITAUP = ITAUQ + NIWORK = ITAUP + N** Bidiagonalize R in WORK(IU), copying result to* WORK(IR)* (Workspace: need 2*N*N+4*N,* prefer 2*N*N+3*N+2*N*NB)*CALL DGEBRD( N, N, WORK( IU ), LDWRKU, S,$ WORK( IE ), WORK( ITAUQ ),$ WORK( ITAUP ), WORK( IWORK ),$ LWORK-IWORK+1, IERR )CALL DLACPY( 'U', N, N, WORK( IU ), LDWRKU,$ WORK( IR ), LDWRKR )** Generate left bidiagonalizing vectors in WORK(IU)* (Workspace: need 2*N*N+4*N, prefer 2*N*N+3*N+N*NB)*CALL DORGBR( 'Q', N, N, N, WORK( IU ), LDWRKU,$ WORK( ITAUQ ), WORK( IWORK ),$ LWORK-IWORK+1, IERR )** Generate right bidiagonalizing vectors in WORK(IR)* (Workspace: need 2*N*N+4*N-1,* prefer 2*N*N+3*N+(N-1)*NB)*CALL DORGBR( 'P', N, N, N, WORK( IR ), LDWRKR,$ WORK( ITAUP ), WORK( IWORK ),$ LWORK-IWORK+1, IERR )IWORK = IE + N** Perform bidiagonal QR iteration, computing left* singular vectors of R in WORK(IU) and computing* right singular vectors of R in WORK(IR)* (Workspace: need 2*N*N+BDSPAC)*CALL DBDSQR( 'U', N, N, N, 0, S, WORK( IE ),$ WORK( IR ), LDWRKR, WORK( IU ),$ LDWRKU, DUM, 1, WORK( IWORK ), INFO )** Multiply Q in U by left singular vectors of R in* WORK(IU), storing result in A* (Workspace: need N*N)*CALL DGEMM( 'N', 'N', M, N, N, ONE, U, LDU,$ WORK( IU ), LDWRKU, ZERO, A, LDA )** Copy left singular vectors of A from A to U*CALL DLACPY( 'F', M, N, A, LDA, U, LDU )** Copy right singular vectors of R from WORK(IR) to A*CALL DLACPY( 'F', N, N, WORK( IR ), LDWRKR, A,$ LDA )*ELSE** Insufficient workspace for a fast algorithm*ITAU = 1IWORK = ITAU + N** Compute A=Q*R, copying result to U* (Workspace: need 2*N, prefer N+N*NB)*CALL DGEQRF( M, N, A, LDA, WORK( ITAU ),$ WORK( IWORK ), LWORK-IWORK+1, IERR )CALL DLACPY( 'L', M, N, A, LDA, U, LDU )** Generate Q in U* (Workspace: need N+M, prefer N+M*NB)*CALL DORGQR( M, M, N, U, LDU, WORK( ITAU ),$ WORK( IWORK ), LWORK-IWORK+1, IERR )IE = ITAUITAUQ = IE + NITAUP = ITAUQ + NIWORK = ITAUP + N** Zero out below R in A*CALL DLASET( 'L', N-1, N-1, ZERO, ZERO, A( 2, 1 ),$ LDA )** Bidiagonalize R in A* (Workspace: need 4*N, prefer 3*N+2*N*NB)*CALL DGEBRD( N, N, A, LDA, S, WORK( IE ),$ WORK( ITAUQ ), WORK( ITAUP ),$ WORK( IWORK ), LWORK-IWORK+1, IERR )** Multiply Q in U by left bidiagonalizing vectors* in A* (Workspace: need 3*N+M, prefer 3*N+M*NB)*CALL DORMBR( 'Q', 'R', 'N', M, N, N, A, LDA,$ WORK( ITAUQ ), U, LDU, WORK( IWORK ),$ LWORK-IWORK+1, IERR )** Generate right bidiagonalizing vectors in A* (Workspace: need 4*N-1, prefer 3*N+(N-1)*NB)*CALL DORGBR( 'P', N, N, N, A, LDA, WORK( ITAUP ),$ WORK( IWORK ), LWORK-IWORK+1, IERR )IWORK = IE + N** Perform bidiagonal QR iteration, computing left* singular vectors of A in U and computing right* singular vectors of A in A* (Workspace: need BDSPAC)*CALL DBDSQR( 'U', N, N, M, 0, S, WORK( IE ), A,$ LDA, U, LDU, DUM, 1, WORK( IWORK ),$ INFO )*END IF*ELSE IF( WNTVAS ) THEN** Path 9 (M much larger than N, JOBU='A', JOBVT='S'* or 'A')* M left singular vectors to be computed in U and* N right singular vectors to be computed in VT*IF( LWORK.GE.N*N+MAX( N+M, 4*N, BDSPAC ) ) THEN** Sufficient workspace for a fast algorithm*IU = 1IF( LWORK.GE.WRKBL+LDA*N ) THEN** WORK(IU) is LDA by N*LDWRKU = LDAELSE** WORK(IU) is N by N*LDWRKU = NEND IFITAU = IU + LDWRKU*NIWORK = ITAU + N** Compute A=Q*R, copying result to U* (Workspace: need N*N+2*N, prefer N*N+N+N*NB)*CALL DGEQRF( M, N, A, LDA, WORK( ITAU ),$ WORK( IWORK ), LWORK-IWORK+1, IERR )CALL DLACPY( 'L', M, N, A, LDA, U, LDU )** Generate Q in U* (Workspace: need N*N+N+M, prefer N*N+N+M*NB)*CALL DORGQR( M, M, N, U, LDU, WORK( ITAU ),$ WORK( IWORK ), LWORK-IWORK+1, IERR )** Copy R to WORK(IU), zeroing out below it*CALL DLACPY( 'U', N, N, A, LDA, WORK( IU ),$ LDWRKU )CALL DLASET( 'L', N-1, N-1, ZERO, ZERO,$ WORK( IU+1 ), LDWRKU )IE = ITAUITAUQ = IE + NITAUP = ITAUQ + NIWORK = ITAUP + N** Bidiagonalize R in WORK(IU), copying result to VT* (Workspace: need N*N+4*N, prefer N*N+3*N+2*N*NB)*CALL DGEBRD( N, N, WORK( IU ), LDWRKU, S,$ WORK( IE ), WORK( ITAUQ ),$ WORK( ITAUP ), WORK( IWORK ),$ LWORK-IWORK+1, IERR )CALL DLACPY( 'U', N, N, WORK( IU ), LDWRKU, VT,$ LDVT )** Generate left bidiagonalizing vectors in WORK(IU)* (Workspace: need N*N+4*N, prefer N*N+3*N+N*NB)*CALL DORGBR( 'Q', N, N, N, WORK( IU ), LDWRKU,$ WORK( ITAUQ ), WORK( IWORK ),$ LWORK-IWORK+1, IERR )** Generate right bidiagonalizing vectors in VT* (Workspace: need N*N+4*N-1,* prefer N*N+3*N+(N-1)*NB)*CALL DORGBR( 'P', N, N, N, VT, LDVT, WORK( ITAUP ),$ WORK( IWORK ), LWORK-IWORK+1, IERR )IWORK = IE + N** Perform bidiagonal QR iteration, computing left* singular vectors of R in WORK(IU) and computing* right singular vectors of R in VT* (Workspace: need N*N+BDSPAC)*CALL DBDSQR( 'U', N, N, N, 0, S, WORK( IE ), VT,$ LDVT, WORK( IU ), LDWRKU, DUM, 1,$ WORK( IWORK ), INFO )** Multiply Q in U by left singular vectors of R in* WORK(IU), storing result in A* (Workspace: need N*N)*CALL DGEMM( 'N', 'N', M, N, N, ONE, U, LDU,$ WORK( IU ), LDWRKU, ZERO, A, LDA )** Copy left singular vectors of A from A to U*CALL DLACPY( 'F', M, N, A, LDA, U, LDU )*ELSE** Insufficient workspace for a fast algorithm*ITAU = 1IWORK = ITAU + N** Compute A=Q*R, copying result to U* (Workspace: need 2*N, prefer N+N*NB)*CALL DGEQRF( M, N, A, LDA, WORK( ITAU ),$ WORK( IWORK ), LWORK-IWORK+1, IERR )CALL DLACPY( 'L', M, N, A, LDA, U, LDU )** Generate Q in U* (Workspace: need N+M, prefer N+M*NB)*CALL DORGQR( M, M, N, U, LDU, WORK( ITAU ),$ WORK( IWORK ), LWORK-IWORK+1, IERR )** Copy R from A to VT, zeroing out below it*CALL DLACPY( 'U', N, N, A, LDA, VT, LDVT )CALL DLASET( 'L', N-1, N-1, ZERO, ZERO, VT( 2, 1 ),$ LDVT )IE = ITAUITAUQ = IE + NITAUP = ITAUQ + NIWORK = ITAUP + N** Bidiagonalize R in VT* (Workspace: need 4*N, prefer 3*N+2*N*NB)*CALL DGEBRD( N, N, VT, LDVT, S, WORK( IE ),$ WORK( ITAUQ ), WORK( ITAUP ),$ WORK( IWORK ), LWORK-IWORK+1, IERR )** Multiply Q in U by left bidiagonalizing vectors* in VT* (Workspace: need 3*N+M, prefer 3*N+M*NB)*CALL DORMBR( 'Q', 'R', 'N', M, N, N, VT, LDVT,$ WORK( ITAUQ ), U, LDU, WORK( IWORK ),$ LWORK-IWORK+1, IERR )** Generate right bidiagonalizing vectors in VT* (Workspace: need 4*N-1, prefer 3*N+(N-1)*NB)*CALL DORGBR( 'P', N, N, N, VT, LDVT, WORK( ITAUP ),$ WORK( IWORK ), LWORK-IWORK+1, IERR )IWORK = IE + N** Perform bidiagonal QR iteration, computing left* singular vectors of A in U and computing right* singular vectors of A in VT* (Workspace: need BDSPAC)*CALL DBDSQR( 'U', N, N, M, 0, S, WORK( IE ), VT,$ LDVT, U, LDU, DUM, 1, WORK( IWORK ),$ INFO )*END IF*END IF*END IF*ELSE** M .LT. MNTHR** Path 10 (M at least N, but not much larger)* Reduce to bidiagonal form without QR decomposition*IE = 1ITAUQ = IE + NITAUP = ITAUQ + NIWORK = ITAUP + N** Bidiagonalize A* (Workspace: need 3*N+M, prefer 3*N+(M+N)*NB)*CALL DGEBRD( M, N, A, LDA, S, WORK( IE ), WORK( ITAUQ ),$ WORK( ITAUP ), WORK( IWORK ), LWORK-IWORK+1,$ IERR )IF( WNTUAS ) THEN** If left singular vectors desired in U, copy result to U* and generate left bidiagonalizing vectors in U* (Workspace: need 3*N+NCU, prefer 3*N+NCU*NB)*CALL DLACPY( 'L', M, N, A, LDA, U, LDU )IF( WNTUS )$ NCU = NIF( WNTUA )$ NCU = MCALL DORGBR( 'Q', M, NCU, N, U, LDU, WORK( ITAUQ ),$ WORK( IWORK ), LWORK-IWORK+1, IERR )END IFIF( WNTVAS ) THEN** If right singular vectors desired in VT, copy result to* VT and generate right bidiagonalizing vectors in VT* (Workspace: need 4*N-1, prefer 3*N+(N-1)*NB)*CALL DLACPY( 'U', N, N, A, LDA, VT, LDVT )CALL DORGBR( 'P', N, N, N, VT, LDVT, WORK( ITAUP ),$ WORK( IWORK ), LWORK-IWORK+1, IERR )END IFIF( WNTUO ) THEN** If left singular vectors desired in A, generate left* bidiagonalizing vectors in A* (Workspace: need 4*N, prefer 3*N+N*NB)*CALL DORGBR( 'Q', M, N, N, A, LDA, WORK( ITAUQ ),$ WORK( IWORK ), LWORK-IWORK+1, IERR )END IFIF( WNTVO ) THEN** If right singular vectors desired in A, generate right* bidiagonalizing vectors in A* (Workspace: need 4*N-1, prefer 3*N+(N-1)*NB)*CALL DORGBR( 'P', N, N, N, A, LDA, WORK( ITAUP ),$ WORK( IWORK ), LWORK-IWORK+1, IERR )END IFIWORK = IE + NIF( WNTUAS .OR. WNTUO )$ NRU = MIF( WNTUN )$ NRU = 0IF( WNTVAS .OR. WNTVO )$ NCVT = NIF( WNTVN )$ NCVT = 0IF( ( .NOT.WNTUO ) .AND. ( .NOT.WNTVO ) ) THEN** Perform bidiagonal QR iteration, if desired, computing* left singular vectors in U and computing right singular* vectors in VT* (Workspace: need BDSPAC)*CALL DBDSQR( 'U', N, NCVT, NRU, 0, S, WORK( IE ), VT,$ LDVT, U, LDU, DUM, 1, WORK( IWORK ), INFO )ELSE IF( ( .NOT.WNTUO ) .AND. WNTVO ) THEN** Perform bidiagonal QR iteration, if desired, computing* left singular vectors in U and computing right singular* vectors in A* (Workspace: need BDSPAC)*CALL DBDSQR( 'U', N, NCVT, NRU, 0, S, WORK( IE ), A, LDA,$ U, LDU, DUM, 1, WORK( IWORK ), INFO )ELSE** Perform bidiagonal QR iteration, if desired, computing* left singular vectors in A and computing right singular* vectors in VT* (Workspace: need BDSPAC)*CALL DBDSQR( 'U', N, NCVT, NRU, 0, S, WORK( IE ), VT,$ LDVT, A, LDA, DUM, 1, WORK( IWORK ), INFO )END IF*END IF*ELSE** A has more columns than rows. If A has sufficiently more* columns than rows, first reduce using the LQ decomposition (if* sufficient workspace available)*IF( N.GE.MNTHR ) THEN*IF( WNTVN ) THEN** Path 1t(N much larger than M, JOBVT='N')* No right singular vectors to be computed*ITAU = 1IWORK = ITAU + M** Compute A=L*Q* (Workspace: need 2*M, prefer M+M*NB)*CALL DGELQF( M, N, A, LDA, WORK( ITAU ), WORK( IWORK ),$ LWORK-IWORK+1, IERR )** Zero out above L*CALL DLASET( 'U', M-1, M-1, ZERO, ZERO, A( 1, 2 ), LDA )IE = 1ITAUQ = IE + MITAUP = ITAUQ + MIWORK = ITAUP + M** Bidiagonalize L in A* (Workspace: need 4*M, prefer 3*M+2*M*NB)*CALL DGEBRD( M, M, A, LDA, S, WORK( IE ), WORK( ITAUQ ),$ WORK( ITAUP ), WORK( IWORK ), LWORK-IWORK+1,$ IERR )IF( WNTUO .OR. WNTUAS ) THEN** If left singular vectors desired, generate Q* (Workspace: need 4*M, prefer 3*M+M*NB)*CALL DORGBR( 'Q', M, M, M, A, LDA, WORK( ITAUQ ),$ WORK( IWORK ), LWORK-IWORK+1, IERR )END IFIWORK = IE + MNRU = 0IF( WNTUO .OR. WNTUAS )$ NRU = M** Perform bidiagonal QR iteration, computing left singular* vectors of A in A if desired* (Workspace: need BDSPAC)*CALL DBDSQR( 'U', M, 0, NRU, 0, S, WORK( IE ), DUM, 1, A,$ LDA, DUM, 1, WORK( IWORK ), INFO )** If left singular vectors desired in U, copy them there*IF( WNTUAS )$ CALL DLACPY( 'F', M, M, A, LDA, U, LDU )*ELSE IF( WNTVO .AND. WNTUN ) THEN** Path 2t(N much larger than M, JOBU='N', JOBVT='O')* M right singular vectors to be overwritten on A and* no left singular vectors to be computed*IF( LWORK.GE.M*M+MAX( 4*M, BDSPAC ) ) THEN** Sufficient workspace for a fast algorithm*IR = 1IF( LWORK.GE.MAX( WRKBL, LDA*N+M )+LDA*M ) THEN** WORK(IU) is LDA by N and WORK(IR) is LDA by M*LDWRKU = LDACHUNK = NLDWRKR = LDAELSE IF( LWORK.GE.MAX( WRKBL, LDA*N+M )+M*M ) THEN** WORK(IU) is LDA by N and WORK(IR) is M by M*LDWRKU = LDACHUNK = NLDWRKR = MELSE** WORK(IU) is M by CHUNK and WORK(IR) is M by M*LDWRKU = MCHUNK = ( LWORK-M*M-M ) / MLDWRKR = MEND IFITAU = IR + LDWRKR*MIWORK = ITAU + M** Compute A=L*Q* (Workspace: need M*M+2*M, prefer M*M+M+M*NB)*CALL DGELQF( M, N, A, LDA, WORK( ITAU ),$ WORK( IWORK ), LWORK-IWORK+1, IERR )** Copy L to WORK(IR) and zero out above it*CALL DLACPY( 'L', M, M, A, LDA, WORK( IR ), LDWRKR )CALL DLASET( 'U', M-1, M-1, ZERO, ZERO,$ WORK( IR+LDWRKR ), LDWRKR )** Generate Q in A* (Workspace: need M*M+2*M, prefer M*M+M+M*NB)*CALL DORGLQ( M, N, M, A, LDA, WORK( ITAU ),$ WORK( IWORK ), LWORK-IWORK+1, IERR )IE = ITAUITAUQ = IE + MITAUP = ITAUQ + MIWORK = ITAUP + M** Bidiagonalize L in WORK(IR)* (Workspace: need M*M+4*M, prefer M*M+3*M+2*M*NB)*CALL DGEBRD( M, M, WORK( IR ), LDWRKR, S, WORK( IE ),$ WORK( ITAUQ ), WORK( ITAUP ),$ WORK( IWORK ), LWORK-IWORK+1, IERR )** Generate right vectors bidiagonalizing L* (Workspace: need M*M+4*M-1, prefer M*M+3*M+(M-1)*NB)*CALL DORGBR( 'P', M, M, M, WORK( IR ), LDWRKR,$ WORK( ITAUP ), WORK( IWORK ),$ LWORK-IWORK+1, IERR )IWORK = IE + M** Perform bidiagonal QR iteration, computing right* singular vectors of L in WORK(IR)* (Workspace: need M*M+BDSPAC)*CALL DBDSQR( 'U', M, M, 0, 0, S, WORK( IE ),$ WORK( IR ), LDWRKR, DUM, 1, DUM, 1,$ WORK( IWORK ), INFO )IU = IE + M** Multiply right singular vectors of L in WORK(IR) by Q* in A, storing result in WORK(IU) and copying to A* (Workspace: need M*M+2*M, prefer M*M+M*N+M)*DO 30 I = 1, N, CHUNKBLK = MIN( N-I+1, CHUNK )CALL DGEMM( 'N', 'N', M, BLK, M, ONE, WORK( IR ),$ LDWRKR, A( 1, I ), LDA, ZERO,$ WORK( IU ), LDWRKU )CALL DLACPY( 'F', M, BLK, WORK( IU ), LDWRKU,$ A( 1, I ), LDA )30 CONTINUE*ELSE** Insufficient workspace for a fast algorithm*IE = 1ITAUQ = IE + MITAUP = ITAUQ + MIWORK = ITAUP + M** Bidiagonalize A* (Workspace: need 3*M+N, prefer 3*M+(M+N)*NB)*CALL DGEBRD( M, N, A, LDA, S, WORK( IE ),$ WORK( ITAUQ ), WORK( ITAUP ),$ WORK( IWORK ), LWORK-IWORK+1, IERR )** Generate right vectors bidiagonalizing A* (Workspace: need 4*M, prefer 3*M+M*NB)*CALL DORGBR( 'P', M, N, M, A, LDA, WORK( ITAUP ),$ WORK( IWORK ), LWORK-IWORK+1, IERR )IWORK = IE + M** Perform bidiagonal QR iteration, computing right* singular vectors of A in A* (Workspace: need BDSPAC)*CALL DBDSQR( 'L', M, N, 0, 0, S, WORK( IE ), A, LDA,$ DUM, 1, DUM, 1, WORK( IWORK ), INFO )*END IF*ELSE IF( WNTVO .AND. WNTUAS ) THEN** Path 3t(N much larger than M, JOBU='S' or 'A', JOBVT='O')* M right singular vectors to be overwritten on A and* M left singular vectors to be computed in U*IF( LWORK.GE.M*M+MAX( 4*M, BDSPAC ) ) THEN** Sufficient workspace for a fast algorithm*IR = 1IF( LWORK.GE.MAX( WRKBL, LDA*N+M )+LDA*M ) THEN** WORK(IU) is LDA by N and WORK(IR) is LDA by M*LDWRKU = LDACHUNK = NLDWRKR = LDAELSE IF( LWORK.GE.MAX( WRKBL, LDA*N+M )+M*M ) THEN** WORK(IU) is LDA by N and WORK(IR) is M by M*LDWRKU = LDACHUNK = NLDWRKR = MELSE** WORK(IU) is M by CHUNK and WORK(IR) is M by M*LDWRKU = MCHUNK = ( LWORK-M*M-M ) / MLDWRKR = MEND IFITAU = IR + LDWRKR*MIWORK = ITAU + M** Compute A=L*Q* (Workspace: need M*M+2*M, prefer M*M+M+M*NB)*CALL DGELQF( M, N, A, LDA, WORK( ITAU ),$ WORK( IWORK ), LWORK-IWORK+1, IERR )** Copy L to U, zeroing about above it*CALL DLACPY( 'L', M, M, A, LDA, U, LDU )CALL DLASET( 'U', M-1, M-1, ZERO, ZERO, U( 1, 2 ),$ LDU )** Generate Q in A* (Workspace: need M*M+2*M, prefer M*M+M+M*NB)*CALL DORGLQ( M, N, M, A, LDA, WORK( ITAU ),$ WORK( IWORK ), LWORK-IWORK+1, IERR )IE = ITAUITAUQ = IE + MITAUP = ITAUQ + MIWORK = ITAUP + M** Bidiagonalize L in U, copying result to WORK(IR)* (Workspace: need M*M+4*M, prefer M*M+3*M+2*M*NB)*CALL DGEBRD( M, M, U, LDU, S, WORK( IE ),$ WORK( ITAUQ ), WORK( ITAUP ),$ WORK( IWORK ), LWORK-IWORK+1, IERR )CALL DLACPY( 'U', M, M, U, LDU, WORK( IR ), LDWRKR )** Generate right vectors bidiagonalizing L in WORK(IR)* (Workspace: need M*M+4*M-1, prefer M*M+3*M+(M-1)*NB)*CALL DORGBR( 'P', M, M, M, WORK( IR ), LDWRKR,$ WORK( ITAUP ), WORK( IWORK ),$ LWORK-IWORK+1, IERR )** Generate left vectors bidiagonalizing L in U* (Workspace: need M*M+4*M, prefer M*M+3*M+M*NB)*CALL DORGBR( 'Q', M, M, M, U, LDU, WORK( ITAUQ ),$ WORK( IWORK ), LWORK-IWORK+1, IERR )IWORK = IE + M** Perform bidiagonal QR iteration, computing left* singular vectors of L in U, and computing right* singular vectors of L in WORK(IR)* (Workspace: need M*M+BDSPAC)*CALL DBDSQR( 'U', M, M, M, 0, S, WORK( IE ),$ WORK( IR ), LDWRKR, U, LDU, DUM, 1,$ WORK( IWORK ), INFO )IU = IE + M** Multiply right singular vectors of L in WORK(IR) by Q* in A, storing result in WORK(IU) and copying to A* (Workspace: need M*M+2*M, prefer M*M+M*N+M))*DO 40 I = 1, N, CHUNKBLK = MIN( N-I+1, CHUNK )CALL DGEMM( 'N', 'N', M, BLK, M, ONE, WORK( IR ),$ LDWRKR, A( 1, I ), LDA, ZERO,$ WORK( IU ), LDWRKU )CALL DLACPY( 'F', M, BLK, WORK( IU ), LDWRKU,$ A( 1, I ), LDA )40 CONTINUE*ELSE** Insufficient workspace for a fast algorithm*ITAU = 1IWORK = ITAU + M** Compute A=L*Q* (Workspace: need 2*M, prefer M+M*NB)*CALL DGELQF( M, N, A, LDA, WORK( ITAU ),$ WORK( IWORK ), LWORK-IWORK+1, IERR )** Copy L to U, zeroing out above it*CALL DLACPY( 'L', M, M, A, LDA, U, LDU )CALL DLASET( 'U', M-1, M-1, ZERO, ZERO, U( 1, 2 ),$ LDU )** Generate Q in A* (Workspace: need 2*M, prefer M+M*NB)*CALL DORGLQ( M, N, M, A, LDA, WORK( ITAU ),$ WORK( IWORK ), LWORK-IWORK+1, IERR )IE = ITAUITAUQ = IE + MITAUP = ITAUQ + MIWORK = ITAUP + M** Bidiagonalize L in U* (Workspace: need 4*M, prefer 3*M+2*M*NB)*CALL DGEBRD( M, M, U, LDU, S, WORK( IE ),$ WORK( ITAUQ ), WORK( ITAUP ),$ WORK( IWORK ), LWORK-IWORK+1, IERR )** Multiply right vectors bidiagonalizing L by Q in A* (Workspace: need 3*M+N, prefer 3*M+N*NB)*CALL DORMBR( 'P', 'L', 'T', M, N, M, U, LDU,$ WORK( ITAUP ), A, LDA, WORK( IWORK ),$ LWORK-IWORK+1, IERR )** Generate left vectors bidiagonalizing L in U* (Workspace: need 4*M, prefer 3*M+M*NB)*CALL DORGBR( 'Q', M, M, M, U, LDU, WORK( ITAUQ ),$ WORK( IWORK ), LWORK-IWORK+1, IERR )IWORK = IE + M** Perform bidiagonal QR iteration, computing left* singular vectors of A in U and computing right* singular vectors of A in A* (Workspace: need BDSPAC)*CALL DBDSQR( 'U', M, N, M, 0, S, WORK( IE ), A, LDA,$ U, LDU, DUM, 1, WORK( IWORK ), INFO )*END IF*ELSE IF( WNTVS ) THEN*IF( WNTUN ) THEN** Path 4t(N much larger than M, JOBU='N', JOBVT='S')* M right singular vectors to be computed in VT and* no left singular vectors to be computed*IF( LWORK.GE.M*M+MAX( 4*M, BDSPAC ) ) THEN** Sufficient workspace for a fast algorithm*IR = 1IF( LWORK.GE.WRKBL+LDA*M ) THEN** WORK(IR) is LDA by M*LDWRKR = LDAELSE** WORK(IR) is M by M*LDWRKR = MEND IFITAU = IR + LDWRKR*MIWORK = ITAU + M** Compute A=L*Q* (Workspace: need M*M+2*M, prefer M*M+M+M*NB)*CALL DGELQF( M, N, A, LDA, WORK( ITAU ),$ WORK( IWORK ), LWORK-IWORK+1, IERR )** Copy L to WORK(IR), zeroing out above it*CALL DLACPY( 'L', M, M, A, LDA, WORK( IR ),$ LDWRKR )CALL DLASET( 'U', M-1, M-1, ZERO, ZERO,$ WORK( IR+LDWRKR ), LDWRKR )** Generate Q in A* (Workspace: need M*M+2*M, prefer M*M+M+M*NB)*CALL DORGLQ( M, N, M, A, LDA, WORK( ITAU ),$ WORK( IWORK ), LWORK-IWORK+1, IERR )IE = ITAUITAUQ = IE + MITAUP = ITAUQ + MIWORK = ITAUP + M** Bidiagonalize L in WORK(IR)* (Workspace: need M*M+4*M, prefer M*M+3*M+2*M*NB)*CALL DGEBRD( M, M, WORK( IR ), LDWRKR, S,$ WORK( IE ), WORK( ITAUQ ),$ WORK( ITAUP ), WORK( IWORK ),$ LWORK-IWORK+1, IERR )** Generate right vectors bidiagonalizing L in* WORK(IR)* (Workspace: need M*M+4*M, prefer M*M+3*M+(M-1)*NB)*CALL DORGBR( 'P', M, M, M, WORK( IR ), LDWRKR,$ WORK( ITAUP ), WORK( IWORK ),$ LWORK-IWORK+1, IERR )IWORK = IE + M** Perform bidiagonal QR iteration, computing right* singular vectors of L in WORK(IR)* (Workspace: need M*M+BDSPAC)*CALL DBDSQR( 'U', M, M, 0, 0, S, WORK( IE ),$ WORK( IR ), LDWRKR, DUM, 1, DUM, 1,$ WORK( IWORK ), INFO )** Multiply right singular vectors of L in WORK(IR) by* Q in A, storing result in VT* (Workspace: need M*M)*CALL DGEMM( 'N', 'N', M, N, M, ONE, WORK( IR ),$ LDWRKR, A, LDA, ZERO, VT, LDVT )*ELSE** Insufficient workspace for a fast algorithm*ITAU = 1IWORK = ITAU + M** Compute A=L*Q* (Workspace: need 2*M, prefer M+M*NB)*CALL DGELQF( M, N, A, LDA, WORK( ITAU ),$ WORK( IWORK ), LWORK-IWORK+1, IERR )** Copy result to VT*CALL DLACPY( 'U', M, N, A, LDA, VT, LDVT )** Generate Q in VT* (Workspace: need 2*M, prefer M+M*NB)*CALL DORGLQ( M, N, M, VT, LDVT, WORK( ITAU ),$ WORK( IWORK ), LWORK-IWORK+1, IERR )IE = ITAUITAUQ = IE + MITAUP = ITAUQ + MIWORK = ITAUP + M** Zero out above L in A*CALL DLASET( 'U', M-1, M-1, ZERO, ZERO, A( 1, 2 ),$ LDA )** Bidiagonalize L in A* (Workspace: need 4*M, prefer 3*M+2*M*NB)*CALL DGEBRD( M, M, A, LDA, S, WORK( IE ),$ WORK( ITAUQ ), WORK( ITAUP ),$ WORK( IWORK ), LWORK-IWORK+1, IERR )** Multiply right vectors bidiagonalizing L by Q in VT* (Workspace: need 3*M+N, prefer 3*M+N*NB)*CALL DORMBR( 'P', 'L', 'T', M, N, M, A, LDA,$ WORK( ITAUP ), VT, LDVT,$ WORK( IWORK ), LWORK-IWORK+1, IERR )IWORK = IE + M** Perform bidiagonal QR iteration, computing right* singular vectors of A in VT* (Workspace: need BDSPAC)*CALL DBDSQR( 'U', M, N, 0, 0, S, WORK( IE ), VT,$ LDVT, DUM, 1, DUM, 1, WORK( IWORK ),$ INFO )*END IF*ELSE IF( WNTUO ) THEN** Path 5t(N much larger than M, JOBU='O', JOBVT='S')* M right singular vectors to be computed in VT and* M left singular vectors to be overwritten on A*IF( LWORK.GE.2*M*M+MAX( 4*M, BDSPAC ) ) THEN** Sufficient workspace for a fast algorithm*IU = 1IF( LWORK.GE.WRKBL+2*LDA*M ) THEN** WORK(IU) is LDA by M and WORK(IR) is LDA by M*LDWRKU = LDAIR = IU + LDWRKU*MLDWRKR = LDAELSE IF( LWORK.GE.WRKBL+( LDA+M )*M ) THEN** WORK(IU) is LDA by M and WORK(IR) is M by M*LDWRKU = LDAIR = IU + LDWRKU*MLDWRKR = MELSE** WORK(IU) is M by M and WORK(IR) is M by M*LDWRKU = MIR = IU + LDWRKU*MLDWRKR = MEND IFITAU = IR + LDWRKR*MIWORK = ITAU + M** Compute A=L*Q* (Workspace: need 2*M*M+2*M, prefer 2*M*M+M+M*NB)*CALL DGELQF( M, N, A, LDA, WORK( ITAU ),$ WORK( IWORK ), LWORK-IWORK+1, IERR )** Copy L to WORK(IU), zeroing out below it*CALL DLACPY( 'L', M, M, A, LDA, WORK( IU ),$ LDWRKU )CALL DLASET( 'U', M-1, M-1, ZERO, ZERO,$ WORK( IU+LDWRKU ), LDWRKU )** Generate Q in A* (Workspace: need 2*M*M+2*M, prefer 2*M*M+M+M*NB)*CALL DORGLQ( M, N, M, A, LDA, WORK( ITAU ),$ WORK( IWORK ), LWORK-IWORK+1, IERR )IE = ITAUITAUQ = IE + MITAUP = ITAUQ + MIWORK = ITAUP + M** Bidiagonalize L in WORK(IU), copying result to* WORK(IR)* (Workspace: need 2*M*M+4*M,* prefer 2*M*M+3*M+2*M*NB)*CALL DGEBRD( M, M, WORK( IU ), LDWRKU, S,$ WORK( IE ), WORK( ITAUQ ),$ WORK( ITAUP ), WORK( IWORK ),$ LWORK-IWORK+1, IERR )CALL DLACPY( 'L', M, M, WORK( IU ), LDWRKU,$ WORK( IR ), LDWRKR )** Generate right bidiagonalizing vectors in WORK(IU)* (Workspace: need 2*M*M+4*M-1,* prefer 2*M*M+3*M+(M-1)*NB)*CALL DORGBR( 'P', M, M, M, WORK( IU ), LDWRKU,$ WORK( ITAUP ), WORK( IWORK ),$ LWORK-IWORK+1, IERR )** Generate left bidiagonalizing vectors in WORK(IR)* (Workspace: need 2*M*M+4*M, prefer 2*M*M+3*M+M*NB)*CALL DORGBR( 'Q', M, M, M, WORK( IR ), LDWRKR,$ WORK( ITAUQ ), WORK( IWORK ),$ LWORK-IWORK+1, IERR )IWORK = IE + M** Perform bidiagonal QR iteration, computing left* singular vectors of L in WORK(IR) and computing* right singular vectors of L in WORK(IU)* (Workspace: need 2*M*M+BDSPAC)*CALL DBDSQR( 'U', M, M, M, 0, S, WORK( IE ),$ WORK( IU ), LDWRKU, WORK( IR ),$ LDWRKR, DUM, 1, WORK( IWORK ), INFO )** Multiply right singular vectors of L in WORK(IU) by* Q in A, storing result in VT* (Workspace: need M*M)*CALL DGEMM( 'N', 'N', M, N, M, ONE, WORK( IU ),$ LDWRKU, A, LDA, ZERO, VT, LDVT )** Copy left singular vectors of L to A* (Workspace: need M*M)*CALL DLACPY( 'F', M, M, WORK( IR ), LDWRKR, A,$ LDA )*ELSE** Insufficient workspace for a fast algorithm*ITAU = 1IWORK = ITAU + M** Compute A=L*Q, copying result to VT* (Workspace: need 2*M, prefer M+M*NB)*CALL DGELQF( M, N, A, LDA, WORK( ITAU ),$ WORK( IWORK ), LWORK-IWORK+1, IERR )CALL DLACPY( 'U', M, N, A, LDA, VT, LDVT )** Generate Q in VT* (Workspace: need 2*M, prefer M+M*NB)*CALL DORGLQ( M, N, M, VT, LDVT, WORK( ITAU ),$ WORK( IWORK ), LWORK-IWORK+1, IERR )IE = ITAUITAUQ = IE + MITAUP = ITAUQ + MIWORK = ITAUP + M** Zero out above L in A*CALL DLASET( 'U', M-1, M-1, ZERO, ZERO, A( 1, 2 ),$ LDA )** Bidiagonalize L in A* (Workspace: need 4*M, prefer 3*M+2*M*NB)*CALL DGEBRD( M, M, A, LDA, S, WORK( IE ),$ WORK( ITAUQ ), WORK( ITAUP ),$ WORK( IWORK ), LWORK-IWORK+1, IERR )** Multiply right vectors bidiagonalizing L by Q in VT* (Workspace: need 3*M+N, prefer 3*M+N*NB)*CALL DORMBR( 'P', 'L', 'T', M, N, M, A, LDA,$ WORK( ITAUP ), VT, LDVT,$ WORK( IWORK ), LWORK-IWORK+1, IERR )** Generate left bidiagonalizing vectors of L in A* (Workspace: need 4*M, prefer 3*M+M*NB)*CALL DORGBR( 'Q', M, M, M, A, LDA, WORK( ITAUQ ),$ WORK( IWORK ), LWORK-IWORK+1, IERR )IWORK = IE + M** Perform bidiagonal QR iteration, compute left* singular vectors of A in A and compute right* singular vectors of A in VT* (Workspace: need BDSPAC)*CALL DBDSQR( 'U', M, N, M, 0, S, WORK( IE ), VT,$ LDVT, A, LDA, DUM, 1, WORK( IWORK ),$ INFO )*END IF*ELSE IF( WNTUAS ) THEN** Path 6t(N much larger than M, JOBU='S' or 'A',* JOBVT='S')* M right singular vectors to be computed in VT and* M left singular vectors to be computed in U*IF( LWORK.GE.M*M+MAX( 4*M, BDSPAC ) ) THEN** Sufficient workspace for a fast algorithm*IU = 1IF( LWORK.GE.WRKBL+LDA*M ) THEN** WORK(IU) is LDA by N*LDWRKU = LDAELSE** WORK(IU) is LDA by M*LDWRKU = MEND IFITAU = IU + LDWRKU*MIWORK = ITAU + M** Compute A=L*Q* (Workspace: need M*M+2*M, prefer M*M+M+M*NB)*CALL DGELQF( M, N, A, LDA, WORK( ITAU ),$ WORK( IWORK ), LWORK-IWORK+1, IERR )** Copy L to WORK(IU), zeroing out above it*CALL DLACPY( 'L', M, M, A, LDA, WORK( IU ),$ LDWRKU )CALL DLASET( 'U', M-1, M-1, ZERO, ZERO,$ WORK( IU+LDWRKU ), LDWRKU )** Generate Q in A* (Workspace: need M*M+2*M, prefer M*M+M+M*NB)*CALL DORGLQ( M, N, M, A, LDA, WORK( ITAU ),$ WORK( IWORK ), LWORK-IWORK+1, IERR )IE = ITAUITAUQ = IE + MITAUP = ITAUQ + MIWORK = ITAUP + M** Bidiagonalize L in WORK(IU), copying result to U* (Workspace: need M*M+4*M, prefer M*M+3*M+2*M*NB)*CALL DGEBRD( M, M, WORK( IU ), LDWRKU, S,$ WORK( IE ), WORK( ITAUQ ),$ WORK( ITAUP ), WORK( IWORK ),$ LWORK-IWORK+1, IERR )CALL DLACPY( 'L', M, M, WORK( IU ), LDWRKU, U,$ LDU )** Generate right bidiagonalizing vectors in WORK(IU)* (Workspace: need M*M+4*M-1,* prefer M*M+3*M+(M-1)*NB)*CALL DORGBR( 'P', M, M, M, WORK( IU ), LDWRKU,$ WORK( ITAUP ), WORK( IWORK ),$ LWORK-IWORK+1, IERR )** Generate left bidiagonalizing vectors in U* (Workspace: need M*M+4*M, prefer M*M+3*M+M*NB)*CALL DORGBR( 'Q', M, M, M, U, LDU, WORK( ITAUQ ),$ WORK( IWORK ), LWORK-IWORK+1, IERR )IWORK = IE + M** Perform bidiagonal QR iteration, computing left* singular vectors of L in U and computing right* singular vectors of L in WORK(IU)* (Workspace: need M*M+BDSPAC)*CALL DBDSQR( 'U', M, M, M, 0, S, WORK( IE ),$ WORK( IU ), LDWRKU, U, LDU, DUM, 1,$ WORK( IWORK ), INFO )** Multiply right singular vectors of L in WORK(IU) by* Q in A, storing result in VT* (Workspace: need M*M)*CALL DGEMM( 'N', 'N', M, N, M, ONE, WORK( IU ),$ LDWRKU, A, LDA, ZERO, VT, LDVT )*ELSE** Insufficient workspace for a fast algorithm*ITAU = 1IWORK = ITAU + M** Compute A=L*Q, copying result to VT* (Workspace: need 2*M, prefer M+M*NB)*CALL DGELQF( M, N, A, LDA, WORK( ITAU ),$ WORK( IWORK ), LWORK-IWORK+1, IERR )CALL DLACPY( 'U', M, N, A, LDA, VT, LDVT )** Generate Q in VT* (Workspace: need 2*M, prefer M+M*NB)*CALL DORGLQ( M, N, M, VT, LDVT, WORK( ITAU ),$ WORK( IWORK ), LWORK-IWORK+1, IERR )** Copy L to U, zeroing out above it*CALL DLACPY( 'L', M, M, A, LDA, U, LDU )CALL DLASET( 'U', M-1, M-1, ZERO, ZERO, U( 1, 2 ),$ LDU )IE = ITAUITAUQ = IE + MITAUP = ITAUQ + MIWORK = ITAUP + M** Bidiagonalize L in U* (Workspace: need 4*M, prefer 3*M+2*M*NB)*CALL DGEBRD( M, M, U, LDU, S, WORK( IE ),$ WORK( ITAUQ ), WORK( ITAUP ),$ WORK( IWORK ), LWORK-IWORK+1, IERR )** Multiply right bidiagonalizing vectors in U by Q* in VT* (Workspace: need 3*M+N, prefer 3*M+N*NB)*CALL DORMBR( 'P', 'L', 'T', M, N, M, U, LDU,$ WORK( ITAUP ), VT, LDVT,$ WORK( IWORK ), LWORK-IWORK+1, IERR )** Generate left bidiagonalizing vectors in U* (Workspace: need 4*M, prefer 3*M+M*NB)*CALL DORGBR( 'Q', M, M, M, U, LDU, WORK( ITAUQ ),$ WORK( IWORK ), LWORK-IWORK+1, IERR )IWORK = IE + M** Perform bidiagonal QR iteration, computing left* singular vectors of A in U and computing right* singular vectors of A in VT* (Workspace: need BDSPAC)*CALL DBDSQR( 'U', M, N, M, 0, S, WORK( IE ), VT,$ LDVT, U, LDU, DUM, 1, WORK( IWORK ),$ INFO )*END IF*END IF*ELSE IF( WNTVA ) THEN*IF( WNTUN ) THEN** Path 7t(N much larger than M, JOBU='N', JOBVT='A')* N right singular vectors to be computed in VT and* no left singular vectors to be computed*IF( LWORK.GE.M*M+MAX( N+M, 4*M, BDSPAC ) ) THEN** Sufficient workspace for a fast algorithm*IR = 1IF( LWORK.GE.WRKBL+LDA*M ) THEN** WORK(IR) is LDA by M*LDWRKR = LDAELSE** WORK(IR) is M by M*LDWRKR = MEND IFITAU = IR + LDWRKR*MIWORK = ITAU + M** Compute A=L*Q, copying result to VT* (Workspace: need M*M+2*M, prefer M*M+M+M*NB)*CALL DGELQF( M, N, A, LDA, WORK( ITAU ),$ WORK( IWORK ), LWORK-IWORK+1, IERR )CALL DLACPY( 'U', M, N, A, LDA, VT, LDVT )** Copy L to WORK(IR), zeroing out above it*CALL DLACPY( 'L', M, M, A, LDA, WORK( IR ),$ LDWRKR )CALL DLASET( 'U', M-1, M-1, ZERO, ZERO,$ WORK( IR+LDWRKR ), LDWRKR )** Generate Q in VT* (Workspace: need M*M+M+N, prefer M*M+M+N*NB)*CALL DORGLQ( N, N, M, VT, LDVT, WORK( ITAU ),$ WORK( IWORK ), LWORK-IWORK+1, IERR )IE = ITAUITAUQ = IE + MITAUP = ITAUQ + MIWORK = ITAUP + M** Bidiagonalize L in WORK(IR)* (Workspace: need M*M+4*M, prefer M*M+3*M+2*M*NB)*CALL DGEBRD( M, M, WORK( IR ), LDWRKR, S,$ WORK( IE ), WORK( ITAUQ ),$ WORK( ITAUP ), WORK( IWORK ),$ LWORK-IWORK+1, IERR )** Generate right bidiagonalizing vectors in WORK(IR)* (Workspace: need M*M+4*M-1,* prefer M*M+3*M+(M-1)*NB)*CALL DORGBR( 'P', M, M, M, WORK( IR ), LDWRKR,$ WORK( ITAUP ), WORK( IWORK ),$ LWORK-IWORK+1, IERR )IWORK = IE + M** Perform bidiagonal QR iteration, computing right* singular vectors of L in WORK(IR)* (Workspace: need M*M+BDSPAC)*CALL DBDSQR( 'U', M, M, 0, 0, S, WORK( IE ),$ WORK( IR ), LDWRKR, DUM, 1, DUM, 1,$ WORK( IWORK ), INFO )** Multiply right singular vectors of L in WORK(IR) by* Q in VT, storing result in A* (Workspace: need M*M)*CALL DGEMM( 'N', 'N', M, N, M, ONE, WORK( IR ),$ LDWRKR, VT, LDVT, ZERO, A, LDA )** Copy right singular vectors of A from A to VT*CALL DLACPY( 'F', M, N, A, LDA, VT, LDVT )*ELSE** Insufficient workspace for a fast algorithm*ITAU = 1IWORK = ITAU + M** Compute A=L*Q, copying result to VT* (Workspace: need 2*M, prefer M+M*NB)*CALL DGELQF( M, N, A, LDA, WORK( ITAU ),$ WORK( IWORK ), LWORK-IWORK+1, IERR )CALL DLACPY( 'U', M, N, A, LDA, VT, LDVT )** Generate Q in VT* (Workspace: need M+N, prefer M+N*NB)*CALL DORGLQ( N, N, M, VT, LDVT, WORK( ITAU ),$ WORK( IWORK ), LWORK-IWORK+1, IERR )IE = ITAUITAUQ = IE + MITAUP = ITAUQ + MIWORK = ITAUP + M** Zero out above L in A*CALL DLASET( 'U', M-1, M-1, ZERO, ZERO, A( 1, 2 ),$ LDA )** Bidiagonalize L in A* (Workspace: need 4*M, prefer 3*M+2*M*NB)*CALL DGEBRD( M, M, A, LDA, S, WORK( IE ),$ WORK( ITAUQ ), WORK( ITAUP ),$ WORK( IWORK ), LWORK-IWORK+1, IERR )** Multiply right bidiagonalizing vectors in A by Q* in VT* (Workspace: need 3*M+N, prefer 3*M+N*NB)*CALL DORMBR( 'P', 'L', 'T', M, N, M, A, LDA,$ WORK( ITAUP ), VT, LDVT,$ WORK( IWORK ), LWORK-IWORK+1, IERR )IWORK = IE + M** Perform bidiagonal QR iteration, computing right* singular vectors of A in VT* (Workspace: need BDSPAC)*CALL DBDSQR( 'U', M, N, 0, 0, S, WORK( IE ), VT,$ LDVT, DUM, 1, DUM, 1, WORK( IWORK ),$ INFO )*END IF*ELSE IF( WNTUO ) THEN** Path 8t(N much larger than M, JOBU='O', JOBVT='A')* N right singular vectors to be computed in VT and* M left singular vectors to be overwritten on A*IF( LWORK.GE.2*M*M+MAX( N+M, 4*M, BDSPAC ) ) THEN** Sufficient workspace for a fast algorithm*IU = 1IF( LWORK.GE.WRKBL+2*LDA*M ) THEN** WORK(IU) is LDA by M and WORK(IR) is LDA by M*LDWRKU = LDAIR = IU + LDWRKU*MLDWRKR = LDAELSE IF( LWORK.GE.WRKBL+( LDA+M )*M ) THEN** WORK(IU) is LDA by M and WORK(IR) is M by M*LDWRKU = LDAIR = IU + LDWRKU*MLDWRKR = MELSE** WORK(IU) is M by M and WORK(IR) is M by M*LDWRKU = MIR = IU + LDWRKU*MLDWRKR = MEND IFITAU = IR + LDWRKR*MIWORK = ITAU + M** Compute A=L*Q, copying result to VT* (Workspace: need 2*M*M+2*M, prefer 2*M*M+M+M*NB)*CALL DGELQF( M, N, A, LDA, WORK( ITAU ),$ WORK( IWORK ), LWORK-IWORK+1, IERR )CALL DLACPY( 'U', M, N, A, LDA, VT, LDVT )** Generate Q in VT* (Workspace: need 2*M*M+M+N, prefer 2*M*M+M+N*NB)*CALL DORGLQ( N, N, M, VT, LDVT, WORK( ITAU ),$ WORK( IWORK ), LWORK-IWORK+1, IERR )** Copy L to WORK(IU), zeroing out above it*CALL DLACPY( 'L', M, M, A, LDA, WORK( IU ),$ LDWRKU )CALL DLASET( 'U', M-1, M-1, ZERO, ZERO,$ WORK( IU+LDWRKU ), LDWRKU )IE = ITAUITAUQ = IE + MITAUP = ITAUQ + MIWORK = ITAUP + M** Bidiagonalize L in WORK(IU), copying result to* WORK(IR)* (Workspace: need 2*M*M+4*M,* prefer 2*M*M+3*M+2*M*NB)*CALL DGEBRD( M, M, WORK( IU ), LDWRKU, S,$ WORK( IE ), WORK( ITAUQ ),$ WORK( ITAUP ), WORK( IWORK ),$ LWORK-IWORK+1, IERR )CALL DLACPY( 'L', M, M, WORK( IU ), LDWRKU,$ WORK( IR ), LDWRKR )** Generate right bidiagonalizing vectors in WORK(IU)* (Workspace: need 2*M*M+4*M-1,* prefer 2*M*M+3*M+(M-1)*NB)*CALL DORGBR( 'P', M, M, M, WORK( IU ), LDWRKU,$ WORK( ITAUP ), WORK( IWORK ),$ LWORK-IWORK+1, IERR )** Generate left bidiagonalizing vectors in WORK(IR)* (Workspace: need 2*M*M+4*M, prefer 2*M*M+3*M+M*NB)*CALL DORGBR( 'Q', M, M, M, WORK( IR ), LDWRKR,$ WORK( ITAUQ ), WORK( IWORK ),$ LWORK-IWORK+1, IERR )IWORK = IE + M** Perform bidiagonal QR iteration, computing left* singular vectors of L in WORK(IR) and computing* right singular vectors of L in WORK(IU)* (Workspace: need 2*M*M+BDSPAC)*CALL DBDSQR( 'U', M, M, M, 0, S, WORK( IE ),$ WORK( IU ), LDWRKU, WORK( IR ),$ LDWRKR, DUM, 1, WORK( IWORK ), INFO )** Multiply right singular vectors of L in WORK(IU) by* Q in VT, storing result in A* (Workspace: need M*M)*CALL DGEMM( 'N', 'N', M, N, M, ONE, WORK( IU ),$ LDWRKU, VT, LDVT, ZERO, A, LDA )** Copy right singular vectors of A from A to VT*CALL DLACPY( 'F', M, N, A, LDA, VT, LDVT )** Copy left singular vectors of A from WORK(IR) to A*CALL DLACPY( 'F', M, M, WORK( IR ), LDWRKR, A,$ LDA )*ELSE** Insufficient workspace for a fast algorithm*ITAU = 1IWORK = ITAU + M** Compute A=L*Q, copying result to VT* (Workspace: need 2*M, prefer M+M*NB)*CALL DGELQF( M, N, A, LDA, WORK( ITAU ),$ WORK( IWORK ), LWORK-IWORK+1, IERR )CALL DLACPY( 'U', M, N, A, LDA, VT, LDVT )** Generate Q in VT* (Workspace: need M+N, prefer M+N*NB)*CALL DORGLQ( N, N, M, VT, LDVT, WORK( ITAU ),$ WORK( IWORK ), LWORK-IWORK+1, IERR )IE = ITAUITAUQ = IE + MITAUP = ITAUQ + MIWORK = ITAUP + M** Zero out above L in A*CALL DLASET( 'U', M-1, M-1, ZERO, ZERO, A( 1, 2 ),$ LDA )** Bidiagonalize L in A* (Workspace: need 4*M, prefer 3*M+2*M*NB)*CALL DGEBRD( M, M, A, LDA, S, WORK( IE ),$ WORK( ITAUQ ), WORK( ITAUP ),$ WORK( IWORK ), LWORK-IWORK+1, IERR )** Multiply right bidiagonalizing vectors in A by Q* in VT* (Workspace: need 3*M+N, prefer 3*M+N*NB)*CALL DORMBR( 'P', 'L', 'T', M, N, M, A, LDA,$ WORK( ITAUP ), VT, LDVT,$ WORK( IWORK ), LWORK-IWORK+1, IERR )** Generate left bidiagonalizing vectors in A* (Workspace: need 4*M, prefer 3*M+M*NB)*CALL DORGBR( 'Q', M, M, M, A, LDA, WORK( ITAUQ ),$ WORK( IWORK ), LWORK-IWORK+1, IERR )IWORK = IE + M** Perform bidiagonal QR iteration, computing left* singular vectors of A in A and computing right* singular vectors of A in VT* (Workspace: need BDSPAC)*CALL DBDSQR( 'U', M, N, M, 0, S, WORK( IE ), VT,$ LDVT, A, LDA, DUM, 1, WORK( IWORK ),$ INFO )*END IF*ELSE IF( WNTUAS ) THEN** Path 9t(N much larger than M, JOBU='S' or 'A',* JOBVT='A')* N right singular vectors to be computed in VT and* M left singular vectors to be computed in U*IF( LWORK.GE.M*M+MAX( N+M, 4*M, BDSPAC ) ) THEN** Sufficient workspace for a fast algorithm*IU = 1IF( LWORK.GE.WRKBL+LDA*M ) THEN** WORK(IU) is LDA by M*LDWRKU = LDAELSE** WORK(IU) is M by M*LDWRKU = MEND IFITAU = IU + LDWRKU*MIWORK = ITAU + M** Compute A=L*Q, copying result to VT* (Workspace: need M*M+2*M, prefer M*M+M+M*NB)*CALL DGELQF( M, N, A, LDA, WORK( ITAU ),$ WORK( IWORK ), LWORK-IWORK+1, IERR )CALL DLACPY( 'U', M, N, A, LDA, VT, LDVT )** Generate Q in VT* (Workspace: need M*M+M+N, prefer M*M+M+N*NB)*CALL DORGLQ( N, N, M, VT, LDVT, WORK( ITAU ),$ WORK( IWORK ), LWORK-IWORK+1, IERR )** Copy L to WORK(IU), zeroing out above it*CALL DLACPY( 'L', M, M, A, LDA, WORK( IU ),$ LDWRKU )CALL DLASET( 'U', M-1, M-1, ZERO, ZERO,$ WORK( IU+LDWRKU ), LDWRKU )IE = ITAUITAUQ = IE + MITAUP = ITAUQ + MIWORK = ITAUP + M** Bidiagonalize L in WORK(IU), copying result to U* (Workspace: need M*M+4*M, prefer M*M+3*M+2*M*NB)*CALL DGEBRD( M, M, WORK( IU ), LDWRKU, S,$ WORK( IE ), WORK( ITAUQ ),$ WORK( ITAUP ), WORK( IWORK ),$ LWORK-IWORK+1, IERR )CALL DLACPY( 'L', M, M, WORK( IU ), LDWRKU, U,$ LDU )** Generate right bidiagonalizing vectors in WORK(IU)* (Workspace: need M*M+4*M, prefer M*M+3*M+(M-1)*NB)*CALL DORGBR( 'P', M, M, M, WORK( IU ), LDWRKU,$ WORK( ITAUP ), WORK( IWORK ),$ LWORK-IWORK+1, IERR )** Generate left bidiagonalizing vectors in U* (Workspace: need M*M+4*M, prefer M*M+3*M+M*NB)*CALL DORGBR( 'Q', M, M, M, U, LDU, WORK( ITAUQ ),$ WORK( IWORK ), LWORK-IWORK+1, IERR )IWORK = IE + M** Perform bidiagonal QR iteration, computing left* singular vectors of L in U and computing right* singular vectors of L in WORK(IU)* (Workspace: need M*M+BDSPAC)*CALL DBDSQR( 'U', M, M, M, 0, S, WORK( IE ),$ WORK( IU ), LDWRKU, U, LDU, DUM, 1,$ WORK( IWORK ), INFO )** Multiply right singular vectors of L in WORK(IU) by* Q in VT, storing result in A* (Workspace: need M*M)*CALL DGEMM( 'N', 'N', M, N, M, ONE, WORK( IU ),$ LDWRKU, VT, LDVT, ZERO, A, LDA )** Copy right singular vectors of A from A to VT*CALL DLACPY( 'F', M, N, A, LDA, VT, LDVT )*ELSE** Insufficient workspace for a fast algorithm*ITAU = 1IWORK = ITAU + M** Compute A=L*Q, copying result to VT* (Workspace: need 2*M, prefer M+M*NB)*CALL DGELQF( M, N, A, LDA, WORK( ITAU ),$ WORK( IWORK ), LWORK-IWORK+1, IERR )CALL DLACPY( 'U', M, N, A, LDA, VT, LDVT )** Generate Q in VT* (Workspace: need M+N, prefer M+N*NB)*CALL DORGLQ( N, N, M, VT, LDVT, WORK( ITAU ),$ WORK( IWORK ), LWORK-IWORK+1, IERR )** Copy L to U, zeroing out above it*CALL DLACPY( 'L', M, M, A, LDA, U, LDU )CALL DLASET( 'U', M-1, M-1, ZERO, ZERO, U( 1, 2 ),$ LDU )IE = ITAUITAUQ = IE + MITAUP = ITAUQ + MIWORK = ITAUP + M** Bidiagonalize L in U* (Workspace: need 4*M, prefer 3*M+2*M*NB)*CALL DGEBRD( M, M, U, LDU, S, WORK( IE ),$ WORK( ITAUQ ), WORK( ITAUP ),$ WORK( IWORK ), LWORK-IWORK+1, IERR )** Multiply right bidiagonalizing vectors in U by Q* in VT* (Workspace: need 3*M+N, prefer 3*M+N*NB)*CALL DORMBR( 'P', 'L', 'T', M, N, M, U, LDU,$ WORK( ITAUP ), VT, LDVT,$ WORK( IWORK ), LWORK-IWORK+1, IERR )** Generate left bidiagonalizing vectors in U* (Workspace: need 4*M, prefer 3*M+M*NB)*CALL DORGBR( 'Q', M, M, M, U, LDU, WORK( ITAUQ ),$ WORK( IWORK ), LWORK-IWORK+1, IERR )IWORK = IE + M** Perform bidiagonal QR iteration, computing left* singular vectors of A in U and computing right* singular vectors of A in VT* (Workspace: need BDSPAC)*CALL DBDSQR( 'U', M, N, M, 0, S, WORK( IE ), VT,$ LDVT, U, LDU, DUM, 1, WORK( IWORK ),$ INFO )*END IF*END IF*END IF*ELSE** N .LT. MNTHR** Path 10t(N greater than M, but not much larger)* Reduce to bidiagonal form without LQ decomposition*IE = 1ITAUQ = IE + MITAUP = ITAUQ + MIWORK = ITAUP + M** Bidiagonalize A* (Workspace: need 3*M+N, prefer 3*M+(M+N)*NB)*CALL DGEBRD( M, N, A, LDA, S, WORK( IE ), WORK( ITAUQ ),$ WORK( ITAUP ), WORK( IWORK ), LWORK-IWORK+1,$ IERR )IF( WNTUAS ) THEN** If left singular vectors desired in U, copy result to U* and generate left bidiagonalizing vectors in U* (Workspace: need 4*M-1, prefer 3*M+(M-1)*NB)*CALL DLACPY( 'L', M, M, A, LDA, U, LDU )CALL DORGBR( 'Q', M, M, N, U, LDU, WORK( ITAUQ ),$ WORK( IWORK ), LWORK-IWORK+1, IERR )END IFIF( WNTVAS ) THEN** If right singular vectors desired in VT, copy result to* VT and generate right bidiagonalizing vectors in VT* (Workspace: need 3*M+NRVT, prefer 3*M+NRVT*NB)*CALL DLACPY( 'U', M, N, A, LDA, VT, LDVT )IF( WNTVA )$ NRVT = NIF( WNTVS )$ NRVT = MCALL DORGBR( 'P', NRVT, N, M, VT, LDVT, WORK( ITAUP ),$ WORK( IWORK ), LWORK-IWORK+1, IERR )END IFIF( WNTUO ) THEN** If left singular vectors desired in A, generate left* bidiagonalizing vectors in A* (Workspace: need 4*M-1, prefer 3*M+(M-1)*NB)*CALL DORGBR( 'Q', M, M, N, A, LDA, WORK( ITAUQ ),$ WORK( IWORK ), LWORK-IWORK+1, IERR )END IFIF( WNTVO ) THEN** If right singular vectors desired in A, generate right* bidiagonalizing vectors in A* (Workspace: need 4*M, prefer 3*M+M*NB)*CALL DORGBR( 'P', M, N, M, A, LDA, WORK( ITAUP ),$ WORK( IWORK ), LWORK-IWORK+1, IERR )END IFIWORK = IE + MIF( WNTUAS .OR. WNTUO )$ NRU = MIF( WNTUN )$ NRU = 0IF( WNTVAS .OR. WNTVO )$ NCVT = NIF( WNTVN )$ NCVT = 0IF( ( .NOT.WNTUO ) .AND. ( .NOT.WNTVO ) ) THEN** Perform bidiagonal QR iteration, if desired, computing* left singular vectors in U and computing right singular* vectors in VT* (Workspace: need BDSPAC)*CALL DBDSQR( 'L', M, NCVT, NRU, 0, S, WORK( IE ), VT,$ LDVT, U, LDU, DUM, 1, WORK( IWORK ), INFO )ELSE IF( ( .NOT.WNTUO ) .AND. WNTVO ) THEN** Perform bidiagonal QR iteration, if desired, computing* left singular vectors in U and computing right singular* vectors in A* (Workspace: need BDSPAC)*CALL DBDSQR( 'L', M, NCVT, NRU, 0, S, WORK( IE ), A, LDA,$ U, LDU, DUM, 1, WORK( IWORK ), INFO )ELSE** Perform bidiagonal QR iteration, if desired, computing* left singular vectors in A and computing right singular* vectors in VT* (Workspace: need BDSPAC)*CALL DBDSQR( 'L', M, NCVT, NRU, 0, S, WORK( IE ), VT,$ LDVT, A, LDA, DUM, 1, WORK( IWORK ), INFO )END IF*END IF*END IF** If DBDSQR failed to converge, copy unconverged superdiagonals* to WORK( 2:MINMN )*IF( INFO.NE.0 ) THENIF( IE.GT.2 ) THENDO 50 I = 1, MINMN - 1WORK( I+1 ) = WORK( I+IE-1 )50 CONTINUEEND IFIF( IE.LT.2 ) THENDO 60 I = MINMN - 1, 1, -1WORK( I+1 ) = WORK( I+IE-1 )60 CONTINUEEND IFEND IF** Undo scaling if necessary*IF( ISCL.EQ.1 ) THENIF( ANRM.GT.BIGNUM )$ CALL DLASCL( 'G', 0, 0, BIGNUM, ANRM, MINMN, 1, S, MINMN,$ IERR )IF( INFO.NE.0 .AND. ANRM.GT.BIGNUM )$ CALL DLASCL( 'G', 0, 0, BIGNUM, ANRM, MINMN-1, 1, WORK( 2 ),$ MINMN, IERR )IF( ANRM.LT.SMLNUM )$ CALL DLASCL( 'G', 0, 0, SMLNUM, ANRM, MINMN, 1, S, MINMN,$ IERR )IF( INFO.NE.0 .AND. ANRM.LT.SMLNUM )$ CALL DLASCL( 'G', 0, 0, SMLNUM, ANRM, MINMN-1, 1, WORK( 2 ),$ MINMN, IERR )END IF** Return optimal workspace in WORK(1)*WORK( 1 ) = MAXWRK*RETURN** End of DGESVD*ENDSUBROUTINE DGESVX( FACT, TRANS, N, NRHS, A, LDA, AF, LDAF, IPIV,$ EQUED, R, C, B, LDB, X, LDX, RCOND, FERR, BERR,$ WORK, IWORK, INFO )** -- LAPACK driver 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 EQUED, FACT, TRANSINTEGER INFO, LDA, LDAF, LDB, LDX, N, NRHSDOUBLE PRECISION RCOND* ..* .. Array Arguments ..INTEGER IPIV( * ), IWORK( * )DOUBLE PRECISION A( LDA, * ), AF( LDAF, * ), B( LDB, * ),$ BERR( * ), C( * ), FERR( * ), R( * ),$ WORK( * ), X( LDX, * )* ..** Purpose* =======** DGESVX uses the LU factorization to compute the solution to a real* system of linear equations* A * X = B,* where A is an N-by-N matrix and X and B are N-by-NRHS matrices.** Error bounds on the solution and a condition estimate are also* provided.** Description* ===========** The following steps are performed:** 1. If FACT = 'E', real scaling factors are computed to equilibrate* the system:* TRANS = 'N': diag(R)*A*diag(C) *inv(diag(C))*X = diag(R)*B* TRANS = 'T': (diag(R)*A*diag(C))**T *inv(diag(R))*X = diag(C)*B* TRANS = 'C': (diag(R)*A*diag(C))**H *inv(diag(R))*X = diag(C)*B* Whether or not the system will be equilibrated depends on the* scaling of the matrix A, but if equilibration is used, A is* overwritten by diag(R)*A*diag(C) and B by diag(R)*B (if TRANS='N')* or diag(C)*B (if TRANS = 'T' or 'C').** 2. If FACT = 'N' or 'E', the LU decomposition is used to factor the* matrix A (after equilibration if FACT = 'E') as* A = P * L * U,* where P is a permutation matrix, L is a unit lower triangular* matrix, and U is upper triangular.** 3. If some U(i,i)=0, so that U is exactly singular, 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.** 4. The system of equations is solved for X using the factored form* of A.** 5. Iterative refinement is applied to improve the computed solution* matrix and calculate error bounds and backward error estimates* for it.** 6. If equilibration was used, the matrix X is premultiplied by* diag(C) (if TRANS = 'N') or diag(R) (if TRANS = 'T' or 'C') so* that it solves the original system before equilibration.** Arguments* =========** FACT (input) CHARACTER*1* Specifies whether or not the factored form of the matrix A is* supplied on entry, and if not, whether the matrix A should be* equilibrated before it is factored.* = 'F': On entry, AF and IPIV contain the factored form of A.* If EQUED is not 'N', the matrix A has been* equilibrated with scaling factors given by R and C.* A, AF, and IPIV are not modified.* = 'N': The matrix A will be copied to AF and factored.* = 'E': The matrix A will be equilibrated if necessary, then* copied to AF and factored.** 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 (Transpose)** N (input) INTEGER* The number of linear equations, i.e., the order of the* matrix A. N >= 0.** NRHS (input) INTEGER* The number of right hand sides, i.e., the number of columns* of the matrices B and X. NRHS >= 0.** A (input/output) DOUBLE PRECISION array, dimension (LDA,N)* On entry, the N-by-N matrix A. If FACT = 'F' and EQUED is* not 'N', then A must have been equilibrated by the scaling* factors in R and/or C. A is not modified if FACT = 'F' or* 'N', or if FACT = 'E' and EQUED = 'N' on exit.** On exit, if EQUED .ne. 'N', A is scaled as follows:* EQUED = 'R': A := diag(R) * A* EQUED = 'C': A := A * diag(C)* EQUED = 'B': A := diag(R) * A * diag(C).** LDA (input) INTEGER* The leading dimension of the array A. LDA >= max(1,N).** AF (input or output) DOUBLE PRECISION array, dimension (LDAF,N)* If FACT = 'F', then AF is an input argument and on entry* contains the factors L and U from the factorization* A = P*L*U as computed by DGETRF. If EQUED .ne. 'N', then* AF is the factored form of the equilibrated matrix A.** If FACT = 'N', then AF is an output argument and on exit* returns the factors L and U from the factorization A = P*L*U* of the original matrix A.** If FACT = 'E', then AF is an output argument and on exit* returns the factors L and U from the factorization A = P*L*U* of the equilibrated matrix A (see the description of A for* the form of the equilibrated matrix).** LDAF (input) INTEGER* The leading dimension of the array AF. LDAF >= max(1,N).** IPIV (input or output) INTEGER array, dimension (N)* If FACT = 'F', then IPIV is an input argument and on entry* contains the pivot indices from the factorization A = P*L*U* as computed by DGETRF; row i of the matrix was interchanged* with row IPIV(i).** If FACT = 'N', then IPIV is an output argument and on exit* contains the pivot indices from the factorization A = P*L*U* of the original matrix A.** If FACT = 'E', then IPIV is an output argument and on exit* contains the pivot indices from the factorization A = P*L*U* of the equilibrated matrix A.** EQUED (input or output) CHARACTER*1* Specifies the form of equilibration that was done.* = 'N': No equilibration (always true if FACT = 'N').* = 'R': Row equilibration, i.e., A has been premultiplied by* diag(R).* = 'C': Column equilibration, i.e., A has been postmultiplied* by diag(C).* = 'B': Both row and column equilibration, i.e., A has been* replaced by diag(R) * A * diag(C).* EQUED is an input argument if FACT = 'F'; otherwise, it is an* output argument.** R (input or output) DOUBLE PRECISION array, dimension (N)* The row scale factors for A. If EQUED = 'R' or 'B', A is* multiplied on the left by diag(R); if EQUED = 'N' or 'C', R* is not accessed. R is an input argument if FACT = 'F';* otherwise, R is an output argument. If FACT = 'F' and* EQUED = 'R' or 'B', each element of R must be positive.** C (input or output) DOUBLE PRECISION array, dimension (N)* The column scale factors for A. If EQUED = 'C' or 'B', A is* multiplied on the right by diag(C); if EQUED = 'N' or 'R', C* is not accessed. C is an input argument if FACT = 'F';* otherwise, C is an output argument. If FACT = 'F' and* EQUED = 'C' or 'B', each element of C must be positive.** B (input/output) DOUBLE PRECISION array, dimension (LDB,NRHS)* On entry, the N-by-NRHS right hand side matrix B.* On exit,* if EQUED = 'N', B is not modified;* if TRANS = 'N' and EQUED = 'R' or 'B', B is overwritten by* diag(R)*B;* if TRANS = 'T' or 'C' and EQUED = 'C' or 'B', B is* overwritten by diag(C)*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 or INFO = N+1, the N-by-NRHS solution matrix X* to the original system of equations. Note that A and B are* modified on exit if EQUED .ne. 'N', and the solution to the* equilibrated system is inv(diag(C))*X if TRANS = 'N' and* EQUED = 'C' or 'B', or inv(diag(R))*X if TRANS = 'T' or 'C'* and EQUED = 'R' or 'B'.** LDX (input) INTEGER* The leading dimension of the array X. LDX >= max(1,N).** RCOND (output) DOUBLE PRECISION* The estimate of the reciprocal condition number of the matrix* A after equilibration (if done). 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 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/output) DOUBLE PRECISION array, dimension (4*N)* On exit, WORK(1) contains the reciprocal pivot growth* factor norm(A)/norm(U). The "max absolute element" norm is* used. If WORK(1) is much less than 1, then the stability* of the LU factorization of the (equilibrated) matrix A* could be poor. This also means that the solution X, condition* estimator RCOND, and forward error bound FERR could be* unreliable. If factorization fails with 0<INFO<=N, then* WORK(1) contains the reciprocal pivot growth factor for the* leading INFO columns of A.** IWORK (workspace) INTEGER 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, and i is* <= N: U(i,i) is exactly zero. The factorization has* been completed, but the factor U is exactly* singular, so the solution and error bounds* could not be 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 ZERO, ONEPARAMETER ( ZERO = 0.0D+0, ONE = 1.0D+0 )* ..* .. Local Scalars ..LOGICAL COLEQU, EQUIL, NOFACT, NOTRAN, ROWEQUCHARACTER NORMINTEGER I, INFEQU, JDOUBLE PRECISION AMAX, ANORM, BIGNUM, COLCND, RCMAX, RCMIN,$ ROWCND, RPVGRW, SMLNUM* ..* .. External Functions ..LOGICAL LSAMEDOUBLE PRECISION DLAMCH, DLANGE, DLANTREXTERNAL LSAME, DLAMCH, DLANGE, DLANTR* ..* .. External Subroutines ..EXTERNAL DGECON, DGEEQU, DGERFS, DGETRF, DGETRS, DLACPY,$ DLAQGE, XERBLA* ..* .. Intrinsic Functions ..INTRINSIC MAX, MIN* ..* .. Executable Statements ..*INFO = 0NOFACT = LSAME( FACT, 'N' )EQUIL = LSAME( FACT, 'E' )NOTRAN = LSAME( TRANS, 'N' )IF( NOFACT .OR. EQUIL ) THENEQUED = 'N'ROWEQU = .FALSE.COLEQU = .FALSE.ELSEROWEQU = LSAME( EQUED, 'R' ) .OR. LSAME( EQUED, 'B' )COLEQU = LSAME( EQUED, 'C' ) .OR. LSAME( EQUED, 'B' )SMLNUM = DLAMCH( 'Safe minimum' )BIGNUM = ONE / SMLNUMEND IF** Test the input parameters.*IF( .NOT.NOFACT .AND. .NOT.EQUIL .AND. .NOT.LSAME( FACT, 'F' ) )$ THENINFO = -1ELSE IF( .NOT.NOTRAN .AND. .NOT.LSAME( TRANS, 'T' ) .AND. .NOT.$ LSAME( TRANS, 'C' ) ) THENINFO = -2ELSE IF( N.LT.0 ) THENINFO = -3ELSE IF( NRHS.LT.0 ) THENINFO = -4ELSE IF( LDA.LT.MAX( 1, N ) ) THENINFO = -6ELSE IF( LDAF.LT.MAX( 1, N ) ) THENINFO = -8ELSE IF( LSAME( FACT, 'F' ) .AND. .NOT.$ ( ROWEQU .OR. COLEQU .OR. LSAME( EQUED, 'N' ) ) ) THENINFO = -10ELSEIF( ROWEQU ) THENRCMIN = BIGNUMRCMAX = ZERODO 10 J = 1, NRCMIN = MIN( RCMIN, R( J ) )RCMAX = MAX( RCMAX, R( J ) )10 CONTINUEIF( RCMIN.LE.ZERO ) THENINFO = -11ELSE IF( N.GT.0 ) THENROWCND = MAX( RCMIN, SMLNUM ) / MIN( RCMAX, BIGNUM )ELSEROWCND = ONEEND IFEND IFIF( COLEQU .AND. INFO.EQ.0 ) THENRCMIN = BIGNUMRCMAX = ZERODO 20 J = 1, NRCMIN = MIN( RCMIN, C( J ) )RCMAX = MAX( RCMAX, C( J ) )20 CONTINUEIF( RCMIN.LE.ZERO ) THENINFO = -12ELSE IF( N.GT.0 ) THENCOLCND = MAX( RCMIN, SMLNUM ) / MIN( RCMAX, BIGNUM )ELSECOLCND = ONEEND IFEND IFIF( INFO.EQ.0 ) THENIF( LDB.LT.MAX( 1, N ) ) THENINFO = -14ELSE IF( LDX.LT.MAX( 1, N ) ) THENINFO = -16END IFEND IFEND IF*IF( INFO.NE.0 ) THENCALL XERBLA( 'DGESVX', -INFO )RETURNEND IF*IF( EQUIL ) THEN** Compute row and column scalings to equilibrate the matrix A.*CALL DGEEQU( N, N, A, LDA, R, C, ROWCND, COLCND, AMAX, INFEQU )IF( INFEQU.EQ.0 ) THEN** Equilibrate the matrix.*CALL DLAQGE( N, N, A, LDA, R, C, ROWCND, COLCND, AMAX,$ EQUED )ROWEQU = LSAME( EQUED, 'R' ) .OR. LSAME( EQUED, 'B' )COLEQU = LSAME( EQUED, 'C' ) .OR. LSAME( EQUED, 'B' )END IFEND IF** Scale the right hand side.*IF( NOTRAN ) THENIF( ROWEQU ) THENDO 40 J = 1, NRHSDO 30 I = 1, NB( I, J ) = R( I )*B( I, J )30 CONTINUE40 CONTINUEEND IFELSE IF( COLEQU ) THENDO 60 J = 1, NRHSDO 50 I = 1, NB( I, J ) = C( I )*B( I, J )50 CONTINUE60 CONTINUEEND IF*IF( NOFACT .OR. EQUIL ) THEN** Compute the LU factorization of A.*CALL DLACPY( 'Full', N, N, A, LDA, AF, LDAF )CALL DGETRF( N, N, AF, LDAF, IPIV, INFO )** Return if INFO is non-zero.*IF( INFO.NE.0 ) THENIF( INFO.GT.0 ) THEN** Compute the reciprocal pivot growth factor of the* leading rank-deficient INFO columns of A.*RPVGRW = DLANTR( 'M', 'U', 'N', INFO, INFO, AF, LDAF,$ WORK )IF( RPVGRW.EQ.ZERO ) THENRPVGRW = ONEELSERPVGRW = DLANGE( 'M', N, INFO, A, LDA, WORK ) / RPVGRWEND IFWORK( 1 ) = RPVGRWRCOND = ZEROEND IFRETURNEND IFEND IF** Compute the norm of the matrix A and the* reciprocal pivot growth factor RPVGRW.*IF( NOTRAN ) THENNORM = '1'ELSENORM = 'I'END IFANORM = DLANGE( NORM, N, N, A, LDA, WORK )RPVGRW = DLANTR( 'M', 'U', 'N', N, N, AF, LDAF, WORK )IF( RPVGRW.EQ.ZERO ) THENRPVGRW = ONEELSERPVGRW = DLANGE( 'M', N, N, A, LDA, WORK ) / RPVGRWEND IF** Compute the reciprocal of the condition number of A.*CALL DGECON( NORM, N, AF, LDAF, ANORM, RCOND, WORK, IWORK, INFO )** Set INFO = N+1 if the matrix is singular to working precision.*IF( RCOND.LT.DLAMCH( 'Epsilon' ) )$ INFO = N + 1** Compute the solution matrix X.*CALL DLACPY( 'Full', N, NRHS, B, LDB, X, LDX )CALL DGETRS( TRANS, N, NRHS, AF, LDAF, IPIV, X, LDX, INFO )** Use iterative refinement to improve the computed solution and* compute error bounds and backward error estimates for it.*CALL DGERFS( TRANS, N, NRHS, A, LDA, AF, LDAF, IPIV, B, LDB, X,$ LDX, FERR, BERR, WORK, IWORK, INFO )** Transform the solution matrix X to a solution of the original* system.*IF( NOTRAN ) THENIF( COLEQU ) THENDO 80 J = 1, NRHSDO 70 I = 1, NX( I, J ) = C( I )*X( I, J )70 CONTINUE80 CONTINUEDO 90 J = 1, NRHSFERR( J ) = FERR( J ) / COLCND90 CONTINUEEND IFELSE IF( ROWEQU ) THENDO 110 J = 1, NRHSDO 100 I = 1, NX( I, J ) = R( I )*X( I, J )100 CONTINUE110 CONTINUEDO 120 J = 1, NRHSFERR( J ) = FERR( J ) / ROWCND120 CONTINUEEND IF*WORK( 1 ) = RPVGRWRETURN** End of DGESVX*ENDSUBROUTINE DGGES( JOBVSL, JOBVSR, SORT, DELCTG, N, A, LDA, B, LDB,$ SDIM, ALPHAR, ALPHAI, BETA, VSL, LDVSL, VSR,$ LDVSR, WORK, LWORK, BWORK, INFO )** -- LAPACK driver 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 JOBVSL, JOBVSR, SORTINTEGER INFO, LDA, LDB, LDVSL, LDVSR, LWORK, N, SDIM* ..* .. Array Arguments ..LOGICAL BWORK( * )DOUBLE PRECISION A( LDA, * ), ALPHAI( * ), ALPHAR( * ),$ B( LDB, * ), BETA( * ), VSL( LDVSL, * ),$ VSR( LDVSR, * ), WORK( * )* ..* .. Function Arguments ..LOGICAL DELCTGEXTERNAL DELCTG* ..** Purpose* =======** DGGES computes for a pair of N-by-N real nonsymmetric matrices (A,B),* the generalized eigenvalues, the generalized real Schur form (S,T),* optionally, the left and/or right matrices of Schur vectors (VSL and* VSR). This gives the generalized Schur factorization** (A,B) = ( (VSL)*S*(VSR)**T, (VSL)*T*(VSR)**T )** Optionally, it also orders the eigenvalues so that a selected cluster* of eigenvalues appears in the leading diagonal blocks of the upper* quasi-triangular matrix S and the upper triangular matrix T.The* leading columns of VSL and VSR then form an orthonormal basis for the* corresponding left and right eigenspaces (deflating subspaces).** (If only the generalized eigenvalues are needed, use the driver* DGGEV instead, which is faster.)** A generalized eigenvalue for a pair of matrices (A,B) is a scalar w* or a ratio alpha/beta = w, such that A - w*B is singular. It is* usually represented as the pair (alpha,beta), as there is a* reasonable interpretation for beta=0 or both being zero.** A pair of matrices (S,T) is in generalized real Schur form if T is* upper triangular with non-negative diagonal and S is block upper* triangular with 1-by-1 and 2-by-2 blocks. 1-by-1 blocks correspond* to real generalized eigenvalues, while 2-by-2 blocks of S will be* "standardized" by making the corresponding elements of T have the* form:* [ a 0 ]* [ 0 b ]** and the pair of corresponding 2-by-2 blocks in S and T will have a* complex conjugate pair of generalized eigenvalues.*** Arguments* =========** JOBVSL (input) CHARACTER*1* = 'N': do not compute the left Schur vectors;* = 'V': compute the left Schur vectors.** JOBVSR (input) CHARACTER*1* = 'N': do not compute the right Schur vectors;* = 'V': compute the right Schur vectors.** SORT (input) CHARACTER*1* Specifies whether or not to order the eigenvalues on the* diagonal of the generalized Schur form.* = 'N': Eigenvalues are not ordered;* = 'S': Eigenvalues are ordered (see DELZTG);** DELZTG (input) LOGICAL FUNCTION of three DOUBLE PRECISION arguments* DELZTG must be declared EXTERNAL in the calling subroutine.* If SORT = 'N', DELZTG is not referenced.* If SORT = 'S', DELZTG is used to select eigenvalues to sort* to the top left of the Schur form.* An eigenvalue (ALPHAR(j)+ALPHAI(j))/BETA(j) is selected if* DELZTG(ALPHAR(j),ALPHAI(j),BETA(j)) is true; i.e. if either* one of a complex conjugate pair of eigenvalues is selected,* then both complex eigenvalues are selected.** Note that in the ill-conditioned case, a selected complex* eigenvalue may no longer satisfy DELZTG(ALPHAR(j),ALPHAI(j),* BETA(j)) = .TRUE. after ordering. INFO is to be set to N+2* in this case.** N (input) INTEGER* The order of the matrices A, B, VSL, and VSR. N >= 0.** A (input/output) DOUBLE PRECISION array, dimension (LDA, N)* On entry, the first of the pair of matrices.* On exit, A has been overwritten by its generalized Schur* form S.** LDA (input) INTEGER* The leading dimension of A. LDA >= max(1,N).** B (input/output) DOUBLE PRECISION array, dimension (LDB, N)* On entry, the second of the pair of matrices.* On exit, B has been overwritten by its generalized Schur* form T.** LDB (input) INTEGER* The leading dimension of B. LDB >= max(1,N).** SDIM (output) INTEGER* If SORT = 'N', SDIM = 0.* If SORT = 'S', SDIM = number of eigenvalues (after sorting)* for which DELZTG is true. (Complex conjugate pairs for which* DELZTG is true for either eigenvalue count as 2.)** 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 Schur form of (A,B) were further reduced to* triangular form using 2-by-2 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.** Note: the quotients ALPHAR(j)/BETA(j) and ALPHAI(j)/BETA(j)* may easily over- or underflow, and BETA(j) may even be zero.* Thus, the user should avoid naively computing the ratio.* However, ALPHAR and ALPHAI will be always less than and* usually comparable with norm(A) in magnitude, and BETA always* less than and usually comparable with norm(B).** VSL (output) DOUBLE PRECISION array, dimension (LDVSL,N)* If JOBVSL = 'V', VSL will contain the left Schur vectors.* Not referenced if JOBVSL = 'N'.** LDVSL (input) INTEGER* The leading dimension of the matrix VSL. LDVSL >=1, and* if JOBVSL = 'V', LDVSL >= N.** VSR (output) DOUBLE PRECISION array, dimension (LDVSR,N)* If JOBVSR = 'V', VSR will contain the right Schur vectors.* Not referenced if JOBVSR = 'N'.** LDVSR (input) INTEGER* The leading dimension of the matrix VSR. LDVSR >= 1, and* if JOBVSR = 'V', LDVSR >= 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 >= 8*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.** BWORK (workspace) LOGICAL array, dimension (N)* Not referenced if SORT = 'N'.** INFO (output) INTEGER* = 0: successful exit* < 0: if INFO = -i, the i-th argument had an illegal value.* = 1,...,N:* The QZ iteration failed. (A,B) are not in Schur* form, but ALPHAR(j), ALPHAI(j), and BETA(j) should* be correct for j=INFO+1,...,N.* > N: =N+1: other than QZ iteration failed in DHGEQZ.* =N+2: after reordering, roundoff changed values of* some complex eigenvalues so that leading* eigenvalues in the Generalized Schur form no* longer satisfy DELZTG=.TRUE. This could also* be caused due to scaling.* =N+3: reordering failed in DTGSEN.** =====================================================================** .. Parameters ..DOUBLE PRECISION ZERO, ONEPARAMETER ( ZERO = 0.0D+0, ONE = 1.0D+0 )* ..* .. Local Scalars ..LOGICAL CURSL, ILASCL, ILBSCL, ILVSL, ILVSR, LASTSL,$ LQUERY, LST2SL, WANTSTINTEGER I, ICOLS, IERR, IHI, IJOBVL, IJOBVR, ILEFT,$ ILO, IP, IRIGHT, IROWS, ITAU, IWRK, MAXWRK,$ MINWRKDOUBLE PRECISION ANRM, ANRMTO, BIGNUM, BNRM, BNRMTO, EPS, PVSL,$ PVSR, SAFMAX, SAFMIN, SMLNUM* ..* .. Local Arrays ..INTEGER IDUM( 1 )DOUBLE PRECISION DIF( 2 )* ..* .. External Subroutines ..EXTERNAL DGEQRF, DGGBAK, DGGBAL, DGGHRD, DHGEQZ, DLABAD,$ DLACPY, DLASCL, DLASET, DORGQR, DORMQR, DTGSEN,$ XERBLA* ..* .. External Functions ..LOGICAL LSAMEINTEGER ILAENVDOUBLE PRECISION DLAMCH, DLANGEEXTERNAL LSAME, ILAENV, DLAMCH, DLANGE* ..* .. Intrinsic Functions ..INTRINSIC ABS, MAX, SQRT* ..* .. Executable Statements ..** Decode the input arguments*IF( LSAME( JOBVSL, 'N' ) ) THENIJOBVL = 1ILVSL = .FALSE.ELSE IF( LSAME( JOBVSL, 'V' ) ) THENIJOBVL = 2ILVSL = .TRUE.ELSEIJOBVL = -1ILVSL = .FALSE.END IF*IF( LSAME( JOBVSR, 'N' ) ) THENIJOBVR = 1ILVSR = .FALSE.ELSE IF( LSAME( JOBVSR, 'V' ) ) THENIJOBVR = 2ILVSR = .TRUE.ELSEIJOBVR = -1ILVSR = .FALSE.END IF*WANTST = LSAME( SORT, 'S' )** Test the input arguments*INFO = 0LQUERY = ( LWORK.EQ.-1 )IF( IJOBVL.LE.0 ) THENINFO = -1ELSE IF( IJOBVR.LE.0 ) THENINFO = -2ELSE IF( ( .NOT.WANTST ) .AND. ( .NOT.LSAME( SORT, 'N' ) ) ) THENINFO = -3ELSE IF( N.LT.0 ) THENINFO = -5ELSE IF( LDA.LT.MAX( 1, N ) ) THENINFO = -7ELSE IF( LDB.LT.MAX( 1, N ) ) THENINFO = -9ELSE IF( LDVSL.LT.1 .OR. ( ILVSL .AND. LDVSL.LT.N ) ) THENINFO = -15ELSE IF( LDVSR.LT.1 .OR. ( ILVSR .AND. LDVSR.LT.N ) ) THENINFO = -17END IF** Compute workspace* (Note: Comments in the code beginning "Workspace:" describe the* minimal amount of workspace needed at that point in the code,* as well as the preferred amount for good performance.* NB refers to the optimal block size for the immediately* following subroutine, as returned by ILAENV.)*MINWRK = 1IF( INFO.EQ.0 .AND. ( LWORK.GE.1 .OR. LQUERY ) ) THENMINWRK = 7*( N+1 ) + 16MAXWRK = 7*( N+1 ) + N*ILAENV( 1, 'DGEQRF', ' ', N, 1, N, 0 ) +$ 16IF( ILVSL ) THENMAXWRK = MAX( MAXWRK, 7*( N+1 )+N*$ ILAENV( 1, 'DORGQR', ' ', N, 1, N, -1 ) )END IFWORK( 1 ) = MAXWRKEND IF*IF( LWORK.LT.MINWRK .AND. .NOT.LQUERY )$ INFO = -19IF( INFO.NE.0 ) THENCALL XERBLA( 'DGGES ', -INFO )RETURNELSE IF( LQUERY ) THENRETURNEND IF** Quick return if possible*IF( N.EQ.0 ) THENSDIM = 0RETURNEND IF** Get machine constants*EPS = DLAMCH( 'P' )SAFMIN = DLAMCH( 'S' )SAFMAX = ONE / SAFMINCALL DLABAD( SAFMIN, SAFMAX )SMLNUM = SQRT( SAFMIN ) / EPSBIGNUM = ONE / SMLNUM** Scale A if max element outside range [SMLNUM,BIGNUM]*ANRM = DLANGE( 'M', N, N, A, LDA, WORK )ILASCL = .FALSE.IF( ANRM.GT.ZERO .AND. ANRM.LT.SMLNUM ) THENANRMTO = SMLNUMILASCL = .TRUE.ELSE IF( ANRM.GT.BIGNUM ) THENANRMTO = BIGNUMILASCL = .TRUE.END IFIF( ILASCL )$ CALL DLASCL( 'G', 0, 0, ANRM, ANRMTO, N, N, A, LDA, IERR )** Scale B if max element outside range [SMLNUM,BIGNUM]*BNRM = DLANGE( 'M', N, N, B, LDB, WORK )ILBSCL = .FALSE.IF( BNRM.GT.ZERO .AND. BNRM.LT.SMLNUM ) THENBNRMTO = SMLNUMILBSCL = .TRUE.ELSE IF( BNRM.GT.BIGNUM ) THENBNRMTO = BIGNUMILBSCL = .TRUE.END IFIF( ILBSCL )$ CALL DLASCL( 'G', 0, 0, BNRM, BNRMTO, N, N, B, LDB, IERR )** Permute the matrix to make it more nearly triangular* (Workspace: need 6*N + 2*N space for storing balancing factors)*ILEFT = 1IRIGHT = N + 1IWRK = IRIGHT + NCALL DGGBAL( 'P', N, A, LDA, B, LDB, ILO, IHI, WORK( ILEFT ),$ WORK( IRIGHT ), WORK( IWRK ), IERR )** Reduce B to triangular form (QR decomposition of B)* (Workspace: need N, prefer N*NB)*IROWS = IHI + 1 - ILOICOLS = N + 1 - ILOITAU = IWRKIWRK = ITAU + IROWSCALL DGEQRF( IROWS, ICOLS, B( ILO, ILO ), LDB, WORK( ITAU ),$ WORK( IWRK ), LWORK+1-IWRK, IERR )** Apply the orthogonal transformation to matrix A* (Workspace: need N, prefer N*NB)*CALL DORMQR( 'L', 'T', IROWS, ICOLS, IROWS, B( ILO, ILO ), LDB,$ WORK( ITAU ), A( ILO, ILO ), LDA, WORK( IWRK ),$ LWORK+1-IWRK, IERR )** Initialize VSL* (Workspace: need N, prefer N*NB)*IF( ILVSL ) THENCALL DLASET( 'Full', N, N, ZERO, ONE, VSL, LDVSL )CALL DLACPY( 'L', IROWS-1, IROWS-1, B( ILO+1, ILO ), LDB,$ VSL( ILO+1, ILO ), LDVSL )CALL DORGQR( IROWS, IROWS, IROWS, VSL( ILO, ILO ), LDVSL,$ WORK( ITAU ), WORK( IWRK ), LWORK+1-IWRK, IERR )END IF** Initialize VSR*IF( ILVSR )$ CALL DLASET( 'Full', N, N, ZERO, ONE, VSR, LDVSR )** Reduce to generalized Hessenberg form* (Workspace: none needed)*CALL DGGHRD( JOBVSL, JOBVSR, N, ILO, IHI, A, LDA, B, LDB, VSL,$ LDVSL, VSR, LDVSR, IERR )** Perform QZ algorithm, computing Schur vectors if desired* (Workspace: need N)*IWRK = ITAUCALL DHGEQZ( 'S', JOBVSL, JOBVSR, N, ILO, IHI, A, LDA, B, LDB,$ ALPHAR, ALPHAI, BETA, VSL, LDVSL, VSR, LDVSR,$ WORK( IWRK ), LWORK+1-IWRK, IERR )IF( IERR.NE.0 ) THENIF( IERR.GT.0 .AND. IERR.LE.N ) THENINFO = IERRELSE IF( IERR.GT.N .AND. IERR.LE.2*N ) THENINFO = IERR - NELSEINFO = N + 1END IFGO TO 50END IF** Sort eigenvalues ALPHA/BETA if desired* (Workspace: need 4*N+16 )*SDIM = 0IF( WANTST ) THEN** Undo scaling on eigenvalues before DELZTGing*IF( ILASCL ) THENCALL DLASCL( 'G', 0, 0, ANRMTO, ANRM, N, 1, ALPHAR, N,$ IERR )CALL DLASCL( 'G', 0, 0, ANRMTO, ANRM, N, 1, ALPHAI, N,$ IERR )END IFIF( ILBSCL )$ CALL DLASCL( 'G', 0, 0, BNRMTO, BNRM, N, 1, BETA, N, IERR )** Select eigenvalues*DO 10 I = 1, NBWORK( I ) = DELCTG( ALPHAR( I ), ALPHAI( I ), BETA( I ) )10 CONTINUE*CALL DTGSEN( 0, ILVSL, ILVSR, BWORK, N, A, LDA, B, LDB, ALPHAR,$ ALPHAI, BETA, VSL, LDVSL, VSR, LDVSR, SDIM, PVSL,$ PVSR, DIF, WORK( IWRK ), LWORK-IWRK+1, IDUM, 1,$ IERR )IF( IERR.EQ.1 )$ INFO = N + 3*END IF** Apply back-permutation to VSL and VSR* (Workspace: none needed)*IF( ILVSL )$ CALL DGGBAK( 'P', 'L', N, ILO, IHI, WORK( ILEFT ),$ WORK( IRIGHT ), N, VSL, LDVSL, IERR )*IF( ILVSR )$ CALL DGGBAK( 'P', 'R', N, ILO, IHI, WORK( ILEFT ),$ WORK( IRIGHT ), N, VSR, LDVSR, IERR )** Check if unscaling would cause over/underflow, if so, rescale* (ALPHAR(I),ALPHAI(I),BETA(I)) so BETA(I) is on the order of* B(I,I) and ALPHAR(I) and ALPHAI(I) are on the order of A(I,I)*IF( ILASCL ) THENDO 20 I = 1, NIF( ALPHAI( I ).NE.ZERO ) THENIF( ( ALPHAR( I ) / SAFMAX ).GT.( ANRMTO / ANRM ) .OR.$ ( SAFMIN / ALPHAR( I ) ).GT.( ANRM / ANRMTO ) ) THENWORK( 1 ) = ABS( A( I, I ) / ALPHAR( I ) )BETA( I ) = BETA( I )*WORK( 1 )ALPHAR( I ) = ALPHAR( I )*WORK( 1 )ALPHAI( I ) = ALPHAI( I )*WORK( 1 )ELSE IF( ( ALPHAI( I ) / SAFMAX ).GT.$ ( ANRMTO / ANRM ) .OR.$ ( SAFMIN / ALPHAI( I ) ).GT.( ANRM / ANRMTO ) )$ THENWORK( 1 ) = ABS( A( I, I+1 ) / ALPHAI( I ) )BETA( I ) = BETA( I )*WORK( 1 )ALPHAR( I ) = ALPHAR( I )*WORK( 1 )ALPHAI( I ) = ALPHAI( I )*WORK( 1 )END IFEND IF20 CONTINUEEND IF*IF( ILBSCL ) THENDO 30 I = 1, NIF( ALPHAI( I ).NE.ZERO ) THENIF( ( BETA( I ) / SAFMAX ).GT.( BNRMTO / BNRM ) .OR.$ ( SAFMIN / BETA( I ) ).GT.( BNRM / BNRMTO ) ) THENWORK( 1 ) = ABS( B( I, I ) / BETA( I ) )BETA( I ) = BETA( I )*WORK( 1 )ALPHAR( I ) = ALPHAR( I )*WORK( 1 )ALPHAI( I ) = ALPHAI( I )*WORK( 1 )END IFEND IF30 CONTINUEEND IF** Undo scaling*IF( ILASCL ) THENCALL DLASCL( 'H', 0, 0, ANRMTO, ANRM, N, N, A, LDA, IERR )CALL DLASCL( 'G', 0, 0, ANRMTO, ANRM, N, 1, ALPHAR, N, IERR )CALL DLASCL( 'G', 0, 0, ANRMTO, ANRM, N, 1, ALPHAI, N, IERR )END IF*IF( ILBSCL ) THENCALL DLASCL( 'U', 0, 0, BNRMTO, BNRM, N, N, B, LDB, IERR )CALL DLASCL( 'G', 0, 0, BNRMTO, BNRM, N, 1, BETA, N, IERR )END IF*IF( WANTST ) THEN** Check if reordering is correct*LASTSL = .TRUE.LST2SL = .TRUE.SDIM = 0IP = 0DO 40 I = 1, NCURSL = DELCTG( ALPHAR( I ), ALPHAI( I ), BETA( I ) )IF( ALPHAI( I ).EQ.ZERO ) THENIF( CURSL )$ SDIM = SDIM + 1IP = 0IF( CURSL .AND. .NOT.LASTSL )$ INFO = N + 2ELSEIF( IP.EQ.1 ) THEN** Last eigenvalue of conjugate pair*CURSL = CURSL .OR. LASTSLLASTSL = CURSLIF( CURSL )$ SDIM = SDIM + 2IP = -1IF( CURSL .AND. .NOT.LST2SL )$ INFO = N + 2ELSE** First eigenvalue of conjugate pair*IP = 1END IFEND IFLST2SL = LASTSLLASTSL = CURSL40 CONTINUE*END IF*50 CONTINUE*WORK( 1 ) = MAXWRK*RETURN** End of DGGES*ENDSUBROUTINE DGGESX( JOBVSL, JOBVSR, SORT, DELCTG, SENSE, N, A, LDA,$ B, LDB, SDIM, ALPHAR, ALPHAI, BETA, VSL, LDVSL,$ VSR, LDVSR, RCONDE, RCONDV, WORK, LWORK, IWORK,$ LIWORK, BWORK, INFO )** -- LAPACK driver 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 JOBVSL, JOBVSR, SENSE, SORTINTEGER INFO, LDA, LDB, LDVSL, LDVSR, LIWORK, LWORK, N,$ SDIM* ..* .. Array Arguments ..LOGICAL BWORK( * )INTEGER IWORK( * )DOUBLE PRECISION A( LDA, * ), ALPHAI( * ), ALPHAR( * ),$ B( LDB, * ), BETA( * ), RCONDE( 2 ),$ RCONDV( 2 ), VSL( LDVSL, * ), VSR( LDVSR, * ),$ WORK( * )* ..* .. Function Arguments ..LOGICAL DELCTGEXTERNAL DELCTG* ..** Purpose* =======** DGGESX computes for a pair of N-by-N real nonsymmetric matrices* (A,B), the generalized eigenvalues, the real Schur form (S,T), and,* optionally, the left and/or right matrices of Schur vectors (VSL and* VSR). This gives the generalized Schur factorization** (A,B) = ( (VSL) S (VSR)**T, (VSL) T (VSR)**T )** Optionally, it also orders the eigenvalues so that a selected cluster* of eigenvalues appears in the leading diagonal blocks of the upper* quasi-triangular matrix S and the upper triangular matrix T; computes* a reciprocal condition number for the average of the selected* eigenvalues (RCONDE); and computes a reciprocal condition number for* the right and left deflating subspaces corresponding to the selected* eigenvalues (RCONDV). The leading columns of VSL and VSR then form* an orthonormal basis for the corresponding left and right eigenspaces* (deflating subspaces).** A generalized eigenvalue for a pair of matrices (A,B) is a scalar w* or a ratio alpha/beta = w, such that A - w*B is singular. It is* usually represented as the pair (alpha,beta), as there is a* reasonable interpretation for beta=0 or for both being zero.** A pair of matrices (S,T) is in generalized real Schur form if T is* upper triangular with non-negative diagonal and S is block upper* triangular with 1-by-1 and 2-by-2 blocks. 1-by-1 blocks correspond* to real generalized eigenvalues, while 2-by-2 blocks of S will be* "standardized" by making the corresponding elements of T have the* form:* [ a 0 ]* [ 0 b ]** and the pair of corresponding 2-by-2 blocks in S and T will have a* complex conjugate pair of generalized eigenvalues.*** Arguments* =========** JOBVSL (input) CHARACTER*1* = 'N': do not compute the left Schur vectors;* = 'V': compute the left Schur vectors.** JOBVSR (input) CHARACTER*1* = 'N': do not compute the right Schur vectors;* = 'V': compute the right Schur vectors.** SORT (input) CHARACTER*1* Specifies whether or not to order the eigenvalues on the* diagonal of the generalized Schur form.* = 'N': Eigenvalues are not ordered;* = 'S': Eigenvalues are ordered (see DELZTG).** DELZTG (input) LOGICAL FUNCTION of three DOUBLE PRECISION arguments* DELZTG must be declared EXTERNAL in the calling subroutine.* If SORT = 'N', DELZTG is not referenced.* If SORT = 'S', DELZTG is used to select eigenvalues to sort* to the top left of the Schur form.* An eigenvalue (ALPHAR(j)+ALPHAI(j))/BETA(j) is selected if* DELZTG(ALPHAR(j),ALPHAI(j),BETA(j)) is true; i.e. if either* one of a complex conjugate pair of eigenvalues is selected,* then both complex eigenvalues are selected.* Note that a selected complex eigenvalue may no longer satisfy* DELZTG(ALPHAR(j),ALPHAI(j),BETA(j)) = .TRUE. after ordering,* since ordering may change the value of complex eigenvalues* (especially if the eigenvalue is ill-conditioned), in this* case INFO is set to N+3.** SENSE (input) CHARACTER* Determines which reciprocal condition numbers are computed.* = 'N' : None are computed;* = 'E' : Computed for average of selected eigenvalues only;* = 'V' : Computed for selected deflating subspaces only;* = 'B' : Computed for both.* If SENSE = 'E', 'V', or 'B', SORT must equal 'S'.** N (input) INTEGER* The order of the matrices A, B, VSL, and VSR. N >= 0.** A (input/output) DOUBLE PRECISION array, dimension (LDA, N)* On entry, the first of the pair of matrices.* On exit, A has been overwritten by its generalized Schur* form S.** LDA (input) INTEGER* The leading dimension of A. LDA >= max(1,N).** B (input/output) DOUBLE PRECISION array, dimension (LDB, N)* On entry, the second of the pair of matrices.* On exit, B has been overwritten by its generalized Schur* form T.** LDB (input) INTEGER* The leading dimension of B. LDB >= max(1,N).** SDIM (output) INTEGER* If SORT = 'N', SDIM = 0.* If SORT = 'S', SDIM = number of eigenvalues (after sorting)* for which DELZTG is true. (Complex conjugate pairs for which* DELZTG is true for either eigenvalue count as 2.)** 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 Schur form of (A,B) were further reduced to* triangular form using 2-by-2 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.** Note: the quotients ALPHAR(j)/BETA(j) and ALPHAI(j)/BETA(j)* may easily over- or underflow, and BETA(j) may even be zero.* Thus, the user should avoid naively computing the ratio.* However, ALPHAR and ALPHAI will be always less than and* usually comparable with norm(A) in magnitude, and BETA always* less than and usually comparable with norm(B).** VSL (output) DOUBLE PRECISION array, dimension (LDVSL,N)* If JOBVSL = 'V', VSL will contain the left Schur vectors.* Not referenced if JOBVSL = 'N'.** LDVSL (input) INTEGER* The leading dimension of the matrix VSL. LDVSL >=1, and* if JOBVSL = 'V', LDVSL >= N.** VSR (output) DOUBLE PRECISION array, dimension (LDVSR,N)* If JOBVSR = 'V', VSR will contain the right Schur vectors.* Not referenced if JOBVSR = 'N'.** LDVSR (input) INTEGER* The leading dimension of the matrix VSR. LDVSR >= 1, and* if JOBVSR = 'V', LDVSR >= N.** RCONDE (output) DOUBLE PRECISION array, dimension ( 2 )* If SENSE = 'E' or 'B', RCONDE(1) and RCONDE(2) contain the* reciprocal condition numbers for the average of the selected* eigenvalues.* Not referenced if SENSE = 'N' or 'V'.** RCONDV (output) DOUBLE PRECISION array, dimension ( 2 )* If SENSE = 'V' or 'B', RCONDV(1) and RCONDV(2) contain the* reciprocal condition numbers for the selected deflating* subspaces.* Not referenced if SENSE = 'N' or 'E'.** 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 >= 8*(N+1)+16.* If SENSE = 'E', 'V', or 'B',* LWORK >= MAX( 8*(N+1)+16, 2*SDIM*(N-SDIM) ).** IWORK (workspace) INTEGER array, dimension (LIWORK)* Not referenced if SENSE = 'N'.** LIWORK (input) INTEGER* The dimension of the array WORK. LIWORK >= N+6.** BWORK (workspace) LOGICAL array, dimension (N)* Not referenced if SORT = 'N'.** INFO (output) INTEGER* = 0: successful exit* < 0: if INFO = -i, the i-th argument had an illegal value.* = 1,...,N:* The QZ iteration failed. (A,B) are not in Schur* form, but ALPHAR(j), ALPHAI(j), and BETA(j) should* be correct for j=INFO+1,...,N.* > N: =N+1: other than QZ iteration failed in DHGEQZ* =N+2: after reordering, roundoff changed values of* some complex eigenvalues so that leading* eigenvalues in the Generalized Schur form no* longer satisfy DELZTG=.TRUE. This could also* be caused due to scaling.* =N+3: reordering failed in DTGSEN.** Further details* ===============** An approximate (asymptotic) bound on the average absolute error of* the selected eigenvalues is** EPS * norm((A, B)) / RCONDE( 1 ).** An approximate (asymptotic) bound on the maximum angular error in* the computed deflating subspaces is** EPS * norm((A, B)) / RCONDV( 2 ).** See LAPACK User's Guide, section 4.11 for more information.** =====================================================================** .. Parameters ..DOUBLE PRECISION ZERO, ONEPARAMETER ( ZERO = 0.0D+0, ONE = 1.0D+0 )* ..* .. Local Scalars ..LOGICAL CURSL, ILASCL, ILBSCL, ILVSL, ILVSR, LASTSL,$ LST2SL, WANTSB, WANTSE, WANTSN, WANTST, WANTSVINTEGER I, ICOLS, IERR, IHI, IJOB, IJOBVL, IJOBVR,$ ILEFT, ILO, IP, IRIGHT, IROWS, ITAU, IWRK,$ LIWMIN, MAXWRK, MINWRKDOUBLE PRECISION ANRM, ANRMTO, BIGNUM, BNRM, BNRMTO, EPS, PL,$ PR, SAFMAX, SAFMIN, SMLNUM* ..* .. Local Arrays ..DOUBLE PRECISION DIF( 2 )* ..* .. External Subroutines ..EXTERNAL DGEQRF, DGGBAK, DGGBAL, DGGHRD, DHGEQZ, DLABAD,$ DLACPY, DLASCL, DLASET, DORGQR, DORMQR, DTGSEN,$ XERBLA* ..* .. External Functions ..LOGICAL LSAMEINTEGER ILAENVDOUBLE PRECISION DLAMCH, DLANGEEXTERNAL LSAME, ILAENV, DLAMCH, DLANGE* ..* .. Intrinsic Functions ..INTRINSIC ABS, MAX, SQRT* ..* .. Executable Statements ..** Decode the input arguments*IF( LSAME( JOBVSL, 'N' ) ) THENIJOBVL = 1ILVSL = .FALSE.ELSE IF( LSAME( JOBVSL, 'V' ) ) THENIJOBVL = 2ILVSL = .TRUE.ELSEIJOBVL = -1ILVSL = .FALSE.END IF*IF( LSAME( JOBVSR, 'N' ) ) THENIJOBVR = 1ILVSR = .FALSE.ELSE IF( LSAME( JOBVSR, 'V' ) ) THENIJOBVR = 2ILVSR = .TRUE.ELSEIJOBVR = -1ILVSR = .FALSE.END IF*WANTST = LSAME( SORT, 'S' )WANTSN = LSAME( SENSE, 'N' )WANTSE = LSAME( SENSE, 'E' )WANTSV = LSAME( SENSE, 'V' )WANTSB = LSAME( SENSE, 'B' )IF( WANTSN ) THENIJOB = 0IWORK( 1 ) = 1ELSE IF( WANTSE ) THENIJOB = 1ELSE IF( WANTSV ) THENIJOB = 2ELSE IF( WANTSB ) THENIJOB = 4END IF** Test the input arguments*INFO = 0IF( IJOBVL.LE.0 ) THENINFO = -1ELSE IF( IJOBVR.LE.0 ) THENINFO = -2ELSE IF( ( .NOT.WANTST ) .AND. ( .NOT.LSAME( SORT, 'N' ) ) ) THENINFO = -3ELSE IF( .NOT.( WANTSN .OR. WANTSE .OR. WANTSV .OR. WANTSB ) .OR.$ ( .NOT.WANTST .AND. .NOT.WANTSN ) ) THENINFO = -5ELSE IF( N.LT.0 ) THENINFO = -6ELSE IF( LDA.LT.MAX( 1, N ) ) THENINFO = -8ELSE IF( LDB.LT.MAX( 1, N ) ) THENINFO = -10ELSE IF( LDVSL.LT.1 .OR. ( ILVSL .AND. LDVSL.LT.N ) ) THENINFO = -16ELSE IF( LDVSR.LT.1 .OR. ( ILVSR .AND. LDVSR.LT.N ) ) THENINFO = -18END IF** Compute workspace* (Note: Comments in the code beginning "Workspace:" describe the* minimal amount of workspace needed at that point in the code,* as well as the preferred amount for good performance.* NB refers to the optimal block size for the immediately* following subroutine, as returned by ILAENV.)*MINWRK = 1IF( INFO.EQ.0 .AND. LWORK.GE.1 ) THENMINWRK = 8*( N+1 ) + 16MAXWRK = 7*( N+1 ) + N*ILAENV( 1, 'DGEQRF', ' ', N, 1, N, 0 ) +$ 16IF( ILVSL ) THENMAXWRK = MAX( MAXWRK, 8*( N+1 )+N*$ ILAENV( 1, 'DORGQR', ' ', N, 1, N, -1 )+16 )END IFWORK( 1 ) = MAXWRKEND IFIF( .NOT.WANTSN ) THENLIWMIN = 1ELSELIWMIN = N + 6END IFIWORK( 1 ) = LIWMIN*IF( INFO.EQ.0 .AND. LWORK.LT.MINWRK ) THENINFO = -22ELSE IF( INFO.EQ.0 .AND. IJOB.GE.1 ) THENIF( LIWORK.LT.LIWMIN )$ INFO = -24END IF*IF( INFO.NE.0 ) THENCALL XERBLA( 'DGGESX', -INFO )RETURNEND IF** Quick return if possible*IF( N.EQ.0 ) THENSDIM = 0RETURNEND IF** Get machine constants*EPS = DLAMCH( 'P' )SAFMIN = DLAMCH( 'S' )SAFMAX = ONE / SAFMINCALL DLABAD( SAFMIN, SAFMAX )SMLNUM = SQRT( SAFMIN ) / EPSBIGNUM = ONE / SMLNUM** Scale A if max element outside range [SMLNUM,BIGNUM]*ANRM = DLANGE( 'M', N, N, A, LDA, WORK )ILASCL = .FALSE.IF( ANRM.GT.ZERO .AND. ANRM.LT.SMLNUM ) THENANRMTO = SMLNUMILASCL = .TRUE.ELSE IF( ANRM.GT.BIGNUM ) THENANRMTO = BIGNUMILASCL = .TRUE.END IFIF( ILASCL )$ CALL DLASCL( 'G', 0, 0, ANRM, ANRMTO, N, N, A, LDA, IERR )** Scale B if max element outside range [SMLNUM,BIGNUM]*BNRM = DLANGE( 'M', N, N, B, LDB, WORK )ILBSCL = .FALSE.IF( BNRM.GT.ZERO .AND. BNRM.LT.SMLNUM ) THENBNRMTO = SMLNUMILBSCL = .TRUE.ELSE IF( BNRM.GT.BIGNUM ) THENBNRMTO = BIGNUMILBSCL = .TRUE.END IFIF( ILBSCL )$ CALL DLASCL( 'G', 0, 0, BNRM, BNRMTO, N, N, B, LDB, IERR )** Permute the matrix to make it more nearly triangular* (Workspace: need 6*N + 2*N for permutation parameters)*ILEFT = 1IRIGHT = N + 1IWRK = IRIGHT + NCALL DGGBAL( 'P', N, A, LDA, B, LDB, ILO, IHI, WORK( ILEFT ),$ WORK( IRIGHT ), WORK( IWRK ), IERR )** Reduce B to triangular form (QR decomposition of B)* (Workspace: need N, prefer N*NB)*IROWS = IHI + 1 - ILOICOLS = N + 1 - ILOITAU = IWRKIWRK = ITAU + IROWSCALL DGEQRF( IROWS, ICOLS, B( ILO, ILO ), LDB, WORK( ITAU ),$ WORK( IWRK ), LWORK+1-IWRK, IERR )** Apply the orthogonal transformation to matrix A* (Workspace: need N, prefer N*NB)*CALL DORMQR( 'L', 'T', IROWS, ICOLS, IROWS, B( ILO, ILO ), LDB,$ WORK( ITAU ), A( ILO, ILO ), LDA, WORK( IWRK ),$ LWORK+1-IWRK, IERR )** Initialize VSL* (Workspace: need N, prefer N*NB)*IF( ILVSL ) THENCALL DLASET( 'Full', N, N, ZERO, ONE, VSL, LDVSL )CALL DLACPY( 'L', IROWS-1, IROWS-1, B( ILO+1, ILO ), LDB,$ VSL( ILO+1, ILO ), LDVSL )CALL DORGQR( IROWS, IROWS, IROWS, VSL( ILO, ILO ), LDVSL,$ WORK( ITAU ), WORK( IWRK ), LWORK+1-IWRK, IERR )END IF** Initialize VSR*IF( ILVSR )$ CALL DLASET( 'Full', N, N, ZERO, ONE, VSR, LDVSR )** Reduce to generalized Hessenberg form* (Workspace: none needed)*CALL DGGHRD( JOBVSL, JOBVSR, N, ILO, IHI, A, LDA, B, LDB, VSL,$ LDVSL, VSR, LDVSR, IERR )*SDIM = 0** Perform QZ algorithm, computing Schur vectors if desired* (Workspace: need N)*IWRK = ITAUCALL DHGEQZ( 'S', JOBVSL, JOBVSR, N, ILO, IHI, A, LDA, B, LDB,$ ALPHAR, ALPHAI, BETA, VSL, LDVSL, VSR, LDVSR,$ WORK( IWRK ), LWORK+1-IWRK, IERR )IF( IERR.NE.0 ) THENIF( IERR.GT.0 .AND. IERR.LE.N ) THENINFO = IERRELSE IF( IERR.GT.N .AND. IERR.LE.2*N ) THENINFO = IERR - NELSEINFO = N + 1END IFGO TO 60END IF** Sort eigenvalues ALPHA/BETA and compute the reciprocal of* condition number(s)* (Workspace: If IJOB >= 1, need MAX( 8*(N+1), 2*SDIM*(N-SDIM) )* otherwise, need 8*(N+1) )*IF( WANTST ) THEN** Undo scaling on eigenvalues before DELZTGing*IF( ILASCL ) THENCALL DLASCL( 'G', 0, 0, ANRMTO, ANRM, N, 1, ALPHAR, N,$ IERR )CALL DLASCL( 'G', 0, 0, ANRMTO, ANRM, N, 1, ALPHAI, N,$ IERR )END IFIF( ILBSCL )$ CALL DLASCL( 'G', 0, 0, BNRMTO, BNRM, N, 1, BETA, N, IERR )** Select eigenvalues*DO 10 I = 1, NBWORK( I ) = DELCTG( ALPHAR( I ), ALPHAI( I ), BETA( I ) )10 CONTINUE** Reorder eigenvalues, transform Generalized Schur vectors, and* compute reciprocal condition numbers*CALL DTGSEN( IJOB, ILVSL, ILVSR, BWORK, N, A, LDA, B, LDB,$ ALPHAR, ALPHAI, BETA, VSL, LDVSL, VSR, LDVSR,$ SDIM, PL, PR, DIF, WORK( IWRK ), LWORK-IWRK+1,$ IWORK, LIWORK, IERR )*IF( IJOB.GE.1 )$ MAXWRK = MAX( MAXWRK, 2*SDIM*( N-SDIM ) )IF( IERR.EQ.-22 ) THEN** not enough real workspace*INFO = -22ELSERCONDE( 1 ) = PLRCONDE( 2 ) = PRRCONDV( 1 ) = DIF( 1 )RCONDV( 2 ) = DIF( 2 )IF( IERR.EQ.1 )$ INFO = N + 3END IF*END IF** Apply permutation to VSL and VSR* (Workspace: none needed)*IF( ILVSL )$ CALL DGGBAK( 'P', 'L', N, ILO, IHI, WORK( ILEFT ),$ WORK( IRIGHT ), N, VSL, LDVSL, IERR )*IF( ILVSR )$ CALL DGGBAK( 'P', 'R', N, ILO, IHI, WORK( ILEFT ),$ WORK( IRIGHT ), N, VSR, LDVSR, IERR )** Check if unscaling would cause over/underflow, if so, rescale* (ALPHAR(I),ALPHAI(I),BETA(I)) so BETA(I) is on the order of* B(I,I) and ALPHAR(I) and ALPHAI(I) are on the order of A(I,I)*IF( ILASCL ) THENDO 20 I = 1, NIF( ALPHAI( I ).NE.ZERO ) THENIF( ( ALPHAR( I ) / SAFMAX ).GT.( ANRMTO / ANRM ) .OR.$ ( SAFMIN / ALPHAR( I ) ).GT.( ANRM / ANRMTO ) ) THENWORK( 1 ) = ABS( A( I, I ) / ALPHAR( I ) )BETA( I ) = BETA( I )*WORK( 1 )ALPHAR( I ) = ALPHAR( I )*WORK( 1 )ALPHAI( I ) = ALPHAI( I )*WORK( 1 )ELSE IF( ( ALPHAI( I ) / SAFMAX ).GT.$ ( ANRMTO / ANRM ) .OR.$ ( SAFMIN / ALPHAI( I ) ).GT.( ANRM / ANRMTO ) )$ THENWORK( 1 ) = ABS( A( I, I+1 ) / ALPHAI( I ) )BETA( I ) = BETA( I )*WORK( 1 )ALPHAR( I ) = ALPHAR( I )*WORK( 1 )ALPHAI( I ) = ALPHAI( I )*WORK( 1 )END IFEND IF20 CONTINUEEND IF*IF( ILBSCL ) THENDO 30 I = 1, NIF( ALPHAI( I ).NE.ZERO ) THENIF( ( BETA( I ) / SAFMAX ).GT.( BNRMTO / BNRM ) .OR.$ ( SAFMIN / BETA( I ) ).GT.( BNRM / BNRMTO ) ) THENWORK( 1 ) = ABS( B( I, I ) / BETA( I ) )BETA( I ) = BETA( I )*WORK( 1 )ALPHAR( I ) = ALPHAR( I )*WORK( 1 )ALPHAI( I ) = ALPHAI( I )*WORK( 1 )END IFEND IF30 CONTINUEEND IF** Undo scaling*IF( ILASCL ) THENCALL DLASCL( 'H', 0, 0, ANRMTO, ANRM, N, N, A, LDA, IERR )CALL DLASCL( 'G', 0, 0, ANRMTO, ANRM, N, 1, ALPHAR, N, IERR )CALL DLASCL( 'G', 0, 0, ANRMTO, ANRM, N, 1, ALPHAI, N, IERR )END IF*IF( ILBSCL ) THENCALL DLASCL( 'U', 0, 0, BNRMTO, BNRM, N, N, B, LDB, IERR )CALL DLASCL( 'G', 0, 0, BNRMTO, BNRM, N, 1, BETA, N, IERR )END IF*40 CONTINUE*IF( WANTST ) THEN** Check if reordering is correct*LASTSL = .TRUE.LST2SL = .TRUE.SDIM = 0IP = 0DO 50 I = 1, NCURSL = DELCTG( ALPHAR( I ), ALPHAI( I ), BETA( I ) )IF( ALPHAI( I ).EQ.ZERO ) THENIF( CURSL )$ SDIM = SDIM + 1IP = 0IF( CURSL .AND. .NOT.LASTSL )$ INFO = N + 2ELSEIF( IP.EQ.1 ) THEN** Last eigenvalue of conjugate pair*CURSL = CURSL .OR. LASTSLLASTSL = CURSLIF( CURSL )$ SDIM = SDIM + 2IP = -1IF( CURSL .AND. .NOT.LST2SL )$ INFO = N + 2ELSE** First eigenvalue of conjugate pair*IP = 1END IFEND IFLST2SL = LASTSLLASTSL = CURSL50 CONTINUE*END IF*60 CONTINUE*WORK( 1 ) = MAXWRKIWORK( 1 ) = LIWMIN*RETURN** End of DGGESX*ENDSUBROUTINE DGGEV( JOBVL, JOBVR, N, A, LDA, B, LDB, ALPHAR, ALPHAI,$ BETA, VL, LDVL, VR, LDVR, WORK, LWORK, INFO )** -- LAPACK driver 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 JOBVL, JOBVRINTEGER INFO, LDA, LDB, LDVL, LDVR, LWORK, N* ..* .. Array Arguments ..DOUBLE PRECISION A( LDA, * ), ALPHAI( * ), ALPHAR( * ),$ B( LDB, * ), BETA( * ), VL( LDVL, * ),$ VR( LDVR, * ), WORK( * )* ..** Purpose* =======** DGGEV computes for a pair of N-by-N real nonsymmetric matrices (A,B)* the generalized eigenvalues, and optionally, the left and/or right* generalized eigenvectors.** A generalized eigenvalue for a pair of matrices (A,B) is a scalar* lambda or a ratio alpha/beta = lambda, such that A - lambda*B is* singular. It is usually represented as the pair (alpha,beta), as* there is a reasonable interpretation for beta=0, and even for both* being zero.** The right eigenvector v(j) corresponding to the eigenvalue lambda(j)* of (A,B) satisfies** A * v(j) = lambda(j) * B * v(j).** The left eigenvector u(j) corresponding to the eigenvalue lambda(j)* of (A,B) satisfies** u(j)**H * A = lambda(j) * u(j)**H * B .** where u(j)**H is the conjugate-transpose of u(j).*** Arguments* =========** JOBVL (input) CHARACTER*1* = 'N': do not compute the left generalized eigenvectors;* = 'V': compute the left generalized eigenvectors.** JOBVR (input) CHARACTER*1* = 'N': do not compute the right generalized eigenvectors;* = 'V': compute the right generalized eigenvectors.** N (input) INTEGER* The order of the matrices A, B, VL, and VR. N >= 0.** A (input/output) DOUBLE PRECISION array, dimension (LDA, N)* On entry, the matrix A in the pair (A,B).* On exit, A has been overwritten.** LDA (input) INTEGER* The leading dimension of A. LDA >= max(1,N).** B (input/output) DOUBLE PRECISION array, dimension (LDB, N)* On entry, the matrix B in the pair (A,B).* On exit, B has been overwritten.** LDB (input) INTEGER* The leading dimension of 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. 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.** Note: the quotients ALPHAR(j)/BETA(j) and ALPHAI(j)/BETA(j)* may easily over- or underflow, and BETA(j) may even be zero.* Thus, the user should avoid naively computing the ratio* alpha/beta. However, ALPHAR and ALPHAI will be always less* than and usually comparable with norm(A) in magnitude, and* BETA always less than and usually comparable with norm(B).** VL (output) DOUBLE PRECISION array, dimension (LDVL,N)* If JOBVL = 'V', the left eigenvectors u(j) are stored one* after another in the columns of VL, in the same order as* their eigenvalues. If the j-th eigenvalue is real, then* u(j) = VL(:,j), the j-th column of VL. If the j-th and* (j+1)-th eigenvalues form a complex conjugate pair, then* u(j) = VL(:,j)+i*VL(:,j+1) and u(j+1) = VL(:,j)-i*VL(:,j+1).* Each eigenvector will be scaled so the largest component have* abs(real part)+abs(imag. part)=1.* Not referenced if JOBVL = 'N'.** LDVL (input) INTEGER* The leading dimension of the matrix VL. LDVL >= 1, and* if JOBVL = 'V', LDVL >= N.** VR (output) DOUBLE PRECISION array, dimension (LDVR,N)* If JOBVR = 'V', the right eigenvectors v(j) are stored one* after another in the columns of VR, in the same order as* their eigenvalues. If the j-th eigenvalue is real, then* v(j) = VR(:,j), the j-th column of VR. If the j-th and* (j+1)-th eigenvalues form a complex conjugate pair, then* v(j) = VR(:,j)+i*VR(:,j+1) and v(j+1) = VR(:,j)-i*VR(:,j+1).* Each eigenvector will be scaled so the largest component have* abs(real part)+abs(imag. part)=1.* Not referenced if JOBVR = 'N'.** LDVR (input) INTEGER* The leading dimension of the matrix VR. LDVR >= 1, and* if JOBVR = 'V', LDVR >= 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 >= max(1,8*N).* For good performance, LWORK must generally be larger.** 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,...,N:* The QZ iteration failed. No eigenvectors have been* calculated, but ALPHAR(j), ALPHAI(j), and BETA(j)* should be correct for j=INFO+1,...,N.* > N: =N+1: other than QZ iteration failed in DHGEQZ.* =N+2: error return from DTGEVC.** =====================================================================** .. Parameters ..DOUBLE PRECISION ZERO, ONEPARAMETER ( ZERO = 0.0D+0, ONE = 1.0D+0 )* ..* .. Local Scalars ..LOGICAL ILASCL, ILBSCL, ILV, ILVL, ILVR, LQUERYCHARACTER CHTEMPINTEGER ICOLS, IERR, IHI, IJOBVL, IJOBVR, ILEFT, ILO,$ IN, IRIGHT, IROWS, ITAU, IWRK, JC, JR, MAXWRK,$ MINWRKDOUBLE PRECISION ANRM, ANRMTO, BIGNUM, BNRM, BNRMTO, EPS,$ SMLNUM, TEMP* ..* .. Local Arrays ..LOGICAL LDUMMA( 1 )* ..* .. External Subroutines ..EXTERNAL DGEQRF, DGGBAK, DGGBAL, DGGHRD, DHGEQZ, DLACPY,$ DLASCL, DLASET, DORGQR, DORMQR, DTGEVC, XERBLA* ..* .. External Functions ..LOGICAL LSAMEINTEGER ILAENVDOUBLE PRECISION DLAMCH, DLANGEEXTERNAL LSAME, ILAENV, DLAMCH, DLANGE* ..* .. Intrinsic Functions ..INTRINSIC ABS, MAX, SQRT* ..* .. Executable Statements ..** Decode the input arguments*IF( LSAME( JOBVL, 'N' ) ) THENIJOBVL = 1ILVL = .FALSE.ELSE IF( LSAME( JOBVL, 'V' ) ) THENIJOBVL = 2ILVL = .TRUE.ELSEIJOBVL = -1ILVL = .FALSE.END IF*IF( LSAME( JOBVR, 'N' ) ) THENIJOBVR = 1ILVR = .FALSE.ELSE IF( LSAME( JOBVR, 'V' ) ) THENIJOBVR = 2ILVR = .TRUE.ELSEIJOBVR = -1ILVR = .FALSE.END IFILV = ILVL .OR. ILVR** Test the input arguments*INFO = 0LQUERY = ( LWORK.EQ.-1 )IF( IJOBVL.LE.0 ) THENINFO = -1ELSE IF( IJOBVR.LE.0 ) THENINFO = -2ELSE IF( N.LT.0 ) THENINFO = -3ELSE IF( LDA.LT.MAX( 1, N ) ) THENINFO = -5ELSE IF( LDB.LT.MAX( 1, N ) ) THENINFO = -7ELSE IF( LDVL.LT.1 .OR. ( ILVL .AND. LDVL.LT.N ) ) THENINFO = -12ELSE IF( LDVR.LT.1 .OR. ( ILVR .AND. LDVR.LT.N ) ) THENINFO = -14END IF** Compute workspace* (Note: Comments in the code beginning "Workspace:" describe the* minimal amount of workspace needed at that point in the code,* as well as the preferred amount for good performance.* NB refers to the optimal block size for the immediately* following subroutine, as returned by ILAENV. The workspace is* computed assuming ILO = 1 and IHI = N, the worst case.)*MINWRK = 1IF( INFO.EQ.0 .AND. ( LWORK.GE.1 .OR. LQUERY ) ) THENMAXWRK = 7*N + N*ILAENV( 1, 'DGEQRF', ' ', N, 1, N, 0 )MINWRK = MAX( 1, 8*N )WORK( 1 ) = MAXWRKEND IF*IF( LWORK.LT.MINWRK .AND. .NOT.LQUERY )$ INFO = -16*IF( INFO.NE.0 ) THENCALL XERBLA( 'DGGEV ', -INFO )RETURNELSE IF( LQUERY ) THENRETURNEND IF** Quick return if possible*IF( N.EQ.0 )$ RETURN** Get machine constants*EPS = DLAMCH( 'P' )SMLNUM = DLAMCH( 'S' )BIGNUM = ONE / SMLNUMCALL DLABAD( SMLNUM, BIGNUM )SMLNUM = SQRT( SMLNUM ) / EPSBIGNUM = ONE / SMLNUM** Scale A if max element outside range [SMLNUM,BIGNUM]*ANRM = DLANGE( 'M', N, N, A, LDA, WORK )ILASCL = .FALSE.IF( ANRM.GT.ZERO .AND. ANRM.LT.SMLNUM ) THENANRMTO = SMLNUMILASCL = .TRUE.ELSE IF( ANRM.GT.BIGNUM ) THENANRMTO = BIGNUMILASCL = .TRUE.END IFIF( ILASCL )$ CALL DLASCL( 'G', 0, 0, ANRM, ANRMTO, N, N, A, LDA, IERR )** Scale B if max element outside range [SMLNUM,BIGNUM]*BNRM = DLANGE( 'M', N, N, B, LDB, WORK )ILBSCL = .FALSE.IF( BNRM.GT.ZERO .AND. BNRM.LT.SMLNUM ) THENBNRMTO = SMLNUMILBSCL = .TRUE.ELSE IF( BNRM.GT.BIGNUM ) THENBNRMTO = BIGNUMILBSCL = .TRUE.END IFIF( ILBSCL )$ CALL DLASCL( 'G', 0, 0, BNRM, BNRMTO, N, N, B, LDB, IERR )** Permute the matrices A, B to isolate eigenvalues if possible* (Workspace: need 6*N)*ILEFT = 1IRIGHT = N + 1IWRK = IRIGHT + NCALL DGGBAL( 'P', N, A, LDA, B, LDB, ILO, IHI, WORK( ILEFT ),$ WORK( IRIGHT ), WORK( IWRK ), IERR )** Reduce B to triangular form (QR decomposition of B)* (Workspace: need N, prefer N*NB)*IROWS = IHI + 1 - ILOIF( ILV ) THENICOLS = N + 1 - ILOELSEICOLS = IROWSEND IFITAU = IWRKIWRK = ITAU + IROWSCALL DGEQRF( IROWS, ICOLS, B( ILO, ILO ), LDB, WORK( ITAU ),$ WORK( IWRK ), LWORK+1-IWRK, IERR )** Apply the orthogonal transformation to matrix A* (Workspace: need N, prefer N*NB)*CALL DORMQR( 'L', 'T', IROWS, ICOLS, IROWS, B( ILO, ILO ), LDB,$ WORK( ITAU ), A( ILO, ILO ), LDA, WORK( IWRK ),$ LWORK+1-IWRK, IERR )** Initialize VL* (Workspace: need N, prefer N*NB)*IF( ILVL ) THENCALL DLASET( 'Full', N, N, ZERO, ONE, VL, LDVL )CALL DLACPY( 'L', IROWS-1, IROWS-1, B( ILO+1, ILO ), LDB,$ VL( ILO+1, ILO ), LDVL )CALL DORGQR( IROWS, IROWS, IROWS, VL( ILO, ILO ), LDVL,$ WORK( ITAU ), WORK( IWRK ), LWORK+1-IWRK, IERR )END IF** Initialize VR*IF( ILVR )$ CALL DLASET( 'Full', N, N, ZERO, ONE, VR, LDVR )** Reduce to generalized Hessenberg form* (Workspace: none needed)*IF( ILV ) THEN** Eigenvectors requested -- work on whole matrix.*CALL DGGHRD( JOBVL, JOBVR, N, ILO, IHI, A, LDA, B, LDB, VL,$ LDVL, VR, LDVR, IERR )ELSECALL DGGHRD( 'N', 'N', IROWS, 1, IROWS, A( ILO, ILO ), LDA,$ B( ILO, ILO ), LDB, VL, LDVL, VR, LDVR, IERR )END IF** Perform QZ algorithm (Compute eigenvalues, and optionally, the* Schur forms and Schur vectors)* (Workspace: need N)*IWRK = ITAUIF( ILV ) THENCHTEMP = 'S'ELSECHTEMP = 'E'END IFCALL DHGEQZ( CHTEMP, JOBVL, JOBVR, N, ILO, IHI, A, LDA, B, LDB,$ ALPHAR, ALPHAI, BETA, VL, LDVL, VR, LDVR,$ WORK( IWRK ), LWORK+1-IWRK, IERR )IF( IERR.NE.0 ) THENIF( IERR.GT.0 .AND. IERR.LE.N ) THENINFO = IERRELSE IF( IERR.GT.N .AND. IERR.LE.2*N ) THENINFO = IERR - NELSEINFO = N + 1END IFGO TO 110END IF** Compute Eigenvectors* (Workspace: need 6*N)*IF( ILV ) THENIF( ILVL ) THENIF( ILVR ) THENCHTEMP = 'B'ELSECHTEMP = 'L'END IFELSECHTEMP = 'R'END IFCALL DTGEVC( CHTEMP, 'B', LDUMMA, N, A, LDA, B, LDB, VL, LDVL,$ VR, LDVR, N, IN, WORK( IWRK ), IERR )IF( IERR.NE.0 ) THENINFO = N + 2GO TO 110END IF** Undo balancing on VL and VR and normalization* (Workspace: none needed)*IF( ILVL ) THENCALL DGGBAK( 'P', 'L', N, ILO, IHI, WORK( ILEFT ),$ WORK( IRIGHT ), N, VL, LDVL, IERR )DO 50 JC = 1, NIF( ALPHAI( JC ).LT.ZERO )$ GO TO 50TEMP = ZEROIF( ALPHAI( JC ).EQ.ZERO ) THENDO 10 JR = 1, NTEMP = MAX( TEMP, ABS( VL( JR, JC ) ) )10 CONTINUEELSEDO 20 JR = 1, NTEMP = MAX( TEMP, ABS( VL( JR, JC ) )+$ ABS( VL( JR, JC+1 ) ) )20 CONTINUEEND IFIF( TEMP.LT.SMLNUM )$ GO TO 50TEMP = ONE / TEMPIF( ALPHAI( JC ).EQ.ZERO ) THENDO 30 JR = 1, NVL( JR, JC ) = VL( JR, JC )*TEMP30 CONTINUEELSEDO 40 JR = 1, NVL( JR, JC ) = VL( JR, JC )*TEMPVL( JR, JC+1 ) = VL( JR, JC+1 )*TEMP40 CONTINUEEND IF50 CONTINUEEND IFIF( ILVR ) THENCALL DGGBAK( 'P', 'R', N, ILO, IHI, WORK( ILEFT ),$ WORK( IRIGHT ), N, VR, LDVR, IERR )DO 100 JC = 1, NIF( ALPHAI( JC ).LT.ZERO )$ GO TO 100TEMP = ZEROIF( ALPHAI( JC ).EQ.ZERO ) THENDO 60 JR = 1, NTEMP = MAX( TEMP, ABS( VR( JR, JC ) ) )60 CONTINUEELSEDO 70 JR = 1, NTEMP = MAX( TEMP, ABS( VR( JR, JC ) )+$ ABS( VR( JR, JC+1 ) ) )70 CONTINUEEND IFIF( TEMP.LT.SMLNUM )$ GO TO 100TEMP = ONE / TEMPIF( ALPHAI( JC ).EQ.ZERO ) THENDO 80 JR = 1, NVR( JR, JC ) = VR( JR, JC )*TEMP80 CONTINUEELSEDO 90 JR = 1, NVR( JR, JC ) = VR( JR, JC )*TEMPVR( JR, JC+1 ) = VR( JR, JC+1 )*TEMP90 CONTINUEEND IF100 CONTINUEEND IF** End of eigenvector calculation*END IF** Undo scaling if necessary*IF( ILASCL ) THENCALL DLASCL( 'G', 0, 0, ANRMTO, ANRM, N, 1, ALPHAR, N, IERR )CALL DLASCL( 'G', 0, 0, ANRMTO, ANRM, N, 1, ALPHAI, N, IERR )END IF*IF( ILBSCL ) THENCALL DLASCL( 'G', 0, 0, BNRMTO, BNRM, N, 1, BETA, N, IERR )END IF*110 CONTINUE*WORK( 1 ) = MAXWRK*RETURN** End of DGGEV*ENDSUBROUTINE DGGEVX( BALANC, JOBVL, JOBVR, SENSE, N, A, LDA, B, LDB,$ ALPHAR, ALPHAI, BETA, VL, LDVL, VR, LDVR, ILO,$ IHI, LSCALE, RSCALE, ABNRM, BBNRM, RCONDE,$ RCONDV, WORK, LWORK, IWORK, BWORK, INFO )** -- LAPACK driver 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 BALANC, JOBVL, JOBVR, SENSEINTEGER IHI, ILO, INFO, LDA, LDB, LDVL, LDVR, LWORK, NDOUBLE PRECISION ABNRM, BBNRM* ..* .. Array Arguments ..LOGICAL BWORK( * )INTEGER IWORK( * )DOUBLE PRECISION A( LDA, * ), ALPHAI( * ), ALPHAR( * ),$ B( LDB, * ), BETA( * ), LSCALE( * ),$ RCONDE( * ), RCONDV( * ), RSCALE( * ),$ VL( LDVL, * ), VR( LDVR, * ), WORK( * )* ..** Purpose* =======** DGGEVX computes for a pair of N-by-N real nonsymmetric matrices (A,B)* the generalized eigenvalues, and optionally, the left and/or right* generalized eigenvectors.** Optionally also, it computes a balancing transformation to improve* the conditioning of the eigenvalues and eigenvectors (ILO, IHI,* LSCALE, RSCALE, ABNRM, and BBNRM), reciprocal condition numbers for* the eigenvalues (RCONDE), and reciprocal condition numbers for the* right eigenvectors (RCONDV).** A generalized eigenvalue for a pair of matrices (A,B) is a scalar* lambda or a ratio alpha/beta = lambda, such that A - lambda*B is* singular. It is usually represented as the pair (alpha,beta), as* there is a reasonable interpretation for beta=0, and even for both* being zero.** The right eigenvector v(j) corresponding to the eigenvalue lambda(j)* of (A,B) satisfies** A * v(j) = lambda(j) * B * v(j) .** The left eigenvector u(j) corresponding to the eigenvalue lambda(j)* of (A,B) satisfies** u(j)**H * A = lambda(j) * u(j)**H * B.** where u(j)**H is the conjugate-transpose of u(j).*** Arguments* =========** BALANC (input) CHARACTER*1* Specifies the balance option to be performed.* = 'N': do not diagonally scale or permute;* = 'P': permute only;* = 'S': scale only;* = 'B': both permute and scale.* Computed reciprocal condition numbers will be for the* matrices after permuting and/or balancing. Permuting does* not change condition numbers (in exact arithmetic), but* balancing does.** JOBVL (input) CHARACTER*1* = 'N': do not compute the left generalized eigenvectors;* = 'V': compute the left generalized eigenvectors.** JOBVR (input) CHARACTER*1* = 'N': do not compute the right generalized eigenvectors;* = 'V': compute the right generalized eigenvectors.** SENSE (input) CHARACTER*1* Determines which reciprocal condition numbers are computed.* = 'N': none are computed;* = 'E': computed for eigenvalues only;* = 'V': computed for eigenvectors only;* = 'B': computed for eigenvalues and eigenvectors.** N (input) INTEGER* The order of the matrices A, B, VL, and VR. N >= 0.** A (input/output) DOUBLE PRECISION array, dimension (LDA, N)* On entry, the matrix A in the pair (A,B).* On exit, A has been overwritten. If JOBVL='V' or JOBVR='V'* or both, then A contains the first part of the real Schur* form of the "balanced" versions of the input A and B.** LDA (input) INTEGER* The leading dimension of A. LDA >= max(1,N).** B (input/output) DOUBLE PRECISION array, dimension (LDB, N)* On entry, the matrix B in the pair (A,B).* On exit, B has been overwritten. If JOBVL='V' or JOBVR='V'* or both, then B contains the second part of the real Schur* form of the "balanced" versions of the input A and B.** LDB (input) INTEGER* The leading dimension of 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. 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.** Note: the quotients ALPHAR(j)/BETA(j) and ALPHAI(j)/BETA(j)* may easily over- or underflow, and BETA(j) may even be zero.* Thus, the user should avoid naively computing the ratio* ALPHA/BETA. However, ALPHAR and ALPHAI will be always less* than and usually comparable with norm(A) in magnitude, and* BETA always less than and usually comparable with norm(B).** VL (output) DOUBLE PRECISION array, dimension (LDVL,N)* If JOBVL = 'V', the left eigenvectors u(j) are stored one* after another in the columns of VL, in the same order as* their eigenvalues. If the j-th eigenvalue is real, then* u(j) = VL(:,j), the j-th column of VL. If the j-th and* (j+1)-th eigenvalues form a complex conjugate pair, then* u(j) = VL(:,j)+i*VL(:,j+1) and u(j+1) = VL(:,j)-i*VL(:,j+1).* Each eigenvector will be scaled so the largest component have* abs(real part) + abs(imag. part) = 1.* Not referenced if JOBVL = 'N'.** LDVL (input) INTEGER* The leading dimension of the matrix VL. LDVL >= 1, and* if JOBVL = 'V', LDVL >= N.** VR (output) DOUBLE PRECISION array, dimension (LDVR,N)* If JOBVR = 'V', the right eigenvectors v(j) are stored one* after another in the columns of VR, in the same order as* their eigenvalues. If the j-th eigenvalue is real, then* v(j) = VR(:,j), the j-th column of VR. If the j-th and* (j+1)-th eigenvalues form a complex conjugate pair, then* v(j) = VR(:,j)+i*VR(:,j+1) and v(j+1) = VR(:,j)-i*VR(:,j+1).* Each eigenvector will be scaled so the largest component have* abs(real part) + abs(imag. part) = 1.* Not referenced if JOBVR = 'N'.** LDVR (input) INTEGER* The leading dimension of the matrix VR. LDVR >= 1, and* if JOBVR = 'V', LDVR >= N.** ILO,IHI (output) INTEGER* ILO and IHI are integer values such that on exit* A(i,j) = 0 and B(i,j) = 0 if i > j and* j = 1,...,ILO-1 or i = IHI+1,...,N.* If BALANC = 'N' or 'S', ILO = 1 and IHI = N.** LSCALE (output) DOUBLE PRECISION array, dimension (N)* Details of the permutations and scaling factors applied* to the left side of A and B. If PL(j) is the index of the* row interchanged with row j, and DL(j) is the scaling* factor applied to row j, then* LSCALE(j) = PL(j) for j = 1,...,ILO-1* = DL(j) for j = ILO,...,IHI* = PL(j) for j = IHI+1,...,N.* The order in which the interchanges are made is N to IHI+1,* then 1 to ILO-1.** RSCALE (output) DOUBLE PRECISION array, dimension (N)* Details of the permutations and scaling factors applied* to the right side of A and B. If PR(j) is the index of the* column interchanged with column j, and DR(j) is the scaling* factor applied to column j, then* RSCALE(j) = PR(j) for j = 1,...,ILO-1* = DR(j) for j = ILO,...,IHI* = PR(j) for j = IHI+1,...,N* The order in which the interchanges are made is N to IHI+1,* then 1 to ILO-1.** ABNRM (output) DOUBLE PRECISION* The one-norm of the balanced matrix A.** BBNRM (output) DOUBLE PRECISION* The one-norm of the balanced matrix B.** RCONDE (output) DOUBLE PRECISION array, dimension (N)* If SENSE = '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 RCONDE are set to the same value.* Thus RCONDE(j), RCONDV(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 SENSE = 'V', RCONDE is not referenced.** RCONDV (output) DOUBLE PRECISION array, dimension (N)* If SENSE = '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 RCONDV are set to the same value. If* the eigenvalues cannot be reordered to compute RCONDV(j),* RCONDV(j) is set to 0; this can only occur when the true* value would be very small anyway.* If SENSE = 'E', RCONDV 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. LWORK >= max(1,6*N).* If SENSE = 'E', LWORK >= 12*N.* If SENSE = 'V' or 'B', LWORK >= 2*N*N+12*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.** IWORK (workspace) INTEGER array, dimension (N+6)* If SENSE = 'E', IWORK is not referenced.** BWORK (workspace) LOGICAL array, dimension (N)* If SENSE = 'N', BWORK is not referenced.** INFO (output) INTEGER* = 0: successful exit* < 0: if INFO = -i, the i-th argument had an illegal value.* = 1,...,N:* The QZ iteration failed. No eigenvectors have been* calculated, but ALPHAR(j), ALPHAI(j), and BETA(j)* should be correct for j=INFO+1,...,N.* > N: =N+1: other than QZ iteration failed in DHGEQZ.* =N+2: error return from DTGEVC.** Further Details* ===============** Balancing a matrix pair (A,B) includes, first, permuting rows and* columns to isolate eigenvalues, second, applying diagonal similarity* transformation to the rows and columns to make the rows and columns* as close in norm as possible. The computed reciprocal condition* numbers correspond to the balanced matrix. Permuting rows and columns* will not change the condition numbers (in exact arithmetic) but* diagonal scaling will. For further explanation of balancing, see* section 4.11.1.2 of LAPACK Users' Guide.** 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(ABNRM, BBNRM) / RCONDE(I)** An approximate error bound for the angle between the i-th computed* eigenvector VL(i) or VR(i) is given by** EPS * norm(ABNRM, BBNRM) / DIF(i).** For further explanation of the reciprocal condition numbers RCONDE* and RCONDV, see section 4.11 of LAPACK User's Guide.** =====================================================================** .. Parameters ..DOUBLE PRECISION ZERO, ONEPARAMETER ( ZERO = 0.0D+0, ONE = 1.0D+0 )* ..* .. Local Scalars ..LOGICAL ILASCL, ILBSCL, ILV, ILVL, ILVR, LQUERY, PAIR,$ WANTSB, WANTSE, WANTSN, WANTSVCHARACTER CHTEMPINTEGER I, ICOLS, IERR, IJOBVL, IJOBVR, IN, IROWS,$ ITAU, IWRK, IWRK1, J, JC, JR, M, MAXWRK,$ MINWRK, MMDOUBLE PRECISION ANRM, ANRMTO, BIGNUM, BNRM, BNRMTO, EPS,$ SMLNUM, TEMP* ..* .. Local Arrays ..LOGICAL LDUMMA( 1 )* ..* .. External Subroutines ..EXTERNAL DGEQRF, DGGBAK, DGGBAL, DGGHRD, DHGEQZ, DLACPY,$ DLASCL, DLASET, DORGQR, DORMQR, DTGEVC, DTGSNA,$ XERBLA* ..* .. External Functions ..LOGICAL LSAMEINTEGER ILAENVDOUBLE PRECISION DLAMCH, DLANGEEXTERNAL LSAME, ILAENV, DLAMCH, DLANGE* ..* .. Intrinsic Functions ..INTRINSIC ABS, MAX, SQRT* ..* .. Executable Statements ..** Decode the input arguments*IF( LSAME( JOBVL, 'N' ) ) THENIJOBVL = 1ILVL = .FALSE.ELSE IF( LSAME( JOBVL, 'V' ) ) THENIJOBVL = 2ILVL = .TRUE.ELSEIJOBVL = -1ILVL = .FALSE.END IF*IF( LSAME( JOBVR, 'N' ) ) THENIJOBVR = 1ILVR = .FALSE.ELSE IF( LSAME( JOBVR, 'V' ) ) THENIJOBVR = 2ILVR = .TRUE.ELSEIJOBVR = -1ILVR = .FALSE.END IFILV = ILVL .OR. ILVR*WANTSN = LSAME( SENSE, 'N' )WANTSE = LSAME( SENSE, 'E' )WANTSV = LSAME( SENSE, 'V' )WANTSB = LSAME( SENSE, 'B' )** Test the input arguments*INFO = 0LQUERY = ( LWORK.EQ.-1 )IF( .NOT.( LSAME( BALANC, 'N' ) .OR. LSAME( BALANC,$ 'S' ) .OR. LSAME( BALANC, 'P' ) .OR. LSAME( BALANC, 'B' ) ) )$ THENINFO = -1ELSE IF( IJOBVL.LE.0 ) THENINFO = -2ELSE IF( IJOBVR.LE.0 ) THENINFO = -3ELSE IF( .NOT.( WANTSN .OR. WANTSE .OR. WANTSB .OR. WANTSV ) )$ THENINFO = -4ELSE IF( N.LT.0 ) THENINFO = -5ELSE IF( LDA.LT.MAX( 1, N ) ) THENINFO = -7ELSE IF( LDB.LT.MAX( 1, N ) ) THENINFO = -9ELSE IF( LDVL.LT.1 .OR. ( ILVL .AND. LDVL.LT.N ) ) THENINFO = -14ELSE IF( LDVR.LT.1 .OR. ( ILVR .AND. LDVR.LT.N ) ) THENINFO = -16END IF** Compute workspace* (Note: Comments in the code beginning "Workspace:" describe the* minimal amount of workspace needed at that point in the code,* as well as the preferred amount for good performance.* NB refers to the optimal block size for the immediately* following subroutine, as returned by ILAENV. The workspace is* computed assuming ILO = 1 and IHI = N, the worst case.)*MINWRK = 1IF( INFO.EQ.0 .AND. ( LWORK.GE.1 .OR. LQUERY ) ) THENMAXWRK = 5*N + N*ILAENV( 1, 'DGEQRF', ' ', N, 1, N, 0 )MINWRK = MAX( 1, 6*N )IF( WANTSE ) THENMINWRK = MAX( 1, 12*N )ELSE IF( WANTSV .OR. WANTSB ) THENMINWRK = 2*N*N + 12*N + 16MAXWRK = MAX( MAXWRK, 2*N*N+12*N+16 )END IFWORK( 1 ) = MAXWRKEND IF*IF( LWORK.LT.MINWRK .AND. .NOT.LQUERY ) THENINFO = -26END IF*IF( INFO.NE.0 ) THENCALL XERBLA( 'DGGEVX', -INFO )RETURNELSE IF( LQUERY ) THENRETURNEND IF** Quick return if possible*IF( N.EQ.0 )$ RETURN*** Get machine constants*EPS = DLAMCH( 'P' )SMLNUM = DLAMCH( 'S' )BIGNUM = ONE / SMLNUMCALL DLABAD( SMLNUM, BIGNUM )SMLNUM = SQRT( SMLNUM ) / EPSBIGNUM = ONE / SMLNUM** Scale A if max element outside range [SMLNUM,BIGNUM]*ANRM = DLANGE( 'M', N, N, A, LDA, WORK )ILASCL = .FALSE.IF( ANRM.GT.ZERO .AND. ANRM.LT.SMLNUM ) THENANRMTO = SMLNUMILASCL = .TRUE.ELSE IF( ANRM.GT.BIGNUM ) THENANRMTO = BIGNUMILASCL = .TRUE.END IFIF( ILASCL )$ CALL DLASCL( 'G', 0, 0, ANRM, ANRMTO, N, N, A, LDA, IERR )** Scale B if max element outside range [SMLNUM,BIGNUM]*BNRM = DLANGE( 'M', N, N, B, LDB, WORK )ILBSCL = .FALSE.IF( BNRM.GT.ZERO .AND. BNRM.LT.SMLNUM ) THENBNRMTO = SMLNUMILBSCL = .TRUE.ELSE IF( BNRM.GT.BIGNUM ) THENBNRMTO = BIGNUMILBSCL = .TRUE.END IFIF( ILBSCL )$ CALL DLASCL( 'G', 0, 0, BNRM, BNRMTO, N, N, B, LDB, IERR )** Permute and/or balance the matrix pair (A,B)* (Workspace: need 6*N)*CALL DGGBAL( BALANC, N, A, LDA, B, LDB, ILO, IHI, LSCALE, RSCALE,$ WORK, IERR )** Compute ABNRM and BBNRM*ABNRM = DLANGE( '1', N, N, A, LDA, WORK( 1 ) )IF( ILASCL ) THENWORK( 1 ) = ABNRMCALL DLASCL( 'G', 0, 0, ANRMTO, ANRM, 1, 1, WORK( 1 ), 1,$ IERR )ABNRM = WORK( 1 )END IF*BBNRM = DLANGE( '1', N, N, B, LDB, WORK( 1 ) )IF( ILBSCL ) THENWORK( 1 ) = BBNRMCALL DLASCL( 'G', 0, 0, BNRMTO, BNRM, 1, 1, WORK( 1 ), 1,$ IERR )BBNRM = WORK( 1 )END IF** Reduce B to triangular form (QR decomposition of B)* (Workspace: need N, prefer N*NB )*IROWS = IHI + 1 - ILOIF( ILV .OR. .NOT.WANTSN ) THENICOLS = N + 1 - ILOELSEICOLS = IROWSEND IFITAU = 1IWRK = ITAU + IROWSCALL DGEQRF( IROWS, ICOLS, B( ILO, ILO ), LDB, WORK( ITAU ),$ WORK( IWRK ), LWORK+1-IWRK, IERR )** Apply the orthogonal transformation to A* (Workspace: need N, prefer N*NB)*CALL DORMQR( 'L', 'T', IROWS, ICOLS, IROWS, B( ILO, ILO ), LDB,$ WORK( ITAU ), A( ILO, ILO ), LDA, WORK( IWRK ),$ LWORK+1-IWRK, IERR )** Initialize VL and/or VR* (Workspace: need N, prefer N*NB)*IF( ILVL ) THENCALL DLASET( 'Full', N, N, ZERO, ONE, VL, LDVL )CALL DLACPY( 'L', IROWS-1, IROWS-1, B( ILO+1, ILO ), LDB,$ VL( ILO+1, ILO ), LDVL )CALL DORGQR( IROWS, IROWS, IROWS, VL( ILO, ILO ), LDVL,$ WORK( ITAU ), WORK( IWRK ), LWORK+1-IWRK, IERR )END IF*IF( ILVR )$ CALL DLASET( 'Full', N, N, ZERO, ONE, VR, LDVR )** Reduce to generalized Hessenberg form* (Workspace: none needed)*IF( ILV .OR. .NOT.WANTSN ) THEN** Eigenvectors requested -- work on whole matrix.*CALL DGGHRD( JOBVL, JOBVR, N, ILO, IHI, A, LDA, B, LDB, VL,$ LDVL, VR, LDVR, IERR )ELSECALL DGGHRD( 'N', 'N', IROWS, 1, IROWS, A( ILO, ILO ), LDA,$ B( ILO, ILO ), LDB, VL, LDVL, VR, LDVR, IERR )END IF** Perform QZ algorithm (Compute eigenvalues, and optionally, the* Schur forms and Schur vectors)* (Workspace: need N)*IF( ILV .OR. .NOT.WANTSN ) THENCHTEMP = 'S'ELSECHTEMP = 'E'END IF*CALL DHGEQZ( CHTEMP, JOBVL, JOBVR, N, ILO, IHI, A, LDA, B, LDB,$ ALPHAR, ALPHAI, BETA, VL, LDVL, VR, LDVR, WORK,$ LWORK, IERR )IF( IERR.NE.0 ) THENIF( IERR.GT.0 .AND. IERR.LE.N ) THENINFO = IERRELSE IF( IERR.GT.N .AND. IERR.LE.2*N ) THENINFO = IERR - NELSEINFO = N + 1END IFGO TO 130END IF** Compute Eigenvectors and estimate condition numbers if desired* (Workspace: DTGEVC: need 6*N* DTGSNA: need 2*N*(N+2)+16 if SENSE = 'V' or 'B',* need N otherwise )*IF( ILV .OR. .NOT.WANTSN ) THENIF( ILV ) THENIF( ILVL ) THENIF( ILVR ) THENCHTEMP = 'B'ELSECHTEMP = 'L'END IFELSECHTEMP = 'R'END IF*CALL DTGEVC( CHTEMP, 'B', LDUMMA, N, A, LDA, B, LDB, VL,$ LDVL, VR, LDVR, N, IN, WORK, IERR )IF( IERR.NE.0 ) THENINFO = N + 2GO TO 130END IFEND IF*IF( .NOT.WANTSN ) THEN** compute eigenvectors (DTGEVC) and estimate condition* numbers (DTGSNA). Note that the definition of the condition* number is not invariant under transformation (u,v) to* (Q*u, Z*v), where (u,v) are eigenvectors of the generalized* Schur form (S,T), Q and Z are orthogonal matrices. In order* to avoid using extra 2*N*N workspace, we have to recalculate* eigenvectors and estimate one condition numbers at a time.*PAIR = .FALSE.DO 20 I = 1, N*IF( PAIR ) THENPAIR = .FALSE.GO TO 20END IFMM = 1IF( I.LT.N ) THENIF( A( I+1, I ).NE.ZERO ) THENPAIR = .TRUE.MM = 2END IFEND IF*DO 10 J = 1, NBWORK( J ) = .FALSE.10 CONTINUEIF( MM.EQ.1 ) THENBWORK( I ) = .TRUE.ELSE IF( MM.EQ.2 ) THENBWORK( I ) = .TRUE.BWORK( I+1 ) = .TRUE.END IF*IWRK = MM*N + 1IWRK1 = IWRK + MM*N** Compute a pair of left and right eigenvectors.* (compute workspace: need up to 4*N + 6*N)*IF( WANTSE .OR. WANTSB ) THENCALL DTGEVC( 'B', 'S', BWORK, N, A, LDA, B, LDB,$ WORK( 1 ), N, WORK( IWRK ), N, MM, M,$ WORK( IWRK1 ), IERR )IF( IERR.NE.0 ) THENINFO = N + 2GO TO 130END IFEND IF*CALL DTGSNA( SENSE, 'S', BWORK, N, A, LDA, B, LDB,$ WORK( 1 ), N, WORK( IWRK ), N, RCONDE( I ),$ RCONDV( I ), MM, M, WORK( IWRK1 ),$ LWORK-IWRK1+1, IWORK, IERR )*20 CONTINUEEND IFEND IF** Undo balancing on VL and VR and normalization* (Workspace: none needed)*IF( ILVL ) THENCALL DGGBAK( BALANC, 'L', N, ILO, IHI, LSCALE, RSCALE, N, VL,$ LDVL, IERR )*DO 70 JC = 1, NIF( ALPHAI( JC ).LT.ZERO )$ GO TO 70TEMP = ZEROIF( ALPHAI( JC ).EQ.ZERO ) THENDO 30 JR = 1, NTEMP = MAX( TEMP, ABS( VL( JR, JC ) ) )30 CONTINUEELSEDO 40 JR = 1, NTEMP = MAX( TEMP, ABS( VL( JR, JC ) )+$ ABS( VL( JR, JC+1 ) ) )40 CONTINUEEND IFIF( TEMP.LT.SMLNUM )$ GO TO 70TEMP = ONE / TEMPIF( ALPHAI( JC ).EQ.ZERO ) THENDO 50 JR = 1, NVL( JR, JC ) = VL( JR, JC )*TEMP50 CONTINUEELSEDO 60 JR = 1, NVL( JR, JC ) = VL( JR, JC )*TEMPVL( JR, JC+1 ) = VL( JR, JC+1 )*TEMP60 CONTINUEEND IF70 CONTINUEEND IFIF( ILVR ) THENCALL DGGBAK( BALANC, 'R', N, ILO, IHI, LSCALE, RSCALE, N, VR,$ LDVR, IERR )DO 120 JC = 1, NIF( ALPHAI( JC ).LT.ZERO )$ GO TO 120TEMP = ZEROIF( ALPHAI( JC ).EQ.ZERO ) THENDO 80 JR = 1, NTEMP = MAX( TEMP, ABS( VR( JR, JC ) ) )80 CONTINUEELSEDO 90 JR = 1, NTEMP = MAX( TEMP, ABS( VR( JR, JC ) )+$ ABS( VR( JR, JC+1 ) ) )90 CONTINUEEND IFIF( TEMP.LT.SMLNUM )$ GO TO 120TEMP = ONE / TEMPIF( ALPHAI( JC ).EQ.ZERO ) THENDO 100 JR = 1, NVR( JR, JC ) = VR( JR, JC )*TEMP100 CONTINUEELSEDO 110 JR = 1, NVR( JR, JC ) = VR( JR, JC )*TEMPVR( JR, JC+1 ) = VR( JR, JC+1 )*TEMP110 CONTINUEEND IF120 CONTINUEEND IF** Undo scaling if necessary*IF( ILASCL ) THENCALL DLASCL( 'G', 0, 0, ANRMTO, ANRM, N, 1, ALPHAR, N, IERR )CALL DLASCL( 'G', 0, 0, ANRMTO, ANRM, N, 1, ALPHAI, N, IERR )END IF*IF( ILBSCL ) THENCALL DLASCL( 'G', 0, 0, BNRMTO, BNRM, N, 1, BETA, N, IERR )END IF*130 CONTINUEWORK( 1 ) = MAXWRK*RETURN** End of DGGEVX*ENDSUBROUTINE DGGGLM( N, M, P, A, LDA, B, LDB, D, X, Y, WORK, LWORK,$ INFO )** -- LAPACK driver 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, LDB, LWORK, M, N, P* ..* .. Array Arguments ..DOUBLE PRECISION A( LDA, * ), B( LDB, * ), D( * ), WORK( * ),$ X( * ), Y( * )* ..** Purpose* =======** DGGGLM solves a general Gauss-Markov linear model (GLM) problem:** minimize || y ||_2 subject to d = A*x + B*y* x** where A is an N-by-M matrix, B is an N-by-P matrix, and d is a* given N-vector. It is assumed that M <= N <= M+P, and** rank(A) = M and rank( A B ) = N.** Under these assumptions, the constrained equation is always* consistent, and there is a unique solution x and a minimal 2-norm* solution y, which is obtained using a generalized QR factorization* of A and B.** In particular, if matrix B is square nonsingular, then the problem* GLM is equivalent to the following weighted linear least squares* problem** minimize || inv(B)*(d-A*x) ||_2* x** where inv(B) denotes the inverse of B.** Arguments* =========** N (input) INTEGER* The number of rows of the matrices A and B. N >= 0.** M (input) INTEGER* The number of columns of the matrix A. 0 <= M <= N.** P (input) INTEGER* The number of columns of the matrix B. P >= N-M.** A (input/output) DOUBLE PRECISION array, dimension (LDA,M)* On entry, the N-by-M matrix A.* On exit, A is destroyed.** LDA (input) INTEGER* The leading dimension of the array A. LDA >= max(1,N).** B (input/output) DOUBLE PRECISION array, dimension (LDB,P)* On entry, the N-by-P matrix B.* On exit, B is destroyed.** LDB (input) INTEGER* The leading dimension of the array B. LDB >= max(1,N).** D (input/output) DOUBLE PRECISION array, dimension (N)* On entry, D is the left hand side of the GLM equation.* On exit, D is destroyed.** X (output) DOUBLE PRECISION array, dimension (M)* Y (output) DOUBLE PRECISION array, dimension (P)* On exit, X and Y are the solutions of the GLM problem.** 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+M+P).* For optimum performance, LWORK >= M+min(N,P)+max(N,P)*NB,* where NB is an upper bound for the optimal blocksizes for* DGEQRF, SGERQF, DORMQR and SORMRQ.** 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, LOPT, LWKOPT, NB, NB1, NB2, NB3, NB4, NP* ..* .. External Subroutines ..EXTERNAL DCOPY, DGEMV, DGGQRF, DORMQR, DORMRQ, DTRSV,$ XERBLA* ..* .. External Functions ..INTEGER ILAENVEXTERNAL ILAENV* ..* .. Intrinsic Functions ..INTRINSIC INT, MAX, MIN* ..* .. Executable Statements ..** Test the input parameters*INFO = 0NP = MIN( N, P )NB1 = ILAENV( 1, 'DGEQRF', ' ', N, M, -1, -1 )NB2 = ILAENV( 1, 'DGERQF', ' ', N, M, -1, -1 )NB3 = ILAENV( 1, 'DORMQR', ' ', N, M, P, -1 )NB4 = ILAENV( 1, 'DORMRQ', ' ', N, M, P, -1 )NB = MAX( NB1, NB2, NB3, NB4 )LWKOPT = M + NP + MAX( N, P )*NBWORK( 1 ) = LWKOPTLQUERY = ( LWORK.EQ.-1 )IF( N.LT.0 ) THENINFO = -1ELSE IF( M.LT.0 .OR. M.GT.N ) THENINFO = -2ELSE IF( P.LT.0 .OR. P.LT.N-M ) THENINFO = -3ELSE IF( LDA.LT.MAX( 1, N ) ) THENINFO = -5ELSE IF( LDB.LT.MAX( 1, N ) ) THENINFO = -7ELSE IF( LWORK.LT.MAX( 1, N+M+P ) .AND. .NOT.LQUERY ) THENINFO = -12END IFIF( INFO.NE.0 ) THENCALL XERBLA( 'DGGGLM', -INFO )RETURNELSE IF( LQUERY ) THENRETURNEND IF** Quick return if possible*IF( N.EQ.0 )$ RETURN** Compute the GQR factorization of matrices A and B:** Q'*A = ( R11 ) M, Q'*B*Z' = ( T11 T12 ) M* ( 0 ) N-M ( 0 T22 ) N-M* M M+P-N N-M** where R11 and T22 are upper triangular, and Q and Z are* orthogonal.*CALL DGGQRF( N, M, P, A, LDA, WORK, B, LDB, WORK( M+1 ),$ WORK( M+NP+1 ), LWORK-M-NP, INFO )LOPT = WORK( M+NP+1 )** Update left-hand-side vector d = Q'*d = ( d1 ) M* ( d2 ) N-M*CALL DORMQR( 'Left', 'Transpose', N, 1, M, A, LDA, WORK, D,$ MAX( 1, N ), WORK( M+NP+1 ), LWORK-M-NP, INFO )LOPT = MAX( LOPT, INT( WORK( M+NP+1 ) ) )** Solve T22*y2 = d2 for y2*CALL DTRSV( 'Upper', 'No transpose', 'Non unit', N-M,$ B( M+1, M+P-N+1 ), LDB, D( M+1 ), 1 )CALL DCOPY( N-M, D( M+1 ), 1, Y( M+P-N+1 ), 1 )** Set y1 = 0*DO 10 I = 1, M + P - NY( I ) = ZERO10 CONTINUE** Update d1 = d1 - T12*y2*CALL DGEMV( 'No transpose', M, N-M, -ONE, B( 1, M+P-N+1 ), LDB,$ Y( M+P-N+1 ), 1, ONE, D, 1 )** Solve triangular system: R11*x = d1*CALL DTRSV( 'Upper', 'No Transpose', 'Non unit', M, A, LDA, D, 1 )** Copy D to X*CALL DCOPY( M, D, 1, X, 1 )** Backward transformation y = Z'*y*CALL DORMRQ( 'Left', 'Transpose', P, 1, NP,$ B( MAX( 1, N-P+1 ), 1 ), LDB, WORK( M+1 ), Y,$ MAX( 1, P ), WORK( M+NP+1 ), LWORK-M-NP, INFO )WORK( 1 ) = M + NP + MAX( LOPT, INT( WORK( M+NP+1 ) ) )*RETURN** End of DGGGLM*ENDSUBROUTINE DGGLSE( M, N, P, A, LDA, B, LDB, C, D, X, WORK, LWORK,$ INFO )** -- LAPACK driver 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, LDB, LWORK, M, N, P* ..* .. Array Arguments ..DOUBLE PRECISION A( LDA, * ), B( LDB, * ), C( * ), D( * ),$ WORK( * ), X( * )* ..** Purpose* =======** DGGLSE solves the linear equality-constrained least squares (LSE)* problem:** minimize || c - A*x ||_2 subject to B*x = d** where A is an M-by-N matrix, B is a P-by-N matrix, c is a given* M-vector, and d is a given P-vector. It is assumed that* P <= N <= M+P, and** rank(B) = P and rank( ( A ) ) = N.* ( ( B ) )** These conditions ensure that the LSE problem has a unique solution,* which is obtained using a GRQ factorization of the matrices B and A.** Arguments* =========** M (input) INTEGER* The number of rows of the matrix A. M >= 0.** N (input) INTEGER* The number of columns of the matrices A and B. N >= 0.** P (input) INTEGER* The number of rows of the matrix B. 0 <= P <= N <= M+P.** A (input/output) DOUBLE PRECISION array, dimension (LDA,N)* On entry, the M-by-N matrix A.* On exit, A is destroyed.** 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, B is destroyed.** LDB (input) INTEGER* The leading dimension of the array B. LDB >= max(1,P).** C (input/output) DOUBLE PRECISION array, dimension (M)* On entry, C contains the right hand side vector for the* least squares part of the LSE problem.* On exit, the residual sum of squares for the solution* is given by the sum of squares of elements N-P+1 to M of* vector C.** D (input/output) DOUBLE PRECISION array, dimension (P)* On entry, D contains the right hand side vector for the* constrained equation.* On exit, D is destroyed.** X (output) DOUBLE PRECISION array, dimension (N)* On exit, X is the solution of the LSE problem.** 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+N+P).* For optimum performance LWORK >= P+min(M,N)+max(M,N)*NB,* where NB is an upper bound for the optimal blocksizes for* DGEQRF, SGERQF, DORMQR and SORMRQ.** 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 ONEPARAMETER ( ONE = 1.0D+0 )* ..* .. Local Scalars ..LOGICAL LQUERYINTEGER LOPT, LWKOPT, MN, NB, NB1, NB2, NB3, NB4, NR* ..* .. External Subroutines ..EXTERNAL DAXPY, DCOPY, DGEMV, DGGRQF, DORMQR, DORMRQ,$ DTRMV, DTRSV, XERBLA* ..* .. External Functions ..INTEGER ILAENVEXTERNAL ILAENV* ..* .. Intrinsic Functions ..INTRINSIC INT, MAX, MIN* ..* .. Executable Statements ..** Test the input parameters*INFO = 0MN = MIN( M, N )NB1 = ILAENV( 1, 'DGEQRF', ' ', M, N, -1, -1 )NB2 = ILAENV( 1, 'DGERQF', ' ', M, N, -1, -1 )NB3 = ILAENV( 1, 'DORMQR', ' ', M, N, P, -1 )NB4 = ILAENV( 1, 'DORMRQ', ' ', M, N, P, -1 )NB = MAX( NB1, NB2, NB3, NB4 )LWKOPT = P + MN + MAX( M, N )*NBWORK( 1 ) = LWKOPTLQUERY = ( LWORK.EQ.-1 )IF( M.LT.0 ) THENINFO = -1ELSE IF( N.LT.0 ) THENINFO = -2ELSE IF( P.LT.0 .OR. P.GT.N .OR. P.LT.N-M ) THENINFO = -3ELSE IF( LDA.LT.MAX( 1, M ) ) THENINFO = -5ELSE IF( LDB.LT.MAX( 1, P ) ) THENINFO = -7ELSE IF( LWORK.LT.MAX( 1, M+N+P ) .AND. .NOT.LQUERY ) THENINFO = -12END IFIF( INFO.NE.0 ) THENCALL XERBLA( 'DGGLSE', -INFO )RETURNELSE IF( LQUERY ) THENRETURNEND IF** Quick return if possible*IF( N.EQ.0 )$ RETURN** Compute the GRQ factorization of matrices B and A:** B*Q' = ( 0 T12 ) P Z'*A*Q' = ( R11 R12 ) N-P* N-P P ( 0 R22 ) M+P-N* N-P P** where T12 and R11 are upper triangular, and Q and Z are* orthogonal.*CALL DGGRQF( P, M, N, B, LDB, WORK, A, LDA, WORK( P+1 ),$ WORK( P+MN+1 ), LWORK-P-MN, INFO )LOPT = WORK( P+MN+1 )** Update c = Z'*c = ( c1 ) N-P* ( c2 ) M+P-N*CALL DORMQR( 'Left', 'Transpose', M, 1, MN, A, LDA, WORK( P+1 ),$ C, MAX( 1, M ), WORK( P+MN+1 ), LWORK-P-MN, INFO )LOPT = MAX( LOPT, INT( WORK( P+MN+1 ) ) )** Solve T12*x2 = d for x2*CALL DTRSV( 'Upper', 'No transpose', 'Non unit', P, B( 1, N-P+1 ),$ LDB, D, 1 )** Update c1*CALL DGEMV( 'No transpose', N-P, P, -ONE, A( 1, N-P+1 ), LDA, D,$ 1, ONE, C, 1 )** Sovle R11*x1 = c1 for x1*CALL DTRSV( 'Upper', 'No transpose', 'Non unit', N-P, A, LDA, C,$ 1 )** Put the solutions in X*CALL DCOPY( N-P, C, 1, X, 1 )CALL DCOPY( P, D, 1, X( N-P+1 ), 1 )** Compute the residual vector:*IF( M.LT.N ) THENNR = M + P - NCALL DGEMV( 'No transpose', NR, N-M, -ONE, A( N-P+1, M+1 ),$ LDA, D( NR+1 ), 1, ONE, C( N-P+1 ), 1 )ELSENR = PEND IFCALL DTRMV( 'Upper', 'No transpose', 'Non unit', NR,$ A( N-P+1, N-P+1 ), LDA, D, 1 )CALL DAXPY( NR, -ONE, D, 1, C( N-P+1 ), 1 )** Backward transformation x = Q'*x*CALL DORMRQ( 'Left', 'Transpose', N, 1, P, B, LDB, WORK( 1 ), X,$ N, WORK( P+MN+1 ), LWORK-P-MN, INFO )WORK( 1 ) = P + MN + MAX( LOPT, INT( WORK( P+MN+1 ) ) )*RETURN** End of DGGLSE*ENDSUBROUTINE DGGSVD( JOBU, JOBV, JOBQ, M, N, P, K, L, A, LDA, B,$ LDB, ALPHA, BETA, U, LDU, V, LDV, Q, LDQ, WORK,$ IWORK, INFO )** -- LAPACK driver 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, P* ..* .. Array Arguments ..INTEGER IWORK( * )DOUBLE PRECISION A( LDA, * ), ALPHA( * ), B( LDB, * ),$ BETA( * ), Q( LDQ, * ), U( LDU, * ),$ V( LDV, * ), WORK( * )* ..** Purpose* =======** DGGSVD computes the generalized singular value decomposition (GSVD)* of an M-by-N real matrix A and P-by-N real matrix B:** U'*A*Q = D1*( 0 R ), V'*B*Q = D2*( 0 R )** where U, V and Q are orthogonal matrices, and Z' is the transpose* of Z. Let K+L = the effective numerical rank of the matrix (A',B')',* then R is a K+L-by-K+L nonsingular upper triangular matrix, D1 and* D2 are M-by-(K+L) and P-by-(K+L) "diagonal" matrices and of the* following structures, respectively:** 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 )* L ( 0 0 R22 )** 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.** (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 routine computes C, S, R, and optionally the orthogonal* transformation matrices U, V and Q.** In particular, if B is an N-by-N nonsingular matrix, then the GSVD of* A and B implicitly gives the SVD of A*inv(B):* A*inv(B) = U*(D1*inv(D2))*V'.* If ( A',B')' has orthonormal columns, then the GSVD of A and B is* also equal to the CS decomposition of A and B. Furthermore, the GSVD* can be used to derive the solution of the eigenvalue problem:* A'*A x = lambda* B'*B x.* In some literature, the GSVD of A and B is presented in the form* U'*A*X = ( 0 D1 ), V'*B*X = ( 0 D2 )* where U and V are orthogonal and X is nonsingular, D1 and D2 are* ``diagonal''. The former GSVD form can be converted to the latter* form by taking the nonsingular matrix X as** X = Q*( I 0 )* ( 0 inv(R) ).** Arguments* =========** JOBU (input) CHARACTER*1* = 'U': Orthogonal matrix U is computed;* = 'N': U is not computed.** JOBV (input) CHARACTER*1* = 'V': Orthogonal matrix V is computed;* = 'N': V is not computed.** JOBQ (input) CHARACTER*1* = 'Q': Orthogonal matrix Q is computed;* = 'N': Q is not computed.** M (input) INTEGER* The number of rows of the matrix A. M >= 0.** N (input) INTEGER* The number of columns of the matrices A and B. N >= 0.** P (input) INTEGER* The number of rows of the matrix B. P >= 0.** K (output) INTEGER* L (output) INTEGER* On exit, K and L specify the dimension of the subblocks* described in the Purpose section.* K + L = effective numerical rank of (A',B')'.** A (input/output) DOUBLE PRECISION array, dimension (LDA,N)* On entry, the M-by-N matrix A.* On exit, A 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, B contains the triangular matrix R if M-K-L < 0.* See Purpose for details.** LDB (input) INTEGER* The leading dimension of the array B. LDA >= max(1,P).** 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) = C,* BETA(K+1:K+L) = 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* and* ALPHA(K+L+1:N) = 0* BETA(K+L+1:N) = 0** U (output) DOUBLE PRECISION array, dimension (LDU,M)* If JOBU = 'U', U contains the M-by-M orthogonal matrix 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 (output) DOUBLE PRECISION array, dimension (LDV,P)* If JOBV = 'V', V contains the P-by-P orthogonal matrix 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 (output) DOUBLE PRECISION array, dimension (LDQ,N)* If JOBQ = 'Q', Q contains the N-by-N orthogonal matrix 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 (max(3*N,M,P)+N)** IWORK (workspace/output) INTEGER array, dimension (N)* On exit, IWORK stores the sorting information. More* precisely, the following loop will sort ALPHA* for I = K+1, min(M,K+L)* swap ALPHA(I) and ALPHA(IWORK(I))* endfor* such that ALPHA(1) >= ALPHA(2) >= ... >= ALPHA(N).** INFO (output)INTEGER* = 0: successful exit* < 0: if INFO = -i, the i-th argument had an illegal value.* > 0: if INFO = 1, the Jacobi-type procedure failed to* converge. For further details, see subroutine DTGSJA.** Internal Parameters* ===================** TOLA DOUBLE PRECISION* TOLB DOUBLE PRECISION* TOLA and TOLB are the thresholds to determine the effective* rank of (A',B')'. Generally, they are set to* TOLA = MAX(M,N)*norm(A)*MAZHEPS,* TOLB = MAX(P,N)*norm(B)*MAZHEPS.* The size of TOLA and TOLB may affect the size of backward* errors of the decomposition.** Further Details* ===============** 2-96 Based on modifications by* Ming Gu and Huan Ren, Computer Science Division, University of* California at Berkeley, USA** =====================================================================** .. Local Scalars ..LOGICAL WANTQ, WANTU, WANTVINTEGER I, IBND, ISUB, J, NCYCLEDOUBLE PRECISION ANORM, BNORM, SMAX, TEMP, TOLA, TOLB, ULP, UNFL* ..* .. External Functions ..LOGICAL LSAMEDOUBLE PRECISION DLAMCH, DLANGEEXTERNAL LSAME, DLAMCH, DLANGE* ..* .. External Subroutines ..EXTERNAL DCOPY, DGGSVP, DTGSJA, XERBLA* ..* .. Intrinsic Functions ..INTRINSIC MAX, MIN* ..* .. Executable Statements ..** Test the input parameters*WANTU = LSAME( JOBU, 'U' )WANTV = LSAME( JOBV, 'V' )WANTQ = LSAME( JOBQ, 'Q' )*INFO = 0IF( .NOT.( WANTU .OR. LSAME( JOBU, 'N' ) ) ) THENINFO = -1ELSE IF( .NOT.( WANTV .OR. LSAME( JOBV, 'N' ) ) ) THENINFO = -2ELSE IF( .NOT.( WANTQ .OR. LSAME( JOBQ, 'N' ) ) ) THENINFO = -3ELSE IF( M.LT.0 ) THENINFO = -4ELSE IF( N.LT.0 ) THENINFO = -5ELSE IF( P.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 = -16ELSE IF( LDV.LT.1 .OR. ( WANTV .AND. LDV.LT.P ) ) THENINFO = -18ELSE IF( LDQ.LT.1 .OR. ( WANTQ .AND. LDQ.LT.N ) ) THENINFO = -20END IFIF( INFO.NE.0 ) THENCALL XERBLA( 'DGGSVD', -INFO )RETURNEND IF** Compute the Frobenius norm of matrices A and B*ANORM = DLANGE( '1', M, N, A, LDA, WORK )BNORM = DLANGE( '1', P, N, B, LDB, WORK )** Get machine precision and set up threshold for determining* the effective numerical rank of the matrices A and B.*ULP = DLAMCH( 'Precision' )UNFL = DLAMCH( 'Safe Minimum' )TOLA = MAX( M, N )*MAX( ANORM, UNFL )*ULPTOLB = MAX( P, N )*MAX( BNORM, UNFL )*ULP** Preprocessing*CALL DGGSVP( JOBU, JOBV, JOBQ, M, P, N, A, LDA, B, LDB, TOLA,$ TOLB, K, L, U, LDU, V, LDV, Q, LDQ, IWORK, WORK,$ WORK( N+1 ), INFO )** Compute the GSVD of two upper "triangular" matrices*CALL 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 )** Sort the singular values and store the pivot indices in IWORK* Copy ALPHA to WORK, then sort ALPHA in WORK*CALL DCOPY( N, ALPHA, 1, WORK, 1 )IBND = MIN( L, M-K )DO 20 I = 1, IBND** Scan for largest ALPHA(K+I)*ISUB = ISMAX = WORK( K+I )DO 10 J = I + 1, IBNDTEMP = WORK( K+J )IF( TEMP.GT.SMAX ) THENISUB = JSMAX = TEMPEND IF10 CONTINUEIF( ISUB.NE.I ) THENWORK( K+ISUB ) = WORK( K+I )WORK( K+I ) = SMAXIWORK( K+I ) = K + ISUBELSEIWORK( K+I ) = K + IEND IF20 CONTINUE*RETURN** End of DGGSVD*ENDSUBROUTINE DLANV2( A, B, C, D, RT1R, RT1I, RT2R, RT2I, CS, SN )** -- LAPACK driver 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 ..DOUBLE PRECISION A, B, C, CS, D, RT1I, RT1R, RT2I, RT2R, SN* ..** Purpose* =======** DLANV2 computes the Schur factorization of a real 2-by-2 nonsymmetric* matrix in standard form:** [ A B ] = [ CS -SN ] [ AA BB ] [ CS SN ]* [ C D ] [ SN CS ] [ CC DD ] [-SN CS ]** where either* 1) CC = 0 so that AA and DD are real eigenvalues of the matrix, or* 2) AA = DD and BB*CC < 0, so that AA + or - sqrt(BB*CC) are complex* conjugate eigenvalues.** Arguments* =========** A (input/output) DOUBLE PRECISION* B (input/output) DOUBLE PRECISION* C (input/output) DOUBLE PRECISION* D (input/output) DOUBLE PRECISION* On entry, the elements of the input matrix.* On exit, they are overwritten by the elements of the* standardised Schur form.** RT1R (output) DOUBLE PRECISION* RT1I (output) DOUBLE PRECISION* RT2R (output) DOUBLE PRECISION* RT2I (output) DOUBLE PRECISION* The real and imaginary parts of the eigenvalues. If the* eigenvalues are a complex conjugate pair, RT1I > 0.** CS (output) DOUBLE PRECISION* SN (output) DOUBLE PRECISION* Parameters of the rotation matrix.** Further Details* ===============** Modified by V. Sima, Research Institute for Informatics, Bucharest,* Romania, to reduce the risk of cancellation errors,* when computing real eigenvalues, and to ensure, if possible, that* abs(RT1R) >= abs(RT2R).** =====================================================================** .. Parameters ..DOUBLE PRECISION ZERO, HALF, ONEPARAMETER ( ZERO = 0.0D+0, HALF = 0.5D+0, ONE = 1.0D+0 )DOUBLE PRECISION MULTPLPARAMETER ( MULTPL = 4.0D+0 )* ..* .. Local Scalars ..DOUBLE PRECISION AA, BB, BCMAX, BCMIS, CC, CS1, DD, EPS, P, SAB,$ SAC, SCALE, SIGMA, SN1, TAU, TEMP, Z* ..* .. External Functions ..DOUBLE PRECISION DLAMCH, DLAPY2EXTERNAL DLAMCH, DLAPY2* ..* .. Intrinsic Functions ..INTRINSIC ABS, MAX, MIN, SIGN, SQRT* ..* .. Executable Statements ..*EPS = DLAMCH( 'P' )IF( C.EQ.ZERO ) THENCS = ONESN = ZEROGO TO 10*ELSE IF( B.EQ.ZERO ) THEN** Swap rows and columns*CS = ZEROSN = ONETEMP = DD = AA = TEMPB = -CC = ZEROGO TO 10ELSE IF( ( A-D ).EQ.ZERO .AND. SIGN( ONE, B ).NE.SIGN( ONE, C ) )$ THENCS = ONESN = ZEROGO TO 10ELSE*TEMP = A - DP = HALF*TEMPBCMAX = MAX( ABS( B ), ABS( C ) )BCMIS = MIN( ABS( B ), ABS( C ) )*SIGN( ONE, B )*SIGN( ONE, C )SCALE = MAX( ABS( P ), BCMAX )Z = ( P / SCALE )*P + ( BCMAX / SCALE )*BCMIS** If Z is of the order of the machine accuracy, postpone the* decision on the nature of eigenvalues*IF( Z.GE.MULTPL*EPS ) THEN** Real eigenvalues. Compute A and D.*Z = P + SIGN( SQRT( SCALE )*SQRT( Z ), P )A = D + ZD = D - ( BCMAX / Z )*BCMIS** Compute B and the rotation matrix*TAU = DLAPY2( C, Z )CS = Z / TAUSN = C / TAUB = B - CC = ZEROELSE** Complex eigenvalues, or real (almost) equal eigenvalues.* Make diagonal elements equal.*SIGMA = B + CTAU = DLAPY2( SIGMA, TEMP )CS = SQRT( HALF*( ONE+ABS( SIGMA ) / TAU ) )SN = -( P / ( TAU*CS ) )*SIGN( ONE, SIGMA )** Compute [ AA BB ] = [ A B ] [ CS -SN ]* [ CC DD ] [ C D ] [ SN CS ]*AA = A*CS + B*SNBB = -A*SN + B*CSCC = C*CS + D*SNDD = -C*SN + D*CS** Compute [ A B ] = [ CS SN ] [ AA BB ]* [ C D ] [-SN CS ] [ CC DD ]*A = AA*CS + CC*SNB = BB*CS + DD*SNC = -AA*SN + CC*CSD = -BB*SN + DD*CS*TEMP = HALF*( A+D )A = TEMPD = TEMP*IF( C.NE.ZERO ) THENIF( B.NE.ZERO ) THENIF( SIGN( ONE, B ).EQ.SIGN( ONE, C ) ) THEN** Real eigenvalues: reduce to upper triangular form*SAB = SQRT( ABS( B ) )SAC = SQRT( ABS( C ) )P = SIGN( SAB*SAC, C )TAU = ONE / SQRT( ABS( B+C ) )A = TEMP + PD = TEMP - PB = B - CC = ZEROCS1 = SAB*TAUSN1 = SAC*TAUTEMP = CS*CS1 - SN*SN1SN = CS*SN1 + SN*CS1CS = TEMPEND IFELSEB = -CC = ZEROTEMP = CSCS = -SNSN = TEMPEND IFEND IFEND IF*END IF*10 CONTINUE** Store eigenvalues in (RT1R,RT1I) and (RT2R,RT2I).*RT1R = ART2R = DIF( C.EQ.ZERO ) THENRT1I = ZERORT2I = ZEROELSERT1I = SQRT( ABS( B ) )*SQRT( ABS( C ) )RT2I = -RT1IEND IFRETURN** End of DLANV2*ENDSUBROUTINE DPBSV( UPLO, N, KD, NRHS, AB, LDAB, B, LDB, INFO )** -- LAPACK driver 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, LDB, N, NRHS* ..* .. Array Arguments ..DOUBLE PRECISION AB( LDAB, * ), B( LDB, * )* ..** Purpose* =======** DPBSV computes the solution to a real system of linear equations* A * X = B,* where A is an N-by-N symmetric positive definite band matrix and X* and B are N-by-NRHS matrices.** The Cholesky decomposition is used to factor A as* A = U**T * U, if UPLO = 'U', or* A = L * L**T, if UPLO = 'L',* where U is an upper triangular band matrix, and L is a lower* triangular band matrix, with the same number of superdiagonals or* subdiagonals as A. The factored form of A is then used to solve the* system of equations A * X = B.** Arguments* =========** UPLO (input) CHARACTER*1* = 'U': Upper triangle of A is stored;* = 'L': Lower triangle of A is stored.** N (input) INTEGER* The number of linear equations, i.e., 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/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).* 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 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.** 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 of A is not* positive definite, so the factorization could not be* completed, and the solution has not been computed.** 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.** =====================================================================** .. External Functions ..LOGICAL LSAMEEXTERNAL LSAME* ..* .. External Subroutines ..EXTERNAL DPBTRF, DPBTRS, 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( 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( 'DPBSV ', -INFO )RETURNEND IF** Compute the Cholesky factorization A = U'*U or A = L*L'.*CALL DPBTRF( UPLO, N, KD, AB, LDAB, INFO )IF( INFO.EQ.0 ) THEN** Solve the system A*X = B, overwriting B with X.*CALL DPBTRS( UPLO, N, KD, NRHS, AB, LDAB, B, LDB, INFO )*END IFRETURN** End of DPBSV*ENDSUBROUTINE DPBSVX( FACT, UPLO, N, KD, NRHS, AB, LDAB, AFB, LDAFB,$ EQUED, S, B, LDB, X, LDX, RCOND, FERR, BERR,$ WORK, IWORK, INFO )** -- LAPACK driver 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 EQUED, FACT, UPLOINTEGER INFO, KD, LDAB, LDAFB, LDB, LDX, N, NRHSDOUBLE PRECISION RCOND* ..* .. Array Arguments ..INTEGER IWORK( * )DOUBLE PRECISION AB( LDAB, * ), AFB( LDAFB, * ), B( LDB, * ),$ BERR( * ), FERR( * ), S( * ), WORK( * ),$ X( LDX, * )* ..** Purpose* =======** DPBSVX uses the Cholesky factorization A = U**T*U or A = L*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 band 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 = 'E', real scaling factors are computed to equilibrate* the system:* diag(S) * A * diag(S) * inv(diag(S)) * X = diag(S) * B* Whether or not the system will be equilibrated depends on the* scaling of the matrix A, but if equilibration is used, A is* overwritten by diag(S)*A*diag(S) and B by diag(S)*B.** 2. If FACT = 'N' or 'E', the Cholesky decomposition is used to* factor the matrix A (after equilibration if FACT = 'E') as* A = U**T * U, if UPLO = 'U', or* A = L * L**T, if UPLO = 'L',* where U is an upper triangular band matrix, and L is a lower* triangular band matrix.** 3. 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.** 4. The system of equations is solved for X using the factored form* of A.** 5. Iterative refinement is applied to improve the computed solution* matrix and calculate error bounds and backward error estimates* for it.** 6. If equilibration was used, the matrix X is premultiplied by* diag(S) so that it solves the original system before* equilibration.** Arguments* =========** FACT (input) CHARACTER*1* Specifies whether or not the factored form of the matrix A is* supplied on entry, and if not, whether the matrix A should be* equilibrated before it is factored.* = 'F': On entry, AFB contains the factored form of A.* If EQUED = 'Y', the matrix A has been equilibrated* with scaling factors given by S. AB and AFB will not* be modified.* = 'N': The matrix A will be copied to AFB and factored.* = 'E': The matrix A will be equilibrated if necessary, then* copied to AFB and factored.** UPLO (input) CHARACTER*1* = 'U': Upper triangle of A is stored;* = 'L': Lower triangle of A is stored.** N (input) INTEGER* The number of linear equations, i.e., 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/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, except* if FACT = 'F' and EQUED = 'Y', then A must contain the* equilibrated matrix diag(S)*A*diag(S). 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).* See below for further details.** On exit, if FACT = 'E' and EQUED = 'Y', A is overwritten by* diag(S)*A*diag(S).** LDAB (input) INTEGER* The leading dimension of the array A. LDAB >= KD+1.** AFB (input or output) DOUBLE PRECISION array, dimension (LDAFB,N)* If FACT = 'F', then AFB is an input argument and on entry* contains 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 (see AB). If EQUED = 'Y',* then AFB is the factored form of the equilibrated matrix A.** If FACT = 'N', then AFB is an output argument and on exit* returns the triangular factor U or L from the Cholesky* factorization A = U**T*U or A = L*L**T.** If FACT = 'E', then AFB is an output argument and on exit* returns the triangular factor U or L from the Cholesky* factorization A = U**T*U or A = L*L**T of the equilibrated* matrix A (see the description of A for the form of the* equilibrated matrix).** LDAFB (input) INTEGER* The leading dimension of the array AFB. LDAFB >= KD+1.** EQUED (input or output) CHARACTER*1* Specifies the form of equilibration that was done.* = 'N': No equilibration (always true if FACT = 'N').* = 'Y': Equilibration was done, i.e., A has been replaced by* diag(S) * A * diag(S).* EQUED is an input argument if FACT = 'F'; otherwise, it is an* output argument.** S (input or output) DOUBLE PRECISION array, dimension (N)* The scale factors for A; not accessed if EQUED = 'N'. S is* an input argument if FACT = 'F'; otherwise, S is an output* argument. If FACT = 'F' and EQUED = 'Y', each element of S* must be positive.** B (input/output) DOUBLE PRECISION array, dimension (LDB,NRHS)* On entry, the N-by-NRHS right hand side matrix B.* On exit, if EQUED = 'N', B is not modified; if EQUED = 'Y',* B is overwritten by diag(S) * 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 or INFO = N+1, the N-by-NRHS solution matrix X to* the original system of equations. Note that if EQUED = 'Y',* A and B are modified on exit, and the solution to the* equilibrated system is inv(diag(S))*X.** LDX (input) INTEGER* The leading dimension of the array X. LDX >= max(1,N).** RCOND (output) DOUBLE PRECISION* The estimate of the reciprocal condition number of the matrix* A after equilibration (if done). 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 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* > 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.** Further Details* ===============** The band storage scheme is illustrated by the following example, when* N = 6, KD = 2, and UPLO = 'U':** Two-dimensional storage of the symmetric matrix A:** a11 a12 a13* a22 a23 a24* a33 a34 a35* a44 a45 a46* a55 a56* (aij=conjg(aji)) a66** Band storage of the upper triangle of A:** * * a13 a24 a35 a46* * a12 a23 a34 a45 a56* a11 a22 a33 a44 a55 a66** Similarly, if UPLO = 'L' the format of A is as follows:** a11 a22 a33 a44 a55 a66* a21 a32 a43 a54 a65 ** a31 a42 a53 a64 * *** Array elements marked * are not used by the routine.** =====================================================================** .. Parameters ..DOUBLE PRECISION ZERO, ONEPARAMETER ( ZERO = 0.0D+0, ONE = 1.0D+0 )* ..* .. Local Scalars ..LOGICAL EQUIL, NOFACT, RCEQU, UPPERINTEGER I, INFEQU, J, J1, J2DOUBLE PRECISION AMAX, ANORM, BIGNUM, SCOND, SMAX, SMIN, SMLNUM* ..* .. External Functions ..LOGICAL LSAMEDOUBLE PRECISION DLAMCH, DLANSBEXTERNAL LSAME, DLAMCH, DLANSB* ..* .. External Subroutines ..EXTERNAL DCOPY, DLACPY, DLAQSB, DPBCON, DPBEQU, DPBRFS,$ DPBTRF, DPBTRS, XERBLA* ..* .. Intrinsic Functions ..INTRINSIC MAX, MIN* ..* .. Executable Statements ..*INFO = 0NOFACT = LSAME( FACT, 'N' )EQUIL = LSAME( FACT, 'E' )UPPER = LSAME( UPLO, 'U' )IF( NOFACT .OR. EQUIL ) THENEQUED = 'N'RCEQU = .FALSE.ELSERCEQU = LSAME( EQUED, 'Y' )SMLNUM = DLAMCH( 'Safe minimum' )BIGNUM = ONE / SMLNUMEND IF** Test the input parameters.*IF( .NOT.NOFACT .AND. .NOT.EQUIL .AND. .NOT.LSAME( FACT, 'F' ) )$ 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( NRHS.LT.0 ) THENINFO = -5ELSE IF( LDAB.LT.KD+1 ) THENINFO = -7ELSE IF( LDAFB.LT.KD+1 ) THENINFO = -9ELSE IF( LSAME( FACT, 'F' ) .AND. .NOT.$ ( RCEQU .OR. LSAME( EQUED, 'N' ) ) ) THENINFO = -10ELSEIF( RCEQU ) THENSMIN = BIGNUMSMAX = ZERODO 10 J = 1, NSMIN = MIN( SMIN, S( J ) )SMAX = MAX( SMAX, S( J ) )10 CONTINUEIF( SMIN.LE.ZERO ) THENINFO = -11ELSE IF( N.GT.0 ) THENSCOND = MAX( SMIN, SMLNUM ) / MIN( SMAX, BIGNUM )ELSESCOND = ONEEND IFEND IFIF( INFO.EQ.0 ) THENIF( LDB.LT.MAX( 1, N ) ) THENINFO = -13ELSE IF( LDX.LT.MAX( 1, N ) ) THENINFO = -15END IFEND IFEND IF*IF( INFO.NE.0 ) THENCALL XERBLA( 'DPBSVX', -INFO )RETURNEND IF*IF( EQUIL ) THEN** Compute row and column scalings to equilibrate the matrix A.*CALL DPBEQU( UPLO, N, KD, AB, LDAB, S, SCOND, AMAX, INFEQU )IF( INFEQU.EQ.0 ) THEN** Equilibrate the matrix.*CALL DLAQSB( UPLO, N, KD, AB, LDAB, S, SCOND, AMAX, EQUED )RCEQU = LSAME( EQUED, 'Y' )END IFEND IF** Scale the right-hand side.*IF( RCEQU ) THENDO 30 J = 1, NRHSDO 20 I = 1, NB( I, J ) = S( I )*B( I, J )20 CONTINUE30 CONTINUEEND IF*IF( NOFACT .OR. EQUIL ) THEN** Compute the Cholesky factorization A = U'*U or A = L*L'.*IF( UPPER ) THENDO 40 J = 1, NJ1 = MAX( J-KD, 1 )CALL DCOPY( J-J1+1, AB( KD+1-J+J1, J ), 1,$ AFB( KD+1-J+J1, J ), 1 )40 CONTINUEELSEDO 50 J = 1, NJ2 = MIN( J+KD, N )CALL DCOPY( J2-J+1, AB( 1, J ), 1, AFB( 1, J ), 1 )50 CONTINUEEND IF*CALL DPBTRF( UPLO, N, KD, AFB, LDAFB, 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 = DLANSB( '1', UPLO, N, KD, AB, LDAB, WORK )** Compute the reciprocal of the condition number of A.*CALL DPBCON( UPLO, N, KD, AFB, LDAFB, ANORM, RCOND, WORK, IWORK,$ INFO )** Set INFO = N+1 if the matrix is singular to working precision.*IF( RCOND.LT.DLAMCH( 'Epsilon' ) )$ INFO = N + 1** Compute the solution matrix X.*CALL DLACPY( 'Full', N, NRHS, B, LDB, X, LDX )CALL DPBTRS( UPLO, N, KD, NRHS, AFB, LDAFB, X, LDX, INFO )** Use iterative refinement to improve the computed solution and* compute error bounds and backward error estimates for it.*CALL DPBRFS( UPLO, N, KD, NRHS, AB, LDAB, AFB, LDAFB, B, LDB, X,$ LDX, FERR, BERR, WORK, IWORK, INFO )** Transform the solution matrix X to a solution of the original* system.*IF( RCEQU ) THENDO 70 J = 1, NRHSDO 60 I = 1, NX( I, J ) = S( I )*X( I, J )60 CONTINUE70 CONTINUEDO 80 J = 1, NRHSFERR( J ) = FERR( J ) / SCOND80 CONTINUEEND IF*RETURN** End of DPBSVX*ENDSUBROUTINE DPOSV( UPLO, N, NRHS, A, LDA, B, LDB, INFO )** -- LAPACK driver 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* =======** DPOSV computes the solution to a real system of linear equations* A * X = B,* where A is an N-by-N symmetric positive definite matrix and X and B* are N-by-NRHS matrices.** The Cholesky decomposition is used to factor A as* 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 a lower triangular* matrix. The factored form of A is then used to solve the system of* equations A * X = B.** Arguments* =========** UPLO (input) CHARACTER*1* = 'U': Upper triangle of A is stored;* = 'L': Lower triangle of A is stored.** N (input) INTEGER* The number of linear equations, i.e., the order of the* matrix A. N >= 0.** NRHS (input) INTEGER* The number of right hand sides, i.e., the number of columns* of the matrix B. NRHS >= 0.** A (input/output) DOUBLE PRECISION array, dimension (LDA,N)* On entry, the 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).** 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 of A is not* positive definite, so the factorization could not be* completed, and the solution has not been computed.** =====================================================================** .. External Functions ..LOGICAL LSAMEEXTERNAL LSAME* ..* .. External Subroutines ..EXTERNAL DPOTRF, DPOTRS, 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( 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( 'DPOSV ', -INFO )RETURNEND IF** Compute the Cholesky factorization A = U'*U or A = L*L'.*CALL DPOTRF( UPLO, N, A, LDA, INFO )IF( INFO.EQ.0 ) THEN** Solve the system A*X = B, overwriting B with X.*CALL DPOTRS( UPLO, N, NRHS, A, LDA, B, LDB, INFO )*END IFRETURN** End of DPOSV*ENDSUBROUTINE DPOSVX( FACT, UPLO, N, NRHS, A, LDA, AF, LDAF, EQUED,$ S, B, LDB, X, LDX, RCOND, FERR, BERR, WORK,$ IWORK, INFO )** -- LAPACK driver 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 EQUED, FACT, UPLOINTEGER INFO, LDA, LDAF, LDB, LDX, N, NRHSDOUBLE PRECISION RCOND* ..* .. Array Arguments ..INTEGER IWORK( * )DOUBLE PRECISION A( LDA, * ), AF( LDAF, * ), B( LDB, * ),$ BERR( * ), FERR( * ), S( * ), WORK( * ),$ X( LDX, * )* ..** Purpose* =======** DPOSVX uses the Cholesky factorization A = U**T*U or A = L*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 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 = 'E', real scaling factors are computed to equilibrate* the system:* diag(S) * A * diag(S) * inv(diag(S)) * X = diag(S) * B* Whether or not the system will be equilibrated depends on the* scaling of the matrix A, but if equilibration is used, A is* overwritten by diag(S)*A*diag(S) and B by diag(S)*B.** 2. If FACT = 'N' or 'E', the Cholesky decomposition is used to* factor the matrix A (after equilibration if FACT = 'E') as* 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 a lower triangular* matrix.** 3. 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.** 4. The system of equations is solved for X using the factored form* of A.** 5. Iterative refinement is applied to improve the computed solution* matrix and calculate error bounds and backward error estimates* for it.** 6. If equilibration was used, the matrix X is premultiplied by* diag(S) so that it solves the original system before* equilibration.** Arguments* =========** FACT (input) CHARACTER*1* Specifies whether or not the factored form of the matrix A is* supplied on entry, and if not, whether the matrix A should be* equilibrated before it is factored.* = 'F': On entry, AF contains the factored form of A.* If EQUED = 'Y', the matrix A has been equilibrated* with scaling factors given by S. A and AF will not* be modified.* = 'N': The matrix A will be copied to AF and factored.* = 'E': The matrix A will be equilibrated if necessary, then* copied to AF and factored.** UPLO (input) CHARACTER*1* = 'U': Upper triangle of A is stored;* = 'L': Lower triangle of A is stored.** N (input) INTEGER* The number of linear equations, i.e., the order of the* matrix A. N >= 0.** NRHS (input) INTEGER* The number of right hand sides, i.e., the number of columns* of the matrices B and X. NRHS >= 0.** A (input/output) DOUBLE PRECISION array, dimension (LDA,N)* On entry, the symmetric matrix A, except if FACT = 'F' and* EQUED = 'Y', then A must contain the equilibrated matrix* diag(S)*A*diag(S). 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. A is not modified if* FACT = 'F' or 'N', or if FACT = 'E' and EQUED = 'N' on exit.** On exit, if FACT = 'E' and EQUED = 'Y', A is overwritten by* diag(S)*A*diag(S).** LDA (input) INTEGER* The leading dimension of the array A. LDA >= max(1,N).** AF (input or output) DOUBLE PRECISION array, dimension (LDAF,N)* If FACT = 'F', then AF is an input argument and on entry* contains 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. If EQUED .ne. 'N', then AF is the factored form* of the equilibrated matrix diag(S)*A*diag(S).** If FACT = 'N', then AF is an output argument and on exit* returns the triangular factor U or L from the Cholesky* factorization A = U**T*U or A = L*L**T of the original* matrix A.** If FACT = 'E', then AF is an output argument and on exit* returns the triangular factor U or L from the Cholesky* factorization A = U**T*U or A = L*L**T of the equilibrated* matrix A (see the description of A for the form of the* equilibrated matrix).** LDAF (input) INTEGER* The leading dimension of the array AF. LDAF >= max(1,N).** EQUED (input or output) CHARACTER*1* Specifies the form of equilibration that was done.* = 'N': No equilibration (always true if FACT = 'N').* = 'Y': Equilibration was done, i.e., A has been replaced by* diag(S) * A * diag(S).* EQUED is an input argument if FACT = 'F'; otherwise, it is an* output argument.** S (input or output) DOUBLE PRECISION array, dimension (N)* The scale factors for A; not accessed if EQUED = 'N'. S is* an input argument if FACT = 'F'; otherwise, S is an output* argument. If FACT = 'F' and EQUED = 'Y', each element of S* must be positive.** B (input/output) DOUBLE PRECISION array, dimension (LDB,NRHS)* On entry, the N-by-NRHS right hand side matrix B.* On exit, if EQUED = 'N', B is not modified; if EQUED = 'Y',* B is overwritten by diag(S) * 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 or INFO = N+1, the N-by-NRHS solution matrix X to* the original system of equations. Note that if EQUED = 'Y',* A and B are modified on exit, and the solution to the* equilibrated system is inv(diag(S))*X.** LDX (input) INTEGER* The leading dimension of the array X. LDX >= max(1,N).** RCOND (output) DOUBLE PRECISION* The estimate of the reciprocal condition number of the matrix* A after equilibration (if done). 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 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* > 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 ZERO, ONEPARAMETER ( ZERO = 0.0D+0, ONE = 1.0D+0 )* ..* .. Local Scalars ..LOGICAL EQUIL, NOFACT, RCEQUINTEGER I, INFEQU, JDOUBLE PRECISION AMAX, ANORM, BIGNUM, SCOND, SMAX, SMIN, SMLNUM* ..* .. External Functions ..LOGICAL LSAMEDOUBLE PRECISION DLAMCH, DLANSYEXTERNAL LSAME, DLAMCH, DLANSY* ..* .. External Subroutines ..EXTERNAL DLACPY, DLAQSY, DPOCON, DPOEQU, DPORFS, DPOTRF,$ DPOTRS, XERBLA* ..* .. Intrinsic Functions ..INTRINSIC MAX, MIN* ..* .. Executable Statements ..*INFO = 0NOFACT = LSAME( FACT, 'N' )EQUIL = LSAME( FACT, 'E' )IF( NOFACT .OR. EQUIL ) THENEQUED = 'N'RCEQU = .FALSE.ELSERCEQU = LSAME( EQUED, 'Y' )SMLNUM = DLAMCH( 'Safe minimum' )BIGNUM = ONE / SMLNUMEND IF** Test the input parameters.*IF( .NOT.NOFACT .AND. .NOT.EQUIL .AND. .NOT.LSAME( FACT, 'F' ) )$ THENINFO = -1ELSE IF( .NOT.LSAME( UPLO, 'U' ) .AND. .NOT.LSAME( UPLO, 'L' ) )$ THENINFO = -2ELSE IF( N.LT.0 ) THENINFO = -3ELSE IF( NRHS.LT.0 ) THENINFO = -4ELSE IF( LDA.LT.MAX( 1, N ) ) THENINFO = -6ELSE IF( LDAF.LT.MAX( 1, N ) ) THENINFO = -8ELSE IF( LSAME( FACT, 'F' ) .AND. .NOT.$ ( RCEQU .OR. LSAME( EQUED, 'N' ) ) ) THENINFO = -9ELSEIF( RCEQU ) THENSMIN = BIGNUMSMAX = ZERODO 10 J = 1, NSMIN = MIN( SMIN, S( J ) )SMAX = MAX( SMAX, S( J ) )10 CONTINUEIF( SMIN.LE.ZERO ) THENINFO = -10ELSE IF( N.GT.0 ) THENSCOND = MAX( SMIN, SMLNUM ) / MIN( SMAX, BIGNUM )ELSESCOND = ONEEND IFEND IFIF( INFO.EQ.0 ) THENIF( LDB.LT.MAX( 1, N ) ) THENINFO = -12ELSE IF( LDX.LT.MAX( 1, N ) ) THENINFO = -14END IFEND IFEND IF*IF( INFO.NE.0 ) THENCALL XERBLA( 'DPOSVX', -INFO )RETURNEND IF*IF( EQUIL ) THEN** Compute row and column scalings to equilibrate the matrix A.*CALL DPOEQU( N, A, LDA, S, SCOND, AMAX, INFEQU )IF( INFEQU.EQ.0 ) THEN** Equilibrate the matrix.*CALL DLAQSY( UPLO, N, A, LDA, S, SCOND, AMAX, EQUED )RCEQU = LSAME( EQUED, 'Y' )END IFEND IF** Scale the right hand side.*IF( RCEQU ) THENDO 30 J = 1, NRHSDO 20 I = 1, NB( I, J ) = S( I )*B( I, J )20 CONTINUE30 CONTINUEEND IF*IF( NOFACT .OR. EQUIL ) THEN** Compute the Cholesky factorization A = U'*U or A = L*L'.*CALL DLACPY( UPLO, N, N, A, LDA, AF, LDAF )CALL DPOTRF( UPLO, N, AF, LDAF, 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 = DLANSY( '1', UPLO, N, A, LDA, WORK )** Compute the reciprocal of the condition number of A.*CALL DPOCON( UPLO, N, AF, LDAF, ANORM, RCOND, WORK, IWORK, INFO )** Set INFO = N+1 if the matrix is singular to working precision.*IF( RCOND.LT.DLAMCH( 'Epsilon' ) )$ INFO = N + 1** Compute the solution matrix X.*CALL DLACPY( 'Full', N, NRHS, B, LDB, X, LDX )CALL DPOTRS( UPLO, N, NRHS, AF, LDAF, X, LDX, INFO )** Use iterative refinement to improve the computed solution and* compute error bounds and backward error estimates for it.*CALL DPORFS( UPLO, N, NRHS, A, LDA, AF, LDAF, B, LDB, X, LDX,$ FERR, BERR, WORK, IWORK, INFO )** Transform the solution matrix X to a solution of the original* system.*IF( RCEQU ) THENDO 50 J = 1, NRHSDO 40 I = 1, NX( I, J ) = S( I )*X( I, J )40 CONTINUE50 CONTINUEDO 60 J = 1, NRHSFERR( J ) = FERR( J ) / SCOND60 CONTINUEEND IF*RETURN** End of DPOSVX*ENDSUBROUTINE DPPSV( UPLO, N, NRHS, AP, B, LDB, INFO )** -- LAPACK driver 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* =======** DPPSV computes the solution to a real system of linear equations* A * X = B,* where A is an N-by-N symmetric positive definite matrix stored in* packed format and X and B are N-by-NRHS matrices.** The Cholesky decomposition is used to factor A as* 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 a lower triangular* matrix. The factored form of A is then used to solve the system of* equations A * X = B.** Arguments* =========** UPLO (input) CHARACTER*1* = 'U': Upper triangle of A is stored;* = 'L': Lower triangle of A is stored.** N (input) INTEGER* The number of linear equations, i.e., the order of the* matrix A. N >= 0.** NRHS (input) INTEGER* The number of right hand sides, i.e., the number of columns* of the matrix B. NRHS >= 0.** 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 factor U or L from the Cholesky* factorization A = U**T*U or A = L*L**T, in the same storage* format as 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 of A is not* positive definite, so the factorization could not be* completed, and the solution has not been computed.** 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 = conjg(aji))* a44** Packed storage of the upper triangle of A:** AP = [ a11, a12, a22, a13, a23, a33, a14, a24, a34, a44 ]** =====================================================================** .. External Functions ..LOGICAL LSAMEEXTERNAL LSAME* ..* .. External Subroutines ..EXTERNAL DPPTRF, DPPTRS, 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( NRHS.LT.0 ) THENINFO = -3ELSE IF( LDB.LT.MAX( 1, N ) ) THENINFO = -6END IFIF( INFO.NE.0 ) THENCALL XERBLA( 'DPPSV ', -INFO )RETURNEND IF** Compute the Cholesky factorization A = U'*U or A = L*L'.*CALL DPPTRF( UPLO, N, AP, INFO )IF( INFO.EQ.0 ) THEN** Solve the system A*X = B, overwriting B with X.*CALL DPPTRS( UPLO, N, NRHS, AP, B, LDB, INFO )*END IFRETURN** End of DPPSV*ENDSUBROUTINE DPPSVX( FACT, UPLO, N, NRHS, AP, AFP, EQUED, S, B, LDB,$ X, LDX, RCOND, FERR, BERR, WORK, IWORK, INFO )** -- LAPACK driver 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 EQUED, FACT, UPLOINTEGER INFO, LDB, LDX, N, NRHSDOUBLE PRECISION RCOND* ..* .. Array Arguments ..INTEGER IWORK( * )DOUBLE PRECISION AFP( * ), AP( * ), B( LDB, * ), BERR( * ),$ FERR( * ), S( * ), WORK( * ), X( LDX, * )* ..** Purpose* =======** DPPSVX uses the Cholesky factorization A = U**T*U or A = L*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 matrix stored in* packed format 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 = 'E', real scaling factors are computed to equilibrate* the system:* diag(S) * A * diag(S) * inv(diag(S)) * X = diag(S) * B* Whether or not the system will be equilibrated depends on the* scaling of the matrix A, but if equilibration is used, A is* overwritten by diag(S)*A*diag(S) and B by diag(S)*B.** 2. If FACT = 'N' or 'E', the Cholesky decomposition is used to* factor the matrix A (after equilibration if FACT = 'E') as* 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 a lower triangular* matrix.** 3. 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.** 4. The system of equations is solved for X using the factored form* of A.** 5. Iterative refinement is applied to improve the computed solution* matrix and calculate error bounds and backward error estimates* for it.** 6. If equilibration was used, the matrix X is premultiplied by* diag(S) so that it solves the original system before* equilibration.** Arguments* =========** FACT (input) CHARACTER*1* Specifies whether or not the factored form of the matrix A is* supplied on entry, and if not, whether the matrix A should be* equilibrated before it is factored.* = 'F': On entry, AFP contains the factored form of A.* If EQUED = 'Y', the matrix A has been equilibrated* with scaling factors given by S. AP and AFP will not* be modified.* = 'N': The matrix A will be copied to AFP and factored.* = 'E': The matrix A will be equilibrated if necessary, then* copied to AFP and factored.** UPLO (input) CHARACTER*1* = 'U': Upper triangle of A is stored;* = 'L': Lower triangle of A is stored.** N (input) INTEGER* The number of linear equations, i.e., the order of the* matrix A. N >= 0.** NRHS (input) INTEGER* The number of right hand sides, i.e., the number of columns* of the matrices B and X. NRHS >= 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, except if FACT = 'F'* and EQUED = 'Y', then A must contain the equilibrated matrix* diag(S)*A*diag(S). 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. A is not modified if* FACT = 'F' or 'N', or if FACT = 'E' and EQUED = 'N' on exit.** On exit, if FACT = 'E' and EQUED = 'Y', A is overwritten by* diag(S)*A*diag(S).** AFP (input or output) DOUBLE PRECISION array, dimension* (N*(N+1)/2)* If FACT = 'F', then AFP is an input argument and on entry* contains the triangular factor U or L from the Cholesky* factorization A = U'*U or A = L*L', in the same storage* format as A. If EQUED .ne. 'N', then AFP is the factored* form of the equilibrated matrix A.** If FACT = 'N', then AFP is an output argument and on exit* returns the triangular factor U or L from the Cholesky* factorization A = U'*U or A = L*L' of the original matrix A.** If FACT = 'E', then AFP is an output argument and on exit* returns the triangular factor U or L from the Cholesky* factorization A = U'*U or A = L*L' of the equilibrated* matrix A (see the description of AP for the form of the* equilibrated matrix).** EQUED (input or output) CHARACTER*1* Specifies the form of equilibration that was done.* = 'N': No equilibration (always true if FACT = 'N').* = 'Y': Equilibration was done, i.e., A has been replaced by* diag(S) * A * diag(S).* EQUED is an input argument if FACT = 'F'; otherwise, it is an* output argument.** S (input or output) DOUBLE PRECISION array, dimension (N)* The scale factors for A; not accessed if EQUED = 'N'. S is* an input argument if FACT = 'F'; otherwise, S is an output* argument. If FACT = 'F' and EQUED = 'Y', each element of S* must be positive.** B (input/output) DOUBLE PRECISION array, dimension (LDB,NRHS)* On entry, the N-by-NRHS right hand side matrix B.* On exit, if EQUED = 'N', B is not modified; if EQUED = 'Y',* B is overwritten by diag(S) * 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 or INFO = N+1, the N-by-NRHS solution matrix X to* the original system of equations. Note that if EQUED = 'Y',* A and B are modified on exit, and the solution to the* equilibrated system is inv(diag(S))*X.** LDX (input) INTEGER* The leading dimension of the array X. LDX >= max(1,N).** RCOND (output) DOUBLE PRECISION* The estimate of the reciprocal condition number of the matrix* A after equilibration (if done). 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 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* > 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.** 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 = conjg(aji))* a44** Packed storage of the upper triangle of A:** AP = [ a11, a12, a22, a13, a23, a33, a14, a24, a34, a44 ]** =====================================================================** .. Parameters ..DOUBLE PRECISION ZERO, ONEPARAMETER ( ZERO = 0.0D+0, ONE = 1.0D+0 )* ..* .. Local Scalars ..LOGICAL EQUIL, NOFACT, RCEQUINTEGER I, INFEQU, JDOUBLE PRECISION AMAX, ANORM, BIGNUM, SCOND, SMAX, SMIN, SMLNUM* ..* .. External Functions ..LOGICAL LSAMEDOUBLE PRECISION DLAMCH, DLANSPEXTERNAL LSAME, DLAMCH, DLANSP* ..* .. External Subroutines ..EXTERNAL DCOPY, DLACPY, DLAQSP, DPPCON, DPPEQU, DPPRFS,$ DPPTRF, DPPTRS, XERBLA* ..* .. Intrinsic Functions ..INTRINSIC MAX, MIN* ..* .. Executable Statements ..*INFO = 0NOFACT = LSAME( FACT, 'N' )EQUIL = LSAME( FACT, 'E' )IF( NOFACT .OR. EQUIL ) THENEQUED = 'N'RCEQU = .FALSE.ELSERCEQU = LSAME( EQUED, 'Y' )SMLNUM = DLAMCH( 'Safe minimum' )BIGNUM = ONE / SMLNUMEND IF** Test the input parameters.*IF( .NOT.NOFACT .AND. .NOT.EQUIL .AND. .NOT.LSAME( FACT, 'F' ) )$ THENINFO = -1ELSE IF( .NOT.LSAME( UPLO, 'U' ) .AND. .NOT.LSAME( UPLO, 'L' ) )$ THENINFO = -2ELSE IF( N.LT.0 ) THENINFO = -3ELSE IF( NRHS.LT.0 ) THENINFO = -4ELSE IF( LSAME( FACT, 'F' ) .AND. .NOT.$ ( RCEQU .OR. LSAME( EQUED, 'N' ) ) ) THENINFO = -7ELSEIF( RCEQU ) THENSMIN = BIGNUMSMAX = ZERODO 10 J = 1, NSMIN = MIN( SMIN, S( J ) )SMAX = MAX( SMAX, S( J ) )10 CONTINUEIF( SMIN.LE.ZERO ) THENINFO = -8ELSE IF( N.GT.0 ) THENSCOND = MAX( SMIN, SMLNUM ) / MIN( SMAX, BIGNUM )ELSESCOND = ONEEND IFEND IFIF( INFO.EQ.0 ) THENIF( LDB.LT.MAX( 1, N ) ) THENINFO = -10ELSE IF( LDX.LT.MAX( 1, N ) ) THENINFO = -12END IFEND IFEND IF*IF( INFO.NE.0 ) THENCALL XERBLA( 'DPPSVX', -INFO )RETURNEND IF*IF( EQUIL ) THEN** Compute row and column scalings to equilibrate the matrix A.*CALL DPPEQU( UPLO, N, AP, S, SCOND, AMAX, INFEQU )IF( INFEQU.EQ.0 ) THEN** Equilibrate the matrix.*CALL DLAQSP( UPLO, N, AP, S, SCOND, AMAX, EQUED )RCEQU = LSAME( EQUED, 'Y' )END IFEND IF** Scale the right-hand side.*IF( RCEQU ) THENDO 30 J = 1, NRHSDO 20 I = 1, NB( I, J ) = S( I )*B( I, J )20 CONTINUE30 CONTINUEEND IF*IF( NOFACT .OR. EQUIL ) THEN** Compute the Cholesky factorization A = U'*U or A = L*L'.*CALL DCOPY( N*( N+1 ) / 2, AP, 1, AFP, 1 )CALL DPPTRF( UPLO, N, AFP, 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 = DLANSP( 'I', UPLO, N, AP, WORK )** Compute the reciprocal of the condition number of A.*CALL DPPCON( UPLO, N, AFP, ANORM, RCOND, WORK, IWORK, INFO )** Set INFO = N+1 if the matrix is singular to working precision.*IF( RCOND.LT.DLAMCH( 'Epsilon' ) )$ INFO = N + 1** Compute the solution matrix X.*CALL DLACPY( 'Full', N, NRHS, B, LDB, X, LDX )CALL DPPTRS( UPLO, N, NRHS, AFP, X, LDX, INFO )** Use iterative refinement to improve the computed solution and* compute error bounds and backward error estimates for it.*CALL DPPRFS( UPLO, N, NRHS, AP, AFP, B, LDB, X, LDX, FERR, BERR,$ WORK, IWORK, INFO )** Transform the solution matrix X to a solution of the original* system.*IF( RCEQU ) THENDO 50 J = 1, NRHSDO 40 I = 1, NX( I, J ) = S( I )*X( I, J )40 CONTINUE50 CONTINUEDO 60 J = 1, NRHSFERR( J ) = FERR( J ) / SCOND60 CONTINUEEND IF*RETURN** End of DPPSVX*ENDSUBROUTINE DSBEV( JOBZ, UPLO, N, KD, AB, LDAB, W, Z, LDZ, WORK,$ INFO )** -- LAPACK driver 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, UPLOINTEGER INFO, KD, LDAB, LDZ, N* ..* .. Array Arguments ..DOUBLE PRECISION AB( LDAB, * ), W( * ), WORK( * ), Z( LDZ, * )* ..** Purpose* =======** DSBEV computes all the eigenvalues and, optionally, eigenvectors of* a real symmetric band matrix A.** Arguments* =========** JOBZ (input) CHARACTER*1* = 'N': Compute eigenvalues only;* = 'V': Compute eigenvalues and eigenvectors.** 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, AB is overwritten by values generated during the* reduction to tridiagonal form. If UPLO = 'U', the first* superdiagonal and the diagonal of the tridiagonal matrix T* are returned in rows KD and KD+1 of AB, and if UPLO = 'L',* the diagonal and first subdiagonal of T are returned in the* first two rows of AB.** LDAB (input) INTEGER* The leading dimension of the array AB. LDAB >= KD + 1.** W (output) DOUBLE PRECISION array, dimension (N)* If INFO = 0, the eigenvalues in ascending order.** Z (output) DOUBLE PRECISION array, dimension (LDZ, N)* If JOBZ = 'V', then if INFO = 0, Z contains the orthonormal* eigenvectors of the matrix A, with the i-th column of Z* holding the eigenvector associated with W(i).* If JOBZ = 'N', then Z is not referenced.** LDZ (input) INTEGER* The leading dimension of the array Z. LDZ >= 1, and if* JOBZ = 'V', LDZ >= max(1,N).** WORK (workspace) DOUBLE PRECISION array, dimension (max(1,3*N-2))** INFO (output) INTEGER* = 0: successful exit* < 0: if INFO = -i, the i-th argument had an illegal value* > 0: if INFO = i, the algorithm failed to converge; i* off-diagonal elements of an intermediate tridiagonal* form did not converge to zero.** =====================================================================** .. Parameters ..DOUBLE PRECISION ZERO, ONEPARAMETER ( ZERO = 0.0D0, ONE = 1.0D0 )* ..* .. Local Scalars ..LOGICAL LOWER, WANTZINTEGER IINFO, IMAX, INDE, INDWRK, ISCALEDOUBLE PRECISION ANRM, BIGNUM, EPS, RMAX, RMIN, SAFMIN, SIGMA,$ SMLNUM* ..* .. External Functions ..LOGICAL LSAMEDOUBLE PRECISION DLAMCH, DLANSBEXTERNAL LSAME, DLAMCH, DLANSB* ..* .. External Subroutines ..EXTERNAL DLASCL, DSBTRD, DSCAL, DSTEQR, DSTERF, XERBLA* ..* .. Intrinsic Functions ..INTRINSIC SQRT* ..* .. Executable Statements ..** Test the input parameters.*WANTZ = LSAME( JOBZ, 'V' )LOWER = LSAME( UPLO, 'L' )*INFO = 0IF( .NOT.( WANTZ .OR. LSAME( JOBZ, 'N' ) ) ) THENINFO = -1ELSE IF( .NOT.( LOWER .OR. LSAME( UPLO, 'U' ) ) ) THENINFO = -2ELSE IF( N.LT.0 ) THENINFO = -3ELSE IF( KD.LT.0 ) THENINFO = -4ELSE IF( LDAB.LT.KD+1 ) THENINFO = -6ELSE IF( LDZ.LT.1 .OR. ( WANTZ .AND. LDZ.LT.N ) ) THENINFO = -9END IF*IF( INFO.NE.0 ) THENCALL XERBLA( 'DSBEV ', -INFO )RETURNEND IF** Quick return if possible*IF( N.EQ.0 )$ RETURN*IF( N.EQ.1 ) THENIF( LOWER ) THENW( 1 ) = AB( 1, 1 )ELSEW( 1 ) = AB( KD+1, 1 )END 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 = SQRT( BIGNUM )** Scale matrix to allowable range, if necessary.*ANRM = DLANSB( 'M', UPLO, N, KD, AB, LDAB, WORK )ISCALE = 0IF( ANRM.GT.ZERO .AND. ANRM.LT.RMIN ) THENISCALE = 1SIGMA = RMIN / ANRMELSE IF( ANRM.GT.RMAX ) THENISCALE = 1SIGMA = RMAX / ANRMEND IFIF( ISCALE.EQ.1 ) THENIF( LOWER ) THENCALL DLASCL( 'B', KD, KD, ONE, SIGMA, N, N, AB, LDAB, INFO )ELSECALL DLASCL( 'Q', KD, KD, ONE, SIGMA, N, N, AB, LDAB, INFO )END IFEND IF** Call DSBTRD to reduce symmetric band matrix to tridiagonal form.*INDE = 1INDWRK = INDE + NCALL DSBTRD( JOBZ, UPLO, N, KD, AB, LDAB, W, WORK( INDE ), Z, LDZ,$ WORK( INDWRK ), IINFO )** For eigenvalues only, call DSTERF. For eigenvectors, call SSTEQR.*IF( .NOT.WANTZ ) THENCALL DSTERF( N, W, WORK( INDE ), INFO )ELSECALL DSTEQR( JOBZ, N, W, WORK( INDE ), Z, LDZ, WORK( INDWRK ),$ INFO )END IF** If matrix was scaled, then rescale eigenvalues appropriately.*IF( ISCALE.EQ.1 ) THENIF( INFO.EQ.0 ) THENIMAX = NELSEIMAX = INFO - 1END IFCALL DSCAL( IMAX, ONE / SIGMA, W, 1 )END IF*RETURN** End of DSBEV*ENDSUBROUTINE DSBEVD( JOBZ, UPLO, N, KD, AB, LDAB, W, Z, LDZ, WORK,$ LWORK, IWORK, LIWORK, INFO )** -- LAPACK driver 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, UPLOINTEGER INFO, KD, LDAB, LDZ, LIWORK, LWORK, N* ..* .. Array Arguments ..INTEGER IWORK( * )DOUBLE PRECISION AB( LDAB, * ), W( * ), WORK( * ), Z( LDZ, * )* ..** Purpose* =======** DSBEVD computes all the eigenvalues and, optionally, eigenvectors of* a real symmetric band matrix A. If eigenvectors are desired, it uses* a divide and conquer algorithm.** The divide and conquer algorithm makes very mild assumptions about* floating point arithmetic. It will work on machines with a guard* digit in add/subtract, or on those binary machines without guard* digits which subtract like the Cray X-MP, Cray Y-MP, Cray C-90, or* Cray-2. It could conceivably fail on hexadecimal or decimal machines* without guard digits, but we know of none.** Arguments* =========** JOBZ (input) CHARACTER*1* = 'N': Compute eigenvalues only;* = 'V': Compute eigenvalues and eigenvectors.** 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, AB is overwritten by values generated during the* reduction to tridiagonal form. If UPLO = 'U', the first* superdiagonal and the diagonal of the tridiagonal matrix T* are returned in rows KD and KD+1 of AB, and if UPLO = 'L',* the diagonal and first subdiagonal of T are returned in the* first two rows of AB.** LDAB (input) INTEGER* The leading dimension of the array AB. LDAB >= KD + 1.** W (output) DOUBLE PRECISION array, dimension (N)* If INFO = 0, the eigenvalues in ascending order.** Z (output) DOUBLE PRECISION array, dimension (LDZ, N)* If JOBZ = 'V', then if INFO = 0, Z contains the orthonormal* eigenvectors of the matrix A, with the i-th column of Z* holding the eigenvector associated with W(i).* If JOBZ = 'N', then Z is not referenced.** LDZ (input) INTEGER* The leading dimension of the array Z. LDZ >= 1, and if* JOBZ = 'V', LDZ >= max(1,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.* IF N <= 1, LWORK must be at least 1.* If JOBZ = 'N' and N > 2, LWORK must be at least 2*N.* If JOBZ = 'V' and N > 2, LWORK must be at least* ( 1 + 5*N + 2*N**2 ).** 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 LIWORK.* If JOBZ = 'N' or N <= 1, LIWORK must be at least 1.* If JOBZ = 'V' and N > 2, LIWORK must be at least 3 + 5*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 = i, the algorithm failed to converge; i* off-diagonal elements of an intermediate tridiagonal* form did not converge to zero.** =====================================================================** .. Parameters ..DOUBLE PRECISION ZERO, ONEPARAMETER ( ZERO = 0.0D+0, ONE = 1.0D+0 )* ..* .. Local Scalars ..LOGICAL LOWER, LQUERY, WANTZINTEGER IINFO, INDE, INDWK2, INDWRK, ISCALE, LIWMIN,$ LLWRK2, LWMINDOUBLE PRECISION ANRM, BIGNUM, EPS, RMAX, RMIN, SAFMIN, SIGMA,$ SMLNUM* ..* .. External Functions ..LOGICAL LSAMEDOUBLE PRECISION DLAMCH, DLANSBEXTERNAL LSAME, DLAMCH, DLANSB* ..* .. External Subroutines ..EXTERNAL DGEMM, DLACPY, DLASCL, DSBTRD, DSCAL, DSTEDC,$ DSTERF, XERBLA* ..* .. Intrinsic Functions ..INTRINSIC SQRT* ..* .. Executable Statements ..** Test the input parameters.*WANTZ = LSAME( JOBZ, 'V' )LOWER = LSAME( UPLO, 'L' )LQUERY = ( LWORK.EQ.-1 .OR. LIWORK.EQ.-1 )*INFO = 0IF( N.LE.1 ) THENLIWMIN = 1LWMIN = 1ELSEIF( WANTZ ) THENLIWMIN = 3 + 5*NLWMIN = 1 + 5*N + 2*N**2ELSELIWMIN = 1LWMIN = 2*NEND IFEND IFIF( .NOT.( WANTZ .OR. LSAME( JOBZ, 'N' ) ) ) THENINFO = -1ELSE IF( .NOT.( LOWER .OR. LSAME( UPLO, 'U' ) ) ) THENINFO = -2ELSE IF( N.LT.0 ) THENINFO = -3ELSE IF( KD.LT.0 ) THENINFO = -4ELSE IF( LDAB.LT.KD+1 ) THENINFO = -6ELSE IF( LDZ.LT.1 .OR. ( WANTZ .AND. LDZ.LT.N ) ) THENINFO = -9ELSE IF( LWORK.LT.LWMIN .AND. .NOT.LQUERY ) THENINFO = -11ELSE IF( LIWORK.LT.LIWMIN .AND. .NOT.LQUERY ) THENINFO = -13END IF*IF( INFO.EQ.0 ) THENWORK( 1 ) = LWMINIWORK( 1 ) = LIWMINEND IF*IF( INFO.NE.0 ) THENCALL XERBLA( 'DSBEVD', -INFO )RETURNELSE IF( LQUERY ) THENRETURNEND IF** Quick return if possible*IF( N.EQ.0 )$ RETURN*IF( N.EQ.1 ) THENW( 1 ) = AB( 1, 1 )IF( WANTZ )$ Z( 1, 1 ) = ONERETURNEND IF** Get machine constants.*SAFMIN = DLAMCH( 'Safe minimum' )EPS = DLAMCH( 'Precision' )SMLNUM = SAFMIN / EPSBIGNUM = ONE / SMLNUMRMIN = SQRT( SMLNUM )RMAX = SQRT( BIGNUM )** Scale matrix to allowable range, if necessary.*ANRM = DLANSB( 'M', UPLO, N, KD, AB, LDAB, WORK )ISCALE = 0IF( ANRM.GT.ZERO .AND. ANRM.LT.RMIN ) THENISCALE = 1SIGMA = RMIN / ANRMELSE IF( ANRM.GT.RMAX ) THENISCALE = 1SIGMA = RMAX / ANRMEND IFIF( ISCALE.EQ.1 ) THENIF( LOWER ) THENCALL DLASCL( 'B', KD, KD, ONE, SIGMA, N, N, AB, LDAB, INFO )ELSECALL DLASCL( 'Q', KD, KD, ONE, SIGMA, N, N, AB, LDAB, INFO )END IFEND IF** Call DSBTRD to reduce symmetric band matrix to tridiagonal form.*INDE = 1INDWRK = INDE + NINDWK2 = INDWRK + N*NLLWRK2 = LWORK - INDWK2 + 1CALL DSBTRD( JOBZ, UPLO, N, KD, AB, LDAB, W, WORK( INDE ), Z, LDZ,$ WORK( INDWRK ), IINFO )** For eigenvalues only, call DSTERF. For eigenvectors, call SSTEDC.*IF( .NOT.WANTZ ) THENCALL DSTERF( N, W, WORK( INDE ), INFO )ELSECALL DSTEDC( 'I', N, W, WORK( INDE ), WORK( INDWRK ), N,$ WORK( INDWK2 ), LLWRK2, IWORK, LIWORK, INFO )CALL DGEMM( 'N', 'N', N, N, N, ONE, Z, LDZ, WORK( INDWRK ), N,$ ZERO, WORK( INDWK2 ), N )CALL DLACPY( 'A', N, N, WORK( INDWK2 ), N, Z, LDZ )END IF** If matrix was scaled, then rescale eigenvalues appropriately.*IF( ISCALE.EQ.1 )$ CALL DSCAL( N, ONE / SIGMA, W, 1 )*WORK( 1 ) = LWMINIWORK( 1 ) = LIWMINRETURN** End of DSBEVD*ENDSUBROUTINE DSBEVX( JOBZ, RANGE, UPLO, N, KD, AB, LDAB, Q, LDQ, VL,$ VU, IL, IU, ABSTOL, M, W, Z, LDZ, WORK, IWORK,$ IFAIL, INFO )** -- LAPACK driver 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, RANGE, UPLOINTEGER IL, INFO, IU, KD, LDAB, LDQ, LDZ, M, NDOUBLE PRECISION ABSTOL, VL, VU* ..* .. Array Arguments ..INTEGER IFAIL( * ), IWORK( * )DOUBLE PRECISION AB( LDAB, * ), Q( LDQ, * ), W( * ), WORK( * ),$ Z( LDZ, * )* ..** Purpose* =======** DSBEVX computes selected eigenvalues and, optionally, eigenvectors* of a real symmetric band matrix A. Eigenvalues and eigenvectors can* be selected by specifying either a range of values or a range of* indices for the desired eigenvalues.** Arguments* =========** JOBZ (input) CHARACTER*1* = 'N': Compute eigenvalues only;* = 'V': Compute eigenvalues and eigenvectors.** RANGE (input) CHARACTER*1* = 'A': all eigenvalues will be found;* = 'V': all eigenvalues in the half-open interval (VL,VU]* will be found;* = 'I': the IL-th through IU-th eigenvalues will be found.** UPLO (input) CHARACTER*1* = 'U': Upper triangle of A is stored;* = 'L': Lower triangle of A is stored.** N (input) INTEGER* The order of the matrix A. N >= 0.** 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, AB is overwritten by values generated during the* reduction to tridiagonal form. If UPLO = 'U', the first* superdiagonal and the diagonal of the tridiagonal matrix T* are returned in rows KD and KD+1 of AB, and if UPLO = 'L',* the diagonal and first subdiagonal of T are returned in the* first two rows of AB.** LDAB (input) INTEGER* The leading dimension of the array AB. LDAB >= KD + 1.** Q (output) DOUBLE PRECISION array, dimension (LDQ, N)* If JOBZ = 'V', the N-by-N orthogonal matrix used in the* reduction to tridiagonal form.* If JOBZ = 'N', the array Q is not referenced.** LDQ (input) INTEGER* The leading dimension of the array Q. If JOBZ = 'V', then* LDQ >= max(1,N).** 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.* An approximate eigenvalue is accepted as converged* when it is determined to lie in an interval [a,b]* of width less than or equal to** ABSTOL + EPS * max( |a|,|b| ) ,** where EPS is the machine precision. If ABSTOL is less than* or equal to zero, then EPS*|T| will be used in its place,* where |T| is the 1-norm of the tridiagonal matrix obtained* by reducing AB to tridiagonal form.** Eigenvalues will be computed most accurately when ABSTOL is* set to twice the underflow threshold 2*DLAMCH('S'), not zero.* If this routine returns with INFO>0, indicating that some* eigenvectors did not converge, try setting ABSTOL to* 2*DLAMCH('S').** See "Computing Small Singular Values of Bidiagonal Matrices* with Guaranteed High Relative Accuracy," by Demmel and* Kahan, LAPACK Working Note #3.** M (output) INTEGER* The total number of eigenvalues found. 0 <= M <= N.* If RANGE = 'A', M = N, and if RANGE = 'I', M = IU-IL+1.** W (output) DOUBLE PRECISION array, dimension (N)* 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 A* corresponding to the selected eigenvalues, with the i-th* column of Z holding the eigenvector associated with W(i).* If an eigenvector fails to converge, then that column of Z* contains the latest approximation to the eigenvector, and the* index of the eigenvector is returned in IFAIL.* If JOBZ = 'N', then Z is not referenced.* Note: the user must ensure that at least max(1,M) columns are* supplied in the array Z; if RANGE = 'V', the exact value of M* is not known in advance and an upper bound must be used.** LDZ (input) INTEGER* The leading dimension of the array Z. LDZ >= 1, and if* JOBZ = 'V', LDZ >= max(1,N).** WORK (workspace) DOUBLE PRECISION array, dimension (7*N)** IWORK (workspace) INTEGER array, dimension (5*N)** IFAIL (output) INTEGER array, dimension (N)* If JOBZ = 'V', then if INFO = 0, the first M elements of* IFAIL are zero. If INFO > 0, then IFAIL contains the* indices of the eigenvectors that failed to converge.* If JOBZ = 'N', then IFAIL is not referenced.** INFO (output) INTEGER* = 0: successful exit.* < 0: if INFO = -i, the i-th argument had an illegal value.* > 0: if INFO = i, then i eigenvectors failed to converge.* Their indices are stored in array IFAIL.** =====================================================================** .. Parameters ..DOUBLE PRECISION ZERO, ONEPARAMETER ( ZERO = 0.0D0, ONE = 1.0D0 )* ..* .. Local Scalars ..LOGICAL ALLEIG, INDEIG, LOWER, VALEIG, WANTZCHARACTER ORDERINTEGER I, IINFO, IMAX, INDD, INDE, INDEE, INDIBL,$ INDISP, INDIWO, INDWRK, ISCALE, ITMP1, J, JJ,$ NSPLITDOUBLE PRECISION ABSTLL, ANRM, BIGNUM, EPS, RMAX, RMIN, SAFMIN,$ SIGMA, SMLNUM, TMP1, VLL, VUU* ..* .. External Functions ..LOGICAL LSAMEDOUBLE PRECISION DLAMCH, DLANSBEXTERNAL LSAME, DLAMCH, DLANSB* ..* .. External Subroutines ..EXTERNAL DCOPY, DGEMV, DLACPY, DLASCL, DSBTRD, DSCAL,$ DSTEBZ, DSTEIN, DSTEQR, DSTERF, DSWAP, XERBLA* ..* .. Intrinsic Functions ..INTRINSIC 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' )LOWER = LSAME( UPLO, 'L' )*INFO = 0IF( .NOT.( WANTZ .OR. LSAME( JOBZ, 'N' ) ) ) THENINFO = -1ELSE IF( .NOT.( ALLEIG .OR. VALEIG .OR. INDEIG ) ) THENINFO = -2ELSE IF( .NOT.( LOWER .OR. LSAME( UPLO, 'U' ) ) ) THENINFO = -3ELSE IF( N.LT.0 ) THENINFO = -4ELSE IF( KD.LT.0 ) THENINFO = -5ELSE IF( LDAB.LT.KD+1 ) THENINFO = -7ELSE IF( WANTZ .AND. LDQ.LT.MAX( 1, N ) ) THENINFO = -9ELSEIF( VALEIG ) THENIF( N.GT.0 .AND. VU.LE.VL )$ INFO = -11ELSE IF( INDEIG ) THENIF( IL.LT.1 .OR. IL.GT.MAX( 1, N ) ) THENINFO = -12ELSE IF( IU.LT.MIN( N, IL ) .OR. IU.GT.N ) THENINFO = -13END IFEND IFEND IFIF( INFO.EQ.0 ) THENIF( LDZ.LT.1 .OR. ( WANTZ .AND. LDZ.LT.N ) )$ INFO = -18END IF*IF( INFO.NE.0 ) THENCALL XERBLA( 'DSBEVX', -INFO )RETURNEND IF** Quick return if possible*M = 0IF( N.EQ.0 )$ RETURN*IF( N.EQ.1 ) THENM = 1IF( LOWER ) THENTMP1 = AB( 1, 1 )ELSETMP1 = AB( KD+1, 1 )END IFIF( VALEIG ) THENIF( .NOT.( VL.LT.TMP1 .AND. VU.GE.TMP1 ) )$ M = 0END IFIF( M.EQ.1 ) THENW( 1 ) = TMP1IF( WANTZ )$ Z( 1, 1 ) = ONEEND IFRETURNEND 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.*ISCALE = 0ABSTLL = ABSTOLIF( VALEIG ) THENVLL = VLVUU = VUELSEVLL = ZEROVUU = ZEROEND IFANRM = DLANSB( 'M', UPLO, N, KD, AB, LDAB, WORK )IF( ANRM.GT.ZERO .AND. ANRM.LT.RMIN ) THENISCALE = 1SIGMA = RMIN / ANRMELSE IF( ANRM.GT.RMAX ) THENISCALE = 1SIGMA = RMAX / ANRMEND IFIF( ISCALE.EQ.1 ) THENIF( LOWER ) THENCALL DLASCL( 'B', KD, KD, ONE, SIGMA, N, N, AB, LDAB, INFO )ELSECALL DLASCL( 'Q', KD, KD, ONE, SIGMA, N, N, AB, LDAB, INFO )END IFIF( ABSTOL.GT.0 )$ ABSTLL = ABSTOL*SIGMAIF( VALEIG ) THENVLL = VL*SIGMAVUU = VU*SIGMAEND IFEND IF** Call DSBTRD to reduce symmetric band matrix to tridiagonal form.*INDD = 1INDE = INDD + NINDWRK = INDE + NCALL DSBTRD( JOBZ, UPLO, N, KD, AB, LDAB, WORK( INDD ),$ WORK( INDE ), Q, LDQ, WORK( INDWRK ), IINFO )** If all eigenvalues are desired and ABSTOL is less than or equal* to zero, then call DSTERF or SSTEQR. If this fails for some* eigenvalue, then try DSTEBZ.*IF( ( ALLEIG .OR. ( INDEIG .AND. IL.EQ.1 .AND. IU.EQ.N ) ) .AND.$ ( ABSTOL.LE.ZERO ) ) THENCALL DCOPY( N, WORK( INDD ), 1, W, 1 )INDEE = INDWRK + 2*NIF( .NOT.WANTZ ) THENCALL DCOPY( N-1, WORK( INDE ), 1, WORK( INDEE ), 1 )CALL DSTERF( N, W, WORK( INDEE ), INFO )ELSECALL DLACPY( 'A', N, N, Q, LDQ, Z, LDZ )CALL DCOPY( N-1, WORK( INDE ), 1, WORK( INDEE ), 1 )CALL DSTEQR( JOBZ, N, W, WORK( INDEE ), Z, LDZ,$ WORK( INDWRK ), INFO )IF( INFO.EQ.0 ) THENDO 10 I = 1, NIFAIL( I ) = 010 CONTINUEEND IFEND IFIF( INFO.EQ.0 ) THENM = NGO TO 30END IFINFO = 0END IF** Otherwise, call DSTEBZ and, if eigenvectors are desired, SSTEIN.*IF( WANTZ ) THENORDER = 'B'ELSEORDER = 'E'END IFINDIBL = 1INDISP = INDIBL + NINDIWO = INDISP + NCALL DSTEBZ( RANGE, ORDER, N, VLL, VUU, IL, IU, ABSTLL,$ WORK( INDD ), WORK( INDE ), M, NSPLIT, W,$ IWORK( INDIBL ), IWORK( INDISP ), WORK( INDWRK ),$ IWORK( INDIWO ), INFO )*IF( WANTZ ) THENCALL DSTEIN( N, WORK( INDD ), WORK( INDE ), M, W,$ IWORK( INDIBL ), IWORK( INDISP ), Z, LDZ,$ WORK( INDWRK ), IWORK( INDIWO ), IFAIL, INFO )** Apply orthogonal matrix used in reduction to tridiagonal* form to eigenvectors returned by DSTEIN.*DO 20 J = 1, MCALL DCOPY( N, Z( 1, J ), 1, WORK( 1 ), 1 )CALL DGEMV( 'N', N, N, ONE, Q, LDQ, WORK, 1, ZERO,$ Z( 1, J ), 1 )20 CONTINUEEND IF** If matrix was scaled, then rescale eigenvalues appropriately.*30 CONTINUEIF( ISCALE.EQ.1 ) THENIF( INFO.EQ.0 ) THENIMAX = MELSEIMAX = INFO - 1END IFCALL DSCAL( IMAX, ONE / SIGMA, W, 1 )END IF** If eigenvalues are not in order, then sort them, along with* eigenvectors.*IF( WANTZ ) THENDO 50 J = 1, M - 1I = 0TMP1 = W( J )DO 40 JJ = J + 1, MIF( W( JJ ).LT.TMP1 ) THENI = JJTMP1 = W( JJ )END IF40 CONTINUE*IF( I.NE.0 ) THENITMP1 = IWORK( INDIBL+I-1 )W( I ) = W( J )IWORK( INDIBL+I-1 ) = IWORK( INDIBL+J-1 )W( J ) = TMP1IWORK( INDIBL+J-1 ) = ITMP1CALL DSWAP( N, Z( 1, I ), 1, Z( 1, J ), 1 )IF( INFO.NE.0 ) THENITMP1 = IFAIL( I )IFAIL( I ) = IFAIL( J )IFAIL( J ) = ITMP1END IFEND IF50 CONTINUEEND IF*RETURN** End of DSBEVX*ENDSUBROUTINE DSBGV( JOBZ, UPLO, N, KA, KB, AB, LDAB, BB, LDBB, W, Z,$ LDZ, WORK, INFO )** -- LAPACK driver 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 JOBZ, UPLOINTEGER INFO, KA, KB, LDAB, LDBB, LDZ, N* ..* .. Array Arguments ..DOUBLE PRECISION AB( LDAB, * ), BB( LDBB, * ), W( * ),$ WORK( * ), Z( LDZ, * )* ..** Purpose* =======** DSBGV computes all the eigenvalues, and optionally, the eigenvectors* of a real generalized symmetric-definite banded eigenproblem, of* the form A*x=(lambda)*B*x. Here A and B are assumed to be symmetric* and banded, and B is also positive definite.** Arguments* =========** JOBZ (input) CHARACTER*1* = 'N': Compute eigenvalues only;* = 'V': Compute eigenvalues and eigenvectors.** UPLO (input) CHARACTER*1* = 'U': Upper triangles of A and B are stored;* = 'L': Lower triangles of A and B are 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'. 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 contents of AB are destroyed.** LDAB (input) INTEGER* The leading dimension of the array AB. LDAB >= KA+1.** BB (input/output) DOUBLE PRECISION array, dimension (LDBB, N)* On entry, the upper or lower triangle of the symmetric band* matrix B, stored in the first kb+1 rows of the array. The* j-th column of B is stored in the j-th column of the array BB* as follows:* if UPLO = 'U', BB(kb+1+i-j,j) = B(i,j) for max(1,j-kb)<=i<=j;* if UPLO = 'L', BB(1+i-j,j) = B(i,j) for j<=i<=min(n,j+kb).** On exit, the factor S from the split Cholesky factorization* B = S**T*S, as returned by DPBSTF.** LDBB (input) INTEGER* The leading dimension of the array BB. LDBB >= KB+1.** W (output) DOUBLE PRECISION array, dimension (N)* If INFO = 0, the eigenvalues in ascending order.** Z (output) DOUBLE PRECISION array, dimension (LDZ, N)* If JOBZ = 'V', then if INFO = 0, Z contains the matrix Z of* eigenvectors, with the i-th column of Z holding the* eigenvector associated with W(i). The eigenvectors are* normalized so that Z**T*B*Z = I.* If JOBZ = 'N', then Z is not referenced.** LDZ (input) INTEGER* The leading dimension of the array Z. LDZ >= 1, and if* JOBZ = 'V', LDZ >= N.** 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* > 0: if INFO = i, and i is:* <= N: the algorithm failed to converge:* i off-diagonal elements of an intermediate* tridiagonal form did not converge to zero;* > N: if INFO = N + i, for 1 <= i <= N, then DPBSTF* returned INFO = i: B is not positive definite.* The factorization of B could not be completed and* no eigenvalues or eigenvectors were computed.** =====================================================================** .. Local Scalars ..LOGICAL UPPER, WANTZCHARACTER VECTINTEGER IINFO, INDE, INDWRK* ..* .. External Functions ..LOGICAL LSAMEEXTERNAL LSAME* ..* .. External Subroutines ..EXTERNAL DPBSTF, DSBGST, DSBTRD, DSTEQR, DSTERF, XERBLA* ..* .. Executable Statements ..** Test the input parameters.*WANTZ = LSAME( JOBZ, 'V' )UPPER = LSAME( UPLO, 'U' )*INFO = 0IF( .NOT.( WANTZ .OR. LSAME( JOBZ, 'N' ) ) ) THENINFO = -1ELSE IF( .NOT.( UPPER .OR. LSAME( UPLO, 'L' ) ) ) THENINFO = -2ELSE IF( N.LT.0 ) THENINFO = -3ELSE IF( KA.LT.0 ) THENINFO = -4ELSE IF( KB.LT.0 .OR. KB.GT.KA ) THENINFO = -5ELSE IF( LDAB.LT.KA+1 ) THENINFO = -7ELSE IF( LDBB.LT.KB+1 ) THENINFO = -9ELSE IF( LDZ.LT.1 .OR. ( WANTZ .AND. LDZ.LT.N ) ) THENINFO = -12END IFIF( INFO.NE.0 ) THENCALL XERBLA( 'DSBGV ', -INFO )RETURNEND IF** Quick return if possible*IF( N.EQ.0 )$ RETURN** Form a split Cholesky factorization of B.*CALL DPBSTF( UPLO, N, KB, BB, LDBB, INFO )IF( INFO.NE.0 ) THENINFO = N + INFORETURNEND IF** Transform problem to standard eigenvalue problem.*INDE = 1INDWRK = INDE + NCALL DSBGST( JOBZ, UPLO, N, KA, KB, AB, LDAB, BB, LDBB, Z, LDZ,$ WORK( INDWRK ), IINFO )** Reduce to tridiagonal form.*IF( WANTZ ) THENVECT = 'U'ELSEVECT = 'N'END IFCALL DSBTRD( VECT, UPLO, N, KA, AB, LDAB, W, WORK( INDE ), Z, LDZ,$ WORK( INDWRK ), IINFO )** For eigenvalues only, call DSTERF. For eigenvectors, call SSTEQR.*IF( .NOT.WANTZ ) THENCALL DSTERF( N, W, WORK( INDE ), INFO )ELSECALL DSTEQR( JOBZ, N, W, WORK( INDE ), Z, LDZ, WORK( INDWRK ),$ INFO )END IFRETURN** End of DSBGV*ENDSUBROUTINE DSBGVD( JOBZ, UPLO, N, KA, KB, AB, LDAB, BB, LDBB, W,$ Z, LDZ, WORK, LWORK, IWORK, LIWORK, INFO )** -- LAPACK driver 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, UPLOINTEGER INFO, KA, KB, LDAB, LDBB, LDZ, LIWORK, LWORK, N* ..* .. Array Arguments ..INTEGER IWORK( * )DOUBLE PRECISION AB( LDAB, * ), BB( LDBB, * ), W( * ),$ WORK( * ), Z( LDZ, * )* ..** Purpose* =======** DSBGVD computes all the eigenvalues, and optionally, the eigenvectors* of a real generalized symmetric-definite banded eigenproblem, of the* form A*x=(lambda)*B*x. Here A and B are assumed to be symmetric and* banded, and B is also positive definite. If eigenvectors are* desired, it uses a divide and conquer algorithm.** The divide and conquer algorithm makes very mild assumptions about* floating point arithmetic. It will work on machines with a guard* digit in add/subtract, or on those binary machines without guard* digits which subtract like the Cray X-MP, Cray Y-MP, Cray C-90, or* Cray-2. It could conceivably fail on hexadecimal or decimal machines* without guard digits, but we know of none.** Arguments* =========** JOBZ (input) CHARACTER*1* = 'N': Compute eigenvalues only;* = 'V': Compute eigenvalues and eigenvectors.** UPLO (input) CHARACTER*1* = 'U': Upper triangles of A and B are stored;* = 'L': Lower triangles of A and B are 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'. 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 contents of AB are destroyed.** LDAB (input) INTEGER* The leading dimension of the array AB. LDAB >= KA+1.** BB (input/output) DOUBLE PRECISION array, dimension (LDBB, N)* On entry, the upper or lower triangle of the symmetric band* matrix B, stored in the first kb+1 rows of the array. The* j-th column of B is stored in the j-th column of the array BB* as follows:* if UPLO = 'U', BB(ka+1+i-j,j) = B(i,j) for max(1,j-kb)<=i<=j;* if UPLO = 'L', BB(1+i-j,j) = B(i,j) for j<=i<=min(n,j+kb).** On exit, the factor S from the split Cholesky factorization* B = S**T*S, as returned by DPBSTF.** LDBB (input) INTEGER* The leading dimension of the array BB. LDBB >= KB+1.** W (output) DOUBLE PRECISION array, dimension (N)* If INFO = 0, the eigenvalues in ascending order.** Z (output) DOUBLE PRECISION array, dimension (LDZ, N)* If JOBZ = 'V', then if INFO = 0, Z contains the matrix Z of* eigenvectors, with the i-th column of Z holding the* eigenvector associated with W(i). The eigenvectors are* normalized so Z**T*B*Z = I.* If JOBZ = 'N', then Z is not referenced.** LDZ (input) INTEGER* The leading dimension of the array Z. LDZ >= 1, and if* JOBZ = 'V', LDZ >= max(1,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.* If N <= 1, LWORK >= 1.* If JOBZ = 'N' and N > 1, LWORK >= 3*N.* If JOBZ = 'V' and N > 1, LWORK >= 1 + 5*N + 2*N**2.** 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 LIWORK > 0, IWORK(1) returns the optimal LIWORK.** LIWORK (input) INTEGER* The dimension of the array IWORK.* If JOBZ = 'N' or N <= 1, LIWORK >= 1.* If JOBZ = 'V' and N > 1, LIWORK >= 3 + 5*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 = i, and i is:* <= N: the algorithm failed to converge:* i off-diagonal elements of an intermediate* tridiagonal form did not converge to zero;* > N: if INFO = N + i, for 1 <= i <= N, then DPBSTF* returned INFO = i: B is not positive definite.* The factorization of B could not be completed and* no eigenvalues or eigenvectors were computed.** Further Details* ===============** Based on contributions by* Mark Fahey, Department of Mathematics, Univ. of Kentucky, USA** =====================================================================** .. Parameters ..DOUBLE PRECISION ONE, ZEROPARAMETER ( ONE = 1.0D+0, ZERO = 0.0D+0 )* ..* .. Local Scalars ..LOGICAL LQUERY, UPPER, WANTZCHARACTER VECTINTEGER IINFO, INDE, INDWK2, INDWRK, LIWMIN, LLWRK2,$ LWMIN* ..* .. External Functions ..LOGICAL LSAMEEXTERNAL LSAME* ..* .. External Subroutines ..EXTERNAL DGEMM, DLACPY, DPBSTF, DSBGST, DSBTRD, DSTEDC,$ DSTERF, XERBLA* ..* .. Executable Statements ..** Test the input parameters.*WANTZ = LSAME( JOBZ, 'V' )UPPER = LSAME( UPLO, 'U' )LQUERY = ( LWORK.EQ.-1 .OR. LIWORK.EQ.-1 )*INFO = 0IF( N.LE.1 ) THENLIWMIN = 1LWMIN = 1ELSEIF( WANTZ ) THENLIWMIN = 3 + 5*NLWMIN = 1 + 5*N + 2*N**2ELSELIWMIN = 1LWMIN = 2*NEND IFEND IF*IF( .NOT.( WANTZ .OR. LSAME( JOBZ, 'N' ) ) ) THENINFO = -1ELSE IF( .NOT.( UPPER .OR. LSAME( UPLO, 'L' ) ) ) THENINFO = -2ELSE IF( N.LT.0 ) THENINFO = -3ELSE IF( KA.LT.0 ) THENINFO = -4ELSE IF( KB.LT.0 .OR. KB.GT.KA ) THENINFO = -5ELSE IF( LDAB.LT.KA+1 ) THENINFO = -7ELSE IF( LDBB.LT.KB+1 ) THENINFO = -9ELSE IF( LDZ.LT.1 .OR. ( WANTZ .AND. LDZ.LT.N ) ) THENINFO = -12ELSE IF( LWORK.LT.LWMIN .AND. .NOT.LQUERY ) THENINFO = -14ELSE IF( LIWORK.LT.LIWMIN .AND. .NOT.LQUERY ) THENINFO = -16END IF*IF( INFO.EQ.0 ) THENWORK( 1 ) = LWMINIWORK( 1 ) = LIWMINEND IF*IF( INFO.NE.0 ) THENCALL XERBLA( 'DSBGVD', -INFO )RETURNELSE IF( LQUERY ) THENRETURNEND IF** Quick return if possible*IF( N.EQ.0 )$ RETURN** Form a split Cholesky factorization of B.*CALL DPBSTF( UPLO, N, KB, BB, LDBB, INFO )IF( INFO.NE.0 ) THENINFO = N + INFORETURNEND IF** Transform problem to standard eigenvalue problem.*INDE = 1INDWRK = INDE + NINDWK2 = INDWRK + N*NLLWRK2 = LWORK - INDWK2 + 1CALL DSBGST( JOBZ, UPLO, N, KA, KB, AB, LDAB, BB, LDBB, Z, LDZ,$ WORK( INDWRK ), IINFO )** Reduce to tridiagonal form.*IF( WANTZ ) THENVECT = 'U'ELSEVECT = 'N'END IFCALL DSBTRD( VECT, UPLO, N, KA, AB, LDAB, W, WORK( INDE ), Z, LDZ,$ WORK( INDWRK ), IINFO )** For eigenvalues only, call DSTERF. For eigenvectors, call SSTEDC.*IF( .NOT.WANTZ ) THENCALL DSTERF( N, W, WORK( INDE ), INFO )ELSECALL DSTEDC( 'I', N, W, WORK( INDE ), WORK( INDWRK ), N,$ WORK( INDWK2 ), LLWRK2, IWORK, LIWORK, INFO )CALL DGEMM( 'N', 'N', N, N, N, ONE, Z, LDZ, WORK( INDWRK ), N,$ ZERO, WORK( INDWK2 ), N )CALL DLACPY( 'A', N, N, WORK( INDWK2 ), N, Z, LDZ )END IF*WORK( 1 ) = LWMINIWORK( 1 ) = LIWMIN*RETURN** End of DSBGVD*ENDSUBROUTINE DSBGVX( JOBZ, RANGE, UPLO, N, KA, KB, AB, LDAB, BB,$ LDBB, Q, LDQ, VL, VU, IL, IU, ABSTOL, M, W, Z,$ LDZ, WORK, IWORK, IFAIL, INFO )** -- LAPACK driver 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, RANGE, UPLOINTEGER IL, INFO, IU, KA, KB, LDAB, LDBB, LDQ, LDZ, M,$ NDOUBLE PRECISION ABSTOL, VL, VU* ..* .. Array Arguments ..INTEGER IFAIL( * ), IWORK( * )DOUBLE PRECISION AB( LDAB, * ), BB( LDBB, * ), Q( LDQ, * ),$ W( * ), WORK( * ), Z( LDZ, * )* ..** Purpose* =======** DSBGVX computes selected eigenvalues, and optionally, eigenvectors* of a real generalized symmetric-definite banded eigenproblem, of* the form A*x=(lambda)*B*x. Here A and B are assumed to be symmetric* and banded, and B is also positive definite. Eigenvalues and* eigenvectors can be selected by specifying either all eigenvalues,* a range of values or a range of indices for the desired eigenvalues.** Arguments* =========** JOBZ (input) CHARACTER*1* = 'N': Compute eigenvalues only;* = 'V': Compute eigenvalues and eigenvectors.** RANGE (input) CHARACTER*1* = 'A': all eigenvalues will be found.* = 'V': all eigenvalues in the half-open interval (VL,VU]* will be found.* = 'I': the IL-th through IU-th eigenvalues will be found.** UPLO (input) CHARACTER*1* = 'U': Upper triangles of A and B are stored;* = 'L': Lower triangles of A and B are 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'. 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 contents of AB are destroyed.** LDAB (input) INTEGER* The leading dimension of the array AB. LDAB >= KA+1.** BB (input/output) DOUBLE PRECISION array, dimension (LDBB, N)* On entry, the upper or lower triangle of the symmetric band* matrix B, stored in the first kb+1 rows of the array. The* j-th column of B is stored in the j-th column of the array BB* as follows:* if UPLO = 'U', BB(ka+1+i-j,j) = B(i,j) for max(1,j-kb)<=i<=j;* if UPLO = 'L', BB(1+i-j,j) = B(i,j) for j<=i<=min(n,j+kb).** On exit, the factor S from the split Cholesky factorization* B = S**T*S, as returned by DPBSTF.** LDBB (input) INTEGER* The leading dimension of the array BB. LDBB >= KB+1.** Q (output) DOUBLE PRECISION array, dimension (LDQ, N)* If JOBZ = 'V', the n-by-n matrix used in the reduction of* A*x = (lambda)*B*x to standard form, i.e. C*x = (lambda)*x,* and consequently C to tridiagonal form.* If JOBZ = 'N', the array Q is not referenced.** LDQ (input) INTEGER* The leading dimension of the array Q. If JOBZ = 'N',* LDQ >= 1. If JOBZ = 'V', LDQ >= max(1,N).** 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.* An approximate eigenvalue is accepted as converged* when it is determined to lie in an interval [a,b]* of width less than or equal to** ABSTOL + EPS * max( |a|,|b| ) ,** where EPS is the machine precision. If ABSTOL is less than* or equal to zero, then EPS*|T| will be used in its place,* where |T| is the 1-norm of the tridiagonal matrix obtained* by reducing A to tridiagonal form.** Eigenvalues will be computed most accurately when ABSTOL is* set to twice the underflow threshold 2*DLAMCH('S'), not zero.* If this routine returns with INFO>0, indicating that some* eigenvectors did not converge, try setting ABSTOL to* 2*DLAMCH('S').** 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)* If INFO = 0, the eigenvalues in ascending order.** Z (output) DOUBLE PRECISION array, dimension (LDZ, N)* If JOBZ = 'V', then if INFO = 0, Z contains the matrix Z of* eigenvectors, with the i-th column of Z holding the* eigenvector associated with W(i). The eigenvectors are* normalized so Z**T*B*Z = I.* If JOBZ = 'N', then Z is not referenced.** LDZ (input) INTEGER* The leading dimension of the array Z. LDZ >= 1, and if* JOBZ = 'V', LDZ >= max(1,N).** WORK (workspace/output) DOUBLE PRECISION array, dimension (7N)** IWORK (workspace/output) INTEGER array, dimension (5N)** IFAIL (input) INTEGER array, dimension (M)* If JOBZ = 'V', then if INFO = 0, the first M elements of* IFAIL are zero. If INFO > 0, then IFAIL contains the* indices of the eigenvalues that failed to converge.* If JOBZ = 'N', then IFAIL is not referenced.** INFO (output) INTEGER* = 0 : successful exit* < 0 : if INFO = -i, the i-th argument had an illegal value* <= N: if INFO = i, then i eigenvectors failed to converge.* Their indices are stored in IFAIL.* > N : DPBSTF returned an error code; i.e.,* if INFO = N + i, for 1 <= i <= N, then the leading* minor of order i of B is not positive definite.* The factorization of B could not be completed and* no eigenvalues or eigenvectors were computed.** Further Details* ===============** Based on contributions by* Mark Fahey, Department of Mathematics, Univ. of Kentucky, USA** =====================================================================** .. Parameters ..DOUBLE PRECISION ZERO, ONEPARAMETER ( ZERO = 0.0D+0, ONE = 1.0D+0 )* ..* .. Local Scalars ..LOGICAL ALLEIG, INDEIG, UPPER, VALEIG, WANTZCHARACTER ORDER, VECTINTEGER I, IINFO, INDD, INDE, INDEE, INDIBL, INDISP,$ INDIWO, INDWRK, ITMP1, J, JJ, NSPLITDOUBLE PRECISION TMP1* ..* .. External Functions ..LOGICAL LSAMEEXTERNAL LSAME* ..* .. External Subroutines ..EXTERNAL DCOPY, DGEMV, DLACPY, DPBSTF, DSBGST, DSBTRD,$ DSTEBZ, DSTEIN, DSTEQR, DSTERF, DSWAP, XERBLA* ..* .. Intrinsic Functions ..INTRINSIC MIN* ..* .. Executable Statements ..** Test the input parameters.*WANTZ = LSAME( JOBZ, 'V' )UPPER = LSAME( UPLO, 'U' )ALLEIG = LSAME( RANGE, 'A' )VALEIG = LSAME( RANGE, 'V' )INDEIG = LSAME( RANGE, 'I' )*INFO = 0IF( .NOT.( WANTZ .OR. LSAME( JOBZ, 'N' ) ) ) THENINFO = -1ELSE IF( .NOT.( ALLEIG .OR. VALEIG .OR. INDEIG ) ) THENINFO = -2ELSE IF( .NOT.( UPPER .OR. LSAME( UPLO, 'L' ) ) ) THENINFO = -3ELSE IF( N.LT.0 ) THENINFO = -4ELSE IF( KA.LT.0 ) THENINFO = -5ELSE IF( KB.LT.0 .OR. KB.GT.KA ) THENINFO = -6ELSE IF( LDAB.LT.KA+1 ) THENINFO = -8ELSE IF( LDBB.LT.KB+1 ) THENINFO = -10ELSE IF( LDQ.LT.1 ) THENINFO = -12ELSE IF( VALEIG .AND. N.GT.0 .AND. VU.LE.VL ) THENINFO = -14ELSE IF( INDEIG .AND. IL.LT.1 ) THENINFO = -15ELSE IF( INDEIG .AND. ( IU.LT.MIN( N, IL ) .OR. IU.GT.N ) ) THENINFO = -16ELSE IF( LDZ.LT.1 .OR. ( WANTZ .AND. LDZ.LT.N ) ) THENINFO = -21END IF*IF( INFO.NE.0 ) THENCALL XERBLA( 'DSBGVX', -INFO )RETURNEND IF** Quick return if possible*M = 0IF( N.EQ.0 ) THENWORK( 1 ) = 1RETURNEND IF** Form a split Cholesky factorization of B.*CALL DPBSTF( UPLO, N, KB, BB, LDBB, INFO )IF( INFO.NE.0 ) THENINFO = N + INFORETURNEND IF** Transform problem to standard eigenvalue problem.*CALL DSBGST( JOBZ, UPLO, N, KA, KB, AB, LDAB, BB, LDBB, Q, LDQ,$ WORK, IINFO )** Reduce symmetric band matrix to tridiagonal form.*INDD = 1INDE = INDD + NINDWRK = INDE + NIF( WANTZ ) THENVECT = 'U'ELSEVECT = 'N'END IFCALL DSBTRD( VECT, UPLO, N, KA, AB, LDAB, WORK( INDD ),$ WORK( INDE ), Q, LDQ, WORK( INDWRK ), IINFO )** If all eigenvalues are desired and ABSTOL is less than or equal* to zero, then call DSTERF or SSTEQR. If this fails for some* eigenvalue, then try DSTEBZ.*IF( ( ALLEIG .OR. ( INDEIG .AND. IL.EQ.1 .AND. IU.EQ.N ) ) .AND.$ ( ABSTOL.LE.ZERO ) ) THENCALL DCOPY( N, WORK( INDD ), 1, W, 1 )INDEE = INDWRK + 2*NCALL DCOPY( N-1, WORK( INDE ), 1, WORK( INDEE ), 1 )IF( .NOT.WANTZ ) THENCALL DSTERF( N, W, WORK( INDEE ), INFO )ELSECALL DLACPY( 'A', N, N, Q, LDQ, Z, LDZ )CALL DSTEQR( JOBZ, N, W, WORK( INDEE ), Z, LDZ,$ WORK( INDWRK ), INFO )IF( INFO.EQ.0 ) THENDO 10 I = 1, NIFAIL( I ) = 010 CONTINUEEND IFEND IFIF( INFO.EQ.0 ) THENM = NGO TO 30END IFINFO = 0END IF** Otherwise, call DSTEBZ and, if eigenvectors are desired,* call DSTEIN.*IF( WANTZ ) THENORDER = 'B'ELSEORDER = 'E'END IFINDIBL = 1INDISP = INDIBL + NINDIWO = INDISP + NCALL DSTEBZ( RANGE, ORDER, N, VL, VU, IL, IU, ABSTOL,$ WORK( INDD ), WORK( INDE ), M, NSPLIT, W,$ IWORK( INDIBL ), IWORK( INDISP ), WORK( INDWRK ),$ IWORK( INDIWO ), INFO )*IF( WANTZ ) THENCALL DSTEIN( N, WORK( INDD ), WORK( INDE ), M, W,$ IWORK( INDIBL ), IWORK( INDISP ), Z, LDZ,$ WORK( INDWRK ), IWORK( INDIWO ), IFAIL, INFO )** Apply transformation matrix used in reduction to tridiagonal* form to eigenvectors returned by DSTEIN.*DO 20 J = 1, MCALL DCOPY( N, Z( 1, J ), 1, WORK( 1 ), 1 )CALL DGEMV( 'N', N, N, ONE, Q, LDQ, WORK, 1, ZERO,$ Z( 1, J ), 1 )20 CONTINUEEND IF*30 CONTINUE** If eigenvalues are not in order, then sort them, along with* eigenvectors.*IF( WANTZ ) THENDO 50 J = 1, M - 1I = 0TMP1 = W( J )DO 40 JJ = J + 1, MIF( W( JJ ).LT.TMP1 ) THENI = JJTMP1 = W( JJ )END IF40 CONTINUE*IF( I.NE.0 ) THENITMP1 = IWORK( INDIBL+I-1 )W( I ) = W( J )IWORK( INDIBL+I-1 ) = IWORK( INDIBL+J-1 )W( J ) = TMP1IWORK( INDIBL+J-1 ) = ITMP1CALL DSWAP( N, Z( 1, I ), 1, Z( 1, J ), 1 )IF( INFO.NE.0 ) THENITMP1 = IFAIL( I )IFAIL( I ) = IFAIL( J )IFAIL( J ) = ITMP1END IFEND IF50 CONTINUEEND IF*RETURN** End of DSBGVX*ENDSUBROUTINE DSPEV( JOBZ, UPLO, N, AP, W, Z, LDZ, WORK, INFO )** -- LAPACK driver 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 JOBZ, UPLOINTEGER INFO, LDZ, N* ..* .. Array Arguments ..DOUBLE PRECISION AP( * ), W( * ), WORK( * ), Z( LDZ, * )* ..** Purpose* =======** DSPEV computes all the eigenvalues and, optionally, eigenvectors of a* real symmetric matrix A in packed storage.** Arguments* =========** JOBZ (input) CHARACTER*1* = 'N': Compute eigenvalues only;* = 'V': Compute eigenvalues and eigenvectors.** 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, AP is overwritten by values generated during the* reduction to tridiagonal form. If UPLO = 'U', the diagonal* and first superdiagonal of the tridiagonal matrix T overwrite* the corresponding elements of A, and if UPLO = 'L', the* diagonal and first subdiagonal of T overwrite the* corresponding elements of A.** W (output) DOUBLE PRECISION array, dimension (N)* If INFO = 0, the eigenvalues in ascending order.** Z (output) DOUBLE PRECISION array, dimension (LDZ, N)* If JOBZ = 'V', then if INFO = 0, Z contains the orthonormal* eigenvectors of the matrix A, with the i-th column of Z* holding the eigenvector associated with W(i).* If JOBZ = 'N', then Z is not referenced.** LDZ (input) INTEGER* The leading dimension of the array Z. LDZ >= 1, and if* JOBZ = 'V', LDZ >= max(1,N).** WORK (workspace) DOUBLE PRECISION array, dimension (3*N)** INFO (output) INTEGER* = 0: successful exit.* < 0: if INFO = -i, the i-th argument had an illegal value.* > 0: if INFO = i, the algorithm failed to converge; i* off-diagonal elements of an intermediate tridiagonal* form did not converge to zero.** =====================================================================** .. Parameters ..DOUBLE PRECISION ZERO, ONEPARAMETER ( ZERO = 0.0D0, ONE = 1.0D0 )* ..* .. Local Scalars ..LOGICAL WANTZINTEGER IINFO, IMAX, INDE, INDTAU, INDWRK, ISCALEDOUBLE PRECISION ANRM, BIGNUM, EPS, RMAX, RMIN, SAFMIN, SIGMA,$ SMLNUM* ..* .. External Functions ..LOGICAL LSAMEDOUBLE PRECISION DLAMCH, DLANSPEXTERNAL LSAME, DLAMCH, DLANSP* ..* .. External Subroutines ..EXTERNAL DOPGTR, DSCAL, DSPTRD, DSTEQR, DSTERF, XERBLA* ..* .. Intrinsic Functions ..INTRINSIC SQRT* ..* .. Executable Statements ..** Test the input parameters.*WANTZ = LSAME( JOBZ, 'V' )*INFO = 0IF( .NOT.( WANTZ .OR. LSAME( JOBZ, 'N' ) ) ) THENINFO = -1ELSE IF( .NOT.( LSAME( UPLO, 'U' ) .OR. LSAME( UPLO, 'L' ) ) )$ THENINFO = -2ELSE IF( N.LT.0 ) THENINFO = -3ELSE IF( LDZ.LT.1 .OR. ( WANTZ .AND. LDZ.LT.N ) ) THENINFO = -7END IF*IF( INFO.NE.0 ) THENCALL XERBLA( 'DSPEV ', -INFO )RETURNEND IF** Quick return if possible*IF( N.EQ.0 )$ RETURN*IF( N.EQ.1 ) THENW( 1 ) = AP( 1 )IF( WANTZ )$ Z( 1, 1 ) = ONERETURNEND IF** Get machine constants.*SAFMIN = DLAMCH( 'Safe minimum' )EPS = DLAMCH( 'Precision' )SMLNUM = SAFMIN / EPSBIGNUM = ONE / SMLNUMRMIN = SQRT( SMLNUM )RMAX = SQRT( BIGNUM )** Scale matrix to allowable range, if necessary.*ANRM = DLANSP( 'M', UPLO, N, AP, WORK )ISCALE = 0IF( ANRM.GT.ZERO .AND. ANRM.LT.RMIN ) THENISCALE = 1SIGMA = RMIN / ANRMELSE IF( ANRM.GT.RMAX ) THENISCALE = 1SIGMA = RMAX / ANRMEND IFIF( ISCALE.EQ.1 ) THENCALL DSCAL( ( N*( N+1 ) ) / 2, SIGMA, AP, 1 )END IF** Call DSPTRD to reduce symmetric packed matrix to tridiagonal form.*INDE = 1INDTAU = INDE + NCALL DSPTRD( UPLO, N, AP, W, WORK( INDE ), WORK( INDTAU ), IINFO )** For eigenvalues only, call DSTERF. For eigenvectors, first call* DOPGTR to generate the orthogonal matrix, then call DSTEQR.*IF( .NOT.WANTZ ) THENCALL DSTERF( N, W, WORK( INDE ), INFO )ELSEINDWRK = INDTAU + NCALL DOPGTR( UPLO, N, AP, WORK( INDTAU ), Z, LDZ,$ WORK( INDWRK ), IINFO )CALL DSTEQR( JOBZ, N, W, WORK( INDE ), Z, LDZ, WORK( INDTAU ),$ INFO )END IF** If matrix was scaled, then rescale eigenvalues appropriately.*IF( ISCALE.EQ.1 ) THENIF( INFO.EQ.0 ) THENIMAX = NELSEIMAX = INFO - 1END IFCALL DSCAL( IMAX, ONE / SIGMA, W, 1 )END IF*RETURN** End of DSPEV*ENDSUBROUTINE DSPEVD( JOBZ, UPLO, N, AP, W, Z, LDZ, WORK, LWORK,$ IWORK, LIWORK, INFO )** -- LAPACK driver 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, UPLOINTEGER INFO, LDZ, LIWORK, LWORK, N* ..* .. Array Arguments ..INTEGER IWORK( * )DOUBLE PRECISION AP( * ), W( * ), WORK( * ), Z( LDZ, * )* ..** Purpose* =======** DSPEVD computes all the eigenvalues and, optionally, eigenvectors* of a real symmetric matrix A in packed storage. If eigenvectors are* desired, it uses a divide and conquer algorithm.** The divide and conquer algorithm makes very mild assumptions about* floating point arithmetic. It will work on machines with a guard* digit in add/subtract, or on those binary machines without guard* digits which subtract like the Cray X-MP, Cray Y-MP, Cray C-90, or* Cray-2. It could conceivably fail on hexadecimal or decimal machines* without guard digits, but we know of none.** Arguments* =========** JOBZ (input) CHARACTER*1* = 'N': Compute eigenvalues only;* = 'V': Compute eigenvalues and eigenvectors.** 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, AP is overwritten by values generated during the* reduction to tridiagonal form. If UPLO = 'U', the diagonal* and first superdiagonal of the tridiagonal matrix T overwrite* the corresponding elements of A, and if UPLO = 'L', the* diagonal and first subdiagonal of T overwrite the* corresponding elements of A.** W (output) DOUBLE PRECISION array, dimension (N)* If INFO = 0, the eigenvalues in ascending order.** Z (output) DOUBLE PRECISION array, dimension (LDZ, N)* If JOBZ = 'V', then if INFO = 0, Z contains the orthonormal* eigenvectors of the matrix A, with the i-th column of Z* holding the eigenvector associated with W(i).* If JOBZ = 'N', then Z is not referenced.** LDZ (input) INTEGER* The leading dimension of the array Z. LDZ >= 1, and if* JOBZ = 'V', LDZ >= max(1,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.* If N <= 1, LWORK must be at least 1.* If JOBZ = 'N' and N > 1, LWORK must be at least 2*N.* If JOBZ = 'V' and N > 1, LWORK must be at least* 1 + 6*N + N**2.** 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.* If JOBZ = 'N' or N <= 1, LIWORK must be at least 1.* If JOBZ = 'V' and N > 1, LIWORK must be at least 3 + 5*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 = i, the algorithm failed to converge; i* off-diagonal elements of an intermediate tridiagonal* form did not converge to zero.** =====================================================================** .. Parameters ..DOUBLE PRECISION ZERO, ONEPARAMETER ( ZERO = 0.0D+0, ONE = 1.0D+0 )* ..* .. Local Scalars ..LOGICAL LQUERY, WANTZINTEGER IINFO, INDE, INDTAU, INDWRK, ISCALE, LIWMIN,$ LLWORK, LWMINDOUBLE PRECISION ANRM, BIGNUM, EPS, RMAX, RMIN, SAFMIN, SIGMA,$ SMLNUM* ..* .. External Functions ..LOGICAL LSAMEDOUBLE PRECISION DLAMCH, DLANSPEXTERNAL LSAME, DLAMCH, DLANSP* ..* .. External Subroutines ..EXTERNAL DOPMTR, DSCAL, DSPTRD, DSTEDC, DSTERF, XERBLA* ..* .. Intrinsic Functions ..INTRINSIC SQRT* ..* .. Executable Statements ..** Test the input parameters.*WANTZ = LSAME( JOBZ, 'V' )LQUERY = ( LWORK.EQ.-1 .OR. LIWORK.EQ.-1 )*INFO = 0IF( N.LE.1 ) THENLIWMIN = 1LWMIN = 1ELSEIF( WANTZ ) THENLIWMIN = 3 + 5*NLWMIN = 1 + 6*N + N**2ELSELIWMIN = 1LWMIN = 2*NEND IFEND IFIF( .NOT.( WANTZ .OR. LSAME( JOBZ, 'N' ) ) ) THENINFO = -1ELSE IF( .NOT.( LSAME( UPLO, 'U' ) .OR. LSAME( UPLO, 'L' ) ) )$ THENINFO = -2ELSE IF( N.LT.0 ) THENINFO = -3ELSE IF( LDZ.LT.1 .OR. ( WANTZ .AND. LDZ.LT.N ) ) THENINFO = -7ELSE IF( LWORK.LT.LWMIN .AND. .NOT.LQUERY ) THENINFO = -9ELSE IF( LIWORK.LT.LIWMIN .AND. .NOT.LQUERY ) THENINFO = -11END IF*IF( INFO.EQ.0 ) THENWORK( 1 ) = LWMINIWORK( 1 ) = LIWMINEND IF*IF( INFO.NE.0 ) THENCALL XERBLA( 'DSPEVD', -INFO )RETURNELSE IF( LQUERY ) THENRETURNEND IF** Quick return if possible*IF( N.EQ.0 )$ RETURN*IF( N.EQ.1 ) THENW( 1 ) = AP( 1 )IF( WANTZ )$ Z( 1, 1 ) = ONERETURNEND IF** Get machine constants.*SAFMIN = DLAMCH( 'Safe minimum' )EPS = DLAMCH( 'Precision' )SMLNUM = SAFMIN / EPSBIGNUM = ONE / SMLNUMRMIN = SQRT( SMLNUM )RMAX = SQRT( BIGNUM )** Scale matrix to allowable range, if necessary.*ANRM = DLANSP( 'M', UPLO, N, AP, WORK )ISCALE = 0IF( ANRM.GT.ZERO .AND. ANRM.LT.RMIN ) THENISCALE = 1SIGMA = RMIN / ANRMELSE IF( ANRM.GT.RMAX ) THENISCALE = 1SIGMA = RMAX / ANRMEND IFIF( ISCALE.EQ.1 ) THENCALL DSCAL( ( N*( N+1 ) ) / 2, SIGMA, AP, 1 )END IF** Call DSPTRD to reduce symmetric packed matrix to tridiagonal form.*INDE = 1INDTAU = INDE + NCALL DSPTRD( UPLO, N, AP, W, WORK( INDE ), WORK( INDTAU ), IINFO )** For eigenvalues only, call DSTERF. For eigenvectors, first call* DSTEDC to generate the eigenvector matrix, WORK(INDWRK), of the* tridiagonal matrix, then call DOPMTR to multiply it by the* Householder transformations represented in AP.*IF( .NOT.WANTZ ) THENCALL DSTERF( N, W, WORK( INDE ), INFO )ELSEINDWRK = INDTAU + NLLWORK = LWORK - INDWRK + 1CALL DSTEDC( 'I', N, W, WORK( INDE ), Z, LDZ, WORK( INDWRK ),$ LLWORK, IWORK, LIWORK, INFO )CALL DOPMTR( 'L', UPLO, 'N', N, N, AP, WORK( INDTAU ), Z, LDZ,$ WORK( INDWRK ), IINFO )END IF** If matrix was scaled, then rescale eigenvalues appropriately.*IF( ISCALE.EQ.1 )$ CALL DSCAL( N, ONE / SIGMA, W, 1 )*WORK( 1 ) = LWMINIWORK( 1 ) = LIWMINRETURN** End of DSPEVD*ENDSUBROUTINE DSPEVX( JOBZ, RANGE, UPLO, N, AP, VL, VU, IL, IU,$ ABSTOL, M, W, Z, LDZ, WORK, IWORK, IFAIL,$ INFO )** -- LAPACK driver 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, RANGE, UPLOINTEGER IL, INFO, IU, LDZ, M, NDOUBLE PRECISION ABSTOL, VL, VU* ..* .. Array Arguments ..INTEGER IFAIL( * ), IWORK( * )DOUBLE PRECISION AP( * ), W( * ), WORK( * ), Z( LDZ, * )* ..** Purpose* =======** DSPEVX computes selected eigenvalues and, optionally, eigenvectors* of a real symmetric matrix A in packed storage. Eigenvalues/vectors* can be selected by specifying either a range of values or a range of* indices for the desired eigenvalues.** Arguments* =========** JOBZ (input) CHARACTER*1* = 'N': Compute eigenvalues only;* = 'V': Compute eigenvalues and eigenvectors.** RANGE (input) CHARACTER*1* = 'A': all eigenvalues will be found;* = 'V': all eigenvalues in the half-open interval (VL,VU]* will be found;* = 'I': the IL-th through IU-th eigenvalues will be found.** UPLO (input) CHARACTER*1* = 'U': Upper triangle of A is stored;* = 'L': Lower triangle of A is stored.** N (input) INTEGER* The order of the matrix A. N >= 0.** 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, AP is overwritten by values generated during the* reduction to tridiagonal form. If UPLO = 'U', the diagonal* and first superdiagonal of the tridiagonal matrix T overwrite* the corresponding elements of A, and if UPLO = 'L', the* diagonal and first subdiagonal of T overwrite the* corresponding elements of A.** 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.* An approximate eigenvalue is accepted as converged* when it is determined to lie in an interval [a,b]* of width less than or equal to** ABSTOL + EPS * max( |a|,|b| ) ,** where EPS is the machine precision. If ABSTOL is less than* or equal to zero, then EPS*|T| will be used in its place,* where |T| is the 1-norm of the tridiagonal matrix obtained* by reducing AP to tridiagonal form.** Eigenvalues will be computed most accurately when ABSTOL is* set to twice the underflow threshold 2*DLAMCH('S'), not zero.* If this routine returns with INFO>0, indicating that some* eigenvectors did not converge, try setting ABSTOL to* 2*DLAMCH('S').** See "Computing Small Singular Values of Bidiagonal Matrices* with Guaranteed High Relative Accuracy," by Demmel and* Kahan, LAPACK Working Note #3.** M (output) INTEGER* The total number of eigenvalues found. 0 <= M <= N.* If RANGE = 'A', M = N, and if RANGE = 'I', M = IU-IL+1.** W (output) DOUBLE PRECISION array, dimension (N)* If INFO = 0, 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 A* corresponding to the selected eigenvalues, with the i-th* column of Z holding the eigenvector associated with W(i).* If an eigenvector fails to converge, then that column of Z* contains the latest approximation to the eigenvector, and the* index of the eigenvector is returned in IFAIL.* If JOBZ = 'N', then Z is not referenced.* Note: the user must ensure that at least max(1,M) columns are* supplied in the array Z; if RANGE = 'V', the exact value of M* is not known in advance and an upper bound must be used.** LDZ (input) INTEGER* The leading dimension of the array Z. LDZ >= 1, and if* JOBZ = 'V', LDZ >= max(1,N).** WORK (workspace) DOUBLE PRECISION array, dimension (8*N)** IWORK (workspace) INTEGER array, dimension (5*N)** IFAIL (output) INTEGER array, dimension (N)* If JOBZ = 'V', then if INFO = 0, the first M elements of* IFAIL are zero. If INFO > 0, then IFAIL contains the* indices of the eigenvectors that failed to converge.* If JOBZ = 'N', then IFAIL is not referenced.** INFO (output) INTEGER* = 0: successful exit* < 0: if INFO = -i, the i-th argument had an illegal value* > 0: if INFO = i, then i eigenvectors failed to converge.* Their indices are stored in array IFAIL.** =====================================================================** .. Parameters ..DOUBLE PRECISION ZERO, ONEPARAMETER ( ZERO = 0.0D0, ONE = 1.0D0 )* ..* .. Local Scalars ..LOGICAL ALLEIG, INDEIG, VALEIG, WANTZCHARACTER ORDERINTEGER I, IINFO, IMAX, INDD, INDE, INDEE, INDIBL,$ INDISP, INDIWO, INDTAU, INDWRK, ISCALE, ITMP1,$ J, JJ, NSPLITDOUBLE PRECISION ABSTLL, ANRM, BIGNUM, EPS, RMAX, RMIN, SAFMIN,$ SIGMA, SMLNUM, TMP1, VLL, VUU* ..* .. External Functions ..LOGICAL LSAMEDOUBLE PRECISION DLAMCH, DLANSPEXTERNAL LSAME, DLAMCH, DLANSP* ..* .. External Subroutines ..EXTERNAL DCOPY, DOPGTR, DOPMTR, DSCAL, DSPTRD, DSTEBZ,$ DSTEIN, DSTEQR, DSTERF, DSWAP, XERBLA* ..* .. Intrinsic Functions ..INTRINSIC 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' )*INFO = 0IF( .NOT.( WANTZ .OR. LSAME( JOBZ, 'N' ) ) ) THENINFO = -1ELSE IF( .NOT.( ALLEIG .OR. VALEIG .OR. INDEIG ) ) THENINFO = -2ELSE IF( .NOT.( LSAME( UPLO, 'L' ) .OR. LSAME( UPLO, 'U' ) ) )$ THENINFO = -3ELSE IF( N.LT.0 ) THENINFO = -4ELSEIF( VALEIG ) THENIF( N.GT.0 .AND. VU.LE.VL )$ INFO = -7ELSE IF( INDEIG ) THENIF( IL.LT.1 .OR. IL.GT.MAX( 1, N ) ) THENINFO = -8ELSE IF( IU.LT.MIN( N, IL ) .OR. IU.GT.N ) THENINFO = -9END IFEND IFEND IFIF( INFO.EQ.0 ) THENIF( LDZ.LT.1 .OR. ( WANTZ .AND. LDZ.LT.N ) )$ INFO = -14END IF*IF( INFO.NE.0 ) THENCALL XERBLA( 'DSPEVX', -INFO )RETURNEND IF** Quick return if possible*M = 0IF( N.EQ.0 )$ RETURN*IF( N.EQ.1 ) THENIF( ALLEIG .OR. INDEIG ) THENM = 1W( 1 ) = AP( 1 )ELSEIF( VL.LT.AP( 1 ) .AND. VU.GE.AP( 1 ) ) THENM = 1W( 1 ) = AP( 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.*ISCALE = 0ABSTLL = ABSTOLIF( VALEIG ) THENVLL = VLVUU = VUELSEVLL = ZEROVUU = ZEROEND IFANRM = DLANSP( 'M', UPLO, N, AP, WORK )IF( ANRM.GT.ZERO .AND. ANRM.LT.RMIN ) THENISCALE = 1SIGMA = RMIN / ANRMELSE IF( ANRM.GT.RMAX ) THENISCALE = 1SIGMA = RMAX / ANRMEND IFIF( ISCALE.EQ.1 ) THENCALL DSCAL( ( N*( N+1 ) ) / 2, SIGMA, AP, 1 )IF( ABSTOL.GT.0 )$ ABSTLL = ABSTOL*SIGMAIF( VALEIG ) THENVLL = VL*SIGMAVUU = VU*SIGMAEND IFEND IF** Call DSPTRD to reduce symmetric packed matrix to tridiagonal form.*INDTAU = 1INDE = INDTAU + NINDD = INDE + NINDWRK = INDD + NCALL DSPTRD( UPLO, N, AP, WORK( INDD ), WORK( INDE ),$ WORK( INDTAU ), IINFO )** If all eigenvalues are desired and ABSTOL is less than or equal* to zero, then call DSTERF or DOPGTR and SSTEQR. If this fails* for some eigenvalue, then try DSTEBZ.*IF( ( ALLEIG .OR. ( INDEIG .AND. IL.EQ.1 .AND. IU.EQ.N ) ) .AND.$ ( ABSTOL.LE.ZERO ) ) THENCALL DCOPY( N, WORK( INDD ), 1, W, 1 )INDEE = INDWRK + 2*NIF( .NOT.WANTZ ) THENCALL DCOPY( N-1, WORK( INDE ), 1, WORK( INDEE ), 1 )CALL DSTERF( N, W, WORK( INDEE ), INFO )ELSECALL DOPGTR( UPLO, N, AP, WORK( INDTAU ), Z, LDZ,$ WORK( INDWRK ), IINFO )CALL DCOPY( N-1, WORK( INDE ), 1, WORK( INDEE ), 1 )CALL DSTEQR( JOBZ, N, W, WORK( INDEE ), Z, LDZ,$ WORK( INDWRK ), INFO )IF( INFO.EQ.0 ) THENDO 10 I = 1, NIFAIL( I ) = 010 CONTINUEEND IFEND IFIF( INFO.EQ.0 ) THENM = NGO TO 20END IFINFO = 0END IF** Otherwise, call DSTEBZ and, if eigenvectors are desired, SSTEIN.*IF( WANTZ ) THENORDER = 'B'ELSEORDER = 'E'END IFINDIBL = 1INDISP = INDIBL + NINDIWO = INDISP + NCALL DSTEBZ( RANGE, ORDER, N, VLL, VUU, IL, IU, ABSTLL,$ WORK( INDD ), WORK( INDE ), M, NSPLIT, W,$ IWORK( INDIBL ), IWORK( INDISP ), WORK( INDWRK ),$ IWORK( INDIWO ), INFO )*IF( WANTZ ) THENCALL DSTEIN( N, WORK( INDD ), WORK( INDE ), M, W,$ IWORK( INDIBL ), IWORK( INDISP ), Z, LDZ,$ WORK( INDWRK ), IWORK( INDIWO ), IFAIL, INFO )** Apply orthogonal matrix used in reduction to tridiagonal* form to eigenvectors returned by DSTEIN.*CALL DOPMTR( 'L', UPLO, 'N', N, M, AP, WORK( INDTAU ), Z, LDZ,$ WORK( INDWRK ), INFO )END IF** If matrix was scaled, then rescale eigenvalues appropriately.*20 CONTINUEIF( ISCALE.EQ.1 ) THENIF( INFO.EQ.0 ) THENIMAX = MELSEIMAX = INFO - 1END IFCALL DSCAL( IMAX, ONE / SIGMA, W, 1 )END IF** If eigenvalues are not in order, then sort them, along with* eigenvectors.*IF( WANTZ ) THENDO 40 J = 1, M - 1I = 0TMP1 = W( J )DO 30 JJ = J + 1, MIF( W( JJ ).LT.TMP1 ) THENI = JJTMP1 = W( JJ )END IF30 CONTINUE*IF( I.NE.0 ) THENITMP1 = IWORK( INDIBL+I-1 )W( I ) = W( J )IWORK( INDIBL+I-1 ) = IWORK( INDIBL+J-1 )W( J ) = TMP1IWORK( INDIBL+J-1 ) = ITMP1CALL DSWAP( N, Z( 1, I ), 1, Z( 1, J ), 1 )IF( INFO.NE.0 ) THENITMP1 = IFAIL( I )IFAIL( I ) = IFAIL( J )IFAIL( J ) = ITMP1END IFEND IF40 CONTINUEEND IF*RETURN** End of DSPEVX*ENDSUBROUTINE DSPGV( ITYPE, JOBZ, UPLO, N, AP, BP, W, Z, LDZ, WORK,$ INFO )** -- LAPACK driver 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 JOBZ, UPLOINTEGER INFO, ITYPE, LDZ, N* ..* .. Array Arguments ..DOUBLE PRECISION AP( * ), BP( * ), W( * ), WORK( * ),$ Z( LDZ, * )* ..** Purpose* =======** DSPGV computes all the eigenvalues and, optionally, the eigenvectors* of a real generalized symmetric-definite eigenproblem, of the form* A*x=(lambda)*B*x, A*Bx=(lambda)*x, or B*A*x=(lambda)*x.* Here A and B are assumed to be symmetric, stored in packed format,* and B is also positive definite.** Arguments* =========** ITYPE (input) INTEGER* Specifies the problem type to be solved:* = 1: A*x = (lambda)*B*x* = 2: A*B*x = (lambda)*x* = 3: B*A*x = (lambda)*x** JOBZ (input) CHARACTER*1* = 'N': Compute eigenvalues only;* = 'V': Compute eigenvalues and eigenvectors.** UPLO (input) CHARACTER*1* = 'U': Upper triangles of A and B are stored;* = 'L': Lower triangles of A and B are stored.** 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)*(2*n-j)/2) = A(i,j) for j<=i<=n.** On exit, the contents of AP are destroyed.** BP (input/output) DOUBLE PRECISION array, dimension (N*(N+1)/2)* On entry, the upper or lower triangle of the symmetric matrix* B, packed columnwise in a linear array. The j-th column of B* is stored in the array BP as follows:* if UPLO = 'U', BP(i + (j-1)*j/2) = B(i,j) for 1<=i<=j;* if UPLO = 'L', BP(i + (j-1)*(2*n-j)/2) = B(i,j) for j<=i<=n.** On exit, the triangular factor U or L from the Cholesky* factorization B = U**T*U or B = L*L**T, in the same storage* format as B.** W (output) DOUBLE PRECISION array, dimension (N)* If INFO = 0, the eigenvalues in ascending order.** Z (output) DOUBLE PRECISION array, dimension (LDZ, N)* If JOBZ = 'V', then if INFO = 0, Z contains the matrix Z of* eigenvectors. The eigenvectors are normalized as follows:* if ITYPE = 1 or 2, Z**T*B*Z = I;* if ITYPE = 3, Z**T*inv(B)*Z = I.* If JOBZ = 'N', then Z is not referenced.** LDZ (input) INTEGER* The leading dimension of the array Z. LDZ >= 1, and if* JOBZ = 'V', LDZ >= max(1,N).** WORK (workspace) DOUBLE PRECISION array, dimension (3*N)** INFO (output) INTEGER* = 0: successful exit* < 0: if INFO = -i, the i-th argument had an illegal value* > 0: DPPTRF or DSPEV returned an error code:* <= N: if INFO = i, DSPEV failed to converge;* i off-diagonal elements of an intermediate* tridiagonal form did not converge to zero.* > N: if INFO = n + i, for 1 <= i <= n, then the leading* minor of order i of B is not positive definite.* The factorization of B could not be completed and* no eigenvalues or eigenvectors were computed.** =====================================================================** .. Local Scalars ..LOGICAL UPPER, WANTZCHARACTER TRANSINTEGER J, NEIG* ..* .. External Functions ..LOGICAL LSAMEEXTERNAL LSAME* ..* .. External Subroutines ..EXTERNAL DPPTRF, DSPEV, DSPGST, DTPMV, DTPSV, XERBLA* ..* .. Executable Statements ..** Test the input parameters.*WANTZ = LSAME( JOBZ, 'V' )UPPER = LSAME( UPLO, 'U' )*INFO = 0IF( ITYPE.LT.0 .OR. ITYPE.GT.3 ) THENINFO = -1ELSE IF( .NOT.( WANTZ .OR. LSAME( JOBZ, 'N' ) ) ) THENINFO = -2ELSE IF( .NOT.( UPPER .OR. LSAME( UPLO, 'L' ) ) ) THENINFO = -3ELSE IF( N.LT.0 ) THENINFO = -4ELSE IF( LDZ.LT.1 .OR. ( WANTZ .AND. LDZ.LT.N ) ) THENINFO = -9END IFIF( INFO.NE.0 ) THENCALL XERBLA( 'DSPGV ', -INFO )RETURNEND IF** Quick return if possible*IF( N.EQ.0 )$ RETURN** Form a Cholesky factorization of B.*CALL DPPTRF( UPLO, N, BP, INFO )IF( INFO.NE.0 ) THENINFO = N + INFORETURNEND IF** Transform problem to standard eigenvalue problem and solve.*CALL DSPGST( ITYPE, UPLO, N, AP, BP, INFO )CALL DSPEV( JOBZ, UPLO, N, AP, W, Z, LDZ, WORK, INFO )*IF( WANTZ ) THEN** Backtransform eigenvectors to the original problem.*NEIG = NIF( INFO.GT.0 )$ NEIG = INFO - 1IF( ITYPE.EQ.1 .OR. ITYPE.EQ.2 ) THEN** For A*x=(lambda)*B*x and A*B*x=(lambda)*x;* backtransform eigenvectors: x = inv(L)'*y or inv(U)*y*IF( UPPER ) THENTRANS = 'N'ELSETRANS = 'T'END IF*DO 10 J = 1, NEIGCALL DTPSV( UPLO, TRANS, 'Non-unit', N, BP, Z( 1, J ),$ 1 )10 CONTINUE*ELSE IF( ITYPE.EQ.3 ) THEN** For B*A*x=(lambda)*x;* backtransform eigenvectors: x = L*y or U'*y*IF( UPPER ) THENTRANS = 'T'ELSETRANS = 'N'END IF*DO 20 J = 1, NEIGCALL DTPMV( UPLO, TRANS, 'Non-unit', N, BP, Z( 1, J ),$ 1 )20 CONTINUEEND IFEND IFRETURN** End of DSPGV*ENDSUBROUTINE DSPGVD( ITYPE, JOBZ, UPLO, N, AP, BP, W, Z, LDZ, WORK,$ LWORK, IWORK, LIWORK, INFO )** -- LAPACK driver 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, UPLOINTEGER INFO, ITYPE, LDZ, LIWORK, LWORK, N* ..* .. Array Arguments ..INTEGER IWORK( * )DOUBLE PRECISION AP( * ), BP( * ), W( * ), WORK( * ),$ Z( LDZ, * )* ..** Purpose* =======** DSPGVD computes all the eigenvalues, and optionally, the eigenvectors* of a real generalized symmetric-definite eigenproblem, of the form* A*x=(lambda)*B*x, A*Bx=(lambda)*x, or B*A*x=(lambda)*x. Here A and* B are assumed to be symmetric, stored in packed format, and B is also* positive definite.* If eigenvectors are desired, it uses a divide and conquer algorithm.** The divide and conquer algorithm makes very mild assumptions about* floating point arithmetic. It will work on machines with a guard* digit in add/subtract, or on those binary machines without guard* digits which subtract like the Cray X-MP, Cray Y-MP, Cray C-90, or* Cray-2. It could conceivably fail on hexadecimal or decimal machines* without guard digits, but we know of none.** Arguments* =========** ITYPE (input) INTEGER* Specifies the problem type to be solved:* = 1: A*x = (lambda)*B*x* = 2: A*B*x = (lambda)*x* = 3: B*A*x = (lambda)*x** JOBZ (input) CHARACTER*1* = 'N': Compute eigenvalues only;* = 'V': Compute eigenvalues and eigenvectors.** UPLO (input) CHARACTER*1* = 'U': Upper triangles of A and B are stored;* = 'L': Lower triangles of A and B are stored.** 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)*(2*n-j)/2) = A(i,j) for j<=i<=n.** On exit, the contents of AP are destroyed.** BP (input/output) DOUBLE PRECISION array, dimension (N*(N+1)/2)* On entry, the upper or lower triangle of the symmetric matrix* B, packed columnwise in a linear array. The j-th column of B* is stored in the array BP as follows:* if UPLO = 'U', BP(i + (j-1)*j/2) = B(i,j) for 1<=i<=j;* if UPLO = 'L', BP(i + (j-1)*(2*n-j)/2) = B(i,j) for j<=i<=n.** On exit, the triangular factor U or L from the Cholesky* factorization B = U**T*U or B = L*L**T, in the same storage* format as B.** W (output) DOUBLE PRECISION array, dimension (N)* If INFO = 0, the eigenvalues in ascending order.** Z (output) DOUBLE PRECISION array, dimension (LDZ, N)* If JOBZ = 'V', then if INFO = 0, Z contains the matrix Z of* eigenvectors. The eigenvectors are normalized as follows:* if ITYPE = 1 or 2, Z**T*B*Z = I;* if ITYPE = 3, Z**T*inv(B)*Z = I.* If JOBZ = 'N', then Z is not referenced.** LDZ (input) INTEGER* The leading dimension of the array Z. LDZ >= 1, and if* JOBZ = 'V', LDZ >= max(1,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.* If N <= 1, LWORK >= 1.* If JOBZ = 'N' and N > 1, LWORK >= 2*N.* If JOBZ = 'V' and N > 1, LWORK >= 1 + 6*N + 2*N**2.** 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.* If JOBZ = 'N' or N <= 1, LIWORK >= 1.* If JOBZ = 'V' and N > 1, LIWORK >= 3 + 5*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: DPPTRF or DSPEVD returned an error code:* <= N: if INFO = i, DSPEVD failed to converge;* i off-diagonal elements of an intermediate* tridiagonal form did not converge to zero;* > N: if INFO = N + i, for 1 <= i <= N, then the leading* minor of order i of B is not positive definite.* The factorization of B could not be completed and* no eigenvalues or eigenvectors were computed.** Further Details* ===============** Based on contributions by* Mark Fahey, Department of Mathematics, Univ. of Kentucky, USA** =====================================================================** .. Parameters ..DOUBLE PRECISION TWOPARAMETER ( TWO = 2.0D+0 )* ..* .. Local Scalars ..LOGICAL LQUERY, UPPER, WANTZCHARACTER TRANSINTEGER J, LGN, LIWMIN, LWMIN, NEIG* ..* .. External Functions ..LOGICAL LSAMEEXTERNAL LSAME* ..* .. External Subroutines ..EXTERNAL DPPTRF, DSPEVD, DSPGST, DTPMV, DTPSV, XERBLA* ..* .. Intrinsic Functions ..INTRINSIC DBLE, INT, LOG, MAX* ..* .. Executable Statements ..** Test the input parameters.*WANTZ = LSAME( JOBZ, 'V' )UPPER = LSAME( UPLO, 'U' )LQUERY = ( LWORK.EQ.-1 .OR. LIWORK.EQ.-1 )*INFO = 0IF( N.LE.1 ) THENLGN = 0LIWMIN = 1LWMIN = 1ELSELGN = INT( LOG( DBLE( N ) ) / LOG( TWO ) )IF( 2**LGN.LT.N )$ LGN = LGN + 1IF( 2**LGN.LT.N )$ LGN = LGN + 1IF( WANTZ ) THENLIWMIN = 3 + 5*NLWMIN = 1 + 5*N + 2*N*LGN + 2*N**2ELSELIWMIN = 1LWMIN = 2*NEND IFEND IF*IF( ITYPE.LT.0 .OR. ITYPE.GT.3 ) THENINFO = -1ELSE IF( .NOT.( WANTZ .OR. LSAME( JOBZ, 'N' ) ) ) THENINFO = -2ELSE IF( .NOT.( UPPER .OR. LSAME( UPLO, 'L' ) ) ) THENINFO = -3ELSE IF( N.LT.0 ) THENINFO = -4ELSE IF( LDZ.LT.MAX( 1, N ) ) THENINFO = -9ELSE IF( LWORK.LT.LWMIN .AND. .NOT.LQUERY ) THENINFO = -11ELSE IF( LIWORK.LT.LIWMIN .AND. .NOT.LQUERY ) THENINFO = -13END IF*IF( INFO.EQ.0 ) THENWORK( 1 ) = LWMINIWORK( 1 ) = LIWMINEND IF*IF( INFO.NE.0 ) THENCALL XERBLA( 'DSPGVD', -INFO )RETURNELSE IF( LQUERY ) THENRETURNEND IF** Quick return if possible*IF( N.EQ.0 )$ RETURN** Form a Cholesky factorization of BP.*CALL DPPTRF( UPLO, N, BP, INFO )IF( INFO.NE.0 ) THENINFO = N + INFORETURNEND IF** Transform problem to standard eigenvalue problem and solve.*CALL DSPGST( ITYPE, UPLO, N, AP, BP, INFO )CALL DSPEVD( JOBZ, UPLO, N, AP, W, Z, LDZ, WORK, LWORK, IWORK,$ LIWORK, INFO )LWMIN = MAX( DBLE( LWMIN ), DBLE( WORK( 1 ) ) )LIWMIN = MAX( DBLE( LIWMIN ), DBLE( IWORK( 1 ) ) )*IF( WANTZ ) THEN** Backtransform eigenvectors to the original problem.*NEIG = NIF( INFO.GT.0 )$ NEIG = INFO - 1IF( ITYPE.EQ.1 .OR. ITYPE.EQ.2 ) THEN** For A*x=(lambda)*B*x and A*B*x=(lambda)*x;* backtransform eigenvectors: x = inv(L)'*y or inv(U)*y*IF( UPPER ) THENTRANS = 'N'ELSETRANS = 'T'END IF*DO 10 J = 1, NEIGCALL DTPSV( UPLO, TRANS, 'Non-unit', N, BP, Z( 1, J ),$ 1 )10 CONTINUE*ELSE IF( ITYPE.EQ.3 ) THEN** For B*A*x=(lambda)*x;* backtransform eigenvectors: x = L*y or U'*y*IF( UPPER ) THENTRANS = 'T'ELSETRANS = 'N'END IF*DO 20 J = 1, NEIGCALL DTPMV( UPLO, TRANS, 'Non-unit', N, BP, Z( 1, J ),$ 1 )20 CONTINUEEND IFEND IF*WORK( 1 ) = LWMINIWORK( 1 ) = LIWMIN*RETURN** End of DSPGVD*ENDSUBROUTINE DSPGVX( ITYPE, JOBZ, RANGE, UPLO, N, AP, BP, VL, VU,$ IL, IU, ABSTOL, M, W, Z, LDZ, WORK, IWORK,$ IFAIL, INFO )** -- LAPACK driver 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, RANGE, UPLOINTEGER IL, INFO, ITYPE, IU, LDZ, M, NDOUBLE PRECISION ABSTOL, VL, VU* ..* .. Array Arguments ..INTEGER IFAIL( * ), IWORK( * )DOUBLE PRECISION AP( * ), BP( * ), W( * ), WORK( * ),$ Z( LDZ, * )* ..** Purpose* =======** DSPGVX computes selected eigenvalues, and optionally, eigenvectors* of a real generalized symmetric-definite eigenproblem, of the form* A*x=(lambda)*B*x, A*Bx=(lambda)*x, or B*A*x=(lambda)*x. Here A* and B are assumed to be symmetric, stored in packed storage, and B* is also positive definite. Eigenvalues and eigenvectors can be* selected by specifying either a range of values or a range of indices* for the desired eigenvalues.** Arguments* =========** ITYPE (input) INTEGER* Specifies the problem type to be solved:* = 1: A*x = (lambda)*B*x* = 2: A*B*x = (lambda)*x* = 3: B*A*x = (lambda)*x** JOBZ (input) CHARACTER*1* = 'N': Compute eigenvalues only;* = 'V': Compute eigenvalues and eigenvectors.** RANGE (input) CHARACTER*1* = 'A': all eigenvalues will be found.* = 'V': all eigenvalues in the half-open interval (VL,VU]* will be found.* = 'I': the IL-th through IU-th eigenvalues will be found.** UPLO (input) CHARACTER*1* = 'U': Upper triangle of A and B are stored;* = 'L': Lower triangle of A and B are stored.** N (input) INTEGER* The order of the matrix pencil (A,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)*(2*n-j)/2) = A(i,j) for j<=i<=n.** On exit, the contents of AP are destroyed.** BP (input/output) DOUBLE PRECISION array, dimension (N*(N+1)/2)* On entry, the upper or lower triangle of the symmetric matrix* B, packed columnwise in a linear array. The j-th column of B* is stored in the array BP as follows:* if UPLO = 'U', BP(i + (j-1)*j/2) = B(i,j) for 1<=i<=j;* if UPLO = 'L', BP(i + (j-1)*(2*n-j)/2) = B(i,j) for j<=i<=n.** On exit, the triangular factor U or L from the Cholesky* factorization B = U**T*U or B = L*L**T, in the same storage* format as B.** 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.* An approximate eigenvalue is accepted as converged* when it is determined to lie in an interval [a,b]* of width less than or equal to** ABSTOL + EPS * max( |a|,|b| ) ,** where EPS is the machine precision. If ABSTOL is less than* or equal to zero, then EPS*|T| will be used in its place,* where |T| is the 1-norm of the tridiagonal matrix obtained* by reducing A to tridiagonal form.** Eigenvalues will be computed most accurately when ABSTOL is* set to twice the underflow threshold 2*DLAMCH('S'), not zero.* If this routine returns with INFO>0, indicating that some* eigenvectors did not converge, try setting ABSTOL to* 2*DLAMCH('S').** M (output) INTEGER* The total number of eigenvalues found. 0 <= M <= N.* If RANGE = 'A', M = N, and if RANGE = 'I', M = IU-IL+1.** W (output) DOUBLE PRECISION array, dimension (N)* On normal exit, the first M elements contain the selected* eigenvalues in ascending order.** Z (output) DOUBLE PRECISION array, dimension (LDZ, max(1,M))* If JOBZ = 'N', then Z is not referenced.* If JOBZ = 'V', then if INFO = 0, the first M columns of Z* contain the orthonormal eigenvectors of the matrix A* corresponding to the selected eigenvalues, with the i-th* column of Z holding the eigenvector associated with W(i).* The eigenvectors are normalized as follows:* if ITYPE = 1 or 2, Z**T*B*Z = I;* if ITYPE = 3, Z**T*inv(B)*Z = I.** If an eigenvector fails to converge, then that column of Z* contains the latest approximation to the eigenvector, and the* index of the eigenvector is returned in IFAIL.* Note: the user must ensure that at least max(1,M) columns are* supplied in the array Z; if RANGE = 'V', the exact value of M* is not known in advance and an upper bound must be used.** LDZ (input) INTEGER* The leading dimension of the array Z. LDZ >= 1, and if* JOBZ = 'V', LDZ >= max(1,N).** WORK (workspace) DOUBLE PRECISION array, dimension (8*N)** IWORK (workspace) INTEGER array, dimension (5*N)** IFAIL (output) INTEGER array, dimension (N)* If JOBZ = 'V', then if INFO = 0, the first M elements of* IFAIL are zero. If INFO > 0, then IFAIL contains the* indices of the eigenvectors that failed to converge.* If JOBZ = 'N', then IFAIL is not referenced.** INFO (output) INTEGER* = 0: successful exit* < 0: if INFO = -i, the i-th argument had an illegal value* > 0: DPPTRF or DSPEVX returned an error code:* <= N: if INFO = i, DSPEVX failed to converge;* i eigenvectors failed to converge. Their indices* are stored in array IFAIL.* > N: if INFO = N + i, for 1 <= i <= N, then the leading* minor of order i of B is not positive definite.* The factorization of B could not be completed and* no eigenvalues or eigenvectors were computed.** Further Details* ===============** Based on contributions by* Mark Fahey, Department of Mathematics, Univ. of Kentucky, USA** =====================================================================** .. Local Scalars ..LOGICAL ALLEIG, INDEIG, UPPER, VALEIG, WANTZCHARACTER TRANSINTEGER J* ..* .. External Functions ..LOGICAL LSAMEEXTERNAL LSAME* ..* .. External Subroutines ..EXTERNAL DPPTRF, DSPEVX, DSPGST, DTPMV, DTPSV, XERBLA* ..* .. Intrinsic Functions ..INTRINSIC MIN* ..* .. Executable Statements ..** Test the input parameters.*UPPER = LSAME( UPLO, 'U' )WANTZ = LSAME( JOBZ, 'V' )ALLEIG = LSAME( RANGE, 'A' )VALEIG = LSAME( RANGE, 'V' )INDEIG = LSAME( RANGE, 'I' )*INFO = 0IF( ITYPE.LT.0 .OR. ITYPE.GT.3 ) THENINFO = -1ELSE IF( .NOT.( WANTZ .OR. LSAME( JOBZ, 'N' ) ) ) THENINFO = -2ELSE IF( .NOT.( ALLEIG .OR. VALEIG .OR. INDEIG ) ) THENINFO = -3ELSE IF( .NOT.( UPPER .OR. LSAME( UPLO, 'L' ) ) ) THENINFO = -4ELSE IF( N.LT.0 ) THENINFO = -5ELSE IF( VALEIG .AND. N.GT.0 .AND. VU.LE.VL ) THENINFO = -9ELSE IF( INDEIG .AND. IL.LT.1 ) THENINFO = -10ELSE IF( INDEIG .AND. ( IU.LT.MIN( N, IL ) .OR. IU.GT.N ) ) THENINFO = -11ELSE IF( LDZ.LT.1 .OR. ( WANTZ .AND. LDZ.LT.N ) ) THENINFO = -16END IF*IF( INFO.NE.0 ) THENCALL XERBLA( 'DSPGVX', -INFO )RETURNEND IF** Quick return if possible*M = 0IF( N.EQ.0 ) THENWORK( 1 ) = 1RETURNEND IF** Form a Cholesky factorization of B.*CALL DPPTRF( UPLO, N, BP, INFO )IF( INFO.NE.0 ) THENINFO = N + INFORETURNEND IF** Transform problem to standard eigenvalue problem and solve.*CALL DSPGST( ITYPE, UPLO, N, AP, BP, INFO )CALL DSPEVX( JOBZ, RANGE, UPLO, N, AP, VL, VU, IL, IU, ABSTOL, M,$ W, Z, LDZ, WORK, IWORK, IFAIL, INFO )*IF( WANTZ ) THEN** Backtransform eigenvectors to the original problem.*IF( INFO.GT.0 )$ M = INFO - 1IF( ITYPE.EQ.1 .OR. ITYPE.EQ.2 ) THEN** For A*x=(lambda)*B*x and A*B*x=(lambda)*x;* backtransform eigenvectors: x = inv(L)'*y or inv(U)*y*IF( UPPER ) THENTRANS = 'N'ELSETRANS = 'T'END IF*DO 10 J = 1, MCALL DTPSV( UPLO, TRANS, 'Non-unit', N, BP, Z( 1, J ),$ 1 )10 CONTINUE*ELSE IF( ITYPE.EQ.3 ) THEN** For B*A*x=(lambda)*x;* backtransform eigenvectors: x = L*y or U'*y*IF( UPPER ) THENTRANS = 'T'ELSETRANS = 'N'END IF*DO 20 J = 1, MCALL DTPMV( UPLO, TRANS, 'Non-unit', N, BP, Z( 1, J ),$ 1 )20 CONTINUEEND IFEND IF*RETURN** End of DSPGVX*ENDSUBROUTINE DSPSV( UPLO, N, NRHS, AP, IPIV, B, LDB, INFO )** -- LAPACK driver 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* =======** DSPSV computes the solution to a real system of linear equations* A * X = B,* where A is an N-by-N symmetric matrix stored in packed format and X* and B are N-by-NRHS matrices.** The diagonal pivoting method is used to factor A as* A = U * D * U**T, if UPLO = 'U', or* A = L * D * L**T, if UPLO = 'L',* where U (or L) is a product of permutation and unit upper (lower)* triangular matrices, D is symmetric and block diagonal with 1-by-1* and 2-by-2 diagonal blocks. The factored form of A is then used to* solve the system of equations A * X = B.** Arguments* =========** UPLO (input) CHARACTER*1* = 'U': Upper triangle of A is stored;* = 'L': Lower triangle of A is stored.** N (input) INTEGER* The number of linear equations, i.e., the order of the* matrix A. N >= 0.** NRHS (input) INTEGER* The number of right hand sides, i.e., the number of columns* of the matrix B. NRHS >= 0.** 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, 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 in the same storage format as A.** IPIV (output) INTEGER array, dimension (N)* Details of the interchanges and the block structure of D, as* determined by DSPTRF. 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.** 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, D(i,i) is exactly zero. The factorization* has been completed, but the block diagonal matrix D is* exactly singular, so the solution could not be* computed.** 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 ]** =====================================================================** .. External Functions ..LOGICAL LSAMEEXTERNAL LSAME* ..* .. External Subroutines ..EXTERNAL DSPTRF, DSPTRS, 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( NRHS.LT.0 ) THENINFO = -3ELSE IF( LDB.LT.MAX( 1, N ) ) THENINFO = -7END IFIF( INFO.NE.0 ) THENCALL XERBLA( 'DSPSV ', -INFO )RETURNEND IF** Compute the factorization A = U*D*U' or A = L*D*L'.*CALL DSPTRF( UPLO, N, AP, IPIV, INFO )IF( INFO.EQ.0 ) THEN** Solve the system A*X = B, overwriting B with X.*CALL DSPTRS( UPLO, N, NRHS, AP, IPIV, B, LDB, INFO )*END IFRETURN** End of DSPSV*ENDSUBROUTINE DSPSVX( FACT, UPLO, N, NRHS, AP, AFP, IPIV, B, LDB, X,$ LDX, RCOND, FERR, BERR, WORK, IWORK, INFO )** -- LAPACK driver 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 FACT, UPLOINTEGER INFO, LDB, LDX, N, NRHSDOUBLE PRECISION RCOND* ..* .. Array Arguments ..INTEGER IPIV( * ), IWORK( * )DOUBLE PRECISION AFP( * ), AP( * ), B( LDB, * ), BERR( * ),$ FERR( * ), WORK( * ), X( LDX, * )* ..** Purpose* =======** DSPSVX uses the diagonal pivoting factorization A = U*D*U**T or* 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 matrix stored* in packed format 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 diagonal pivoting method is used to factor A as* A = U * D * U**T, if UPLO = 'U', or* A = L * D * L**T, if UPLO = 'L',* 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.** 2. If some D(i,i)=0, so that D is exactly singular, 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, AFP and IPIV contain the factored form of* A. AP, AFP and IPIV will not be modified.* = 'N': The matrix A will be copied to AFP and factored.** UPLO (input) CHARACTER*1* = 'U': Upper triangle of A is stored;* = 'L': Lower triangle of A is stored.** N (input) INTEGER* The number of linear equations, i.e., the order of the* matrix A. N >= 0.** NRHS (input) INTEGER* The number of right hand sides, i.e., the number of columns* of the 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.* See below for further details.** AFP (input or output) DOUBLE PRECISION array, dimension* (N*(N+1)/2)* If FACT = 'F', then AFP is an input argument and on entry* 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 in the same storage format as A.** If FACT = 'N', then AFP is an output argument and on exit* 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 in the same storage format as A.** IPIV (input or output) INTEGER array, dimension (N)* If FACT = 'F', then IPIV is an input argument and on entry* contains details of the interchanges and the block structure* of D, as determined by DSPTRF.* 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.** If FACT = 'N', then IPIV is an output argument and on exit* contains details of the interchanges and the block structure* of D, as determined by DSPTRF.** 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 or 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 estimate of 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 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* > 0: if INFO = i, and i is* <= N: D(i,i) is exactly zero. The factorization* has been completed but the factor D is exactly* singular, so the solution and error bounds could* not be computed. RCOND = 0 is returned.* = N+1: D 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.** 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 ZEROPARAMETER ( ZERO = 0.0D+0 )* ..* .. Local Scalars ..LOGICAL NOFACTDOUBLE PRECISION ANORM* ..* .. External Functions ..LOGICAL LSAMEDOUBLE PRECISION DLAMCH, DLANSPEXTERNAL LSAME, DLAMCH, DLANSP* ..* .. External Subroutines ..EXTERNAL DCOPY, DLACPY, DSPCON, DSPRFS, DSPTRF, DSPTRS,$ 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( .NOT.LSAME( UPLO, 'U' ) .AND. .NOT.LSAME( UPLO, 'L' ) )$ THENINFO = -2ELSE IF( N.LT.0 ) THENINFO = -3ELSE IF( NRHS.LT.0 ) THENINFO = -4ELSE IF( LDB.LT.MAX( 1, N ) ) THENINFO = -9ELSE IF( LDX.LT.MAX( 1, N ) ) THENINFO = -11END IFIF( INFO.NE.0 ) THENCALL XERBLA( 'DSPSVX', -INFO )RETURNEND IF*IF( NOFACT ) THEN** Compute the factorization A = U*D*U' or A = L*D*L'.*CALL DCOPY( N*( N+1 ) / 2, AP, 1, AFP, 1 )CALL DSPTRF( UPLO, N, AFP, IPIV, 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 = DLANSP( 'I', UPLO, N, AP, WORK )** Compute the reciprocal of the condition number of A.*CALL DSPCON( UPLO, N, AFP, IPIV, ANORM, RCOND, WORK, IWORK, 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 DSPTRS( UPLO, N, NRHS, AFP, IPIV, X, LDX, INFO )** Use iterative refinement to improve the computed solutions and* compute error bounds and backward error estimates for them.*CALL DSPRFS( UPLO, N, NRHS, AP, AFP, IPIV, B, LDB, X, LDX, FERR,$ BERR, WORK, IWORK, INFO )*RETURN** End of DSPSVX*ENDSUBROUTINE DSTEDC( COMPZ, N, D, E, Z, LDZ, WORK, LWORK, IWORK,$ LIWORK, INFO )** -- LAPACK driver 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 COMPZINTEGER INFO, LDZ, LIWORK, LWORK, N* ..* .. Array Arguments ..INTEGER IWORK( * )DOUBLE PRECISION D( * ), E( * ), WORK( * ), Z( LDZ, * )* ..** Purpose* =======** DSTEDC computes all eigenvalues and, optionally, eigenvectors of a* symmetric tridiagonal matrix using the divide and conquer method.* The eigenvectors of a full or band real symmetric matrix can also be* found if DSYTRD or DSPTRD or DSBTRD has been used to reduce this* matrix to tridiagonal form.** This code makes very mild assumptions about floating point* arithmetic. It will work on machines with a guard digit in* add/subtract, or on those binary machines without guard digits* which subtract like the Cray X-MP, Cray Y-MP, Cray C-90, or Cray-2.* It could conceivably fail on hexadecimal or decimal machines* without guard digits, but we know of none. See DLAED3 for details.** Arguments* =========** COMPZ (input) CHARACTER*1* = 'N': Compute eigenvalues only.* = 'I': Compute eigenvectors of tridiagonal matrix also.* = 'V': Compute eigenvectors of original dense symmetric* matrix also. On entry, Z contains the orthogonal* matrix used to reduce the original matrix to* tridiagonal form.** N (input) INTEGER* The dimension of the symmetric tridiagonal 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 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.* If eigenvectors are desired, then LDZ >= max(1,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.* If COMPZ = 'N' or N <= 1 then LWORK must be at least 1.* If COMPZ = 'V' and N > 1 then LWORK must be at least* ( 1 + 3*N + 2*N*lg N + 3*N**2 ),* where lg( N ) = smallest integer k such* that 2**k >= N.* If COMPZ = 'I' and N > 1 then LWORK must be at least* ( 1 + 4*N + N**2 ).** 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.* If COMPZ = 'N' or N <= 1 then LIWORK must be at least 1.* If COMPZ = 'V' and N > 1 then LIWORK must be at least* ( 6 + 6*N + 5*N*lg N ).* If COMPZ = 'I' and N > 1 then LIWORK must be at least* ( 3 + 5*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: The algorithm failed to compute an eigenvalue while* working on the submatrix lying in rows and columns* INFO/(N+1) through mod(INFO,N+1).** Further Details* ===============** Based on contributions by* Jeff Rutter, Computer Science Division, University of California* at Berkeley, USA* Modified by Francoise Tisseur, University of Tennessee.** =====================================================================** .. Parameters ..DOUBLE PRECISION ZERO, ONE, TWOPARAMETER ( ZERO = 0.0D0, ONE = 1.0D0, TWO = 2.0D0 )* ..* .. Local Scalars ..LOGICAL LQUERYINTEGER DTRTRW, END, I, ICOMPZ, II, J, K, LGN, LIWMIN,$ LWMIN, M, SMLSIZ, START, STOREZDOUBLE PRECISION EPS, ORGNRM, P, TINY* ..* .. External Functions ..LOGICAL LSAMEINTEGER ILAENVDOUBLE PRECISION DLAMCH, DLANSTEXTERNAL LSAME, ILAENV, DLAMCH, DLANST* ..* .. External Subroutines ..EXTERNAL DGEMM, DLACPY, DLAED0, DLASCL, DLASET, DLASRT,$ DSTEQR, DSTERF, DSWAP, XERBLA* ..* .. Intrinsic Functions ..INTRINSIC ABS, DBLE, INT, LOG, MAX, MOD, SQRT* ..* .. Executable Statements ..** Test the input parameters.*INFO = 0LQUERY = ( LWORK.EQ.-1 .OR. LIWORK.EQ.-1 )*IF( LSAME( COMPZ, 'N' ) ) THENICOMPZ = 0ELSE IF( LSAME( COMPZ, 'V' ) ) THENICOMPZ = 1ELSE IF( LSAME( COMPZ, 'I' ) ) THENICOMPZ = 2ELSEICOMPZ = -1END IFIF( N.LE.1 .OR. ICOMPZ.LE.0 ) THENLIWMIN = 1LWMIN = 1ELSELGN = INT( LOG( DBLE( N ) ) / LOG( TWO ) )IF( 2**LGN.LT.N )$ LGN = LGN + 1IF( 2**LGN.LT.N )$ LGN = LGN + 1IF( ICOMPZ.EQ.1 ) THENLWMIN = 1 + 3*N + 2*N*LGN + 3*N**2LIWMIN = 6 + 6*N + 5*N*LGNELSE IF( ICOMPZ.EQ.2 ) THENLWMIN = 1 + 4*N + N**2LIWMIN = 3 + 5*NEND IFEND 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 = -6ELSE IF( LWORK.LT.LWMIN .AND. .NOT.LQUERY ) THENINFO = -8ELSE IF( LIWORK.LT.LIWMIN .AND. .NOT.LQUERY ) THENINFO = -10END IF*IF( INFO.EQ.0 ) THENWORK( 1 ) = LWMINIWORK( 1 ) = LIWMINEND IF*IF( INFO.NE.0 ) THENCALL XERBLA( 'DSTEDC', -INFO )RETURNELSE IF( LQUERY ) THENRETURNEND IF** Quick return if possible*IF( N.EQ.0 )$ RETURNIF( N.EQ.1 ) THENIF( ICOMPZ.NE.0 )$ Z( 1, 1 ) = ONERETURNEND IF*SMLSIZ = ILAENV( 9, 'DSTEDC', ' ', 0, 0, 0, 0 )** If the following conditional clause is removed, then the routine* will use the Divide and Conquer routine to compute only the* eigenvalues, which requires (3N + 3N**2) real workspace and* (2 + 5N + 2N lg(N)) integer workspace.* Since on many architectures DSTERF is much faster than any other* algorithm for finding eigenvalues only, it is used here* as the default.** If COMPZ = 'N', use DSTERF to compute the eigenvalues.*IF( ICOMPZ.EQ.0 ) THENCALL DSTERF( N, D, E, INFO )RETURNEND IF** If N is smaller than the minimum divide size (SMLSIZ+1), then* solve the problem with another solver.*IF( N.LE.SMLSIZ ) THENIF( ICOMPZ.EQ.0 ) THENCALL DSTERF( N, D, E, INFO )RETURNELSE IF( ICOMPZ.EQ.2 ) THENCALL DSTEQR( 'I', N, D, E, Z, LDZ, WORK, INFO )RETURNELSECALL DSTEQR( 'V', N, D, E, Z, LDZ, WORK, INFO )RETURNEND IFEND IF** If COMPZ = 'V', the Z matrix must be stored elsewhere for later* use.*IF( ICOMPZ.EQ.1 ) THENSTOREZ = 1 + N*NELSESTOREZ = 1END IF*IF( ICOMPZ.EQ.2 ) THENCALL DLASET( 'Full', N, N, ZERO, ONE, Z, LDZ )END IF** Scale.*ORGNRM = DLANST( 'M', N, D, E )IF( ORGNRM.EQ.ZERO )$ RETURN*EPS = DLAMCH( 'Epsilon' )*START = 1** while ( START <= N )*10 CONTINUEIF( START.LE.N ) THEN** Let END be the position of the next subdiagonal entry such that* E( END ) <= TINY or END = N if no such subdiagonal exists. The* matrix identified by the elements between START and END* constitutes an independent sub-problem.*END = START20 CONTINUEIF( END.LT.N ) THENTINY = EPS*SQRT( ABS( D( END ) ) )*SQRT( ABS( D( END+1 ) ) )IF( ABS( E( END ) ).GT.TINY ) THENEND = END + 1GO TO 20END IFEND IF** (Sub) Problem determined. Compute its size and solve it.*M = END - START + 1IF( M.EQ.1 ) THENSTART = END + 1GO TO 10END IFIF( M.GT.SMLSIZ ) THENINFO = SMLSIZ** Scale.*ORGNRM = DLANST( 'M', M, D( START ), E( START ) )CALL DLASCL( 'G', 0, 0, ORGNRM, ONE, M, 1, D( START ), M,$ INFO )CALL DLASCL( 'G', 0, 0, ORGNRM, ONE, M-1, 1, E( START ),$ M-1, INFO )*IF( ICOMPZ.EQ.1 ) THENDTRTRW = 1ELSEDTRTRW = STARTEND IFCALL DLAED0( ICOMPZ, N, M, D( START ), E( START ),$ Z( DTRTRW, START ), LDZ, WORK( 1 ), N,$ WORK( STOREZ ), IWORK, INFO )IF( INFO.NE.0 ) THENINFO = ( INFO / ( M+1 )+START-1 )*( N+1 ) +$ MOD( INFO, ( M+1 ) ) + START - 1RETURNEND IF** Scale back.*CALL DLASCL( 'G', 0, 0, ONE, ORGNRM, M, 1, D( START ), M,$ INFO )*ELSEIF( ICOMPZ.EQ.1 ) THEN** Since QR won't update a Z matrix which is larger than the* length of D, we must solve the sub-problem in a workspace and* then multiply back into Z.*CALL DSTEQR( 'I', M, D( START ), E( START ), WORK, M,$ WORK( M*M+1 ), INFO )CALL DLACPY( 'A', N, M, Z( 1, START ), LDZ,$ WORK( STOREZ ), N )CALL DGEMM( 'N', 'N', N, M, M, ONE, WORK( STOREZ ), LDZ,$ WORK, M, ZERO, Z( 1, START ), LDZ )ELSE IF( ICOMPZ.EQ.2 ) THENCALL DSTEQR( 'I', M, D( START ), E( START ),$ Z( START, START ), LDZ, WORK, INFO )ELSECALL DSTERF( M, D( START ), E( START ), INFO )END IFIF( INFO.NE.0 ) THENINFO = START*( N+1 ) + ENDRETURNEND IFEND IF*START = END + 1GO TO 10END IF** endwhile** If the problem split any number of times, then the eigenvalues* will not be properly ordered. Here we permute the eigenvalues* (and the associated eigenvectors) into ascending order.*IF( M.NE.N ) THENIF( ICOMPZ.EQ.0 ) THEN** Use Quick Sort*CALL DLASRT( 'I', N, D, INFO )*ELSE** Use Selection Sort to minimize swaps of eigenvectors*DO 40 II = 2, NI = II - 1K = IP = D( I )DO 30 J = II, NIF( D( J ).LT.P ) THENK = JP = D( J )END IF30 CONTINUEIF( K.NE.I ) THEND( K ) = D( I )D( I ) = PCALL DSWAP( N, Z( 1, I ), 1, Z( 1, K ), 1 )END IF40 CONTINUEEND IFEND IF*WORK( 1 ) = LWMINIWORK( 1 ) = LIWMIN*RETURN** End of DSTEDC*ENDSUBROUTINE DSTEV( JOBZ, N, D, E, Z, LDZ, WORK, INFO )** -- LAPACK driver 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 JOBZINTEGER INFO, LDZ, N* ..* .. Array Arguments ..DOUBLE PRECISION D( * ), E( * ), WORK( * ), Z( LDZ, * )* ..** Purpose* =======** DSTEV computes all eigenvalues and, optionally, eigenvectors of a* real symmetric tridiagonal matrix A.** Arguments* =========** JOBZ (input) CHARACTER*1* = 'N': Compute eigenvalues only;* = 'V': Compute eigenvalues and eigenvectors.** 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* A.* On exit, if INFO = 0, the eigenvalues in ascending order.** E (input/output) DOUBLE PRECISION array, dimension (N)* On entry, the (n-1) subdiagonal elements of the tridiagonal* matrix A, stored in elements 1 to N-1 of E; E(N) need not* be set, but is used by the routine.* On exit, the contents of E are destroyed.** Z (output) DOUBLE PRECISION array, dimension (LDZ, N)* If JOBZ = 'V', then if INFO = 0, Z contains the orthonormal* eigenvectors of the matrix A, with the i-th column of Z* holding the eigenvector associated with D(i).* If JOBZ = 'N', then Z is not referenced.** LDZ (input) INTEGER* The leading dimension of the array Z. LDZ >= 1, and if* JOBZ = 'V', LDZ >= max(1,N).** WORK (workspace) DOUBLE PRECISION array, dimension (max(1,2*N-2))* If JOBZ = 'N', WORK is not referenced.** INFO (output) INTEGER* = 0: successful exit* < 0: if INFO = -i, the i-th argument had an illegal value* > 0: if INFO = i, the algorithm failed to converge; i* off-diagonal elements of E did not converge to zero.** =====================================================================** .. Parameters ..DOUBLE PRECISION ZERO, ONEPARAMETER ( ZERO = 0.0D0, ONE = 1.0D0 )* ..* .. Local Scalars ..LOGICAL WANTZINTEGER IMAX, ISCALEDOUBLE PRECISION BIGNUM, EPS, RMAX, RMIN, SAFMIN, SIGMA, SMLNUM,$ TNRM* ..* .. External Functions ..LOGICAL LSAMEDOUBLE PRECISION DLAMCH, DLANSTEXTERNAL LSAME, DLAMCH, DLANST* ..* .. External Subroutines ..EXTERNAL DSCAL, DSTEQR, DSTERF, XERBLA* ..* .. Intrinsic Functions ..INTRINSIC SQRT* ..* .. Executable Statements ..** Test the input parameters.*WANTZ = LSAME( JOBZ, 'V' )*INFO = 0IF( .NOT.( WANTZ .OR. LSAME( JOBZ, 'N' ) ) ) THENINFO = -1ELSE IF( N.LT.0 ) THENINFO = -2ELSE IF( LDZ.LT.1 .OR. ( WANTZ .AND. LDZ.LT.N ) ) THENINFO = -6END IF*IF( INFO.NE.0 ) THENCALL XERBLA( 'DSTEV ', -INFO )RETURNEND IF** Quick return if possible*IF( N.EQ.0 )$ RETURN*IF( N.EQ.1 ) THENIF( WANTZ )$ Z( 1, 1 ) = ONERETURNEND IF** Get machine constants.*SAFMIN = DLAMCH( 'Safe minimum' )EPS = DLAMCH( 'Precision' )SMLNUM = SAFMIN / EPSBIGNUM = ONE / SMLNUMRMIN = SQRT( SMLNUM )RMAX = SQRT( BIGNUM )** Scale matrix to allowable range, if necessary.*ISCALE = 0TNRM = DLANST( 'M', N, D, E )IF( TNRM.GT.ZERO .AND. TNRM.LT.RMIN ) THENISCALE = 1SIGMA = RMIN / TNRMELSE IF( TNRM.GT.RMAX ) THENISCALE = 1SIGMA = RMAX / TNRMEND IFIF( ISCALE.EQ.1 ) THENCALL DSCAL( N, SIGMA, D, 1 )CALL DSCAL( N-1, SIGMA, E( 1 ), 1 )END IF** For eigenvalues only, call DSTERF. For eigenvalues and* eigenvectors, call DSTEQR.*IF( .NOT.WANTZ ) THENCALL DSTERF( N, D, E, INFO )ELSECALL DSTEQR( 'I', N, D, E, Z, LDZ, WORK, INFO )END IF** If matrix was scaled, then rescale eigenvalues appropriately.*IF( ISCALE.EQ.1 ) THENIF( INFO.EQ.0 ) THENIMAX = NELSEIMAX = INFO - 1END IFCALL DSCAL( IMAX, ONE / SIGMA, D, 1 )END IF*RETURN** End of DSTEV*ENDSUBROUTINE DSTEVD( JOBZ, N, D, E, Z, LDZ, WORK, LWORK, IWORK,$ LIWORK, INFO )** -- LAPACK driver 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 JOBZINTEGER INFO, LDZ, LIWORK, LWORK, N* ..* .. Array Arguments ..INTEGER IWORK( * )DOUBLE PRECISION D( * ), E( * ), WORK( * ), Z( LDZ, * )* ..** Purpose* =======** DSTEVD computes all eigenvalues and, optionally, eigenvectors of a* real symmetric tridiagonal matrix. If eigenvectors are desired, it* uses a divide and conquer algorithm.** The divide and conquer algorithm makes very mild assumptions about* floating point arithmetic. It will work on machines with a guard* digit in add/subtract, or on those binary machines without guard* digits which subtract like the Cray X-MP, Cray Y-MP, Cray C-90, or* Cray-2. It could conceivably fail on hexadecimal or decimal machines* without guard digits, but we know of none.** Arguments* =========** JOBZ (input) CHARACTER*1* = 'N': Compute eigenvalues only;* = 'V': Compute eigenvalues and eigenvectors.** 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* A.* On exit, if INFO = 0, the eigenvalues in ascending order.** E (input/output) DOUBLE PRECISION array, dimension (N)* On entry, the (n-1) subdiagonal elements of the tridiagonal* matrix A, stored in elements 1 to N-1 of E; E(N) need not* be set, but is used by the routine.* On exit, the contents of E are destroyed.** Z (output) DOUBLE PRECISION array, dimension (LDZ, N)* If JOBZ = 'V', then if INFO = 0, Z contains the orthonormal* eigenvectors of the matrix A, with the i-th column of Z* holding the eigenvector associated with D(i).* If JOBZ = 'N', then Z is not referenced.** LDZ (input) INTEGER* The leading dimension of the array Z. LDZ >= 1, and if* JOBZ = 'V', LDZ >= max(1,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.* If JOBZ = 'N' or N <= 1 then LWORK must be at least 1.* If JOBZ = 'V' and N > 1 then LWORK must be at least* ( 1 + 4*N + N**2 ).** 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.* If JOBZ = 'N' or N <= 1 then LIWORK must be at least 1.* If JOBZ = 'V' and N > 1 then LIWORK must be at least 3+5*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 = i, the algorithm failed to converge; i* off-diagonal elements of E did not converge to zero.** =====================================================================** .. Parameters ..DOUBLE PRECISION ZERO, ONEPARAMETER ( ZERO = 0.0D0, ONE = 1.0D0 )* ..* .. Local Scalars ..LOGICAL LQUERY, WANTZINTEGER ISCALE, LIWMIN, LWMINDOUBLE PRECISION BIGNUM, EPS, RMAX, RMIN, SAFMIN, SIGMA, SMLNUM,$ TNRM* ..* .. External Functions ..LOGICAL LSAMEDOUBLE PRECISION DLAMCH, DLANSTEXTERNAL LSAME, DLAMCH, DLANST* ..* .. External Subroutines ..EXTERNAL DSCAL, DSTEDC, DSTERF, XERBLA* ..* .. Intrinsic Functions ..INTRINSIC SQRT* ..* .. Executable Statements ..** Test the input parameters.*WANTZ = LSAME( JOBZ, 'V' )LQUERY = ( LWORK.EQ.-1 .OR. LIWORK.EQ.-1 )*INFO = 0LIWMIN = 1LWMIN = 1IF( N.GT.1 .AND. WANTZ ) THENLWMIN = 1 + 4*N + N**2LIWMIN = 3 + 5*NEND IF*IF( .NOT.( WANTZ .OR. LSAME( JOBZ, 'N' ) ) ) THENINFO = -1ELSE IF( N.LT.0 ) THENINFO = -2ELSE IF( LDZ.LT.1 .OR. ( WANTZ .AND. LDZ.LT.N ) ) THENINFO = -6ELSE IF( LWORK.LT.LWMIN .AND. .NOT.LQUERY ) THENINFO = -8ELSE IF( LIWORK.LT.LIWMIN .AND. .NOT.LQUERY ) THENINFO = -10END IF*IF( INFO.EQ.0 ) THENWORK( 1 ) = LWMINIWORK( 1 ) = LIWMINEND IF*IF( INFO.NE.0 ) THENCALL XERBLA( 'DSTEVD', -INFO )RETURNELSE IF( LQUERY ) THENRETURNEND IF** Quick return if possible*IF( N.EQ.0 )$ RETURN*IF( N.EQ.1 ) THENIF( WANTZ )$ Z( 1, 1 ) = ONERETURNEND IF** Get machine constants.*SAFMIN = DLAMCH( 'Safe minimum' )EPS = DLAMCH( 'Precision' )SMLNUM = SAFMIN / EPSBIGNUM = ONE / SMLNUMRMIN = SQRT( SMLNUM )RMAX = SQRT( BIGNUM )** Scale matrix to allowable range, if necessary.*ISCALE = 0TNRM = DLANST( 'M', N, D, E )IF( TNRM.GT.ZERO .AND. TNRM.LT.RMIN ) THENISCALE = 1SIGMA = RMIN / TNRMELSE IF( TNRM.GT.RMAX ) THENISCALE = 1SIGMA = RMAX / TNRMEND IFIF( ISCALE.EQ.1 ) THENCALL DSCAL( N, SIGMA, D, 1 )CALL DSCAL( N-1, SIGMA, E( 1 ), 1 )END IF** For eigenvalues only, call DSTERF. For eigenvalues and* eigenvectors, call DSTEDC.*IF( .NOT.WANTZ ) THENCALL DSTERF( N, D, E, INFO )ELSECALL DSTEDC( 'I', N, D, E, Z, LDZ, WORK, LWORK, IWORK, LIWORK,$ INFO )END IF** If matrix was scaled, then rescale eigenvalues appropriately.*IF( ISCALE.EQ.1 )$ CALL DSCAL( N, ONE / SIGMA, D, 1 )*WORK( 1 ) = LWMINIWORK( 1 ) = LIWMIN*RETURN** End of DSTEVD*ENDSUBROUTINE DSTEVR( JOBZ, RANGE, N, D, E, VL, VU, IL, IU, ABSTOL,$ M, W, Z, LDZ, ISUPPZ, WORK, LWORK, IWORK,$ LIWORK, INFO )** -- LAPACK driver routine (version 3.0) --* Univ. of Tennessee, Univ. of California Berkeley, NAG Ltd.,* Courant Institute, Argonne National Lab, and Rice University* March 20, 2000** .. 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* =======** DSTEVR 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.** Whenever possible, DSTEVR calls SSTEGR to compute the* eigenspectrum using Relatively Robust Representations. DSTEGR* computes eigenvalues by the dqds algorithm, while orthogonal* eigenvectors are computed from various "good" L D L^T representations* (also known as Relatively Robust Representations). Gram-Schmidt* orthogonalization is avoided as far as possible. More specifically,* the various steps of the algorithm are as follows. For 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 : DSTEVR calls SSTEGR when the full spectrum is requested* on machines which conform to the ieee-754 floating point standard.* DSTEVR calls SSTEBZ and SSTEIN on non-ieee machines and* when partial spectrum requests are made.** Normal execution of DSTEGR may create NaNs and infinities and* hence may abort due to a floating point exception in environments* which do not handle NaNs and infinities in the ieee standard default* manner.** 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.********** For RANGE = 'V' or 'I' and IU - IL < N - 1, DSTEBZ and********** DSTEIN are called** 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* A.* On exit, D may be multiplied by a constant factor chosen* to avoid over/underflow in computing the eigenvalues.** E (input/output) DOUBLE PRECISION array, dimension (N)* On entry, the (n-1) subdiagonal elements of the tridiagonal* matrix A in elements 1 to N-1 of E; E(N) need not be set.* On exit, E may be multiplied by a constant factor chosen* to avoid over/underflow in computing the eigenvalues.** 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.* An approximate eigenvalue is accepted as converged* when it is determined to lie in an interval [a,b]* of width less than or equal to** ABSTOL + EPS * max( |a|,|b| ) ,** where EPS is the machine precision. If ABSTOL is less than* or equal to zero, then EPS*|T| will be used in its place,* where |T| is the 1-norm of the tridiagonal matrix obtained* by reducing A to tridiagonal form.** See "Computing Small Singular Values of Bidiagonal Matrices* with Guaranteed High Relative Accuracy," by Demmel and* Kahan, LAPACK Working Note #3.** If high relative accuracy is important, set ABSTOL to* DLAMCH( 'Safe minimum' ). Doing so will guarantee that* eigenvalues are computed to high relative accuracy when* possible in future releases. The current code does not* make any guarantees about high relative accuracy, but* future releases will. See J. Barlow and J. 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 A* corresponding to the selected eigenvalues, with the i-th* column of Z holding the eigenvector associated with W(i).* 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 ).********** Implemented only for RANGE = 'A' or 'I' and IU - IL = N - 1** 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 >= 20*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 (and* minimal) LIWORK.** LIWORK (input) INTEGER* The dimension of the array IWORK. LIWORK >= 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: Internal error** Further Details* ===============** Based on contributions by* Inderjit Dhillon, IBM Almaden, USA* Osni Marques, LBNL/NERSC, USA* Ken Stanley, Computer Science Division, University of* California at Berkeley, USA** =====================================================================** .. Parameters ..DOUBLE PRECISION ZERO, ONEPARAMETER ( ZERO = 0.0D+0, ONE = 1.0D+0 )* ..* .. Local Scalars ..LOGICAL ALLEIG, INDEIG, LQUERY, VALEIG, WANTZCHARACTER ORDERINTEGER I, IEEEOK, IMAX, INDIBL, INDIFL, INDISP,$ INDIWO, ISCALE, ITMP1, J, JJ, LIWMIN, LWMIN,$ NSPLITDOUBLE PRECISION BIGNUM, EPS, RMAX, RMIN, SAFMIN, SIGMA, SMLNUM,$ TMP1, TNRM, VLL, VUU* ..* .. External Functions ..LOGICAL LSAMEINTEGER ILAENVDOUBLE PRECISION DLAMCH, DLANSTEXTERNAL LSAME, ILAENV, DLAMCH, DLANST* ..* .. External Subroutines ..EXTERNAL DCOPY, DSCAL, DSTEBZ, DSTEGR, DSTEIN, DSTERF,$ DSWAP, XERBLA* ..* .. Intrinsic Functions ..INTRINSIC MAX, MIN, SQRT* ..* .. Executable Statements ..*** Test the input parameters.*IEEEOK = ILAENV( 10, 'DSTEVR', 'N', 1, 2, 3, 4 )*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 = 20*NLIWMIN = 10*N**INFO = 0IF( .NOT.( WANTZ .OR. LSAME( JOBZ, 'N' ) ) ) THENINFO = -1ELSE IF( .NOT.( ALLEIG .OR. VALEIG .OR. INDEIG ) ) THENINFO = -2ELSE IF( N.LT.0 ) THENINFO = -3ELSEIF( VALEIG ) THENIF( N.GT.0 .AND. VU.LE.VL )$ INFO = -7ELSE IF( INDEIG ) THENIF( IL.LT.1 .OR. IL.GT.MAX( 1, N ) ) THENINFO = -8ELSE IF( IU.LT.MIN( N, IL ) .OR. IU.GT.N ) THENINFO = -9END IFEND IFEND IFIF( INFO.EQ.0 ) THENIF( 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 IFEND IF*IF( INFO.EQ.0 ) THENWORK( 1 ) = LWMINIWORK( 1 ) = LIWMINEND IF*IF( INFO.NE.0 ) THENCALL XERBLA( 'DSTEVR', -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.*ISCALE = 0VLL = VLVUU = VU*TNRM = DLANST( 'M', N, D, E )IF( TNRM.GT.ZERO .AND. TNRM.LT.RMIN ) THENISCALE = 1SIGMA = RMIN / TNRMELSE IF( TNRM.GT.RMAX ) THENISCALE = 1SIGMA = RMAX / TNRMEND IFIF( ISCALE.EQ.1 ) THENCALL DSCAL( N, SIGMA, D, 1 )CALL DSCAL( N-1, SIGMA, E( 1 ), 1 )IF( VALEIG ) THENVLL = VL*SIGMAVUU = VU*SIGMAEND IFEND IF** If all eigenvalues are desired, then* call DSTERF or SSTEGR. If this fails for some eigenvalue, then* try DSTEBZ.**IF( ( ALLEIG .OR. ( INDEIG .AND. IL.EQ.1 .AND. IU.EQ.N ) ) .AND.$ IEEEOK.EQ.1 ) THENCALL DCOPY( N-1, E( 1 ), 1, WORK( 1 ), 1 )IF( .NOT.WANTZ ) THENCALL DCOPY( N, D, 1, W, 1 )CALL DSTERF( N, W, WORK, INFO )ELSECALL DCOPY( N, D, 1, WORK( N+1 ), 1 )CALL DSTEGR( JOBZ, 'A', N, WORK( N+1 ), WORK, VL, VU, IL,$ IU, ABSTOL, M, W, Z, LDZ, ISUPPZ,$ WORK( 2*N+1 ), LWORK-2*N, IWORK, LIWORK, INFO )*END IFIF( INFO.EQ.0 ) THENM = NGO TO 10END IFINFO = 0END IF** Otherwise, call DSTEBZ and, if eigenvectors are desired, SSTEIN.*IF( WANTZ ) THENORDER = 'B'ELSEORDER = 'E'END IFINDIBL = 1INDISP = INDIBL + NINDIFL = INDISP + NINDIWO = INDIFL + NCALL DSTEBZ( RANGE, ORDER, N, VLL, VUU, IL, IU, ABSTOL, D, E, M,$ NSPLIT, W, IWORK( INDIBL ), IWORK( INDISP ), WORK,$ IWORK( INDIWO ), INFO )*IF( WANTZ ) THENCALL DSTEIN( N, D, E, M, W, IWORK( INDIBL ), IWORK( INDISP ),$ Z, LDZ, WORK, IWORK( INDIWO ), IWORK( INDIFL ),$ INFO )END IF** If matrix was scaled, then rescale eigenvalues appropriately.*10 CONTINUEIF( ISCALE.EQ.1 ) THENIF( INFO.EQ.0 ) THENIMAX = MELSEIMAX = INFO - 1END IFCALL DSCAL( IMAX, ONE / SIGMA, W, 1 )END IF** If eigenvalues are not in order, then sort them, along with* eigenvectors.*IF( WANTZ ) THENDO 30 J = 1, M - 1I = 0TMP1 = W( J )DO 20 JJ = J + 1, MIF( W( JJ ).LT.TMP1 ) THENI = JJTMP1 = W( JJ )END IF20 CONTINUE*IF( I.NE.0 ) THENITMP1 = IWORK( I )W( I ) = W( J )IWORK( I ) = IWORK( J )W( J ) = TMP1IWORK( J ) = ITMP1CALL DSWAP( N, Z( 1, I ), 1, Z( 1, J ), 1 )END IF30 CONTINUEEND IF** Causes problems with tests 19 & 20:* IF (wantz .and. INDEIG ) Z( 1,1) = Z(1,1) / 1.002 + .002**WORK( 1 ) = LWMINIWORK( 1 ) = LIWMINRETURN** End of DSTEVR*ENDSUBROUTINE DSTEVX( JOBZ, RANGE, N, D, E, VL, VU, IL, IU, ABSTOL,$ M, W, Z, LDZ, WORK, IWORK, IFAIL, INFO )** -- LAPACK driver 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, M, NDOUBLE PRECISION ABSTOL, VL, VU* ..* .. Array Arguments ..INTEGER IFAIL( * ), IWORK( * )DOUBLE PRECISION D( * ), E( * ), W( * ), WORK( * ), Z( LDZ, * )* ..** Purpose* =======** DSTEVX computes selected eigenvalues and, optionally, eigenvectors* of a real symmetric tridiagonal matrix A. Eigenvalues and* eigenvectors can be selected by specifying either a range of values* or a range of indices for the desired eigenvalues.** Arguments* =========** JOBZ (input) CHARACTER*1* = 'N': Compute eigenvalues only;* = 'V': Compute eigenvalues and eigenvectors.** RANGE (input) CHARACTER*1* = 'A': all eigenvalues will be found.* = 'V': all eigenvalues in the half-open interval (VL,VU]* will be found.* = 'I': the IL-th through IU-th eigenvalues will be found.** 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* A.* On exit, D may be multiplied by a constant factor chosen* to avoid over/underflow in computing the eigenvalues.** E (input/output) DOUBLE PRECISION array, dimension (N)* On entry, the (n-1) subdiagonal elements of the tridiagonal* matrix A in elements 1 to N-1 of E; E(N) need not be set.* On exit, E may be multiplied by a constant factor chosen* to avoid over/underflow in computing the eigenvalues.** 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.* An approximate eigenvalue is accepted as converged* when it is determined to lie in an interval [a,b]* of width less than or equal to** ABSTOL + EPS * max( |a|,|b| ) ,** where EPS is the machine precision. If ABSTOL is less* than or equal to zero, then EPS*|T| will be used in* its place, where |T| is the 1-norm of the tridiagonal* matrix.** Eigenvalues will be computed most accurately when ABSTOL is* set to twice the underflow threshold 2*DLAMCH('S'), not zero.* If this routine returns with INFO>0, indicating that some* eigenvectors did not converge, try setting ABSTOL to* 2*DLAMCH('S').** See "Computing Small Singular Values of Bidiagonal Matrices* with Guaranteed High Relative Accuracy," by Demmel and* Kahan, LAPACK Working Note #3.** M (output) INTEGER* The total number of eigenvalues found. 0 <= M <= N.* If RANGE = 'A', M = N, and if RANGE = 'I', M = IU-IL+1.** W (output) DOUBLE PRECISION array, dimension (N)* 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 A* corresponding to the selected eigenvalues, with the i-th* column of Z holding the eigenvector associated with W(i).* If an eigenvector fails to converge (INFO > 0), then that* column of Z contains the latest approximation to the* eigenvector, and the index of the eigenvector is returned* in IFAIL. If JOBZ = 'N', then Z is not referenced.* Note: the user must ensure that at least max(1,M) columns are* supplied in the array Z; if RANGE = 'V', the exact value of M* is not known in advance and an upper bound must be used.** LDZ (input) INTEGER* The leading dimension of the array Z. LDZ >= 1, and if* JOBZ = 'V', LDZ >= max(1,N).** WORK (workspace) DOUBLE PRECISION array, dimension (5*N)** IWORK (workspace) INTEGER array, dimension (5*N)** IFAIL (output) INTEGER array, dimension (N)* If JOBZ = 'V', then if INFO = 0, the first M elements of* IFAIL are zero. If INFO > 0, then IFAIL contains the* indices of the eigenvectors that failed to converge.* If JOBZ = 'N', then IFAIL is not referenced.** INFO (output) INTEGER* = 0: successful exit* < 0: if INFO = -i, the i-th argument had an illegal value* > 0: if INFO = i, then i eigenvectors failed to converge.* Their indices are stored in array IFAIL.** =====================================================================** .. Parameters ..DOUBLE PRECISION ZERO, ONEPARAMETER ( ZERO = 0.0D0, ONE = 1.0D0 )* ..* .. Local Scalars ..LOGICAL ALLEIG, INDEIG, VALEIG, WANTZCHARACTER ORDERINTEGER I, IMAX, INDIBL, INDISP, INDIWO, INDWRK,$ ISCALE, ITMP1, J, JJ, NSPLITDOUBLE PRECISION BIGNUM, EPS, RMAX, RMIN, SAFMIN, SIGMA, SMLNUM,$ TMP1, TNRM, VLL, VUU* ..* .. External Functions ..LOGICAL LSAMEDOUBLE PRECISION DLAMCH, DLANSTEXTERNAL LSAME, DLAMCH, DLANST* ..* .. External Subroutines ..EXTERNAL DCOPY, DSCAL, DSTEBZ, DSTEIN, DSTEQR, DSTERF,$ DSWAP, XERBLA* ..* .. Intrinsic Functions ..INTRINSIC 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' )*INFO = 0IF( .NOT.( WANTZ .OR. LSAME( JOBZ, 'N' ) ) ) THENINFO = -1ELSE IF( .NOT.( ALLEIG .OR. VALEIG .OR. INDEIG ) ) THENINFO = -2ELSE IF( N.LT.0 ) THENINFO = -3ELSEIF( VALEIG ) THENIF( N.GT.0 .AND. VU.LE.VL )$ INFO = -7ELSE IF( INDEIG ) THENIF( IL.LT.1 .OR. IL.GT.MAX( 1, N ) ) THENINFO = -8ELSE IF( IU.LT.MIN( N, IL ) .OR. IU.GT.N ) THENINFO = -9END IFEND IFEND IFIF( INFO.EQ.0 ) THENIF( LDZ.LT.1 .OR. ( WANTZ .AND. LDZ.LT.N ) )$ INFO = -14END IF*IF( INFO.NE.0 ) THENCALL XERBLA( 'DSTEVX', -INFO )RETURNEND 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.*ISCALE = 0IF( VALEIG ) THENVLL = VLVUU = VUELSEVLL = ZEROVUU = ZEROEND IFTNRM = DLANST( 'M', N, D, E )IF( TNRM.GT.ZERO .AND. TNRM.LT.RMIN ) THENISCALE = 1SIGMA = RMIN / TNRMELSE IF( TNRM.GT.RMAX ) THENISCALE = 1SIGMA = RMAX / TNRMEND IFIF( ISCALE.EQ.1 ) THENCALL DSCAL( N, SIGMA, D, 1 )CALL DSCAL( N-1, SIGMA, E( 1 ), 1 )IF( VALEIG ) THENVLL = VL*SIGMAVUU = VU*SIGMAEND IFEND IF** If all eigenvalues are desired and ABSTOL is less than zero, then* call DSTERF or SSTEQR. If this fails for some eigenvalue, then* try DSTEBZ.*IF( ( ALLEIG .OR. ( INDEIG .AND. IL.EQ.1 .AND. IU.EQ.N ) ) .AND.$ ( ABSTOL.LE.ZERO ) ) THENCALL DCOPY( N, D, 1, W, 1 )CALL DCOPY( N-1, E( 1 ), 1, WORK( 1 ), 1 )INDWRK = N + 1IF( .NOT.WANTZ ) THENCALL DSTERF( N, W, WORK, INFO )ELSECALL DSTEQR( 'I', N, W, WORK, Z, LDZ, WORK( INDWRK ), INFO )IF( INFO.EQ.0 ) THENDO 10 I = 1, NIFAIL( I ) = 010 CONTINUEEND IFEND IFIF( INFO.EQ.0 ) THENM = NGO TO 20END IFINFO = 0END IF** Otherwise, call DSTEBZ and, if eigenvectors are desired, SSTEIN.*IF( WANTZ ) THENORDER = 'B'ELSEORDER = 'E'END IFINDWRK = 1INDIBL = 1INDISP = INDIBL + NINDIWO = INDISP + NCALL DSTEBZ( RANGE, ORDER, N, VLL, VUU, IL, IU, ABSTOL, D, E, M,$ NSPLIT, W, IWORK( INDIBL ), IWORK( INDISP ),$ WORK( INDWRK ), IWORK( INDIWO ), INFO )*IF( WANTZ ) THENCALL DSTEIN( N, D, E, M, W, IWORK( INDIBL ), IWORK( INDISP ),$ Z, LDZ, WORK( INDWRK ), IWORK( INDIWO ), IFAIL,$ INFO )END IF** If matrix was scaled, then rescale eigenvalues appropriately.*20 CONTINUEIF( ISCALE.EQ.1 ) THENIF( INFO.EQ.0 ) THENIMAX = MELSEIMAX = INFO - 1END IFCALL DSCAL( IMAX, ONE / SIGMA, W, 1 )END IF** If eigenvalues are not in order, then sort them, along with* eigenvectors.*IF( WANTZ ) THENDO 40 J = 1, M - 1I = 0TMP1 = W( J )DO 30 JJ = J + 1, MIF( W( JJ ).LT.TMP1 ) THENI = JJTMP1 = W( JJ )END IF30 CONTINUE*IF( I.NE.0 ) THENITMP1 = IWORK( INDIBL+I-1 )W( I ) = W( J )IWORK( INDIBL+I-1 ) = IWORK( INDIBL+J-1 )W( J ) = TMP1IWORK( INDIBL+J-1 ) = ITMP1CALL DSWAP( N, Z( 1, I ), 1, Z( 1, J ), 1 )IF( INFO.NE.0 ) THENITMP1 = IFAIL( I )IFAIL( I ) = IFAIL( J )IFAIL( J ) = ITMP1END IFEND IF40 CONTINUEEND IF*RETURN** End of DSTEVX*ENDSUBROUTINE DSYEV( JOBZ, UPLO, N, A, LDA, W, WORK, LWORK, INFO )** -- LAPACK driver 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, UPLOINTEGER INFO, LDA, LWORK, N* ..* .. Array Arguments ..DOUBLE PRECISION A( LDA, * ), W( * ), WORK( * )* ..** Purpose* =======** DSYEV computes all eigenvalues and, optionally, eigenvectors of a* real symmetric matrix A.** Arguments* =========** JOBZ (input) CHARACTER*1* = 'N': Compute eigenvalues only;* = 'V': Compute eigenvalues and eigenvectors.** 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. If UPLO = 'L',* the leading N-by-N lower triangular part of A contains* the lower triangular part of the matrix A.* On exit, if JOBZ = 'V', then if INFO = 0, A contains the* orthonormal eigenvectors of the matrix A.* If JOBZ = 'N', then on exit the lower triangle (if UPLO='L')* or the upper triangle (if UPLO='U') of A, including the* diagonal, is destroyed.** LDA (input) INTEGER* The leading dimension of the array A. LDA >= max(1,N).** W (output) DOUBLE PRECISION array, dimension (N)* If INFO = 0, the eigenvalues in ascending order.** 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 the array WORK. LWORK >= max(1,3*N-1).* For optimal efficiency, LWORK >= (NB+2)*N,* where NB is the blocksize for DSYTRD 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, the algorithm failed to converge; i* off-diagonal elements of an intermediate tridiagonal* form did not converge to zero.** =====================================================================** .. Parameters ..DOUBLE PRECISION ZERO, ONEPARAMETER ( ZERO = 0.0D0, ONE = 1.0D0 )* ..* .. Local Scalars ..LOGICAL LOWER, LQUERY, WANTZINTEGER IINFO, IMAX, INDE, INDTAU, INDWRK, ISCALE,$ LLWORK, LOPT, LWKOPT, NBDOUBLE PRECISION ANRM, BIGNUM, EPS, RMAX, RMIN, SAFMIN, SIGMA,$ SMLNUM* ..* .. External Functions ..LOGICAL LSAMEINTEGER ILAENVDOUBLE PRECISION DLAMCH, DLANSYEXTERNAL LSAME, ILAENV, DLAMCH, DLANSY* ..* .. External Subroutines ..EXTERNAL DLASCL, DORGTR, DSCAL, DSTEQR, DSTERF, DSYTRD,$ XERBLA* ..* .. Intrinsic Functions ..INTRINSIC MAX, SQRT* ..* .. Executable Statements ..** Test the input parameters.*WANTZ = LSAME( JOBZ, 'V' )LOWER = LSAME( UPLO, 'L' )LQUERY = ( LWORK.EQ.-1 )*INFO = 0IF( .NOT.( WANTZ .OR. LSAME( JOBZ, 'N' ) ) ) THENINFO = -1ELSE IF( .NOT.( LOWER .OR. LSAME( UPLO, 'U' ) ) ) THENINFO = -2ELSE IF( N.LT.0 ) THENINFO = -3ELSE IF( LDA.LT.MAX( 1, N ) ) THENINFO = -5ELSE IF( LWORK.LT.MAX( 1, 3*N-1 ) .AND. .NOT.LQUERY ) THENINFO = -8END IF*IF( INFO.EQ.0 ) THENNB = ILAENV( 1, 'DSYTRD', UPLO, N, -1, -1, -1 )LWKOPT = MAX( 1, ( NB+2 )*N )WORK( 1 ) = LWKOPTEND IF*IF( INFO.NE.0 ) THENCALL XERBLA( 'DSYEV ', -INFO )RETURNELSE IF( LQUERY ) THENRETURNEND IF** Quick return if possible*IF( N.EQ.0 ) THENWORK( 1 ) = 1RETURNEND IF*IF( N.EQ.1 ) THENW( 1 ) = A( 1, 1 )WORK( 1 ) = 3IF( WANTZ )$ A( 1, 1 ) = ONERETURNEND IF** Get machine constants.*SAFMIN = DLAMCH( 'Safe minimum' )EPS = DLAMCH( 'Precision' )SMLNUM = SAFMIN / EPSBIGNUM = ONE / SMLNUMRMIN = SQRT( SMLNUM )RMAX = SQRT( BIGNUM )** Scale matrix to allowable range, if necessary.*ANRM = DLANSY( 'M', UPLO, N, A, LDA, WORK )ISCALE = 0IF( ANRM.GT.ZERO .AND. ANRM.LT.RMIN ) THENISCALE = 1SIGMA = RMIN / ANRMELSE IF( ANRM.GT.RMAX ) THENISCALE = 1SIGMA = RMAX / ANRMEND IFIF( ISCALE.EQ.1 )$ CALL DLASCL( UPLO, 0, 0, ONE, SIGMA, N, N, A, LDA, INFO )** Call DSYTRD to reduce symmetric matrix to tridiagonal form.*INDE = 1INDTAU = INDE + NINDWRK = INDTAU + NLLWORK = LWORK - INDWRK + 1CALL DSYTRD( UPLO, N, A, LDA, W, WORK( INDE ), WORK( INDTAU ),$ WORK( INDWRK ), LLWORK, IINFO )LOPT = 2*N + WORK( INDWRK )** For eigenvalues only, call DSTERF. For eigenvectors, first call* DORGTR to generate the orthogonal matrix, then call DSTEQR.*IF( .NOT.WANTZ ) THENCALL DSTERF( N, W, WORK( INDE ), INFO )ELSECALL DORGTR( UPLO, N, A, LDA, WORK( INDTAU ), WORK( INDWRK ),$ LLWORK, IINFO )CALL DSTEQR( JOBZ, N, W, WORK( INDE ), A, LDA, WORK( INDTAU ),$ INFO )END IF** If matrix was scaled, then rescale eigenvalues appropriately.*IF( ISCALE.EQ.1 ) THENIF( INFO.EQ.0 ) THENIMAX = NELSEIMAX = INFO - 1END IFCALL DSCAL( IMAX, ONE / SIGMA, W, 1 )END IF** Set WORK(1) to optimal workspace size.*WORK( 1 ) = LWKOPT*RETURN** End of DSYEV*ENDSUBROUTINE DSYEVD( JOBZ, UPLO, N, A, LDA, W, WORK, LWORK, IWORK,$ LIWORK, INFO )** -- LAPACK driver 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, UPLOINTEGER INFO, LDA, LIWORK, LWORK, N* ..* .. Array Arguments ..INTEGER IWORK( * )DOUBLE PRECISION A( LDA, * ), W( * ), WORK( * )* ..** Purpose* =======** DSYEVD computes all eigenvalues and, optionally, eigenvectors of a* real symmetric matrix A. If eigenvectors are desired, it uses a* divide and conquer algorithm.** The divide and conquer algorithm makes very mild assumptions about* floating point arithmetic. It will work on machines with a guard* digit in add/subtract, or on those binary machines without guard* digits which subtract like the Cray X-MP, Cray Y-MP, Cray C-90, or* Cray-2. It could conceivably fail on hexadecimal or decimal machines* without guard digits, but we know of none.** Because of large use of BLAS of level 3, DSYEVD needs N**2 more* workspace than DSYEVX.** Arguments* =========** JOBZ (input) CHARACTER*1* = 'N': Compute eigenvalues only;* = 'V': Compute eigenvalues and eigenvectors.** 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. If UPLO = 'L',* the leading N-by-N lower triangular part of A contains* the lower triangular part of the matrix A.* On exit, if JOBZ = 'V', then if INFO = 0, A contains the* orthonormal eigenvectors of the matrix A.* If JOBZ = 'N', then on exit the lower triangle (if UPLO='L')* or the upper triangle (if UPLO='U') of A, including the* diagonal, is destroyed.** LDA (input) INTEGER* The leading dimension of the array A. LDA >= max(1,N).** W (output) DOUBLE PRECISION array, dimension (N)* If INFO = 0, the eigenvalues in ascending order.** 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 N <= 1, LWORK must be at least 1.* If JOBZ = 'N' and N > 1, LWORK must be at least 2*N+1.* If JOBZ = 'V' and N > 1, LWORK must be at least* 1 + 6*N + 2*N**2.** 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.* If N <= 1, LIWORK must be at least 1.* If JOBZ = 'N' and N > 1, LIWORK must be at least 1.* If JOBZ = 'V' and N > 1, LIWORK must be at least 3 + 5*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 = i, the algorithm failed to converge; i* off-diagonal elements of an intermediate tridiagonal* form did not converge to zero.** Further Details* ===============** Based on contributions by* Jeff Rutter, Computer Science Division, University of California* at Berkeley, USA* Modified by Francoise Tisseur, University of Tennessee.** =====================================================================** .. Parameters ..DOUBLE PRECISION ZERO, ONEPARAMETER ( ZERO = 0.0D+0, ONE = 1.0D+0 )* ..* .. Local Scalars ..*LOGICAL LOWER, LQUERY, WANTZINTEGER IINFO, INDE, INDTAU, INDWK2, INDWRK, ISCALE,$ LIOPT, LIWMIN, LLWORK, LLWRK2, LOPT, LWMINDOUBLE PRECISION ANRM, BIGNUM, EPS, RMAX, RMIN, SAFMIN, SIGMA,$ SMLNUM* ..* .. External Functions ..LOGICAL LSAMEDOUBLE PRECISION DLAMCH, DLANSYEXTERNAL LSAME, DLAMCH, DLANSY* ..* .. External Subroutines ..EXTERNAL DLACPY, DLASCL, DORMTR, DSCAL, DSTEDC, DSTERF,$ DSYTRD, XERBLA* ..* .. Intrinsic Functions ..INTRINSIC MAX, SQRT* ..* .. Executable Statements ..** Test the input parameters.*WANTZ = LSAME( JOBZ, 'V' )LOWER = LSAME( UPLO, 'L' )LQUERY = ( LWORK.EQ.-1 .OR. LIWORK.EQ.-1 )*INFO = 0IF( N.LE.1 ) THENLIWMIN = 1LWMIN = 1LOPT = LWMINLIOPT = LIWMINELSEIF( WANTZ ) THENLIWMIN = 3 + 5*NLWMIN = 1 + 6*N + 2*N**2ELSELIWMIN = 1LWMIN = 2*N + 1END IFLOPT = LWMINLIOPT = LIWMINEND IFIF( .NOT.( WANTZ .OR. LSAME( JOBZ, 'N' ) ) ) THENINFO = -1ELSE IF( .NOT.( LOWER .OR. LSAME( UPLO, 'U' ) ) ) THENINFO = -2ELSE IF( N.LT.0 ) THENINFO = -3ELSE IF( LDA.LT.MAX( 1, N ) ) THENINFO = -5ELSE IF( LWORK.LT.LWMIN .AND. .NOT.LQUERY ) THENINFO = -8ELSE IF( LIWORK.LT.LIWMIN .AND. .NOT.LQUERY ) THENINFO = -10END IF*IF( INFO.EQ.0 ) THENWORK( 1 ) = LOPTIWORK( 1 ) = LIOPTEND IF*IF( INFO.NE.0 ) THENCALL XERBLA( 'DSYEVD', -INFO )RETURNELSE IF( LQUERY ) THENRETURNEND IF** Quick return if possible*IF( N.EQ.0 )$ RETURN*IF( N.EQ.1 ) THENW( 1 ) = A( 1, 1 )IF( WANTZ )$ A( 1, 1 ) = ONERETURNEND IF** Get machine constants.*SAFMIN = DLAMCH( 'Safe minimum' )EPS = DLAMCH( 'Precision' )SMLNUM = SAFMIN / EPSBIGNUM = ONE / SMLNUMRMIN = SQRT( SMLNUM )RMAX = SQRT( BIGNUM )** Scale matrix to allowable range, if necessary.*ANRM = DLANSY( 'M', UPLO, N, A, LDA, WORK )ISCALE = 0IF( ANRM.GT.ZERO .AND. ANRM.LT.RMIN ) THENISCALE = 1SIGMA = RMIN / ANRMELSE IF( ANRM.GT.RMAX ) THENISCALE = 1SIGMA = RMAX / ANRMEND IFIF( ISCALE.EQ.1 )$ CALL DLASCL( UPLO, 0, 0, ONE, SIGMA, N, N, A, LDA, INFO )** Call DSYTRD to reduce symmetric matrix to tridiagonal form.*INDE = 1INDTAU = INDE + NINDWRK = INDTAU + NLLWORK = LWORK - INDWRK + 1INDWK2 = INDWRK + N*NLLWRK2 = LWORK - INDWK2 + 1*CALL DSYTRD( UPLO, N, A, LDA, W, WORK( INDE ), WORK( INDTAU ),$ WORK( INDWRK ), LLWORK, IINFO )LOPT = 2*N + WORK( INDWRK )** For eigenvalues only, call DSTERF. For eigenvectors, first call* DSTEDC to generate the eigenvector matrix, WORK(INDWRK), of the* tridiagonal matrix, then call DORMTR to multiply it by the* Householder transformations stored in A.*IF( .NOT.WANTZ ) THENCALL DSTERF( N, W, WORK( INDE ), INFO )ELSECALL DSTEDC( 'I', N, W, WORK( INDE ), WORK( INDWRK ), N,$ WORK( INDWK2 ), LLWRK2, IWORK, LIWORK, INFO )CALL DORMTR( 'L', UPLO, 'N', N, N, A, LDA, WORK( INDTAU ),$ WORK( INDWRK ), N, WORK( INDWK2 ), LLWRK2, IINFO )CALL DLACPY( 'A', N, N, WORK( INDWRK ), N, A, LDA )LOPT = MAX( LOPT, 1+6*N+2*N**2 )END IF** If matrix was scaled, then rescale eigenvalues appropriately.*IF( ISCALE.EQ.1 )$ CALL DSCAL( N, ONE / SIGMA, W, 1 )*WORK( 1 ) = LOPTIWORK( 1 ) = LIOPT*RETURN** End of DSYEVD*ENDSUBROUTINE DSYEVR( JOBZ, RANGE, UPLO, N, A, LDA, VL, VU, IL, IU,$ ABSTOL, M, W, Z, LDZ, ISUPPZ, WORK, LWORK,$ IWORK, LIWORK, INFO )** -- LAPACK driver routine (version 3.0) --* Univ. of Tennessee, Univ. of California Berkeley, NAG Ltd.,* Courant Institute, Argonne National Lab, and Rice University* March 20, 2000** .. Scalar Arguments ..CHARACTER JOBZ, RANGE, UPLOINTEGER IL, INFO, IU, LDA, LDZ, LIWORK, LWORK, M, NDOUBLE PRECISION ABSTOL, VL, VU* ..* .. Array Arguments ..INTEGER ISUPPZ( * ), IWORK( * )DOUBLE PRECISION A( LDA, * ), W( * ), WORK( * ), Z( LDZ, * )* ..** Purpose* =======** DSYEVR computes selected eigenvalues and, optionally, eigenvectors* of a real symmetric matrix T. Eigenvalues and eigenvectors can be* selected by specifying either a range of values or a range of* indices for the desired eigenvalues.** Whenever possible, DSYEVR calls DSTEGR to compute the* eigenspectrum using Relatively Robust Representations. DSTEGR* computes eigenvalues by the dqds algorithm, while orthogonal* eigenvectors are computed from various "good" L D L^T representations* (also known as Relatively Robust Representations). Gram-Schmidt* orthogonalization is avoided as far as possible. More specifically,* the various steps of the algorithm are as follows. For 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 : DSYEVR calls DSTEGR when the full spectrum is requested* on machines which conform to the ieee-754 floating point standard.* DSYEVR calls DSTEBZ and SSTEIN on non-ieee machines and* when partial spectrum requests are made.** Normal execution of DSTEGR may create NaNs and infinities and* hence may abort due to a floating point exception in environments* which do not handle NaNs and infinities in the ieee standard default* manner.** 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.********** For RANGE = 'V' or 'I' and IU - IL < N - 1, DSTEBZ and********** DSTEIN are called** 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. If UPLO = 'L',* the leading N-by-N lower triangular part of A contains* the lower triangular part of the matrix A.* On exit, the lower triangle (if UPLO='L') or the upper* triangle (if UPLO='U') of A, including the diagonal, is* destroyed.** LDA (input) INTEGER* The leading dimension of the array A. LDA >= max(1,N).** VL (input) DOUBLE PRECISION* 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.* An approximate eigenvalue is accepted as converged* when it is determined to lie in an interval [a,b]* of width less than or equal to** ABSTOL + EPS * max( |a|,|b| ) ,** where EPS is the machine precision. If ABSTOL is less than* or equal to zero, then EPS*|T| will be used in its place,* where |T| is the 1-norm of the tridiagonal matrix obtained* by reducing A to tridiagonal form.** See "Computing Small Singular Values of Bidiagonal Matrices* with Guaranteed High Relative Accuracy," by Demmel and* Kahan, LAPACK Working Note #3.** If high relative accuracy is important, set ABSTOL to* DLAMCH( 'Safe minimum' ). Doing so will guarantee that* eigenvalues are computed to high relative accuracy when* possible in future releases. The current code does not* make any guarantees about high relative accuracy, but* furutre releases will. See J. Barlow and J. 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 A* corresponding to the selected eigenvalues, with the i-th* column of Z holding the eigenvector associated with W(i).* If JOBZ = 'N', then Z is not referenced.* Note: the user must ensure that at least max(1,M) columns are* supplied in the array Z; if RANGE = 'V', the exact value of M* is not known in advance and an upper bound must be used.** 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 ).********** Implemented only for RANGE = 'A' or 'I' and IU - IL = N - 1** 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,26*N).* For optimal efficiency, LWORK >= (NB+6)*N,* where NB is the max of the blocksize for DSYTRD and DORMTR* 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.** IWORK (workspace/output) INTEGER array, dimension (LIWORK)* On exit, if INFO = 0, IWORK(1) returns the optimal LWORK.** 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: Internal error** Further Details* ===============** Based on contributions by* Inderjit Dhillon, IBM Almaden, USA* Osni Marques, LBNL/NERSC, USA* Ken Stanley, Computer Science Division, University of* California at Berkeley, USA** =====================================================================** .. Parameters ..DOUBLE PRECISION ZERO, ONEPARAMETER ( ZERO = 0.0D+0, ONE = 1.0D+0 )* ..* .. Local Scalars ..LOGICAL ALLEIG, INDEIG, LOWER, LQUERY, VALEIG, WANTZCHARACTER ORDERINTEGER I, IEEEOK, IINFO, IMAX, INDD, INDDD, INDE,$ INDEE, INDIBL, INDIFL, INDISP, INDIWO, INDTAU,$ INDWK, INDWKN, ISCALE, ITMP1, J, JJ, LIWMIN,$ LLWORK, LLWRKN, LWKOPT, LWMIN, NB, NSPLITDOUBLE PRECISION ABSTLL, ANRM, BIGNUM, EPS, RMAX, RMIN, SAFMIN,$ SIGMA, SMLNUM, TMP1, VLL, VUU* ..* .. External Functions ..LOGICAL LSAMEINTEGER ILAENVDOUBLE PRECISION DLAMCH, DLANSYEXTERNAL LSAME, ILAENV, DLAMCH, DLANSY* ..* .. External Subroutines ..EXTERNAL DCOPY, DORMTR, DSCAL, DSTEBZ, DSTEGR, DSTEIN,$ DSTERF, DSWAP, DSYTRD, XERBLA* ..* .. Intrinsic Functions ..INTRINSIC MAX, MIN, SQRT* ..* .. Executable Statements ..** Test the input parameters.*IEEEOK = ILAENV( 10, 'DSYEVR', 'N', 1, 2, 3, 4 )*LOWER = LSAME( UPLO, 'L' )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 = MAX( 1, 26*N )LIWMIN = MAX( 1, 10*N )*INFO = 0IF( .NOT.( WANTZ .OR. LSAME( JOBZ, 'N' ) ) ) THENINFO = -1ELSE IF( .NOT.( ALLEIG .OR. VALEIG .OR. INDEIG ) ) THENINFO = -2ELSE IF( .NOT.( LOWER .OR. LSAME( UPLO, 'U' ) ) ) THENINFO = -3ELSE IF( N.LT.0 ) THENINFO = -4ELSE IF( LDA.LT.MAX( 1, N ) ) THENINFO = -6ELSEIF( VALEIG ) THENIF( N.GT.0 .AND. VU.LE.VL )$ INFO = -8ELSE IF( INDEIG ) THENIF( IL.LT.1 .OR. IL.GT.MAX( 1, N ) ) THENINFO = -9ELSE IF( IU.LT.MIN( N, IL ) .OR. IU.GT.N ) THENINFO = -10END IFEND IFEND IFIF( INFO.EQ.0 ) THENIF( LDZ.LT.1 .OR. ( WANTZ .AND. LDZ.LT.N ) ) THENINFO = -15ELSE IF( LWORK.LT.LWMIN .AND. .NOT.LQUERY ) THENINFO = -18ELSE IF( LIWORK.LT.LIWMIN .AND. .NOT.LQUERY ) THENINFO = -20END IFEND IF*IF( INFO.EQ.0 ) THENNB = ILAENV( 1, 'ZHETRD', UPLO, N, -1, -1, -1 )NB = MAX( NB, ILAENV( 1, 'ZUNMTR', UPLO, N, -1, -1, -1 ) )LWKOPT = MAX( ( NB+1 )*N, LWMIN )WORK( 1 ) = LWKOPTIWORK( 1 ) = LIWMINEND IF*IF( INFO.NE.0 ) THENCALL XERBLA( 'DSYEVR', -INFO )RETURNELSE IF( LQUERY ) THENRETURNEND IF** Quick return if possible*M = 0IF( N.EQ.0 ) THENWORK( 1 ) = 1RETURNEND IF*IF( N.EQ.1 ) THENWORK( 1 ) = 7IF( ALLEIG .OR. INDEIG ) THENM = 1W( 1 ) = A( 1, 1 )ELSEIF( VL.LT.A( 1, 1 ) .AND. VU.GE.A( 1, 1 ) ) THENM = 1W( 1 ) = A( 1, 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.*ISCALE = 0ABSTLL = ABSTOLVLL = VLVUU = VUANRM = DLANSY( 'M', UPLO, N, A, LDA, WORK )IF( ANRM.GT.ZERO .AND. ANRM.LT.RMIN ) THENISCALE = 1SIGMA = RMIN / ANRMELSE IF( ANRM.GT.RMAX ) THENISCALE = 1SIGMA = RMAX / ANRMEND IFIF( ISCALE.EQ.1 ) THENIF( LOWER ) THENDO 10 J = 1, NCALL DSCAL( N-J+1, SIGMA, A( J, J ), 1 )10 CONTINUEELSEDO 20 J = 1, NCALL DSCAL( J, SIGMA, A( 1, J ), 1 )20 CONTINUEEND IFIF( ABSTOL.GT.0 )$ ABSTLL = ABSTOL*SIGMAIF( VALEIG ) THENVLL = VL*SIGMAVUU = VU*SIGMAEND IFEND IF** Call DSYTRD to reduce symmetric matrix to tridiagonal form.*INDTAU = 1INDE = INDTAU + NINDD = INDE + NINDEE = INDD + NINDDD = INDEE + NINDIFL = INDDD + NINDWK = INDIFL + NLLWORK = LWORK - INDWK + 1CALL DSYTRD( UPLO, N, A, LDA, WORK( INDD ), WORK( INDE ),$ WORK( INDTAU ), WORK( INDWK ), LLWORK, IINFO )** If all eigenvalues are desired* then call DSTERF or SSTEGR and DORMTR.*IF( ( ALLEIG .OR. ( INDEIG .AND. IL.EQ.1 .AND. IU.EQ.N ) ) .AND.$ IEEEOK.EQ.1 ) THENIF( .NOT.WANTZ ) THENCALL DCOPY( N, WORK( INDD ), 1, W, 1 )CALL DCOPY( N-1, WORK( INDE ), 1, WORK( INDEE ), 1 )CALL DSTERF( N, W, WORK( INDEE ), INFO )ELSECALL DCOPY( N-1, WORK( INDE ), 1, WORK( INDEE ), 1 )CALL DCOPY( N, WORK( INDD ), 1, WORK( INDDD ), 1 )*CALL DSTEGR( JOBZ, 'A', N, WORK( INDDD ), WORK( INDEE ),$ VL, VU, IL, IU, ABSTOL, M, W, Z, LDZ, ISUPPZ,$ WORK( INDWK ), LWORK, IWORK, LIWORK, INFO )**** Apply orthogonal matrix used in reduction to tridiagonal* form to eigenvectors returned by DSTEIN.*IF( WANTZ .AND. INFO.EQ.0 ) THENINDWKN = INDELLWRKN = LWORK - INDWKN + 1CALL DORMTR( 'L', UPLO, 'N', N, M, A, LDA,$ WORK( INDTAU ), Z, LDZ, WORK( INDWKN ),$ LLWRKN, IINFO )END IFEND IF**IF( INFO.EQ.0 ) THENM = NGO TO 30END IFINFO = 0END IF** Otherwise, call DSTEBZ and, if eigenvectors are desired, SSTEIN.* Also call DSTEBZ and SSTEIN if SSTEGR fails.*IF( WANTZ ) THENORDER = 'B'ELSEORDER = 'E'END IFINDIFL = 1INDIBL = INDIFL + NINDISP = INDIBL + NINDIWO = INDISP + NCALL DSTEBZ( RANGE, ORDER, N, VLL, VUU, IL, IU, ABSTLL,$ WORK( INDD ), WORK( INDE ), M, NSPLIT, W,$ IWORK( INDIBL ), IWORK( INDISP ), WORK( INDWK ),$ IWORK( INDIWO ), INFO )*IF( WANTZ ) THENCALL DSTEIN( N, WORK( INDD ), WORK( INDE ), M, W,$ IWORK( INDIBL ), IWORK( INDISP ), Z, LDZ,$ WORK( INDWK ), IWORK( INDIWO ), IWORK( INDIFL ),$ INFO )** Apply orthogonal matrix used in reduction to tridiagonal* form to eigenvectors returned by DSTEIN.*INDWKN = INDELLWRKN = LWORK - INDWKN + 1CALL DORMTR( 'L', UPLO, 'N', N, M, A, LDA, WORK( INDTAU ), Z,$ LDZ, WORK( INDWKN ), LLWRKN, IINFO )END IF** If matrix was scaled, then rescale eigenvalues appropriately.*30 CONTINUEIF( ISCALE.EQ.1 ) THENIF( INFO.EQ.0 ) THENIMAX = MELSEIMAX = INFO - 1END IFCALL DSCAL( IMAX, ONE / SIGMA, W, 1 )END IF** If eigenvalues are not in order, then sort them, along with* eigenvectors.*IF( WANTZ ) THENDO 50 J = 1, M - 1I = 0TMP1 = W( J )DO 40 JJ = J + 1, MIF( W( JJ ).LT.TMP1 ) THENI = JJTMP1 = W( JJ )END IF40 CONTINUE*IF( I.NE.0 ) THENITMP1 = IWORK( INDIBL+I-1 )W( I ) = W( J )IWORK( INDIBL+I-1 ) = IWORK( INDIBL+J-1 )W( J ) = TMP1IWORK( INDIBL+J-1 ) = ITMP1CALL DSWAP( N, Z( 1, I ), 1, Z( 1, J ), 1 )END IF50 CONTINUEEND IF** Set WORK(1) to optimal workspace size.*WORK( 1 ) = LWKOPTIWORK( 1 ) = LIWMIN*RETURN** End of DSYEVR*ENDSUBROUTINE DSYEVX( JOBZ, RANGE, UPLO, N, A, LDA, VL, VU, IL, IU,$ ABSTOL, M, W, Z, LDZ, WORK, LWORK, IWORK,$ IFAIL, INFO )** -- LAPACK driver routine (version 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, RANGE, UPLOINTEGER IL, INFO, IU, LDA, LDZ, LWORK, M, NDOUBLE PRECISION ABSTOL, VL, VU* ..* .. Array Arguments ..INTEGER IFAIL( * ), IWORK( * )DOUBLE PRECISION A( LDA, * ), W( * ), WORK( * ), Z( LDZ, * )* ..** Purpose* =======** DSYEVX computes selected eigenvalues and, optionally, eigenvectors* of a real symmetric matrix A. Eigenvalues and eigenvectors can be* selected by specifying either a range of values or a range of indices* for the desired eigenvalues.** Arguments* =========** JOBZ (input) CHARACTER*1* = 'N': Compute eigenvalues only;* = 'V': Compute eigenvalues and eigenvectors.** RANGE (input) CHARACTER*1* = 'A': all eigenvalues will be found.* = 'V': all eigenvalues in the half-open interval (VL,VU]* will be found.* = 'I': the IL-th through IU-th eigenvalues will be found.** UPLO (input) CHARACTER*1* = 'U': Upper triangle of A is stored;* = 'L': Lower triangle of A is stored.** N (input) INTEGER* The order of the matrix A. N >= 0.** A (input/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. If UPLO = 'L',* the leading N-by-N lower triangular part of A contains* the lower triangular part of the matrix A.* On exit, the lower triangle (if UPLO='L') or the upper* triangle (if UPLO='U') of A, including the diagonal, is* destroyed.** LDA (input) INTEGER* The leading dimension of the array A. LDA >= max(1,N).** VL (input) DOUBLE PRECISION* 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.* An approximate eigenvalue is accepted as converged* when it is determined to lie in an interval [a,b]* of width less than or equal to** ABSTOL + EPS * max( |a|,|b| ) ,** where EPS is the machine precision. If ABSTOL is less than* or equal to zero, then EPS*|T| will be used in its place,* where |T| is the 1-norm of the tridiagonal matrix obtained* by reducing A to tridiagonal form.** Eigenvalues will be computed most accurately when ABSTOL is* set to twice the underflow threshold 2*DLAMCH('S'), not zero.* If this routine returns with INFO>0, indicating that some* eigenvectors did not converge, try setting ABSTOL to* 2*DLAMCH('S').** See "Computing Small Singular Values of Bidiagonal Matrices* with Guaranteed High Relative Accuracy," by Demmel and* Kahan, LAPACK Working Note #3.** M (output) INTEGER* The total number of eigenvalues found. 0 <= M <= N.* If RANGE = 'A', M = N, and if RANGE = 'I', M = IU-IL+1.** W (output) DOUBLE PRECISION array, dimension (N)* On normal exit, the first M 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 A* corresponding to the selected eigenvalues, with the i-th* column of Z holding the eigenvector associated with W(i).* If an eigenvector fails to converge, then that column of Z* contains the latest approximation to the eigenvector, and the* index of the eigenvector is returned in IFAIL.* If JOBZ = 'N', then Z is not referenced.* Note: the user must ensure that at least max(1,M) columns are* supplied in the array Z; if RANGE = 'V', the exact value of M* is not known in advance and an upper bound must be used.** LDZ (input) INTEGER* The leading dimension of the array Z. LDZ >= 1, and if* JOBZ = 'V', LDZ >= max(1,N).** WORK (workspace/output) DOUBLE PRECISION array, dimension (LWORK)* On exit, if INFO = 0, WORK(1) returns the optimal LWORK.** LWORK (input) INTEGER* The length of the array WORK. LWORK >= max(1,8*N).* For optimal efficiency, LWORK >= (NB+3)*N,* where NB is the max of the blocksize for DSYTRD and DORMTR* 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.** IWORK (workspace) INTEGER array, dimension (5*N)** IFAIL (output) INTEGER array, dimension (N)* If JOBZ = 'V', then if INFO = 0, the first M elements of* IFAIL are zero. If INFO > 0, then IFAIL contains the* indices of the eigenvectors that failed to converge.* If JOBZ = 'N', then IFAIL is not referenced.** INFO (output) INTEGER* = 0: successful exit* < 0: if INFO = -i, the i-th argument had an illegal value* > 0: if INFO = i, then i eigenvectors failed to converge.* Their indices are stored in array IFAIL.** =====================================================================** .. Parameters ..DOUBLE PRECISION ZERO, ONEPARAMETER ( ZERO = 0.0D+0, ONE = 1.0D+0 )* ..* .. Local Scalars ..LOGICAL ALLEIG, INDEIG, LOWER, LQUERY, VALEIG, WANTZCHARACTER ORDERINTEGER I, IINFO, IMAX, INDD, INDE, INDEE, INDIBL,$ INDISP, INDIWO, INDTAU, INDWKN, INDWRK, ISCALE,$ ITMP1, J, JJ, LLWORK, LLWRKN, LOPT, LWKOPT, NB,$ NSPLITDOUBLE PRECISION ABSTLL, ANRM, BIGNUM, EPS, RMAX, RMIN, SAFMIN,$ SIGMA, SMLNUM, TMP1, VLL, VUU* ..* .. External Functions ..LOGICAL LSAMEINTEGER ILAENVDOUBLE PRECISION DLAMCH, DLANSYEXTERNAL LSAME, ILAENV, DLAMCH, DLANSY* ..* .. External Subroutines ..EXTERNAL DCOPY, DLACPY, DORGTR, DORMTR, DSCAL, DSTEBZ,$ DSTEIN, DSTEQR, DSTERF, DSWAP, DSYTRD, XERBLA* ..* .. Intrinsic Functions ..INTRINSIC MAX, MIN, SQRT* ..* .. Executable Statements ..** Test the input parameters.*LOWER = LSAME( UPLO, 'L' )WANTZ = LSAME( JOBZ, 'V' )ALLEIG = LSAME( RANGE, 'A' )VALEIG = LSAME( RANGE, 'V' )INDEIG = LSAME( RANGE, 'I' )LQUERY = ( LWORK.EQ.-1 )*INFO = 0IF( .NOT.( WANTZ .OR. LSAME( JOBZ, 'N' ) ) ) THENINFO = -1ELSE IF( .NOT.( ALLEIG .OR. VALEIG .OR. INDEIG ) ) THENINFO = -2ELSE IF( .NOT.( LOWER .OR. LSAME( UPLO, 'U' ) ) ) THENINFO = -3ELSE IF( N.LT.0 ) THENINFO = -4ELSE IF( LDA.LT.MAX( 1, N ) ) THENINFO = -6ELSEIF( VALEIG ) THENIF( N.GT.0 .AND. VU.LE.VL )$ INFO = -8ELSE IF( INDEIG ) THENIF( IL.LT.1 .OR. IL.GT.MAX( 1, N ) ) THENINFO = -9ELSE IF( IU.LT.MIN( N, IL ) .OR. IU.GT.N ) THENINFO = -10END IFEND IFEND IFIF( INFO.EQ.0 ) THENIF( LDZ.LT.1 .OR. ( WANTZ .AND. LDZ.LT.N ) ) THENINFO = -15ELSE IF( LWORK.LT.MAX( 1, 8*N ) .AND. .NOT.LQUERY ) THENINFO = -17END IFEND IF*IF( INFO.EQ.0 ) THENNB = ILAENV( 1, 'DSYTRD', UPLO, N, -1, -1, -1 )NB = MAX( NB, ILAENV( 1, 'DORMTR', UPLO, N, -1, -1, -1 ) )LWKOPT = ( NB+3 )*NWORK( 1 ) = LWKOPTEND IF*IF( INFO.NE.0 ) THENCALL XERBLA( 'DSYEVX', -INFO )RETURNELSE IF( LQUERY ) THENRETURNEND IF** Quick return if possible*M = 0IF( N.EQ.0 ) THENWORK( 1 ) = 1RETURNEND IF*IF( N.EQ.1 ) THENWORK( 1 ) = 7IF( ALLEIG .OR. INDEIG ) THENM = 1W( 1 ) = A( 1, 1 )ELSEIF( VL.LT.A( 1, 1 ) .AND. VU.GE.A( 1, 1 ) ) THENM = 1W( 1 ) = A( 1, 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.*ISCALE = 0ABSTLL = ABSTOLVLL = VLVUU = VUANRM = DLANSY( 'M', UPLO, N, A, LDA, WORK )IF( ANRM.GT.ZERO .AND. ANRM.LT.RMIN ) THENISCALE = 1SIGMA = RMIN / ANRMELSE IF( ANRM.GT.RMAX ) THENISCALE = 1SIGMA = RMAX / ANRMEND IFIF( ISCALE.EQ.1 ) THENIF( LOWER ) THENDO 10 J = 1, NCALL DSCAL( N-J+1, SIGMA, A( J, J ), 1 )10 CONTINUEELSEDO 20 J = 1, NCALL DSCAL( J, SIGMA, A( 1, J ), 1 )20 CONTINUEEND IFIF( ABSTOL.GT.0 )$ ABSTLL = ABSTOL*SIGMAIF( VALEIG ) THENVLL = VL*SIGMAVUU = VU*SIGMAEND IFEND IF** Call DSYTRD to reduce symmetric matrix to tridiagonal form.*INDTAU = 1INDE = INDTAU + NINDD = INDE + NINDWRK = INDD + NLLWORK = LWORK - INDWRK + 1CALL DSYTRD( UPLO, N, A, LDA, WORK( INDD ), WORK( INDE ),$ WORK( INDTAU ), WORK( INDWRK ), LLWORK, IINFO )LOPT = 3*N + WORK( INDWRK )** If all eigenvalues are desired and ABSTOL is less than or equal to* zero, then call DSTERF or DORGTR and SSTEQR. If this fails for* some eigenvalue, then try DSTEBZ.*IF( ( ALLEIG .OR. ( INDEIG .AND. IL.EQ.1 .AND. IU.EQ.N ) ) .AND.$ ( ABSTOL.LE.ZERO ) ) THENCALL DCOPY( N, WORK( INDD ), 1, W, 1 )INDEE = INDWRK + 2*NIF( .NOT.WANTZ ) THENCALL DCOPY( N-1, WORK( INDE ), 1, WORK( INDEE ), 1 )CALL DSTERF( N, W, WORK( INDEE ), INFO )ELSECALL DLACPY( 'A', N, N, A, LDA, Z, LDZ )CALL DORGTR( UPLO, N, Z, LDZ, WORK( INDTAU ),$ WORK( INDWRK ), LLWORK, IINFO )CALL DCOPY( N-1, WORK( INDE ), 1, WORK( INDEE ), 1 )CALL DSTEQR( JOBZ, N, W, WORK( INDEE ), Z, LDZ,$ WORK( INDWRK ), INFO )IF( INFO.EQ.0 ) THENDO 30 I = 1, NIFAIL( I ) = 030 CONTINUEEND IFEND IFIF( INFO.EQ.0 ) THENM = NGO TO 40END IFINFO = 0END IF** Otherwise, call DSTEBZ and, if eigenvectors are desired, SSTEIN.*IF( WANTZ ) THENORDER = 'B'ELSEORDER = 'E'END IFINDIBL = 1INDISP = INDIBL + NINDIWO = INDISP + NCALL DSTEBZ( RANGE, ORDER, N, VLL, VUU, IL, IU, ABSTLL,$ WORK( INDD ), WORK( INDE ), M, NSPLIT, W,$ IWORK( INDIBL ), IWORK( INDISP ), WORK( INDWRK ),$ IWORK( INDIWO ), INFO )*IF( WANTZ ) THENCALL DSTEIN( N, WORK( INDD ), WORK( INDE ), M, W,$ IWORK( INDIBL ), IWORK( INDISP ), Z, LDZ,$ WORK( INDWRK ), IWORK( INDIWO ), IFAIL, INFO )** Apply orthogonal matrix used in reduction to tridiagonal* form to eigenvectors returned by DSTEIN.*INDWKN = INDELLWRKN = LWORK - INDWKN + 1CALL DORMTR( 'L', UPLO, 'N', N, M, A, LDA, WORK( INDTAU ), Z,$ LDZ, WORK( INDWKN ), LLWRKN, IINFO )END IF** If matrix was scaled, then rescale eigenvalues appropriately.*40 CONTINUEIF( ISCALE.EQ.1 ) THENIF( INFO.EQ.0 ) THENIMAX = MELSEIMAX = INFO - 1END IFCALL DSCAL( IMAX, ONE / SIGMA, W, 1 )END IF** If eigenvalues are not in order, then sort them, along with* eigenvectors.*IF( WANTZ ) THENDO 60 J = 1, M - 1I = 0TMP1 = W( J )DO 50 JJ = J + 1, MIF( W( JJ ).LT.TMP1 ) THENI = JJTMP1 = W( JJ )END IF50 CONTINUE*IF( I.NE.0 ) THENITMP1 = IWORK( INDIBL+I-1 )W( I ) = W( J )IWORK( INDIBL+I-1 ) = IWORK( INDIBL+J-1 )W( J ) = TMP1IWORK( INDIBL+J-1 ) = ITMP1CALL DSWAP( N, Z( 1, I ), 1, Z( 1, J ), 1 )IF( INFO.NE.0 ) THENITMP1 = IFAIL( I )IFAIL( I ) = IFAIL( J )IFAIL( J ) = ITMP1END IFEND IF60 CONTINUEEND IF** Set WORK(1) to optimal workspace size.*WORK( 1 ) = LWKOPT*RETURN** End of DSYEVX*ENDSUBROUTINE DSYGV( ITYPE, JOBZ, UPLO, N, A, LDA, B, LDB, W, WORK,$ LWORK, INFO )** -- LAPACK driver 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, UPLOINTEGER INFO, ITYPE, LDA, LDB, LWORK, N* ..* .. Array Arguments ..DOUBLE PRECISION A( LDA, * ), B( LDB, * ), W( * ), WORK( * )* ..** Purpose* =======** DSYGV computes all the eigenvalues, and optionally, the eigenvectors* of a real generalized symmetric-definite eigenproblem, of the form* A*x=(lambda)*B*x, A*Bx=(lambda)*x, or B*A*x=(lambda)*x.* Here A and B are assumed to be symmetric and B is also* positive definite.** Arguments* =========** ITYPE (input) INTEGER* Specifies the problem type to be solved:* = 1: A*x = (lambda)*B*x* = 2: A*B*x = (lambda)*x* = 3: B*A*x = (lambda)*x** JOBZ (input) CHARACTER*1* = 'N': Compute eigenvalues only;* = 'V': Compute eigenvalues and eigenvectors.** UPLO (input) CHARACTER*1* = 'U': Upper triangles of A and B are stored;* = 'L': Lower triangles of A and B are stored.** 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. If UPLO = 'L',* the leading N-by-N lower triangular part of A contains* the lower triangular part of the matrix A.** On exit, if JOBZ = 'V', then if INFO = 0, A contains the* matrix Z of eigenvectors. The eigenvectors are normalized* as follows:* if ITYPE = 1 or 2, Z**T*B*Z = I;* if ITYPE = 3, Z**T*inv(B)*Z = I.* If JOBZ = 'N', then on exit the upper triangle (if UPLO='U')* or the lower triangle (if UPLO='L') of A, including the* diagonal, is destroyed.** 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 symmetric positive definite matrix B.* If UPLO = 'U', the leading N-by-N upper triangular part of B* contains the upper triangular part of the matrix B.* If UPLO = 'L', the leading N-by-N lower triangular part of B* contains the lower triangular part of the matrix B.** On exit, if INFO <= N, the part of B containing the matrix is* overwritten by the triangular factor U or L from the Cholesky* factorization B = U**T*U or B = L*L**T.** LDB (input) INTEGER* The leading dimension of the array B. LDB >= max(1,N).** W (output) DOUBLE PRECISION array, dimension (N)* If INFO = 0, the eigenvalues in ascending order.** 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 the array WORK. LWORK >= max(1,3*N-1).* For optimal efficiency, LWORK >= (NB+2)*N,* where NB is the blocksize for DSYTRD 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: DPOTRF or DSYEV returned an error code:* <= N: if INFO = i, DSYEV failed to converge;* i off-diagonal elements of an intermediate* tridiagonal form did not converge to zero;* > N: if INFO = N + i, for 1 <= i <= N, then the leading* minor of order i of B is not positive definite.* The factorization of B could not be completed and* no eigenvalues or eigenvectors were computed.** =====================================================================** .. Parameters ..DOUBLE PRECISION ONEPARAMETER ( ONE = 1.0D+0 )* ..* .. Local Scalars ..LOGICAL LQUERY, UPPER, WANTZCHARACTER TRANSINTEGER LWKOPT, NB, NEIG* ..* .. External Functions ..LOGICAL LSAMEINTEGER ILAENVEXTERNAL LSAME, ILAENV* ..* .. External Subroutines ..EXTERNAL DPOTRF, DSYEV, DSYGST, DTRMM, DTRSM, XERBLA* ..* .. Intrinsic Functions ..INTRINSIC MAX* ..* .. Executable Statements ..** Test the input parameters.*WANTZ = LSAME( JOBZ, 'V' )UPPER = LSAME( UPLO, 'U' )LQUERY = ( LWORK.EQ.-1 )*INFO = 0IF( ITYPE.LT.1 .OR. ITYPE.GT.3 ) THENINFO = -1ELSE IF( .NOT.( WANTZ .OR. LSAME( JOBZ, 'N' ) ) ) THENINFO = -2ELSE IF( .NOT.( UPPER .OR. LSAME( UPLO, 'L' ) ) ) THENINFO = -3ELSE IF( N.LT.0 ) THENINFO = -4ELSE IF( LDA.LT.MAX( 1, N ) ) THENINFO = -6ELSE IF( LDB.LT.MAX( 1, N ) ) THENINFO = -8ELSE IF( LWORK.LT.MAX( 1, 3*N-1 ) .AND. .NOT.LQUERY ) THENINFO = -11END IF*IF( INFO.EQ.0 ) THENNB = ILAENV( 1, 'DSYTRD', UPLO, N, -1, -1, -1 )LWKOPT = ( NB+2 )*NWORK( 1 ) = LWKOPTEND IF*IF( INFO.NE.0 ) THENCALL XERBLA( 'DSYGV ', -INFO )RETURNELSE IF( LQUERY ) THENRETURNEND IF** Quick return if possible*IF( N.EQ.0 )$ RETURN** Form a Cholesky factorization of B.*CALL DPOTRF( UPLO, N, B, LDB, INFO )IF( INFO.NE.0 ) THENINFO = N + INFORETURNEND IF** Transform problem to standard eigenvalue problem and solve.*CALL DSYGST( ITYPE, UPLO, N, A, LDA, B, LDB, INFO )CALL DSYEV( JOBZ, UPLO, N, A, LDA, W, WORK, LWORK, INFO )*IF( WANTZ ) THEN** Backtransform eigenvectors to the original problem.*NEIG = NIF( INFO.GT.0 )$ NEIG = INFO - 1IF( ITYPE.EQ.1 .OR. ITYPE.EQ.2 ) THEN** For A*x=(lambda)*B*x and A*B*x=(lambda)*x;* backtransform eigenvectors: x = inv(L)'*y or inv(U)*y*IF( UPPER ) THENTRANS = 'N'ELSETRANS = 'T'END IF*CALL DTRSM( 'Left', UPLO, TRANS, 'Non-unit', N, NEIG, ONE,$ B, LDB, A, LDA )*ELSE IF( ITYPE.EQ.3 ) THEN** For B*A*x=(lambda)*x;* backtransform eigenvectors: x = L*y or U'*y*IF( UPPER ) THENTRANS = 'T'ELSETRANS = 'N'END IF*CALL DTRMM( 'Left', UPLO, TRANS, 'Non-unit', N, NEIG, ONE,$ B, LDB, A, LDA )END IFEND IF*WORK( 1 ) = LWKOPTRETURN** End of DSYGV*ENDSUBROUTINE DSYGVD( ITYPE, JOBZ, UPLO, N, A, LDA, B, LDB, W, WORK,$ LWORK, IWORK, LIWORK, INFO )** -- LAPACK driver 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, UPLOINTEGER INFO, ITYPE, LDA, LDB, LIWORK, LWORK, N* ..* .. Array Arguments ..INTEGER IWORK( * )DOUBLE PRECISION A( LDA, * ), B( LDB, * ), W( * ), WORK( * )* ..** Purpose* =======** DSYGVD computes all the eigenvalues, and optionally, the eigenvectors* of a real generalized symmetric-definite eigenproblem, of the form* A*x=(lambda)*B*x, A*Bx=(lambda)*x, or B*A*x=(lambda)*x. Here A and* B are assumed to be symmetric and B is also positive definite.* If eigenvectors are desired, it uses a divide and conquer algorithm.** The divide and conquer algorithm makes very mild assumptions about* floating point arithmetic. It will work on machines with a guard* digit in add/subtract, or on those binary machines without guard* digits which subtract like the Cray X-MP, Cray Y-MP, Cray C-90, or* Cray-2. It could conceivably fail on hexadecimal or decimal machines* without guard digits, but we know of none.** Arguments* =========** ITYPE (input) INTEGER* Specifies the problem type to be solved:* = 1: A*x = (lambda)*B*x* = 2: A*B*x = (lambda)*x* = 3: B*A*x = (lambda)*x** JOBZ (input) CHARACTER*1* = 'N': Compute eigenvalues only;* = 'V': Compute eigenvalues and eigenvectors.** UPLO (input) CHARACTER*1* = 'U': Upper triangles of A and B are stored;* = 'L': Lower triangles of A and B are stored.** 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. If UPLO = 'L',* the leading N-by-N lower triangular part of A contains* the lower triangular part of the matrix A.** On exit, if JOBZ = 'V', then if INFO = 0, A contains the* matrix Z of eigenvectors. The eigenvectors are normalized* as follows:* if ITYPE = 1 or 2, Z**T*B*Z = I;* if ITYPE = 3, Z**T*inv(B)*Z = I.* If JOBZ = 'N', then on exit the upper triangle (if UPLO='U')* or the lower triangle (if UPLO='L') of A, including the* diagonal, is destroyed.** 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 symmetric matrix B. If UPLO = 'U', the* leading N-by-N upper triangular part of B contains the* upper triangular part of the matrix B. If UPLO = 'L',* the leading N-by-N lower triangular part of B contains* the lower triangular part of the matrix B.** On exit, if INFO <= N, the part of B containing the matrix is* overwritten by the triangular factor U or L from the Cholesky* factorization B = U**T*U or B = L*L**T.** LDB (input) INTEGER* The leading dimension of the array B. LDB >= max(1,N).** W (output) DOUBLE PRECISION array, dimension (N)* If INFO = 0, the eigenvalues in ascending order.** 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 N <= 1, LWORK >= 1.* If JOBZ = 'N' and N > 1, LWORK >= 2*N+1.* If JOBZ = 'V' and N > 1, LWORK >= 1 + 6*N + 2*N**2.** 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.* If N <= 1, LIWORK >= 1.* If JOBZ = 'N' and N > 1, LIWORK >= 1.* If JOBZ = 'V' and N > 1, LIWORK >= 3 + 5*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: DPOTRF or DSYEVD returned an error code:* <= N: if INFO = i, DSYEVD failed to converge;* i off-diagonal elements of an intermediate* tridiagonal form did not converge to zero;* > N: if INFO = N + i, for 1 <= i <= N, then the leading* minor of order i of B is not positive definite.* The factorization of B could not be completed and* no eigenvalues or eigenvectors were computed.** Further Details* ===============** Based on contributions by* Mark Fahey, Department of Mathematics, Univ. of Kentucky, USA** =====================================================================** .. Parameters ..DOUBLE PRECISION ONEPARAMETER ( ONE = 1.0D+0 )* ..* .. Local Scalars ..LOGICAL LQUERY, UPPER, WANTZCHARACTER TRANSINTEGER LIOPT, LIWMIN, LOPT, LWMIN, NEIG* ..* .. External Functions ..LOGICAL LSAMEEXTERNAL LSAME* ..* .. External Subroutines ..EXTERNAL DPOTRF, DSYEVD, DSYGST, DTRMM, DTRSM, XERBLA* ..* .. Intrinsic Functions ..INTRINSIC DBLE, MAX* ..* .. Executable Statements ..** Test the input parameters.*WANTZ = LSAME( JOBZ, 'V' )UPPER = LSAME( UPLO, 'U' )LQUERY = ( LWORK.EQ.-1 .OR. LIWORK.EQ.-1 )*INFO = 0IF( N.LE.1 ) THENLIWMIN = 1LWMIN = 1LOPT = LWMINLIOPT = LIWMINELSEIF( WANTZ ) THENLIWMIN = 3 + 5*NLWMIN = 1 + 6*N + 2*N**2ELSELIWMIN = 1LWMIN = 2*N + 1END IFLOPT = LWMINLIOPT = LIWMINEND IFIF( ITYPE.LT.0 .OR. ITYPE.GT.3 ) THENINFO = -1ELSE IF( .NOT.( WANTZ .OR. LSAME( JOBZ, 'N' ) ) ) THENINFO = -2ELSE IF( .NOT.( UPPER .OR. LSAME( UPLO, 'L' ) ) ) THENINFO = -3ELSE IF( N.LT.0 ) THENINFO = -4ELSE IF( LDA.LT.MAX( 1, N ) ) THENINFO = -6ELSE IF( LDB.LT.MAX( 1, N ) ) THENINFO = -8ELSE IF( LWORK.LT.LWMIN .AND. .NOT.LQUERY ) THENINFO = -11ELSE IF( LIWORK.LT.LIWMIN .AND. .NOT.LQUERY ) THENINFO = -13END IF*IF( INFO.EQ.0 ) THENWORK( 1 ) = LOPTIWORK( 1 ) = LIOPTEND IF*IF( INFO.NE.0 ) THENCALL XERBLA( 'DSYGVD', -INFO )RETURNELSE IF( LQUERY ) THENRETURNEND IF** Quick return if possible*IF( N.EQ.0 )$ RETURN** Form a Cholesky factorization of B.*CALL DPOTRF( UPLO, N, B, LDB, INFO )IF( INFO.NE.0 ) THENINFO = N + INFORETURNEND IF** Transform problem to standard eigenvalue problem and solve.*CALL DSYGST( ITYPE, UPLO, N, A, LDA, B, LDB, INFO )CALL DSYEVD( JOBZ, UPLO, N, A, LDA, W, WORK, LWORK, IWORK, LIWORK,$ INFO )LOPT = MAX( DBLE( LOPT ), DBLE( WORK( 1 ) ) )LIOPT = MAX( DBLE( LIOPT ), DBLE( IWORK( 1 ) ) )*IF( WANTZ ) THEN** Backtransform eigenvectors to the original problem.*NEIG = NIF( INFO.GT.0 )$ NEIG = INFO - 1IF( ITYPE.EQ.1 .OR. ITYPE.EQ.2 ) THEN** For A*x=(lambda)*B*x and A*B*x=(lambda)*x;* backtransform eigenvectors: x = inv(L)'*y or inv(U)*y*IF( UPPER ) THENTRANS = 'N'ELSETRANS = 'T'END IF*CALL DTRSM( 'Left', UPLO, TRANS, 'Non-unit', N, NEIG, ONE,$ B, LDB, A, LDA )*ELSE IF( ITYPE.EQ.3 ) THEN** For B*A*x=(lambda)*x;* backtransform eigenvectors: x = L*y or U'*y*IF( UPPER ) THENTRANS = 'T'ELSETRANS = 'N'END IF*CALL DTRMM( 'Left', UPLO, TRANS, 'Non-unit', N, NEIG, ONE,$ B, LDB, A, LDA )END IFEND IF*WORK( 1 ) = LOPTIWORK( 1 ) = LIOPT*RETURN** End of DSYGVD*ENDSUBROUTINE DSYGVX( ITYPE, JOBZ, RANGE, UPLO, N, A, LDA, B, LDB,$ VL, VU, IL, IU, ABSTOL, M, W, Z, LDZ, WORK,$ LWORK, IWORK, IFAIL, INFO )** -- LAPACK driver 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, RANGE, UPLOINTEGER IL, INFO, ITYPE, IU, LDA, LDB, LDZ, LWORK, M, NDOUBLE PRECISION ABSTOL, VL, VU* ..* .. Array Arguments ..INTEGER IFAIL( * ), IWORK( * )DOUBLE PRECISION A( LDA, * ), B( LDB, * ), W( * ), WORK( * ),$ Z( LDZ, * )* ..** Purpose* =======** DSYGVX computes selected eigenvalues, and optionally, eigenvectors* of a real generalized symmetric-definite eigenproblem, of the form* A*x=(lambda)*B*x, A*Bx=(lambda)*x, or B*A*x=(lambda)*x. Here A* and B are assumed to be symmetric and B is also positive definite.* Eigenvalues and eigenvectors can be selected by specifying either a* range of values or a range of indices for the desired eigenvalues.** Arguments* =========** ITYPE (input) INTEGER* Specifies the problem type to be solved:* = 1: A*x = (lambda)*B*x* = 2: A*B*x = (lambda)*x* = 3: B*A*x = (lambda)*x** JOBZ (input) CHARACTER*1* = 'N': Compute eigenvalues only;* = 'V': Compute eigenvalues and eigenvectors.** RANGE (input) CHARACTER*1* = 'A': all eigenvalues will be found.* = 'V': all eigenvalues in the half-open interval (VL,VU]* will be found.* = 'I': the IL-th through IU-th eigenvalues will be found.** UPLO (input) CHARACTER*1* = 'U': Upper triangle of A and B are stored;* = 'L': Lower triangle of A and B are stored.** N (input) INTEGER* The order of the matrix pencil (A,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. If UPLO = 'L',* the leading N-by-N lower triangular part of A contains* the lower triangular part of the matrix A.** On exit, the lower triangle (if UPLO='L') or the upper* triangle (if UPLO='U') of A, including the diagonal, is* destroyed.** LDA (input) INTEGER* The leading dimension of the array A. LDA >= max(1,N).** B (input/output) DOUBLE PRECISION array, dimension (LDA, N)* On entry, the symmetric matrix B. If UPLO = 'U', the* leading N-by-N upper triangular part of B contains the* upper triangular part of the matrix B. If UPLO = 'L',* the leading N-by-N lower triangular part of B contains* the lower triangular part of the matrix B.** On exit, if INFO <= N, the part of B containing the matrix is* overwritten by the triangular factor U or L from the Cholesky* factorization B = U**T*U or B = L*L**T.** LDB (input) INTEGER* The leading dimension of the array B. LDB >= max(1,N).** 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.* An approximate eigenvalue is accepted as converged* when it is determined to lie in an interval [a,b]* of width less than or equal to** ABSTOL + EPS * max( |a|,|b| ) ,** where EPS is the machine precision. If ABSTOL is less than* or equal to zero, then EPS*|T| will be used in its place,* where |T| is the 1-norm of the tridiagonal matrix obtained* by reducing A to tridiagonal form.** Eigenvalues will be computed most accurately when ABSTOL is* set to twice the underflow threshold 2*DLAMCH('S'), not zero.* If this routine returns with INFO>0, indicating that some* eigenvectors did not converge, try setting ABSTOL to* 2*DLAMCH('S').** M (output) INTEGER* The total number of eigenvalues found. 0 <= M <= N.* If RANGE = 'A', M = N, and if RANGE = 'I', M = IU-IL+1.** W (output) DOUBLE PRECISION array, dimension (N)* On normal exit, the first M elements contain the selected* eigenvalues in ascending order.** Z (output) DOUBLE PRECISION array, dimension (LDZ, max(1,M))* If JOBZ = 'N', then Z is not referenced.* If JOBZ = 'V', then if INFO = 0, the first M columns of Z* contain the orthonormal eigenvectors of the matrix A* corresponding to the selected eigenvalues, with the i-th* column of Z holding the eigenvector associated with W(i).* The eigenvectors are normalized as follows:* if ITYPE = 1 or 2, Z**T*B*Z = I;* if ITYPE = 3, Z**T*inv(B)*Z = I.** If an eigenvector fails to converge, then that column of Z* contains the latest approximation to the eigenvector, and the* index of the eigenvector is returned in IFAIL.* Note: the user must ensure that at least max(1,M) columns are* supplied in the array Z; if RANGE = 'V', the exact value of M* is not known in advance and an upper bound must be used.** LDZ (input) INTEGER* The leading dimension of the array Z. LDZ >= 1, and if* JOBZ = 'V', LDZ >= max(1,N).** 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 the array WORK. LWORK >= max(1,8*N).* For optimal efficiency, LWORK >= (NB+3)*N,* where NB is the blocksize for DSYTRD returned by ILAENV.** 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 (5*N)** IFAIL (output) INTEGER array, dimension (N)* If JOBZ = 'V', then if INFO = 0, the first M elements of* IFAIL are zero. If INFO > 0, then IFAIL contains the* indices of the eigenvectors that failed to converge.* If JOBZ = 'N', then IFAIL is not referenced.** INFO (output) INTEGER* = 0: successful exit* < 0: if INFO = -i, the i-th argument had an illegal value* > 0: DPOTRF or DSYEVX returned an error code:* <= N: if INFO = i, DSYEVX failed to converge;* i eigenvectors failed to converge. Their indices* are stored in array IFAIL.* > N: if INFO = N + i, for 1 <= i <= N, then the leading* minor of order i of B is not positive definite.* The factorization of B could not be completed and* no eigenvalues or eigenvectors were computed.** Further Details* ===============** Based on contributions by* Mark Fahey, Department of Mathematics, Univ. of Kentucky, USA** =====================================================================** .. Parameters ..DOUBLE PRECISION ONEPARAMETER ( ONE = 1.0D+0 )* ..* .. Local Scalars ..LOGICAL ALLEIG, INDEIG, LQUERY, UPPER, VALEIG, WANTZCHARACTER TRANSINTEGER LOPT, LWKOPT, NB* ..* .. External Functions ..LOGICAL LSAMEINTEGER ILAENVEXTERNAL LSAME, ILAENV* ..* .. External Subroutines ..EXTERNAL DPOTRF, DSYEVX, DSYGST, DTRMM, DTRSM, XERBLA* ..* .. Intrinsic Functions ..INTRINSIC MAX, MIN* ..* .. Executable Statements ..** Test the input parameters.*UPPER = LSAME( UPLO, 'U' )WANTZ = LSAME( JOBZ, 'V' )ALLEIG = LSAME( RANGE, 'A' )VALEIG = LSAME( RANGE, 'V' )INDEIG = LSAME( RANGE, 'I' )LQUERY = ( LWORK.EQ.-1 )*INFO = 0IF( ITYPE.LT.0 .OR. ITYPE.GT.3 ) THENINFO = -1ELSE IF( .NOT.( WANTZ .OR. LSAME( JOBZ, 'N' ) ) ) THENINFO = -2ELSE IF( .NOT.( ALLEIG .OR. VALEIG .OR. INDEIG ) ) THENINFO = -3ELSE IF( .NOT.( UPPER .OR. LSAME( UPLO, 'L' ) ) ) THENINFO = -4ELSE IF( N.LT.0 ) THENINFO = -5ELSE IF( LDA.LT.MAX( 1, N ) ) THENINFO = -7ELSE IF( LDB.LT.MAX( 1, N ) ) THENINFO = -9ELSE IF( VALEIG .AND. N.GT.0 ) THENIF( VU.LE.VL )$ INFO = -11ELSE IF( INDEIG .AND. IL.LT.1 ) THENINFO = -12ELSE IF( INDEIG .AND. ( IU.LT.MIN( N, IL ) .OR. IU.GT.N ) ) THENINFO = -13ELSE IF( LDZ.LT.1 .OR. ( WANTZ .AND. LDZ.LT.N ) ) THENINFO = -18ELSE IF( LWORK.LT.MAX( 1, 8*N ) .AND. .NOT.LQUERY ) THENINFO = -20END IF*IF( INFO.EQ.0 ) THENNB = ILAENV( 1, 'DSYTRD', UPLO, N, -1, -1, -1 )LWKOPT = ( NB+3 )*NWORK( 1 ) = LWKOPTEND IF*IF( INFO.NE.0 ) THENCALL XERBLA( 'DSYGVX', -INFO )RETURNELSE IF( LQUERY ) THENRETURNEND IF** Quick return if possible*M = 0IF( N.EQ.0 ) THENWORK( 1 ) = 1RETURNEND IF** Form a Cholesky factorization of B.*CALL DPOTRF( UPLO, N, B, LDB, INFO )IF( INFO.NE.0 ) THENINFO = N + INFORETURNEND IF** Transform problem to standard eigenvalue problem and solve.*CALL DSYGST( ITYPE, UPLO, N, A, LDA, B, LDB, INFO )CALL DSYEVX( JOBZ, RANGE, UPLO, N, A, LDA, VL, VU, IL, IU, ABSTOL,$ M, W, Z, LDZ, WORK, LWORK, IWORK, IFAIL, INFO )LOPT = WORK( 1 )*IF( WANTZ ) THEN** Backtransform eigenvectors to the original problem.*IF( INFO.GT.0 )$ M = INFO - 1IF( ITYPE.EQ.1 .OR. ITYPE.EQ.2 ) THEN** For A*x=(lambda)*B*x and A*B*x=(lambda)*x;* backtransform eigenvectors: x = inv(L)'*y or inv(U)*y*IF( UPPER ) THENTRANS = 'N'ELSETRANS = 'T'END IF*CALL DTRSM( 'Left', UPLO, TRANS, 'Non-unit', N, M, ONE, B,$ LDB, Z, LDZ )*ELSE IF( ITYPE.EQ.3 ) THEN** For B*A*x=(lambda)*x;* backtransform eigenvectors: x = L*y or U'*y*IF( UPPER ) THENTRANS = 'T'ELSETRANS = 'N'END IF*CALL DTRMM( 'Left', UPLO, TRANS, 'Non-unit', N, M, ONE, B,$ LDB, Z, LDZ )END IFEND IF** Set WORK(1) to optimal workspace size.*WORK( 1 ) = LWKOPT*RETURN** End of DSYGVX*ENDSUBROUTINE DSYSV( UPLO, N, NRHS, A, LDA, IPIV, B, LDB, WORK,$ LWORK, INFO )** -- LAPACK driver 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, LDB, LWORK, N, NRHS* ..* .. Array Arguments ..INTEGER IPIV( * )DOUBLE PRECISION A( LDA, * ), B( LDB, * ), WORK( * )* ..** Purpose* =======** DSYSV computes the solution to a real system of linear equations* A * X = B,* where A is an N-by-N symmetric matrix and X and B are N-by-NRHS* matrices.** The diagonal pivoting method is used to factor A as* A = U * D * U**T, if UPLO = 'U', or* A = L * D * L**T, if UPLO = 'L',* 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. The factored form of A is then* used to solve the system of equations A * X = B.** Arguments* =========** UPLO (input) CHARACTER*1* = 'U': Upper triangle of A is stored;* = 'L': Lower triangle of A is stored.** N (input) INTEGER* The number of linear equations, i.e., the order of the* matrix A. N >= 0.** NRHS (input) INTEGER* The number of right hand sides, i.e., the number of columns* of the matrix B. NRHS >= 0.** A (input/output) DOUBLE PRECISION array, dimension (LDA,N)* On entry, the 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 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.** 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, as* determined by DSYTRF. 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.** 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).** 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, and for best performance* LWORK >= N*NB, where NB is the optimal blocksize for* DSYTRF.** 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, so the solution could not be computed.** =====================================================================** .. Local Scalars ..LOGICAL LQUERYINTEGER LWKOPT, NB* ..* .. External Functions ..LOGICAL LSAMEINTEGER ILAENVEXTERNAL LSAME, ILAENV* ..* .. External Subroutines ..EXTERNAL DSYTRF, DSYTRS, XERBLA* ..* .. Intrinsic Functions ..INTRINSIC MAX* ..* .. Executable Statements ..** Test the input parameters.*INFO = 0LQUERY = ( LWORK.EQ.-1 )IF( .NOT.LSAME( UPLO, 'U' ) .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 = -8ELSE IF( LWORK.LT.1 .AND. .NOT.LQUERY ) THENINFO = -10END IF*IF( INFO.EQ.0 ) THENNB = ILAENV( 1, 'DSYTRF', UPLO, N, -1, -1, -1 )LWKOPT = N*NBWORK( 1 ) = LWKOPTEND IF*IF( INFO.NE.0 ) THENCALL XERBLA( 'DSYSV ', -INFO )RETURNELSE IF( LQUERY ) THENRETURNEND IF** Compute the factorization A = U*D*U' or A = L*D*L'.*CALL DSYTRF( UPLO, N, A, LDA, IPIV, WORK, LWORK, INFO )IF( INFO.EQ.0 ) THEN** Solve the system A*X = B, overwriting B with X.*CALL DSYTRS( UPLO, N, NRHS, A, LDA, IPIV, B, LDB, INFO )*END IF*WORK( 1 ) = LWKOPT*RETURN** End of DSYSV*ENDSUBROUTINE DSYSVX( FACT, UPLO, N, NRHS, A, LDA, AF, LDAF, IPIV, B,$ LDB, X, LDX, RCOND, FERR, BERR, WORK, LWORK,$ IWORK, INFO )** -- LAPACK driver 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 FACT, UPLOINTEGER INFO, LDA, LDAF, LDB, LDX, LWORK, N, NRHSDOUBLE PRECISION RCOND* ..* .. Array Arguments ..INTEGER IPIV( * ), IWORK( * )DOUBLE PRECISION A( LDA, * ), AF( LDAF, * ), B( LDB, * ),$ BERR( * ), FERR( * ), WORK( * ), X( LDX, * )* ..** Purpose* =======** DSYSVX uses the diagonal pivoting factorization to compute the* solution to a real system of linear equations A * X = B,* where A is an N-by-N symmetric 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 diagonal pivoting method is used to factor A.* The form of the factorization is* A = U * D * U**T, if UPLO = 'U', or* A = L * D * L**T, if UPLO = 'L',* 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.** 2. If some D(i,i)=0, so that D is exactly singular, 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, AF and IPIV contain the factored form of* A. AF and IPIV will not be modified.* = 'N': The matrix A will be copied to AF and factored.** UPLO (input) CHARACTER*1* = 'U': Upper triangle of A is stored;* = 'L': Lower triangle of A is stored.** N (input) INTEGER* The number of linear equations, i.e., the order of the* matrix A. N >= 0.** NRHS (input) INTEGER* The number of right hand sides, i.e., the number of columns* of the 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 or output) DOUBLE PRECISION array, dimension (LDAF,N)* If FACT = 'F', then AF is an input argument and on entry* 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.** If FACT = 'N', then AF is an output argument and on exit* returns 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.** LDAF (input) INTEGER* The leading dimension of the array AF. LDAF >= max(1,N).** IPIV (input or output) INTEGER array, dimension (N)* If FACT = 'F', then IPIV is an input argument and on entry* contains details of the interchanges and the block structure* of D, as determined by DSYTRF.* 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.** If FACT = 'N', then IPIV is an output argument and on exit* contains details of the interchanges and the block structure* of D, as determined by DSYTRF.** 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 or 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 estimate of 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 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/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 >= 3*N, and for best performance* LWORK >= N*NB, where NB is the optimal blocksize for* DSYTRF.** 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)** 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: D(i,i) is exactly zero. The factorization* has been completed but the factor D is exactly* singular, so the solution and error bounds could* not be computed. RCOND = 0 is returned.* = N+1: D 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 LQUERY, NOFACTINTEGER LWKOPT, NBDOUBLE PRECISION ANORM* ..* .. External Functions ..LOGICAL LSAMEINTEGER ILAENVDOUBLE PRECISION DLAMCH, DLANSYEXTERNAL LSAME, ILAENV, DLAMCH, DLANSY* ..* .. External Subroutines ..EXTERNAL DLACPY, DSYCON, DSYRFS, DSYTRF, DSYTRS, XERBLA* ..* .. Intrinsic Functions ..INTRINSIC MAX* ..* .. Executable Statements ..** Test the input parameters.*INFO = 0NOFACT = LSAME( FACT, 'N' )LQUERY = ( LWORK.EQ.-1 )IF( .NOT.NOFACT .AND. .NOT.LSAME( FACT, 'F' ) ) THENINFO = -1ELSE IF( .NOT.LSAME( UPLO, 'U' ) .AND. .NOT.LSAME( UPLO, 'L' ) )$ THENINFO = -2ELSE IF( N.LT.0 ) THENINFO = -3ELSE IF( NRHS.LT.0 ) THENINFO = -4ELSE IF( LDA.LT.MAX( 1, N ) ) THENINFO = -6ELSE IF( LDAF.LT.MAX( 1, N ) ) THENINFO = -8ELSE IF( LDB.LT.MAX( 1, N ) ) THENINFO = -11ELSE IF( LDX.LT.MAX( 1, N ) ) THENINFO = -13ELSE IF( LWORK.LT.MAX( 1, 3*N ) .AND. .NOT.LQUERY ) THENINFO = -18END IF*IF( INFO.EQ.0 ) THENNB = ILAENV( 1, 'DSYTRF', UPLO, N, -1, -1, -1 )LWKOPT = N*NBWORK( 1 ) = LWKOPTEND IF*IF( INFO.NE.0 ) THENCALL XERBLA( 'DSYSVX', -INFO )RETURNELSE IF( LQUERY ) THENRETURNEND IF*IF( NOFACT ) THEN** Compute the factorization A = U*D*U' or A = L*D*L'.*CALL DLACPY( UPLO, N, N, A, LDA, AF, LDAF )CALL DSYTRF( UPLO, N, AF, LDAF, IPIV, WORK, LWORK, 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 = DLANSY( 'I', UPLO, N, A, LDA, WORK )** Compute the reciprocal of the condition number of A.*CALL DSYCON( UPLO, N, AF, LDAF, IPIV, ANORM, RCOND, WORK, IWORK,$ 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 DSYTRS( UPLO, N, NRHS, AF, LDAF, IPIV, X, LDX, INFO )** Use iterative refinement to improve the computed solutions and* compute error bounds and backward error estimates for them.*CALL DSYRFS( UPLO, N, NRHS, A, LDA, AF, LDAF, IPIV, B, LDB, X,$ LDX, FERR, BERR, WORK, IWORK, INFO )*RETURN** End of DSYSVX*END