Rev 17290 | Blame | Compare with Previous | Last modification | View Log | Download | RSS feed
SUBROUTINE DBDSQR( UPLO, N, NCVT, NRU, NCC, D, E, VT, LDVT, U,$ LDU, C, LDC, WORK, INFO )** -- LAPACK routine (version 3.0) --* Univ. of Tennessee, Univ. of California Berkeley, NAG Ltd.,* Courant Institute, Argonne National Lab, and Rice University* June 30, 1999** .. Scalar Arguments ..CHARACTER UPLOINTEGER INFO, LDC, LDU, LDVT, N, NCC, NCVT, NRU* ..* .. Array Arguments ..DOUBLE PRECISION C( LDC, * ), D( * ), E( * ), U( LDU, * ),$ VT( LDVT, * ), WORK( * )* ..** Purpose* =======** DBDSQR computes the singular value decomposition (SVD) of a real* N-by-N (upper or lower) bidiagonal matrix B: B = Q * S * P' (P'* denotes the transpose of P), where S is a diagonal matrix with* non-negative diagonal elements (the singular values of B), and Q* and P are orthogonal matrices.** The routine computes S, and optionally computes U * Q, P' * VT,* or Q' * C, for given real input matrices U, VT, and C.** See "Computing Small Singular Values of Bidiagonal Matrices With* Guaranteed High Relative Accuracy," by J. Demmel and W. Kahan,* LAPACK Working Note #3 (or SIAM J. Sci. Statist. Comput. vol. 11,* no. 5, pp. 873-912, Sept 1990) and* "Accurate singular values and differential qd algorithms," by* B. Parlett and V. Fernando, Technical Report CPAM-554, Mathematics* Department, University of California at Berkeley, July 1992* for a detailed description of the algorithm.** Arguments* =========** UPLO (input) CHARACTER*1* = 'U': B is upper bidiagonal;* = 'L': B is lower bidiagonal.** N (input) INTEGER* The order of the matrix B. N >= 0.** NCVT (input) INTEGER* The number of columns of the matrix VT. NCVT >= 0.** NRU (input) INTEGER* The number of rows of the matrix U. NRU >= 0.** NCC (input) INTEGER* The number of columns of the matrix C. NCC >= 0.** D (input/output) DOUBLE PRECISION array, dimension (N)* On entry, the n diagonal elements of the bidiagonal matrix B.* On exit, if INFO=0, the singular values of B in decreasing* order.** E (input/output) DOUBLE PRECISION array, dimension (N)* On entry, the elements of E contain the* offdiagonal elements of the bidiagonal matrix whose SVD* is desired. On normal exit (INFO = 0), E is destroyed.* If the algorithm does not converge (INFO > 0), D and E* will contain the diagonal and superdiagonal elements of a* bidiagonal matrix orthogonally equivalent to the one given* as input. E(N) is used for workspace.** VT (input/output) DOUBLE PRECISION array, dimension (LDVT, NCVT)* On entry, an N-by-NCVT matrix VT.* On exit, VT is overwritten by P' * VT.* VT is not referenced if NCVT = 0.** LDVT (input) INTEGER* The leading dimension of the array VT.* LDVT >= max(1,N) if NCVT > 0; LDVT >= 1 if NCVT = 0.** U (input/output) DOUBLE PRECISION array, dimension (LDU, N)* On entry, an NRU-by-N matrix U.* On exit, U is overwritten by U * Q.* U is not referenced if NRU = 0.** LDU (input) INTEGER* The leading dimension of the array U. LDU >= max(1,NRU).** C (input/output) DOUBLE PRECISION array, dimension (LDC, NCC)* On entry, an N-by-NCC matrix C.* On exit, C is overwritten by Q' * C.* C is not referenced if NCC = 0.** LDC (input) INTEGER* The leading dimension of the array C.* LDC >= max(1,N) if NCC > 0; LDC >=1 if NCC = 0.** WORK (workspace) DOUBLE PRECISION array, dimension* 4*N if only singular values wanted (NCVT = NRU = NCC = 0)* max( 1, 4*N-4 ) otherwise** INFO (output) INTEGER* = 0: successful exit* < 0: If INFO = -i, the i-th argument had an illegal value* > 0: the algorithm did not converge; D and E contain the* elements of a bidiagonal matrix which is orthogonally* similar to the input matrix B; if INFO = i, i* elements of E have not converged to zero.** Internal Parameters* ===================** TOLMUL DOUBLE PRECISION, default = max(10,min(100,EPS**(-1/8)))* TOLMUL controls the convergence criterion of the QR loop.* If it is positive, TOLMUL*EPS is the desired relative* precision in the computed singular values.* If it is negative, abs(TOLMUL*EPS*sigma_max) is the* desired absolute accuracy in the computed singular* values (corresponds to relative accuracy* abs(TOLMUL*EPS) in the largest singular value.* abs(TOLMUL) should be between 1 and 1/EPS, and preferably* between 10 (for fast convergence) and .1/EPS* (for there to be some accuracy in the results).* Default is to lose at either one eighth or 2 of the* available decimal digits in each computed singular value* (whichever is smaller).** MAXITR INTEGER, default = 6* MAXITR controls the maximum number of passes of the* algorithm through its inner loop. The algorithms stops* (and so fails to converge) if the number of passes* through the inner loop exceeds MAXITR*N**2.** =====================================================================** .. Parameters ..DOUBLE PRECISION ZEROPARAMETER ( ZERO = 0.0D0 )DOUBLE PRECISION ONEPARAMETER ( ONE = 1.0D0 )DOUBLE PRECISION NEGONEPARAMETER ( NEGONE = -1.0D0 )DOUBLE PRECISION HNDRTHPARAMETER ( HNDRTH = 0.01D0 )DOUBLE PRECISION TENPARAMETER ( TEN = 10.0D0 )DOUBLE PRECISION HNDRDPARAMETER ( HNDRD = 100.0D0 )DOUBLE PRECISION MEIGTHPARAMETER ( MEIGTH = -0.125D0 )INTEGER MAXITRPARAMETER ( MAXITR = 6 )* ..* .. Local Scalars ..LOGICAL LOWER, ROTATEINTEGER I, IDIR, ISUB, ITER, J, LL, LLL, M, MAXIT, NM1,$ NM12, NM13, OLDLL, OLDMDOUBLE PRECISION ABSE, ABSS, COSL, COSR, CS, EPS, F, G, H, MU,$ OLDCS, OLDSN, R, SHIFT, SIGMN, SIGMX, SINL,$ SINR, SLL, SMAX, SMIN, SMINL, SMINLO, SMINOA,$ SN, THRESH, TOL, TOLMUL, UNFL* ..* .. External Functions ..LOGICAL LSAMEDOUBLE PRECISION DLAMCHEXTERNAL LSAME, DLAMCH* ..* .. External Subroutines ..EXTERNAL DLARTG, DLAS2, DLASQ1, DLASR, DLASV2, DROT,$ DSCAL, DSWAP, XERBLA* ..* .. Intrinsic Functions ..INTRINSIC ABS, DBLE, MAX, MIN, SIGN, SQRT* ..* .. Executable Statements ..** Test the input parameters.*INFO = 0LOWER = LSAME( UPLO, 'L' )IF( .NOT.LSAME( UPLO, 'U' ) .AND. .NOT.LOWER ) THENINFO = -1ELSE IF( N.LT.0 ) THENINFO = -2ELSE IF( NCVT.LT.0 ) THENINFO = -3ELSE IF( NRU.LT.0 ) THENINFO = -4ELSE IF( NCC.LT.0 ) THENINFO = -5ELSE IF( ( NCVT.EQ.0 .AND. LDVT.LT.1 ) .OR.$ ( NCVT.GT.0 .AND. LDVT.LT.MAX( 1, N ) ) ) THENINFO = -9ELSE IF( LDU.LT.MAX( 1, NRU ) ) THENINFO = -11ELSE IF( ( NCC.EQ.0 .AND. LDC.LT.1 ) .OR.$ ( NCC.GT.0 .AND. LDC.LT.MAX( 1, N ) ) ) THENINFO = -13END IFIF( INFO.NE.0 ) THENCALL XERBLA( 'DBDSQR', -INFO )RETURNEND IFIF( N.EQ.0 )$ RETURNIF( N.EQ.1 )$ GO TO 160** ROTATE is true if any singular vectors desired, false otherwise*ROTATE = ( NCVT.GT.0 ) .OR. ( NRU.GT.0 ) .OR. ( NCC.GT.0 )** If no singular vectors desired, use qd algorithm*IF( .NOT.ROTATE ) THENCALL DLASQ1( N, D, E, WORK, INFO )RETURNEND IF*NM1 = N - 1NM12 = NM1 + NM1NM13 = NM12 + NM1IDIR = 0** Get machine constants*EPS = DLAMCH( 'Epsilon' )UNFL = DLAMCH( 'Safe minimum' )** If matrix lower bidiagonal, rotate to be upper bidiagonal* by applying Givens rotations on the left*IF( LOWER ) THENDO 10 I = 1, N - 1CALL DLARTG( D( I ), E( I ), CS, SN, R )D( I ) = RE( I ) = SN*D( I+1 )D( I+1 ) = CS*D( I+1 )WORK( I ) = CSWORK( NM1+I ) = SN10 CONTINUE** Update singular vectors if desired*IF( NRU.GT.0 )$ CALL DLASR( 'R', 'V', 'F', NRU, N, WORK( 1 ), WORK( N ), U,$ LDU )IF( NCC.GT.0 )$ CALL DLASR( 'L', 'V', 'F', N, NCC, WORK( 1 ), WORK( N ), C,$ LDC )END IF** Compute singular values to relative accuracy TOL* (By setting TOL to be negative, algorithm will compute* singular values to absolute accuracy ABS(TOL)*norm(input matrix))*TOLMUL = MAX( TEN, MIN( HNDRD, EPS**MEIGTH ) )TOL = TOLMUL*EPS** Compute approximate maximum, minimum singular values*SMAX = ZERODO 20 I = 1, NSMAX = MAX( SMAX, ABS( D( I ) ) )20 CONTINUEDO 30 I = 1, N - 1SMAX = MAX( SMAX, ABS( E( I ) ) )30 CONTINUESMINL = ZEROIF( TOL.GE.ZERO ) THEN** Relative accuracy desired*SMINOA = ABS( D( 1 ) )IF( SMINOA.EQ.ZERO )$ GO TO 50MU = SMINOADO 40 I = 2, NMU = ABS( D( I ) )*( MU / ( MU+ABS( E( I-1 ) ) ) )SMINOA = MIN( SMINOA, MU )IF( SMINOA.EQ.ZERO )$ GO TO 5040 CONTINUE50 CONTINUESMINOA = SMINOA / SQRT( DBLE( N ) )THRESH = MAX( TOL*SMINOA, MAXITR*N*N*UNFL )ELSE** Absolute accuracy desired*THRESH = MAX( ABS( TOL )*SMAX, MAXITR*N*N*UNFL )END IF** Prepare for main iteration loop for the singular values* (MAXIT is the maximum number of passes through the inner* loop permitted before nonconvergence signalled.)*MAXIT = MAXITR*N*NITER = 0OLDLL = -1OLDM = -1** M points to last element of unconverged part of matrix*M = N** Begin main iteration loop*60 CONTINUE** Check for convergence or exceeding iteration count*IF( M.LE.1 )$ GO TO 160IF( ITER.GT.MAXIT )$ GO TO 200** Find diagonal block of matrix to work on*IF( TOL.LT.ZERO .AND. ABS( D( M ) ).LE.THRESH )$ D( M ) = ZEROSMAX = ABS( D( M ) )SMIN = SMAXDO 70 LLL = 1, M - 1LL = M - LLLABSS = ABS( D( LL ) )ABSE = ABS( E( LL ) )IF( TOL.LT.ZERO .AND. ABSS.LE.THRESH )$ D( LL ) = ZEROIF( ABSE.LE.THRESH )$ GO TO 80SMIN = MIN( SMIN, ABSS )SMAX = MAX( SMAX, ABSS, ABSE )70 CONTINUELL = 0GO TO 9080 CONTINUEE( LL ) = ZERO** Matrix splits since E(LL) = 0*IF( LL.EQ.M-1 ) THEN** Convergence of bottom singular value, return to top of loop*M = M - 1GO TO 60END IF90 CONTINUELL = LL + 1** E(LL) through E(M-1) are nonzero, E(LL-1) is zero*IF( LL.EQ.M-1 ) THEN** 2 by 2 block, handle separately*CALL DLASV2( D( M-1 ), E( M-1 ), D( M ), SIGMN, SIGMX, SINR,$ COSR, SINL, COSL )D( M-1 ) = SIGMXE( M-1 ) = ZEROD( M ) = SIGMN** Compute singular vectors, if desired*IF( NCVT.GT.0 )$ CALL DROT( NCVT, VT( M-1, 1 ), LDVT, VT( M, 1 ), LDVT, COSR,$ SINR )IF( NRU.GT.0 )$ CALL DROT( NRU, U( 1, M-1 ), 1, U( 1, M ), 1, COSL, SINL )IF( NCC.GT.0 )$ CALL DROT( NCC, C( M-1, 1 ), LDC, C( M, 1 ), LDC, COSL,$ SINL )M = M - 2GO TO 60END IF** If working on new submatrix, choose shift direction* (from larger end diagonal element towards smaller)*IF( LL.GT.OLDM .OR. M.LT.OLDLL ) THENIF( ABS( D( LL ) ).GE.ABS( D( M ) ) ) THEN** Chase bulge from top (big end) to bottom (small end)*IDIR = 1ELSE** Chase bulge from bottom (big end) to top (small end)*IDIR = 2END IFEND IF** Apply convergence tests*IF( IDIR.EQ.1 ) THEN** Run convergence test in forward direction* First apply standard test to bottom of matrix*IF( ABS( E( M-1 ) ).LE.ABS( TOL )*ABS( D( M ) ) .OR.$ ( TOL.LT.ZERO .AND. ABS( E( M-1 ) ).LE.THRESH ) ) THENE( M-1 ) = ZEROGO TO 60END IF*IF( TOL.GE.ZERO ) THEN** If relative accuracy desired,* apply convergence criterion forward*MU = ABS( D( LL ) )SMINL = MUDO 100 LLL = LL, M - 1IF( ABS( E( LLL ) ).LE.TOL*MU ) THENE( LLL ) = ZEROGO TO 60END IFSMINLO = SMINLMU = ABS( D( LLL+1 ) )*( MU / ( MU+ABS( E( LLL ) ) ) )SMINL = MIN( SMINL, MU )100 CONTINUEEND IF*ELSE** Run convergence test in backward direction* First apply standard test to top of matrix*IF( ABS( E( LL ) ).LE.ABS( TOL )*ABS( D( LL ) ) .OR.$ ( TOL.LT.ZERO .AND. ABS( E( LL ) ).LE.THRESH ) ) THENE( LL ) = ZEROGO TO 60END IF*IF( TOL.GE.ZERO ) THEN** If relative accuracy desired,* apply convergence criterion backward*MU = ABS( D( M ) )SMINL = MUDO 110 LLL = M - 1, LL, -1IF( ABS( E( LLL ) ).LE.TOL*MU ) THENE( LLL ) = ZEROGO TO 60END IFSMINLO = SMINLMU = ABS( D( LLL ) )*( MU / ( MU+ABS( E( LLL ) ) ) )SMINL = MIN( SMINL, MU )110 CONTINUEEND IFEND IFOLDLL = LLOLDM = M** Compute shift. First, test if shifting would ruin relative* accuracy, and if so set the shift to zero.*IF( TOL.GE.ZERO .AND. N*TOL*( SMINL / SMAX ).LE.$ MAX( EPS, HNDRTH*TOL ) ) THEN** Use a zero shift to avoid loss of relative accuracy*SHIFT = ZEROELSE** Compute the shift from 2-by-2 block at end of matrix*IF( IDIR.EQ.1 ) THENSLL = ABS( D( LL ) )CALL DLAS2( D( M-1 ), E( M-1 ), D( M ), SHIFT, R )ELSESLL = ABS( D( M ) )CALL DLAS2( D( LL ), E( LL ), D( LL+1 ), SHIFT, R )END IF** Test if shift negligible, and if so set to zero*IF( SLL.GT.ZERO ) THENIF( ( SHIFT / SLL )**2.LT.EPS )$ SHIFT = ZEROEND IFEND IF** Increment iteration count*ITER = ITER + M - LL** If SHIFT = 0, do simplified QR iteration*IF( SHIFT.EQ.ZERO ) THENIF( IDIR.EQ.1 ) THEN** Chase bulge from top to bottom* Save cosines and sines for later singular vector updates*CS = ONEOLDCS = ONEDO 120 I = LL, M - 1CALL DLARTG( D( I )*CS, E( I ), CS, SN, R )IF( I.GT.LL )$ E( I-1 ) = OLDSN*RCALL DLARTG( OLDCS*R, D( I+1 )*SN, OLDCS, OLDSN, D( I ) )WORK( I-LL+1 ) = CSWORK( I-LL+1+NM1 ) = SNWORK( I-LL+1+NM12 ) = OLDCSWORK( I-LL+1+NM13 ) = OLDSN120 CONTINUEH = D( M )*CSD( M ) = H*OLDCSE( M-1 ) = H*OLDSN** Update singular vectors*IF( NCVT.GT.0 )$ CALL DLASR( 'L', 'V', 'F', M-LL+1, NCVT, WORK( 1 ),$ WORK( N ), VT( LL, 1 ), LDVT )IF( NRU.GT.0 )$ CALL DLASR( 'R', 'V', 'F', NRU, M-LL+1, WORK( NM12+1 ),$ WORK( NM13+1 ), U( 1, LL ), LDU )IF( NCC.GT.0 )$ CALL DLASR( 'L', 'V', 'F', M-LL+1, NCC, WORK( NM12+1 ),$ WORK( NM13+1 ), C( LL, 1 ), LDC )** Test convergence*IF( ABS( E( M-1 ) ).LE.THRESH )$ E( M-1 ) = ZERO*ELSE** Chase bulge from bottom to top* Save cosines and sines for later singular vector updates*CS = ONEOLDCS = ONEDO 130 I = M, LL + 1, -1CALL DLARTG( D( I )*CS, E( I-1 ), CS, SN, R )IF( I.LT.M )$ E( I ) = OLDSN*RCALL DLARTG( OLDCS*R, D( I-1 )*SN, OLDCS, OLDSN, D( I ) )WORK( I-LL ) = CSWORK( I-LL+NM1 ) = -SNWORK( I-LL+NM12 ) = OLDCSWORK( I-LL+NM13 ) = -OLDSN130 CONTINUEH = D( LL )*CSD( LL ) = H*OLDCSE( LL ) = H*OLDSN** Update singular vectors*IF( NCVT.GT.0 )$ CALL DLASR( 'L', 'V', 'B', M-LL+1, NCVT, WORK( NM12+1 ),$ WORK( NM13+1 ), VT( LL, 1 ), LDVT )IF( NRU.GT.0 )$ CALL DLASR( 'R', 'V', 'B', NRU, M-LL+1, WORK( 1 ),$ WORK( N ), U( 1, LL ), LDU )IF( NCC.GT.0 )$ CALL DLASR( 'L', 'V', 'B', M-LL+1, NCC, WORK( 1 ),$ WORK( N ), C( LL, 1 ), LDC )** Test convergence*IF( ABS( E( LL ) ).LE.THRESH )$ E( LL ) = ZEROEND IFELSE** Use nonzero shift*IF( IDIR.EQ.1 ) THEN** Chase bulge from top to bottom* Save cosines and sines for later singular vector updates*F = ( ABS( D( LL ) )-SHIFT )*$ ( SIGN( ONE, D( LL ) )+SHIFT / D( LL ) )G = E( LL )DO 140 I = LL, M - 1CALL DLARTG( F, G, COSR, SINR, R )IF( I.GT.LL )$ E( I-1 ) = RF = COSR*D( I ) + SINR*E( I )E( I ) = COSR*E( I ) - SINR*D( I )G = SINR*D( I+1 )D( I+1 ) = COSR*D( I+1 )CALL DLARTG( F, G, COSL, SINL, R )D( I ) = RF = COSL*E( I ) + SINL*D( I+1 )D( I+1 ) = COSL*D( I+1 ) - SINL*E( I )IF( I.LT.M-1 ) THENG = SINL*E( I+1 )E( I+1 ) = COSL*E( I+1 )END IFWORK( I-LL+1 ) = COSRWORK( I-LL+1+NM1 ) = SINRWORK( I-LL+1+NM12 ) = COSLWORK( I-LL+1+NM13 ) = SINL140 CONTINUEE( M-1 ) = F** Update singular vectors*IF( NCVT.GT.0 )$ CALL DLASR( 'L', 'V', 'F', M-LL+1, NCVT, WORK( 1 ),$ WORK( N ), VT( LL, 1 ), LDVT )IF( NRU.GT.0 )$ CALL DLASR( 'R', 'V', 'F', NRU, M-LL+1, WORK( NM12+1 ),$ WORK( NM13+1 ), U( 1, LL ), LDU )IF( NCC.GT.0 )$ CALL DLASR( 'L', 'V', 'F', M-LL+1, NCC, WORK( NM12+1 ),$ WORK( NM13+1 ), C( LL, 1 ), LDC )** Test convergence*IF( ABS( E( M-1 ) ).LE.THRESH )$ E( M-1 ) = ZERO*ELSE** Chase bulge from bottom to top* Save cosines and sines for later singular vector updates*F = ( ABS( D( M ) )-SHIFT )*( SIGN( ONE, D( M ) )+SHIFT /$ D( M ) )G = E( M-1 )DO 150 I = M, LL + 1, -1CALL DLARTG( F, G, COSR, SINR, R )IF( I.LT.M )$ E( I ) = RF = COSR*D( I ) + SINR*E( I-1 )E( I-1 ) = COSR*E( I-1 ) - SINR*D( I )G = SINR*D( I-1 )D( I-1 ) = COSR*D( I-1 )CALL DLARTG( F, G, COSL, SINL, R )D( I ) = RF = COSL*E( I-1 ) + SINL*D( I-1 )D( I-1 ) = COSL*D( I-1 ) - SINL*E( I-1 )IF( I.GT.LL+1 ) THENG = SINL*E( I-2 )E( I-2 ) = COSL*E( I-2 )END IFWORK( I-LL ) = COSRWORK( I-LL+NM1 ) = -SINRWORK( I-LL+NM12 ) = COSLWORK( I-LL+NM13 ) = -SINL150 CONTINUEE( LL ) = F** Test convergence*IF( ABS( E( LL ) ).LE.THRESH )$ E( LL ) = ZERO** Update singular vectors if desired*IF( NCVT.GT.0 )$ CALL DLASR( 'L', 'V', 'B', M-LL+1, NCVT, WORK( NM12+1 ),$ WORK( NM13+1 ), VT( LL, 1 ), LDVT )IF( NRU.GT.0 )$ CALL DLASR( 'R', 'V', 'B', NRU, M-LL+1, WORK( 1 ),$ WORK( N ), U( 1, LL ), LDU )IF( NCC.GT.0 )$ CALL DLASR( 'L', 'V', 'B', M-LL+1, NCC, WORK( 1 ),$ WORK( N ), C( LL, 1 ), LDC )END IFEND IF** QR iteration finished, go back and check convergence*GO TO 60** All singular values converged, so make them positive*160 CONTINUEDO 170 I = 1, NIF( D( I ).LT.ZERO ) THEND( I ) = -D( I )** Change sign of singular vectors, if desired*IF( NCVT.GT.0 )$ CALL DSCAL( NCVT, NEGONE, VT( I, 1 ), LDVT )END IF170 CONTINUE** Sort the singular values into decreasing order (insertion sort on* singular values, but only one transposition per singular vector)*DO 190 I = 1, N - 1** Scan for smallest D(I)*ISUB = 1SMIN = D( 1 )DO 180 J = 2, N + 1 - IIF( D( J ).LE.SMIN ) THENISUB = JSMIN = D( J )END IF180 CONTINUEIF( ISUB.NE.N+1-I ) THEN** Swap singular values and vectors*D( ISUB ) = D( N+1-I )D( N+1-I ) = SMINIF( NCVT.GT.0 )$ CALL DSWAP( NCVT, VT( ISUB, 1 ), LDVT, VT( N+1-I, 1 ),$ LDVT )IF( NRU.GT.0 )$ CALL DSWAP( NRU, U( 1, ISUB ), 1, U( 1, N+1-I ), 1 )IF( NCC.GT.0 )$ CALL DSWAP( NCC, C( ISUB, 1 ), LDC, C( N+1-I, 1 ), LDC )END IF190 CONTINUEGO TO 220** Maximum number of iterations exceeded, failure to converge*200 CONTINUEINFO = 0DO 210 I = 1, N - 1IF( E( I ).NE.ZERO )$ INFO = INFO + 1210 CONTINUE220 CONTINUERETURN** End of DBDSQR*ENDSUBROUTINE DGEBAK( JOB, SIDE, N, ILO, IHI, SCALE, M, V, LDV,$ INFO )** -- LAPACK routine (version 3.0) --* Univ. of Tennessee, Univ. of California Berkeley, NAG Ltd.,* Courant Institute, Argonne National Lab, and Rice University* September 30, 1994** .. Scalar Arguments ..CHARACTER JOB, SIDEINTEGER IHI, ILO, INFO, LDV, M, N* ..* .. Array Arguments ..DOUBLE PRECISION SCALE( * ), V( LDV, * )* ..** Purpose* =======** DGEBAK forms the right or left eigenvectors of a real general matrix* by backward transformation on the computed eigenvectors of the* balanced matrix output by DGEBAL.** Arguments* =========** JOB (input) CHARACTER*1* Specifies the type of backward transformation required:* = 'N', do nothing, return immediately;* = 'P', do backward transformation for permutation only;* = 'S', do backward transformation for scaling only;* = 'B', do backward transformations for both permutation and* scaling.* JOB must be the same as the argument JOB supplied to DGEBAL.** SIDE (input) CHARACTER*1* = 'R': V contains right eigenvectors;* = 'L': V contains left eigenvectors.** N (input) INTEGER* The number of rows of the matrix V. N >= 0.** ILO (input) INTEGER* IHI (input) INTEGER* The integers ILO and IHI determined by DGEBAL.* 1 <= ILO <= IHI <= N, if N > 0; ILO=1 and IHI=0, if N=0.** SCALE (input) DOUBLE PRECISION array, dimension (N)* Details of the permutation and scaling factors, as returned* by DGEBAL.** M (input) INTEGER* The number of columns of the matrix V. M >= 0.** V (input/output) DOUBLE PRECISION array, dimension (LDV,M)* On entry, the matrix of right or left eigenvectors to be* transformed, as returned by DHSEIN or DTREVC.* On exit, V is overwritten by the transformed eigenvectors.** LDV (input) INTEGER* The leading dimension of the array V. LDV >= max(1,N).** INFO (output) INTEGER* = 0: successful exit* < 0: if INFO = -i, the i-th argument had an illegal value.** =====================================================================** .. Parameters ..DOUBLE PRECISION ONEPARAMETER ( ONE = 1.0D+0 )* ..* .. Local Scalars ..LOGICAL LEFTV, RIGHTVINTEGER I, II, KDOUBLE PRECISION S* ..* .. External Functions ..LOGICAL LSAMEEXTERNAL LSAME* ..* .. External Subroutines ..EXTERNAL DSCAL, DSWAP, XERBLA* ..* .. Intrinsic Functions ..INTRINSIC MAX, MIN* ..* .. Executable Statements ..** Decode and Test the input parameters*RIGHTV = LSAME( SIDE, 'R' )LEFTV = LSAME( SIDE, 'L' )*INFO = 0IF( .NOT.LSAME( JOB, 'N' ) .AND. .NOT.LSAME( JOB, 'P' ) .AND.$ .NOT.LSAME( JOB, 'S' ) .AND. .NOT.LSAME( JOB, 'B' ) ) THENINFO = -1ELSE IF( .NOT.RIGHTV .AND. .NOT.LEFTV ) THENINFO = -2ELSE IF( N.LT.0 ) THENINFO = -3ELSE IF( ILO.LT.1 .OR. ILO.GT.MAX( 1, N ) ) THENINFO = -4ELSE IF( IHI.LT.MIN( ILO, N ) .OR. IHI.GT.N ) THENINFO = -5ELSE IF( M.LT.0 ) THENINFO = -7ELSE IF( LDV.LT.MAX( 1, N ) ) THENINFO = -9END IFIF( INFO.NE.0 ) THENCALL XERBLA( 'DGEBAK', -INFO )RETURNEND IF** Quick return if possible*IF( N.EQ.0 )$ RETURNIF( M.EQ.0 )$ RETURNIF( LSAME( JOB, 'N' ) )$ RETURN*IF( ILO.EQ.IHI )$ GO TO 30** Backward balance*IF( LSAME( JOB, 'S' ) .OR. LSAME( JOB, 'B' ) ) THEN*IF( RIGHTV ) THENDO 10 I = ILO, IHIS = SCALE( I )CALL DSCAL( M, S, V( I, 1 ), LDV )10 CONTINUEEND IF*IF( LEFTV ) THENDO 20 I = ILO, IHIS = ONE / SCALE( I )CALL DSCAL( M, S, V( I, 1 ), LDV )20 CONTINUEEND IF*END IF** Backward permutation** For I = ILO-1 step -1 until 1,* IHI+1 step 1 until N do --*30 CONTINUEIF( LSAME( JOB, 'P' ) .OR. LSAME( JOB, 'B' ) ) THENIF( RIGHTV ) THENDO 40 II = 1, NI = IIIF( I.GE.ILO .AND. I.LE.IHI )$ GO TO 40IF( I.LT.ILO )$ I = ILO - IIK = SCALE( I )IF( K.EQ.I )$ GO TO 40CALL DSWAP( M, V( I, 1 ), LDV, V( K, 1 ), LDV )40 CONTINUEEND IF*IF( LEFTV ) THENDO 50 II = 1, NI = IIIF( I.GE.ILO .AND. I.LE.IHI )$ GO TO 50IF( I.LT.ILO )$ I = ILO - IIK = SCALE( I )IF( K.EQ.I )$ GO TO 50CALL DSWAP( M, V( I, 1 ), LDV, V( K, 1 ), LDV )50 CONTINUEEND IFEND IF*RETURN** End of DGEBAK*ENDSUBROUTINE DGEBAL( JOB, N, A, LDA, ILO, IHI, SCALE, INFO )** -- LAPACK routine (version 3.0) --* Univ. of Tennessee, Univ. of California Berkeley, NAG Ltd.,* Courant Institute, Argonne National Lab, and Rice University* June 30, 1999** .. Scalar Arguments ..CHARACTER JOBINTEGER IHI, ILO, INFO, LDA, N* ..* .. Array Arguments ..DOUBLE PRECISION A( LDA, * ), SCALE( * )* ..** Purpose* =======** DGEBAL balances a general real matrix A. This involves, first,* permuting A by a similarity transformation to isolate eigenvalues* in the first 1 to ILO-1 and last IHI+1 to N elements on the* diagonal; and second, applying a diagonal similarity transformation* to rows and columns ILO to IHI to make the rows and columns as* close in norm as possible. Both steps are optional.** Balancing may reduce the 1-norm of the matrix, and improve the* accuracy of the computed eigenvalues and/or eigenvectors.** Arguments* =========** JOB (input) CHARACTER*1* Specifies the operations to be performed on A:* = 'N': none: simply set ILO = 1, IHI = N, SCALE(I) = 1.0* for i = 1,...,N;* = 'P': permute only;* = 'S': scale only;* = 'B': both permute and scale.** N (input) INTEGER* The order of the matrix A. N >= 0.** A (input/output) DOUBLE PRECISION array, dimension (LDA,N)* On entry, the input matrix A.* On exit, A is overwritten by the balanced matrix.* If JOB = 'N', A is not referenced.* See Further Details.** LDA (input) INTEGER* The leading dimension of the array A. LDA >= max(1,N).** ILO (output) INTEGER* IHI (output) INTEGER* ILO and IHI are set to integers such that on exit* A(i,j) = 0 if i > j and j = 1,...,ILO-1 or I = IHI+1,...,N.* If JOB = 'N' or 'S', ILO = 1 and IHI = N.** SCALE (output) DOUBLE PRECISION array, dimension (N)* Details of the permutations and scaling factors applied to* 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.** INFO (output) INTEGER* = 0: successful exit.* < 0: if INFO = -i, the i-th argument had an illegal value.** Further Details* ===============** The permutations consist of row and column interchanges which put* the matrix in the form** ( T1 X Y )* P A P = ( 0 B Z )* ( 0 0 T2 )** where T1 and T2 are upper triangular matrices whose eigenvalues lie* along the diagonal. The column indices ILO and IHI mark the starting* and ending columns of the submatrix B. Balancing consists of applying* a diagonal similarity transformation inv(D) * B * D to make the* 1-norms of each row of B and its corresponding column nearly equal.* The output matrix is** ( T1 X*D Y )* ( 0 inv(D)*B*D inv(D)*Z ).* ( 0 0 T2 )** Information about the permutations P and the diagonal matrix D is* returned in the vector SCALE.** This subroutine is based on the EISPACK routine BALANC.** Modified by Tzu-Yi Chen, Computer Science Division, University of* California at Berkeley, USA** =====================================================================** .. Parameters ..DOUBLE PRECISION ZERO, ONEPARAMETER ( ZERO = 0.0D+0, ONE = 1.0D+0 )DOUBLE PRECISION SCLFACPARAMETER ( SCLFAC = 0.8D+1 )DOUBLE PRECISION FACTORPARAMETER ( FACTOR = 0.95D+0 )* ..* .. Local Scalars ..LOGICAL NOCONVINTEGER I, ICA, IEXC, IRA, J, K, L, MDOUBLE PRECISION C, CA, F, G, R, RA, S, SFMAX1, SFMAX2, SFMIN1,$ SFMIN2* ..* .. External Functions ..LOGICAL LSAMEINTEGER IDAMAXDOUBLE PRECISION DLAMCHEXTERNAL LSAME, IDAMAX, DLAMCH* ..* .. External Subroutines ..EXTERNAL DSCAL, DSWAP, XERBLA* ..* .. Intrinsic Functions ..INTRINSIC ABS, MAX, MIN* ..* .. Executable Statements ..** Test the input parameters*INFO = 0IF( .NOT.LSAME( JOB, 'N' ) .AND. .NOT.LSAME( JOB, 'P' ) .AND.$ .NOT.LSAME( JOB, 'S' ) .AND. .NOT.LSAME( JOB, 'B' ) ) THENINFO = -1ELSE IF( N.LT.0 ) THENINFO = -2ELSE IF( LDA.LT.MAX( 1, N ) ) THENINFO = -4END IFIF( INFO.NE.0 ) THENCALL XERBLA( 'DGEBAL', -INFO )RETURNEND IF*K = 1L = N*IF( N.EQ.0 )$ GO TO 210*IF( LSAME( JOB, 'N' ) ) THENDO 10 I = 1, NSCALE( I ) = ONE10 CONTINUEGO TO 210END IF*IF( LSAME( JOB, 'S' ) )$ GO TO 120** Permutation to isolate eigenvalues if possible*GO TO 50** Row and column exchange.*20 CONTINUESCALE( M ) = JIF( J.EQ.M )$ GO TO 30*CALL DSWAP( L, A( 1, J ), 1, A( 1, M ), 1 )CALL DSWAP( N-K+1, A( J, K ), LDA, A( M, K ), LDA )*30 CONTINUEGO TO ( 40, 80 )IEXC** Search for rows isolating an eigenvalue and push them down.*40 CONTINUEIF( L.EQ.1 )$ GO TO 210L = L - 1*50 CONTINUEDO 70 J = L, 1, -1*DO 60 I = 1, LIF( I.EQ.J )$ GO TO 60IF( A( J, I ).NE.ZERO )$ GO TO 7060 CONTINUE*M = LIEXC = 1GO TO 2070 CONTINUE*GO TO 90** Search for columns isolating an eigenvalue and push them left.*80 CONTINUEK = K + 1*90 CONTINUEDO 110 J = K, L*DO 100 I = K, LIF( I.EQ.J )$ GO TO 100IF( A( I, J ).NE.ZERO )$ GO TO 110100 CONTINUE*M = KIEXC = 2GO TO 20110 CONTINUE*120 CONTINUEDO 130 I = K, LSCALE( I ) = ONE130 CONTINUE*IF( LSAME( JOB, 'P' ) )$ GO TO 210** Balance the submatrix in rows K to L.** Iterative loop for norm reduction*SFMIN1 = DLAMCH( 'S' ) / DLAMCH( 'P' )SFMAX1 = ONE / SFMIN1SFMIN2 = SFMIN1*SCLFACSFMAX2 = ONE / SFMIN2140 CONTINUENOCONV = .FALSE.*DO 200 I = K, LC = ZEROR = ZERO*DO 150 J = K, LIF( J.EQ.I )$ GO TO 150C = C + ABS( A( J, I ) )R = R + ABS( A( I, J ) )150 CONTINUEICA = IDAMAX( L, A( 1, I ), 1 )CA = ABS( A( ICA, I ) )IRA = IDAMAX( N-K+1, A( I, K ), LDA )RA = ABS( A( I, IRA+K-1 ) )** Guard against zero C or R due to underflow.*IF( C.EQ.ZERO .OR. R.EQ.ZERO )$ GO TO 200G = R / SCLFACF = ONES = C + R160 CONTINUEIF( C.GE.G .OR. MAX( F, C, CA ).GE.SFMAX2 .OR.$ MIN( R, G, RA ).LE.SFMIN2 )GO TO 170F = F*SCLFACC = C*SCLFACCA = CA*SCLFACR = R / SCLFACG = G / SCLFACRA = RA / SCLFACGO TO 160*170 CONTINUEG = C / SCLFAC180 CONTINUEIF( G.LT.R .OR. MAX( R, RA ).GE.SFMAX2 .OR.$ MIN( F, C, G, CA ).LE.SFMIN2 )GO TO 190F = F / SCLFACC = C / SCLFACG = G / SCLFACCA = CA / SCLFACR = R*SCLFACRA = RA*SCLFACGO TO 180** Now balance.*190 CONTINUEIF( ( C+R ).GE.FACTOR*S )$ GO TO 200IF( F.LT.ONE .AND. SCALE( I ).LT.ONE ) THENIF( F*SCALE( I ).LE.SFMIN1 )$ GO TO 200END IFIF( F.GT.ONE .AND. SCALE( I ).GT.ONE ) THENIF( SCALE( I ).GE.SFMAX1 / F )$ GO TO 200END IFG = ONE / FSCALE( I ) = SCALE( I )*FNOCONV = .TRUE.*CALL DSCAL( N-K+1, G, A( I, K ), LDA )CALL DSCAL( L, F, A( 1, I ), 1 )*200 CONTINUE*IF( NOCONV )$ GO TO 140*210 CONTINUEILO = KIHI = L*RETURN** End of DGEBAL*ENDSUBROUTINE DGEBD2( M, N, A, LDA, D, E, TAUQ, TAUP, WORK, INFO )** -- LAPACK routine (version 3.0) --* Univ. of Tennessee, Univ. of California Berkeley, NAG Ltd.,* Courant Institute, Argonne National Lab, and Rice University* February 29, 1992** .. Scalar Arguments ..INTEGER INFO, LDA, M, N* ..* .. Array Arguments ..DOUBLE PRECISION A( LDA, * ), D( * ), E( * ), TAUP( * ),$ TAUQ( * ), WORK( * )* ..** Purpose* =======** DGEBD2 reduces a real general m by n matrix A to upper or lower* bidiagonal form B by an orthogonal transformation: Q' * A * P = B.** If m >= n, B is upper bidiagonal; if m < n, B is lower bidiagonal.** Arguments* =========** M (input) INTEGER* The number of rows in the matrix A. M >= 0.** N (input) INTEGER* The number of columns in the matrix A. N >= 0.** A (input/output) DOUBLE PRECISION array, dimension (LDA,N)* On entry, the m by n general matrix to be reduced.* On exit,* if m >= n, the diagonal and the first superdiagonal are* overwritten with the upper bidiagonal matrix B; the* elements below the diagonal, with the array TAUQ, represent* the orthogonal matrix Q as a product of elementary* reflectors, and the elements above the first superdiagonal,* with the array TAUP, represent the orthogonal matrix P as* a product of elementary reflectors;* if m < n, the diagonal and the first subdiagonal are* overwritten with the lower bidiagonal matrix B; the* elements below the first subdiagonal, with the array TAUQ,* represent the orthogonal matrix Q as a product of* elementary reflectors, and the elements above the diagonal,* with the array TAUP, represent the orthogonal matrix P as* a product of elementary reflectors.* See Further Details.** LDA (input) INTEGER* The leading dimension of the array A. LDA >= max(1,M).** D (output) DOUBLE PRECISION array, dimension (min(M,N))* The diagonal elements of the bidiagonal matrix B:* D(i) = A(i,i).** E (output) DOUBLE PRECISION array, dimension (min(M,N)-1)* The off-diagonal elements of the bidiagonal matrix B:* if m >= n, E(i) = A(i,i+1) for i = 1,2,...,n-1;* if m < n, E(i) = A(i+1,i) for i = 1,2,...,m-1.** TAUQ (output) DOUBLE PRECISION array dimension (min(M,N))* The scalar factors of the elementary reflectors which* represent the orthogonal matrix Q. See Further Details.** TAUP (output) DOUBLE PRECISION array, dimension (min(M,N))* The scalar factors of the elementary reflectors which* represent the orthogonal matrix P. See Further Details.** WORK (workspace) DOUBLE PRECISION array, dimension (max(M,N))** INFO (output) INTEGER* = 0: successful exit.* < 0: if INFO = -i, the i-th argument had an illegal value.** Further Details* ===============** The matrices Q and P are represented as products of elementary* reflectors:** If m >= n,** Q = H(1) H(2) . . . H(n) and P = G(1) G(2) . . . G(n-1)** Each H(i) and G(i) has the form:** H(i) = I - tauq * v * v' and G(i) = I - taup * u * u'** where tauq and taup are real scalars, and v and u are real vectors;* v(1:i-1) = 0, v(i) = 1, and v(i+1:m) is stored on exit in A(i+1:m,i);* u(1:i) = 0, u(i+1) = 1, and u(i+2:n) is stored on exit in A(i,i+2:n);* tauq is stored in TAUQ(i) and taup in TAUP(i).** If m < n,** Q = H(1) H(2) . . . H(m-1) and P = G(1) G(2) . . . G(m)** Each H(i) and G(i) has the form:** H(i) = I - tauq * v * v' and G(i) = I - taup * u * u'** where tauq and taup are real scalars, and v and u are real vectors;* v(1:i) = 0, v(i+1) = 1, and v(i+2:m) is stored on exit in A(i+2:m,i);* u(1:i-1) = 0, u(i) = 1, and u(i+1:n) is stored on exit in A(i,i+1:n);* tauq is stored in TAUQ(i) and taup in TAUP(i).** The contents of A on exit are illustrated by the following examples:** m = 6 and n = 5 (m > n): m = 5 and n = 6 (m < n):** ( d e u1 u1 u1 ) ( d u1 u1 u1 u1 u1 )* ( v1 d e u2 u2 ) ( e d u2 u2 u2 u2 )* ( v1 v2 d e u3 ) ( v1 e d u3 u3 u3 )* ( v1 v2 v3 d e ) ( v1 v2 e d u4 u4 )* ( v1 v2 v3 v4 d ) ( v1 v2 v3 e d u5 )* ( v1 v2 v3 v4 v5 )** where d and e denote diagonal and off-diagonal elements of B, vi* denotes an element of the vector defining H(i), and ui an element of* the vector defining G(i).** =====================================================================** .. Parameters ..DOUBLE PRECISION ZERO, ONEPARAMETER ( ZERO = 0.0D+0, ONE = 1.0D+0 )* ..* .. Local Scalars ..INTEGER I* ..* .. External Subroutines ..EXTERNAL DLARF, DLARFG, XERBLA* ..* .. Intrinsic Functions ..INTRINSIC MAX, MIN* ..* .. Executable Statements ..** Test the input parameters*INFO = 0IF( M.LT.0 ) THENINFO = -1ELSE IF( N.LT.0 ) THENINFO = -2ELSE IF( LDA.LT.MAX( 1, M ) ) THENINFO = -4END IFIF( INFO.LT.0 ) THENCALL XERBLA( 'DGEBD2', -INFO )RETURNEND IF*IF( M.GE.N ) THEN** Reduce to upper bidiagonal form*DO 10 I = 1, N** Generate elementary reflector H(i) to annihilate A(i+1:m,i)*CALL DLARFG( M-I+1, A( I, I ), A( MIN( I+1, M ), I ), 1,$ TAUQ( I ) )D( I ) = A( I, I )A( I, I ) = ONE** Apply H(i) to A(i:m,i+1:n) from the left*CALL DLARF( 'Left', M-I+1, N-I, A( I, I ), 1, TAUQ( I ),$ A( I, I+1 ), LDA, WORK )A( I, I ) = D( I )*IF( I.LT.N ) THEN** Generate elementary reflector G(i) to annihilate* A(i,i+2:n)*CALL DLARFG( N-I, A( I, I+1 ), A( I, MIN( I+2, N ) ),$ LDA, TAUP( I ) )E( I ) = A( I, I+1 )A( I, I+1 ) = ONE** Apply G(i) to A(i+1:m,i+1:n) from the right*CALL DLARF( 'Right', M-I, N-I, A( I, I+1 ), LDA,$ TAUP( I ), A( I+1, I+1 ), LDA, WORK )A( I, I+1 ) = E( I )ELSETAUP( I ) = ZEROEND IF10 CONTINUEELSE** Reduce to lower bidiagonal form*DO 20 I = 1, M** Generate elementary reflector G(i) to annihilate A(i,i+1:n)*CALL DLARFG( N-I+1, A( I, I ), A( I, MIN( I+1, N ) ), LDA,$ TAUP( I ) )D( I ) = A( I, I )A( I, I ) = ONE** Apply G(i) to A(i+1:m,i:n) from the right*CALL DLARF( 'Right', M-I, N-I+1, A( I, I ), LDA, TAUP( I ),$ A( MIN( I+1, M ), I ), LDA, WORK )A( I, I ) = D( I )*IF( I.LT.M ) THEN** Generate elementary reflector H(i) to annihilate* A(i+2:m,i)*CALL DLARFG( M-I, A( I+1, I ), A( MIN( I+2, M ), I ), 1,$ TAUQ( I ) )E( I ) = A( I+1, I )A( I+1, I ) = ONE** Apply H(i) to A(i+1:m,i+1:n) from the left*CALL DLARF( 'Left', M-I, N-I, A( I+1, I ), 1, TAUQ( I ),$ A( I+1, I+1 ), LDA, WORK )A( I+1, I ) = E( I )ELSETAUQ( I ) = ZEROEND IF20 CONTINUEEND IFRETURN** End of DGEBD2*ENDSUBROUTINE DGEBRD( M, N, A, LDA, D, E, TAUQ, TAUP, WORK, LWORK,$ INFO )** -- LAPACK routine (version 3.0) --* Univ. of Tennessee, Univ. of California Berkeley, NAG Ltd.,* Courant Institute, Argonne National Lab, and Rice University* June 30, 1999** .. Scalar Arguments ..INTEGER INFO, LDA, LWORK, M, N* ..* .. Array Arguments ..DOUBLE PRECISION A( LDA, * ), D( * ), E( * ), TAUP( * ),$ TAUQ( * ), WORK( * )* ..** Purpose* =======** DGEBRD reduces a general real M-by-N matrix A to upper or lower* bidiagonal form B by an orthogonal transformation: Q**T * A * P = B.** If m >= n, B is upper bidiagonal; if m < n, B is lower bidiagonal.** Arguments* =========** M (input) INTEGER* The number of rows in the matrix A. M >= 0.** N (input) INTEGER* The number of columns in the matrix A. N >= 0.** A (input/output) DOUBLE PRECISION array, dimension (LDA,N)* On entry, the M-by-N general matrix to be reduced.* On exit,* if m >= n, the diagonal and the first superdiagonal are* overwritten with the upper bidiagonal matrix B; the* elements below the diagonal, with the array TAUQ, represent* the orthogonal matrix Q as a product of elementary* reflectors, and the elements above the first superdiagonal,* with the array TAUP, represent the orthogonal matrix P as* a product of elementary reflectors;* if m < n, the diagonal and the first subdiagonal are* overwritten with the lower bidiagonal matrix B; the* elements below the first subdiagonal, with the array TAUQ,* represent the orthogonal matrix Q as a product of* elementary reflectors, and the elements above the diagonal,* with the array TAUP, represent the orthogonal matrix P as* a product of elementary reflectors.* See Further Details.** LDA (input) INTEGER* The leading dimension of the array A. LDA >= max(1,M).** D (output) DOUBLE PRECISION array, dimension (min(M,N))* The diagonal elements of the bidiagonal matrix B:* D(i) = A(i,i).** E (output) DOUBLE PRECISION array, dimension (min(M,N)-1)* The off-diagonal elements of the bidiagonal matrix B:* if m >= n, E(i) = A(i,i+1) for i = 1,2,...,n-1;* if m < n, E(i) = A(i+1,i) for i = 1,2,...,m-1.** TAUQ (output) DOUBLE PRECISION array dimension (min(M,N))* The scalar factors of the elementary reflectors which* represent the orthogonal matrix Q. See Further Details.** TAUP (output) DOUBLE PRECISION array, dimension (min(M,N))* The scalar factors of the elementary reflectors which* represent the orthogonal matrix P. See Further Details.** WORK (workspace/output) DOUBLE PRECISION array, dimension (LWORK)* On exit, if INFO = 0, WORK(1) returns the optimal LWORK.** LWORK (input) INTEGER* The length of the array WORK. LWORK >= max(1,M,N).* For optimum performance LWORK >= (M+N)*NB, where NB* is the optimal blocksize.** If LWORK = -1, then a workspace query is assumed; the routine* only calculates the optimal size of the WORK array, returns* this value as the first entry of the WORK array, and no error* message related to LWORK is issued by XERBLA.** INFO (output) INTEGER* = 0: successful exit* < 0: if INFO = -i, the i-th argument had an illegal value.** Further Details* ===============** The matrices Q and P are represented as products of elementary* reflectors:** If m >= n,** Q = H(1) H(2) . . . H(n) and P = G(1) G(2) . . . G(n-1)** Each H(i) and G(i) has the form:** H(i) = I - tauq * v * v' and G(i) = I - taup * u * u'** where tauq and taup are real scalars, and v and u are real vectors;* v(1:i-1) = 0, v(i) = 1, and v(i+1:m) is stored on exit in A(i+1:m,i);* u(1:i) = 0, u(i+1) = 1, and u(i+2:n) is stored on exit in A(i,i+2:n);* tauq is stored in TAUQ(i) and taup in TAUP(i).** If m < n,** Q = H(1) H(2) . . . H(m-1) and P = G(1) G(2) . . . G(m)** Each H(i) and G(i) has the form:** H(i) = I - tauq * v * v' and G(i) = I - taup * u * u'** where tauq and taup are real scalars, and v and u are real vectors;* v(1:i) = 0, v(i+1) = 1, and v(i+2:m) is stored on exit in A(i+2:m,i);* u(1:i-1) = 0, u(i) = 1, and u(i+1:n) is stored on exit in A(i,i+1:n);* tauq is stored in TAUQ(i) and taup in TAUP(i).** The contents of A on exit are illustrated by the following examples:** m = 6 and n = 5 (m > n): m = 5 and n = 6 (m < n):** ( d e u1 u1 u1 ) ( d u1 u1 u1 u1 u1 )* ( v1 d e u2 u2 ) ( e d u2 u2 u2 u2 )* ( v1 v2 d e u3 ) ( v1 e d u3 u3 u3 )* ( v1 v2 v3 d e ) ( v1 v2 e d u4 u4 )* ( v1 v2 v3 v4 d ) ( v1 v2 v3 e d u5 )* ( v1 v2 v3 v4 v5 )** where d and e denote diagonal and off-diagonal elements of B, vi* denotes an element of the vector defining H(i), and ui an element of* the vector defining G(i).** =====================================================================** .. Parameters ..DOUBLE PRECISION ONEPARAMETER ( ONE = 1.0D+0 )* ..* .. Local Scalars ..LOGICAL LQUERYINTEGER I, IINFO, J, LDWRKX, LDWRKY, LWKOPT, MINMN, NB,$ NBMIN, NXDOUBLE PRECISION WS* ..* .. External Subroutines ..EXTERNAL DGEBD2, DGEMM, DLABRD, XERBLA* ..* .. Intrinsic Functions ..INTRINSIC DBLE, MAX, MIN* ..* .. External Functions ..INTEGER ILAENVEXTERNAL ILAENV* ..* .. Executable Statements ..** Test the input parameters*INFO = 0NB = MAX( 1, ILAENV( 1, 'DGEBRD', ' ', M, N, -1, -1 ) )LWKOPT = ( M+N )*NBWORK( 1 ) = DBLE( LWKOPT )LQUERY = ( LWORK.EQ.-1 )IF( M.LT.0 ) THENINFO = -1ELSE IF( N.LT.0 ) THENINFO = -2ELSE IF( LDA.LT.MAX( 1, M ) ) THENINFO = -4ELSE IF( LWORK.LT.MAX( 1, M, N ) .AND. .NOT.LQUERY ) THENINFO = -10END IFIF( INFO.LT.0 ) THENCALL XERBLA( 'DGEBRD', -INFO )RETURNELSE IF( LQUERY ) THENRETURNEND IF** Quick return if possible*MINMN = MIN( M, N )IF( MINMN.EQ.0 ) THENWORK( 1 ) = 1RETURNEND IF*WS = MAX( M, N )LDWRKX = MLDWRKY = N*IF( NB.GT.1 .AND. NB.LT.MINMN ) THEN** Set the crossover point NX.*NX = MAX( NB, ILAENV( 3, 'DGEBRD', ' ', M, N, -1, -1 ) )** Determine when to switch from blocked to unblocked code.*IF( NX.LT.MINMN ) THENWS = ( M+N )*NBIF( LWORK.LT.WS ) THEN** Not enough work space for the optimal NB, consider using* a smaller block size.*NBMIN = ILAENV( 2, 'DGEBRD', ' ', M, N, -1, -1 )IF( LWORK.GE.( M+N )*NBMIN ) THENNB = LWORK / ( M+N )ELSENB = 1NX = MINMNEND IFEND IFEND IFELSENX = MINMNEND IF*DO 30 I = 1, MINMN - NX, NB** Reduce rows and columns i:i+nb-1 to bidiagonal form and return* the matrices X and Y which are needed to update the unreduced* part of the matrix*CALL DLABRD( M-I+1, N-I+1, NB, A( I, I ), LDA, D( I ), E( I ),$ TAUQ( I ), TAUP( I ), WORK, LDWRKX,$ WORK( LDWRKX*NB+1 ), LDWRKY )** Update the trailing submatrix A(i+nb:m,i+nb:n), using an update* of the form A := A - V*Y' - X*U'*CALL DGEMM( 'No transpose', 'Transpose', M-I-NB+1, N-I-NB+1,$ NB, -ONE, A( I+NB, I ), LDA,$ WORK( LDWRKX*NB+NB+1 ), LDWRKY, ONE,$ A( I+NB, I+NB ), LDA )CALL DGEMM( 'No transpose', 'No transpose', M-I-NB+1, N-I-NB+1,$ NB, -ONE, WORK( NB+1 ), LDWRKX, A( I, I+NB ), LDA,$ ONE, A( I+NB, I+NB ), LDA )** Copy diagonal and off-diagonal elements of B back into A*IF( M.GE.N ) THENDO 10 J = I, I + NB - 1A( J, J ) = D( J )A( J, J+1 ) = E( J )10 CONTINUEELSEDO 20 J = I, I + NB - 1A( J, J ) = D( J )A( J+1, J ) = E( J )20 CONTINUEEND IF30 CONTINUE** Use unblocked code to reduce the remainder of the matrix*CALL DGEBD2( M-I+1, N-I+1, A( I, I ), LDA, D( I ), E( I ),$ TAUQ( I ), TAUP( I ), WORK, IINFO )WORK( 1 ) = WSRETURN** End of DGEBRD*ENDSUBROUTINE DGECON( NORM, N, A, LDA, ANORM, RCOND, WORK, IWORK,$ INFO )** -- LAPACK routine (version 3.0) --* Univ. of Tennessee, Univ. of California Berkeley, NAG Ltd.,* Courant Institute, Argonne National Lab, and Rice University* February 29, 1992** .. Scalar Arguments ..CHARACTER NORMINTEGER INFO, LDA, NDOUBLE PRECISION ANORM, RCOND* ..* .. Array Arguments ..INTEGER IWORK( * )DOUBLE PRECISION A( LDA, * ), WORK( * )* ..** Purpose* =======** DGECON estimates the reciprocal of the condition number of a general* real matrix A, in either the 1-norm or the infinity-norm, using* the LU factorization computed by DGETRF.** An estimate is obtained for norm(inv(A)), and the reciprocal of the* condition number is computed as* RCOND = 1 / ( norm(A) * norm(inv(A)) ).** Arguments* =========** NORM (input) CHARACTER*1* Specifies whether the 1-norm condition number or the* infinity-norm condition number is required:* = '1' or 'O': 1-norm;* = 'I': Infinity-norm.** N (input) INTEGER* The order of the matrix A. N >= 0.** A (input) DOUBLE PRECISION array, dimension (LDA,N)* The factors L and U from the factorization A = P*L*U* as computed by DGETRF.** LDA (input) INTEGER* The leading dimension of the array A. LDA >= max(1,N).** ANORM (input) DOUBLE PRECISION* If NORM = '1' or 'O', the 1-norm of the original matrix A.* If NORM = 'I', the infinity-norm of the original matrix A.** RCOND (output) DOUBLE PRECISION* The reciprocal of the condition number of the matrix A,* computed as RCOND = 1/(norm(A) * norm(inv(A))).** WORK (workspace) DOUBLE PRECISION array, dimension (4*N)** IWORK (workspace) INTEGER array, dimension (N)** INFO (output) INTEGER* = 0: successful exit* < 0: if INFO = -i, the i-th argument had an illegal value** =====================================================================** .. Parameters ..DOUBLE PRECISION ONE, ZEROPARAMETER ( ONE = 1.0D+0, ZERO = 0.0D+0 )* ..* .. Local Scalars ..LOGICAL ONENRMCHARACTER NORMININTEGER IX, KASE, KASE1DOUBLE PRECISION AINVNM, SCALE, SL, SMLNUM, SU* ..* .. External Functions ..LOGICAL LSAMEINTEGER IDAMAXDOUBLE PRECISION DLAMCHEXTERNAL LSAME, IDAMAX, DLAMCH* ..* .. External Subroutines ..EXTERNAL DLACON, DLATRS, DRSCL, XERBLA* ..* .. Intrinsic Functions ..INTRINSIC ABS, MAX* ..* .. Executable Statements ..** Test the input parameters.*INFO = 0ONENRM = NORM.EQ.'1' .OR. LSAME( NORM, 'O' )IF( .NOT.ONENRM .AND. .NOT.LSAME( NORM, 'I' ) ) THENINFO = -1ELSE IF( N.LT.0 ) THENINFO = -2ELSE IF( LDA.LT.MAX( 1, N ) ) THENINFO = -4ELSE IF( ANORM.LT.ZERO ) THENINFO = -5END IFIF( INFO.NE.0 ) THENCALL XERBLA( 'DGECON', -INFO )RETURNEND IF** Quick return if possible*RCOND = ZEROIF( N.EQ.0 ) THENRCOND = ONERETURNELSE IF( ANORM.EQ.ZERO ) THENRETURNEND IF*SMLNUM = DLAMCH( 'Safe minimum' )** Estimate the norm of inv(A).*AINVNM = ZERONORMIN = 'N'IF( ONENRM ) THENKASE1 = 1ELSEKASE1 = 2END IFKASE = 010 CONTINUECALL DLACON( N, WORK( N+1 ), WORK, IWORK, AINVNM, KASE )IF( KASE.NE.0 ) THENIF( KASE.EQ.KASE1 ) THEN** Multiply by inv(L).*CALL DLATRS( 'Lower', 'No transpose', 'Unit', NORMIN, N, A,$ LDA, WORK, SL, WORK( 2*N+1 ), INFO )** Multiply by inv(U).*CALL DLATRS( 'Upper', 'No transpose', 'Non-unit', NORMIN, N,$ A, LDA, WORK, SU, WORK( 3*N+1 ), INFO )ELSE** Multiply by inv(U').*CALL DLATRS( 'Upper', 'Transpose', 'Non-unit', NORMIN, N, A,$ LDA, WORK, SU, WORK( 3*N+1 ), INFO )** Multiply by inv(L').*CALL DLATRS( 'Lower', 'Transpose', 'Unit', NORMIN, N, A,$ LDA, WORK, SL, WORK( 2*N+1 ), INFO )END IF** Divide X by 1/(SL*SU) if doing so will not cause overflow.*SCALE = SL*SUNORMIN = 'Y'IF( SCALE.NE.ONE ) THENIX = IDAMAX( N, WORK, 1 )IF( SCALE.LT.ABS( WORK( IX ) )*SMLNUM .OR. SCALE.EQ.ZERO )$ GO TO 20CALL DRSCL( N, SCALE, WORK, 1 )END IFGO TO 10END IF** Compute the estimate of the reciprocal condition number.*IF( AINVNM.NE.ZERO )$ RCOND = ( ONE / AINVNM ) / ANORM*20 CONTINUERETURN** End of DGECON*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* June 30, 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 ) THENc IF( INFO.EQ.0 .AND. LWORK.GE.1 ) 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 DGEHD2( N, ILO, IHI, A, LDA, TAU, WORK, INFO )** -- LAPACK routine (version 3.0) --* Univ. of Tennessee, Univ. of California Berkeley, NAG Ltd.,* Courant Institute, Argonne National Lab, and Rice University* October 31, 1992** .. Scalar Arguments ..INTEGER IHI, ILO, INFO, LDA, N* ..* .. Array Arguments ..DOUBLE PRECISION A( LDA, * ), TAU( * ), WORK( * )* ..** Purpose* =======** DGEHD2 reduces a real general matrix A to upper Hessenberg form H by* an orthogonal similarity transformation: Q' * A * Q = H .** Arguments* =========** N (input) INTEGER* The order of the matrix A. N >= 0.** ILO (input) INTEGER* IHI (input) INTEGER* It is assumed that A is already upper triangular in rows* and columns 1:ILO-1 and IHI+1:N. ILO and IHI are normally* set by a previous call to DGEBAL; otherwise they should be* set to 1 and N respectively. See Further Details.* 1 <= ILO <= IHI <= max(1,N).** A (input/output) DOUBLE PRECISION array, dimension (LDA,N)* On entry, the n by n general matrix to be reduced.* On exit, the upper triangle and the first subdiagonal of A* are overwritten with the upper Hessenberg matrix H, and the* elements below the first subdiagonal, with the array TAU,* represent the orthogonal matrix Q as a product of elementary* reflectors. See Further Details.** LDA (input) INTEGER* The leading dimension of the array A. LDA >= max(1,N).** TAU (output) DOUBLE PRECISION array, dimension (N-1)* The scalar factors of the elementary reflectors (see Further* Details).** WORK (workspace) DOUBLE PRECISION array, dimension (N)** INFO (output) INTEGER* = 0: successful exit.* < 0: if INFO = -i, the i-th argument had an illegal value.** Further Details* ===============** The matrix Q is represented as a product of (ihi-ilo) elementary* reflectors** Q = H(ilo) H(ilo+1) . . . H(ihi-1).** Each H(i) has the form** H(i) = I - tau * v * v'** where tau is a real scalar, and v is a real vector with* v(1:i) = 0, v(i+1) = 1 and v(ihi+1:n) = 0; v(i+2:ihi) is stored on* exit in A(i+2:ihi,i), and tau in TAU(i).** The contents of A are illustrated by the following example, with* n = 7, ilo = 2 and ihi = 6:** on entry, on exit,** ( a a a a a a a ) ( a a h h h h a )* ( a a a a a a ) ( a h h h h a )* ( a a a a a a ) ( h h h h h h )* ( a a a a a a ) ( v2 h h h h h )* ( a a a a a a ) ( v2 v3 h h h h )* ( a a a a a a ) ( v2 v3 v4 h h h )* ( a ) ( a )** where a denotes an element of the original matrix A, h denotes a* modified element of the upper Hessenberg matrix H, and vi denotes an* element of the vector defining H(i).** =====================================================================** .. Parameters ..DOUBLE PRECISION ONEPARAMETER ( ONE = 1.0D+0 )* ..* .. Local Scalars ..INTEGER IDOUBLE PRECISION AII* ..* .. External Subroutines ..EXTERNAL DLARF, DLARFG, XERBLA* ..* .. Intrinsic Functions ..INTRINSIC MAX, MIN* ..* .. Executable Statements ..** Test the input parameters*INFO = 0IF( N.LT.0 ) THENINFO = -1ELSE IF( ILO.LT.1 .OR. ILO.GT.MAX( 1, N ) ) THENINFO = -2ELSE IF( IHI.LT.MIN( ILO, N ) .OR. IHI.GT.N ) THENINFO = -3ELSE IF( LDA.LT.MAX( 1, N ) ) THENINFO = -5END IFIF( INFO.NE.0 ) THENCALL XERBLA( 'DGEHD2', -INFO )RETURNEND IF*DO 10 I = ILO, IHI - 1** Compute elementary reflector H(i) to annihilate A(i+2:ihi,i)*CALL DLARFG( IHI-I, A( I+1, I ), A( MIN( I+2, N ), I ), 1,$ TAU( I ) )AII = A( I+1, I )A( I+1, I ) = ONE** Apply H(i) to A(1:ihi,i+1:ihi) from the right*CALL DLARF( 'Right', IHI, IHI-I, A( I+1, I ), 1, TAU( I ),$ A( 1, I+1 ), LDA, WORK )** Apply H(i) to A(i+1:ihi,i+1:n) from the left*CALL DLARF( 'Left', IHI-I, N-I, A( I+1, I ), 1, TAU( I ),$ A( I+1, I+1 ), LDA, WORK )*A( I+1, I ) = AII10 CONTINUE*RETURN** End of DGEHD2*ENDSUBROUTINE DGEHRD( N, ILO, IHI, A, LDA, TAU, WORK, LWORK, INFO )** -- LAPACK routine (version 3.0) --* Univ. of Tennessee, Univ. of California Berkeley, NAG Ltd.,* Courant Institute, Argonne National Lab, and Rice University* June 30, 1999** .. Scalar Arguments ..INTEGER IHI, ILO, INFO, LDA, LWORK, N* ..* .. Array Arguments ..DOUBLE PRECISION A( LDA, * ), TAU( * ), WORK( * )* ..** Purpose* =======** DGEHRD reduces a real general matrix A to upper Hessenberg form H by* an orthogonal similarity transformation: Q' * A * Q = H .** Arguments* =========** N (input) INTEGER* The order of the matrix A. N >= 0.** ILO (input) INTEGER* IHI (input) INTEGER* It is assumed that A is already upper triangular in rows* and columns 1:ILO-1 and IHI+1:N. ILO and IHI are normally* set by a previous call to DGEBAL; otherwise they should be* set to 1 and N respectively. See Further Details.* 1 <= ILO <= IHI <= N, if N > 0; ILO=1 and IHI=0, if N=0.** A (input/output) DOUBLE PRECISION array, dimension (LDA,N)* On entry, the N-by-N general matrix to be reduced.* On exit, the upper triangle and the first subdiagonal of A* are overwritten with the upper Hessenberg matrix H, and the* elements below the first subdiagonal, with the array TAU,* represent the orthogonal matrix Q as a product of elementary* reflectors. See Further Details.** LDA (input) INTEGER* The leading dimension of the array A. LDA >= max(1,N).** TAU (output) DOUBLE PRECISION array, dimension (N-1)* The scalar factors of the elementary reflectors (see Further* Details). Elements 1:ILO-1 and IHI:N-1 of TAU are set to* zero.** 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,N).* For optimum performance LWORK >= N*NB, where NB is the* optimal blocksize.** If LWORK = -1, then a workspace query is assumed; the routine* only calculates the optimal size of the WORK array, returns* this value as the first entry of the WORK array, and no error* message related to LWORK is issued by XERBLA.** INFO (output) INTEGER* = 0: successful exit* < 0: if INFO = -i, the i-th argument had an illegal value.** Further Details* ===============** The matrix Q is represented as a product of (ihi-ilo) elementary* reflectors** Q = H(ilo) H(ilo+1) . . . H(ihi-1).** Each H(i) has the form** H(i) = I - tau * v * v'** where tau is a real scalar, and v is a real vector with* v(1:i) = 0, v(i+1) = 1 and v(ihi+1:n) = 0; v(i+2:ihi) is stored on* exit in A(i+2:ihi,i), and tau in TAU(i).** The contents of A are illustrated by the following example, with* n = 7, ilo = 2 and ihi = 6:** on entry, on exit,** ( a a a a a a a ) ( a a h h h h a )* ( a a a a a a ) ( a h h h h a )* ( a a a a a a ) ( h h h h h h )* ( a a a a a a ) ( v2 h h h h h )* ( a a a a a a ) ( v2 v3 h h h h )* ( a a a a a a ) ( v2 v3 v4 h h h )* ( a ) ( a )** where a denotes an element of the original matrix A, h denotes a* modified element of the upper Hessenberg matrix H, and vi denotes an* element of the vector defining H(i).** =====================================================================** .. Parameters ..INTEGER NBMAX, LDTPARAMETER ( NBMAX = 64, LDT = NBMAX+1 )DOUBLE PRECISION ZERO, ONEPARAMETER ( ZERO = 0.0D+0, ONE = 1.0D+0 )* ..* .. Local Scalars ..LOGICAL LQUERYINTEGER I, IB, IINFO, IWS, LDWORK, LWKOPT, NB, NBMIN,$ NH, NXDOUBLE PRECISION EI* ..* .. Local Arrays ..DOUBLE PRECISION T( LDT, NBMAX )* ..* .. External Subroutines ..EXTERNAL DGEHD2, DGEMM, DLAHRD, DLARFB, XERBLA* ..* .. Intrinsic Functions ..INTRINSIC MAX, MIN* ..* .. External Functions ..INTEGER ILAENVEXTERNAL ILAENV* ..* .. Executable Statements ..** Test the input parameters*INFO = 0NB = MIN( NBMAX, ILAENV( 1, 'DGEHRD', ' ', N, ILO, IHI, -1 ) )LWKOPT = N*NBWORK( 1 ) = LWKOPTLQUERY = ( LWORK.EQ.-1 )IF( N.LT.0 ) THENINFO = -1ELSE IF( ILO.LT.1 .OR. ILO.GT.MAX( 1, N ) ) THENINFO = -2ELSE IF( IHI.LT.MIN( ILO, N ) .OR. IHI.GT.N ) THENINFO = -3ELSE IF( LDA.LT.MAX( 1, N ) ) THENINFO = -5ELSE IF( LWORK.LT.MAX( 1, N ) .AND. .NOT.LQUERY ) THENINFO = -8END IFIF( INFO.NE.0 ) THENCALL XERBLA( 'DGEHRD', -INFO )RETURNELSE IF( LQUERY ) THENRETURNEND IF** Set elements 1:ILO-1 and IHI:N-1 of TAU to zero*DO 10 I = 1, ILO - 1TAU( I ) = ZERO10 CONTINUEDO 20 I = MAX( 1, IHI ), N - 1TAU( I ) = ZERO20 CONTINUE** Quick return if possible*NH = IHI - ILO + 1IF( NH.LE.1 ) THENWORK( 1 ) = 1RETURNEND IF** Determine the block size.*NB = MIN( NBMAX, ILAENV( 1, 'DGEHRD', ' ', N, ILO, IHI, -1 ) )NBMIN = 2IWS = 1IF( NB.GT.1 .AND. NB.LT.NH ) THEN** Determine when to cross over from blocked to unblocked code* (last block is always handled by unblocked code).*NX = MAX( NB, ILAENV( 3, 'DGEHRD', ' ', N, ILO, IHI, -1 ) )IF( NX.LT.NH ) THEN** Determine if workspace is large enough for blocked code.*IWS = N*NBIF( LWORK.LT.IWS ) THEN** Not enough workspace to use optimal NB: determine the* minimum value of NB, and reduce NB or force use of* unblocked code.*NBMIN = MAX( 2, ILAENV( 2, 'DGEHRD', ' ', N, ILO, IHI,$ -1 ) )IF( LWORK.GE.N*NBMIN ) THENNB = LWORK / NELSENB = 1END IFEND IFEND IFEND IFLDWORK = N*IF( NB.LT.NBMIN .OR. NB.GE.NH ) THEN** Use unblocked code below*I = ILO*ELSE** Use blocked code*DO 30 I = ILO, IHI - 1 - NX, NBIB = MIN( NB, IHI-I )** Reduce columns i:i+ib-1 to Hessenberg form, returning the* matrices V and T of the block reflector H = I - V*T*V'* which performs the reduction, and also the matrix Y = A*V*T*CALL DLAHRD( IHI, I, IB, A( 1, I ), LDA, TAU( I ), T, LDT,$ WORK, LDWORK )** Apply the block reflector H to A(1:ihi,i+ib:ihi) from the* right, computing A := A - Y * V'. V(i+ib,ib-1) must be set* to 1.*EI = A( I+IB, I+IB-1 )A( I+IB, I+IB-1 ) = ONECALL DGEMM( 'No transpose', 'Transpose', IHI, IHI-I-IB+1,$ IB, -ONE, WORK, LDWORK, A( I+IB, I ), LDA, ONE,$ A( 1, I+IB ), LDA )A( I+IB, I+IB-1 ) = EI** Apply the block reflector H to A(i+1:ihi,i+ib:n) from the* left*CALL DLARFB( 'Left', 'Transpose', 'Forward', 'Columnwise',$ IHI-I, N-I-IB+1, IB, A( I+1, I ), LDA, T, LDT,$ A( I+1, I+IB ), LDA, WORK, LDWORK )30 CONTINUEEND IF** Use unblocked code to reduce the rest of the matrix*CALL DGEHD2( N, I, IHI, A, LDA, TAU, WORK, IINFO )WORK( 1 ) = IWS*RETURN** End of DGEHRD*ENDSUBROUTINE DGELQ2( M, N, A, LDA, TAU, WORK, INFO )** -- LAPACK routine (version 3.0) --* Univ. of Tennessee, Univ. of California Berkeley, NAG Ltd.,* Courant Institute, Argonne National Lab, and Rice University* February 29, 1992** .. Scalar Arguments ..INTEGER INFO, LDA, M, N* ..* .. Array Arguments ..DOUBLE PRECISION A( LDA, * ), TAU( * ), WORK( * )* ..** Purpose* =======** DGELQ2 computes an LQ factorization of a real m by n matrix A:* A = L * 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.** A (input/output) DOUBLE PRECISION array, dimension (LDA,N)* On entry, the m by n matrix A.* On exit, the elements on and below the diagonal of the array* contain the m by min(m,n) lower trapezoidal matrix L (L is* lower triangular if m <= n); the elements above the diagonal,* with the array TAU, represent the orthogonal matrix Q as a* product of elementary reflectors (see Further Details).** LDA (input) INTEGER* The leading dimension of the array A. LDA >= max(1,M).** TAU (output) DOUBLE PRECISION array, dimension (min(M,N))* The scalar factors of the elementary reflectors (see Further* Details).** WORK (workspace) DOUBLE PRECISION array, dimension (M)** INFO (output) INTEGER* = 0: successful exit* < 0: if INFO = -i, the i-th argument had an illegal value** Further Details* ===============** The matrix Q is represented as a product of elementary reflectors** Q = H(k) . . . H(2) H(1), where k = min(m,n).** Each H(i) has the form** H(i) = I - tau * v * v'** where tau is a real scalar, and v is a real vector with* v(1:i-1) = 0 and v(i) = 1; v(i+1:n) is stored on exit in A(i,i+1:n),* and tau in TAU(i).** =====================================================================** .. Parameters ..DOUBLE PRECISION ONEPARAMETER ( ONE = 1.0D+0 )* ..* .. Local Scalars ..INTEGER I, KDOUBLE PRECISION AII* ..* .. External Subroutines ..EXTERNAL DLARF, DLARFG, XERBLA* ..* .. Intrinsic Functions ..INTRINSIC MAX, MIN* ..* .. Executable Statements ..** Test the input arguments*INFO = 0IF( M.LT.0 ) THENINFO = -1ELSE IF( N.LT.0 ) THENINFO = -2ELSE IF( LDA.LT.MAX( 1, M ) ) THENINFO = -4END IFIF( INFO.NE.0 ) THENCALL XERBLA( 'DGELQ2', -INFO )RETURNEND IF*K = MIN( M, N )*DO 10 I = 1, K** Generate elementary reflector H(i) to annihilate A(i,i+1:n)*CALL DLARFG( N-I+1, A( I, I ), A( I, MIN( I+1, N ) ), LDA,$ TAU( I ) )IF( I.LT.M ) THEN** Apply H(i) to A(i+1:m,i:n) from the right*AII = A( I, I )A( I, I ) = ONECALL DLARF( 'Right', M-I, N-I+1, A( I, I ), LDA, TAU( I ),$ A( I+1, I ), LDA, WORK )A( I, I ) = AIIEND IF10 CONTINUERETURN** End of DGELQ2*ENDSUBROUTINE DGELQF( M, N, A, LDA, TAU, WORK, LWORK, INFO )** -- LAPACK routine (version 3.0) --* Univ. of Tennessee, Univ. of California Berkeley, NAG Ltd.,* Courant Institute, Argonne National Lab, and Rice University* June 30, 1999** .. Scalar Arguments ..INTEGER INFO, LDA, LWORK, M, N* ..* .. Array Arguments ..DOUBLE PRECISION A( LDA, * ), TAU( * ), WORK( * )* ..** Purpose* =======** DGELQF computes an LQ factorization of a real M-by-N matrix A:* A = L * 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.** A (input/output) DOUBLE PRECISION array, dimension (LDA,N)* On entry, the M-by-N matrix A.* On exit, the elements on and below the diagonal of the array* contain the m-by-min(m,n) lower trapezoidal matrix L (L is* lower triangular if m <= n); the elements above the diagonal,* with the array TAU, represent the orthogonal matrix Q as a* product of elementary reflectors (see Further Details).** LDA (input) INTEGER* The leading dimension of the array A. LDA >= max(1,M).** TAU (output) DOUBLE PRECISION array, dimension (min(M,N))* The scalar factors of the elementary reflectors (see Further* Details).** WORK (workspace/output) DOUBLE PRECISION array, dimension (LWORK)* On exit, if INFO = 0, WORK(1) returns the optimal LWORK.** LWORK (input) INTEGER* The dimension of the array WORK. LWORK >= max(1,M).* For optimum performance LWORK >= M*NB, where NB is the* optimal blocksize.** If LWORK = -1, then a workspace query is assumed; the routine* only calculates the optimal size of the WORK array, returns* this value as the first entry of the WORK array, and no error* message related to LWORK is issued by XERBLA.** INFO (output) INTEGER* = 0: successful exit* < 0: if INFO = -i, the i-th argument had an illegal value** Further Details* ===============** The matrix Q is represented as a product of elementary reflectors** Q = H(k) . . . H(2) H(1), where k = min(m,n).** Each H(i) has the form** H(i) = I - tau * v * v'** where tau is a real scalar, and v is a real vector with* v(1:i-1) = 0 and v(i) = 1; v(i+1:n) is stored on exit in A(i,i+1:n),* and tau in TAU(i).** =====================================================================** .. Local Scalars ..LOGICAL LQUERYINTEGER I, IB, IINFO, IWS, K, LDWORK, LWKOPT, NB,$ NBMIN, NX* ..* .. External Subroutines ..EXTERNAL DGELQ2, DLARFB, DLARFT, XERBLA* ..* .. Intrinsic Functions ..INTRINSIC MAX, MIN* ..* .. External Functions ..INTEGER ILAENVEXTERNAL ILAENV* ..* .. Executable Statements ..** Test the input arguments*INFO = 0NB = ILAENV( 1, 'DGELQF', ' ', M, N, -1, -1 )LWKOPT = M*NBWORK( 1 ) = LWKOPTLQUERY = ( LWORK.EQ.-1 )IF( M.LT.0 ) THENINFO = -1ELSE IF( N.LT.0 ) THENINFO = -2ELSE IF( LDA.LT.MAX( 1, M ) ) THENINFO = -4ELSE IF( LWORK.LT.MAX( 1, M ) .AND. .NOT.LQUERY ) THENINFO = -7END IFIF( INFO.NE.0 ) THENCALL XERBLA( 'DGELQF', -INFO )RETURNELSE IF( LQUERY ) THENRETURNEND IF** Quick return if possible*K = MIN( M, N )IF( K.EQ.0 ) THENWORK( 1 ) = 1RETURNEND IF*NBMIN = 2NX = 0IWS = MIF( NB.GT.1 .AND. NB.LT.K ) THEN** Determine when to cross over from blocked to unblocked code.*NX = MAX( 0, ILAENV( 3, 'DGELQF', ' ', M, N, -1, -1 ) )IF( NX.LT.K ) THEN** Determine if workspace is large enough for blocked code.*LDWORK = MIWS = LDWORK*NBIF( LWORK.LT.IWS ) THEN** Not enough workspace to use optimal NB: reduce NB and* determine the minimum value of NB.*NB = LWORK / LDWORKNBMIN = MAX( 2, ILAENV( 2, 'DGELQF', ' ', M, N, -1,$ -1 ) )END IFEND IFEND IF*IF( NB.GE.NBMIN .AND. NB.LT.K .AND. NX.LT.K ) THEN** Use blocked code initially*DO 10 I = 1, K - NX, NBIB = MIN( K-I+1, NB )** Compute the LQ factorization of the current block* A(i:i+ib-1,i:n)*CALL DGELQ2( IB, N-I+1, A( I, I ), LDA, TAU( I ), WORK,$ IINFO )IF( I+IB.LE.M ) THEN** Form the triangular factor of the block reflector* H = H(i) H(i+1) . . . H(i+ib-1)*CALL DLARFT( 'Forward', 'Rowwise', N-I+1, IB, A( I, I ),$ LDA, TAU( I ), WORK, LDWORK )** Apply H to A(i+ib:m,i:n) from the right*CALL DLARFB( 'Right', 'No transpose', 'Forward',$ 'Rowwise', M-I-IB+1, N-I+1, IB, A( I, I ),$ LDA, WORK, LDWORK, A( I+IB, I ), LDA,$ WORK( IB+1 ), LDWORK )END IF10 CONTINUEELSEI = 1END IF** Use unblocked code to factor the last or only block.*IF( I.LE.K )$ CALL DGELQ2( M-I+1, N-I+1, A( I, I ), LDA, TAU( I ), WORK,$ IINFO )*WORK( 1 ) = IWSRETURN** End of DGELQF*ENDSUBROUTINE DGEQR2( M, N, A, LDA, TAU, WORK, INFO )** -- LAPACK routine (version 3.0) --* Univ. of Tennessee, Univ. of California Berkeley, NAG Ltd.,* Courant Institute, Argonne National Lab, and Rice University* February 29, 1992** .. Scalar Arguments ..INTEGER INFO, LDA, M, N* ..* .. Array Arguments ..DOUBLE PRECISION A( LDA, * ), TAU( * ), WORK( * )* ..** Purpose* =======** DGEQR2 computes a QR factorization of a real m by n matrix A:* A = Q * R.** Arguments* =========** M (input) INTEGER* The number of rows of the matrix A. M >= 0.** N (input) INTEGER* The number of columns of the matrix A. N >= 0.** A (input/output) DOUBLE PRECISION array, dimension (LDA,N)* On entry, the m by n matrix A.* On exit, the elements on and above the diagonal of the array* contain the min(m,n) by n upper trapezoidal matrix R (R is* upper triangular if m >= n); the elements below the diagonal,* with the array TAU, represent the orthogonal matrix Q as a* product of elementary reflectors (see Further Details).** LDA (input) INTEGER* The leading dimension of the array A. LDA >= max(1,M).** TAU (output) DOUBLE PRECISION array, dimension (min(M,N))* The scalar factors of the elementary reflectors (see Further* Details).** WORK (workspace) DOUBLE PRECISION array, dimension (N)** INFO (output) INTEGER* = 0: successful exit* < 0: if INFO = -i, the i-th argument had an illegal value** Further Details* ===============** The matrix Q is represented as a product of elementary reflectors** Q = H(1) H(2) . . . H(k), where k = min(m,n).** Each H(i) has the form** H(i) = I - tau * v * v'** where tau is a real scalar, and v is a real vector with* v(1:i-1) = 0 and v(i) = 1; v(i+1:m) is stored on exit in A(i+1:m,i),* and tau in TAU(i).** =====================================================================** .. Parameters ..DOUBLE PRECISION ONEPARAMETER ( ONE = 1.0D+0 )* ..* .. Local Scalars ..INTEGER I, KDOUBLE PRECISION AII* ..* .. External Subroutines ..EXTERNAL DLARF, DLARFG, XERBLA* ..* .. Intrinsic Functions ..INTRINSIC MAX, MIN* ..* .. Executable Statements ..** Test the input arguments*INFO = 0IF( M.LT.0 ) THENINFO = -1ELSE IF( N.LT.0 ) THENINFO = -2ELSE IF( LDA.LT.MAX( 1, M ) ) THENINFO = -4END IFIF( INFO.NE.0 ) THENCALL XERBLA( 'DGEQR2', -INFO )RETURNEND IF*K = MIN( M, N )*DO 10 I = 1, K** Generate elementary reflector H(i) to annihilate A(i+1:m,i)*CALL DLARFG( M-I+1, A( I, I ), A( MIN( I+1, M ), I ), 1,$ TAU( I ) )IF( I.LT.N ) THEN** Apply H(i) to A(i:m,i+1:n) from the left*AII = A( I, I )A( I, I ) = ONECALL DLARF( 'Left', M-I+1, N-I, A( I, I ), 1, TAU( I ),$ A( I, I+1 ), LDA, WORK )A( I, I ) = AIIEND IF10 CONTINUERETURN** End of DGEQR2*ENDSUBROUTINE DGEQRF( M, N, A, LDA, TAU, WORK, LWORK, INFO )** -- LAPACK routine (version 3.0) --* Univ. of Tennessee, Univ. of California Berkeley, NAG Ltd.,* Courant Institute, Argonne National Lab, and Rice University* June 30, 1999** .. Scalar Arguments ..INTEGER INFO, LDA, LWORK, M, N* ..* .. Array Arguments ..DOUBLE PRECISION A( LDA, * ), TAU( * ), WORK( * )* ..** Purpose* =======** DGEQRF computes a QR factorization of a real M-by-N matrix A:* A = Q * R.** Arguments* =========** M (input) INTEGER* The number of rows of the matrix A. M >= 0.** N (input) INTEGER* The number of columns of the matrix A. N >= 0.** A (input/output) DOUBLE PRECISION array, dimension (LDA,N)* On entry, the M-by-N matrix A.* On exit, the elements on and above the diagonal of the array* contain the min(M,N)-by-N upper trapezoidal matrix R (R is* upper triangular if m >= n); the elements below the diagonal,* with the array TAU, represent the orthogonal matrix Q as a* product of min(m,n) elementary reflectors (see Further* Details).** LDA (input) INTEGER* The leading dimension of the array A. LDA >= max(1,M).** TAU (output) DOUBLE PRECISION array, dimension (min(M,N))* The scalar factors of the elementary reflectors (see Further* Details).** WORK (workspace/output) DOUBLE PRECISION array, dimension (LWORK)* On exit, if INFO = 0, WORK(1) returns the optimal LWORK.** LWORK (input) INTEGER* The dimension of the array WORK. LWORK >= max(1,N).* For optimum performance LWORK >= N*NB, where NB is* the optimal blocksize.** If LWORK = -1, then a workspace query is assumed; the routine* only calculates the optimal size of the WORK array, returns* this value as the first entry of the WORK array, and no error* message related to LWORK is issued by XERBLA.** INFO (output) INTEGER* = 0: successful exit* < 0: if INFO = -i, the i-th argument had an illegal value** Further Details* ===============** The matrix Q is represented as a product of elementary reflectors** Q = H(1) H(2) . . . H(k), where k = min(m,n).** Each H(i) has the form** H(i) = I - tau * v * v'** where tau is a real scalar, and v is a real vector with* v(1:i-1) = 0 and v(i) = 1; v(i+1:m) is stored on exit in A(i+1:m,i),* and tau in TAU(i).** =====================================================================** .. Local Scalars ..LOGICAL LQUERYINTEGER I, IB, IINFO, IWS, K, LDWORK, LWKOPT, NB,$ NBMIN, NX* ..* .. External Subroutines ..EXTERNAL DGEQR2, DLARFB, DLARFT, XERBLA* ..* .. Intrinsic Functions ..INTRINSIC MAX, MIN* ..* .. External Functions ..INTEGER ILAENVEXTERNAL ILAENV* ..* .. Executable Statements ..** Test the input arguments*INFO = 0NB = ILAENV( 1, 'DGEQRF', ' ', M, N, -1, -1 )LWKOPT = N*NBWORK( 1 ) = LWKOPTLQUERY = ( LWORK.EQ.-1 )IF( M.LT.0 ) THENINFO = -1ELSE IF( N.LT.0 ) THENINFO = -2ELSE IF( LDA.LT.MAX( 1, M ) ) THENINFO = -4ELSE IF( LWORK.LT.MAX( 1, N ) .AND. .NOT.LQUERY ) THENINFO = -7END IFIF( INFO.NE.0 ) THENCALL XERBLA( 'DGEQRF', -INFO )RETURNELSE IF( LQUERY ) THENRETURNEND IF** Quick return if possible*K = MIN( M, N )IF( K.EQ.0 ) THENWORK( 1 ) = 1RETURNEND IF*NBMIN = 2NX = 0IWS = NIF( NB.GT.1 .AND. NB.LT.K ) THEN** Determine when to cross over from blocked to unblocked code.*NX = MAX( 0, ILAENV( 3, 'DGEQRF', ' ', M, N, -1, -1 ) )IF( NX.LT.K ) THEN** Determine if workspace is large enough for blocked code.*LDWORK = NIWS = LDWORK*NBIF( LWORK.LT.IWS ) THEN** Not enough workspace to use optimal NB: reduce NB and* determine the minimum value of NB.*NB = LWORK / LDWORKNBMIN = MAX( 2, ILAENV( 2, 'DGEQRF', ' ', M, N, -1,$ -1 ) )END IFEND IFEND IF*IF( NB.GE.NBMIN .AND. NB.LT.K .AND. NX.LT.K ) THEN** Use blocked code initially*DO 10 I = 1, K - NX, NBIB = MIN( K-I+1, NB )** Compute the QR factorization of the current block* A(i:m,i:i+ib-1)*CALL DGEQR2( M-I+1, IB, A( I, I ), LDA, TAU( I ), WORK,$ IINFO )IF( I+IB.LE.N ) THEN** Form the triangular factor of the block reflector* H = H(i) H(i+1) . . . H(i+ib-1)*CALL DLARFT( 'Forward', 'Columnwise', M-I+1, IB,$ A( I, I ), LDA, TAU( I ), WORK, LDWORK )** Apply H' to A(i:m,i+ib:n) from the left*CALL DLARFB( 'Left', 'Transpose', 'Forward',$ 'Columnwise', M-I+1, N-I-IB+1, IB,$ A( I, I ), LDA, WORK, LDWORK, A( I, I+IB ),$ LDA, WORK( IB+1 ), LDWORK )END IF10 CONTINUEELSEI = 1END IF** Use unblocked code to factor the last or only block.*IF( I.LE.K )$ CALL DGEQR2( M-I+1, N-I+1, A( I, I ), LDA, TAU( I ), WORK,$ IINFO )*WORK( 1 ) = IWSRETURN** End of DGEQRF*ENDSUBROUTINE DGESC2( N, A, LDA, RHS, IPIV, JPIV, SCALE )** -- LAPACK auxiliary 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 LDA, NDOUBLE PRECISION SCALE* ..* .. Array Arguments ..INTEGER IPIV( * ), JPIV( * )DOUBLE PRECISION A( LDA, * ), RHS( * )* ..** Purpose* =======** DGESC2 solves a system of linear equations** A * X = scale* RHS** with a general N-by-N matrix A using the LU factorization with* complete pivoting computed by DGETC2.** Arguments* =========** N (input) INTEGER* The order of the matrix A.** A (input) DOUBLE PRECISION array, dimension (LDA,N)* On entry, the LU part of the factorization of the n-by-n* matrix A computed by DGETC2: A = P * L * U * Q** LDA (input) INTEGER* The leading dimension of the array A. LDA >= max(1, N).** RHS (input/output) DOUBLE PRECISION array, dimension (N).* On entry, the right hand side vector b.* On exit, the solution vector X.** IPIV (iput) INTEGER array, dimension (N).* The pivot indices; for 1 <= i <= N, row i of the* matrix has been interchanged with row IPIV(i).** JPIV (iput) INTEGER array, dimension (N).* The pivot indices; for 1 <= j <= N, column j of the* matrix has been interchanged with column JPIV(j).** SCALE (output) DOUBLE PRECISION* On exit, SCALE contains the scale factor. SCALE is chosen* 0 <= SCALE <= 1 to prevent owerflow in the solution.** Further Details* ===============** Based on contributions by* Bo Kagstrom and Peter Poromaa, Department of Computing Science,* Umea University, S-901 87 Umea, Sweden.** =====================================================================** .. Parameters ..DOUBLE PRECISION ONE, TWOPARAMETER ( ONE = 1.0D+0, TWO = 2.0D+0 )* ..* .. Local Scalars ..INTEGER I, JDOUBLE PRECISION BIGNUM, EPS, SMLNUM, TEMP* ..* .. External Subroutines ..EXTERNAL DLASWP, DSCAL* ..* .. External Functions ..INTEGER IDAMAXDOUBLE PRECISION DLAMCHEXTERNAL IDAMAX, DLAMCH* ..* .. Intrinsic Functions ..INTRINSIC ABS* ..* .. Executable Statements ..** Set constant to control owerflow*EPS = DLAMCH( 'P' )SMLNUM = DLAMCH( 'S' ) / EPSBIGNUM = ONE / SMLNUMCALL DLABAD( SMLNUM, BIGNUM )** Apply permutations IPIV to RHS*CALL DLASWP( 1, RHS, LDA, 1, N-1, IPIV, 1 )** Solve for L part*DO 20 I = 1, N - 1DO 10 J = I + 1, NRHS( J ) = RHS( J ) - A( J, I )*RHS( I )10 CONTINUE20 CONTINUE** Solve for U part*SCALE = ONE** Check for scaling*I = IDAMAX( N, RHS, 1 )IF( TWO*SMLNUM*ABS( RHS( I ) ).GT.ABS( A( N, N ) ) ) THENTEMP = ( ONE / TWO ) / ABS( RHS( I ) )CALL DSCAL( N, TEMP, RHS( 1 ), 1 )SCALE = SCALE*TEMPEND IF*DO 40 I = N, 1, -1TEMP = ONE / A( I, I )RHS( I ) = RHS( I )*TEMPDO 30 J = I + 1, NRHS( I ) = RHS( I ) - RHS( J )*( A( I, J )*TEMP )30 CONTINUE40 CONTINUE** Apply permutations JPIV to the solution (RHS)*CALL DLASWP( 1, RHS, LDA, 1, N-1, JPIV, -1 )RETURN** End of DGESC2*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* June 30, 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 DHSEQR( JOB, COMPZ, N, ILO, IHI, H, LDH, WR, WI, Z,$ LDZ, WORK, LWORK, INFO )** -- LAPACK routine (version 3.0) --* Univ. of Tennessee, Univ. of California Berkeley, NAG Ltd.,* Courant Institute, Argonne National Lab, and Rice University* June 30, 1999** .. Scalar Arguments ..CHARACTER COMPZ, JOBINTEGER IHI, ILO, INFO, LDH, LDZ, LWORK, N* ..* .. Array Arguments ..DOUBLE PRECISION H( LDH, * ), WI( * ), WORK( * ), WR( * ),$ Z( LDZ, * )* ..** Purpose* =======** DHSEQR computes the eigenvalues of a real upper Hessenberg matrix H* and, optionally, the matrices T and Z from the Schur decomposition* H = Z T Z**T, where T is an upper quasi-triangular matrix (the Schur* form), and Z is the orthogonal matrix of Schur vectors.** Optionally Z may be postmultiplied into an input orthogonal matrix Q,* so that this routine can give the Schur factorization of a matrix A* which has been reduced to the Hessenberg form H by the orthogonal* matrix Q: A = Q*H*Q**T = (QZ)*T*(QZ)**T.** Arguments* =========** JOB (input) CHARACTER*1* = 'E': compute eigenvalues only;* = 'S': compute eigenvalues and the Schur form T.** COMPZ (input) CHARACTER*1* = 'N': no Schur vectors are computed;* = 'I': Z is initialized to the unit matrix and the matrix Z* of Schur vectors of H is returned;* = 'V': Z must contain an orthogonal matrix Q on entry, and* the product Q*Z is returned.** N (input) INTEGER* The order of the matrix H. N >= 0.** ILO (input) INTEGER* IHI (input) INTEGER* It is assumed that H is already upper triangular in rows* and columns 1:ILO-1 and IHI+1:N. ILO and IHI are normally* set by a previous call to DGEBAL, and then passed to SGEHRD* when the matrix output by DGEBAL is reduced to Hessenberg* form. Otherwise ILO and IHI should be set to 1 and N* respectively.* 1 <= ILO <= IHI <= N, if N > 0; ILO=1 and IHI=0, if N=0.** H (input/output) DOUBLE PRECISION array, dimension (LDH,N)* On entry, the upper Hessenberg matrix H.* On exit, if JOB = 'S', H contains the upper quasi-triangular* matrix T from the Schur decomposition (the Schur form);* 2-by-2 diagonal blocks (corresponding to complex conjugate* pairs of eigenvalues) are returned in standard form, with* H(i,i) = H(i+1,i+1) and H(i+1,i)*H(i,i+1) < 0. If JOB = 'E',* the contents of H are unspecified on exit.** LDH (input) INTEGER* The leading dimension of the array H. LDH >= max(1,N).** WR (output) DOUBLE PRECISION array, dimension (N)* WI (output) DOUBLE PRECISION array, dimension (N)* The real and imaginary parts, respectively, of the computed* eigenvalues. If two eigenvalues are computed as a complex* conjugate pair, they are stored in consecutive elements of* WR and WI, say the i-th and (i+1)th, with WI(i) > 0 and* WI(i+1) < 0. If JOB = 'S', the eigenvalues are stored in the* same order as on the diagonal of the Schur form returned in* H, with WR(i) = H(i,i) and, if H(i:i+1,i:i+1) is a 2-by-2* diagonal block, WI(i) = sqrt(H(i+1,i)*H(i,i+1)) and* WI(i+1) = -WI(i).** Z (input/output) DOUBLE PRECISION array, dimension (LDZ,N)* If COMPZ = 'N': Z is not referenced.* If COMPZ = 'I': on entry, Z need not be set, and on exit, Z* contains the orthogonal matrix Z of the Schur vectors of H.* If COMPZ = 'V': on entry Z must contain an N-by-N matrix Q,* which is assumed to be equal to the unit matrix except for* the submatrix Z(ILO:IHI,ILO:IHI); on exit Z contains Q*Z.* Normally Q is the orthogonal matrix generated by DORGHR after* the call to DGEHRD which formed the Hessenberg matrix H.** LDZ (input) INTEGER* The leading dimension of the array Z.* LDZ >= max(1,N) if COMPZ = 'I' or 'V'; LDZ >= 1 otherwise.** 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).** 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, DHSEQR failed to compute all of the* eigenvalues in a total of 30*(IHI-ILO+1) iterations;* elements 1:ilo-1 and i+1:n of WR and WI contain those* eigenvalues which have been successfully computed.** =====================================================================** .. Parameters ..DOUBLE PRECISION ZERO, ONE, TWOPARAMETER ( ZERO = 0.0D+0, ONE = 1.0D+0, TWO = 2.0D+0 )DOUBLE PRECISION CONSTPARAMETER ( CONST = 1.5D+0 )INTEGER NSMAX, LDSPARAMETER ( NSMAX = 15, LDS = NSMAX )* ..* .. Local Scalars ..LOGICAL INITZ, LQUERY, WANTT, WANTZINTEGER I, I1, I2, IERR, II, ITEMP, ITN, ITS, J, K, L,$ MAXB, NH, NR, NS, NVDOUBLE PRECISION ABSW, OVFL, SMLNUM, TAU, TEMP, TST1, ULP, UNFL* ..* .. Local Arrays ..DOUBLE PRECISION S( LDS, NSMAX ), V( NSMAX+1 ), VV( NSMAX+1 )* ..* .. External Functions ..LOGICAL LSAMEINTEGER IDAMAX, ILAENVDOUBLE PRECISION DLAMCH, DLANHS, DLAPY2EXTERNAL LSAME, IDAMAX, ILAENV, DLAMCH, DLANHS, DLAPY2* ..* .. External Subroutines ..EXTERNAL DCOPY, DGEMV, DLACPY, DLAHQR, DLARFG, DLARFX,$ DLASET, DSCAL, XERBLA* ..* .. Intrinsic Functions ..INTRINSIC ABS, MAX, MIN* ..* .. Executable Statements ..** Decode and test the input parameters*WANTT = LSAME( JOB, 'S' )INITZ = LSAME( COMPZ, 'I' )WANTZ = INITZ .OR. LSAME( COMPZ, 'V' )*INFO = 0WORK( 1 ) = MAX( 1, N )LQUERY = ( LWORK.EQ.-1 )IF( .NOT.LSAME( JOB, 'E' ) .AND. .NOT.WANTT ) THENINFO = -1ELSE IF( .NOT.LSAME( COMPZ, 'N' ) .AND. .NOT.WANTZ ) THENINFO = -2ELSE IF( N.LT.0 ) THENINFO = -3ELSE IF( ILO.LT.1 .OR. ILO.GT.MAX( 1, N ) ) THENINFO = -4ELSE IF( IHI.LT.MIN( ILO, N ) .OR. IHI.GT.N ) THENINFO = -5ELSE IF( LDH.LT.MAX( 1, N ) ) THENINFO = -7ELSE IF( LDZ.LT.1 .OR. WANTZ .AND. LDZ.LT.MAX( 1, N ) ) THENINFO = -11ELSE IF( LWORK.LT.MAX( 1, N ) .AND. .NOT.LQUERY ) THENINFO = -13END IFIF( INFO.NE.0 ) THENCALL XERBLA( 'DHSEQR', -INFO )RETURNELSE IF( LQUERY ) THENRETURNEND IF** Initialize Z, if necessary*IF( INITZ )$ CALL DLASET( 'Full', N, N, ZERO, ONE, Z, LDZ )** Store the eigenvalues isolated by DGEBAL.*DO 10 I = 1, ILO - 1WR( I ) = H( I, I )WI( I ) = ZERO10 CONTINUEDO 20 I = IHI + 1, NWR( I ) = H( I, I )WI( I ) = ZERO20 CONTINUE** Quick return if possible.*IF( N.EQ.0 )$ RETURNIF( ILO.EQ.IHI ) THENWR( ILO ) = H( ILO, ILO )WI( ILO ) = ZERORETURNEND IF** Set rows and columns ILO to IHI to zero below the first* subdiagonal.*DO 40 J = ILO, IHI - 2DO 30 I = J + 2, NH( I, J ) = ZERO30 CONTINUE40 CONTINUENH = IHI - ILO + 1** Determine the order of the multi-shift QR algorithm to be used.*NS = ILAENV( 4, 'DHSEQR', JOB // COMPZ, N, ILO, IHI, -1 )MAXB = ILAENV( 8, 'DHSEQR', JOB // COMPZ, N, ILO, IHI, -1 )IF( NS.LE.2 .OR. NS.GT.NH .OR. MAXB.GE.NH ) THEN** Use the standard double-shift algorithm*CALL DLAHQR( WANTT, WANTZ, N, ILO, IHI, H, LDH, WR, WI, ILO,$ IHI, Z, LDZ, INFO )RETURNEND IFMAXB = MAX( 3, MAXB )NS = MIN( NS, MAXB, NSMAX )** Now 2 < NS <= MAXB < NH.** Set machine-dependent constants for the stopping criterion.* If norm(H) <= sqrt(OVFL), overflow should not occur.*UNFL = DLAMCH( 'Safe minimum' )OVFL = ONE / UNFLCALL DLABAD( UNFL, OVFL )ULP = DLAMCH( 'Precision' )SMLNUM = UNFL*( NH / ULP )** I1 and I2 are the indices of the first row and last column of H* to which transformations must be applied. If eigenvalues only are* being computed, I1 and I2 are set inside the main loop.*IF( WANTT ) THENI1 = 1I2 = NEND IF** ITN is the total number of multiple-shift QR iterations allowed.*ITN = 30*NH** The main loop begins here. I is the loop index and decreases from* IHI to ILO in steps of at most MAXB. Each iteration of the loop* works with the active submatrix in rows and columns L to I.* Eigenvalues I+1 to IHI have already converged. Either L = ILO or* H(L,L-1) is negligible so that the matrix splits.*I = IHI50 CONTINUEL = ILOIF( I.LT.ILO )$ GO TO 170** Perform multiple-shift QR iterations on rows and columns ILO to I* until a submatrix of order at most MAXB splits off at the bottom* because a subdiagonal element has become negligible.*DO 150 ITS = 0, ITN** Look for a single small subdiagonal element.*DO 60 K = I, L + 1, -1TST1 = ABS( H( K-1, K-1 ) ) + ABS( H( K, K ) )IF( TST1.EQ.ZERO )$ TST1 = DLANHS( '1', I-L+1, H( L, L ), LDH, WORK )IF( ABS( H( K, K-1 ) ).LE.MAX( ULP*TST1, SMLNUM ) )$ GO TO 7060 CONTINUE70 CONTINUEL = KIF( L.GT.ILO ) THEN** H(L,L-1) is negligible.*H( L, L-1 ) = ZEROEND IF** Exit from loop if a submatrix of order <= MAXB has split off.*IF( L.GE.I-MAXB+1 )$ GO TO 160** Now the active submatrix is in rows and columns L to I. If* eigenvalues only are being computed, only the active submatrix* need be transformed.*IF( .NOT.WANTT ) THENI1 = LI2 = IEND IF*IF( ITS.EQ.20 .OR. ITS.EQ.30 ) THEN** Exceptional shifts.*DO 80 II = I - NS + 1, IWR( II ) = CONST*( ABS( H( II, II-1 ) )+$ ABS( H( II, II ) ) )WI( II ) = ZERO80 CONTINUEELSE** Use eigenvalues of trailing submatrix of order NS as shifts.*CALL DLACPY( 'Full', NS, NS, H( I-NS+1, I-NS+1 ), LDH, S,$ LDS )CALL DLAHQR( .FALSE., .FALSE., NS, 1, NS, S, LDS,$ WR( I-NS+1 ), WI( I-NS+1 ), 1, NS, Z, LDZ,$ IERR )IF( IERR.GT.0 ) THEN** If DLAHQR failed to compute all NS eigenvalues, use the* unconverged diagonal elements as the remaining shifts.*DO 90 II = 1, IERRWR( I-NS+II ) = S( II, II )WI( I-NS+II ) = ZERO90 CONTINUEEND IFEND IF** Form the first column of (G-w(1)) (G-w(2)) . . . (G-w(ns))* where G is the Hessenberg submatrix H(L:I,L:I) and w is* the vector of shifts (stored in WR and WI). The result is* stored in the local array V.*V( 1 ) = ONEDO 100 II = 2, NS + 1V( II ) = ZERO100 CONTINUENV = 1DO 120 J = I - NS + 1, IIF( WI( J ).GE.ZERO ) THENIF( WI( J ).EQ.ZERO ) THEN** real shift*CALL DCOPY( NV+1, V, 1, VV, 1 )CALL DGEMV( 'No transpose', NV+1, NV, ONE, H( L, L ),$ LDH, VV, 1, -WR( J ), V, 1 )NV = NV + 1ELSE IF( WI( J ).GT.ZERO ) THEN** complex conjugate pair of shifts*CALL DCOPY( NV+1, V, 1, VV, 1 )CALL DGEMV( 'No transpose', NV+1, NV, ONE, H( L, L ),$ LDH, V, 1, -TWO*WR( J ), VV, 1 )ITEMP = IDAMAX( NV+1, VV, 1 )TEMP = ONE / MAX( ABS( VV( ITEMP ) ), SMLNUM )CALL DSCAL( NV+1, TEMP, VV, 1 )ABSW = DLAPY2( WR( J ), WI( J ) )TEMP = ( TEMP*ABSW )*ABSWCALL DGEMV( 'No transpose', NV+2, NV+1, ONE,$ H( L, L ), LDH, VV, 1, TEMP, V, 1 )NV = NV + 2END IF** Scale V(1:NV) so that max(abs(V(i))) = 1. If V is zero,* reset it to the unit vector.*ITEMP = IDAMAX( NV, V, 1 )TEMP = ABS( V( ITEMP ) )IF( TEMP.EQ.ZERO ) THENV( 1 ) = ONEDO 110 II = 2, NVV( II ) = ZERO110 CONTINUEELSETEMP = MAX( TEMP, SMLNUM )CALL DSCAL( NV, ONE / TEMP, V, 1 )END IFEND IF120 CONTINUE** Multiple-shift QR step*DO 140 K = L, I - 1** The first iteration of this loop determines a reflection G* from the vector V and applies it from left and right to H,* thus creating a nonzero bulge below the subdiagonal.** Each subsequent iteration determines a reflection G to* restore the Hessenberg form in the (K-1)th column, and thus* chases the bulge one step toward the bottom of the active* submatrix. NR is the order of G.*NR = MIN( NS+1, I-K+1 )IF( K.GT.L )$ CALL DCOPY( NR, H( K, K-1 ), 1, V, 1 )CALL DLARFG( NR, V( 1 ), V( 2 ), 1, TAU )IF( K.GT.L ) THENH( K, K-1 ) = V( 1 )DO 130 II = K + 1, IH( II, K-1 ) = ZERO130 CONTINUEEND IFV( 1 ) = ONE** Apply G from the left to transform the rows of the matrix in* columns K to I2.*CALL DLARFX( 'Left', NR, I2-K+1, V, TAU, H( K, K ), LDH,$ WORK )** Apply G from the right to transform the columns of the* matrix in rows I1 to min(K+NR,I).*CALL DLARFX( 'Right', MIN( K+NR, I )-I1+1, NR, V, TAU,$ H( I1, K ), LDH, WORK )*IF( WANTZ ) THEN** Accumulate transformations in the matrix Z*CALL DLARFX( 'Right', NH, NR, V, TAU, Z( ILO, K ), LDZ,$ WORK )END IF140 CONTINUE*150 CONTINUE** Failure to converge in remaining number of iterations*INFO = IRETURN*160 CONTINUE** A submatrix of order <= MAXB in rows and columns L to I has split* off. Use the double-shift QR algorithm to handle it.*CALL DLAHQR( WANTT, WANTZ, N, L, I, H, LDH, WR, WI, ILO, IHI, Z,$ LDZ, INFO )IF( INFO.GT.0 )$ RETURN** Decrement number of remaining iterations, and return to start of* the main loop with a new value of I.*ITN = ITN - ITSI = L - 1GO TO 50*170 CONTINUEWORK( 1 ) = MAX( 1, N )RETURN** End of DHSEQR*ENDSUBROUTINE DLABAD( SMALL, LARGE )** -- LAPACK auxiliary routine (version 3.0) --* Univ. of Tennessee, Univ. of California Berkeley, NAG Ltd.,* Courant Institute, Argonne National Lab, and Rice University* October 31, 1992** .. Scalar Arguments ..DOUBLE PRECISION LARGE, SMALL* ..** Purpose* =======** DLABAD takes as input the values computed by DLAMCH for underflow and* overflow, and returns the square root of each of these values if the* log of LARGE is sufficiently large. This subroutine is intended to* identify machines with a large exponent range, such as the Crays, and* redefine the underflow and overflow limits to be the square roots of* the values computed by DLAMCH. This subroutine is needed because* DLAMCH does not compensate for poor arithmetic in the upper half of* the exponent range, as is found on a Cray.** Arguments* =========** SMALL (input/output) DOUBLE PRECISION* On entry, the underflow threshold as computed by DLAMCH.* On exit, if LOG10(LARGE) is sufficiently large, the square* root of SMALL, otherwise unchanged.** LARGE (input/output) DOUBLE PRECISION* On entry, the overflow threshold as computed by DLAMCH.* On exit, if LOG10(LARGE) is sufficiently large, the square* root of LARGE, otherwise unchanged.** =====================================================================** .. Intrinsic Functions ..INTRINSIC LOG10, SQRT* ..* .. Executable Statements ..** If it looks like we're on a Cray, take the square root of* SMALL and LARGE to avoid overflow and underflow problems.*IF( LOG10( LARGE ).GT.2000.D0 ) THENSMALL = SQRT( SMALL )LARGE = SQRT( LARGE )END IF*RETURN** End of DLABAD*ENDSUBROUTINE DLABRD( M, N, NB, A, LDA, D, E, TAUQ, TAUP, X, LDX, Y,$ LDY )** -- LAPACK auxiliary routine (version 3.0) --* Univ. of Tennessee, Univ. of California Berkeley, NAG Ltd.,* Courant Institute, Argonne National Lab, and Rice University* February 29, 1992** .. Scalar Arguments ..INTEGER LDA, LDX, LDY, M, N, NB* ..* .. Array Arguments ..DOUBLE PRECISION A( LDA, * ), D( * ), E( * ), TAUP( * ),$ TAUQ( * ), X( LDX, * ), Y( LDY, * )* ..** Purpose* =======** DLABRD reduces the first NB rows and columns of a real general* m by n matrix A to upper or lower bidiagonal form by an orthogonal* transformation Q' * A * P, and returns the matrices X and Y which* are needed to apply the transformation to the unreduced part of A.** If m >= n, A is reduced to upper bidiagonal form; if m < n, to lower* bidiagonal form.** This is an auxiliary routine called by DGEBRD** Arguments* =========** M (input) INTEGER* The number of rows in the matrix A.** N (input) INTEGER* The number of columns in the matrix A.** NB (input) INTEGER* The number of leading rows and columns of A to be reduced.** A (input/output) DOUBLE PRECISION array, dimension (LDA,N)* On entry, the m by n general matrix to be reduced.* On exit, the first NB rows and columns of the matrix are* overwritten; the rest of the array is unchanged.* If m >= n, elements on and below the diagonal in the first NB* columns, with the array TAUQ, represent the orthogonal* matrix Q as a product of elementary reflectors; and* elements above the diagonal in the first NB rows, with the* array TAUP, represent the orthogonal matrix P as a product* of elementary reflectors.* If m < n, elements below the diagonal in the first NB* columns, with the array TAUQ, represent the orthogonal* matrix Q as a product of elementary reflectors, and* elements on and above the diagonal in the first NB rows,* with the array TAUP, represent the orthogonal matrix P as* a product of elementary reflectors.* See Further Details.** LDA (input) INTEGER* The leading dimension of the array A. LDA >= max(1,M).** D (output) DOUBLE PRECISION array, dimension (NB)* The diagonal elements of the first NB rows and columns of* the reduced matrix. D(i) = A(i,i).** E (output) DOUBLE PRECISION array, dimension (NB)* The off-diagonal elements of the first NB rows and columns of* the reduced matrix.** TAUQ (output) DOUBLE PRECISION array dimension (NB)* The scalar factors of the elementary reflectors which* represent the orthogonal matrix Q. See Further Details.** TAUP (output) DOUBLE PRECISION array, dimension (NB)* The scalar factors of the elementary reflectors which* represent the orthogonal matrix P. See Further Details.** X (output) DOUBLE PRECISION array, dimension (LDX,NB)* The m-by-nb matrix X required to update the unreduced part* of A.** LDX (input) INTEGER* The leading dimension of the array X. LDX >= M.** Y (output) DOUBLE PRECISION array, dimension (LDY,NB)* The n-by-nb matrix Y required to update the unreduced part* of A.** LDY (output) INTEGER* The leading dimension of the array Y. LDY >= N.** Further Details* ===============** The matrices Q and P are represented as products of elementary* reflectors:** Q = H(1) H(2) . . . H(nb) and P = G(1) G(2) . . . G(nb)** Each H(i) and G(i) has the form:** H(i) = I - tauq * v * v' and G(i) = I - taup * u * u'** where tauq and taup are real scalars, and v and u are real vectors.** If m >= n, v(1:i-1) = 0, v(i) = 1, and v(i:m) is stored on exit in* A(i:m,i); u(1:i) = 0, u(i+1) = 1, and u(i+1:n) is stored on exit in* A(i,i+1:n); tauq is stored in TAUQ(i) and taup in TAUP(i).** If m < n, v(1:i) = 0, v(i+1) = 1, and v(i+1:m) is stored on exit in* A(i+2:m,i); u(1:i-1) = 0, u(i) = 1, and u(i:n) is stored on exit in* A(i,i+1:n); tauq is stored in TAUQ(i) and taup in TAUP(i).** The elements of the vectors v and u together form the m-by-nb matrix* V and the nb-by-n matrix U' which are needed, with X and Y, to apply* the transformation to the unreduced part of the matrix, using a block* update of the form: A := A - V*Y' - X*U'.** The contents of A on exit are illustrated by the following examples* with nb = 2:** m = 6 and n = 5 (m > n): m = 5 and n = 6 (m < n):** ( 1 1 u1 u1 u1 ) ( 1 u1 u1 u1 u1 u1 )* ( v1 1 1 u2 u2 ) ( 1 1 u2 u2 u2 u2 )* ( v1 v2 a a a ) ( v1 1 a a a a )* ( v1 v2 a a a ) ( v1 v2 a a a a )* ( v1 v2 a a a ) ( v1 v2 a a a a )* ( v1 v2 a a a )** where a denotes an element of the original matrix which is unchanged,* vi denotes an element of the vector defining H(i), and ui an element* of the vector defining G(i).** =====================================================================** .. Parameters ..DOUBLE PRECISION ZERO, ONEPARAMETER ( ZERO = 0.0D0, ONE = 1.0D0 )* ..* .. Local Scalars ..INTEGER I* ..* .. External Subroutines ..EXTERNAL DGEMV, DLARFG, DSCAL* ..* .. Intrinsic Functions ..INTRINSIC MIN* ..* .. Executable Statements ..** Quick return if possible*IF( M.LE.0 .OR. N.LE.0 )$ RETURN*IF( M.GE.N ) THEN** Reduce to upper bidiagonal form*DO 10 I = 1, NB** Update A(i:m,i)*CALL DGEMV( 'No transpose', M-I+1, I-1, -ONE, A( I, 1 ),$ LDA, Y( I, 1 ), LDY, ONE, A( I, I ), 1 )CALL DGEMV( 'No transpose', M-I+1, I-1, -ONE, X( I, 1 ),$ LDX, A( 1, I ), 1, ONE, A( I, I ), 1 )** Generate reflection Q(i) to annihilate A(i+1:m,i)*CALL DLARFG( M-I+1, A( I, I ), A( MIN( I+1, M ), I ), 1,$ TAUQ( I ) )D( I ) = A( I, I )IF( I.LT.N ) THENA( I, I ) = ONE** Compute Y(i+1:n,i)*CALL DGEMV( 'Transpose', M-I+1, N-I, ONE, A( I, I+1 ),$ LDA, A( I, I ), 1, ZERO, Y( I+1, I ), 1 )CALL DGEMV( 'Transpose', M-I+1, I-1, ONE, A( I, 1 ), LDA,$ A( I, I ), 1, ZERO, Y( 1, I ), 1 )CALL DGEMV( 'No transpose', N-I, I-1, -ONE, Y( I+1, 1 ),$ LDY, Y( 1, I ), 1, ONE, Y( I+1, I ), 1 )CALL DGEMV( 'Transpose', M-I+1, I-1, ONE, X( I, 1 ), LDX,$ A( I, I ), 1, ZERO, Y( 1, I ), 1 )CALL DGEMV( 'Transpose', I-1, N-I, -ONE, A( 1, I+1 ),$ LDA, Y( 1, I ), 1, ONE, Y( I+1, I ), 1 )CALL DSCAL( N-I, TAUQ( I ), Y( I+1, I ), 1 )** Update A(i,i+1:n)*CALL DGEMV( 'No transpose', N-I, I, -ONE, Y( I+1, 1 ),$ LDY, A( I, 1 ), LDA, ONE, A( I, I+1 ), LDA )CALL DGEMV( 'Transpose', I-1, N-I, -ONE, A( 1, I+1 ),$ LDA, X( I, 1 ), LDX, ONE, A( I, I+1 ), LDA )** Generate reflection P(i) to annihilate A(i,i+2:n)*CALL DLARFG( N-I, A( I, I+1 ), A( I, MIN( I+2, N ) ),$ LDA, TAUP( I ) )E( I ) = A( I, I+1 )A( I, I+1 ) = ONE** Compute X(i+1:m,i)*CALL DGEMV( 'No transpose', M-I, N-I, ONE, A( I+1, I+1 ),$ LDA, A( I, I+1 ), LDA, ZERO, X( I+1, I ), 1 )CALL DGEMV( 'Transpose', N-I, I, ONE, Y( I+1, 1 ), LDY,$ A( I, I+1 ), LDA, ZERO, X( 1, I ), 1 )CALL DGEMV( 'No transpose', M-I, I, -ONE, A( I+1, 1 ),$ LDA, X( 1, I ), 1, ONE, X( I+1, I ), 1 )CALL DGEMV( 'No transpose', I-1, N-I, ONE, A( 1, I+1 ),$ LDA, A( I, I+1 ), LDA, ZERO, X( 1, I ), 1 )CALL DGEMV( 'No transpose', M-I, I-1, -ONE, X( I+1, 1 ),$ LDX, X( 1, I ), 1, ONE, X( I+1, I ), 1 )CALL DSCAL( M-I, TAUP( I ), X( I+1, I ), 1 )END IF10 CONTINUEELSE** Reduce to lower bidiagonal form*DO 20 I = 1, NB** Update A(i,i:n)*CALL DGEMV( 'No transpose', N-I+1, I-1, -ONE, Y( I, 1 ),$ LDY, A( I, 1 ), LDA, ONE, A( I, I ), LDA )CALL DGEMV( 'Transpose', I-1, N-I+1, -ONE, A( 1, I ), LDA,$ X( I, 1 ), LDX, ONE, A( I, I ), LDA )** Generate reflection P(i) to annihilate A(i,i+1:n)*CALL DLARFG( N-I+1, A( I, I ), A( I, MIN( I+1, N ) ), LDA,$ TAUP( I ) )D( I ) = A( I, I )IF( I.LT.M ) THENA( I, I ) = ONE** Compute X(i+1:m,i)*CALL DGEMV( 'No transpose', M-I, N-I+1, ONE, A( I+1, I ),$ LDA, A( I, I ), LDA, ZERO, X( I+1, I ), 1 )CALL DGEMV( 'Transpose', N-I+1, I-1, ONE, Y( I, 1 ), LDY,$ A( I, I ), LDA, ZERO, X( 1, I ), 1 )CALL DGEMV( 'No transpose', M-I, I-1, -ONE, A( I+1, 1 ),$ LDA, X( 1, I ), 1, ONE, X( I+1, I ), 1 )CALL DGEMV( 'No transpose', I-1, N-I+1, ONE, A( 1, I ),$ LDA, A( I, I ), LDA, ZERO, X( 1, I ), 1 )CALL DGEMV( 'No transpose', M-I, I-1, -ONE, X( I+1, 1 ),$ LDX, X( 1, I ), 1, ONE, X( I+1, I ), 1 )CALL DSCAL( M-I, TAUP( I ), X( I+1, I ), 1 )** Update A(i+1:m,i)*CALL DGEMV( 'No transpose', M-I, I-1, -ONE, A( I+1, 1 ),$ LDA, Y( I, 1 ), LDY, ONE, A( I+1, I ), 1 )CALL DGEMV( 'No transpose', M-I, I, -ONE, X( I+1, 1 ),$ LDX, A( 1, I ), 1, ONE, A( I+1, I ), 1 )** Generate reflection Q(i) to annihilate A(i+2:m,i)*CALL DLARFG( M-I, A( I+1, I ), A( MIN( I+2, M ), I ), 1,$ TAUQ( I ) )E( I ) = A( I+1, I )A( I+1, I ) = ONE** Compute Y(i+1:n,i)*CALL DGEMV( 'Transpose', M-I, N-I, ONE, A( I+1, I+1 ),$ LDA, A( I+1, I ), 1, ZERO, Y( I+1, I ), 1 )CALL DGEMV( 'Transpose', M-I, I-1, ONE, A( I+1, 1 ), LDA,$ A( I+1, I ), 1, ZERO, Y( 1, I ), 1 )CALL DGEMV( 'No transpose', N-I, I-1, -ONE, Y( I+1, 1 ),$ LDY, Y( 1, I ), 1, ONE, Y( I+1, I ), 1 )CALL DGEMV( 'Transpose', M-I, I, ONE, X( I+1, 1 ), LDX,$ A( I+1, I ), 1, ZERO, Y( 1, I ), 1 )CALL DGEMV( 'Transpose', I, N-I, -ONE, A( 1, I+1 ), LDA,$ Y( 1, I ), 1, ONE, Y( I+1, I ), 1 )CALL DSCAL( N-I, TAUQ( I ), Y( I+1, I ), 1 )END IF20 CONTINUEEND IFRETURN** End of DLABRD*ENDSUBROUTINE DLACON( N, V, X, ISGN, EST, KASE )** -- LAPACK auxiliary routine (version 3.0) --* Univ. of Tennessee, Univ. of California Berkeley, NAG Ltd.,* Courant Institute, Argonne National Lab, and Rice University* February 29, 1992** .. Scalar Arguments ..INTEGER KASE, NDOUBLE PRECISION EST* ..* .. Array Arguments ..INTEGER ISGN( * )DOUBLE PRECISION V( * ), X( * )* ..** Purpose* =======** DLACON estimates the 1-norm of a square, real matrix A.* Reverse communication is used for evaluating matrix-vector products.** Arguments* =========** N (input) INTEGER* The order of the matrix. N >= 1.** V (workspace) DOUBLE PRECISION array, dimension (N)* On the final return, V = A*W, where EST = norm(V)/norm(W)* (W is not returned).** X (input/output) DOUBLE PRECISION array, dimension (N)* On an intermediate return, X should be overwritten by* A * X, if KASE=1,* A' * X, if KASE=2,* and DLACON must be re-called with all the other parameters* unchanged.** ISGN (workspace) INTEGER array, dimension (N)** EST (output) DOUBLE PRECISION* An estimate (a lower bound) for norm(A).** KASE (input/output) INTEGER* On the initial call to DLACON, KASE should be 0.* On an intermediate return, KASE will be 1 or 2, indicating* whether X should be overwritten by A * X or A' * X.* On the final return from DLACON, KASE will again be 0.** Further Details* ======= =======** Contributed by Nick Higham, University of Manchester.* Originally named SONEST, dated March 16, 1988.** Reference: N.J. Higham, "FORTRAN codes for estimating the one-norm of* a real or complex matrix, with applications to condition estimation",* ACM Trans. Math. Soft., vol. 14, no. 4, pp. 381-396, December 1988.** =====================================================================** .. Parameters ..INTEGER ITMAXPARAMETER ( ITMAX = 5 )DOUBLE PRECISION ZERO, ONE, TWOPARAMETER ( ZERO = 0.0D+0, ONE = 1.0D+0, TWO = 2.0D+0 )* ..* .. Local Scalars ..INTEGER I, ITER, J, JLAST, JUMPDOUBLE PRECISION ALTSGN, ESTOLD, TEMP* ..* .. External Functions ..INTEGER IDAMAXDOUBLE PRECISION DASUMEXTERNAL IDAMAX, DASUM* ..* .. External Subroutines ..EXTERNAL DCOPY* ..* .. Intrinsic Functions ..INTRINSIC ABS, DBLE, NINT, SIGN* ..* .. Save statement ..SAVE* ..* .. Executable Statements ..*IF( KASE.EQ.0 ) THENDO 10 I = 1, NX( I ) = ONE / DBLE( N )10 CONTINUEKASE = 1JUMP = 1RETURNEND IF*GO TO ( 20, 40, 70, 110, 140 )JUMP** ................ ENTRY (JUMP = 1)* FIRST ITERATION. X HAS BEEN OVERWRITTEN BY A*X.*20 CONTINUEIF( N.EQ.1 ) THENV( 1 ) = X( 1 )EST = ABS( V( 1 ) )* ... QUITGO TO 150END IFEST = DASUM( N, X, 1 )*DO 30 I = 1, NX( I ) = SIGN( ONE, X( I ) )ISGN( I ) = NINT( X( I ) )30 CONTINUEKASE = 2JUMP = 2RETURN** ................ ENTRY (JUMP = 2)* FIRST ITERATION. X HAS BEEN OVERWRITTEN BY TRANDPOSE(A)*X.*40 CONTINUEJ = IDAMAX( N, X, 1 )ITER = 2** MAIN LOOP - ITERATIONS 2,3,...,ITMAX.*50 CONTINUEDO 60 I = 1, NX( I ) = ZERO60 CONTINUEX( J ) = ONEKASE = 1JUMP = 3RETURN** ................ ENTRY (JUMP = 3)* X HAS BEEN OVERWRITTEN BY A*X.*70 CONTINUECALL DCOPY( N, X, 1, V, 1 )ESTOLD = ESTEST = DASUM( N, V, 1 )DO 80 I = 1, NIF( NINT( SIGN( ONE, X( I ) ) ).NE.ISGN( I ) )$ GO TO 9080 CONTINUE* REPEATED SIGN VECTOR DETECTED, HENCE ALGORITHM HAS CONVERGED.GO TO 120*90 CONTINUE* TEST FOR CYCLING.IF( EST.LE.ESTOLD )$ GO TO 120*DO 100 I = 1, NX( I ) = SIGN( ONE, X( I ) )ISGN( I ) = NINT( X( I ) )100 CONTINUEKASE = 2JUMP = 4RETURN** ................ ENTRY (JUMP = 4)* X HAS BEEN OVERWRITTEN BY TRANDPOSE(A)*X.*110 CONTINUEJLAST = JJ = IDAMAX( N, X, 1 )IF( ( X( JLAST ).NE.ABS( X( J ) ) ) .AND. ( ITER.LT.ITMAX ) ) THENITER = ITER + 1GO TO 50END IF** ITERATION COMPLETE. FINAL STAGE.*120 CONTINUEALTSGN = ONEDO 130 I = 1, NX( I ) = ALTSGN*( ONE+DBLE( I-1 ) / DBLE( N-1 ) )ALTSGN = -ALTSGN130 CONTINUEKASE = 1JUMP = 5RETURN** ................ ENTRY (JUMP = 5)* X HAS BEEN OVERWRITTEN BY A*X.*140 CONTINUETEMP = TWO*( DASUM( N, X, 1 ) / DBLE( 3*N ) )IF( TEMP.GT.EST ) THENCALL DCOPY( N, X, 1, V, 1 )EST = TEMPEND IF*150 CONTINUEKASE = 0RETURN** End of DLACON*ENDSUBROUTINE DLACPY( UPLO, M, N, A, LDA, B, LDB )** -- LAPACK auxiliary routine (version 3.0) --* Univ. of Tennessee, Univ. of California Berkeley, NAG Ltd.,* Courant Institute, Argonne National Lab, and Rice University* February 29, 1992** .. Scalar Arguments ..CHARACTER UPLOINTEGER LDA, LDB, M, N* ..* .. Array Arguments ..DOUBLE PRECISION A( LDA, * ), B( LDB, * )* ..** Purpose* =======** DLACPY copies all or part of a two-dimensional matrix A to another* matrix B.** Arguments* =========** UPLO (input) CHARACTER*1* Specifies the part of the matrix A to be copied to B.* = 'U': Upper triangular part* = 'L': Lower triangular part* Otherwise: All of the matrix A** M (input) INTEGER* The number of rows of the matrix A. M >= 0.** N (input) INTEGER* The number of columns of the matrix A. N >= 0.** A (input) DOUBLE PRECISION array, dimension (LDA,N)* The m by n matrix A. If UPLO = 'U', only the upper triangle* or trapezoid is accessed; if UPLO = 'L', only the lower* triangle or trapezoid is accessed.** LDA (input) INTEGER* The leading dimension of the array A. LDA >= max(1,M).** B (output) DOUBLE PRECISION array, dimension (LDB,N)* On exit, B = A in the locations specified by UPLO.** LDB (input) INTEGER* The leading dimension of the array B. LDB >= max(1,M).** =====================================================================** .. Local Scalars ..INTEGER I, J* ..* .. External Functions ..LOGICAL LSAMEEXTERNAL LSAME* ..* .. Intrinsic Functions ..INTRINSIC MIN* ..* .. Executable Statements ..*IF( LSAME( UPLO, 'U' ) ) THENDO 20 J = 1, NDO 10 I = 1, MIN( J, M )B( I, J ) = A( I, J )10 CONTINUE20 CONTINUEELSE IF( LSAME( UPLO, 'L' ) ) THENDO 40 J = 1, NDO 30 I = J, MB( I, J ) = A( I, J )30 CONTINUE40 CONTINUEELSEDO 60 J = 1, NDO 50 I = 1, MB( I, J ) = A( I, J )50 CONTINUE60 CONTINUEEND IFRETURN** End of DLACPY*ENDSUBROUTINE DLADIV( A, B, C, D, P, Q )** -- LAPACK auxiliary routine (version 3.0) --* Univ. of Tennessee, Univ. of California Berkeley, NAG Ltd.,* Courant Institute, Argonne National Lab, and Rice University* October 31, 1992** .. Scalar Arguments ..DOUBLE PRECISION A, B, C, D, P, Q* ..** Purpose* =======** DLADIV performs complex division in real arithmetic** a + i*b* p + i*q = ---------* c + i*d** The algorithm is due to Robert L. Smith and can be found* in D. Knuth, The art of Computer Programming, Vol.2, p.195** Arguments* =========** A (input) DOUBLE PRECISION* B (input) DOUBLE PRECISION* C (input) DOUBLE PRECISION* D (input) DOUBLE PRECISION* The scalars a, b, c, and d in the above expression.** P (output) DOUBLE PRECISION* Q (output) DOUBLE PRECISION* The scalars p and q in the above expression.** =====================================================================** .. Local Scalars ..DOUBLE PRECISION E, F* ..* .. Intrinsic Functions ..INTRINSIC ABS* ..* .. Executable Statements ..*IF( ABS( D ).LT.ABS( C ) ) THENE = D / CF = C + D*EP = ( A+B*E ) / FQ = ( B-A*E ) / FELSEE = C / DF = D + C*EP = ( B+A*E ) / FQ = ( -A+B*E ) / FEND IF*RETURN** End of DLADIV*ENDSUBROUTINE DLAE2( A, B, C, RT1, RT2 )** -- LAPACK auxiliary routine (version 3.0) --* Univ. of Tennessee, Univ. of California Berkeley, NAG Ltd.,* Courant Institute, Argonne National Lab, and Rice University* October 31, 1992** .. Scalar Arguments ..DOUBLE PRECISION A, B, C, RT1, RT2* ..** Purpose* =======** DLAE2 computes the eigenvalues of a 2-by-2 symmetric matrix* [ A B ]* [ B C ].* On return, RT1 is the eigenvalue of larger absolute value, and RT2* is the eigenvalue of smaller absolute value.** Arguments* =========** A (input) DOUBLE PRECISION* The (1,1) element of the 2-by-2 matrix.** B (input) DOUBLE PRECISION* The (1,2) and (2,1) elements of the 2-by-2 matrix.** C (input) DOUBLE PRECISION* The (2,2) element of the 2-by-2 matrix.** RT1 (output) DOUBLE PRECISION* The eigenvalue of larger absolute value.** RT2 (output) DOUBLE PRECISION* The eigenvalue of smaller absolute value.** Further Details* ===============** RT1 is accurate to a few ulps barring over/underflow.** RT2 may be inaccurate if there is massive cancellation in the* determinant A*C-B*B; higher precision or correctly rounded or* correctly truncated arithmetic would be needed to compute RT2* accurately in all cases.** Overflow is possible only if RT1 is within a factor of 5 of overflow.* Underflow is harmless if the input data is 0 or exceeds* underflow_threshold / macheps.** =====================================================================** .. Parameters ..DOUBLE PRECISION ONEPARAMETER ( ONE = 1.0D0 )DOUBLE PRECISION TWOPARAMETER ( TWO = 2.0D0 )DOUBLE PRECISION ZEROPARAMETER ( ZERO = 0.0D0 )DOUBLE PRECISION HALFPARAMETER ( HALF = 0.5D0 )* ..* .. Local Scalars ..DOUBLE PRECISION AB, ACMN, ACMX, ADF, DF, RT, SM, TB* ..* .. Intrinsic Functions ..INTRINSIC ABS, SQRT* ..* .. Executable Statements ..** Compute the eigenvalues*SM = A + CDF = A - CADF = ABS( DF )TB = B + BAB = ABS( TB )IF( ABS( A ).GT.ABS( C ) ) THENACMX = AACMN = CELSEACMX = CACMN = AEND IFIF( ADF.GT.AB ) THENRT = ADF*SQRT( ONE+( AB / ADF )**2 )ELSE IF( ADF.LT.AB ) THENRT = AB*SQRT( ONE+( ADF / AB )**2 )ELSE** Includes case AB=ADF=0*RT = AB*SQRT( TWO )END IFIF( SM.LT.ZERO ) THENRT1 = HALF*( SM-RT )** Order of execution important.* To get fully accurate smaller eigenvalue,* next line needs to be executed in higher precision.*RT2 = ( ACMX / RT1 )*ACMN - ( B / RT1 )*BELSE IF( SM.GT.ZERO ) THENRT1 = HALF*( SM+RT )** Order of execution important.* To get fully accurate smaller eigenvalue,* next line needs to be executed in higher precision.*RT2 = ( ACMX / RT1 )*ACMN - ( B / RT1 )*BELSE** Includes case RT1 = RT2 = 0*RT1 = HALF*RTRT2 = -HALF*RTEND IFRETURN** End of DLAE2*ENDSUBROUTINE DLAEV2( A, B, C, RT1, RT2, CS1, SN1 )** -- LAPACK auxiliary routine (version 3.0) --* Univ. of Tennessee, Univ. of California Berkeley, NAG Ltd.,* Courant Institute, Argonne National Lab, and Rice University* October 31, 1992** .. Scalar Arguments ..DOUBLE PRECISION A, B, C, CS1, RT1, RT2, SN1* ..** Purpose* =======** DLAEV2 computes the eigendecomposition of a 2-by-2 symmetric matrix* [ A B ]* [ B C ].* On return, RT1 is the eigenvalue of larger absolute value, RT2 is the* eigenvalue of smaller absolute value, and (CS1,SN1) is the unit right* eigenvector for RT1, giving the decomposition** [ CS1 SN1 ] [ A B ] [ CS1 -SN1 ] = [ RT1 0 ]* [-SN1 CS1 ] [ B C ] [ SN1 CS1 ] [ 0 RT2 ].** Arguments* =========** A (input) DOUBLE PRECISION* The (1,1) element of the 2-by-2 matrix.** B (input) DOUBLE PRECISION* The (1,2) element and the conjugate of the (2,1) element of* the 2-by-2 matrix.** C (input) DOUBLE PRECISION* The (2,2) element of the 2-by-2 matrix.** RT1 (output) DOUBLE PRECISION* The eigenvalue of larger absolute value.** RT2 (output) DOUBLE PRECISION* The eigenvalue of smaller absolute value.** CS1 (output) DOUBLE PRECISION* SN1 (output) DOUBLE PRECISION* The vector (CS1, SN1) is a unit right eigenvector for RT1.** Further Details* ===============** RT1 is accurate to a few ulps barring over/underflow.** RT2 may be inaccurate if there is massive cancellation in the* determinant A*C-B*B; higher precision or correctly rounded or* correctly truncated arithmetic would be needed to compute RT2* accurately in all cases.** CS1 and SN1 are accurate to a few ulps barring over/underflow.** Overflow is possible only if RT1 is within a factor of 5 of overflow.* Underflow is harmless if the input data is 0 or exceeds* underflow_threshold / macheps.** =====================================================================** .. Parameters ..DOUBLE PRECISION ONEPARAMETER ( ONE = 1.0D0 )DOUBLE PRECISION TWOPARAMETER ( TWO = 2.0D0 )DOUBLE PRECISION ZEROPARAMETER ( ZERO = 0.0D0 )DOUBLE PRECISION HALFPARAMETER ( HALF = 0.5D0 )* ..* .. Local Scalars ..INTEGER SGN1, SGN2DOUBLE PRECISION AB, ACMN, ACMX, ACS, ADF, CS, CT, DF, RT, SM,$ TB, TN* ..* .. Intrinsic Functions ..INTRINSIC ABS, SQRT* ..* .. Executable Statements ..** Compute the eigenvalues*SM = A + CDF = A - CADF = ABS( DF )TB = B + BAB = ABS( TB )IF( ABS( A ).GT.ABS( C ) ) THENACMX = AACMN = CELSEACMX = CACMN = AEND IFIF( ADF.GT.AB ) THENRT = ADF*SQRT( ONE+( AB / ADF )**2 )ELSE IF( ADF.LT.AB ) THENRT = AB*SQRT( ONE+( ADF / AB )**2 )ELSE** Includes case AB=ADF=0*RT = AB*SQRT( TWO )END IFIF( SM.LT.ZERO ) THENRT1 = HALF*( SM-RT )SGN1 = -1** Order of execution important.* To get fully accurate smaller eigenvalue,* next line needs to be executed in higher precision.*RT2 = ( ACMX / RT1 )*ACMN - ( B / RT1 )*BELSE IF( SM.GT.ZERO ) THENRT1 = HALF*( SM+RT )SGN1 = 1** Order of execution important.* To get fully accurate smaller eigenvalue,* next line needs to be executed in higher precision.*RT2 = ( ACMX / RT1 )*ACMN - ( B / RT1 )*BELSE** Includes case RT1 = RT2 = 0*RT1 = HALF*RTRT2 = -HALF*RTSGN1 = 1END IF** Compute the eigenvector*IF( DF.GE.ZERO ) THENCS = DF + RTSGN2 = 1ELSECS = DF - RTSGN2 = -1END IFACS = ABS( CS )IF( ACS.GT.AB ) THENCT = -TB / CSSN1 = ONE / SQRT( ONE+CT*CT )CS1 = CT*SN1ELSEIF( AB.EQ.ZERO ) THENCS1 = ONESN1 = ZEROELSETN = -CS / TBCS1 = ONE / SQRT( ONE+TN*TN )SN1 = TN*CS1END IFEND IFIF( SGN1.EQ.SGN2 ) THENTN = CS1CS1 = -SN1SN1 = TNEND IFRETURN** End of DLAEV2*ENDSUBROUTINE DLAEXC( WANTQ, N, T, LDT, Q, LDQ, J1, N1, N2, WORK,$ INFO )** -- LAPACK auxiliary routine (version 3.0) --* Univ. of Tennessee, Univ. of California Berkeley, NAG Ltd.,* Courant Institute, Argonne National Lab, and Rice University* February 29, 1992** .. Scalar Arguments ..LOGICAL WANTQINTEGER INFO, J1, LDQ, LDT, N, N1, N2* ..* .. Array Arguments ..DOUBLE PRECISION Q( LDQ, * ), T( LDT, * ), WORK( * )* ..** Purpose* =======** DLAEXC swaps adjacent diagonal blocks T11 and T22 of order 1 or 2 in* an upper quasi-triangular matrix T by an orthogonal similarity* transformation.** T must be in Schur canonical form, that is, block upper triangular* with 1-by-1 and 2-by-2 diagonal blocks; each 2-by-2 diagonal block* has its diagonal elemnts equal and its off-diagonal elements of* opposite sign.** Arguments* =========** WANTQ (input) LOGICAL* = .TRUE. : accumulate the transformation in the matrix Q;* = .FALSE.: do not accumulate the transformation.** N (input) INTEGER* The order of the matrix T. N >= 0.** T (input/output) DOUBLE PRECISION array, dimension (LDT,N)* On entry, the upper quasi-triangular matrix T, in Schur* canonical form.* On exit, the updated matrix T, again in Schur canonical form.** LDT (input) INTEGER* The leading dimension of the array T. LDT >= max(1,N).** Q (input/output) DOUBLE PRECISION array, dimension (LDQ,N)* On entry, if WANTQ is .TRUE., the orthogonal matrix Q.* On exit, if WANTQ is .TRUE., the updated matrix Q.* If WANTQ is .FALSE., Q is not referenced.** LDQ (input) INTEGER* The leading dimension of the array Q.* LDQ >= 1; and if WANTQ is .TRUE., LDQ >= N.** J1 (input) INTEGER* The index of the first row of the first block T11.** N1 (input) INTEGER* The order of the first block T11. N1 = 0, 1 or 2.** N2 (input) INTEGER* The order of the second block T22. N2 = 0, 1 or 2.** WORK (workspace) DOUBLE PRECISION array, dimension (N)** INFO (output) INTEGER* = 0: successful exit* = 1: the transformed matrix T would be too far from Schur* form; the blocks are not swapped and T and Q are* unchanged.** =====================================================================** .. Parameters ..DOUBLE PRECISION ZERO, ONEPARAMETER ( ZERO = 0.0D+0, ONE = 1.0D+0 )DOUBLE PRECISION TENPARAMETER ( TEN = 1.0D+1 )INTEGER LDD, LDXPARAMETER ( LDD = 4, LDX = 2 )* ..* .. Local Scalars ..INTEGER IERR, J2, J3, J4, K, NDDOUBLE PRECISION CS, DNORM, EPS, SCALE, SMLNUM, SN, T11, T22,$ T33, TAU, TAU1, TAU2, TEMP, THRESH, WI1, WI2,$ WR1, WR2, XNORM* ..* .. Local Arrays ..DOUBLE PRECISION D( LDD, 4 ), U( 3 ), U1( 3 ), U2( 3 ),$ X( LDX, 2 )* ..* .. External Functions ..DOUBLE PRECISION DLAMCH, DLANGEEXTERNAL DLAMCH, DLANGE* ..* .. External Subroutines ..EXTERNAL DLACPY, DLANV2, DLARFG, DLARFX, DLARTG, DLASY2,$ DROT* ..* .. Intrinsic Functions ..INTRINSIC ABS, MAX* ..* .. Executable Statements ..*INFO = 0** Quick return if possible*IF( N.EQ.0 .OR. N1.EQ.0 .OR. N2.EQ.0 )$ RETURNIF( J1+N1.GT.N )$ RETURN*J2 = J1 + 1J3 = J1 + 2J4 = J1 + 3*IF( N1.EQ.1 .AND. N2.EQ.1 ) THEN** Swap two 1-by-1 blocks.*T11 = T( J1, J1 )T22 = T( J2, J2 )** Determine the transformation to perform the interchange.*CALL DLARTG( T( J1, J2 ), T22-T11, CS, SN, TEMP )** Apply transformation to the matrix T.*IF( J3.LE.N )$ CALL DROT( N-J1-1, T( J1, J3 ), LDT, T( J2, J3 ), LDT, CS,$ SN )CALL DROT( J1-1, T( 1, J1 ), 1, T( 1, J2 ), 1, CS, SN )*T( J1, J1 ) = T22T( J2, J2 ) = T11*IF( WANTQ ) THEN** Accumulate transformation in the matrix Q.*CALL DROT( N, Q( 1, J1 ), 1, Q( 1, J2 ), 1, CS, SN )END IF*ELSE** Swapping involves at least one 2-by-2 block.** Copy the diagonal block of order N1+N2 to the local array D* and compute its norm.*ND = N1 + N2CALL DLACPY( 'Full', ND, ND, T( J1, J1 ), LDT, D, LDD )DNORM = DLANGE( 'Max', ND, ND, D, LDD, WORK )** Compute machine-dependent threshold for test for accepting* swap.*EPS = DLAMCH( 'P' )SMLNUM = DLAMCH( 'S' ) / EPSTHRESH = MAX( TEN*EPS*DNORM, SMLNUM )** Solve T11*X - X*T22 = scale*T12 for X.*CALL DLASY2( .FALSE., .FALSE., -1, N1, N2, D, LDD,$ D( N1+1, N1+1 ), LDD, D( 1, N1+1 ), LDD, SCALE, X,$ LDX, XNORM, IERR )** Swap the adjacent diagonal blocks.*K = N1 + N1 + N2 - 3GO TO ( 10, 20, 30 )K*10 CONTINUE** N1 = 1, N2 = 2: generate elementary reflector H so that:** ( scale, X11, X12 ) H = ( 0, 0, * )*U( 1 ) = SCALEU( 2 ) = X( 1, 1 )U( 3 ) = X( 1, 2 )CALL DLARFG( 3, U( 3 ), U, 1, TAU )U( 3 ) = ONET11 = T( J1, J1 )** Perform swap provisionally on diagonal block in D.*CALL DLARFX( 'L', 3, 3, U, TAU, D, LDD, WORK )CALL DLARFX( 'R', 3, 3, U, TAU, D, LDD, WORK )** Test whether to reject swap.*IF( MAX( ABS( D( 3, 1 ) ), ABS( D( 3, 2 ) ), ABS( D( 3,$ 3 )-T11 ) ).GT.THRESH )GO TO 50** Accept swap: apply transformation to the entire matrix T.*CALL DLARFX( 'L', 3, N-J1+1, U, TAU, T( J1, J1 ), LDT, WORK )CALL DLARFX( 'R', J2, 3, U, TAU, T( 1, J1 ), LDT, WORK )*T( J3, J1 ) = ZEROT( J3, J2 ) = ZEROT( J3, J3 ) = T11*IF( WANTQ ) THEN** Accumulate transformation in the matrix Q.*CALL DLARFX( 'R', N, 3, U, TAU, Q( 1, J1 ), LDQ, WORK )END IFGO TO 40*20 CONTINUE** N1 = 2, N2 = 1: generate elementary reflector H so that:** H ( -X11 ) = ( * )* ( -X21 ) = ( 0 )* ( scale ) = ( 0 )*U( 1 ) = -X( 1, 1 )U( 2 ) = -X( 2, 1 )U( 3 ) = SCALECALL DLARFG( 3, U( 1 ), U( 2 ), 1, TAU )U( 1 ) = ONET33 = T( J3, J3 )** Perform swap provisionally on diagonal block in D.*CALL DLARFX( 'L', 3, 3, U, TAU, D, LDD, WORK )CALL DLARFX( 'R', 3, 3, U, TAU, D, LDD, WORK )** Test whether to reject swap.*IF( MAX( ABS( D( 2, 1 ) ), ABS( D( 3, 1 ) ), ABS( D( 1,$ 1 )-T33 ) ).GT.THRESH )GO TO 50** Accept swap: apply transformation to the entire matrix T.*CALL DLARFX( 'R', J3, 3, U, TAU, T( 1, J1 ), LDT, WORK )CALL DLARFX( 'L', 3, N-J1, U, TAU, T( J1, J2 ), LDT, WORK )*T( J1, J1 ) = T33T( J2, J1 ) = ZEROT( J3, J1 ) = ZERO*IF( WANTQ ) THEN** Accumulate transformation in the matrix Q.*CALL DLARFX( 'R', N, 3, U, TAU, Q( 1, J1 ), LDQ, WORK )END IFGO TO 40*30 CONTINUE** N1 = 2, N2 = 2: generate elementary reflectors H(1) and H(2) so* that:** H(2) H(1) ( -X11 -X12 ) = ( * * )* ( -X21 -X22 ) ( 0 * )* ( scale 0 ) ( 0 0 )* ( 0 scale ) ( 0 0 )*U1( 1 ) = -X( 1, 1 )U1( 2 ) = -X( 2, 1 )U1( 3 ) = SCALECALL DLARFG( 3, U1( 1 ), U1( 2 ), 1, TAU1 )U1( 1 ) = ONE*TEMP = -TAU1*( X( 1, 2 )+U1( 2 )*X( 2, 2 ) )U2( 1 ) = -TEMP*U1( 2 ) - X( 2, 2 )U2( 2 ) = -TEMP*U1( 3 )U2( 3 ) = SCALECALL DLARFG( 3, U2( 1 ), U2( 2 ), 1, TAU2 )U2( 1 ) = ONE** Perform swap provisionally on diagonal block in D.*CALL DLARFX( 'L', 3, 4, U1, TAU1, D, LDD, WORK )CALL DLARFX( 'R', 4, 3, U1, TAU1, D, LDD, WORK )CALL DLARFX( 'L', 3, 4, U2, TAU2, D( 2, 1 ), LDD, WORK )CALL DLARFX( 'R', 4, 3, U2, TAU2, D( 1, 2 ), LDD, WORK )** Test whether to reject swap.*IF( MAX( ABS( D( 3, 1 ) ), ABS( D( 3, 2 ) ), ABS( D( 4, 1 ) ),$ ABS( D( 4, 2 ) ) ).GT.THRESH )GO TO 50** Accept swap: apply transformation to the entire matrix T.*CALL DLARFX( 'L', 3, N-J1+1, U1, TAU1, T( J1, J1 ), LDT, WORK )CALL DLARFX( 'R', J4, 3, U1, TAU1, T( 1, J1 ), LDT, WORK )CALL DLARFX( 'L', 3, N-J1+1, U2, TAU2, T( J2, J1 ), LDT, WORK )CALL DLARFX( 'R', J4, 3, U2, TAU2, T( 1, J2 ), LDT, WORK )*T( J3, J1 ) = ZEROT( J3, J2 ) = ZEROT( J4, J1 ) = ZEROT( J4, J2 ) = ZERO*IF( WANTQ ) THEN** Accumulate transformation in the matrix Q.*CALL DLARFX( 'R', N, 3, U1, TAU1, Q( 1, J1 ), LDQ, WORK )CALL DLARFX( 'R', N, 3, U2, TAU2, Q( 1, J2 ), LDQ, WORK )END IF*40 CONTINUE*IF( N2.EQ.2 ) THEN** Standardize new 2-by-2 block T11*CALL DLANV2( T( J1, J1 ), T( J1, J2 ), T( J2, J1 ),$ T( J2, J2 ), WR1, WI1, WR2, WI2, CS, SN )CALL DROT( N-J1-1, T( J1, J1+2 ), LDT, T( J2, J1+2 ), LDT,$ CS, SN )CALL DROT( J1-1, T( 1, J1 ), 1, T( 1, J2 ), 1, CS, SN )IF( WANTQ )$ CALL DROT( N, Q( 1, J1 ), 1, Q( 1, J2 ), 1, CS, SN )END IF*IF( N1.EQ.2 ) THEN** Standardize new 2-by-2 block T22*J3 = J1 + N2J4 = J3 + 1CALL DLANV2( T( J3, J3 ), T( J3, J4 ), T( J4, J3 ),$ T( J4, J4 ), WR1, WI1, WR2, WI2, CS, SN )IF( J3+2.LE.N )$ CALL DROT( N-J3-1, T( J3, J3+2 ), LDT, T( J4, J3+2 ),$ LDT, CS, SN )CALL DROT( J3-1, T( 1, J3 ), 1, T( 1, J4 ), 1, CS, SN )IF( WANTQ )$ CALL DROT( N, Q( 1, J3 ), 1, Q( 1, J4 ), 1, CS, SN )END IF*END IFRETURN** Exit with INFO = 1 if swap was rejected.*50 CONTINUEINFO = 1RETURN** End of DLAEXC*ENDSUBROUTINE DLAHQR( WANTT, WANTZ, N, ILO, IHI, H, LDH, WR, WI,$ ILOZ, IHIZ, Z, LDZ, INFO )** -- LAPACK auxiliary routine (version 3.0) --* Univ. of Tennessee, Univ. of California Berkeley, NAG Ltd.,* Courant Institute, Argonne National Lab, and Rice University* June 30, 1999** .. Scalar Arguments ..LOGICAL WANTT, WANTZINTEGER IHI, IHIZ, ILO, ILOZ, INFO, LDH, LDZ, N* ..* .. Array Arguments ..DOUBLE PRECISION H( LDH, * ), WI( * ), WR( * ), Z( LDZ, * )* ..** Purpose* =======** DLAHQR is an auxiliary routine called by DHSEQR to update the* eigenvalues and Schur decomposition already computed by DHSEQR, by* dealing with the Hessenberg submatrix in rows and columns ILO to IHI.** Arguments* =========** WANTT (input) LOGICAL* = .TRUE. : the full Schur form T is required;* = .FALSE.: only eigenvalues are required.** WANTZ (input) LOGICAL* = .TRUE. : the matrix of Schur vectors Z is required;* = .FALSE.: Schur vectors are not required.** N (input) INTEGER* The order of the matrix H. N >= 0.** ILO (input) INTEGER* IHI (input) INTEGER* It is assumed that H is already upper quasi-triangular in* rows and columns IHI+1:N, and that H(ILO,ILO-1) = 0 (unless* ILO = 1). DLAHQR works primarily with the Hessenberg* submatrix in rows and columns ILO to IHI, but applies* transformations to all of H if WANTT is .TRUE..* 1 <= ILO <= max(1,IHI); IHI <= N.** H (input/output) DOUBLE PRECISION array, dimension (LDH,N)* On entry, the upper Hessenberg matrix H.* On exit, if WANTT is .TRUE., H is upper quasi-triangular in* rows and columns ILO:IHI, with any 2-by-2 diagonal blocks in* standard form. If WANTT is .FALSE., the contents of H are* unspecified on exit.** LDH (input) INTEGER* The leading dimension of the array H. LDH >= max(1,N).** WR (output) DOUBLE PRECISION array, dimension (N)* WI (output) DOUBLE PRECISION array, dimension (N)* The real and imaginary parts, respectively, of the computed* eigenvalues ILO to IHI are stored in the corresponding* elements of WR and WI. If two eigenvalues are computed as a* complex conjugate pair, they are stored in consecutive* elements of WR and WI, say the i-th and (i+1)th, with* WI(i) > 0 and WI(i+1) < 0. If WANTT is .TRUE., the* eigenvalues are stored in the same order as on the diagonal* of the Schur form returned in H, with WR(i) = H(i,i), and, if* H(i:i+1,i:i+1) is a 2-by-2 diagonal block,* WI(i) = sqrt(H(i+1,i)*H(i,i+1)) and WI(i+1) = -WI(i).** ILOZ (input) INTEGER* IHIZ (input) INTEGER* Specify the rows of Z to which transformations must be* applied if WANTZ is .TRUE..* 1 <= ILOZ <= ILO; IHI <= IHIZ <= N.** Z (input/output) DOUBLE PRECISION array, dimension (LDZ,N)* If WANTZ is .TRUE., on entry Z must contain the current* matrix Z of transformations accumulated by DHSEQR, and on* exit Z has been updated; transformations are applied only to* the submatrix Z(ILOZ:IHIZ,ILO:IHI).* If WANTZ is .FALSE., Z is not referenced.** LDZ (input) INTEGER* The leading dimension of the array Z. LDZ >= max(1,N).** INFO (output) INTEGER* = 0: successful exit* > 0: DLAHQR failed to compute all the eigenvalues ILO to IHI* in a total of 30*(IHI-ILO+1) iterations; if INFO = i,* elements i+1:ihi of WR and WI contain those eigenvalues* which have been successfully computed.** Further Details* ===============** 2-96 Based on modifications by* David Day, Sandia National Laboratory, USA** =====================================================================** .. Parameters ..DOUBLE PRECISION ZERO, ONE, HALFPARAMETER ( ZERO = 0.0D+0, ONE = 1.0D+0, HALF = 0.5D0 )DOUBLE PRECISION DAT1, DAT2PARAMETER ( DAT1 = 0.75D+0, DAT2 = -0.4375D+0 )* ..* .. Local Scalars ..INTEGER I, I1, I2, ITN, ITS, J, K, L, M, NH, NR, NZDOUBLE PRECISION AVE, CS, DISC, H00, H10, H11, H12, H21, H22,$ H33, H33S, H43H34, H44, H44S, OVFL, S, SMLNUM,$ SN, SUM, T1, T2, T3, TST1, ULP, UNFL, V1, V2,$ V3* ..* .. Local Arrays ..DOUBLE PRECISION V( 3 ), WORK( 1 )* ..* .. External Functions ..DOUBLE PRECISION DLAMCH, DLANHSEXTERNAL DLAMCH, DLANHS* ..* .. External Subroutines ..EXTERNAL DCOPY, DLANV2, DLARFG, DROT* ..* .. Intrinsic Functions ..INTRINSIC ABS, MAX, MIN, SIGN, SQRT* ..* .. Executable Statements ..*INFO = 0** Quick return if possible*IF( N.EQ.0 )$ RETURNIF( ILO.EQ.IHI ) THENWR( ILO ) = H( ILO, ILO )WI( ILO ) = ZERORETURNEND IF*NH = IHI - ILO + 1NZ = IHIZ - ILOZ + 1** Set machine-dependent constants for the stopping criterion.* If norm(H) <= sqrt(OVFL), overflow should not occur.*UNFL = DLAMCH( 'Safe minimum' )OVFL = ONE / UNFLCALL DLABAD( UNFL, OVFL )ULP = DLAMCH( 'Precision' )SMLNUM = UNFL*( NH / ULP )** I1 and I2 are the indices of the first row and last column of H* to which transformations must be applied. If eigenvalues only are* being computed, I1 and I2 are set inside the main loop.*IF( WANTT ) THENI1 = 1I2 = NEND IF** ITN is the total number of QR iterations allowed.*ITN = 30*NH** The main loop begins here. I is the loop index and decreases from* IHI to ILO in steps of 1 or 2. Each iteration of the loop works* with the active submatrix in rows and columns L to I.* Eigenvalues I+1 to IHI have already converged. Either L = ILO or* H(L,L-1) is negligible so that the matrix splits.*I = IHI10 CONTINUEL = ILOIF( I.LT.ILO )$ GO TO 150** Perform QR iterations on rows and columns ILO to I until a* submatrix of order 1 or 2 splits off at the bottom because a* subdiagonal element has become negligible.*DO 130 ITS = 0, ITN** Look for a single small subdiagonal element.*DO 20 K = I, L + 1, -1TST1 = ABS( H( K-1, K-1 ) ) + ABS( H( K, K ) )IF( TST1.EQ.ZERO )$ TST1 = DLANHS( '1', I-L+1, H( L, L ), LDH, WORK )IF( ABS( H( K, K-1 ) ).LE.MAX( ULP*TST1, SMLNUM ) )$ GO TO 3020 CONTINUE30 CONTINUEL = KIF( L.GT.ILO ) THEN** H(L,L-1) is negligible*H( L, L-1 ) = ZEROEND IF** Exit from loop if a submatrix of order 1 or 2 has split off.*IF( L.GE.I-1 )$ GO TO 140** Now the active submatrix is in rows and columns L to I. If* eigenvalues only are being computed, only the active submatrix* need be transformed.*IF( .NOT.WANTT ) THENI1 = LI2 = IEND IF*IF( ITS.EQ.10 .OR. ITS.EQ.20 ) THEN** Exceptional shift.*S = ABS( H( I, I-1 ) ) + ABS( H( I-1, I-2 ) )H44 = DAT1*S + H( I, I )H33 = H44H43H34 = DAT2*S*SELSE** Prepare to use Francis' double shift* (i.e. 2nd degree generalized Rayleigh quotient)*H44 = H( I, I )H33 = H( I-1, I-1 )H43H34 = H( I, I-1 )*H( I-1, I )S = H( I-1, I-2 )*H( I-1, I-2 )DISC = ( H33-H44 )*HALFDISC = DISC*DISC + H43H34IF( DISC.GT.ZERO ) THEN** Real roots: use Wilkinson's shift twice*DISC = SQRT( DISC )AVE = HALF*( H33+H44 )IF( ABS( H33 )-ABS( H44 ).GT.ZERO ) THENH33 = H33*H44 - H43H34H44 = H33 / ( SIGN( DISC, AVE )+AVE )ELSEH44 = SIGN( DISC, AVE ) + AVEEND IFH33 = H44H43H34 = ZEROEND IFEND IF** Look for two consecutive small subdiagonal elements.*DO 40 M = I - 2, L, -1* Determine the effect of starting the double-shift QR* iteration at row M, and see if this would make H(M,M-1)* negligible.*H11 = H( M, M )H22 = H( M+1, M+1 )H21 = H( M+1, M )H12 = H( M, M+1 )H44S = H44 - H11H33S = H33 - H11V1 = ( H33S*H44S-H43H34 ) / H21 + H12V2 = H22 - H11 - H33S - H44SV3 = H( M+2, M+1 )S = ABS( V1 ) + ABS( V2 ) + ABS( V3 )V1 = V1 / SV2 = V2 / SV3 = V3 / SV( 1 ) = V1V( 2 ) = V2V( 3 ) = V3IF( M.EQ.L )$ GO TO 50H00 = H( M-1, M-1 )H10 = H( M, M-1 )TST1 = ABS( V1 )*( ABS( H00 )+ABS( H11 )+ABS( H22 ) )IF( ABS( H10 )*( ABS( V2 )+ABS( V3 ) ).LE.ULP*TST1 )$ GO TO 5040 CONTINUE50 CONTINUE** Double-shift QR step*DO 120 K = M, I - 1** The first iteration of this loop determines a reflection G* from the vector V and applies it from left and right to H,* thus creating a nonzero bulge below the subdiagonal.** Each subsequent iteration determines a reflection G to* restore the Hessenberg form in the (K-1)th column, and thus* chases the bulge one step toward the bottom of the active* submatrix. NR is the order of G.*NR = MIN( 3, I-K+1 )IF( K.GT.M )$ CALL DCOPY( NR, H( K, K-1 ), 1, V, 1 )CALL DLARFG( NR, V( 1 ), V( 2 ), 1, T1 )IF( K.GT.M ) THENH( K, K-1 ) = V( 1 )H( K+1, K-1 ) = ZEROIF( K.LT.I-1 )$ H( K+2, K-1 ) = ZEROELSE IF( M.GT.L ) THENH( K, K-1 ) = -H( K, K-1 )END IFV2 = V( 2 )T2 = T1*V2IF( NR.EQ.3 ) THENV3 = V( 3 )T3 = T1*V3** Apply G from the left to transform the rows of the matrix* in columns K to I2.*DO 60 J = K, I2SUM = H( K, J ) + V2*H( K+1, J ) + V3*H( K+2, J )H( K, J ) = H( K, J ) - SUM*T1H( K+1, J ) = H( K+1, J ) - SUM*T2H( K+2, J ) = H( K+2, J ) - SUM*T360 CONTINUE** Apply G from the right to transform the columns of the* matrix in rows I1 to min(K+3,I).*DO 70 J = I1, MIN( K+3, I )SUM = H( J, K ) + V2*H( J, K+1 ) + V3*H( J, K+2 )H( J, K ) = H( J, K ) - SUM*T1H( J, K+1 ) = H( J, K+1 ) - SUM*T2H( J, K+2 ) = H( J, K+2 ) - SUM*T370 CONTINUE*IF( WANTZ ) THEN** Accumulate transformations in the matrix Z*DO 80 J = ILOZ, IHIZSUM = Z( J, K ) + V2*Z( J, K+1 ) + V3*Z( J, K+2 )Z( J, K ) = Z( J, K ) - SUM*T1Z( J, K+1 ) = Z( J, K+1 ) - SUM*T2Z( J, K+2 ) = Z( J, K+2 ) - SUM*T380 CONTINUEEND IFELSE IF( NR.EQ.2 ) THEN** Apply G from the left to transform the rows of the matrix* in columns K to I2.*DO 90 J = K, I2SUM = H( K, J ) + V2*H( K+1, J )H( K, J ) = H( K, J ) - SUM*T1H( K+1, J ) = H( K+1, J ) - SUM*T290 CONTINUE** Apply G from the right to transform the columns of the* matrix in rows I1 to min(K+3,I).*DO 100 J = I1, ISUM = H( J, K ) + V2*H( J, K+1 )H( J, K ) = H( J, K ) - SUM*T1H( J, K+1 ) = H( J, K+1 ) - SUM*T2100 CONTINUE*IF( WANTZ ) THEN** Accumulate transformations in the matrix Z*DO 110 J = ILOZ, IHIZSUM = Z( J, K ) + V2*Z( J, K+1 )Z( J, K ) = Z( J, K ) - SUM*T1Z( J, K+1 ) = Z( J, K+1 ) - SUM*T2110 CONTINUEEND IFEND IF120 CONTINUE*130 CONTINUE** Failure to converge in remaining number of iterations*INFO = IRETURN*140 CONTINUE*IF( L.EQ.I ) THEN** H(I,I-1) is negligible: one eigenvalue has converged.*WR( I ) = H( I, I )WI( I ) = ZEROELSE IF( L.EQ.I-1 ) THEN** H(I-1,I-2) is negligible: a pair of eigenvalues have converged.** Transform the 2-by-2 submatrix to standard Schur form,* and compute and store the eigenvalues.*CALL DLANV2( H( I-1, I-1 ), H( I-1, I ), H( I, I-1 ),$ H( I, I ), WR( I-1 ), WI( I-1 ), WR( I ), WI( I ),$ CS, SN )*IF( WANTT ) THEN** Apply the transformation to the rest of H.*IF( I2.GT.I )$ CALL DROT( I2-I, H( I-1, I+1 ), LDH, H( I, I+1 ), LDH,$ CS, SN )CALL DROT( I-I1-1, H( I1, I-1 ), 1, H( I1, I ), 1, CS, SN )END IFIF( WANTZ ) THEN** Apply the transformation to Z.*CALL DROT( NZ, Z( ILOZ, I-1 ), 1, Z( ILOZ, I ), 1, CS, SN )END IFEND IF** Decrement number of remaining iterations, and return to start of* the main loop with new value of I.*ITN = ITN - ITSI = L - 1GO TO 10*150 CONTINUERETURN** End of DLAHQR*ENDSUBROUTINE DLAHRD( N, K, NB, A, LDA, TAU, T, LDT, Y, LDY )** -- LAPACK auxiliary 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 K, LDA, LDT, LDY, N, NB* ..* .. Array Arguments ..DOUBLE PRECISION A( LDA, * ), T( LDT, NB ), TAU( NB ),$ Y( LDY, NB )* ..** Purpose* =======** DLAHRD reduces the first NB columns of a real general n-by-(n-k+1)* matrix A so that elements below the k-th subdiagonal are zero. The* reduction is performed by an orthogonal similarity transformation* Q' * A * Q. The routine returns the matrices V and T which determine* Q as a block reflector I - V*T*V', and also the matrix Y = A * V * T.** This is an auxiliary routine called by DGEHRD.** Arguments* =========** N (input) INTEGER* The order of the matrix A.** K (input) INTEGER* The offset for the reduction. Elements below the k-th* subdiagonal in the first NB columns are reduced to zero.** NB (input) INTEGER* The number of columns to be reduced.** A (input/output) DOUBLE PRECISION array, dimension (LDA,N-K+1)* On entry, the n-by-(n-k+1) general matrix A.* On exit, the elements on and above the k-th subdiagonal in* the first NB columns are overwritten with the corresponding* elements of the reduced matrix; the elements below the k-th* subdiagonal, with the array TAU, represent the matrix Q as a* product of elementary reflectors. The other columns of A are* unchanged. See Further Details.** LDA (input) INTEGER* The leading dimension of the array A. LDA >= max(1,N).** TAU (output) DOUBLE PRECISION array, dimension (NB)* The scalar factors of the elementary reflectors. See Further* Details.** T (output) DOUBLE PRECISION array, dimension (LDT,NB)* The upper triangular matrix T.** LDT (input) INTEGER* The leading dimension of the array T. LDT >= NB.** Y (output) DOUBLE PRECISION array, dimension (LDY,NB)* The n-by-nb matrix Y.** LDY (input) INTEGER* The leading dimension of the array Y. LDY >= N.** Further Details* ===============** The matrix Q is represented as a product of nb elementary reflectors** Q = H(1) H(2) . . . H(nb).** Each H(i) has the form** H(i) = I - tau * v * v'** where tau is a real scalar, and v is a real vector with* v(1:i+k-1) = 0, v(i+k) = 1; v(i+k+1:n) is stored on exit in* A(i+k+1:n,i), and tau in TAU(i).** The elements of the vectors v together form the (n-k+1)-by-nb matrix* V which is needed, with T and Y, to apply the transformation to the* unreduced part of the matrix, using an update of the form:* A := (I - V*T*V') * (A - Y*V').** The contents of A on exit are illustrated by the following example* with n = 7, k = 3 and nb = 2:** ( a h a a a )* ( a h a a a )* ( a h a a a )* ( h h a a a )* ( v1 h a a a )* ( v1 v2 a a a )* ( v1 v2 a a a )** where a denotes an element of the original matrix A, h denotes a* modified element of the upper Hessenberg matrix H, and vi denotes an* element of the vector defining H(i).** =====================================================================** .. Parameters ..DOUBLE PRECISION ZERO, ONEPARAMETER ( ZERO = 0.0D+0, ONE = 1.0D+0 )* ..* .. Local Scalars ..INTEGER IDOUBLE PRECISION EI* ..* .. External Subroutines ..EXTERNAL DAXPY, DCOPY, DGEMV, DLARFG, DSCAL, DTRMV* ..* .. Intrinsic Functions ..INTRINSIC MIN* ..* .. Executable Statements ..** Quick return if possible*IF( N.LE.1 )$ RETURN*DO 10 I = 1, NBIF( I.GT.1 ) THEN** Update A(1:n,i)** Compute i-th column of A - Y * V'*CALL DGEMV( 'No transpose', N, I-1, -ONE, Y, LDY,$ A( K+I-1, 1 ), LDA, ONE, A( 1, I ), 1 )** Apply I - V * T' * V' to this column (call it b) from the* left, using the last column of T as workspace** Let V = ( V1 ) and b = ( b1 ) (first I-1 rows)* ( V2 ) ( b2 )** where V1 is unit lower triangular** w := V1' * b1*CALL DCOPY( I-1, A( K+1, I ), 1, T( 1, NB ), 1 )CALL DTRMV( 'Lower', 'Transpose', 'Unit', I-1, A( K+1, 1 ),$ LDA, T( 1, NB ), 1 )** w := w + V2'*b2*CALL DGEMV( 'Transpose', N-K-I+1, I-1, ONE, A( K+I, 1 ),$ LDA, A( K+I, I ), 1, ONE, T( 1, NB ), 1 )** w := T'*w*CALL DTRMV( 'Upper', 'Transpose', 'Non-unit', I-1, T, LDT,$ T( 1, NB ), 1 )** b2 := b2 - V2*w*CALL DGEMV( 'No transpose', N-K-I+1, I-1, -ONE, A( K+I, 1 ),$ LDA, T( 1, NB ), 1, ONE, A( K+I, I ), 1 )** b1 := b1 - V1*w*CALL DTRMV( 'Lower', 'No transpose', 'Unit', I-1,$ A( K+1, 1 ), LDA, T( 1, NB ), 1 )CALL DAXPY( I-1, -ONE, T( 1, NB ), 1, A( K+1, I ), 1 )*A( K+I-1, I-1 ) = EIEND IF** Generate the elementary reflector H(i) to annihilate* A(k+i+1:n,i)*CALL DLARFG( N-K-I+1, A( K+I, I ), A( MIN( K+I+1, N ), I ), 1,$ TAU( I ) )EI = A( K+I, I )A( K+I, I ) = ONE** Compute Y(1:n,i)*CALL DGEMV( 'No transpose', N, N-K-I+1, ONE, A( 1, I+1 ), LDA,$ A( K+I, I ), 1, ZERO, Y( 1, I ), 1 )CALL DGEMV( 'Transpose', N-K-I+1, I-1, ONE, A( K+I, 1 ), LDA,$ A( K+I, I ), 1, ZERO, T( 1, I ), 1 )CALL DGEMV( 'No transpose', N, I-1, -ONE, Y, LDY, T( 1, I ), 1,$ ONE, Y( 1, I ), 1 )CALL DSCAL( N, TAU( I ), Y( 1, I ), 1 )** Compute T(1:i,i)*CALL DSCAL( I-1, -TAU( I ), T( 1, I ), 1 )CALL DTRMV( 'Upper', 'No transpose', 'Non-unit', I-1, T, LDT,$ T( 1, I ), 1 )T( I, I ) = TAU( I )*10 CONTINUEA( K+NB, NB ) = EI*RETURN** End of DLAHRD*ENDSUBROUTINE DLALN2( LTRANS, NA, NW, SMIN, CA, A, LDA, D1, D2, B,$ LDB, WR, WI, X, LDX, SCALE, XNORM, INFO )** -- LAPACK auxiliary routine (version 3.0) --* Univ. of Tennessee, Univ. of California Berkeley, NAG Ltd.,* Courant Institute, Argonne National Lab, and Rice University* October 31, 1992** .. Scalar Arguments ..LOGICAL LTRANSINTEGER INFO, LDA, LDB, LDX, NA, NWDOUBLE PRECISION CA, D1, D2, SCALE, SMIN, WI, WR, XNORM* ..* .. Array Arguments ..DOUBLE PRECISION A( LDA, * ), B( LDB, * ), X( LDX, * )* ..** Purpose* =======** DLALN2 solves a system of the form (ca A - w D ) X = s B* or (ca A' - w D) X = s B with possible scaling ("s") and* perturbation of A. (A' means A-transpose.)** A is an NA x NA real matrix, ca is a real scalar, D is an NA x NA* real diagonal matrix, w is a real or complex value, and X and B are* NA x 1 matrices -- real if w is real, complex if w is complex. NA* may be 1 or 2.** If w is complex, X and B are represented as NA x 2 matrices,* the first column of each being the real part and the second* being the imaginary part.** "s" is a scaling factor (.LE. 1), computed by DLALN2, which is* so chosen that X can be computed without overflow. X is further* scaled if necessary to assure that norm(ca A - w D)*norm(X) is less* than overflow.** If both singular values of (ca A - w D) are less than SMIN,* SMIN*identity will be used instead of (ca A - w D). If only one* singular value is less than SMIN, one element of (ca A - w D) will be* perturbed enough to make the smallest singular value roughly SMIN.* If both singular values are at least SMIN, (ca A - w D) will not be* perturbed. In any case, the perturbation will be at most some small* multiple of max( SMIN, ulp*norm(ca A - w D) ). The singular values* are computed by infinity-norm approximations, and thus will only be* correct to a factor of 2 or so.** Note: all input quantities are assumed to be smaller than overflow* by a reasonable factor. (See BIGNUM.)** Arguments* ==========** LTRANS (input) LOGICAL* =.TRUE.: A-transpose will be used.* =.FALSE.: A will be used (not transposed.)** NA (input) INTEGER* The size of the matrix A. It may (only) be 1 or 2.** NW (input) INTEGER* 1 if "w" is real, 2 if "w" is complex. It may only be 1* or 2.** SMIN (input) DOUBLE PRECISION* The desired lower bound on the singular values of A. This* should be a safe distance away from underflow or overflow,* say, between (underflow/machine precision) and (machine* precision * overflow ). (See BIGNUM and ULP.)** CA (input) DOUBLE PRECISION* The coefficient c, which A is multiplied by.** A (input) DOUBLE PRECISION array, dimension (LDA,NA)* The NA x NA matrix A.** LDA (input) INTEGER* The leading dimension of A. It must be at least NA.** D1 (input) DOUBLE PRECISION* The 1,1 element in the diagonal matrix D.** D2 (input) DOUBLE PRECISION* The 2,2 element in the diagonal matrix D. Not used if NW=1.** B (input) DOUBLE PRECISION array, dimension (LDB,NW)* The NA x NW matrix B (right-hand side). If NW=2 ("w" is* complex), column 1 contains the real part of B and column 2* contains the imaginary part.** LDB (input) INTEGER* The leading dimension of B. It must be at least NA.** WR (input) DOUBLE PRECISION* The real part of the scalar "w".** WI (input) DOUBLE PRECISION* The imaginary part of the scalar "w". Not used if NW=1.** X (output) DOUBLE PRECISION array, dimension (LDX,NW)* The NA x NW matrix X (unknowns), as computed by DLALN2.* If NW=2 ("w" is complex), on exit, column 1 will contain* the real part of X and column 2 will contain the imaginary* part.** LDX (input) INTEGER* The leading dimension of X. It must be at least NA.** SCALE (output) DOUBLE PRECISION* The scale factor that B must be multiplied by to insure* that overflow does not occur when computing X. Thus,* (ca A - w D) X will be SCALE*B, not B (ignoring* perturbations of A.) It will be at most 1.** XNORM (output) DOUBLE PRECISION* The infinity-norm of X, when X is regarded as an NA x NW* real matrix.** INFO (output) INTEGER* An error flag. It will be set to zero if no error occurs,* a negative number if an argument is in error, or a positive* number if ca A - w D had to be perturbed.* The possible values are:* = 0: No error occurred, and (ca A - w D) did not have to be* perturbed.* = 1: (ca A - w D) had to be perturbed to make its smallest* (or only) singular value greater than SMIN.* NOTE: In the interests of speed, this routine does not* check the inputs for errors.** =====================================================================** .. Parameters ..DOUBLE PRECISION ZERO, ONEPARAMETER ( ZERO = 0.0D0, ONE = 1.0D0 )DOUBLE PRECISION TWOPARAMETER ( TWO = 2.0D0 )* ..* .. Local Scalars ..INTEGER ICMAX, JDOUBLE PRECISION BBND, BI1, BI2, BIGNUM, BNORM, BR1, BR2, CI21,$ CI22, CMAX, CNORM, CR21, CR22, CSI, CSR, LI21,$ LR21, SMINI, SMLNUM, TEMP, U22ABS, UI11, UI11R,$ UI12, UI12S, UI22, UR11, UR11R, UR12, UR12S,$ UR22, XI1, XI2, XR1, XR2* ..* .. Local Arrays ..LOGICAL RSWAP( 4 ), ZSWAP( 4 )INTEGER IPIVOT( 4, 4 )DOUBLE PRECISION CI( 2, 2 ), CIV( 4 ), CR( 2, 2 ), CRV( 4 )* ..* .. External Functions ..DOUBLE PRECISION DLAMCHEXTERNAL DLAMCH* ..* .. External Subroutines ..EXTERNAL DLADIV* ..* .. Intrinsic Functions ..INTRINSIC ABS, MAX* ..* .. Equivalences ..EQUIVALENCE ( CI( 1, 1 ), CIV( 1 ) ),$ ( CR( 1, 1 ), CRV( 1 ) )* ..* .. Data statements ..DATA ZSWAP / .FALSE., .FALSE., .TRUE., .TRUE. /DATA RSWAP / .FALSE., .TRUE., .FALSE., .TRUE. /DATA IPIVOT / 1, 2, 3, 4, 2, 1, 4, 3, 3, 4, 1, 2, 4,$ 3, 2, 1 /* ..* .. Executable Statements ..** Compute BIGNUM*SMLNUM = TWO*DLAMCH( 'Safe minimum' )BIGNUM = ONE / SMLNUMSMINI = MAX( SMIN, SMLNUM )** Don't check for input errors*INFO = 0** Standard Initializations*SCALE = ONE*IF( NA.EQ.1 ) THEN** 1 x 1 (i.e., scalar) system C X = B*IF( NW.EQ.1 ) THEN** Real 1x1 system.** C = ca A - w D*CSR = CA*A( 1, 1 ) - WR*D1CNORM = ABS( CSR )** If | C | < SMINI, use C = SMINI*IF( CNORM.LT.SMINI ) THENCSR = SMINICNORM = SMINIINFO = 1END IF** Check scaling for X = B / C*BNORM = ABS( B( 1, 1 ) )IF( CNORM.LT.ONE .AND. BNORM.GT.ONE ) THENIF( BNORM.GT.BIGNUM*CNORM )$ SCALE = ONE / BNORMEND IF** Compute X*X( 1, 1 ) = ( B( 1, 1 )*SCALE ) / CSRXNORM = ABS( X( 1, 1 ) )ELSE** Complex 1x1 system (w is complex)** C = ca A - w D*CSR = CA*A( 1, 1 ) - WR*D1CSI = -WI*D1CNORM = ABS( CSR ) + ABS( CSI )** If | C | < SMINI, use C = SMINI*IF( CNORM.LT.SMINI ) THENCSR = SMINICSI = ZEROCNORM = SMINIINFO = 1END IF** Check scaling for X = B / C*BNORM = ABS( B( 1, 1 ) ) + ABS( B( 1, 2 ) )IF( CNORM.LT.ONE .AND. BNORM.GT.ONE ) THENIF( BNORM.GT.BIGNUM*CNORM )$ SCALE = ONE / BNORMEND IF** Compute X*CALL DLADIV( SCALE*B( 1, 1 ), SCALE*B( 1, 2 ), CSR, CSI,$ X( 1, 1 ), X( 1, 2 ) )XNORM = ABS( X( 1, 1 ) ) + ABS( X( 1, 2 ) )END IF*ELSE** 2x2 System** Compute the real part of C = ca A - w D (or ca A' - w D )*CR( 1, 1 ) = CA*A( 1, 1 ) - WR*D1CR( 2, 2 ) = CA*A( 2, 2 ) - WR*D2IF( LTRANS ) THENCR( 1, 2 ) = CA*A( 2, 1 )CR( 2, 1 ) = CA*A( 1, 2 )ELSECR( 2, 1 ) = CA*A( 2, 1 )CR( 1, 2 ) = CA*A( 1, 2 )END IF*IF( NW.EQ.1 ) THEN** Real 2x2 system (w is real)** Find the largest element in C*CMAX = ZEROICMAX = 0*DO 10 J = 1, 4IF( ABS( CRV( J ) ).GT.CMAX ) THENCMAX = ABS( CRV( J ) )ICMAX = JEND IF10 CONTINUE** If norm(C) < SMINI, use SMINI*identity.*IF( CMAX.LT.SMINI ) THENBNORM = MAX( ABS( B( 1, 1 ) ), ABS( B( 2, 1 ) ) )IF( SMINI.LT.ONE .AND. BNORM.GT.ONE ) THENIF( BNORM.GT.BIGNUM*SMINI )$ SCALE = ONE / BNORMEND IFTEMP = SCALE / SMINIX( 1, 1 ) = TEMP*B( 1, 1 )X( 2, 1 ) = TEMP*B( 2, 1 )XNORM = TEMP*BNORMINFO = 1RETURNEND IF** Gaussian elimination with complete pivoting.*UR11 = CRV( ICMAX )CR21 = CRV( IPIVOT( 2, ICMAX ) )UR12 = CRV( IPIVOT( 3, ICMAX ) )CR22 = CRV( IPIVOT( 4, ICMAX ) )UR11R = ONE / UR11LR21 = UR11R*CR21UR22 = CR22 - UR12*LR21** If smaller pivot < SMINI, use SMINI*IF( ABS( UR22 ).LT.SMINI ) THENUR22 = SMINIINFO = 1END IFIF( RSWAP( ICMAX ) ) THENBR1 = B( 2, 1 )BR2 = B( 1, 1 )ELSEBR1 = B( 1, 1 )BR2 = B( 2, 1 )END IFBR2 = BR2 - LR21*BR1BBND = MAX( ABS( BR1*( UR22*UR11R ) ), ABS( BR2 ) )IF( BBND.GT.ONE .AND. ABS( UR22 ).LT.ONE ) THENIF( BBND.GE.BIGNUM*ABS( UR22 ) )$ SCALE = ONE / BBNDEND IF*XR2 = ( BR2*SCALE ) / UR22XR1 = ( SCALE*BR1 )*UR11R - XR2*( UR11R*UR12 )IF( ZSWAP( ICMAX ) ) THENX( 1, 1 ) = XR2X( 2, 1 ) = XR1ELSEX( 1, 1 ) = XR1X( 2, 1 ) = XR2END IFXNORM = MAX( ABS( XR1 ), ABS( XR2 ) )** Further scaling if norm(A) norm(X) > overflow*IF( XNORM.GT.ONE .AND. CMAX.GT.ONE ) THENIF( XNORM.GT.BIGNUM / CMAX ) THENTEMP = CMAX / BIGNUMX( 1, 1 ) = TEMP*X( 1, 1 )X( 2, 1 ) = TEMP*X( 2, 1 )XNORM = TEMP*XNORMSCALE = TEMP*SCALEEND IFEND IFELSE** Complex 2x2 system (w is complex)** Find the largest element in C*CI( 1, 1 ) = -WI*D1CI( 2, 1 ) = ZEROCI( 1, 2 ) = ZEROCI( 2, 2 ) = -WI*D2CMAX = ZEROICMAX = 0*DO 20 J = 1, 4IF( ABS( CRV( J ) )+ABS( CIV( J ) ).GT.CMAX ) THENCMAX = ABS( CRV( J ) ) + ABS( CIV( J ) )ICMAX = JEND IF20 CONTINUE** If norm(C) < SMINI, use SMINI*identity.*IF( CMAX.LT.SMINI ) THENBNORM = MAX( ABS( B( 1, 1 ) )+ABS( B( 1, 2 ) ),$ ABS( B( 2, 1 ) )+ABS( B( 2, 2 ) ) )IF( SMINI.LT.ONE .AND. BNORM.GT.ONE ) THENIF( BNORM.GT.BIGNUM*SMINI )$ SCALE = ONE / BNORMEND IFTEMP = SCALE / SMINIX( 1, 1 ) = TEMP*B( 1, 1 )X( 2, 1 ) = TEMP*B( 2, 1 )X( 1, 2 ) = TEMP*B( 1, 2 )X( 2, 2 ) = TEMP*B( 2, 2 )XNORM = TEMP*BNORMINFO = 1RETURNEND IF** Gaussian elimination with complete pivoting.*UR11 = CRV( ICMAX )UI11 = CIV( ICMAX )CR21 = CRV( IPIVOT( 2, ICMAX ) )CI21 = CIV( IPIVOT( 2, ICMAX ) )UR12 = CRV( IPIVOT( 3, ICMAX ) )UI12 = CIV( IPIVOT( 3, ICMAX ) )CR22 = CRV( IPIVOT( 4, ICMAX ) )CI22 = CIV( IPIVOT( 4, ICMAX ) )IF( ICMAX.EQ.1 .OR. ICMAX.EQ.4 ) THEN** Code when off-diagonals of pivoted C are real*IF( ABS( UR11 ).GT.ABS( UI11 ) ) THENTEMP = UI11 / UR11UR11R = ONE / ( UR11*( ONE+TEMP**2 ) )UI11R = -TEMP*UR11RELSETEMP = UR11 / UI11UI11R = -ONE / ( UI11*( ONE+TEMP**2 ) )UR11R = -TEMP*UI11REND IFLR21 = CR21*UR11RLI21 = CR21*UI11RUR12S = UR12*UR11RUI12S = UR12*UI11RUR22 = CR22 - UR12*LR21UI22 = CI22 - UR12*LI21ELSE** Code when diagonals of pivoted C are real*UR11R = ONE / UR11UI11R = ZEROLR21 = CR21*UR11RLI21 = CI21*UR11RUR12S = UR12*UR11RUI12S = UI12*UR11RUR22 = CR22 - UR12*LR21 + UI12*LI21UI22 = -UR12*LI21 - UI12*LR21END IFU22ABS = ABS( UR22 ) + ABS( UI22 )** If smaller pivot < SMINI, use SMINI*IF( U22ABS.LT.SMINI ) THENUR22 = SMINIUI22 = ZEROINFO = 1END IFIF( RSWAP( ICMAX ) ) THENBR2 = B( 1, 1 )BR1 = B( 2, 1 )BI2 = B( 1, 2 )BI1 = B( 2, 2 )ELSEBR1 = B( 1, 1 )BR2 = B( 2, 1 )BI1 = B( 1, 2 )BI2 = B( 2, 2 )END IFBR2 = BR2 - LR21*BR1 + LI21*BI1BI2 = BI2 - LI21*BR1 - LR21*BI1BBND = MAX( ( ABS( BR1 )+ABS( BI1 ) )*$ ( U22ABS*( ABS( UR11R )+ABS( UI11R ) ) ),$ ABS( BR2 )+ABS( BI2 ) )IF( BBND.GT.ONE .AND. U22ABS.LT.ONE ) THENIF( BBND.GE.BIGNUM*U22ABS ) THENSCALE = ONE / BBNDBR1 = SCALE*BR1BI1 = SCALE*BI1BR2 = SCALE*BR2BI2 = SCALE*BI2END IFEND IF*CALL DLADIV( BR2, BI2, UR22, UI22, XR2, XI2 )XR1 = UR11R*BR1 - UI11R*BI1 - UR12S*XR2 + UI12S*XI2XI1 = UI11R*BR1 + UR11R*BI1 - UI12S*XR2 - UR12S*XI2IF( ZSWAP( ICMAX ) ) THENX( 1, 1 ) = XR2X( 2, 1 ) = XR1X( 1, 2 ) = XI2X( 2, 2 ) = XI1ELSEX( 1, 1 ) = XR1X( 2, 1 ) = XR2X( 1, 2 ) = XI1X( 2, 2 ) = XI2END IFXNORM = MAX( ABS( XR1 )+ABS( XI1 ), ABS( XR2 )+ABS( XI2 ) )** Further scaling if norm(A) norm(X) > overflow*IF( XNORM.GT.ONE .AND. CMAX.GT.ONE ) THENIF( XNORM.GT.BIGNUM / CMAX ) THENTEMP = CMAX / BIGNUMX( 1, 1 ) = TEMP*X( 1, 1 )X( 2, 1 ) = TEMP*X( 2, 1 )X( 1, 2 ) = TEMP*X( 1, 2 )X( 2, 2 ) = TEMP*X( 2, 2 )XNORM = TEMP*XNORMSCALE = TEMP*SCALEEND IFEND IFEND IFEND IF*RETURN** End of DLALN2*ENDDOUBLE PRECISION FUNCTION DLAMCH( CMACH )** -- LAPACK auxiliary routine (version 3.0) --* Univ. of Tennessee, Univ. of California Berkeley, NAG Ltd.,* Courant Institute, Argonne National Lab, and Rice University* October 31, 1992** .. Scalar Arguments ..CHARACTER CMACH* ..** Purpose* =======** DLAMCH determines double precision machine parameters.** Arguments* =========** CMACH (input) CHARACTER*1* Specifies the value to be returned by DLAMCH:* = 'E' or 'e', DLAMCH := eps* = 'S' or 's , DLAMCH := sfmin* = 'B' or 'b', DLAMCH := base* = 'P' or 'p', DLAMCH := eps*base* = 'N' or 'n', DLAMCH := t* = 'R' or 'r', DLAMCH := rnd* = 'M' or 'm', DLAMCH := emin* = 'U' or 'u', DLAMCH := rmin* = 'L' or 'l', DLAMCH := emax* = 'O' or 'o', DLAMCH := rmax** where** eps = relative machine precision* sfmin = safe minimum, such that 1/sfmin does not overflow* base = base of the machine* prec = eps*base* t = number of (base) digits in the mantissa* rnd = 1.0 when rounding occurs in addition, 0.0 otherwise* emin = minimum exponent before (gradual) underflow* rmin = underflow threshold - base**(emin-1)* emax = largest exponent before overflow* rmax = overflow threshold - (base**emax)*(1-eps)** =====================================================================** .. Parameters ..DOUBLE PRECISION ONE, ZEROPARAMETER ( ONE = 1.0D+0, ZERO = 0.0D+0 )* ..* .. Local Scalars ..LOGICAL FIRST, LRNDINTEGER BETA, IMAX, IMIN, ITDOUBLE PRECISION BASE, EMAX, EMIN, EPS, PREC, RMACH, RMAX, RMIN,$ RND, SFMIN, SMALL, T* ..* .. External Functions ..LOGICAL LSAMEEXTERNAL LSAME* ..* .. External Subroutines ..EXTERNAL DLAMC2* ..* .. Save statement ..SAVE FIRST, EPS, SFMIN, BASE, T, RND, EMIN, RMIN,$ EMAX, RMAX, PREC* ..* .. Data statements ..DATA FIRST / .TRUE. /* ..* .. Executable Statements ..*IF( FIRST ) THENFIRST = .FALSE.CALL DLAMC2( BETA, IT, LRND, EPS, IMIN, RMIN, IMAX, RMAX )BASE = BETAT = ITIF( LRND ) THENRND = ONEEPS = ( BASE**( 1-IT ) ) / 2ELSERND = ZEROEPS = BASE**( 1-IT )END IFPREC = EPS*BASEEMIN = IMINEMAX = IMAXSFMIN = RMINSMALL = ONE / RMAXIF( SMALL.GE.SFMIN ) THEN** Use SMALL plus a bit, to avoid the possibility of rounding* causing overflow when computing 1/sfmin.*SFMIN = SMALL*( ONE+EPS )END IFEND IF*IF( LSAME( CMACH, 'E' ) ) THENRMACH = EPSELSE IF( LSAME( CMACH, 'S' ) ) THENRMACH = SFMINELSE IF( LSAME( CMACH, 'B' ) ) THENRMACH = BASEELSE IF( LSAME( CMACH, 'P' ) ) THENRMACH = PRECELSE IF( LSAME( CMACH, 'N' ) ) THENRMACH = TELSE IF( LSAME( CMACH, 'R' ) ) THENRMACH = RNDELSE IF( LSAME( CMACH, 'M' ) ) THENRMACH = EMINELSE IF( LSAME( CMACH, 'U' ) ) THENRMACH = RMINELSE IF( LSAME( CMACH, 'L' ) ) THENRMACH = EMAXELSE IF( LSAME( CMACH, 'O' ) ) THENRMACH = RMAXEND IF*DLAMCH = RMACHRETURN** End of DLAMCH*END**************************************************************************SUBROUTINE DLAMC1( BETA, T, RND, IEEE1 )** -- LAPACK auxiliary routine (version 3.0) --* Univ. of Tennessee, Univ. of California Berkeley, NAG Ltd.,* Courant Institute, Argonne National Lab, and Rice University* October 31, 1992** .. Scalar Arguments ..LOGICAL IEEE1, RNDINTEGER BETA, T* ..** Purpose* =======** DLAMC1 determines the machine parameters given by BETA, T, RND, and* IEEE1.** Arguments* =========** BETA (output) INTEGER* The base of the machine.** T (output) INTEGER* The number of ( BETA ) digits in the mantissa.** RND (output) LOGICAL* Specifies whether proper rounding ( RND = .TRUE. ) or* chopping ( RND = .FALSE. ) occurs in addition. This may not* be a reliable guide to the way in which the machine performs* its arithmetic.** IEEE1 (output) LOGICAL* Specifies whether rounding appears to be done in the IEEE* 'round to nearest' style.** Further Details* ===============** The routine is based on the routine ENVRON by Malcolm and* incorporates suggestions by Gentleman and Marovich. See** Malcolm M. A. (1972) Algorithms to reveal properties of* floating-point arithmetic. Comms. of the ACM, 15, 949-951.** Gentleman W. M. and Marovich S. B. (1974) More on algorithms* that reveal properties of floating point arithmetic units.* Comms. of the ACM, 17, 276-277.** =====================================================================** .. Local Scalars ..LOGICAL FIRST, LIEEE1, LRNDINTEGER LBETA, LTDOUBLE PRECISION A, B, C, F, ONE, QTR, SAVEC, T1, T2* ..* .. External Functions ..DOUBLE PRECISION DLAMC3EXTERNAL DLAMC3* ..* .. Save statement ..SAVE FIRST, LIEEE1, LBETA, LRND, LT* ..* .. Data statements ..DATA FIRST / .TRUE. /* ..* .. Executable Statements ..*IF( FIRST ) THENFIRST = .FALSE.ONE = 1** LBETA, LIEEE1, LT and LRND are the local values of BETA,* IEEE1, T and RND.** Throughout this routine we use the function DLAMC3 to ensure* that relevant values are stored and not held in registers, or* are not affected by optimizers.** Compute a = 2.0**m with the smallest positive integer m such* that** fl( a + 1.0 ) = a.*A = 1C = 1**+ WHILE( C.EQ.ONE )LOOP10 CONTINUEIF( C.EQ.ONE ) THENA = 2*AC = DLAMC3( A, ONE )C = DLAMC3( C, -A )GO TO 10END IF*+ END WHILE** Now compute b = 2.0**m with the smallest positive integer m* such that** fl( a + b ) .gt. a.*B = 1C = DLAMC3( A, B )**+ WHILE( C.EQ.A )LOOP20 CONTINUEIF( C.EQ.A ) THENB = 2*BC = DLAMC3( A, B )GO TO 20END IF*+ END WHILE** Now compute the base. a and c are neighbouring floating point* numbers in the interval ( beta**t, beta**( t + 1 ) ) and so* their difference is beta. Adding 0.25 to c is to ensure that it* is truncated to beta and not ( beta - 1 ).*QTR = ONE / 4SAVEC = CC = DLAMC3( C, -A )LBETA = C + QTR** Now determine whether rounding or chopping occurs, by adding a* bit less than beta/2 and a bit more than beta/2 to a.*B = LBETAF = DLAMC3( B / 2, -B / 100 )C = DLAMC3( F, A )IF( C.EQ.A ) THENLRND = .TRUE.ELSELRND = .FALSE.END IFF = DLAMC3( B / 2, B / 100 )C = DLAMC3( F, A )IF( ( LRND ) .AND. ( C.EQ.A ) )$ LRND = .FALSE.** Try and decide whether rounding is done in the IEEE 'round to* nearest' style. B/2 is half a unit in the last place of the two* numbers A and SAVEC. Furthermore, A is even, i.e. has last bit* zero, and SAVEC is odd. Thus adding B/2 to A should not change* A, but adding B/2 to SAVEC should change SAVEC.*T1 = DLAMC3( B / 2, A )T2 = DLAMC3( B / 2, SAVEC )LIEEE1 = ( T1.EQ.A ) .AND. ( T2.GT.SAVEC ) .AND. LRND** Now find the mantissa, t. It should be the integer part of* log to the base beta of a, however it is safer to determine t* by powering. So we find t as the smallest positive integer for* which** fl( beta**t + 1.0 ) = 1.0.*LT = 0A = 1C = 1**+ WHILE( C.EQ.ONE )LOOP30 CONTINUEIF( C.EQ.ONE ) THENLT = LT + 1A = A*LBETAC = DLAMC3( A, ONE )C = DLAMC3( C, -A )GO TO 30END IF*+ END WHILE*END IF*BETA = LBETAT = LTRND = LRNDIEEE1 = LIEEE1RETURN** End of DLAMC1*END**************************************************************************SUBROUTINE DLAMC2( BETA, T, RND, EPS, EMIN, RMIN, EMAX, RMAX )** -- LAPACK auxiliary routine (version 3.0) --* Univ. of Tennessee, Univ. of California Berkeley, NAG Ltd.,* Courant Institute, Argonne National Lab, and Rice University* October 31, 1992** .. Scalar Arguments ..LOGICAL RNDINTEGER BETA, EMAX, EMIN, TDOUBLE PRECISION EPS, RMAX, RMIN* ..** Purpose* =======** DLAMC2 determines the machine parameters specified in its argument* list.** Arguments* =========** BETA (output) INTEGER* The base of the machine.** T (output) INTEGER* The number of ( BETA ) digits in the mantissa.** RND (output) LOGICAL* Specifies whether proper rounding ( RND = .TRUE. ) or* chopping ( RND = .FALSE. ) occurs in addition. This may not* be a reliable guide to the way in which the machine performs* its arithmetic.** EPS (output) DOUBLE PRECISION* The smallest positive number such that** fl( 1.0 - EPS ) .LT. 1.0,** where fl denotes the computed value.** EMIN (output) INTEGER* The minimum exponent before (gradual) underflow occurs.** RMIN (output) DOUBLE PRECISION* The smallest normalized number for the machine, given by* BASE**( EMIN - 1 ), where BASE is the floating point value* of BETA.** EMAX (output) INTEGER* The maximum exponent before overflow occurs.** RMAX (output) DOUBLE PRECISION* The largest positive number for the machine, given by* BASE**EMAX * ( 1 - EPS ), where BASE is the floating point* value of BETA.** Further Details* ===============** The computation of EPS is based on a routine PARANOIA by* W. Kahan of the University of California at Berkeley.** =====================================================================** .. Local Scalars ..LOGICAL FIRST, IEEE, IWARN, LIEEE1, LRNDINTEGER GNMIN, GPMIN, I, LBETA, LEMAX, LEMIN, LT,$ NGNMIN, NGPMINDOUBLE PRECISION A, B, C, HALF, LEPS, LRMAX, LRMIN, ONE, RBASE,$ SIXTH, SMALL, THIRD, TWO, ZERO* ..* .. External Functions ..DOUBLE PRECISION DLAMC3EXTERNAL DLAMC3* ..* .. External Subroutines ..EXTERNAL DLAMC1, DLAMC4, DLAMC5* ..* .. Intrinsic Functions ..INTRINSIC ABS, MAX, MIN* ..* .. Save statement ..SAVE FIRST, IWARN, LBETA, LEMAX, LEMIN, LEPS, LRMAX,$ LRMIN, LT* ..* .. Data statements ..DATA FIRST / .TRUE. / , IWARN / .FALSE. /* ..* .. Executable Statements ..*IF( FIRST ) THENFIRST = .FALSE.ZERO = 0ONE = 1TWO = 2** LBETA, LT, LRND, LEPS, LEMIN and LRMIN are the local values of* BETA, T, RND, EPS, EMIN and RMIN.** Throughout this routine we use the function DLAMC3 to ensure* that relevant values are stored and not held in registers, or* are not affected by optimizers.** DLAMC1 returns the parameters LBETA, LT, LRND and LIEEE1.*CALL DLAMC1( LBETA, LT, LRND, LIEEE1 )** Start to find EPS.*B = LBETAA = B**( -LT )LEPS = A** Try some tricks to see whether or not this is the correct EPS.*B = TWO / 3HALF = ONE / 2SIXTH = DLAMC3( B, -HALF )THIRD = DLAMC3( SIXTH, SIXTH )B = DLAMC3( THIRD, -HALF )B = DLAMC3( B, SIXTH )B = ABS( B )IF( B.LT.LEPS )$ B = LEPS*LEPS = 1**+ WHILE( ( LEPS.GT.B ).AND.( B.GT.ZERO ) )LOOP10 CONTINUEIF( ( LEPS.GT.B ) .AND. ( B.GT.ZERO ) ) THENLEPS = BC = DLAMC3( HALF*LEPS, ( TWO**5 )*( LEPS**2 ) )C = DLAMC3( HALF, -C )B = DLAMC3( HALF, C )C = DLAMC3( HALF, -B )B = DLAMC3( HALF, C )GO TO 10END IF*+ END WHILE*IF( A.LT.LEPS )$ LEPS = A** Computation of EPS complete.** Now find EMIN. Let A = + or - 1, and + or - (1 + BASE**(-3)).* Keep dividing A by BETA until (gradual) underflow occurs. This* is detected when we cannot recover the previous A.*RBASE = ONE / LBETASMALL = ONEDO 20 I = 1, 3SMALL = DLAMC3( SMALL*RBASE, ZERO )20 CONTINUEA = DLAMC3( ONE, SMALL )CALL DLAMC4( NGPMIN, ONE, LBETA )CALL DLAMC4( NGNMIN, -ONE, LBETA )CALL DLAMC4( GPMIN, A, LBETA )CALL DLAMC4( GNMIN, -A, LBETA )IEEE = .FALSE.*IF( ( NGPMIN.EQ.NGNMIN ) .AND. ( GPMIN.EQ.GNMIN ) ) THENIF( NGPMIN.EQ.GPMIN ) THENLEMIN = NGPMIN* ( Non twos-complement machines, no gradual underflow;* e.g., VAX )ELSE IF( ( GPMIN-NGPMIN ).EQ.3 ) THENLEMIN = NGPMIN - 1 + LTIEEE = .TRUE.* ( Non twos-complement machines, with gradual underflow;* e.g., IEEE standard followers )ELSELEMIN = MIN( NGPMIN, GPMIN )* ( A guess; no known machine )IWARN = .TRUE.END IF*ELSE IF( ( NGPMIN.EQ.GPMIN ) .AND. ( NGNMIN.EQ.GNMIN ) ) THENIF( ABS( NGPMIN-NGNMIN ).EQ.1 ) THENLEMIN = MAX( NGPMIN, NGNMIN )* ( Twos-complement machines, no gradual underflow;* e.g., CYBER 205 )ELSELEMIN = MIN( NGPMIN, NGNMIN )* ( A guess; no known machine )IWARN = .TRUE.END IF*ELSE IF( ( ABS( NGPMIN-NGNMIN ).EQ.1 ) .AND.$ ( GPMIN.EQ.GNMIN ) ) THENIF( ( GPMIN-MIN( NGPMIN, NGNMIN ) ).EQ.3 ) THENLEMIN = MAX( NGPMIN, NGNMIN ) - 1 + LT* ( Twos-complement machines with gradual underflow;* no known machine )ELSELEMIN = MIN( NGPMIN, NGNMIN )* ( A guess; no known machine )IWARN = .TRUE.END IF*ELSELEMIN = MIN( NGPMIN, NGNMIN, GPMIN, GNMIN )* ( A guess; no known machine )IWARN = .TRUE.END IF**** Comment out this if block if EMIN is okIF( IWARN ) THENFIRST = .TRUE.WRITE( 6, FMT = 9999 )LEMINEND IF***** Assume IEEE arithmetic if we found denormalised numbers above,* or if arithmetic seems to round in the IEEE style, determined* in routine DLAMC1. A true IEEE machine should have both things* true; however, faulty machines may have one or the other.*IEEE = IEEE .OR. LIEEE1** Compute RMIN by successive division by BETA. We could compute* RMIN as BASE**( EMIN - 1 ), but some machines underflow during* this computation.*LRMIN = 1DO 30 I = 1, 1 - LEMINLRMIN = DLAMC3( LRMIN*RBASE, ZERO )30 CONTINUE** Finally, call DLAMC5 to compute EMAX and RMAX.*CALL DLAMC5( LBETA, LT, LEMIN, IEEE, LEMAX, LRMAX )END IF*BETA = LBETAT = LTRND = LRNDEPS = LEPSEMIN = LEMINRMIN = LRMINEMAX = LEMAXRMAX = LRMAX*RETURN*9999 FORMAT( / / ' WARNING. The value EMIN may be incorrect:-',$ ' EMIN = ', I8, /$ ' If, after inspection, the value EMIN looks',$ ' acceptable please comment out ',$ / ' the IF block as marked within the code of routine',$ ' DLAMC2,', / ' otherwise supply EMIN explicitly.', / )** End of DLAMC2*END**************************************************************************DOUBLE PRECISION FUNCTION DLAMC3( A, B )** -- LAPACK auxiliary routine (version 3.0) --* Univ. of Tennessee, Univ. of California Berkeley, NAG Ltd.,* Courant Institute, Argonne National Lab, and Rice University* October 31, 1992** .. Scalar Arguments ..DOUBLE PRECISION A, B* ..** Purpose* =======** DLAMC3 is intended to force A and B to be stored prior to doing* the addition of A and B , for use in situations where optimizers* might hold one of these in a register.** Arguments* =========** A, B (input) DOUBLE PRECISION* The values A and B.** =====================================================================** .. Executable Statements ..*DLAMC3 = A + B*RETURN** End of DLAMC3*END**************************************************************************SUBROUTINE DLAMC4( EMIN, START, BASE )** -- LAPACK auxiliary routine (version 3.0) --* Univ. of Tennessee, Univ. of California Berkeley, NAG Ltd.,* Courant Institute, Argonne National Lab, and Rice University* October 31, 1992** .. Scalar Arguments ..INTEGER BASE, EMINDOUBLE PRECISION START* ..** Purpose* =======** DLAMC4 is a service routine for DLAMC2.** Arguments* =========** EMIN (output) EMIN* The minimum exponent before (gradual) underflow, computed by* setting A = START and dividing by BASE until the previous A* can not be recovered.** START (input) DOUBLE PRECISION* The starting point for determining EMIN.** BASE (input) INTEGER* The base of the machine.** =====================================================================** .. Local Scalars ..INTEGER IDOUBLE PRECISION A, B1, B2, C1, C2, D1, D2, ONE, RBASE, ZERO* ..* .. External Functions ..DOUBLE PRECISION DLAMC3EXTERNAL DLAMC3* ..* .. Executable Statements ..*A = STARTONE = 1RBASE = ONE / BASEZERO = 0EMIN = 1B1 = DLAMC3( A*RBASE, ZERO )C1 = AC2 = AD1 = AD2 = A*+ WHILE( ( C1.EQ.A ).AND.( C2.EQ.A ).AND.* $ ( D1.EQ.A ).AND.( D2.EQ.A ) )LOOP10 CONTINUEIF( ( C1.EQ.A ) .AND. ( C2.EQ.A ) .AND. ( D1.EQ.A ) .AND.$ ( D2.EQ.A ) ) THENEMIN = EMIN - 1A = B1B1 = DLAMC3( A / BASE, ZERO )C1 = DLAMC3( B1*BASE, ZERO )D1 = ZERODO 20 I = 1, BASED1 = D1 + B120 CONTINUEB2 = DLAMC3( A*RBASE, ZERO )C2 = DLAMC3( B2 / RBASE, ZERO )D2 = ZERODO 30 I = 1, BASED2 = D2 + B230 CONTINUEGO TO 10END IF*+ END WHILE*RETURN** End of DLAMC4*END**************************************************************************SUBROUTINE DLAMC5( BETA, P, EMIN, IEEE, EMAX, RMAX )** -- LAPACK auxiliary routine (version 3.0) --* Univ. of Tennessee, Univ. of California Berkeley, NAG Ltd.,* Courant Institute, Argonne National Lab, and Rice University* October 31, 1992** .. Scalar Arguments ..LOGICAL IEEEINTEGER BETA, EMAX, EMIN, PDOUBLE PRECISION RMAX* ..** Purpose* =======** DLAMC5 attempts to compute RMAX, the largest machine floating-point* number, without overflow. It assumes that EMAX + abs(EMIN) sum* approximately to a power of 2. It will fail on machines where this* assumption does not hold, for example, the Cyber 205 (EMIN = -28625,* EMAX = 28718). It will also fail if the value supplied for EMIN is* too large (i.e. too close to zero), probably with overflow.** Arguments* =========** BETA (input) INTEGER* The base of floating-point arithmetic.** P (input) INTEGER* The number of base BETA digits in the mantissa of a* floating-point value.** EMIN (input) INTEGER* The minimum exponent before (gradual) underflow.** IEEE (input) LOGICAL* A logical flag specifying whether or not the arithmetic* system is thought to comply with the IEEE standard.** EMAX (output) INTEGER* The largest exponent before overflow** RMAX (output) DOUBLE PRECISION* The largest machine floating-point number.** =====================================================================** .. Parameters ..DOUBLE PRECISION ZERO, ONEPARAMETER ( ZERO = 0.0D0, ONE = 1.0D0 )* ..* .. Local Scalars ..INTEGER EXBITS, EXPSUM, I, LEXP, NBITS, TRY, UEXPDOUBLE PRECISION OLDY, RECBAS, Y, Z* ..* .. External Functions ..DOUBLE PRECISION DLAMC3EXTERNAL DLAMC3* ..* .. Intrinsic Functions ..INTRINSIC MOD* ..* .. Executable Statements ..** First compute LEXP and UEXP, two powers of 2 that bound* abs(EMIN). We then assume that EMAX + abs(EMIN) will sum* approximately to the bound that is closest to abs(EMIN).* (EMAX is the exponent of the required number RMAX).*LEXP = 1EXBITS = 110 CONTINUETRY = LEXP*2IF( TRY.LE.( -EMIN ) ) THENLEXP = TRYEXBITS = EXBITS + 1GO TO 10END IFIF( LEXP.EQ.-EMIN ) THENUEXP = LEXPELSEUEXP = TRYEXBITS = EXBITS + 1END IF** Now -LEXP is less than or equal to EMIN, and -UEXP is greater* than or equal to EMIN. EXBITS is the number of bits needed to* store the exponent.*IF( ( UEXP+EMIN ).GT.( -LEXP-EMIN ) ) THENEXPSUM = 2*LEXPELSEEXPSUM = 2*UEXPEND IF** EXPSUM is the exponent range, approximately equal to* EMAX - EMIN + 1 .*EMAX = EXPSUM + EMIN - 1NBITS = 1 + EXBITS + P** NBITS is the total number of bits needed to store a* floating-point number.*IF( ( MOD( NBITS, 2 ).EQ.1 ) .AND. ( BETA.EQ.2 ) ) THEN** Either there are an odd number of bits used to store a* floating-point number, which is unlikely, or some bits are* not used in the representation of numbers, which is possible,* (e.g. Cray machines) or the mantissa has an implicit bit,* (e.g. IEEE machines, Dec Vax machines), which is perhaps the* most likely. We have to assume the last alternative.* If this is true, then we need to reduce EMAX by one because* there must be some way of representing zero in an implicit-bit* system. On machines like Cray, we are reducing EMAX by one* unnecessarily.*EMAX = EMAX - 1END IF*IF( IEEE ) THEN** Assume we are on an IEEE machine which reserves one exponent* for infinity and NaN.*EMAX = EMAX - 1END IF** Now create RMAX, the largest machine number, which should* be equal to (1.0 - BETA**(-P)) * BETA**EMAX .** First compute 1.0 - BETA**(-P), being careful that the* result is less than 1.0 .*RECBAS = ONE / BETAZ = BETA - ONEY = ZERODO 20 I = 1, PZ = Z*RECBASIF( Y.LT.ONE )$ OLDY = YY = DLAMC3( Y, Z )20 CONTINUEIF( Y.GE.ONE )$ Y = OLDY** Now multiply by BETA**EMAX to get RMAX.*DO 30 I = 1, EMAXY = DLAMC3( Y*BETA, ZERO )30 CONTINUE*RMAX = YRETURN** End of DLAMC5*ENDDOUBLE PRECISION FUNCTION DLANGE( NORM, M, N, A, LDA, WORK )** -- LAPACK auxiliary routine (version 3.0) --* Univ. of Tennessee, Univ. of California Berkeley, NAG Ltd.,* Courant Institute, Argonne National Lab, and Rice University* October 31, 1992** .. Scalar Arguments ..CHARACTER NORMINTEGER LDA, M, N* ..* .. Array Arguments ..DOUBLE PRECISION A( LDA, * ), WORK( * )* ..** Purpose* =======** DLANGE returns the value of the one norm, or the Frobenius norm, or* the infinity norm, or the element of largest absolute value of a* real matrix A.** Description* ===========** DLANGE returns the value** DLANGE = ( max(abs(A(i,j))), NORM = 'M' or 'm'* (* ( norm1(A), NORM = '1', 'O' or 'o'* (* ( normI(A), NORM = 'I' or 'i'* (* ( normF(A), NORM = 'F', 'f', 'E' or 'e'** where norm1 denotes the one norm of a matrix (maximum column sum),* normI denotes the infinity norm of a matrix (maximum row sum) and* normF denotes the Frobenius norm of a matrix (square root of sum of* squares). Note that max(abs(A(i,j))) is not a matrix norm.** Arguments* =========** NORM (input) CHARACTER*1* Specifies the value to be returned in DLANGE as described* above.** M (input) INTEGER* The number of rows of the matrix A. M >= 0. When M = 0,* DLANGE is set to zero.** N (input) INTEGER* The number of columns of the matrix A. N >= 0. When N = 0,* DLANGE is set to zero.** A (input) DOUBLE PRECISION array, dimension (LDA,N)* The m by n matrix A.** LDA (input) INTEGER* The leading dimension of the array A. LDA >= max(M,1).** WORK (workspace) DOUBLE PRECISION array, dimension (LWORK),* where LWORK >= M when NORM = 'I'; otherwise, WORK is not* referenced.** =====================================================================** .. Parameters ..DOUBLE PRECISION ONE, ZEROPARAMETER ( ONE = 1.0D+0, ZERO = 0.0D+0 )* ..* .. Local Scalars ..INTEGER I, JDOUBLE PRECISION SCALE, SUM, VALUE* ..* .. External Subroutines ..EXTERNAL DLASSQ* ..* .. External Functions ..LOGICAL LSAMEEXTERNAL LSAME* ..* .. Intrinsic Functions ..INTRINSIC ABS, MAX, MIN, SQRT* ..* .. Executable Statements ..*IF( MIN( M, N ).EQ.0 ) THENVALUE = ZEROELSE IF( LSAME( NORM, 'M' ) ) THEN** Find max(abs(A(i,j))).*VALUE = ZERODO 20 J = 1, NDO 10 I = 1, MVALUE = MAX( VALUE, ABS( A( I, J ) ) )10 CONTINUE20 CONTINUEELSE IF( ( LSAME( NORM, 'O' ) ) .OR. ( NORM.EQ.'1' ) ) THEN** Find norm1(A).*VALUE = ZERODO 40 J = 1, NSUM = ZERODO 30 I = 1, MSUM = SUM + ABS( A( I, J ) )30 CONTINUEVALUE = MAX( VALUE, SUM )40 CONTINUEELSE IF( LSAME( NORM, 'I' ) ) THEN** Find normI(A).*DO 50 I = 1, MWORK( I ) = ZERO50 CONTINUEDO 70 J = 1, NDO 60 I = 1, MWORK( I ) = WORK( I ) + ABS( A( I, J ) )60 CONTINUE70 CONTINUEVALUE = ZERODO 80 I = 1, MVALUE = MAX( VALUE, WORK( I ) )80 CONTINUEELSE IF( ( LSAME( NORM, 'F' ) ) .OR. ( LSAME( NORM, 'E' ) ) ) THEN** Find normF(A).*SCALE = ZEROSUM = ONEDO 90 J = 1, NCALL DLASSQ( M, A( 1, J ), 1, SCALE, SUM )90 CONTINUEVALUE = SCALE*SQRT( SUM )END IF*DLANGE = VALUERETURN** End of DLANGE*ENDDOUBLE PRECISION FUNCTION DLANHS( NORM, N, A, LDA, WORK )** -- LAPACK auxiliary routine (version 3.0) --* Univ. of Tennessee, Univ. of California Berkeley, NAG Ltd.,* Courant Institute, Argonne National Lab, and Rice University* October 31, 1992** .. Scalar Arguments ..CHARACTER NORMINTEGER LDA, N* ..* .. Array Arguments ..DOUBLE PRECISION A( LDA, * ), WORK( * )* ..** Purpose* =======** DLANHS returns the value of the one norm, or the Frobenius norm, or* the infinity norm, or the element of largest absolute value of a* Hessenberg matrix A.** Description* ===========** DLANHS returns the value** DLANHS = ( max(abs(A(i,j))), NORM = 'M' or 'm'* (* ( norm1(A), NORM = '1', 'O' or 'o'* (* ( normI(A), NORM = 'I' or 'i'* (* ( normF(A), NORM = 'F', 'f', 'E' or 'e'** where norm1 denotes the one norm of a matrix (maximum column sum),* normI denotes the infinity norm of a matrix (maximum row sum) and* normF denotes the Frobenius norm of a matrix (square root of sum of* squares). Note that max(abs(A(i,j))) is not a matrix norm.** Arguments* =========** NORM (input) CHARACTER*1* Specifies the value to be returned in DLANHS as described* above.** N (input) INTEGER* The order of the matrix A. N >= 0. When N = 0, DLANHS is* set to zero.** A (input) DOUBLE PRECISION array, dimension (LDA,N)* The n by n upper Hessenberg matrix A; the part of A below the* first sub-diagonal is not referenced.** LDA (input) INTEGER* The leading dimension of the array A. LDA >= max(N,1).** WORK (workspace) DOUBLE PRECISION array, dimension (LWORK),* where LWORK >= N when NORM = 'I'; otherwise, WORK is not* referenced.** =====================================================================** .. Parameters ..DOUBLE PRECISION ONE, ZEROPARAMETER ( ONE = 1.0D+0, ZERO = 0.0D+0 )* ..* .. Local Scalars ..INTEGER I, JDOUBLE PRECISION SCALE, SUM, VALUE* ..* .. External Subroutines ..EXTERNAL DLASSQ* ..* .. External Functions ..LOGICAL LSAMEEXTERNAL LSAME* ..* .. Intrinsic Functions ..INTRINSIC ABS, MAX, MIN, SQRT* ..* .. Executable Statements ..*IF( N.EQ.0 ) THENVALUE = ZEROELSE IF( LSAME( NORM, 'M' ) ) THEN** Find max(abs(A(i,j))).*VALUE = ZERODO 20 J = 1, NDO 10 I = 1, MIN( N, J+1 )VALUE = MAX( VALUE, ABS( A( I, J ) ) )10 CONTINUE20 CONTINUEELSE IF( ( LSAME( NORM, 'O' ) ) .OR. ( NORM.EQ.'1' ) ) THEN** Find norm1(A).*VALUE = ZERODO 40 J = 1, NSUM = ZERODO 30 I = 1, MIN( N, J+1 )SUM = SUM + ABS( A( I, J ) )30 CONTINUEVALUE = MAX( VALUE, SUM )40 CONTINUEELSE IF( LSAME( NORM, 'I' ) ) THEN** Find normI(A).*DO 50 I = 1, NWORK( I ) = ZERO50 CONTINUEDO 70 J = 1, NDO 60 I = 1, MIN( N, J+1 )WORK( I ) = WORK( I ) + ABS( A( I, J ) )60 CONTINUE70 CONTINUEVALUE = ZERODO 80 I = 1, NVALUE = MAX( VALUE, WORK( I ) )80 CONTINUEELSE IF( ( LSAME( NORM, 'F' ) ) .OR. ( LSAME( NORM, 'E' ) ) ) THEN** Find normF(A).*SCALE = ZEROSUM = ONEDO 90 J = 1, NCALL DLASSQ( MIN( N, J+1 ), A( 1, J ), 1, SCALE, SUM )90 CONTINUEVALUE = SCALE*SQRT( SUM )END IF*DLANHS = VALUERETURN** End of DLANHS*ENDDOUBLE PRECISION FUNCTION DLANST( NORM, N, D, E )** -- LAPACK auxiliary routine (version 3.0) --* Univ. of Tennessee, Univ. of California Berkeley, NAG Ltd.,* Courant Institute, Argonne National Lab, and Rice University* February 29, 1992** .. Scalar Arguments ..CHARACTER NORMINTEGER N* ..* .. Array Arguments ..DOUBLE PRECISION D( * ), E( * )* ..** Purpose* =======** DLANST returns the value of the one norm, or the Frobenius norm, or* the infinity norm, or the element of largest absolute value of a* real symmetric tridiagonal matrix A.** Description* ===========** DLANST returns the value** DLANST = ( max(abs(A(i,j))), NORM = 'M' or 'm'* (* ( norm1(A), NORM = '1', 'O' or 'o'* (* ( normI(A), NORM = 'I' or 'i'* (* ( normF(A), NORM = 'F', 'f', 'E' or 'e'** where norm1 denotes the one norm of a matrix (maximum column sum),* normI denotes the infinity norm of a matrix (maximum row sum) and* normF denotes the Frobenius norm of a matrix (square root of sum of* squares). Note that max(abs(A(i,j))) is not a matrix norm.** Arguments* =========** NORM (input) CHARACTER*1* Specifies the value to be returned in DLANST as described* above.** N (input) INTEGER* The order of the matrix A. N >= 0. When N = 0, DLANST is* set to zero.** D (input) DOUBLE PRECISION array, dimension (N)* The diagonal elements of A.** E (input) DOUBLE PRECISION array, dimension (N-1)* The (n-1) sub-diagonal or super-diagonal elements of A.** =====================================================================** .. Parameters ..DOUBLE PRECISION ONE, ZEROPARAMETER ( ONE = 1.0D+0, ZERO = 0.0D+0 )* ..* .. Local Scalars ..INTEGER IDOUBLE PRECISION ANORM, SCALE, SUM* ..* .. External Functions ..LOGICAL LSAMEEXTERNAL LSAME* ..* .. External Subroutines ..EXTERNAL DLASSQ* ..* .. Intrinsic Functions ..INTRINSIC ABS, MAX, SQRT* ..* .. Executable Statements ..*IF( N.LE.0 ) THENANORM = ZEROELSE IF( LSAME( NORM, 'M' ) ) THEN** Find max(abs(A(i,j))).*ANORM = ABS( D( N ) )DO 10 I = 1, N - 1ANORM = MAX( ANORM, ABS( D( I ) ) )ANORM = MAX( ANORM, ABS( E( I ) ) )10 CONTINUEELSE IF( LSAME( NORM, 'O' ) .OR. NORM.EQ.'1' .OR.$ LSAME( NORM, 'I' ) ) THEN** Find norm1(A).*IF( N.EQ.1 ) THENANORM = ABS( D( 1 ) )ELSEANORM = MAX( ABS( D( 1 ) )+ABS( E( 1 ) ),$ ABS( E( N-1 ) )+ABS( D( N ) ) )DO 20 I = 2, N - 1ANORM = MAX( ANORM, ABS( D( I ) )+ABS( E( I ) )+$ ABS( E( I-1 ) ) )20 CONTINUEEND IFELSE IF( ( LSAME( NORM, 'F' ) ) .OR. ( LSAME( NORM, 'E' ) ) ) THEN** Find normF(A).*SCALE = ZEROSUM = ONEIF( N.GT.1 ) THENCALL DLASSQ( N-1, E, 1, SCALE, SUM )SUM = 2*SUMEND IFCALL DLASSQ( N, D, 1, SCALE, SUM )ANORM = SCALE*SQRT( SUM )END IF*DLANST = ANORMRETURN** End of DLANST*ENDDOUBLE PRECISION FUNCTION DLANSY( NORM, UPLO, N, A, LDA, WORK )** -- LAPACK auxiliary routine (version 3.0) --* Univ. of Tennessee, Univ. of California Berkeley, NAG Ltd.,* Courant Institute, Argonne National Lab, and Rice University* October 31, 1992** .. Scalar Arguments ..CHARACTER NORM, UPLOINTEGER LDA, N* ..* .. Array Arguments ..DOUBLE PRECISION A( LDA, * ), WORK( * )* ..** Purpose* =======** DLANSY returns the value of the one norm, or the Frobenius norm, or* the infinity norm, or the element of largest absolute value of a* real symmetric matrix A.** Description* ===========** DLANSY returns the value** DLANSY = ( max(abs(A(i,j))), NORM = 'M' or 'm'* (* ( norm1(A), NORM = '1', 'O' or 'o'* (* ( normI(A), NORM = 'I' or 'i'* (* ( normF(A), NORM = 'F', 'f', 'E' or 'e'** where norm1 denotes the one norm of a matrix (maximum column sum),* normI denotes the infinity norm of a matrix (maximum row sum) and* normF denotes the Frobenius norm of a matrix (square root of sum of* squares). Note that max(abs(A(i,j))) is not a matrix norm.** Arguments* =========** NORM (input) CHARACTER*1* Specifies the value to be returned in DLANSY as described* above.** UPLO (input) CHARACTER*1* Specifies whether the upper or lower triangular part of the* symmetric matrix A is to be referenced.* = 'U': Upper triangular part of A is referenced* = 'L': Lower triangular part of A is referenced** N (input) INTEGER* The order of the matrix A. N >= 0. When N = 0, DLANSY is* set to zero.** A (input) DOUBLE PRECISION array, dimension (LDA,N)* The symmetric matrix A. If UPLO = 'U', the leading n by n* upper triangular part of A contains the upper triangular part* of the matrix A, and the strictly lower triangular part of A* is not referenced. If UPLO = 'L', the leading n by n lower* triangular part of A contains the lower triangular part of* the matrix A, and the strictly upper triangular part of A is* not referenced.** LDA (input) INTEGER* The leading dimension of the array A. LDA >= max(N,1).** WORK (workspace) DOUBLE PRECISION array, dimension (LWORK),* where LWORK >= N when NORM = 'I' or '1' or 'O'; otherwise,* WORK is not referenced.** =====================================================================** .. Parameters ..DOUBLE PRECISION ONE, ZEROPARAMETER ( ONE = 1.0D+0, ZERO = 0.0D+0 )* ..* .. Local Scalars ..INTEGER I, JDOUBLE PRECISION ABSA, SCALE, SUM, VALUE* ..* .. External Subroutines ..EXTERNAL DLASSQ* ..* .. External Functions ..LOGICAL LSAMEEXTERNAL LSAME* ..* .. Intrinsic Functions ..INTRINSIC ABS, MAX, SQRT* ..* .. Executable Statements ..*IF( N.EQ.0 ) THENVALUE = ZEROELSE IF( LSAME( NORM, 'M' ) ) THEN** Find max(abs(A(i,j))).*VALUE = ZEROIF( LSAME( UPLO, 'U' ) ) THENDO 20 J = 1, NDO 10 I = 1, JVALUE = MAX( VALUE, ABS( A( I, J ) ) )10 CONTINUE20 CONTINUEELSEDO 40 J = 1, NDO 30 I = J, NVALUE = MAX( VALUE, ABS( A( I, J ) ) )30 CONTINUE40 CONTINUEEND IFELSE IF( ( LSAME( NORM, 'I' ) ) .OR. ( LSAME( NORM, 'O' ) ) .OR.$ ( NORM.EQ.'1' ) ) THEN** Find normI(A) ( = norm1(A), since A is symmetric).*VALUE = ZEROIF( LSAME( UPLO, 'U' ) ) THENDO 60 J = 1, NSUM = ZERODO 50 I = 1, J - 1ABSA = ABS( A( I, J ) )SUM = SUM + ABSAWORK( I ) = WORK( I ) + ABSA50 CONTINUEWORK( J ) = SUM + ABS( A( J, J ) )60 CONTINUEDO 70 I = 1, NVALUE = MAX( VALUE, WORK( I ) )70 CONTINUEELSEDO 80 I = 1, NWORK( I ) = ZERO80 CONTINUEDO 100 J = 1, NSUM = WORK( J ) + ABS( A( J, J ) )DO 90 I = J + 1, NABSA = ABS( A( I, J ) )SUM = SUM + ABSAWORK( I ) = WORK( I ) + ABSA90 CONTINUEVALUE = MAX( VALUE, SUM )100 CONTINUEEND IFELSE IF( ( LSAME( NORM, 'F' ) ) .OR. ( LSAME( NORM, 'E' ) ) ) THEN** Find normF(A).*SCALE = ZEROSUM = ONEIF( LSAME( UPLO, 'U' ) ) THENDO 110 J = 2, NCALL DLASSQ( J-1, A( 1, J ), 1, SCALE, SUM )110 CONTINUEELSEDO 120 J = 1, N - 1CALL DLASSQ( N-J, A( J+1, J ), 1, SCALE, SUM )120 CONTINUEEND IFSUM = 2*SUMCALL DLASSQ( N, A, LDA+1, SCALE, SUM )VALUE = SCALE*SQRT( SUM )END IF*DLANSY = VALUERETURN** End of DLANSY*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*ENDDOUBLE PRECISION FUNCTION DLAPY2( X, Y )** -- LAPACK auxiliary routine (version 3.0) --* Univ. of Tennessee, Univ. of California Berkeley, NAG Ltd.,* Courant Institute, Argonne National Lab, and Rice University* October 31, 1992** .. Scalar Arguments ..DOUBLE PRECISION X, Y* ..** Purpose* =======** DLAPY2 returns sqrt(x**2+y**2), taking care not to cause unnecessary* overflow.** Arguments* =========** X (input) DOUBLE PRECISION* Y (input) DOUBLE PRECISION* X and Y specify the values x and y.** =====================================================================** .. Parameters ..DOUBLE PRECISION ZEROPARAMETER ( ZERO = 0.0D0 )DOUBLE PRECISION ONEPARAMETER ( ONE = 1.0D0 )* ..* .. Local Scalars ..DOUBLE PRECISION W, XABS, YABS, Z* ..* .. Intrinsic Functions ..INTRINSIC ABS, MAX, MIN, SQRT* ..* .. Executable Statements ..*XABS = ABS( X )YABS = ABS( Y )W = MAX( XABS, YABS )Z = MIN( XABS, YABS )IF( Z.EQ.ZERO ) THENDLAPY2 = WELSEDLAPY2 = W*SQRT( ONE+( Z / W )**2 )END IFRETURN** End of DLAPY2*ENDSUBROUTINE DLAQTR( LTRAN, LREAL, N, T, LDT, B, W, SCALE, X, WORK,$ INFO )** -- LAPACK auxiliary routine (version 3.0) --* Univ. of Tennessee, Univ. of California Berkeley, NAG Ltd.,* Courant Institute, Argonne National Lab, and Rice University* June 30, 1999** .. Scalar Arguments ..LOGICAL LREAL, LTRANINTEGER INFO, LDT, NDOUBLE PRECISION SCALE, W* ..* .. Array Arguments ..DOUBLE PRECISION B( * ), T( LDT, * ), WORK( * ), X( * )* ..** Purpose* =======** DLAQTR solves the real quasi-triangular system** op(T)*p = scale*c, if LREAL = .TRUE.** or the complex quasi-triangular systems** op(T + iB)*(p+iq) = scale*(c+id), if LREAL = .FALSE.** in real arithmetic, where T is upper quasi-triangular.* If LREAL = .FALSE., then the first diagonal block of T must be* 1 by 1, B is the specially structured matrix** B = [ b(1) b(2) ... b(n) ]* [ w ]* [ w ]* [ . ]* [ w ]** op(A) = A or A', A' denotes the conjugate transpose of* matrix A.** On input, X = [ c ]. On output, X = [ p ].* [ d ] [ q ]** This subroutine is designed for the condition number estimation* in routine DTRSNA.** Arguments* =========** LTRAN (input) LOGICAL* On entry, LTRAN specifies the option of conjugate transpose:* = .FALSE., op(T+i*B) = T+i*B,* = .TRUE., op(T+i*B) = (T+i*B)'.** LREAL (input) LOGICAL* On entry, LREAL specifies the input matrix structure:* = .FALSE., the input is complex* = .TRUE., the input is real** N (input) INTEGER* On entry, N specifies the order of T+i*B. N >= 0.** T (input) DOUBLE PRECISION array, dimension (LDT,N)* On entry, T contains a matrix in Schur canonical form.* If LREAL = .FALSE., then the first diagonal block of T mu* be 1 by 1.** LDT (input) INTEGER* The leading dimension of the matrix T. LDT >= max(1,N).** B (input) DOUBLE PRECISION array, dimension (N)* On entry, B contains the elements to form the matrix* B as described above.* If LREAL = .TRUE., B is not referenced.** W (input) DOUBLE PRECISION* On entry, W is the diagonal element of the matrix B.* If LREAL = .TRUE., W is not referenced.** SCALE (output) DOUBLE PRECISION* On exit, SCALE is the scale factor.** X (input/output) DOUBLE PRECISION array, dimension (2*N)* On entry, X contains the right hand side of the system.* On exit, X is overwritten by the solution.** WORK (workspace) DOUBLE PRECISION array, dimension (N)** INFO (output) INTEGER* On exit, INFO is set to* 0: successful exit.* 1: the some diagonal 1 by 1 block has been perturbed by* a small number SMIN to keep nonsingularity.* 2: the some diagonal 2 by 2 block has been perturbed by* a small number in DLALN2 to keep nonsingularity.* NOTE: In the interests of speed, this routine does not* check the inputs for errors.** =====================================================================** .. Parameters ..DOUBLE PRECISION ZERO, ONEPARAMETER ( ZERO = 0.0D+0, ONE = 1.0D+0 )* ..* .. Local Scalars ..LOGICAL NOTRANINTEGER I, IERR, J, J1, J2, JNEXT, K, N1, N2DOUBLE PRECISION BIGNUM, EPS, REC, SCALOC, SI, SMIN, SMINW,$ SMLNUM, SR, TJJ, TMP, XJ, XMAX, XNORM, Z* ..* .. Local Arrays ..DOUBLE PRECISION D( 2, 2 ), V( 2, 2 )* ..* .. External Functions ..INTEGER IDAMAXDOUBLE PRECISION DASUM, DDOT, DLAMCH, DLANGEEXTERNAL IDAMAX, DASUM, DDOT, DLAMCH, DLANGE* ..* .. External Subroutines ..EXTERNAL DAXPY, DLADIV, DLALN2, DSCAL* ..* .. Intrinsic Functions ..INTRINSIC ABS, MAX* ..* .. Executable Statements ..** Do not test the input parameters for errors*NOTRAN = .NOT.LTRANINFO = 0** Quick return if possible*IF( N.EQ.0 )$ RETURN** Set constants to control overflow*EPS = DLAMCH( 'P' )SMLNUM = DLAMCH( 'S' ) / EPSBIGNUM = ONE / SMLNUM*XNORM = DLANGE( 'M', N, N, T, LDT, D )IF( .NOT.LREAL )$ XNORM = MAX( XNORM, ABS( W ), DLANGE( 'M', N, 1, B, N, D ) )SMIN = MAX( SMLNUM, EPS*XNORM )** Compute 1-norm of each column of strictly upper triangular* part of T to control overflow in triangular solver.*WORK( 1 ) = ZERODO 10 J = 2, NWORK( J ) = DASUM( J-1, T( 1, J ), 1 )10 CONTINUE*IF( .NOT.LREAL ) THENDO 20 I = 2, NWORK( I ) = WORK( I ) + ABS( B( I ) )20 CONTINUEEND IF*N2 = 2*NN1 = NIF( .NOT.LREAL )$ N1 = N2K = IDAMAX( N1, X, 1 )XMAX = ABS( X( K ) )SCALE = ONE*IF( XMAX.GT.BIGNUM ) THENSCALE = BIGNUM / XMAXCALL DSCAL( N1, SCALE, X, 1 )XMAX = BIGNUMEND IF*IF( LREAL ) THEN*IF( NOTRAN ) THEN** Solve T*p = scale*c*JNEXT = NDO 30 J = N, 1, -1IF( J.GT.JNEXT )$ GO TO 30J1 = JJ2 = JJNEXT = J - 1IF( J.GT.1 ) THENIF( T( J, J-1 ).NE.ZERO ) THENJ1 = J - 1JNEXT = J - 2END IFEND IF*IF( J1.EQ.J2 ) THEN** Meet 1 by 1 diagonal block** Scale to avoid overflow when computing* x(j) = b(j)/T(j,j)*XJ = ABS( X( J1 ) )TJJ = ABS( T( J1, J1 ) )TMP = T( J1, J1 )IF( TJJ.LT.SMIN ) THENTMP = SMINTJJ = SMININFO = 1END IF*IF( XJ.EQ.ZERO )$ GO TO 30*IF( TJJ.LT.ONE ) THENIF( XJ.GT.BIGNUM*TJJ ) THENREC = ONE / XJCALL DSCAL( N, REC, X, 1 )SCALE = SCALE*RECXMAX = XMAX*RECEND IFEND IFX( J1 ) = X( J1 ) / TMPXJ = ABS( X( J1 ) )** Scale x if necessary to avoid overflow when adding a* multiple of column j1 of T.*IF( XJ.GT.ONE ) THENREC = ONE / XJIF( WORK( J1 ).GT.( BIGNUM-XMAX )*REC ) THENCALL DSCAL( N, REC, X, 1 )SCALE = SCALE*RECEND IFEND IFIF( J1.GT.1 ) THENCALL DAXPY( J1-1, -X( J1 ), T( 1, J1 ), 1, X, 1 )K = IDAMAX( J1-1, X, 1 )XMAX = ABS( X( K ) )END IF*ELSE** Meet 2 by 2 diagonal block** Call 2 by 2 linear system solve, to take* care of possible overflow by scaling factor.*D( 1, 1 ) = X( J1 )D( 2, 1 ) = X( J2 )CALL DLALN2( .FALSE., 2, 1, SMIN, ONE, T( J1, J1 ),$ LDT, ONE, ONE, D, 2, ZERO, ZERO, V, 2,$ SCALOC, XNORM, IERR )IF( IERR.NE.0 )$ INFO = 2*IF( SCALOC.NE.ONE ) THENCALL DSCAL( N, SCALOC, X, 1 )SCALE = SCALE*SCALOCEND IFX( J1 ) = V( 1, 1 )X( J2 ) = V( 2, 1 )** Scale V(1,1) (= X(J1)) and/or V(2,1) (=X(J2))* to avoid overflow in updating right-hand side.*XJ = MAX( ABS( V( 1, 1 ) ), ABS( V( 2, 1 ) ) )IF( XJ.GT.ONE ) THENREC = ONE / XJIF( MAX( WORK( J1 ), WORK( J2 ) ).GT.$ ( BIGNUM-XMAX )*REC ) THENCALL DSCAL( N, REC, X, 1 )SCALE = SCALE*RECEND IFEND IF** Update right-hand side*IF( J1.GT.1 ) THENCALL DAXPY( J1-1, -X( J1 ), T( 1, J1 ), 1, X, 1 )CALL DAXPY( J1-1, -X( J2 ), T( 1, J2 ), 1, X, 1 )K = IDAMAX( J1-1, X, 1 )XMAX = ABS( X( K ) )END IF*END IF*30 CONTINUE*ELSE** Solve T'*p = scale*c*JNEXT = 1DO 40 J = 1, NIF( J.LT.JNEXT )$ GO TO 40J1 = JJ2 = JJNEXT = J + 1IF( J.LT.N ) THENIF( T( J+1, J ).NE.ZERO ) THENJ2 = J + 1JNEXT = J + 2END IFEND IF*IF( J1.EQ.J2 ) THEN** 1 by 1 diagonal block** Scale if necessary to avoid overflow in forming the* right-hand side element by inner product.*XJ = ABS( X( J1 ) )IF( XMAX.GT.ONE ) THENREC = ONE / XMAXIF( WORK( J1 ).GT.( BIGNUM-XJ )*REC ) THENCALL DSCAL( N, REC, X, 1 )SCALE = SCALE*RECXMAX = XMAX*RECEND IFEND IF*X( J1 ) = X( J1 ) - DDOT( J1-1, T( 1, J1 ), 1, X, 1 )*XJ = ABS( X( J1 ) )TJJ = ABS( T( J1, J1 ) )TMP = T( J1, J1 )IF( TJJ.LT.SMIN ) THENTMP = SMINTJJ = SMININFO = 1END IF*IF( TJJ.LT.ONE ) THENIF( XJ.GT.BIGNUM*TJJ ) THENREC = ONE / XJCALL DSCAL( N, REC, X, 1 )SCALE = SCALE*RECXMAX = XMAX*RECEND IFEND IFX( J1 ) = X( J1 ) / TMPXMAX = MAX( XMAX, ABS( X( J1 ) ) )*ELSE** 2 by 2 diagonal block** Scale if necessary to avoid overflow in forming the* right-hand side elements by inner product.*XJ = MAX( ABS( X( J1 ) ), ABS( X( J2 ) ) )IF( XMAX.GT.ONE ) THENREC = ONE / XMAXIF( MAX( WORK( J2 ), WORK( J1 ) ).GT.( BIGNUM-XJ )*$ REC ) THENCALL DSCAL( N, REC, X, 1 )SCALE = SCALE*RECXMAX = XMAX*RECEND IFEND IF*D( 1, 1 ) = X( J1 ) - DDOT( J1-1, T( 1, J1 ), 1, X,$ 1 )D( 2, 1 ) = X( J2 ) - DDOT( J1-1, T( 1, J2 ), 1, X,$ 1 )*CALL DLALN2( .TRUE., 2, 1, SMIN, ONE, T( J1, J1 ),$ LDT, ONE, ONE, D, 2, ZERO, ZERO, V, 2,$ SCALOC, XNORM, IERR )IF( IERR.NE.0 )$ INFO = 2*IF( SCALOC.NE.ONE ) THENCALL DSCAL( N, SCALOC, X, 1 )SCALE = SCALE*SCALOCEND IFX( J1 ) = V( 1, 1 )X( J2 ) = V( 2, 1 )XMAX = MAX( ABS( X( J1 ) ), ABS( X( J2 ) ), XMAX )*END IF40 CONTINUEEND IF*ELSE*SMINW = MAX( EPS*ABS( W ), SMIN )IF( NOTRAN ) THEN** Solve (T + iB)*(p+iq) = c+id*JNEXT = NDO 70 J = N, 1, -1IF( J.GT.JNEXT )$ GO TO 70J1 = JJ2 = JJNEXT = J - 1IF( J.GT.1 ) THENIF( T( J, J-1 ).NE.ZERO ) THENJ1 = J - 1JNEXT = J - 2END IFEND IF*IF( J1.EQ.J2 ) THEN** 1 by 1 diagonal block** Scale if necessary to avoid overflow in division*Z = WIF( J1.EQ.1 )$ Z = B( 1 )XJ = ABS( X( J1 ) ) + ABS( X( N+J1 ) )TJJ = ABS( T( J1, J1 ) ) + ABS( Z )TMP = T( J1, J1 )IF( TJJ.LT.SMINW ) THENTMP = SMINWTJJ = SMINWINFO = 1END IF*IF( XJ.EQ.ZERO )$ GO TO 70*IF( TJJ.LT.ONE ) THENIF( XJ.GT.BIGNUM*TJJ ) THENREC = ONE / XJCALL DSCAL( N2, REC, X, 1 )SCALE = SCALE*RECXMAX = XMAX*RECEND IFEND IFCALL DLADIV( X( J1 ), X( N+J1 ), TMP, Z, SR, SI )X( J1 ) = SRX( N+J1 ) = SIXJ = ABS( X( J1 ) ) + ABS( X( N+J1 ) )** Scale x if necessary to avoid overflow when adding a* multiple of column j1 of T.*IF( XJ.GT.ONE ) THENREC = ONE / XJIF( WORK( J1 ).GT.( BIGNUM-XMAX )*REC ) THENCALL DSCAL( N2, REC, X, 1 )SCALE = SCALE*RECEND IFEND IF*IF( J1.GT.1 ) THENCALL DAXPY( J1-1, -X( J1 ), T( 1, J1 ), 1, X, 1 )CALL DAXPY( J1-1, -X( N+J1 ), T( 1, J1 ), 1,$ X( N+1 ), 1 )*X( 1 ) = X( 1 ) + B( J1 )*X( N+J1 )X( N+1 ) = X( N+1 ) - B( J1 )*X( J1 )*XMAX = ZERODO 50 K = 1, J1 - 1XMAX = MAX( XMAX, ABS( X( K ) )+$ ABS( X( K+N ) ) )50 CONTINUEEND IF*ELSE** Meet 2 by 2 diagonal block*D( 1, 1 ) = X( J1 )D( 2, 1 ) = X( J2 )D( 1, 2 ) = X( N+J1 )D( 2, 2 ) = X( N+J2 )CALL DLALN2( .FALSE., 2, 2, SMINW, ONE, T( J1, J1 ),$ LDT, ONE, ONE, D, 2, ZERO, -W, V, 2,$ SCALOC, XNORM, IERR )IF( IERR.NE.0 )$ INFO = 2*IF( SCALOC.NE.ONE ) THENCALL DSCAL( 2*N, SCALOC, X, 1 )SCALE = SCALOC*SCALEEND IFX( J1 ) = V( 1, 1 )X( J2 ) = V( 2, 1 )X( N+J1 ) = V( 1, 2 )X( N+J2 ) = V( 2, 2 )** Scale X(J1), .... to avoid overflow in* updating right hand side.*XJ = MAX( ABS( V( 1, 1 ) )+ABS( V( 1, 2 ) ),$ ABS( V( 2, 1 ) )+ABS( V( 2, 2 ) ) )IF( XJ.GT.ONE ) THENREC = ONE / XJIF( MAX( WORK( J1 ), WORK( J2 ) ).GT.$ ( BIGNUM-XMAX )*REC ) THENCALL DSCAL( N2, REC, X, 1 )SCALE = SCALE*RECEND IFEND IF** Update the right-hand side.*IF( J1.GT.1 ) THENCALL DAXPY( J1-1, -X( J1 ), T( 1, J1 ), 1, X, 1 )CALL DAXPY( J1-1, -X( J2 ), T( 1, J2 ), 1, X, 1 )*CALL DAXPY( J1-1, -X( N+J1 ), T( 1, J1 ), 1,$ X( N+1 ), 1 )CALL DAXPY( J1-1, -X( N+J2 ), T( 1, J2 ), 1,$ X( N+1 ), 1 )*X( 1 ) = X( 1 ) + B( J1 )*X( N+J1 ) +$ B( J2 )*X( N+J2 )X( N+1 ) = X( N+1 ) - B( J1 )*X( J1 ) -$ B( J2 )*X( J2 )*XMAX = ZERODO 60 K = 1, J1 - 1XMAX = MAX( ABS( X( K ) )+ABS( X( K+N ) ),$ XMAX )60 CONTINUEEND IF*END IF70 CONTINUE*ELSE** Solve (T + iB)'*(p+iq) = c+id*JNEXT = 1DO 80 J = 1, NIF( J.LT.JNEXT )$ GO TO 80J1 = JJ2 = JJNEXT = J + 1IF( J.LT.N ) THENIF( T( J+1, J ).NE.ZERO ) THENJ2 = J + 1JNEXT = J + 2END IFEND IF*IF( J1.EQ.J2 ) THEN** 1 by 1 diagonal block** Scale if necessary to avoid overflow in forming the* right-hand side element by inner product.*XJ = ABS( X( J1 ) ) + ABS( X( J1+N ) )IF( XMAX.GT.ONE ) THENREC = ONE / XMAXIF( WORK( J1 ).GT.( BIGNUM-XJ )*REC ) THENCALL DSCAL( N2, REC, X, 1 )SCALE = SCALE*RECXMAX = XMAX*RECEND IFEND IF*X( J1 ) = X( J1 ) - DDOT( J1-1, T( 1, J1 ), 1, X, 1 )X( N+J1 ) = X( N+J1 ) - DDOT( J1-1, T( 1, J1 ), 1,$ X( N+1 ), 1 )IF( J1.GT.1 ) THENX( J1 ) = X( J1 ) - B( J1 )*X( N+1 )X( N+J1 ) = X( N+J1 ) + B( J1 )*X( 1 )END IFXJ = ABS( X( J1 ) ) + ABS( X( J1+N ) )*Z = WIF( J1.EQ.1 )$ Z = B( 1 )** Scale if necessary to avoid overflow in* complex division*TJJ = ABS( T( J1, J1 ) ) + ABS( Z )TMP = T( J1, J1 )IF( TJJ.LT.SMINW ) THENTMP = SMINWTJJ = SMINWINFO = 1END IF*IF( TJJ.LT.ONE ) THENIF( XJ.GT.BIGNUM*TJJ ) THENREC = ONE / XJCALL DSCAL( N2, REC, X, 1 )SCALE = SCALE*RECXMAX = XMAX*RECEND IFEND IFCALL DLADIV( X( J1 ), X( N+J1 ), TMP, -Z, SR, SI )X( J1 ) = SRX( J1+N ) = SIXMAX = MAX( ABS( X( J1 ) )+ABS( X( J1+N ) ), XMAX )*ELSE** 2 by 2 diagonal block** Scale if necessary to avoid overflow in forming the* right-hand side element by inner product.*XJ = MAX( ABS( X( J1 ) )+ABS( X( N+J1 ) ),$ ABS( X( J2 ) )+ABS( X( N+J2 ) ) )IF( XMAX.GT.ONE ) THENREC = ONE / XMAXIF( MAX( WORK( J1 ), WORK( J2 ) ).GT.$ ( BIGNUM-XJ ) / XMAX ) THENCALL DSCAL( N2, REC, X, 1 )SCALE = SCALE*RECXMAX = XMAX*RECEND IFEND IF*D( 1, 1 ) = X( J1 ) - DDOT( J1-1, T( 1, J1 ), 1, X,$ 1 )D( 2, 1 ) = X( J2 ) - DDOT( J1-1, T( 1, J2 ), 1, X,$ 1 )D( 1, 2 ) = X( N+J1 ) - DDOT( J1-1, T( 1, J1 ), 1,$ X( N+1 ), 1 )D( 2, 2 ) = X( N+J2 ) - DDOT( J1-1, T( 1, J2 ), 1,$ X( N+1 ), 1 )D( 1, 1 ) = D( 1, 1 ) - B( J1 )*X( N+1 )D( 2, 1 ) = D( 2, 1 ) - B( J2 )*X( N+1 )D( 1, 2 ) = D( 1, 2 ) + B( J1 )*X( 1 )D( 2, 2 ) = D( 2, 2 ) + B( J2 )*X( 1 )*CALL DLALN2( .TRUE., 2, 2, SMINW, ONE, T( J1, J1 ),$ LDT, ONE, ONE, D, 2, ZERO, W, V, 2,$ SCALOC, XNORM, IERR )IF( IERR.NE.0 )$ INFO = 2*IF( SCALOC.NE.ONE ) THENCALL DSCAL( N2, SCALOC, X, 1 )SCALE = SCALOC*SCALEEND IFX( J1 ) = V( 1, 1 )X( J2 ) = V( 2, 1 )X( N+J1 ) = V( 1, 2 )X( N+J2 ) = V( 2, 2 )XMAX = MAX( ABS( X( J1 ) )+ABS( X( N+J1 ) ),$ ABS( X( J2 ) )+ABS( X( N+J2 ) ), XMAX )*END IF*80 CONTINUE*END IF*END IF*RETURN** End of DLAQTR*ENDSUBROUTINE DLARF( SIDE, M, N, V, INCV, TAU, C, LDC, WORK )** -- LAPACK auxiliary routine (version 3.0) --* Univ. of Tennessee, Univ. of California Berkeley, NAG Ltd.,* Courant Institute, Argonne National Lab, and Rice University* February 29, 1992** .. Scalar Arguments ..CHARACTER SIDEINTEGER INCV, LDC, M, NDOUBLE PRECISION TAU* ..* .. Array Arguments ..DOUBLE PRECISION C( LDC, * ), V( * ), WORK( * )* ..** Purpose* =======** DLARF applies a real elementary reflector H to a real m by n matrix* C, from either the left or the right. H is represented in the form** H = I - tau * v * v'** where tau is a real scalar and v is a real vector.** If tau = 0, then H is taken to be the unit matrix.** Arguments* =========** SIDE (input) CHARACTER*1* = 'L': form H * C* = 'R': form C * H** M (input) INTEGER* The number of rows of the matrix C.** N (input) INTEGER* The number of columns of the matrix C.** V (input) DOUBLE PRECISION array, dimension* (1 + (M-1)*abs(INCV)) if SIDE = 'L'* or (1 + (N-1)*abs(INCV)) if SIDE = 'R'* The vector v in the representation of H. V is not used if* TAU = 0.** INCV (input) INTEGER* The increment between elements of v. INCV <> 0.** TAU (input) DOUBLE PRECISION* The value tau in the representation of H.** C (input/output) DOUBLE PRECISION array, dimension (LDC,N)* On entry, the m by n matrix C.* On exit, C is overwritten by the matrix H * C if SIDE = 'L',* or C * H if SIDE = 'R'.** LDC (input) INTEGER* The leading dimension of the array C. LDC >= max(1,M).** WORK (workspace) DOUBLE PRECISION array, dimension* (N) if SIDE = 'L'* or (M) if SIDE = 'R'** =====================================================================** .. Parameters ..DOUBLE PRECISION ONE, ZEROPARAMETER ( ONE = 1.0D+0, ZERO = 0.0D+0 )* ..* .. External Subroutines ..EXTERNAL DGEMV, DGER* ..* .. External Functions ..LOGICAL LSAMEEXTERNAL LSAME* ..* .. Executable Statements ..*IF( LSAME( SIDE, 'L' ) ) THEN** Form H * C*IF( TAU.NE.ZERO ) THEN** w := C' * v*CALL DGEMV( 'Transpose', M, N, ONE, C, LDC, V, INCV, ZERO,$ WORK, 1 )** C := C - v * w'*CALL DGER( M, N, -TAU, V, INCV, WORK, 1, C, LDC )END IFELSE** Form C * H*IF( TAU.NE.ZERO ) THEN** w := C * v*CALL DGEMV( 'No transpose', M, N, ONE, C, LDC, V, INCV,$ ZERO, WORK, 1 )** C := C - w * v'*CALL DGER( M, N, -TAU, WORK, 1, V, INCV, C, LDC )END IFEND IFRETURN** End of DLARF*ENDSUBROUTINE DLARFB( SIDE, TRANS, DIRECT, STOREV, M, N, K, V, LDV,$ T, LDT, C, LDC, WORK, LDWORK )** -- LAPACK auxiliary routine (version 3.0) --* Univ. of Tennessee, Univ. of California Berkeley, NAG Ltd.,* Courant Institute, Argonne National Lab, and Rice University* February 29, 1992** .. Scalar Arguments ..CHARACTER DIRECT, SIDE, STOREV, TRANSINTEGER K, LDC, LDT, LDV, LDWORK, M, N* ..* .. Array Arguments ..DOUBLE PRECISION C( LDC, * ), T( LDT, * ), V( LDV, * ),$ WORK( LDWORK, * )* ..** Purpose* =======** DLARFB applies a real block reflector H or its transpose H' to a* real m by n matrix C, from either the left or the right.** Arguments* =========** SIDE (input) CHARACTER*1* = 'L': apply H or H' from the Left* = 'R': apply H or H' from the Right** TRANS (input) CHARACTER*1* = 'N': apply H (No transpose)* = 'T': apply H' (Transpose)** DIRECT (input) CHARACTER*1* Indicates how H is formed from a product of elementary* reflectors* = 'F': H = H(1) H(2) . . . H(k) (Forward)* = 'B': H = H(k) . . . H(2) H(1) (Backward)** STOREV (input) CHARACTER*1* Indicates how the vectors which define the elementary* reflectors are stored:* = 'C': Columnwise* = 'R': Rowwise** M (input) INTEGER* The number of rows of the matrix C.** N (input) INTEGER* The number of columns of the matrix C.** K (input) INTEGER* The order of the matrix T (= the number of elementary* reflectors whose product defines the block reflector).** V (input) DOUBLE PRECISION array, dimension* (LDV,K) if STOREV = 'C'* (LDV,M) if STOREV = 'R' and SIDE = 'L'* (LDV,N) if STOREV = 'R' and SIDE = 'R'* The matrix V. See further details.** LDV (input) INTEGER* The leading dimension of the array V.* If STOREV = 'C' and SIDE = 'L', LDV >= max(1,M);* if STOREV = 'C' and SIDE = 'R', LDV >= max(1,N);* if STOREV = 'R', LDV >= K.** T (input) DOUBLE PRECISION array, dimension (LDT,K)* The triangular k by k matrix T in the representation of the* block reflector.** LDT (input) INTEGER* The leading dimension of the array T. LDT >= K.** C (input/output) DOUBLE PRECISION array, dimension (LDC,N)* On entry, the m by n matrix C.* On exit, C is overwritten by H*C or H'*C or C*H or C*H'.** LDC (input) INTEGER* The leading dimension of the array C. LDA >= max(1,M).** WORK (workspace) DOUBLE PRECISION array, dimension (LDWORK,K)** LDWORK (input) INTEGER* The leading dimension of the array WORK.* If SIDE = 'L', LDWORK >= max(1,N);* if SIDE = 'R', LDWORK >= max(1,M).** =====================================================================** .. Parameters ..DOUBLE PRECISION ONEPARAMETER ( ONE = 1.0D+0 )* ..* .. Local Scalars ..CHARACTER TRANSTINTEGER I, J* ..* .. External Functions ..LOGICAL LSAMEEXTERNAL LSAME* ..* .. External Subroutines ..EXTERNAL DCOPY, DGEMM, DTRMM* ..* .. Executable Statements ..** Quick return if possible*IF( M.LE.0 .OR. N.LE.0 )$ RETURN*IF( LSAME( TRANS, 'N' ) ) THENTRANST = 'T'ELSETRANST = 'N'END IF*IF( LSAME( STOREV, 'C' ) ) THEN*IF( LSAME( DIRECT, 'F' ) ) THEN** Let V = ( V1 ) (first K rows)* ( V2 )* where V1 is unit lower triangular.*IF( LSAME( SIDE, 'L' ) ) THEN** Form H * C or H' * C where C = ( C1 )* ( C2 )** W := C' * V = (C1'*V1 + C2'*V2) (stored in WORK)** W := C1'*DO 10 J = 1, KCALL DCOPY( N, C( J, 1 ), LDC, WORK( 1, J ), 1 )10 CONTINUE** W := W * V1*CALL DTRMM( 'Right', 'Lower', 'No transpose', 'Unit', N,$ K, ONE, V, LDV, WORK, LDWORK )IF( M.GT.K ) THEN** W := W + C2'*V2*CALL DGEMM( 'Transpose', 'No transpose', N, K, M-K,$ ONE, C( K+1, 1 ), LDC, V( K+1, 1 ), LDV,$ ONE, WORK, LDWORK )END IF** W := W * T' or W * T*CALL DTRMM( 'Right', 'Upper', TRANST, 'Non-unit', N, K,$ ONE, T, LDT, WORK, LDWORK )** C := C - V * W'*IF( M.GT.K ) THEN** C2 := C2 - V2 * W'*CALL DGEMM( 'No transpose', 'Transpose', M-K, N, K,$ -ONE, V( K+1, 1 ), LDV, WORK, LDWORK, ONE,$ C( K+1, 1 ), LDC )END IF** W := W * V1'*CALL DTRMM( 'Right', 'Lower', 'Transpose', 'Unit', N, K,$ ONE, V, LDV, WORK, LDWORK )** C1 := C1 - W'*DO 30 J = 1, KDO 20 I = 1, NC( J, I ) = C( J, I ) - WORK( I, J )20 CONTINUE30 CONTINUE*ELSE IF( LSAME( SIDE, 'R' ) ) THEN** Form C * H or C * H' where C = ( C1 C2 )** W := C * V = (C1*V1 + C2*V2) (stored in WORK)** W := C1*DO 40 J = 1, KCALL DCOPY( M, C( 1, J ), 1, WORK( 1, J ), 1 )40 CONTINUE** W := W * V1*CALL DTRMM( 'Right', 'Lower', 'No transpose', 'Unit', M,$ K, ONE, V, LDV, WORK, LDWORK )IF( N.GT.K ) THEN** W := W + C2 * V2*CALL DGEMM( 'No transpose', 'No transpose', M, K, N-K,$ ONE, C( 1, K+1 ), LDC, V( K+1, 1 ), LDV,$ ONE, WORK, LDWORK )END IF** W := W * T or W * T'*CALL DTRMM( 'Right', 'Upper', TRANS, 'Non-unit', M, K,$ ONE, T, LDT, WORK, LDWORK )** C := C - W * V'*IF( N.GT.K ) THEN** C2 := C2 - W * V2'*CALL DGEMM( 'No transpose', 'Transpose', M, N-K, K,$ -ONE, WORK, LDWORK, V( K+1, 1 ), LDV, ONE,$ C( 1, K+1 ), LDC )END IF** W := W * V1'*CALL DTRMM( 'Right', 'Lower', 'Transpose', 'Unit', M, K,$ ONE, V, LDV, WORK, LDWORK )** C1 := C1 - W*DO 60 J = 1, KDO 50 I = 1, MC( I, J ) = C( I, J ) - WORK( I, J )50 CONTINUE60 CONTINUEEND IF*ELSE** Let V = ( V1 )* ( V2 ) (last K rows)* where V2 is unit upper triangular.*IF( LSAME( SIDE, 'L' ) ) THEN** Form H * C or H' * C where C = ( C1 )* ( C2 )** W := C' * V = (C1'*V1 + C2'*V2) (stored in WORK)** W := C2'*DO 70 J = 1, KCALL DCOPY( N, C( M-K+J, 1 ), LDC, WORK( 1, J ), 1 )70 CONTINUE** W := W * V2*CALL DTRMM( 'Right', 'Upper', 'No transpose', 'Unit', N,$ K, ONE, V( M-K+1, 1 ), LDV, WORK, LDWORK )IF( M.GT.K ) THEN** W := W + C1'*V1*CALL DGEMM( 'Transpose', 'No transpose', N, K, M-K,$ ONE, C, LDC, V, LDV, ONE, WORK, LDWORK )END IF** W := W * T' or W * T*CALL DTRMM( 'Right', 'Lower', TRANST, 'Non-unit', N, K,$ ONE, T, LDT, WORK, LDWORK )** C := C - V * W'*IF( M.GT.K ) THEN** C1 := C1 - V1 * W'*CALL DGEMM( 'No transpose', 'Transpose', M-K, N, K,$ -ONE, V, LDV, WORK, LDWORK, ONE, C, LDC )END IF** W := W * V2'*CALL DTRMM( 'Right', 'Upper', 'Transpose', 'Unit', N, K,$ ONE, V( M-K+1, 1 ), LDV, WORK, LDWORK )** C2 := C2 - W'*DO 90 J = 1, KDO 80 I = 1, NC( M-K+J, I ) = C( M-K+J, I ) - WORK( I, J )80 CONTINUE90 CONTINUE*ELSE IF( LSAME( SIDE, 'R' ) ) THEN** Form C * H or C * H' where C = ( C1 C2 )** W := C * V = (C1*V1 + C2*V2) (stored in WORK)** W := C2*DO 100 J = 1, KCALL DCOPY( M, C( 1, N-K+J ), 1, WORK( 1, J ), 1 )100 CONTINUE** W := W * V2*CALL DTRMM( 'Right', 'Upper', 'No transpose', 'Unit', M,$ K, ONE, V( N-K+1, 1 ), LDV, WORK, LDWORK )IF( N.GT.K ) THEN** W := W + C1 * V1*CALL DGEMM( 'No transpose', 'No transpose', M, K, N-K,$ ONE, C, LDC, V, LDV, ONE, WORK, LDWORK )END IF** W := W * T or W * T'*CALL DTRMM( 'Right', 'Lower', TRANS, 'Non-unit', M, K,$ ONE, T, LDT, WORK, LDWORK )** C := C - W * V'*IF( N.GT.K ) THEN** C1 := C1 - W * V1'*CALL DGEMM( 'No transpose', 'Transpose', M, N-K, K,$ -ONE, WORK, LDWORK, V, LDV, ONE, C, LDC )END IF** W := W * V2'*CALL DTRMM( 'Right', 'Upper', 'Transpose', 'Unit', M, K,$ ONE, V( N-K+1, 1 ), LDV, WORK, LDWORK )** C2 := C2 - W*DO 120 J = 1, KDO 110 I = 1, MC( I, N-K+J ) = C( I, N-K+J ) - WORK( I, J )110 CONTINUE120 CONTINUEEND IFEND IF*ELSE IF( LSAME( STOREV, 'R' ) ) THEN*IF( LSAME( DIRECT, 'F' ) ) THEN** Let V = ( V1 V2 ) (V1: first K columns)* where V1 is unit upper triangular.*IF( LSAME( SIDE, 'L' ) ) THEN** Form H * C or H' * C where C = ( C1 )* ( C2 )** W := C' * V' = (C1'*V1' + C2'*V2') (stored in WORK)** W := C1'*DO 130 J = 1, KCALL DCOPY( N, C( J, 1 ), LDC, WORK( 1, J ), 1 )130 CONTINUE** W := W * V1'*CALL DTRMM( 'Right', 'Upper', 'Transpose', 'Unit', N, K,$ ONE, V, LDV, WORK, LDWORK )IF( M.GT.K ) THEN** W := W + C2'*V2'*CALL DGEMM( 'Transpose', 'Transpose', N, K, M-K, ONE,$ C( K+1, 1 ), LDC, V( 1, K+1 ), LDV, ONE,$ WORK, LDWORK )END IF** W := W * T' or W * T*CALL DTRMM( 'Right', 'Upper', TRANST, 'Non-unit', N, K,$ ONE, T, LDT, WORK, LDWORK )** C := C - V' * W'*IF( M.GT.K ) THEN** C2 := C2 - V2' * W'*CALL DGEMM( 'Transpose', 'Transpose', M-K, N, K, -ONE,$ V( 1, K+1 ), LDV, WORK, LDWORK, ONE,$ C( K+1, 1 ), LDC )END IF** W := W * V1*CALL DTRMM( 'Right', 'Upper', 'No transpose', 'Unit', N,$ K, ONE, V, LDV, WORK, LDWORK )** C1 := C1 - W'*DO 150 J = 1, KDO 140 I = 1, NC( J, I ) = C( J, I ) - WORK( I, J )140 CONTINUE150 CONTINUE*ELSE IF( LSAME( SIDE, 'R' ) ) THEN** Form C * H or C * H' where C = ( C1 C2 )** W := C * V' = (C1*V1' + C2*V2') (stored in WORK)** W := C1*DO 160 J = 1, KCALL DCOPY( M, C( 1, J ), 1, WORK( 1, J ), 1 )160 CONTINUE** W := W * V1'*CALL DTRMM( 'Right', 'Upper', 'Transpose', 'Unit', M, K,$ ONE, V, LDV, WORK, LDWORK )IF( N.GT.K ) THEN** W := W + C2 * V2'*CALL DGEMM( 'No transpose', 'Transpose', M, K, N-K,$ ONE, C( 1, K+1 ), LDC, V( 1, K+1 ), LDV,$ ONE, WORK, LDWORK )END IF** W := W * T or W * T'*CALL DTRMM( 'Right', 'Upper', TRANS, 'Non-unit', M, K,$ ONE, T, LDT, WORK, LDWORK )** C := C - W * V*IF( N.GT.K ) THEN** C2 := C2 - W * V2*CALL DGEMM( 'No transpose', 'No transpose', M, N-K, K,$ -ONE, WORK, LDWORK, V( 1, K+1 ), LDV, ONE,$ C( 1, K+1 ), LDC )END IF** W := W * V1*CALL DTRMM( 'Right', 'Upper', 'No transpose', 'Unit', M,$ K, ONE, V, LDV, WORK, LDWORK )** C1 := C1 - W*DO 180 J = 1, KDO 170 I = 1, MC( I, J ) = C( I, J ) - WORK( I, J )170 CONTINUE180 CONTINUE*END IF*ELSE** Let V = ( V1 V2 ) (V2: last K columns)* where V2 is unit lower triangular.*IF( LSAME( SIDE, 'L' ) ) THEN** Form H * C or H' * C where C = ( C1 )* ( C2 )** W := C' * V' = (C1'*V1' + C2'*V2') (stored in WORK)** W := C2'*DO 190 J = 1, KCALL DCOPY( N, C( M-K+J, 1 ), LDC, WORK( 1, J ), 1 )190 CONTINUE** W := W * V2'*CALL DTRMM( 'Right', 'Lower', 'Transpose', 'Unit', N, K,$ ONE, V( 1, M-K+1 ), LDV, WORK, LDWORK )IF( M.GT.K ) THEN** W := W + C1'*V1'*CALL DGEMM( 'Transpose', 'Transpose', N, K, M-K, ONE,$ C, LDC, V, LDV, ONE, WORK, LDWORK )END IF** W := W * T' or W * T*CALL DTRMM( 'Right', 'Lower', TRANST, 'Non-unit', N, K,$ ONE, T, LDT, WORK, LDWORK )** C := C - V' * W'*IF( M.GT.K ) THEN** C1 := C1 - V1' * W'*CALL DGEMM( 'Transpose', 'Transpose', M-K, N, K, -ONE,$ V, LDV, WORK, LDWORK, ONE, C, LDC )END IF** W := W * V2*CALL DTRMM( 'Right', 'Lower', 'No transpose', 'Unit', N,$ K, ONE, V( 1, M-K+1 ), LDV, WORK, LDWORK )** C2 := C2 - W'*DO 210 J = 1, KDO 200 I = 1, NC( M-K+J, I ) = C( M-K+J, I ) - WORK( I, J )200 CONTINUE210 CONTINUE*ELSE IF( LSAME( SIDE, 'R' ) ) THEN** Form C * H or C * H' where C = ( C1 C2 )** W := C * V' = (C1*V1' + C2*V2') (stored in WORK)** W := C2*DO 220 J = 1, KCALL DCOPY( M, C( 1, N-K+J ), 1, WORK( 1, J ), 1 )220 CONTINUE** W := W * V2'*CALL DTRMM( 'Right', 'Lower', 'Transpose', 'Unit', M, K,$ ONE, V( 1, N-K+1 ), LDV, WORK, LDWORK )IF( N.GT.K ) THEN** W := W + C1 * V1'*CALL DGEMM( 'No transpose', 'Transpose', M, K, N-K,$ ONE, C, LDC, V, LDV, ONE, WORK, LDWORK )END IF** W := W * T or W * T'*CALL DTRMM( 'Right', 'Lower', TRANS, 'Non-unit', M, K,$ ONE, T, LDT, WORK, LDWORK )** C := C - W * V*IF( N.GT.K ) THEN** C1 := C1 - W * V1*CALL DGEMM( 'No transpose', 'No transpose', M, N-K, K,$ -ONE, WORK, LDWORK, V, LDV, ONE, C, LDC )END IF** W := W * V2*CALL DTRMM( 'Right', 'Lower', 'No transpose', 'Unit', M,$ K, ONE, V( 1, N-K+1 ), LDV, WORK, LDWORK )** C1 := C1 - W*DO 240 J = 1, KDO 230 I = 1, MC( I, N-K+J ) = C( I, N-K+J ) - WORK( I, J )230 CONTINUE240 CONTINUE*END IF*END IFEND IF*RETURN** End of DLARFB*ENDSUBROUTINE DLARFG( N, ALPHA, X, INCX, TAU )** -- LAPACK auxiliary routine (version 3.0) --* Univ. of Tennessee, Univ. of California Berkeley, NAG Ltd.,* Courant Institute, Argonne National Lab, and Rice University* September 30, 1994** .. Scalar Arguments ..INTEGER INCX, NDOUBLE PRECISION ALPHA, TAU* ..* .. Array Arguments ..DOUBLE PRECISION X( * )* ..** Purpose* =======** DLARFG generates a real elementary reflector H of order n, such* that** H * ( alpha ) = ( beta ), H' * H = I.* ( x ) ( 0 )** where alpha and beta are scalars, and x is an (n-1)-element real* vector. H is represented in the form** H = I - tau * ( 1 ) * ( 1 v' ) ,* ( v )** where tau is a real scalar and v is a real (n-1)-element* vector.** If the elements of x are all zero, then tau = 0 and H is taken to be* the unit matrix.** Otherwise 1 <= tau <= 2.** Arguments* =========** N (input) INTEGER* The order of the elementary reflector.** ALPHA (input/output) DOUBLE PRECISION* On entry, the value alpha.* On exit, it is overwritten with the value beta.** X (input/output) DOUBLE PRECISION array, dimension* (1+(N-2)*abs(INCX))* On entry, the vector x.* On exit, it is overwritten with the vector v.** INCX (input) INTEGER* The increment between elements of X. INCX > 0.** TAU (output) DOUBLE PRECISION* The value tau.** =====================================================================** .. Parameters ..DOUBLE PRECISION ONE, ZEROPARAMETER ( ONE = 1.0D+0, ZERO = 0.0D+0 )* ..* .. Local Scalars ..INTEGER J, KNTDOUBLE PRECISION BETA, RSAFMN, SAFMIN, XNORM* ..* .. External Functions ..DOUBLE PRECISION DLAMCH, DLAPY2, DNRM2EXTERNAL DLAMCH, DLAPY2, DNRM2* ..* .. Intrinsic Functions ..INTRINSIC ABS, SIGN* ..* .. External Subroutines ..EXTERNAL DSCAL* ..* .. Executable Statements ..*IF( N.LE.1 ) THENTAU = ZERORETURNEND IF*XNORM = DNRM2( N-1, X, INCX )*IF( XNORM.EQ.ZERO ) THEN** H = I*TAU = ZEROELSE** general case*BETA = -SIGN( DLAPY2( ALPHA, XNORM ), ALPHA )SAFMIN = DLAMCH( 'S' ) / DLAMCH( 'E' )IF( ABS( BETA ).LT.SAFMIN ) THEN** XNORM, BETA may be inaccurate; scale X and recompute them*RSAFMN = ONE / SAFMINKNT = 010 CONTINUEKNT = KNT + 1CALL DSCAL( N-1, RSAFMN, X, INCX )BETA = BETA*RSAFMNALPHA = ALPHA*RSAFMNIF( ABS( BETA ).LT.SAFMIN )$ GO TO 10** New BETA is at most 1, at least SAFMIN*XNORM = DNRM2( N-1, X, INCX )BETA = -SIGN( DLAPY2( ALPHA, XNORM ), ALPHA )TAU = ( BETA-ALPHA ) / BETACALL DSCAL( N-1, ONE / ( ALPHA-BETA ), X, INCX )** If ALPHA is subnormal, it may lose relative accuracy*ALPHA = BETADO 20 J = 1, KNTALPHA = ALPHA*SAFMIN20 CONTINUEELSETAU = ( BETA-ALPHA ) / BETACALL DSCAL( N-1, ONE / ( ALPHA-BETA ), X, INCX )ALPHA = BETAEND IFEND IF*RETURN** End of DLARFG*ENDSUBROUTINE DLARFT( DIRECT, STOREV, N, K, V, LDV, TAU, T, LDT )** -- LAPACK auxiliary routine (version 3.0) --* Univ. of Tennessee, Univ. of California Berkeley, NAG Ltd.,* Courant Institute, Argonne National Lab, and Rice University* February 29, 1992** .. Scalar Arguments ..CHARACTER DIRECT, STOREVINTEGER K, LDT, LDV, N* ..* .. Array Arguments ..DOUBLE PRECISION T( LDT, * ), TAU( * ), V( LDV, * )* ..** Purpose* =======** DLARFT forms the triangular factor T of a real block reflector H* of order n, which is defined as a product of k elementary reflectors.** If DIRECT = 'F', H = H(1) H(2) . . . H(k) and T is upper triangular;** If DIRECT = 'B', H = H(k) . . . H(2) H(1) and T is lower triangular.** If STOREV = 'C', the vector which defines the elementary reflector* H(i) is stored in the i-th column of the array V, and** H = I - V * T * V'** If STOREV = 'R', the vector which defines the elementary reflector* H(i) is stored in the i-th row of the array V, and** H = I - V' * T * V** Arguments* =========** DIRECT (input) CHARACTER*1* Specifies the order in which the elementary reflectors are* multiplied to form the block reflector:* = 'F': H = H(1) H(2) . . . H(k) (Forward)* = 'B': H = H(k) . . . H(2) H(1) (Backward)** STOREV (input) CHARACTER*1* Specifies how the vectors which define the elementary* reflectors are stored (see also Further Details):* = 'C': columnwise* = 'R': rowwise** N (input) INTEGER* The order of the block reflector H. N >= 0.** K (input) INTEGER* The order of the triangular factor T (= the number of* elementary reflectors). K >= 1.** V (input/output) DOUBLE PRECISION array, dimension* (LDV,K) if STOREV = 'C'* (LDV,N) if STOREV = 'R'* The matrix V. See further details.** LDV (input) INTEGER* The leading dimension of the array V.* If STOREV = 'C', LDV >= max(1,N); if STOREV = 'R', LDV >= K.** TAU (input) DOUBLE PRECISION array, dimension (K)* TAU(i) must contain the scalar factor of the elementary* reflector H(i).** T (output) DOUBLE PRECISION array, dimension (LDT,K)* The k by k triangular factor T of the block reflector.* If DIRECT = 'F', T is upper triangular; if DIRECT = 'B', T is* lower triangular. The rest of the array is not used.** LDT (input) INTEGER* The leading dimension of the array T. LDT >= K.** Further Details* ===============** The shape of the matrix V and the storage of the vectors which define* the H(i) is best illustrated by the following example with n = 5 and* k = 3. The elements equal to 1 are not stored; the corresponding* array elements are modified but restored on exit. The rest of the* array is not used.** DIRECT = 'F' and STOREV = 'C': DIRECT = 'F' and STOREV = 'R':** V = ( 1 ) V = ( 1 v1 v1 v1 v1 )* ( v1 1 ) ( 1 v2 v2 v2 )* ( v1 v2 1 ) ( 1 v3 v3 )* ( v1 v2 v3 )* ( v1 v2 v3 )** DIRECT = 'B' and STOREV = 'C': DIRECT = 'B' and STOREV = 'R':** V = ( v1 v2 v3 ) V = ( v1 v1 1 )* ( v1 v2 v3 ) ( v2 v2 v2 1 )* ( 1 v2 v3 ) ( v3 v3 v3 v3 1 )* ( 1 v3 )* ( 1 )** =====================================================================** .. Parameters ..DOUBLE PRECISION ONE, ZEROPARAMETER ( ONE = 1.0D+0, ZERO = 0.0D+0 )* ..* .. Local Scalars ..INTEGER I, JDOUBLE PRECISION VII* ..* .. External Subroutines ..EXTERNAL DGEMV, DTRMV* ..* .. External Functions ..LOGICAL LSAMEEXTERNAL LSAME* ..* .. Executable Statements ..** Quick return if possible*IF( N.EQ.0 )$ RETURN*IF( LSAME( DIRECT, 'F' ) ) THENDO 20 I = 1, KIF( TAU( I ).EQ.ZERO ) THEN** H(i) = I*DO 10 J = 1, IT( J, I ) = ZERO10 CONTINUEELSE** general case*VII = V( I, I )V( I, I ) = ONEIF( LSAME( STOREV, 'C' ) ) THEN** T(1:i-1,i) := - tau(i) * V(i:n,1:i-1)' * V(i:n,i)*CALL DGEMV( 'Transpose', N-I+1, I-1, -TAU( I ),$ V( I, 1 ), LDV, V( I, I ), 1, ZERO,$ T( 1, I ), 1 )ELSE** T(1:i-1,i) := - tau(i) * V(1:i-1,i:n) * V(i,i:n)'*CALL DGEMV( 'No transpose', I-1, N-I+1, -TAU( I ),$ V( 1, I ), LDV, V( I, I ), LDV, ZERO,$ T( 1, I ), 1 )END IFV( I, I ) = VII** T(1:i-1,i) := T(1:i-1,1:i-1) * T(1:i-1,i)*CALL DTRMV( 'Upper', 'No transpose', 'Non-unit', I-1, T,$ LDT, T( 1, I ), 1 )T( I, I ) = TAU( I )END IF20 CONTINUEELSEDO 40 I = K, 1, -1IF( TAU( I ).EQ.ZERO ) THEN** H(i) = I*DO 30 J = I, KT( J, I ) = ZERO30 CONTINUEELSE** general case*IF( I.LT.K ) THENIF( LSAME( STOREV, 'C' ) ) THENVII = V( N-K+I, I )V( N-K+I, I ) = ONE** T(i+1:k,i) :=* - tau(i) * V(1:n-k+i,i+1:k)' * V(1:n-k+i,i)*CALL DGEMV( 'Transpose', N-K+I, K-I, -TAU( I ),$ V( 1, I+1 ), LDV, V( 1, I ), 1, ZERO,$ T( I+1, I ), 1 )V( N-K+I, I ) = VIIELSEVII = V( I, N-K+I )V( I, N-K+I ) = ONE** T(i+1:k,i) :=* - tau(i) * V(i+1:k,1:n-k+i) * V(i,1:n-k+i)'*CALL DGEMV( 'No transpose', K-I, N-K+I, -TAU( I ),$ V( I+1, 1 ), LDV, V( I, 1 ), LDV, ZERO,$ T( I+1, I ), 1 )V( I, N-K+I ) = VIIEND IF** T(i+1:k,i) := T(i+1:k,i+1:k) * T(i+1:k,i)*CALL DTRMV( 'Lower', 'No transpose', 'Non-unit', K-I,$ T( I+1, I+1 ), LDT, T( I+1, I ), 1 )END IFT( I, I ) = TAU( I )END IF40 CONTINUEEND IFRETURN** End of DLARFT*ENDSUBROUTINE DLARFX( SIDE, M, N, V, TAU, C, LDC, WORK )** -- LAPACK auxiliary routine (version 3.0) --* Univ. of Tennessee, Univ. of California Berkeley, NAG Ltd.,* Courant Institute, Argonne National Lab, and Rice University* February 29, 1992** .. Scalar Arguments ..CHARACTER SIDEINTEGER LDC, M, NDOUBLE PRECISION TAU* ..* .. Array Arguments ..DOUBLE PRECISION C( LDC, * ), V( * ), WORK( * )* ..** Purpose* =======** DLARFX applies a real elementary reflector H to a real m by n* matrix C, from either the left or the right. H is represented in the* form** H = I - tau * v * v'** where tau is a real scalar and v is a real vector.** If tau = 0, then H is taken to be the unit matrix** This version uses inline code if H has order < 11.** Arguments* =========** SIDE (input) CHARACTER*1* = 'L': form H * C* = 'R': form C * H** M (input) INTEGER* The number of rows of the matrix C.** N (input) INTEGER* The number of columns of the matrix C.** V (input) DOUBLE PRECISION array, dimension (M) if SIDE = 'L'* or (N) if SIDE = 'R'* The vector v in the representation of H.** TAU (input) DOUBLE PRECISION* The value tau in the representation of H.** C (input/output) DOUBLE PRECISION array, dimension (LDC,N)* On entry, the m by n matrix C.* On exit, C is overwritten by the matrix H * C if SIDE = 'L',* or C * H if SIDE = 'R'.** LDC (input) INTEGER* The leading dimension of the array C. LDA >= (1,M).** WORK (workspace) DOUBLE PRECISION array, dimension* (N) if SIDE = 'L'* or (M) if SIDE = 'R'* WORK is not referenced if H has order < 11.** =====================================================================** .. Parameters ..DOUBLE PRECISION ZERO, ONEPARAMETER ( ZERO = 0.0D+0, ONE = 1.0D+0 )* ..* .. Local Scalars ..INTEGER JDOUBLE PRECISION SUM, T1, T10, T2, T3, T4, T5, T6, T7, T8, T9,$ V1, V10, V2, V3, V4, V5, V6, V7, V8, V9* ..* .. External Functions ..LOGICAL LSAMEEXTERNAL LSAME* ..* .. External Subroutines ..EXTERNAL DGEMV, DGER* ..* .. Executable Statements ..*IF( TAU.EQ.ZERO )$ RETURNIF( LSAME( SIDE, 'L' ) ) THEN** Form H * C, where H has order m.*GO TO ( 10, 30, 50, 70, 90, 110, 130, 150,$ 170, 190 )M** Code for general M** w := C'*v*CALL DGEMV( 'Transpose', M, N, ONE, C, LDC, V, 1, ZERO, WORK,$ 1 )** C := C - tau * v * w'*CALL DGER( M, N, -TAU, V, 1, WORK, 1, C, LDC )GO TO 41010 CONTINUE** Special code for 1 x 1 Householder*T1 = ONE - TAU*V( 1 )*V( 1 )DO 20 J = 1, NC( 1, J ) = T1*C( 1, J )20 CONTINUEGO TO 41030 CONTINUE** Special code for 2 x 2 Householder*V1 = V( 1 )T1 = TAU*V1V2 = V( 2 )T2 = TAU*V2DO 40 J = 1, NSUM = V1*C( 1, J ) + V2*C( 2, J )C( 1, J ) = C( 1, J ) - SUM*T1C( 2, J ) = C( 2, J ) - SUM*T240 CONTINUEGO TO 41050 CONTINUE** Special code for 3 x 3 Householder*V1 = V( 1 )T1 = TAU*V1V2 = V( 2 )T2 = TAU*V2V3 = V( 3 )T3 = TAU*V3DO 60 J = 1, NSUM = V1*C( 1, J ) + V2*C( 2, J ) + V3*C( 3, J )C( 1, J ) = C( 1, J ) - SUM*T1C( 2, J ) = C( 2, J ) - SUM*T2C( 3, J ) = C( 3, J ) - SUM*T360 CONTINUEGO TO 41070 CONTINUE** Special code for 4 x 4 Householder*V1 = V( 1 )T1 = TAU*V1V2 = V( 2 )T2 = TAU*V2V3 = V( 3 )T3 = TAU*V3V4 = V( 4 )T4 = TAU*V4DO 80 J = 1, NSUM = V1*C( 1, J ) + V2*C( 2, J ) + V3*C( 3, J ) +$ V4*C( 4, J )C( 1, J ) = C( 1, J ) - SUM*T1C( 2, J ) = C( 2, J ) - SUM*T2C( 3, J ) = C( 3, J ) - SUM*T3C( 4, J ) = C( 4, J ) - SUM*T480 CONTINUEGO TO 41090 CONTINUE** Special code for 5 x 5 Householder*V1 = V( 1 )T1 = TAU*V1V2 = V( 2 )T2 = TAU*V2V3 = V( 3 )T3 = TAU*V3V4 = V( 4 )T4 = TAU*V4V5 = V( 5 )T5 = TAU*V5DO 100 J = 1, NSUM = V1*C( 1, J ) + V2*C( 2, J ) + V3*C( 3, J ) +$ V4*C( 4, J ) + V5*C( 5, J )C( 1, J ) = C( 1, J ) - SUM*T1C( 2, J ) = C( 2, J ) - SUM*T2C( 3, J ) = C( 3, J ) - SUM*T3C( 4, J ) = C( 4, J ) - SUM*T4C( 5, J ) = C( 5, J ) - SUM*T5100 CONTINUEGO TO 410110 CONTINUE** Special code for 6 x 6 Householder*V1 = V( 1 )T1 = TAU*V1V2 = V( 2 )T2 = TAU*V2V3 = V( 3 )T3 = TAU*V3V4 = V( 4 )T4 = TAU*V4V5 = V( 5 )T5 = TAU*V5V6 = V( 6 )T6 = TAU*V6DO 120 J = 1, NSUM = V1*C( 1, J ) + V2*C( 2, J ) + V3*C( 3, J ) +$ V4*C( 4, J ) + V5*C( 5, J ) + V6*C( 6, J )C( 1, J ) = C( 1, J ) - SUM*T1C( 2, J ) = C( 2, J ) - SUM*T2C( 3, J ) = C( 3, J ) - SUM*T3C( 4, J ) = C( 4, J ) - SUM*T4C( 5, J ) = C( 5, J ) - SUM*T5C( 6, J ) = C( 6, J ) - SUM*T6120 CONTINUEGO TO 410130 CONTINUE** Special code for 7 x 7 Householder*V1 = V( 1 )T1 = TAU*V1V2 = V( 2 )T2 = TAU*V2V3 = V( 3 )T3 = TAU*V3V4 = V( 4 )T4 = TAU*V4V5 = V( 5 )T5 = TAU*V5V6 = V( 6 )T6 = TAU*V6V7 = V( 7 )T7 = TAU*V7DO 140 J = 1, NSUM = V1*C( 1, J ) + V2*C( 2, J ) + V3*C( 3, J ) +$ V4*C( 4, J ) + V5*C( 5, J ) + V6*C( 6, J ) +$ V7*C( 7, J )C( 1, J ) = C( 1, J ) - SUM*T1C( 2, J ) = C( 2, J ) - SUM*T2C( 3, J ) = C( 3, J ) - SUM*T3C( 4, J ) = C( 4, J ) - SUM*T4C( 5, J ) = C( 5, J ) - SUM*T5C( 6, J ) = C( 6, J ) - SUM*T6C( 7, J ) = C( 7, J ) - SUM*T7140 CONTINUEGO TO 410150 CONTINUE** Special code for 8 x 8 Householder*V1 = V( 1 )T1 = TAU*V1V2 = V( 2 )T2 = TAU*V2V3 = V( 3 )T3 = TAU*V3V4 = V( 4 )T4 = TAU*V4V5 = V( 5 )T5 = TAU*V5V6 = V( 6 )T6 = TAU*V6V7 = V( 7 )T7 = TAU*V7V8 = V( 8 )T8 = TAU*V8DO 160 J = 1, NSUM = V1*C( 1, J ) + V2*C( 2, J ) + V3*C( 3, J ) +$ V4*C( 4, J ) + V5*C( 5, J ) + V6*C( 6, J ) +$ V7*C( 7, J ) + V8*C( 8, J )C( 1, J ) = C( 1, J ) - SUM*T1C( 2, J ) = C( 2, J ) - SUM*T2C( 3, J ) = C( 3, J ) - SUM*T3C( 4, J ) = C( 4, J ) - SUM*T4C( 5, J ) = C( 5, J ) - SUM*T5C( 6, J ) = C( 6, J ) - SUM*T6C( 7, J ) = C( 7, J ) - SUM*T7C( 8, J ) = C( 8, J ) - SUM*T8160 CONTINUEGO TO 410170 CONTINUE** Special code for 9 x 9 Householder*V1 = V( 1 )T1 = TAU*V1V2 = V( 2 )T2 = TAU*V2V3 = V( 3 )T3 = TAU*V3V4 = V( 4 )T4 = TAU*V4V5 = V( 5 )T5 = TAU*V5V6 = V( 6 )T6 = TAU*V6V7 = V( 7 )T7 = TAU*V7V8 = V( 8 )T8 = TAU*V8V9 = V( 9 )T9 = TAU*V9DO 180 J = 1, NSUM = V1*C( 1, J ) + V2*C( 2, J ) + V3*C( 3, J ) +$ V4*C( 4, J ) + V5*C( 5, J ) + V6*C( 6, J ) +$ V7*C( 7, J ) + V8*C( 8, J ) + V9*C( 9, J )C( 1, J ) = C( 1, J ) - SUM*T1C( 2, J ) = C( 2, J ) - SUM*T2C( 3, J ) = C( 3, J ) - SUM*T3C( 4, J ) = C( 4, J ) - SUM*T4C( 5, J ) = C( 5, J ) - SUM*T5C( 6, J ) = C( 6, J ) - SUM*T6C( 7, J ) = C( 7, J ) - SUM*T7C( 8, J ) = C( 8, J ) - SUM*T8C( 9, J ) = C( 9, J ) - SUM*T9180 CONTINUEGO TO 410190 CONTINUE** Special code for 10 x 10 Householder*V1 = V( 1 )T1 = TAU*V1V2 = V( 2 )T2 = TAU*V2V3 = V( 3 )T3 = TAU*V3V4 = V( 4 )T4 = TAU*V4V5 = V( 5 )T5 = TAU*V5V6 = V( 6 )T6 = TAU*V6V7 = V( 7 )T7 = TAU*V7V8 = V( 8 )T8 = TAU*V8V9 = V( 9 )T9 = TAU*V9V10 = V( 10 )T10 = TAU*V10DO 200 J = 1, NSUM = V1*C( 1, J ) + V2*C( 2, J ) + V3*C( 3, J ) +$ V4*C( 4, J ) + V5*C( 5, J ) + V6*C( 6, J ) +$ V7*C( 7, J ) + V8*C( 8, J ) + V9*C( 9, J ) +$ V10*C( 10, J )C( 1, J ) = C( 1, J ) - SUM*T1C( 2, J ) = C( 2, J ) - SUM*T2C( 3, J ) = C( 3, J ) - SUM*T3C( 4, J ) = C( 4, J ) - SUM*T4C( 5, J ) = C( 5, J ) - SUM*T5C( 6, J ) = C( 6, J ) - SUM*T6C( 7, J ) = C( 7, J ) - SUM*T7C( 8, J ) = C( 8, J ) - SUM*T8C( 9, J ) = C( 9, J ) - SUM*T9C( 10, J ) = C( 10, J ) - SUM*T10200 CONTINUEGO TO 410ELSE** Form C * H, where H has order n.*GO TO ( 210, 230, 250, 270, 290, 310, 330, 350,$ 370, 390 )N** Code for general N** w := C * v*CALL DGEMV( 'No transpose', M, N, ONE, C, LDC, V, 1, ZERO,$ WORK, 1 )** C := C - tau * w * v'*CALL DGER( M, N, -TAU, WORK, 1, V, 1, C, LDC )GO TO 410210 CONTINUE** Special code for 1 x 1 Householder*T1 = ONE - TAU*V( 1 )*V( 1 )DO 220 J = 1, MC( J, 1 ) = T1*C( J, 1 )220 CONTINUEGO TO 410230 CONTINUE** Special code for 2 x 2 Householder*V1 = V( 1 )T1 = TAU*V1V2 = V( 2 )T2 = TAU*V2DO 240 J = 1, MSUM = V1*C( J, 1 ) + V2*C( J, 2 )C( J, 1 ) = C( J, 1 ) - SUM*T1C( J, 2 ) = C( J, 2 ) - SUM*T2240 CONTINUEGO TO 410250 CONTINUE** Special code for 3 x 3 Householder*V1 = V( 1 )T1 = TAU*V1V2 = V( 2 )T2 = TAU*V2V3 = V( 3 )T3 = TAU*V3DO 260 J = 1, MSUM = V1*C( J, 1 ) + V2*C( J, 2 ) + V3*C( J, 3 )C( J, 1 ) = C( J, 1 ) - SUM*T1C( J, 2 ) = C( J, 2 ) - SUM*T2C( J, 3 ) = C( J, 3 ) - SUM*T3260 CONTINUEGO TO 410270 CONTINUE** Special code for 4 x 4 Householder*V1 = V( 1 )T1 = TAU*V1V2 = V( 2 )T2 = TAU*V2V3 = V( 3 )T3 = TAU*V3V4 = V( 4 )T4 = TAU*V4DO 280 J = 1, MSUM = V1*C( J, 1 ) + V2*C( J, 2 ) + V3*C( J, 3 ) +$ V4*C( J, 4 )C( J, 1 ) = C( J, 1 ) - SUM*T1C( J, 2 ) = C( J, 2 ) - SUM*T2C( J, 3 ) = C( J, 3 ) - SUM*T3C( J, 4 ) = C( J, 4 ) - SUM*T4280 CONTINUEGO TO 410290 CONTINUE** Special code for 5 x 5 Householder*V1 = V( 1 )T1 = TAU*V1V2 = V( 2 )T2 = TAU*V2V3 = V( 3 )T3 = TAU*V3V4 = V( 4 )T4 = TAU*V4V5 = V( 5 )T5 = TAU*V5DO 300 J = 1, MSUM = V1*C( J, 1 ) + V2*C( J, 2 ) + V3*C( J, 3 ) +$ V4*C( J, 4 ) + V5*C( J, 5 )C( J, 1 ) = C( J, 1 ) - SUM*T1C( J, 2 ) = C( J, 2 ) - SUM*T2C( J, 3 ) = C( J, 3 ) - SUM*T3C( J, 4 ) = C( J, 4 ) - SUM*T4C( J, 5 ) = C( J, 5 ) - SUM*T5300 CONTINUEGO TO 410310 CONTINUE** Special code for 6 x 6 Householder*V1 = V( 1 )T1 = TAU*V1V2 = V( 2 )T2 = TAU*V2V3 = V( 3 )T3 = TAU*V3V4 = V( 4 )T4 = TAU*V4V5 = V( 5 )T5 = TAU*V5V6 = V( 6 )T6 = TAU*V6DO 320 J = 1, MSUM = V1*C( J, 1 ) + V2*C( J, 2 ) + V3*C( J, 3 ) +$ V4*C( J, 4 ) + V5*C( J, 5 ) + V6*C( J, 6 )C( J, 1 ) = C( J, 1 ) - SUM*T1C( J, 2 ) = C( J, 2 ) - SUM*T2C( J, 3 ) = C( J, 3 ) - SUM*T3C( J, 4 ) = C( J, 4 ) - SUM*T4C( J, 5 ) = C( J, 5 ) - SUM*T5C( J, 6 ) = C( J, 6 ) - SUM*T6320 CONTINUEGO TO 410330 CONTINUE** Special code for 7 x 7 Householder*V1 = V( 1 )T1 = TAU*V1V2 = V( 2 )T2 = TAU*V2V3 = V( 3 )T3 = TAU*V3V4 = V( 4 )T4 = TAU*V4V5 = V( 5 )T5 = TAU*V5V6 = V( 6 )T6 = TAU*V6V7 = V( 7 )T7 = TAU*V7DO 340 J = 1, MSUM = V1*C( J, 1 ) + V2*C( J, 2 ) + V3*C( J, 3 ) +$ V4*C( J, 4 ) + V5*C( J, 5 ) + V6*C( J, 6 ) +$ V7*C( J, 7 )C( J, 1 ) = C( J, 1 ) - SUM*T1C( J, 2 ) = C( J, 2 ) - SUM*T2C( J, 3 ) = C( J, 3 ) - SUM*T3C( J, 4 ) = C( J, 4 ) - SUM*T4C( J, 5 ) = C( J, 5 ) - SUM*T5C( J, 6 ) = C( J, 6 ) - SUM*T6C( J, 7 ) = C( J, 7 ) - SUM*T7340 CONTINUEGO TO 410350 CONTINUE** Special code for 8 x 8 Householder*V1 = V( 1 )T1 = TAU*V1V2 = V( 2 )T2 = TAU*V2V3 = V( 3 )T3 = TAU*V3V4 = V( 4 )T4 = TAU*V4V5 = V( 5 )T5 = TAU*V5V6 = V( 6 )T6 = TAU*V6V7 = V( 7 )T7 = TAU*V7V8 = V( 8 )T8 = TAU*V8DO 360 J = 1, MSUM = V1*C( J, 1 ) + V2*C( J, 2 ) + V3*C( J, 3 ) +$ V4*C( J, 4 ) + V5*C( J, 5 ) + V6*C( J, 6 ) +$ V7*C( J, 7 ) + V8*C( J, 8 )C( J, 1 ) = C( J, 1 ) - SUM*T1C( J, 2 ) = C( J, 2 ) - SUM*T2C( J, 3 ) = C( J, 3 ) - SUM*T3C( J, 4 ) = C( J, 4 ) - SUM*T4C( J, 5 ) = C( J, 5 ) - SUM*T5C( J, 6 ) = C( J, 6 ) - SUM*T6C( J, 7 ) = C( J, 7 ) - SUM*T7C( J, 8 ) = C( J, 8 ) - SUM*T8360 CONTINUEGO TO 410370 CONTINUE** Special code for 9 x 9 Householder*V1 = V( 1 )T1 = TAU*V1V2 = V( 2 )T2 = TAU*V2V3 = V( 3 )T3 = TAU*V3V4 = V( 4 )T4 = TAU*V4V5 = V( 5 )T5 = TAU*V5V6 = V( 6 )T6 = TAU*V6V7 = V( 7 )T7 = TAU*V7V8 = V( 8 )T8 = TAU*V8V9 = V( 9 )T9 = TAU*V9DO 380 J = 1, MSUM = V1*C( J, 1 ) + V2*C( J, 2 ) + V3*C( J, 3 ) +$ V4*C( J, 4 ) + V5*C( J, 5 ) + V6*C( J, 6 ) +$ V7*C( J, 7 ) + V8*C( J, 8 ) + V9*C( J, 9 )C( J, 1 ) = C( J, 1 ) - SUM*T1C( J, 2 ) = C( J, 2 ) - SUM*T2C( J, 3 ) = C( J, 3 ) - SUM*T3C( J, 4 ) = C( J, 4 ) - SUM*T4C( J, 5 ) = C( J, 5 ) - SUM*T5C( J, 6 ) = C( J, 6 ) - SUM*T6C( J, 7 ) = C( J, 7 ) - SUM*T7C( J, 8 ) = C( J, 8 ) - SUM*T8C( J, 9 ) = C( J, 9 ) - SUM*T9380 CONTINUEGO TO 410390 CONTINUE** Special code for 10 x 10 Householder*V1 = V( 1 )T1 = TAU*V1V2 = V( 2 )T2 = TAU*V2V3 = V( 3 )T3 = TAU*V3V4 = V( 4 )T4 = TAU*V4V5 = V( 5 )T5 = TAU*V5V6 = V( 6 )T6 = TAU*V6V7 = V( 7 )T7 = TAU*V7V8 = V( 8 )T8 = TAU*V8V9 = V( 9 )T9 = TAU*V9V10 = V( 10 )T10 = TAU*V10DO 400 J = 1, MSUM = V1*C( J, 1 ) + V2*C( J, 2 ) + V3*C( J, 3 ) +$ V4*C( J, 4 ) + V5*C( J, 5 ) + V6*C( J, 6 ) +$ V7*C( J, 7 ) + V8*C( J, 8 ) + V9*C( J, 9 ) +$ V10*C( J, 10 )C( J, 1 ) = C( J, 1 ) - SUM*T1C( J, 2 ) = C( J, 2 ) - SUM*T2C( J, 3 ) = C( J, 3 ) - SUM*T3C( J, 4 ) = C( J, 4 ) - SUM*T4C( J, 5 ) = C( J, 5 ) - SUM*T5C( J, 6 ) = C( J, 6 ) - SUM*T6C( J, 7 ) = C( J, 7 ) - SUM*T7C( J, 8 ) = C( J, 8 ) - SUM*T8C( J, 9 ) = C( J, 9 ) - SUM*T9C( J, 10 ) = C( J, 10 ) - SUM*T10400 CONTINUEGO TO 410END IF410 CONTINUERETURN** End of DLARFX*ENDSUBROUTINE DLARTG( F, G, CS, SN, R )** -- LAPACK auxiliary 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 ..DOUBLE PRECISION CS, F, G, R, SN* ..** Purpose* =======** DLARTG generate a plane rotation so that** [ CS SN ] . [ F ] = [ R ] where CS**2 + SN**2 = 1.* [ -SN CS ] [ G ] [ 0 ]** This is a slower, more accurate version of the BLAS1 routine DROTG,* with the following other differences:* F and G are unchanged on return.* If G=0, then CS=1 and SN=0.* If F=0 and (G .ne. 0), then CS=0 and SN=1 without doing any* floating point operations (saves work in DBDSQR when* there are zeros on the diagonal).** If F exceeds G in magnitude, CS will be positive.** Arguments* =========** F (input) DOUBLE PRECISION* The first component of vector to be rotated.** G (input) DOUBLE PRECISION* The second component of vector to be rotated.** CS (output) DOUBLE PRECISION* The cosine of the rotation.** SN (output) DOUBLE PRECISION* The sine of the rotation.** R (output) DOUBLE PRECISION* The nonzero component of the rotated vector.** =====================================================================** .. Parameters ..DOUBLE PRECISION ZEROPARAMETER ( ZERO = 0.0D0 )DOUBLE PRECISION ONEPARAMETER ( ONE = 1.0D0 )DOUBLE PRECISION TWOPARAMETER ( TWO = 2.0D0 )* ..* .. Local Scalars ..LOGICAL FIRSTINTEGER COUNT, IDOUBLE PRECISION EPS, F1, G1, SAFMIN, SAFMN2, SAFMX2, SCALE* ..* .. External Functions ..DOUBLE PRECISION DLAMCHEXTERNAL DLAMCH* ..* .. Intrinsic Functions ..INTRINSIC ABS, INT, LOG, MAX, SQRT* ..* .. Save statement ..SAVE FIRST, SAFMX2, SAFMIN, SAFMN2* ..* .. Data statements ..DATA FIRST / .TRUE. /* ..* .. Executable Statements ..*IF( FIRST ) THENFIRST = .FALSE.SAFMIN = DLAMCH( 'S' )EPS = DLAMCH( 'E' )SAFMN2 = DLAMCH( 'B' )**INT( LOG( SAFMIN / EPS ) /$ LOG( DLAMCH( 'B' ) ) / TWO )SAFMX2 = ONE / SAFMN2END IFIF( G.EQ.ZERO ) THENCS = ONESN = ZEROR = FELSE IF( F.EQ.ZERO ) THENCS = ZEROSN = ONER = GELSEF1 = FG1 = GSCALE = MAX( ABS( F1 ), ABS( G1 ) )IF( SCALE.GE.SAFMX2 ) THENCOUNT = 010 CONTINUECOUNT = COUNT + 1F1 = F1*SAFMN2G1 = G1*SAFMN2SCALE = MAX( ABS( F1 ), ABS( G1 ) )IF( SCALE.GE.SAFMX2 )$ GO TO 10R = SQRT( F1**2+G1**2 )CS = F1 / RSN = G1 / RDO 20 I = 1, COUNTR = R*SAFMX220 CONTINUEELSE IF( SCALE.LE.SAFMN2 ) THENCOUNT = 030 CONTINUECOUNT = COUNT + 1F1 = F1*SAFMX2G1 = G1*SAFMX2SCALE = MAX( ABS( F1 ), ABS( G1 ) )IF( SCALE.LE.SAFMN2 )$ GO TO 30R = SQRT( F1**2+G1**2 )CS = F1 / RSN = G1 / RDO 40 I = 1, COUNTR = R*SAFMN240 CONTINUEELSER = SQRT( F1**2+G1**2 )CS = F1 / RSN = G1 / REND IFIF( ABS( F ).GT.ABS( G ) .AND. CS.LT.ZERO ) THENCS = -CSSN = -SNR = -REND IFEND IFRETURN** End of DLARTG*ENDSUBROUTINE DLAS2( F, G, H, SSMIN, SSMAX )** -- LAPACK auxiliary 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 ..DOUBLE PRECISION F, G, H, SSMAX, SSMIN* ..** Purpose* =======** DLAS2 computes the singular values of the 2-by-2 matrix* [ F G ]* [ 0 H ].* On return, SSMIN is the smaller singular value and SSMAX is the* larger singular value.** Arguments* =========** F (input) DOUBLE PRECISION* The (1,1) element of the 2-by-2 matrix.** G (input) DOUBLE PRECISION* The (1,2) element of the 2-by-2 matrix.** H (input) DOUBLE PRECISION* The (2,2) element of the 2-by-2 matrix.** SSMIN (output) DOUBLE PRECISION* The smaller singular value.** SSMAX (output) DOUBLE PRECISION* The larger singular value.** Further Details* ===============** Barring over/underflow, all output quantities are correct to within* a few units in the last place (ulps), even in the absence of a guard* digit in addition/subtraction.** In IEEE arithmetic, the code works correctly if one matrix element is* infinite.** Overflow will not occur unless the largest singular value itself* overflows, or is within a few ulps of overflow. (On machines with* partial overflow, like the Cray, overflow may occur if the largest* singular value is within a factor of 2 of overflow.)** Underflow is harmless if underflow is gradual. Otherwise, results* may correspond to a matrix modified by perturbations of size near* the underflow threshold.** ====================================================================** .. Parameters ..DOUBLE PRECISION ZEROPARAMETER ( ZERO = 0.0D0 )DOUBLE PRECISION ONEPARAMETER ( ONE = 1.0D0 )DOUBLE PRECISION TWOPARAMETER ( TWO = 2.0D0 )* ..* .. Local Scalars ..DOUBLE PRECISION AS, AT, AU, C, FA, FHMN, FHMX, GA, HA* ..* .. Intrinsic Functions ..INTRINSIC ABS, MAX, MIN, SQRT* ..* .. Executable Statements ..*FA = ABS( F )GA = ABS( G )HA = ABS( H )FHMN = MIN( FA, HA )FHMX = MAX( FA, HA )IF( FHMN.EQ.ZERO ) THENSSMIN = ZEROIF( FHMX.EQ.ZERO ) THENSSMAX = GAELSESSMAX = MAX( FHMX, GA )*SQRT( ONE+$ ( MIN( FHMX, GA ) / MAX( FHMX, GA ) )**2 )END IFELSEIF( GA.LT.FHMX ) THENAS = ONE + FHMN / FHMXAT = ( FHMX-FHMN ) / FHMXAU = ( GA / FHMX )**2C = TWO / ( SQRT( AS*AS+AU )+SQRT( AT*AT+AU ) )SSMIN = FHMN*CSSMAX = FHMX / CELSEAU = FHMX / GAIF( AU.EQ.ZERO ) THEN** Avoid possible harmful underflow if exponent range* asymmetric (true SSMIN may not underflow even if* AU underflows)*SSMIN = ( FHMN*FHMX ) / GASSMAX = GAELSEAS = ONE + FHMN / FHMXAT = ( FHMX-FHMN ) / FHMXC = ONE / ( SQRT( ONE+( AS*AU )**2 )+$ SQRT( ONE+( AT*AU )**2 ) )SSMIN = ( FHMN*C )*AUSSMIN = SSMIN + SSMINSSMAX = GA / ( C+C )END IFEND IFEND IFRETURN** End of DLAS2*ENDSUBROUTINE DLASCL( TYPE, KL, KU, CFROM, CTO, M, N, A, LDA, INFO )** -- LAPACK auxiliary routine (version 3.0) --* Univ. of Tennessee, Univ. of California Berkeley, NAG Ltd.,* Courant Institute, Argonne National Lab, and Rice University* February 29, 1992** .. Scalar Arguments ..CHARACTER TYPEINTEGER INFO, KL, KU, LDA, M, NDOUBLE PRECISION CFROM, CTO* ..* .. Array Arguments ..DOUBLE PRECISION A( LDA, * )* ..** Purpose* =======** DLASCL multiplies the M by N real matrix A by the real scalar* CTO/CFROM. This is done without over/underflow as long as the final* result CTO*A(I,J)/CFROM does not over/underflow. TYPE specifies that* A may be full, upper triangular, lower triangular, upper Hessenberg,* or banded.** Arguments* =========** TYPE (input) CHARACTER*1* TYPE indices the storage type of the input matrix.* = 'G': A is a full matrix.* = 'L': A is a lower triangular matrix.* = 'U': A is an upper triangular matrix.* = 'H': A is an upper Hessenberg matrix.* = 'B': A is a symmetric band matrix with lower bandwidth KL* and upper bandwidth KU and with the only the lower* half stored.* = 'Q': A is a symmetric band matrix with lower bandwidth KL* and upper bandwidth KU and with the only the upper* half stored.* = 'Z': A is a band matrix with lower bandwidth KL and upper* bandwidth KU.** KL (input) INTEGER* The lower bandwidth of A. Referenced only if TYPE = 'B',* 'Q' or 'Z'.** KU (input) INTEGER* The upper bandwidth of A. Referenced only if TYPE = 'B',* 'Q' or 'Z'.** CFROM (input) DOUBLE PRECISION* CTO (input) DOUBLE PRECISION* The matrix A is multiplied by CTO/CFROM. A(I,J) is computed* without over/underflow if the final result CTO*A(I,J)/CFROM* can be represented without over/underflow. CFROM must be* nonzero.** M (input) INTEGER* The number of rows of the matrix A. M >= 0.** N (input) INTEGER* The number of columns of the matrix A. N >= 0.** A (input/output) DOUBLE PRECISION array, dimension (LDA,M)* The matrix to be multiplied by CTO/CFROM. See TYPE for the* storage type.** LDA (input) INTEGER* The leading dimension of the array A. LDA >= max(1,M).** 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 DONEINTEGER I, ITYPE, J, K1, K2, K3, K4DOUBLE PRECISION BIGNUM, CFROM1, CFROMC, CTO1, CTOC, MUL, SMLNUM* ..* .. External Functions ..LOGICAL LSAMEDOUBLE PRECISION DLAMCHEXTERNAL LSAME, DLAMCH* ..* .. Intrinsic Functions ..INTRINSIC ABS, MAX, MIN* ..* .. External Subroutines ..EXTERNAL XERBLA* ..* .. Executable Statements ..** Test the input arguments*INFO = 0*IF( LSAME( TYPE, 'G' ) ) THENITYPE = 0ELSE IF( LSAME( TYPE, 'L' ) ) THENITYPE = 1ELSE IF( LSAME( TYPE, 'U' ) ) THENITYPE = 2ELSE IF( LSAME( TYPE, 'H' ) ) THENITYPE = 3ELSE IF( LSAME( TYPE, 'B' ) ) THENITYPE = 4ELSE IF( LSAME( TYPE, 'Q' ) ) THENITYPE = 5ELSE IF( LSAME( TYPE, 'Z' ) ) THENITYPE = 6ELSEITYPE = -1END IF*IF( ITYPE.EQ.-1 ) THENINFO = -1ELSE IF( CFROM.EQ.ZERO ) THENINFO = -4ELSE IF( M.LT.0 ) THENINFO = -6ELSE IF( N.LT.0 .OR. ( ITYPE.EQ.4 .AND. N.NE.M ) .OR.$ ( ITYPE.EQ.5 .AND. N.NE.M ) ) THENINFO = -7ELSE IF( ITYPE.LE.3 .AND. LDA.LT.MAX( 1, M ) ) THENINFO = -9ELSE IF( ITYPE.GE.4 ) THENIF( KL.LT.0 .OR. KL.GT.MAX( M-1, 0 ) ) THENINFO = -2ELSE IF( KU.LT.0 .OR. KU.GT.MAX( N-1, 0 ) .OR.$ ( ( ITYPE.EQ.4 .OR. ITYPE.EQ.5 ) .AND. KL.NE.KU ) )$ THENINFO = -3ELSE IF( ( ITYPE.EQ.4 .AND. LDA.LT.KL+1 ) .OR.$ ( ITYPE.EQ.5 .AND. LDA.LT.KU+1 ) .OR.$ ( ITYPE.EQ.6 .AND. LDA.LT.2*KL+KU+1 ) ) THENINFO = -9END IFEND IF*IF( INFO.NE.0 ) THENCALL XERBLA( 'DLASCL', -INFO )RETURNEND IF** Quick return if possible*IF( N.EQ.0 .OR. M.EQ.0 )$ RETURN** Get machine parameters*SMLNUM = DLAMCH( 'S' )BIGNUM = ONE / SMLNUM*CFROMC = CFROMCTOC = CTO*10 CONTINUECFROM1 = CFROMC*SMLNUMCTO1 = CTOC / BIGNUMIF( ABS( CFROM1 ).GT.ABS( CTOC ) .AND. CTOC.NE.ZERO ) THENMUL = SMLNUMDONE = .FALSE.CFROMC = CFROM1ELSE IF( ABS( CTO1 ).GT.ABS( CFROMC ) ) THENMUL = BIGNUMDONE = .FALSE.CTOC = CTO1ELSEMUL = CTOC / CFROMCDONE = .TRUE.END IF*IF( ITYPE.EQ.0 ) THEN** Full matrix*DO 30 J = 1, NDO 20 I = 1, MA( I, J ) = A( I, J )*MUL20 CONTINUE30 CONTINUE*ELSE IF( ITYPE.EQ.1 ) THEN** Lower triangular matrix*DO 50 J = 1, NDO 40 I = J, MA( I, J ) = A( I, J )*MUL40 CONTINUE50 CONTINUE*ELSE IF( ITYPE.EQ.2 ) THEN** Upper triangular matrix*DO 70 J = 1, NDO 60 I = 1, MIN( J, M )A( I, J ) = A( I, J )*MUL60 CONTINUE70 CONTINUE*ELSE IF( ITYPE.EQ.3 ) THEN** Upper Hessenberg matrix*DO 90 J = 1, NDO 80 I = 1, MIN( J+1, M )A( I, J ) = A( I, J )*MUL80 CONTINUE90 CONTINUE*ELSE IF( ITYPE.EQ.4 ) THEN** Lower half of a symmetric band matrix*K3 = KL + 1K4 = N + 1DO 110 J = 1, NDO 100 I = 1, MIN( K3, K4-J )A( I, J ) = A( I, J )*MUL100 CONTINUE110 CONTINUE*ELSE IF( ITYPE.EQ.5 ) THEN** Upper half of a symmetric band matrix*K1 = KU + 2K3 = KU + 1DO 130 J = 1, NDO 120 I = MAX( K1-J, 1 ), K3A( I, J ) = A( I, J )*MUL120 CONTINUE130 CONTINUE*ELSE IF( ITYPE.EQ.6 ) THEN** Band matrix*K1 = KL + KU + 2K2 = KL + 1K3 = 2*KL + KU + 1K4 = KL + KU + 1 + MDO 150 J = 1, NDO 140 I = MAX( K1-J, K2 ), MIN( K3, K4-J )A( I, J ) = A( I, J )*MUL140 CONTINUE150 CONTINUE*END IF*IF( .NOT.DONE )$ GO TO 10*RETURN** End of DLASCL*ENDSUBROUTINE DLASET( UPLO, M, N, ALPHA, BETA, A, LDA )** -- LAPACK auxiliary routine (version 3.0) --* Univ. of Tennessee, Univ. of California Berkeley, NAG Ltd.,* Courant Institute, Argonne National Lab, and Rice University* October 31, 1992** .. Scalar Arguments ..CHARACTER UPLOINTEGER LDA, M, NDOUBLE PRECISION ALPHA, BETA* ..* .. Array Arguments ..DOUBLE PRECISION A( LDA, * )* ..** Purpose* =======** DLASET initializes an m-by-n matrix A to BETA on the diagonal and* ALPHA on the offdiagonals.** Arguments* =========** UPLO (input) CHARACTER*1* Specifies the part of the matrix A to be set.* = 'U': Upper triangular part is set; the strictly lower* triangular part of A is not changed.* = 'L': Lower triangular part is set; the strictly upper* triangular part of A is not changed.* Otherwise: All of the matrix A is set.** M (input) INTEGER* The number of rows of the matrix A. M >= 0.** N (input) INTEGER* The number of columns of the matrix A. N >= 0.** ALPHA (input) DOUBLE PRECISION* The constant to which the offdiagonal elements are to be set.** BETA (input) DOUBLE PRECISION* The constant to which the diagonal elements are to be set.** A (input/output) DOUBLE PRECISION array, dimension (LDA,N)* On exit, the leading m-by-n submatrix of A is set as follows:** if UPLO = 'U', A(i,j) = ALPHA, 1<=i<=j-1, 1<=j<=n,* if UPLO = 'L', A(i,j) = ALPHA, j+1<=i<=m, 1<=j<=n,* otherwise, A(i,j) = ALPHA, 1<=i<=m, 1<=j<=n, i.ne.j,** and, for all UPLO, A(i,i) = BETA, 1<=i<=min(m,n).** LDA (input) INTEGER* The leading dimension of the array A. LDA >= max(1,M).** =====================================================================** .. Local Scalars ..INTEGER I, J* ..* .. External Functions ..LOGICAL LSAMEEXTERNAL LSAME* ..* .. Intrinsic Functions ..INTRINSIC MIN* ..* .. Executable Statements ..*IF( LSAME( UPLO, 'U' ) ) THEN** Set the strictly upper triangular or trapezoidal part of the* array to ALPHA.*DO 20 J = 2, NDO 10 I = 1, MIN( J-1, M )A( I, J ) = ALPHA10 CONTINUE20 CONTINUE*ELSE IF( LSAME( UPLO, 'L' ) ) THEN** Set the strictly lower triangular or trapezoidal part of the* array to ALPHA.*DO 40 J = 1, MIN( M, N )DO 30 I = J + 1, MA( I, J ) = ALPHA30 CONTINUE40 CONTINUE*ELSE** Set the leading m-by-n submatrix to ALPHA.*DO 60 J = 1, NDO 50 I = 1, MA( I, J ) = ALPHA50 CONTINUE60 CONTINUEEND IF** Set the first min(M,N) diagonal elements to BETA.*DO 70 I = 1, MIN( M, N )A( I, I ) = BETA70 CONTINUE*RETURN** End of DLASET*ENDSUBROUTINE DLASQ1( N, D, E, WORK, INFO )** -- LAPACK routine (version 3.0) --* Univ. of Tennessee, Univ. of California Berkeley, NAG Ltd.,* Courant Institute, Argonne National Lab, and Rice University* June 30, 1999** .. Scalar Arguments ..INTEGER INFO, N* ..* .. Array Arguments ..DOUBLE PRECISION D( * ), E( * ), WORK( * )* ..** Purpose* =======** DLASQ1 computes the singular values of a real N-by-N bidiagonal* matrix with diagonal D and off-diagonal E. The singular values* are computed to high relative accuracy, in the absence of* denormalization, underflow and overflow. The algorithm was first* presented in** "Accurate singular values and differential qd algorithms" by K. V.* Fernando and B. N. Parlett, Numer. Math., Vol-67, No. 2, pp. 191-230,* 1994,** and the present implementation is described in "An implementation of* dqds", LAPACK technical report.** Note : DLASQ1 works only on machines which follow ieee-754* floating-point standard in their handling of infinities and NaNs.* Normal execution of DLASQ1 may create NaNs and infinities and hence* may abort due to a floating point exception in environments which* do not conform to the ieee standard.** Arguments* =========** N (input) INTEGER* The number of rows and columns in the matrix. N >= 0.** D (input/output) DOUBLE PRECISION array, dimension (N)* On entry, D contains the diagonal elements of the* bidiagonal matrix whose SVD is desired. On normal exit,* D contains the singular values in decreasing order.** E (input/output) DOUBLE PRECISION array, dimension (N)* On entry, elements E(1:N-1) contain the off-diagonal elements* of the bidiagonal matrix whose SVD is desired.* On exit, E is overwritten.** WORK (workspace) DOUBLE PRECISION array, dimension (4*N)** INFO (output) INTEGER* = 0: successful exit* < 0: if INFO = -i, the i-th argument had an illegal value* > 0: the algorithm failed* = 1, a split was marked by a positive value in E* = 2, current block of Z not diagonalized after 30*N* iterations (in inner while loop)* = 3, termination criterion of outer while loop not met* (program created more than N unreduced blocks)** =====================================================================** .. Parameters ..DOUBLE PRECISION ZEROPARAMETER ( ZERO = 0.0D0 )* ..* .. Local Scalars ..INTEGER I, IINFODOUBLE PRECISION EPS, SCALE, SFMIN, SIGMN, SIGMX* ..* .. External Subroutines ..EXTERNAL DCOPY, DLAS2, DLASCL, DLASQ2, DLASRT, XERBLA* ..* .. External Functions ..DOUBLE PRECISION DLAMCHEXTERNAL DLAMCH* ..* .. Intrinsic Functions ..INTRINSIC ABS, MAX, SQRT* ..* .. Executable Statements ..*INFO = 0IF( N.LT.0 ) THENINFO = -2CALL XERBLA( 'DLASQ1', -INFO )RETURNELSE IF( N.EQ.0 ) THENRETURNELSE IF( N.EQ.1 ) THEND( 1 ) = ABS( D( 1 ) )RETURNELSE IF( N.EQ.2 ) THENCALL DLAS2( D( 1 ), E( 1 ), D( 2 ), SIGMN, SIGMX )D( 1 ) = SIGMXD( 2 ) = SIGMNRETURNEND IF** Estimate the largest singular value.*SIGMX = ZERODO 10 I = 1, N - 1D( I ) = ABS( D( I ) )SIGMX = MAX( SIGMX, ABS( E( I ) ) )10 CONTINUED( N ) = ABS( D( N ) )** Early return if SIGMX is zero (matrix is already diagonal).*IF( SIGMX.EQ.ZERO ) THENCALL DLASRT( 'D', N, D, IINFO )GO TO 50END IF*DO 20 I = 1, NSIGMX = MAX( SIGMX, D( I ) )20 CONTINUE** Copy D and E into WORK (in the Z format) and scale (squaring the* input data makes scaling by a power of the radix pointless).*EPS = DLAMCH( 'Precision' )SFMIN = DLAMCH( 'Safe minimum' )SCALE = SQRT( EPS / SFMIN )CALL DCOPY( N, D, 1, WORK( 1 ), 2 )CALL DCOPY( N-1, E, 1, WORK( 2 ), 2 )CALL DLASCL( 'G', 0, 0, SIGMX, SCALE, 2*N-1, 1, WORK, 2*N-1,$ IINFO )** Compute the q's and e's.*DO 30 I = 1, 2*N - 1WORK( I ) = WORK( I )**230 CONTINUEWORK( 2*N ) = ZERO*CALL DLASQ2( N, WORK, INFO )*IF( INFO.EQ.0 ) THENDO 40 I = 1, ND( I ) = SQRT( WORK( I ) )40 CONTINUECALL DLASCL( 'G', 0, 0, SCALE, SIGMX, N, 1, D, N, IINFO )END IF*50 CONTINUERETURN** End of DLASQ1*ENDSUBROUTINE DLASQ2( N, Z, INFO )** -- LAPACK auxiliary routine (version 3.0) --* Univ. of Tennessee, Univ. of California Berkeley, NAG Ltd.,* Courant Institute, Argonne National Lab, and Rice University* June 30, 1999** .. Scalar Arguments ..INTEGER INFO, N* ..* .. Array Arguments ..DOUBLE PRECISION Z( * )* ..** Purpose* =======** DLASQ2 computes all the eigenvalues of the symmetric positive* definite tridiagonal matrix associated with the qd array Z to high* relative accuracy are computed to high relative accuracy, in the* absence of denormalization, underflow and overflow.** To see the relation of Z to the tridiagonal matrix, let L be a* unit lower bidiagonal matrix with subdiagonals Z(2,4,6,,..) and* let U be an upper bidiagonal matrix with 1's above and diagonal* Z(1,3,5,,..). The tridiagonal is L*U or, if you prefer, the* symmetric tridiagonal to which it is similar.** Note : DLASQ2 works only on machines which follow ieee-754* floating-point standard in their handling of infinities and NaNs.* Normal execution of DLASQ2 may create NaNs and infinities and hence* may abort due to a floating point exception in environments which* do not conform to the ieee standard.** Arguments* =========** N (input) INTEGER* The number of rows and columns in the matrix. N >= 0.** Z (workspace) DOUBLE PRECISION array, dimension ( 4*N )* On entry Z holds the qd array. On exit, entries 1 to N hold* the eigenvalues in decreasing order, Z( 2*N+1 ) holds the* trace, Z( 2*N+2 ) holds the sum of the eigenvalues, Z( 2*N+3 )* holds the iteration count, Z( 2*N+4 ) holds NDIVS/NIN^2, and* Z( 2*N+5 ) holds the percentage of shifts that failed.** INFO (output) INTEGER* = 0: successful exit* < 0: if the i-th argument is a scalar and had an illegal* value, then INFO = -i, if the i-th argument is an* array and the j-entry had an illegal value, then* INFO = -(i*100+j)* > 0: the algorithm failed* = 1, a split was marked by a positive value in E* = 2, current block of Z not diagonalized after 30*N* iterations (in inner while loop)* = 3, termination criterion of outer while loop not met* (program created more than N unreduced blocks)** Further Details* ===============* Local Variables: I0:N0 defines a current unreduced segment of Z.* The shifts are accumulated in SIGMA. Iteration count is in ITER.* Ping-pong is controlled by PP (alternates between 0 and 1).** =====================================================================** .. Parameters ..DOUBLE PRECISION CBIASPARAMETER ( CBIAS = 1.50D0 )DOUBLE PRECISION ZERO, HALF, ONE, TWO, FOUR, TEN, HNDRDPARAMETER ( ZERO = 0.0D0, HALF = 0.5D0, ONE = 1.0D0,$ TWO = 2.0D0, FOUR = 4.0D0, TEN = 10.0D0,$ HNDRD = 100.0D0 )* ..* .. Local Scalars ..INTEGER I0, I4, IINFO, IPN4, ITER, IWHILA, IWHILB, K,$ N0, NBIG, NDIV, NFAIL, PP, SPLTDOUBLE PRECISION D, DESIG, DMIN, DMIN1, DMIN2, DN, DN1, DN2, E,$ EMAX, EMIN, EPS, EPS2, OLDEMN, QMAX, QMIN, S,$ SIGMA, T, TAU, TEMP, TRACE, ZMAX* ..* .. External Subroutines ..EXTERNAL DLASQ3, DLASQ5, DLASRT, XERBLA* ..* .. External Functions ..DOUBLE PRECISION DLAMCHEXTERNAL DLAMCH* ..* .. Intrinsic Functions ..INTRINSIC ABS, DBLE, MAX, MIN, SQRT* ..* .. Executable Statements ..** Test the input arguments.* (in case DLASQ2 is not called by DLASQ1)*INFO = 0EPS = DLAMCH( 'Precision' )*TENEPS2 = EPS**2*IF( N.LT.0 ) THENINFO = -1CALL XERBLA( 'DLASQ2', 1 )RETURNELSE IF( N.EQ.0 ) THENRETURNELSE IF( N.EQ.1 ) THEN** 1-by-1 case.*IF( Z( 1 ).LT.ZERO ) THENINFO = -201CALL XERBLA( 'DLASQ2', 2 )END IFRETURNELSE IF( N.EQ.2 ) THEN** 2-by-2 case.*IF( Z( 2 ).LT.ZERO .OR. Z( 3 ).LT.ZERO ) THENINFO = -2CALL XERBLA( 'DLASQ2', 2 )RETURNELSE IF( Z( 3 ).GT.Z( 1 ) ) THEND = Z( 3 )Z( 3 ) = Z( 1 )Z( 1 ) = DEND IFZ( 5 ) = Z( 1 ) + Z( 2 ) + Z( 3 )IF( Z( 2 ).GT.Z( 3 )*EPS2 ) THENT = HALF*( ( Z( 1 )-Z( 3 ) )+Z( 2 ) )S = Z( 3 )*( Z( 2 ) / T )IF( S.LE.T ) THENS = Z( 3 )*( Z( 2 ) / ( T*( ONE+SQRT( ONE+S / T ) ) ) )ELSES = Z( 3 )*( Z( 2 ) / ( T+SQRT( T )*SQRT( T+S ) ) )END IFT = Z( 1 ) + ( S+Z( 2 ) )Z( 3 ) = Z( 3 )*( Z( 1 ) / T )Z( 1 ) = TEND IFZ( 2 ) = Z( 3 )Z( 6 ) = Z( 2 ) + Z( 1 )Z( 7 ) = ZEROZ( 8 ) = ZEROZ( 9 ) = ZERORETURNEND IF** Check for negative data and compute sums of q's and e's.*Z( 2*N ) = ZEROEMIN = Z( 2 )QMAX = ZEROD = ZEROE = ZERO*DO 10 K = 1, NIF( Z( K ).LT.ZERO ) THENINFO = -( 200+K )CALL XERBLA( 'DLASQ2', 2 )RETURNELSE IF( Z( N+K ).LT.ZERO ) THENINFO = -( 200+N+K )CALL XERBLA( 'DLASQ2', 2 )RETURNEND IFD = D + Z( K )E = E + Z( N+K )QMAX = MAX( QMAX, Z( K ) )10 CONTINUEZMAX = QMAXDO 20 K = 1, N - 1EMIN = MIN( EMIN, Z( N+K ) )ZMAX = MAX( ZMAX, Z( N+K ) )20 CONTINUE** Check for diagonality.*IF( E.EQ.ZERO ) THENCALL DLASRT( 'D', N, Z, IINFO )Z( 2*N-1 ) = DRETURNEND IF*TRACE = D + EI0 = 1N0 = N** Check for zero data.*IF( TRACE.EQ.ZERO ) THENZ( 2*N-1 ) = ZERORETURNEND IF** Rearrange data for locality: Z=(q1,qq1,e1,ee1,q2,qq2,e2,ee2,...).*DO 30 K = 2*N, 2, -2Z( 2*K ) = ZEROZ( 2*K-1 ) = Z( K )Z( 2*K-2 ) = ZEROZ( 2*K-3 ) = Z( K-1 )30 CONTINUE** Reverse the qd-array, if warranted.*IF( CBIAS*Z( 4*I0-3 ).LT.Z( 4*N0-3 ) ) THENIPN4 = 4*( I0+N0 )DO 40 I4 = 4*I0, 2*( I0+N0-1 ), 4TEMP = Z( I4-3 )Z( I4-3 ) = Z( IPN4-I4-3 )Z( IPN4-I4-3 ) = TEMPTEMP = Z( I4-1 )Z( I4-1 ) = Z( IPN4-I4-5 )Z( IPN4-I4-5 ) = TEMP40 CONTINUEEND IF** Initial split checking via dqd and Li's test.*PP = 0*DO 80 K = 1, 2*IF( EMIN.LE.EPS2*QMAX ) THEN** Li's reverse test.*D = Z( 4*N0+PP-3 )DO 50 I4 = 4*( N0-1 ) + PP, 4*I0 + PP, -4IF( Z( I4-1 ).LE.EPS2*D ) THENZ( I4-1 ) = -ZEROD = Z( I4-3 )ELSED = Z( I4-3 )*( D / ( D+Z( I4-1 ) ) )END IF50 CONTINUE** dqd maps Z to ZZ plus Li's test.*EMIN = Z( 4*I0+PP+1 )D = Z( 4*I0+PP-3 )DO 60 I4 = 4*I0 + PP, 4*( N0-1 ) + PP, 4IF( Z( I4-1 ).LE.EPS2*D ) THENZ( I4-1 ) = -ZEROZ( I4-2*PP-2 ) = DZ( I4-2*PP ) = ZEROD = Z( I4+1 )EMIN = ZEROELSEZ( I4-2*PP-2 ) = D + Z( I4-1 )Z( I4-2*PP ) = Z( I4+1 )*( Z( I4-1 ) /$ Z( I4-2*PP-2 ) )D = Z( I4+1 )*( D / Z( I4-2*PP-2 ) )EMIN = MIN( EMIN, Z( I4-2*PP ) )END IF60 CONTINUEZ( 4*N0-PP-2 ) = DELSETAU = ZEROCALL DLASQ5( I0, N0, Z, PP, TAU, DMIN, DMIN1, DMIN2, DN,$ DN1, DN2 )*EMIN = Z( 4*N0 )END IF** Now find qmax.*QMAX = Z( 4*I0-PP-2 )DO 70 I4 = 4*I0 - PP + 2, 4*N0 - PP - 2, 4QMAX = MAX( QMAX, Z( I4 ) )70 CONTINUE** Prepare for the next iteration on K.*PP = 1 - PP80 CONTINUE*ITER = 2NFAIL = 0NDIV = 2*( N0-I0 )*DO 140 IWHILA = 1, N + 1IF( N0.LT.1 )$ GO TO 150** While array unfinished do** E(N0) holds the value of SIGMA when submatrix in I0:N0* splits from the rest of the array, but is negated.*DESIG = ZEROIF( N0.EQ.N ) THENSIGMA = ZEROELSESIGMA = -Z( 4*N0-1 )END IFIF( SIGMA.LT.ZERO ) THENINFO = 1RETURNEND IF** Find last unreduced submatrix's top index I0, find QMAX and* EMIN. Find Gershgorin-type bound if Q's much greater than E's.*EMAX = ZEROIF( N0.GT.I0 ) THENEMIN = ABS( Z( 4*N0-5 ) )ELSEEMIN = ZEROEND IFQMIN = Z( 4*N0-3 )QMAX = QMINDO 90 I4 = 4*N0, 8, -4IF( Z( I4-5 ).LE.ZERO )$ GO TO 100IF( QMIN.GE.FOUR*EMAX ) THENQMIN = MIN( QMIN, Z( I4-3 ) )EMAX = MAX( EMAX, Z( I4-5 ) )END IFQMAX = MAX( QMAX, Z( I4-7 )+Z( I4-5 ) )EMIN = MIN( EMIN, Z( I4-5 ) )90 CONTINUEI4 = 4*100 CONTINUEI0 = I4 / 4** Store EMIN for passing to DLASQ3.*Z( 4*N0-1 ) = EMIN** Put -(initial shift) into DMIN.*DMIN = -MAX( ZERO, QMIN-TWO*SQRT( QMIN )*SQRT( EMAX ) )** Now I0:N0 is unreduced. PP = 0 for ping, PP = 1 for pong.*PP = 0*NBIG = 30*( N0-I0+1 )DO 120 IWHILB = 1, NBIGIF( I0.GT.N0 )$ GO TO 130** While submatrix unfinished take a good dqds step.*CALL DLASQ3( I0, N0, Z, PP, DMIN, SIGMA, DESIG, QMAX, NFAIL,$ ITER, NDIV )*PP = 1 - PP** When EMIN is very small check for splits.*IF( PP.EQ.0 .AND. N0-I0.GE.3 ) THENIF( Z( 4*N0 ).LE.EPS2*QMAX .OR. Z( 4*N0-1 ).LE.EPS2*$ SIGMA ) THENSPLT = I0 - 1QMAX = Z( 4*I0-3 )EMIN = Z( 4*I0-1 )OLDEMN = Z( 4*I0 )DO 110 I4 = 4*I0, 4*( N0-3 ), 4IF( Z( I4 ).LE.EPS2*Z( I4-3 ) .OR. Z( I4-1 ).LE.$ EPS2*SIGMA ) THENZ( I4-1 ) = -SIGMASPLT = I4 / 4QMAX = ZEROEMIN = Z( I4+3 )OLDEMN = Z( I4+4 )ELSEQMAX = MAX( QMAX, Z( I4+1 ) )EMIN = MIN( EMIN, Z( I4-1 ) )OLDEMN = MIN( OLDEMN, Z( I4 ) )END IF110 CONTINUEZ( 4*N0-1 ) = EMINZ( 4*N0 ) = OLDEMNI0 = SPLT + 1END IFEND IF*120 CONTINUE*INFO = 2RETURN** end IWHILB*130 CONTINUE*140 CONTINUE*INFO = 3RETURN** end IWHILA*150 CONTINUE** Move q's to the front.*DO 160 K = 2, NZ( K ) = Z( 4*K-3 )160 CONTINUE** Sort and compute sum of eigenvalues.*CALL DLASRT( 'D', N, Z, IINFO )*E = ZERODO 170 K = N, 1, -1E = E + Z( K )170 CONTINUE** Store trace, sum(eigenvalues) and information on performance.*Z( 2*N+1 ) = TRACEZ( 2*N+2 ) = EZ( 2*N+3 ) = DBLE( ITER )Z( 2*N+4 ) = DBLE( NDIV ) / DBLE( N**2 )Z( 2*N+5 ) = HNDRD*NFAIL / DBLE( ITER )RETURN** End of DLASQ2*ENDSUBROUTINE DLASQ3( I0, N0, Z, PP, DMIN, SIGMA, DESIG, QMAX, NFAIL,$ ITER, NDIV )** -- LAPACK auxiliary 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 I0, ITER, N0, NDIV, NFAIL, PPDOUBLE PRECISION DESIG, DMIN, QMAX, SIGMA* ..* .. Array Arguments ..DOUBLE PRECISION Z( * )* ..** Purpose* =======* DLASQ3 checks for deflation, computes a shift (TAU) and calls dqds.* In case of failure it changes shifts, and tries again until output* is positive.** Arguments* =========** I0 (input) INTEGER* First index.** N0 (input) INTEGER* Last index.** Z (input) DOUBLE PRECISION array, dimension ( 4*N )* Z holds the qd array.** PP (input) INTEGER* PP=0 for ping, PP=1 for pong.** DMIN (output) DOUBLE PRECISION* Minimum value of d.** SIGMA (output) DOUBLE PRECISION* Sum of shifts used in current segment.** DESIG (input/output) DOUBLE PRECISION* Lower order part of SIGMA** QMAX (input) DOUBLE PRECISION* Maximum value of q.** NFAIL (output) INTEGER* Number of times shift was too big.** ITER (output) INTEGER* Number of iterations.** NDIV (output) INTEGER* Number of divisions.** TTYPE (output) INTEGER* Shift type.** =====================================================================** .. Parameters ..DOUBLE PRECISION CBIASPARAMETER ( CBIAS = 1.50D0 )DOUBLE PRECISION ZERO, QURTR, HALF, ONE, TWO, TENPARAMETER ( ZERO = 0.0D0, QURTR = 0.250D0, HALF = 0.5D0,$ ONE = 1.0D0, TWO = 2.0D0, TEN = 10.0D0 )* ..* .. Local Scalars ..INTEGER IPN4, J4, N0IN, NN, TTYPEDOUBLE PRECISION DMIN1, DMIN2, DN, DN1, DN2, EPS, EPS2, S,$ SFMIN, T, TAU, TEMP* ..* .. External Subroutines ..EXTERNAL DLASQ4, DLASQ5, DLASQ6* ..* .. External Functions ..DOUBLE PRECISION DLAMCHEXTERNAL DLAMCH* ..* .. Intrinsic Functions ..INTRINSIC ABS, MAX, MIN, SQRT* ..* .. Save statement ..SAVE TTYPE, DMIN1, DMIN2, DN, DN1, DN2, TAU* ..* .. Data statements ..DATA TTYPE / 0 /DATA DMIN1 / ZERO / , DMIN2 / ZERO / , DN / ZERO / ,$ DN1 / ZERO / , DN2 / ZERO / , TAU / ZERO /* ..* .. Executable Statements ..*N0IN = N0EPS = DLAMCH( 'Precision' )*TENSFMIN = DLAMCH( 'Safe minimum' )EPS2 = EPS**2** Check for deflation.*10 CONTINUE*IF( N0.LT.I0 )$ RETURNIF( N0.EQ.I0 )$ GO TO 20NN = 4*N0 + PPIF( N0.EQ.( I0+1 ) )$ GO TO 40** Check whether E(N0-1) is negligible, 1-by-1 case.*IF( Z( NN-5 ).GT.EPS2*( SIGMA+Z( NN-3 ) ) .AND. Z( NN-2*PP-4 ).GT.$ EPS2*Z( NN-7 ) )GO TO 30*20 CONTINUE*Z( 4*N0-3 ) = Z( 4*N0+PP-3 ) + SIGMAN0 = N0 - 1GO TO 10** Check whether E(N0-2) is negligible, 2-by-2 case.*30 CONTINUE*IF( Z( NN-9 ).GT.EPS2*SIGMA .AND. Z( NN-2*PP-8 ).GT.EPS2*$ Z( NN-11 ) )GO TO 50*40 CONTINUE*IF( Z( NN-3 ).GT.Z( NN-7 ) ) THENS = Z( NN-3 )Z( NN-3 ) = Z( NN-7 )Z( NN-7 ) = SEND IFIF( Z( NN-5 ).GT.Z( NN-3 )*EPS2 ) THENT = HALF*( ( Z( NN-7 )-Z( NN-3 ) )+Z( NN-5 ) )S = Z( NN-3 )*( Z( NN-5 ) / T )IF( S.LE.T ) THENS = Z( NN-3 )*( Z( NN-5 ) / ( T*( ONE+SQRT( ONE+S /$ T ) ) ) )ELSES = Z( NN-3 )*( Z( NN-5 ) / ( T+SQRT( T )*SQRT( T+S ) ) )END IFT = Z( NN-7 ) + ( S+Z( NN-5 ) )Z( NN-3 ) = Z( NN-3 )*( Z( NN-7 ) / T )Z( NN-7 ) = TEND IFZ( 4*N0-7 ) = Z( NN-7 ) + SIGMAZ( 4*N0-3 ) = Z( NN-3 ) + SIGMAN0 = N0 - 2GO TO 10*50 CONTINUE** Reverse the qd-array, if warranted.*IF( DMIN.LE.ZERO .OR. N0.LT.N0IN ) THENIF( CBIAS*Z( 4*I0+PP-3 ).LT.Z( 4*N0+PP-3 ) ) THENIPN4 = 4*( I0+N0 )DO 60 J4 = 4*I0, 2*( I0+N0-1 ), 4TEMP = Z( J4-3 )Z( J4-3 ) = Z( IPN4-J4-3 )Z( IPN4-J4-3 ) = TEMPTEMP = Z( J4-2 )Z( J4-2 ) = Z( IPN4-J4-2 )Z( IPN4-J4-2 ) = TEMPTEMP = Z( J4-1 )Z( J4-1 ) = Z( IPN4-J4-5 )Z( IPN4-J4-5 ) = TEMPTEMP = Z( J4 )Z( J4 ) = Z( IPN4-J4-4 )Z( IPN4-J4-4 ) = TEMP60 CONTINUEIF( N0-I0.LE.4 ) THENZ( 4*N0+PP-1 ) = Z( 4*I0+PP-1 )Z( 4*N0-PP ) = Z( 4*I0-PP )END IFDMIN2 = MIN( DMIN2, Z( 4*N0+PP-1 ) )Z( 4*N0+PP-1 ) = MIN( Z( 4*N0+PP-1 ), Z( 4*I0+PP-1 ),$ Z( 4*I0+PP+3 ) )Z( 4*I0-PP ) = MIN( Z( 4*N0-PP ), Z( 4*I0-PP ),$ Z( 4*I0-PP+4 ) )QMAX = MAX( QMAX, Z( 4*I0+PP-3 ), Z( 4*I0+PP+1 ) )DMIN = -ZEROEND IFEND IF*70 CONTINUE*IF( DMIN.LT.ZERO .OR. SFMIN*QMAX.LE.$ MIN( Z( 4*N0+PP-1 ), Z( 4*N0+PP-9 ), DMIN2+Z( 4*N0-PP ) ) )$ THEN** Choose a shift.*CALL DLASQ4( I0, N0, Z, PP, N0IN, DMIN, DMIN1, DMIN2, DN, DN1,$ DN2, TAU, TTYPE )** Call dqds until DMIN > 0.*80 CONTINUE*CALL DLASQ5( I0, N0, Z, PP, TAU, DMIN, DMIN1, DMIN2, DN, DN1,$ DN2 )*ITER = ITER + 1NDIV = NDIV + ( N0-I0+2 )** Check for NaN: "DMIN.NE.DMIN"*IF( DMIN.NE.DMIN ) THENZ( 4*N0+PP-1 ) = ZEROTAU = ZEROGO TO 70END IF** Check for convergence hidden by negative DN.*IF( DMIN.LT.ZERO .AND. DMIN1.GT.ZERO .AND.$ Z( 4*( N0-1 )-PP ).LT.EPS*( SIGMA+DN1 ) .AND. ABS( DN ).LT.$ EPS*SIGMA ) THENZ( 4*( N0-1 )-PP+2 ) = ZERODMIN = ABS( DMIN )END IF*IF( DMIN.LT.ZERO ) THEN** Failure. Select new TAU and try again.*NFAIL = NFAIL + 1** Failed twice. Play it safe.*IF( TTYPE.LT.-22 ) THENTAU = ZEROGO TO 80END IF*IF( DMIN1.GT.ZERO ) THEN** Late failure. Gives excellent shift.*TAU = ( TAU+DMIN )*( ONE-TWO*EPS )TTYPE = TTYPE - 11ELSE** Early failure. Divide by 4.*TAU = QURTR*TAUTTYPE = TTYPE - 12END IFGO TO 80END IFELSECALL DLASQ6( I0, N0, Z, PP, DMIN, DMIN1, DMIN2, DN, DN1, DN2 )ITER = ITER + 1NDIV = NDIV + ( N0-I0 )TAU = ZEROEND IF*IF( TAU.LT.SIGMA ) THENDESIG = DESIG + TAUT = SIGMA + DESIGDESIG = DESIG - ( T-SIGMA )ELSET = SIGMA + TAUDESIG = SIGMA - ( T-TAU ) + DESIGEND IFSIGMA = T*RETURN** End of DLASQ3*ENDSUBROUTINE DLASQ4( I0, N0, Z, PP, N0IN, DMIN, DMIN1, DMIN2, DN,$ DN1, DN2, TAU, TTYPE )** -- LAPACK auxiliary 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 I0, N0, N0IN, PP, TTYPEDOUBLE PRECISION DMIN, DMIN1, DMIN2, DN, DN1, DN2, TAU* ..* .. Array Arguments ..DOUBLE PRECISION Z( * )* ..** Purpose* =======* DLASQ4 computes an approximation TAU to the smallest eigenvalue* using values of d from the previous transform.** I0 (input) INTEGER* First index.** N0 (input) INTEGER* Last index.** Z (input) DOUBLE PRECISION array, dimension ( 4*N )* Z holds the qd array.** PP (input) INTEGER* PP=0 for ping, PP=1 for pong.** NOIN (input) INTEGER* The value of N0 at start of EIGTEST.** DMIN (input) DOUBLE PRECISION* Minimum value of d.** DMIN1 (input) DOUBLE PRECISION* Minimum value of d, excluding D( N0 ).** DMIN2 (input) DOUBLE PRECISION* Minimum value of d, excluding D( N0 ) and D( N0-1 ).** DN (input) DOUBLE PRECISION* d(N)** DN1 (input) DOUBLE PRECISION* d(N-1)** DN2 (input) DOUBLE PRECISION* d(N-2)** TAU (output) DOUBLE PRECISION* This is the shift.** TTYPE (output) INTEGER* Shift type.** Further Details* ===============* CNST1 = 9/16** =====================================================================** .. Parameters ..DOUBLE PRECISION CNST1, CNST2, CNST3PARAMETER ( CNST1 = 0.5630D0, CNST2 = 1.010D0,$ CNST3 = 1.050D0 )DOUBLE PRECISION QURTR, THIRD, HALF, ZERO, ONE, TWO, HNDRDPARAMETER ( QURTR = 0.250D0, THIRD = 0.3330D0,$ HALF = 0.50D0, ZERO = 0.0D0, ONE = 1.0D0,$ TWO = 2.0D0, HNDRD = 100.0D0 )* ..* .. Local Scalars ..INTEGER I4, NN, NPDOUBLE PRECISION A2, B1, B2, G, GAM, GAP1, GAP2, S* ..* .. Intrinsic Functions ..INTRINSIC MAX, MIN, SQRT* ..* .. Save statement ..SAVE G* ..* .. Data statements ..DATA G / ZERO /* ..* .. Executable Statements ..** A negative DMIN forces the shift to take that absolute value* TTYPE records the type of shift.*IF( DMIN.LE.ZERO ) THENTAU = -DMINTTYPE = -1RETURNEND IF*NN = 4*N0 + PPIF( N0IN.EQ.N0 ) THEN** No eigenvalues deflated.*IF( DMIN.EQ.DN .OR. DMIN.EQ.DN1 ) THEN*B1 = SQRT( Z( NN-3 ) )*SQRT( Z( NN-5 ) )B2 = SQRT( Z( NN-7 ) )*SQRT( Z( NN-9 ) )A2 = Z( NN-7 ) + Z( NN-5 )** Cases 2 and 3.*IF( DMIN.EQ.DN .AND. DMIN1.EQ.DN1 ) THENGAP2 = DMIN2 - A2 - DMIN2*QURTRIF( GAP2.GT.ZERO .AND. GAP2.GT.B2 ) THENGAP1 = A2 - DN - ( B2 / GAP2 )*B2ELSEGAP1 = A2 - DN - ( B1+B2 )END IFIF( GAP1.GT.ZERO .AND. GAP1.GT.B1 ) THENS = MAX( DN-( B1 / GAP1 )*B1, HALF*DMIN )TTYPE = -2ELSES = ZEROIF( DN.GT.B1 )$ S = DN - B1IF( A2.GT.( B1+B2 ) )$ S = MIN( S, A2-( B1+B2 ) )S = MAX( S, THIRD*DMIN )TTYPE = -3END IFELSE** Case 4.*IF( DMIN.EQ.DN ) THENGAM = DNA2 = ZEROB2 = Z( NN-5 ) / Z( NN-7 )NP = NN - 9ELSENP = NN - 2*PPB2 = Z( NP-2 )GAM = DN1A2 = Z( NP-4 ) / Z( NP-2 )B2 = Z( NN-9 ) / Z( NN-11 )NP = NN - 13END IF** Approximate contribution to norm squared from I < NN-1.*IF( B2.EQ.ZERO )$ GO TO 20A2 = A2 + B2DO 10 I4 = NP, 4*I0 - 1 + PP, -4B1 = B2B2 = B2*( Z( I4 ) / Z( I4-2 ) )A2 = A2 + B2IF( HNDRD*MAX( B2, B1 ).LT.A2 .OR. CNST1.LT.A2 )$ GO TO 2010 CONTINUE20 CONTINUEA2 = CNST3*A2** Rayleigh quotient residual bound.*IF( A2.LT.CNST1 ) THENS = GAM*( ONE-SQRT( A2 ) ) / ( ONE+A2 )ELSES = QURTR*GAMEND IFTTYPE = -4END IFELSE IF( DMIN.EQ.DN2 ) THEN** Case 5.** Compute contribution to norm squared from I > NN-2.*NP = NN - 2*PPB1 = Z( NP-2 )B2 = Z( NP-6 )GAM = DN2A2 = ( Z( NP-8 ) / B2 )*( ONE+Z( NP-4 ) / B1 )** Approximate contribution to norm squared from I < NN-2.*IF( N0-I0.GT.2 ) THENB2 = Z( NN-13 ) / Z( NN-15 )IF( B2.EQ.ZERO )$ GO TO 40A2 = A2 + B2DO 30 I4 = NN - 17, 4*I0 - 1 + PP, -4B1 = B2B2 = B2*( Z( I4 ) / Z( I4-2 ) )A2 = A2 + B2IF( HNDRD*MAX( B2, B1 ).LT.A2 .OR. CNST1.LT.A2 )$ GO TO 4030 CONTINUE40 CONTINUEA2 = CNST3*A2END IF*IF( A2.LT.CNST1 ) THENS = GAM*( ONE-SQRT( A2 ) ) / ( ONE+A2 )ELSES = QURTR*GAM / ( ONE+A2 )END IFTTYPE = -5ELSE** Case 6, no information to guide us.*IF( TTYPE.EQ.-6 ) THENG = G + THIRD*( ONE-G )ELSE IF( TTYPE.EQ.-18 ) THENG = QURTR*THIRDELSEG = QURTREND IFS = G*DMINTTYPE = -6END IF*ELSE IF( N0IN.EQ.( N0+1 ) ) THEN** One eigenvalue just deflated. Use DMIN1, DN1 for DMIN and DN.*IF( DMIN1.EQ.DN1 .AND. DMIN2.EQ.DN2 ) THEN** Cases 7 and 8.*B1 = Z( NN-5 ) / Z( NN-7 )B2 = B1IF( B2.EQ.ZERO )$ GO TO 60DO 50 I4 = 4*N0 - 9 + PP, 4*I0 - 1 + PP, -4A2 = B1B1 = B1*( Z( I4 ) / Z( I4-2 ) )B2 = B2 + B1IF( HNDRD*MAX( B1, A2 ).LT.B2 )$ GO TO 6050 CONTINUE60 CONTINUEB2 = SQRT( CNST3*B2 )A2 = DMIN1 / ( ONE+B2**2 )GAP2 = HALF*DMIN2 - A2IF( GAP2.GT.ZERO .AND. GAP2.GT.B2*A2 ) THENS = MAX( A2*( ONE-CNST2*A2*( B2 / GAP2 )*B2 ),$ THIRD*DMIN1 )TTYPE = -7ELSES = MAX( A2*( ONE-CNST2*B2 ), THIRD*DMIN1 )TTYPE = -8END IFELSE** Case 9.*S = QURTR*DMIN1IF( DMIN1.EQ.DN1 )$ S = HALF*DMIN1TTYPE = -9END IF*ELSE IF( N0IN.EQ.( N0+2 ) ) THEN** Two eigenvalues deflated. Use DMIN2, DN2 for DMIN and DN.** Cases 10 and 11.*IF( DMIN2.EQ.DN2 .AND. TWO*Z( NN-5 ).LT.Z( NN-7 ) ) THENB1 = Z( NN-5 ) / Z( NN-7 )B2 = B1IF( B2.EQ.ZERO )$ GO TO 80DO 70 I4 = 4*N0 - 9 + PP, 4*I0 - 1 + PP, -4B1 = B1*( Z( I4 ) / Z( I4-2 ) )B2 = B2 + B1IF( HNDRD*B1.LT.B2 )$ GO TO 8070 CONTINUE80 CONTINUEB2 = SQRT( CNST3*B2 )A2 = DMIN2 / ( ONE+B2**2 )GAP2 = Z( NN-7 ) + Z( NN-9 ) -$ SQRT( Z( NN-11 ) )*SQRT( Z( NN-9 ) ) - A2IF( GAP2.GT.ZERO .AND. GAP2.GT.B2*A2 ) THENS = MAX( A2*( ONE-CNST2*A2*( B2 / GAP2 )*B2 ),$ THIRD*DMIN2 )ELSES = MAX( A2*( ONE-CNST2*B2 ), THIRD*DMIN2 )END IFTTYPE = -10ELSES = QURTR*DMIN2TTYPE = -11END IFELSE IF( N0IN.GT.( N0+2 ) ) THEN** Case 12, more than two eigenvalues deflated. No information.*S = ZEROTTYPE = -12END IF*TAU = SRETURN** End of DLASQ4*ENDSUBROUTINE DLASQ5( I0, N0, Z, PP, TAU, DMIN, DMIN1, DMIN2, DN,$ DNM1, DNM2 )** -- LAPACK auxiliary 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 I0, N0, PPDOUBLE PRECISION DMIN, DMIN1, DMIN2, DN, DNM1, DNM2, TAU* ..* .. Array Arguments ..DOUBLE PRECISION Z( * )* ..** Purpose* =======* DLASQ5 computes one dqds transform in ping-pong form.** Arguments* =========** I0 (input) INTEGER* First index.** N0 (input) INTEGER* Last index.** Z (input) DOUBLE PRECISION array, dimension ( 4*N )* Z holds the qd array. EMIN is stored in Z(4*N0) to avoid* an extra argument.** PP (input) INTEGER* PP=0 for ping, PP=1 for pong.** TAU (input) DOUBLE PRECISION* This is the shift.** DMIN (output) DOUBLE PRECISION* Minimum value of d.** DMIN1 (output) DOUBLE PRECISION* Minimum value of d, excluding D( N0 ).** DMIN2 (output) DOUBLE PRECISION* Minimum value of d, excluding D( N0 ) and D( N0-1 ).** DN (output) DOUBLE PRECISION* d(N0), the last value of d.** DNM1 (output) DOUBLE PRECISION* d(N0-1).** DNM2 (output) DOUBLE PRECISION* d(N0-2).** =====================================================================** .. Local Scalars ..INTEGER J4, J4P2DOUBLE PRECISION D, EMIN, TEMP* ..* .. Intrinsic Functions ..INTRINSIC MIN* ..* .. Executable Statements ..*IF( ( N0-I0-1 ).LE.0 )$ RETURN*J4 = 4*I0 + PP - 3EMIN = Z( J4+4 )D = Z( J4 ) - TAUDMIN = D*IF( PP.EQ.0 ) THENDO 10 J4 = 4*I0, 4*( N0-3 ), 4Z( J4-2 ) = D + Z( J4-1 )TEMP = Z( J4+1 ) / Z( J4-2 )D = D*TEMP - TAUDMIN = MIN( DMIN, D )Z( J4 ) = Z( J4-1 )*TEMPEMIN = MIN( Z( J4 ), EMIN )10 CONTINUEELSEDO 20 J4 = 4*I0, 4*( N0-3 ), 4Z( J4-3 ) = D + Z( J4 )TEMP = Z( J4+2 ) / Z( J4-3 )D = D*TEMP - TAUDMIN = MIN( DMIN, D )Z( J4-1 ) = Z( J4 )*TEMPEMIN = MIN( Z( J4-1 ), EMIN )20 CONTINUEEND IF** Unroll last two steps.*DNM2 = DDMIN2 = DMINJ4 = 4*( N0-2 ) - PPJ4P2 = J4 + 2*PP - 1Z( J4-2 ) = DNM2 + Z( J4P2 )Z( J4 ) = Z( J4P2+2 )*( Z( J4P2 ) / Z( J4-2 ) )DNM1 = Z( J4P2+2 )*( DNM2 / Z( J4-2 ) ) - TAUDMIN = MIN( DMIN, DNM1 )*DMIN1 = DMINJ4 = J4 + 4J4P2 = J4 + 2*PP - 1Z( J4-2 ) = DNM1 + Z( J4P2 )Z( J4 ) = Z( J4P2+2 )*( Z( J4P2 ) / Z( J4-2 ) )DN = Z( J4P2+2 )*( DNM1 / Z( J4-2 ) ) - TAUDMIN = MIN( DMIN, DN )*Z( J4+2 ) = DNZ( 4*N0-PP ) = EMINRETURN** End of DLASQ5*ENDSUBROUTINE DLASQ6( I0, N0, Z, PP, DMIN, DMIN1, DMIN2, DN, DNM1,$ DNM2 )** -- LAPACK auxiliary 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 I0, N0, PPDOUBLE PRECISION DMIN, DMIN1, DMIN2, DN, DNM1, DNM2* ..* .. Array Arguments ..DOUBLE PRECISION Z( * )* ..** Purpose* =======* DLASQ6 computes one dqds transform in ping-pong form.** Arguments* =========** I0 (input) INTEGER* First index.** N0 (input) INTEGER* Last index.** Z (input) DOUBLE PRECISION array, dimension ( 4*N )* Z holds the qd array. EMIN is stored in Z(4*N0) to avoid* an extra argument.** PP (input) INTEGER* PP=0 for ping, PP=1 for pong.** DMIN (output) DOUBLE PRECISION* Minimum value of d.** DMIN1 (output) DOUBLE PRECISION* Minimum value of d, excluding D( N0 ).** DMIN2 (output) DOUBLE PRECISION* Minimum value of d, excluding D( N0 ) and D( N0-1 ).** DN (output) DOUBLE PRECISION* d(N0), the last value of d.** DNM1 (output) DOUBLE PRECISION* d(N0-1).** DNM2 (output) DOUBLE PRECISION* d(N0-2).** =====================================================================** .. Parameters ..DOUBLE PRECISION ZEROPARAMETER ( ZERO = 0.0D0 )* ..* .. Local Scalars ..INTEGER J4, J4P2DOUBLE PRECISION D, EMIN, SFMIN, TEMP* ..* .. External Functions ..DOUBLE PRECISION DLAMCHEXTERNAL DLAMCH* ..* .. Intrinsic Functions ..INTRINSIC MIN* ..* .. Executable Statements ..*IF( ( N0-I0-1 ).LE.0 )$ RETURN*SFMIN = DLAMCH( 'Safe minimum' )J4 = 4*I0 + PP - 3EMIN = Z( J4+4 )D = Z( J4 )DMIN = D*DO 10 J4 = 4*I0 - PP, 4*( N0-3 ) - PP, 4J4P2 = J4 + 2*PP - 1Z( J4-2 ) = D + Z( J4P2 )IF( Z( J4-2 ).EQ.ZERO ) THENZ( J4 ) = ZEROD = Z( J4P2+2 )DMIN = DEMIN = ZEROELSE IF( SFMIN*Z( J4P2+2 ).LT.Z( J4-2 ) ) THENTEMP = Z( J4P2+2 ) / Z( J4-2 )Z( J4 ) = Z( J4P2 )*TEMPD = D*TEMPELSEZ( J4 ) = Z( J4P2+2 )*( Z( J4P2 ) / Z( J4-2 ) )D = Z( J4P2+2 )*( D / Z( J4-2 ) )END IFDMIN = MIN( DMIN, D )EMIN = MIN( EMIN, Z( J4 ) )10 CONTINUE** Unroll last two steps.*DNM2 = DDMIN2 = DMINJ4 = 4*( N0-2 ) - PPJ4P2 = J4 + 2*PP - 1Z( J4-2 ) = DNM2 + Z( J4P2 )IF( Z( J4-2 ).EQ.ZERO ) THENZ( J4 ) = ZERODNM1 = Z( J4P2+2 )DMIN = DNM1EMIN = ZEROELSE IF( SFMIN*Z( J4P2+2 ).LT.Z( J4-2 ) ) THENTEMP = Z( J4P2+2 ) / Z( J4-2 )Z( J4 ) = Z( J4P2 )*TEMPDNM1 = DNM2*TEMPELSEZ( J4 ) = Z( J4P2+2 )*( Z( J4P2 ) / Z( J4-2 ) )DNM1 = Z( J4P2+2 )*( DNM2 / Z( J4-2 ) )END IFDMIN = MIN( DMIN, DNM1 )*DMIN1 = DMINJ4 = J4 + 4J4P2 = J4 + 2*PP - 1Z( J4-2 ) = DNM1 + Z( J4P2 )IF( Z( J4-2 ).EQ.ZERO ) THENZ( J4 ) = ZERODN = Z( J4P2+2 )DMIN = DNEMIN = ZEROELSE IF( SFMIN*Z( J4P2+2 ).LT.Z( J4-2 ) ) THENTEMP = Z( J4P2+2 ) / Z( J4-2 )Z( J4 ) = Z( J4P2 )*TEMPDN = DNM1*TEMPELSEZ( J4 ) = Z( J4P2+2 )*( Z( J4P2 ) / Z( J4-2 ) )DN = Z( J4P2+2 )*( DNM1 / Z( J4-2 ) )END IFDMIN = MIN( DMIN, DN )*Z( J4+2 ) = DNZ( 4*N0-PP ) = EMINRETURN** End of DLASQ6*ENDSUBROUTINE DLASR( SIDE, PIVOT, DIRECT, M, N, C, S, A, LDA )** -- LAPACK auxiliary routine (version 3.0) --* Univ. of Tennessee, Univ. of California Berkeley, NAG Ltd.,* Courant Institute, Argonne National Lab, and Rice University* October 31, 1992** .. Scalar Arguments ..CHARACTER DIRECT, PIVOT, SIDEINTEGER LDA, M, N* ..* .. Array Arguments ..DOUBLE PRECISION A( LDA, * ), C( * ), S( * )* ..** Purpose* =======** DLASR performs the transformation** A := P*A, when SIDE = 'L' or 'l' ( Left-hand side )** A := A*P', when SIDE = 'R' or 'r' ( Right-hand side )** where A is an m by n real matrix and P is an orthogonal matrix,* consisting of a sequence of plane rotations determined by the* parameters PIVOT and DIRECT as follows ( z = m when SIDE = 'L' or 'l'* and z = n when SIDE = 'R' or 'r' ):** When DIRECT = 'F' or 'f' ( Forward sequence ) then** P = P( z - 1 )*...*P( 2 )*P( 1 ),** and when DIRECT = 'B' or 'b' ( Backward sequence ) then** P = P( 1 )*P( 2 )*...*P( z - 1 ),** where P( k ) is a plane rotation matrix for the following planes:** when PIVOT = 'V' or 'v' ( Variable pivot ),* the plane ( k, k + 1 )** when PIVOT = 'T' or 't' ( Top pivot ),* the plane ( 1, k + 1 )** when PIVOT = 'B' or 'b' ( Bottom pivot ),* the plane ( k, z )** c( k ) and s( k ) must contain the cosine and sine that define the* matrix P( k ). The two by two plane rotation part of the matrix* P( k ), R( k ), is assumed to be of the form** R( k ) = ( c( k ) s( k ) ).* ( -s( k ) c( k ) )** This version vectorises across rows of the array A when SIDE = 'L'.** Arguments* =========** SIDE (input) CHARACTER*1* Specifies whether the plane rotation matrix P is applied to* A on the left or the right.* = 'L': Left, compute A := P*A* = 'R': Right, compute A:= A*P'** DIRECT (input) CHARACTER*1* Specifies whether P is a forward or backward sequence of* plane rotations.* = 'F': Forward, P = P( z - 1 )*...*P( 2 )*P( 1 )* = 'B': Backward, P = P( 1 )*P( 2 )*...*P( z - 1 )** PIVOT (input) CHARACTER*1* Specifies the plane for which P(k) is a plane rotation* matrix.* = 'V': Variable pivot, the plane (k,k+1)* = 'T': Top pivot, the plane (1,k+1)* = 'B': Bottom pivot, the plane (k,z)** M (input) INTEGER* The number of rows of the matrix A. If m <= 1, an immediate* return is effected.** N (input) INTEGER* The number of columns of the matrix A. If n <= 1, an* immediate return is effected.** C, S (input) DOUBLE PRECISION arrays, dimension* (M-1) if SIDE = 'L'* (N-1) if SIDE = 'R'* c(k) and s(k) contain the cosine and sine that define the* matrix P(k). The two by two plane rotation part of the* matrix P(k), R(k), is assumed to be of the form* R( k ) = ( c( k ) s( k ) ).* ( -s( k ) c( k ) )** A (input/output) DOUBLE PRECISION array, dimension (LDA,N)* The m by n matrix A. On exit, A is overwritten by P*A if* SIDE = 'R' or by A*P' if SIDE = 'L'.** LDA (input) INTEGER* The leading dimension of the array A. LDA >= max(1,M).** =====================================================================** .. Parameters ..DOUBLE PRECISION ONE, ZEROPARAMETER ( ONE = 1.0D+0, ZERO = 0.0D+0 )* ..* .. Local Scalars ..INTEGER I, INFO, JDOUBLE PRECISION CTEMP, STEMP, TEMP* ..* .. External Functions ..LOGICAL LSAMEEXTERNAL LSAME* ..* .. External Subroutines ..EXTERNAL XERBLA* ..* .. Intrinsic Functions ..INTRINSIC MAX* ..* .. Executable Statements ..** Test the input parameters*INFO = 0IF( .NOT.( LSAME( SIDE, 'L' ) .OR. LSAME( SIDE, 'R' ) ) ) THENINFO = 1ELSE IF( .NOT.( LSAME( PIVOT, 'V' ) .OR. LSAME( PIVOT,$ 'T' ) .OR. LSAME( PIVOT, 'B' ) ) ) THENINFO = 2ELSE IF( .NOT.( LSAME( DIRECT, 'F' ) .OR. LSAME( DIRECT, 'B' ) ) )$ THENINFO = 3ELSE IF( M.LT.0 ) THENINFO = 4ELSE IF( N.LT.0 ) THENINFO = 5ELSE IF( LDA.LT.MAX( 1, M ) ) THENINFO = 9END IFIF( INFO.NE.0 ) THENCALL XERBLA( 'DLASR ', INFO )RETURNEND IF** Quick return if possible*IF( ( M.EQ.0 ) .OR. ( N.EQ.0 ) )$ RETURNIF( LSAME( SIDE, 'L' ) ) THEN** Form P * A*IF( LSAME( PIVOT, 'V' ) ) THENIF( LSAME( DIRECT, 'F' ) ) THENDO 20 J = 1, M - 1CTEMP = C( J )STEMP = S( J )IF( ( CTEMP.NE.ONE ) .OR. ( STEMP.NE.ZERO ) ) THENDO 10 I = 1, NTEMP = A( J+1, I )A( J+1, I ) = CTEMP*TEMP - STEMP*A( J, I )A( J, I ) = STEMP*TEMP + CTEMP*A( J, I )10 CONTINUEEND IF20 CONTINUEELSE IF( LSAME( DIRECT, 'B' ) ) THENDO 40 J = M - 1, 1, -1CTEMP = C( J )STEMP = S( J )IF( ( CTEMP.NE.ONE ) .OR. ( STEMP.NE.ZERO ) ) THENDO 30 I = 1, NTEMP = A( J+1, I )A( J+1, I ) = CTEMP*TEMP - STEMP*A( J, I )A( J, I ) = STEMP*TEMP + CTEMP*A( J, I )30 CONTINUEEND IF40 CONTINUEEND IFELSE IF( LSAME( PIVOT, 'T' ) ) THENIF( LSAME( DIRECT, 'F' ) ) THENDO 60 J = 2, MCTEMP = C( J-1 )STEMP = S( J-1 )IF( ( CTEMP.NE.ONE ) .OR. ( STEMP.NE.ZERO ) ) THENDO 50 I = 1, NTEMP = A( J, I )A( J, I ) = CTEMP*TEMP - STEMP*A( 1, I )A( 1, I ) = STEMP*TEMP + CTEMP*A( 1, I )50 CONTINUEEND IF60 CONTINUEELSE IF( LSAME( DIRECT, 'B' ) ) THENDO 80 J = M, 2, -1CTEMP = C( J-1 )STEMP = S( J-1 )IF( ( CTEMP.NE.ONE ) .OR. ( STEMP.NE.ZERO ) ) THENDO 70 I = 1, NTEMP = A( J, I )A( J, I ) = CTEMP*TEMP - STEMP*A( 1, I )A( 1, I ) = STEMP*TEMP + CTEMP*A( 1, I )70 CONTINUEEND IF80 CONTINUEEND IFELSE IF( LSAME( PIVOT, 'B' ) ) THENIF( LSAME( DIRECT, 'F' ) ) THENDO 100 J = 1, M - 1CTEMP = C( J )STEMP = S( J )IF( ( CTEMP.NE.ONE ) .OR. ( STEMP.NE.ZERO ) ) THENDO 90 I = 1, NTEMP = A( J, I )A( J, I ) = STEMP*A( M, I ) + CTEMP*TEMPA( M, I ) = CTEMP*A( M, I ) - STEMP*TEMP90 CONTINUEEND IF100 CONTINUEELSE IF( LSAME( DIRECT, 'B' ) ) THENDO 120 J = M - 1, 1, -1CTEMP = C( J )STEMP = S( J )IF( ( CTEMP.NE.ONE ) .OR. ( STEMP.NE.ZERO ) ) THENDO 110 I = 1, NTEMP = A( J, I )A( J, I ) = STEMP*A( M, I ) + CTEMP*TEMPA( M, I ) = CTEMP*A( M, I ) - STEMP*TEMP110 CONTINUEEND IF120 CONTINUEEND IFEND IFELSE IF( LSAME( SIDE, 'R' ) ) THEN** Form A * P'*IF( LSAME( PIVOT, 'V' ) ) THENIF( LSAME( DIRECT, 'F' ) ) THENDO 140 J = 1, N - 1CTEMP = C( J )STEMP = S( J )IF( ( CTEMP.NE.ONE ) .OR. ( STEMP.NE.ZERO ) ) THENDO 130 I = 1, MTEMP = A( I, J+1 )A( I, J+1 ) = CTEMP*TEMP - STEMP*A( I, J )A( I, J ) = STEMP*TEMP + CTEMP*A( I, J )130 CONTINUEEND IF140 CONTINUEELSE IF( LSAME( DIRECT, 'B' ) ) THENDO 160 J = N - 1, 1, -1CTEMP = C( J )STEMP = S( J )IF( ( CTEMP.NE.ONE ) .OR. ( STEMP.NE.ZERO ) ) THENDO 150 I = 1, MTEMP = A( I, J+1 )A( I, J+1 ) = CTEMP*TEMP - STEMP*A( I, J )A( I, J ) = STEMP*TEMP + CTEMP*A( I, J )150 CONTINUEEND IF160 CONTINUEEND IFELSE IF( LSAME( PIVOT, 'T' ) ) THENIF( LSAME( DIRECT, 'F' ) ) THENDO 180 J = 2, NCTEMP = C( J-1 )STEMP = S( J-1 )IF( ( CTEMP.NE.ONE ) .OR. ( STEMP.NE.ZERO ) ) THENDO 170 I = 1, MTEMP = A( I, J )A( I, J ) = CTEMP*TEMP - STEMP*A( I, 1 )A( I, 1 ) = STEMP*TEMP + CTEMP*A( I, 1 )170 CONTINUEEND IF180 CONTINUEELSE IF( LSAME( DIRECT, 'B' ) ) THENDO 200 J = N, 2, -1CTEMP = C( J-1 )STEMP = S( J-1 )IF( ( CTEMP.NE.ONE ) .OR. ( STEMP.NE.ZERO ) ) THENDO 190 I = 1, MTEMP = A( I, J )A( I, J ) = CTEMP*TEMP - STEMP*A( I, 1 )A( I, 1 ) = STEMP*TEMP + CTEMP*A( I, 1 )190 CONTINUEEND IF200 CONTINUEEND IFELSE IF( LSAME( PIVOT, 'B' ) ) THENIF( LSAME( DIRECT, 'F' ) ) THENDO 220 J = 1, N - 1CTEMP = C( J )STEMP = S( J )IF( ( CTEMP.NE.ONE ) .OR. ( STEMP.NE.ZERO ) ) THENDO 210 I = 1, MTEMP = A( I, J )A( I, J ) = STEMP*A( I, N ) + CTEMP*TEMPA( I, N ) = CTEMP*A( I, N ) - STEMP*TEMP210 CONTINUEEND IF220 CONTINUEELSE IF( LSAME( DIRECT, 'B' ) ) THENDO 240 J = N - 1, 1, -1CTEMP = C( J )STEMP = S( J )IF( ( CTEMP.NE.ONE ) .OR. ( STEMP.NE.ZERO ) ) THENDO 230 I = 1, MTEMP = A( I, J )A( I, J ) = STEMP*A( I, N ) + CTEMP*TEMPA( I, N ) = CTEMP*A( I, N ) - STEMP*TEMP230 CONTINUEEND IF240 CONTINUEEND IFEND IFEND IF*RETURN** End of DLASR*ENDSUBROUTINE DLASRT( ID, N, D, INFO )** -- LAPACK routine (version 3.0) --* Univ. of Tennessee, Univ. of California Berkeley, NAG Ltd.,* Courant Institute, Argonne National Lab, and Rice University* September 30, 1994** .. Scalar Arguments ..CHARACTER IDINTEGER INFO, N* ..* .. Array Arguments ..DOUBLE PRECISION D( * )* ..** Purpose* =======** Sort the numbers in D in increasing order (if ID = 'I') or* in decreasing order (if ID = 'D' ).** Use Quick Sort, reverting to Insertion sort on arrays of* size <= 20. Dimension of STACK limits N to about 2**32.** Arguments* =========** ID (input) CHARACTER*1* = 'I': sort D in increasing order;* = 'D': sort D in decreasing order.** N (input) INTEGER* The length of the array D.** D (input/output) DOUBLE PRECISION array, dimension (N)* On entry, the array to be sorted.* On exit, D has been sorted into increasing order* (D(1) <= ... <= D(N) ) or into decreasing order* (D(1) >= ... >= D(N) ), depending on ID.** INFO (output) INTEGER* = 0: successful exit* < 0: if INFO = -i, the i-th argument had an illegal value** =====================================================================** .. Parameters ..INTEGER SELECTPARAMETER ( SELECT = 20 )* ..* .. Local Scalars ..INTEGER DIR, ENDD, I, J, START, STKPNTDOUBLE PRECISION D1, D2, D3, DMNMX, TMP* ..* .. Local Arrays ..INTEGER STACK( 2, 32 )* ..* .. External Functions ..LOGICAL LSAMEEXTERNAL LSAME* ..* .. External Subroutines ..EXTERNAL XERBLA* ..* .. Executable Statements ..** Test the input paramters.*INFO = 0DIR = -1IF( LSAME( ID, 'D' ) ) THENDIR = 0ELSE IF( LSAME( ID, 'I' ) ) THENDIR = 1END IFIF( DIR.EQ.-1 ) THENINFO = -1ELSE IF( N.LT.0 ) THENINFO = -2END IFIF( INFO.NE.0 ) THENCALL XERBLA( 'DLASRT', -INFO )RETURNEND IF** Quick return if possible*IF( N.LE.1 )$ RETURN*STKPNT = 1STACK( 1, 1 ) = 1STACK( 2, 1 ) = N10 CONTINUESTART = STACK( 1, STKPNT )ENDD = STACK( 2, STKPNT )STKPNT = STKPNT - 1IF( ENDD-START.LE.SELECT .AND. ENDD-START.GT.0 ) THEN** Do Insertion sort on D( START:ENDD )*IF( DIR.EQ.0 ) THEN** Sort into decreasing order*DO 30 I = START + 1, ENDDDO 20 J = I, START + 1, -1IF( D( J ).GT.D( J-1 ) ) THENDMNMX = D( J )D( J ) = D( J-1 )D( J-1 ) = DMNMXELSEGO TO 30END IF20 CONTINUE30 CONTINUE*ELSE** Sort into increasing order*DO 50 I = START + 1, ENDDDO 40 J = I, START + 1, -1IF( D( J ).LT.D( J-1 ) ) THENDMNMX = D( J )D( J ) = D( J-1 )D( J-1 ) = DMNMXELSEGO TO 50END IF40 CONTINUE50 CONTINUE*END IF*ELSE IF( ENDD-START.GT.SELECT ) THEN** Partition D( START:ENDD ) and stack parts, largest one first** Choose partition entry as median of 3*D1 = D( START )D2 = D( ENDD )I = ( START+ENDD ) / 2D3 = D( I )IF( D1.LT.D2 ) THENIF( D3.LT.D1 ) THENDMNMX = D1ELSE IF( D3.LT.D2 ) THENDMNMX = D3ELSEDMNMX = D2END IFELSEIF( D3.LT.D2 ) THENDMNMX = D2ELSE IF( D3.LT.D1 ) THENDMNMX = D3ELSEDMNMX = D1END IFEND IF*IF( DIR.EQ.0 ) THEN** Sort into decreasing order*I = START - 1J = ENDD + 160 CONTINUE70 CONTINUEJ = J - 1IF( D( J ).LT.DMNMX )$ GO TO 7080 CONTINUEI = I + 1IF( D( I ).GT.DMNMX )$ GO TO 80IF( I.LT.J ) THENTMP = D( I )D( I ) = D( J )D( J ) = TMPGO TO 60END IFIF( J-START.GT.ENDD-J-1 ) THENSTKPNT = STKPNT + 1STACK( 1, STKPNT ) = STARTSTACK( 2, STKPNT ) = JSTKPNT = STKPNT + 1STACK( 1, STKPNT ) = J + 1STACK( 2, STKPNT ) = ENDDELSESTKPNT = STKPNT + 1STACK( 1, STKPNT ) = J + 1STACK( 2, STKPNT ) = ENDDSTKPNT = STKPNT + 1STACK( 1, STKPNT ) = STARTSTACK( 2, STKPNT ) = JEND IFELSE** Sort into increasing order*I = START - 1J = ENDD + 190 CONTINUE100 CONTINUEJ = J - 1IF( D( J ).GT.DMNMX )$ GO TO 100110 CONTINUEI = I + 1IF( D( I ).LT.DMNMX )$ GO TO 110IF( I.LT.J ) THENTMP = D( I )D( I ) = D( J )D( J ) = TMPGO TO 90END IFIF( J-START.GT.ENDD-J-1 ) THENSTKPNT = STKPNT + 1STACK( 1, STKPNT ) = STARTSTACK( 2, STKPNT ) = JSTKPNT = STKPNT + 1STACK( 1, STKPNT ) = J + 1STACK( 2, STKPNT ) = ENDDELSESTKPNT = STKPNT + 1STACK( 1, STKPNT ) = J + 1STACK( 2, STKPNT ) = ENDDSTKPNT = STKPNT + 1STACK( 1, STKPNT ) = STARTSTACK( 2, STKPNT ) = JEND IFEND IFEND IFIF( STKPNT.GT.0 )$ GO TO 10RETURN** End of DLASRT*ENDSUBROUTINE DLASSQ( N, X, INCX, SCALE, SUMSQ )** -- LAPACK auxiliary 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 INCX, NDOUBLE PRECISION SCALE, SUMSQ* ..* .. Array Arguments ..DOUBLE PRECISION X( * )* ..** Purpose* =======** DLASSQ returns the values scl and smsq such that** ( scl**2 )*smsq = x( 1 )**2 +...+ x( n )**2 + ( scale**2 )*sumsq,** where x( i ) = X( 1 + ( i - 1 )*INCX ). The value of sumsq is* assumed to be non-negative and scl returns the value** scl = max( scale, abs( x( i ) ) ).** scale and sumsq must be supplied in SCALE and SUMSQ and* scl and smsq are overwritten on SCALE and SUMSQ respectively.** The routine makes only one pass through the vector x.** Arguments* =========** N (input) INTEGER* The number of elements to be used from the vector X.** X (input) DOUBLE PRECISION array, dimension (N)* The vector for which a scaled sum of squares is computed.* x( i ) = X( 1 + ( i - 1 )*INCX ), 1 <= i <= n.** INCX (input) INTEGER* The increment between successive values of the vector X.* INCX > 0.** SCALE (input/output) DOUBLE PRECISION* On entry, the value scale in the equation above.* On exit, SCALE is overwritten with scl , the scaling factor* for the sum of squares.** SUMSQ (input/output) DOUBLE PRECISION* On entry, the value sumsq in the equation above.* On exit, SUMSQ is overwritten with smsq , the basic sum of* squares from which scl has been factored out.** =====================================================================** .. Parameters ..DOUBLE PRECISION ZEROPARAMETER ( ZERO = 0.0D+0 )* ..* .. Local Scalars ..INTEGER IXDOUBLE PRECISION ABSXI* ..* .. Intrinsic Functions ..INTRINSIC ABS* ..* .. Executable Statements ..*IF( N.GT.0 ) THENDO 10 IX = 1, 1 + ( N-1 )*INCX, INCXIF( X( IX ).NE.ZERO ) THENABSXI = ABS( X( IX ) )IF( SCALE.LT.ABSXI ) THENSUMSQ = 1 + SUMSQ*( SCALE / ABSXI )**2SCALE = ABSXIELSESUMSQ = SUMSQ + ( ABSXI / SCALE )**2END IFEND IF10 CONTINUEEND IFRETURN** End of DLASSQ*ENDSUBROUTINE DLASV2( F, G, H, SSMIN, SSMAX, SNR, CSR, SNL, CSL )** -- LAPACK auxiliary routine (version 3.0) --* Univ. of Tennessee, Univ. of California Berkeley, NAG Ltd.,* Courant Institute, Argonne National Lab, and Rice University* October 31, 1992** .. Scalar Arguments ..DOUBLE PRECISION CSL, CSR, F, G, H, SNL, SNR, SSMAX, SSMIN* ..** Purpose* =======** DLASV2 computes the singular value decomposition of a 2-by-2* triangular matrix* [ F G ]* [ 0 H ].* On return, abs(SSMAX) is the larger singular value, abs(SSMIN) is the* smaller singular value, and (CSL,SNL) and (CSR,SNR) are the left and* right singular vectors for abs(SSMAX), giving the decomposition** [ CSL SNL ] [ F G ] [ CSR -SNR ] = [ SSMAX 0 ]* [-SNL CSL ] [ 0 H ] [ SNR CSR ] [ 0 SSMIN ].** Arguments* =========** F (input) DOUBLE PRECISION* The (1,1) element of the 2-by-2 matrix.** G (input) DOUBLE PRECISION* The (1,2) element of the 2-by-2 matrix.** H (input) DOUBLE PRECISION* The (2,2) element of the 2-by-2 matrix.** SSMIN (output) DOUBLE PRECISION* abs(SSMIN) is the smaller singular value.** SSMAX (output) DOUBLE PRECISION* abs(SSMAX) is the larger singular value.** SNL (output) DOUBLE PRECISION* CSL (output) DOUBLE PRECISION* The vector (CSL, SNL) is a unit left singular vector for the* singular value abs(SSMAX).** SNR (output) DOUBLE PRECISION* CSR (output) DOUBLE PRECISION* The vector (CSR, SNR) is a unit right singular vector for the* singular value abs(SSMAX).** Further Details* ===============** Any input parameter may be aliased with any output parameter.** Barring over/underflow and assuming a guard digit in subtraction, all* output quantities are correct to within a few units in the last* place (ulps).** In IEEE arithmetic, the code works correctly if one matrix element is* infinite.** Overflow will not occur unless the largest singular value itself* overflows or is within a few ulps of overflow. (On machines with* partial overflow, like the Cray, overflow may occur if the largest* singular value is within a factor of 2 of overflow.)** Underflow is harmless if underflow is gradual. Otherwise, results* may correspond to a matrix modified by perturbations of size near* the underflow threshold.** =====================================================================** .. Parameters ..DOUBLE PRECISION ZEROPARAMETER ( ZERO = 0.0D0 )DOUBLE PRECISION HALFPARAMETER ( HALF = 0.5D0 )DOUBLE PRECISION ONEPARAMETER ( ONE = 1.0D0 )DOUBLE PRECISION TWOPARAMETER ( TWO = 2.0D0 )DOUBLE PRECISION FOURPARAMETER ( FOUR = 4.0D0 )* ..* .. Local Scalars ..LOGICAL GASMAL, SWAPINTEGER PMAXDOUBLE PRECISION A, CLT, CRT, D, FA, FT, GA, GT, HA, HT, L, M,$ MM, R, S, SLT, SRT, T, TEMP, TSIGN, TT* ..* .. Intrinsic Functions ..INTRINSIC ABS, SIGN, SQRT* ..* .. External Functions ..DOUBLE PRECISION DLAMCHEXTERNAL DLAMCH* ..* .. Executable Statements ..*FT = FFA = ABS( FT )HT = HHA = ABS( H )** PMAX points to the maximum absolute element of matrix* PMAX = 1 if F largest in absolute values* PMAX = 2 if G largest in absolute values* PMAX = 3 if H largest in absolute values*PMAX = 1SWAP = ( HA.GT.FA )IF( SWAP ) THENPMAX = 3TEMP = FTFT = HTHT = TEMPTEMP = FAFA = HAHA = TEMP** Now FA .ge. HA*END IFGT = GGA = ABS( GT )IF( GA.EQ.ZERO ) THEN** Diagonal matrix*SSMIN = HASSMAX = FACLT = ONECRT = ONESLT = ZEROSRT = ZEROELSEGASMAL = .TRUE.IF( GA.GT.FA ) THENPMAX = 2IF( ( FA / GA ).LT.DLAMCH( 'EPS' ) ) THEN** Case of very large GA*GASMAL = .FALSE.SSMAX = GAIF( HA.GT.ONE ) THENSSMIN = FA / ( GA / HA )ELSESSMIN = ( FA / GA )*HAEND IFCLT = ONESLT = HT / GTSRT = ONECRT = FT / GTEND IFEND IFIF( GASMAL ) THEN** Normal case*D = FA - HAIF( D.EQ.FA ) THEN** Copes with infinite F or H*L = ONEELSEL = D / FAEND IF** Note that 0 .le. L .le. 1*M = GT / FT** Note that abs(M) .le. 1/macheps*T = TWO - L** Note that T .ge. 1*MM = M*MTT = T*TS = SQRT( TT+MM )** Note that 1 .le. S .le. 1 + 1/macheps*IF( L.EQ.ZERO ) THENR = ABS( M )ELSER = SQRT( L*L+MM )END IF** Note that 0 .le. R .le. 1 + 1/macheps*A = HALF*( S+R )** Note that 1 .le. A .le. 1 + abs(M)*SSMIN = HA / ASSMAX = FA*AIF( MM.EQ.ZERO ) THEN** Note that M is very tiny*IF( L.EQ.ZERO ) THENT = SIGN( TWO, FT )*SIGN( ONE, GT )ELSET = GT / SIGN( D, FT ) + M / TEND IFELSET = ( M / ( S+T )+M / ( R+L ) )*( ONE+A )END IFL = SQRT( T*T+FOUR )CRT = TWO / LSRT = T / LCLT = ( CRT+SRT*M ) / ASLT = ( HT / FT )*SRT / AEND IFEND IFIF( SWAP ) THENCSL = SRTSNL = CRTCSR = SLTSNR = CLTELSECSL = CLTSNL = SLTCSR = CRTSNR = SRTEND IF** Correct signs of SSMAX and SSMIN*IF( PMAX.EQ.1 )$ TSIGN = SIGN( ONE, CSR )*SIGN( ONE, CSL )*SIGN( ONE, F )IF( PMAX.EQ.2 )$ TSIGN = SIGN( ONE, SNR )*SIGN( ONE, CSL )*SIGN( ONE, G )IF( PMAX.EQ.3 )$ TSIGN = SIGN( ONE, SNR )*SIGN( ONE, SNL )*SIGN( ONE, H )SSMAX = SIGN( SSMAX, TSIGN )SSMIN = SIGN( SSMIN, TSIGN*SIGN( ONE, F )*SIGN( ONE, H ) )RETURN** End of DLASV2*ENDSUBROUTINE DLASWP( N, A, LDA, K1, K2, IPIV, INCX )** -- LAPACK auxiliary 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 INCX, K1, K2, LDA, N* ..* .. Array Arguments ..INTEGER IPIV( * )DOUBLE PRECISION A( LDA, * )* ..** Purpose* =======** DLASWP performs a series of row interchanges on the matrix A.* One row interchange is initiated for each of rows K1 through K2 of A.** Arguments* =========** N (input) INTEGER* The number of columns of the matrix A.** A (input/output) DOUBLE PRECISION array, dimension (LDA,N)* On entry, the matrix of column dimension N to which the row* interchanges will be applied.* On exit, the permuted matrix.** LDA (input) INTEGER* The leading dimension of the array A.** K1 (input) INTEGER* The first element of IPIV for which a row interchange will* be done.** K2 (input) INTEGER* The last element of IPIV for which a row interchange will* be done.** IPIV (input) INTEGER array, dimension (M*abs(INCX))* The vector of pivot indices. Only the elements in positions* K1 through K2 of IPIV are accessed.* IPIV(K) = L implies rows K and L are to be interchanged.** INCX (input) INTEGER* The increment between successive values of IPIV. If IPIV* is negative, the pivots are applied in reverse order.** Further Details* ===============** Modified by* R. C. Whaley, Computer Science Dept., Univ. of Tenn., Knoxville, USA** =====================================================================** .. Local Scalars ..INTEGER I, I1, I2, INC, IP, IX, IX0, J, K, N32DOUBLE PRECISION TEMP* ..* .. Executable Statements ..** Interchange row I with row IPIV(I) for each of rows K1 through K2.*IF( INCX.GT.0 ) THENIX0 = K1I1 = K1I2 = K2INC = 1ELSE IF( INCX.LT.0 ) THENIX0 = 1 + ( 1-K2 )*INCXI1 = K2I2 = K1INC = -1ELSERETURNEND IF*N32 = ( N / 32 )*32IF( N32.NE.0 ) THENDO 30 J = 1, N32, 32IX = IX0DO 20 I = I1, I2, INCIP = IPIV( IX )IF( IP.NE.I ) THENDO 10 K = J, J + 31TEMP = A( I, K )A( I, K ) = A( IP, K )A( IP, K ) = TEMP10 CONTINUEEND IFIX = IX + INCX20 CONTINUE30 CONTINUEEND IFIF( N32.NE.N ) THENN32 = N32 + 1IX = IX0DO 50 I = I1, I2, INCIP = IPIV( IX )IF( IP.NE.I ) THENDO 40 K = N32, NTEMP = A( I, K )A( I, K ) = A( IP, K )A( IP, K ) = TEMP40 CONTINUEEND IFIX = IX + INCX50 CONTINUEEND IF*RETURN** End of DLASWP*ENDSUBROUTINE DLASY2( LTRANL, LTRANR, ISGN, N1, N2, TL, LDTL, TR,$ LDTR, B, LDB, SCALE, X, LDX, XNORM, INFO )** -- LAPACK auxiliary routine (version 3.0) --* Univ. of Tennessee, Univ. of California Berkeley, NAG Ltd.,* Courant Institute, Argonne National Lab, and Rice University* October 31, 1992** .. Scalar Arguments ..LOGICAL LTRANL, LTRANRINTEGER INFO, ISGN, LDB, LDTL, LDTR, LDX, N1, N2DOUBLE PRECISION SCALE, XNORM* ..* .. Array Arguments ..DOUBLE PRECISION B( LDB, * ), TL( LDTL, * ), TR( LDTR, * ),$ X( LDX, * )* ..** Purpose* =======** DLASY2 solves for the N1 by N2 matrix X, 1 <= N1,N2 <= 2, in** op(TL)*X + ISGN*X*op(TR) = SCALE*B,** where TL is N1 by N1, TR is N2 by N2, B is N1 by N2, and ISGN = 1 or* -1. op(T) = T or T', where T' denotes the transpose of T.** Arguments* =========** LTRANL (input) LOGICAL* On entry, LTRANL specifies the op(TL):* = .FALSE., op(TL) = TL,* = .TRUE., op(TL) = TL'.** LTRANR (input) LOGICAL* On entry, LTRANR specifies the op(TR):* = .FALSE., op(TR) = TR,* = .TRUE., op(TR) = TR'.** ISGN (input) INTEGER* On entry, ISGN specifies the sign of the equation* as described before. ISGN may only be 1 or -1.** N1 (input) INTEGER* On entry, N1 specifies the order of matrix TL.* N1 may only be 0, 1 or 2.** N2 (input) INTEGER* On entry, N2 specifies the order of matrix TR.* N2 may only be 0, 1 or 2.** TL (input) DOUBLE PRECISION array, dimension (LDTL,2)* On entry, TL contains an N1 by N1 matrix.** LDTL (input) INTEGER* The leading dimension of the matrix TL. LDTL >= max(1,N1).** TR (input) DOUBLE PRECISION array, dimension (LDTR,2)* On entry, TR contains an N2 by N2 matrix.** LDTR (input) INTEGER* The leading dimension of the matrix TR. LDTR >= max(1,N2).** B (input) DOUBLE PRECISION array, dimension (LDB,2)* On entry, the N1 by N2 matrix B contains the right-hand* side of the equation.** LDB (input) INTEGER* The leading dimension of the matrix B. LDB >= max(1,N1).** SCALE (output) DOUBLE PRECISION* On exit, SCALE contains the scale factor. SCALE is chosen* less than or equal to 1 to prevent the solution overflowing.** X (output) DOUBLE PRECISION array, dimension (LDX,2)* On exit, X contains the N1 by N2 solution.** LDX (input) INTEGER* The leading dimension of the matrix X. LDX >= max(1,N1).** XNORM (output) DOUBLE PRECISION* On exit, XNORM is the infinity-norm of the solution.** INFO (output) INTEGER* On exit, INFO is set to* 0: successful exit.* 1: TL and TR have too close eigenvalues, so TL or* TR is perturbed to get a nonsingular equation.* NOTE: In the interests of speed, this routine does not* check the inputs for errors.** =====================================================================** .. Parameters ..DOUBLE PRECISION ZERO, ONEPARAMETER ( ZERO = 0.0D+0, ONE = 1.0D+0 )DOUBLE PRECISION TWO, HALF, EIGHTPARAMETER ( TWO = 2.0D+0, HALF = 0.5D+0, EIGHT = 8.0D+0 )* ..* .. Local Scalars ..LOGICAL BSWAP, XSWAPINTEGER I, IP, IPIV, IPSV, J, JP, JPSV, KDOUBLE PRECISION BET, EPS, GAM, L21, SGN, SMIN, SMLNUM, TAU1,$ TEMP, U11, U12, U22, XMAX* ..* .. Local Arrays ..LOGICAL BSWPIV( 4 ), XSWPIV( 4 )INTEGER JPIV( 4 ), LOCL21( 4 ), LOCU12( 4 ),$ LOCU22( 4 )DOUBLE PRECISION BTMP( 4 ), T16( 4, 4 ), TMP( 4 ), X2( 2 )* ..* .. External Functions ..INTEGER IDAMAXDOUBLE PRECISION DLAMCHEXTERNAL IDAMAX, DLAMCH* ..* .. External Subroutines ..EXTERNAL DCOPY, DSWAP* ..* .. Intrinsic Functions ..INTRINSIC ABS, MAX* ..* .. Data statements ..DATA LOCU12 / 3, 4, 1, 2 / , LOCL21 / 2, 1, 4, 3 / ,$ LOCU22 / 4, 3, 2, 1 /DATA XSWPIV / .FALSE., .FALSE., .TRUE., .TRUE. /DATA BSWPIV / .FALSE., .TRUE., .FALSE., .TRUE. /* ..* .. Executable Statements ..** Do not check the input parameters for errors*INFO = 0** Quick return if possible*IF( N1.EQ.0 .OR. N2.EQ.0 )$ RETURN** Set constants to control overflow*EPS = DLAMCH( 'P' )SMLNUM = DLAMCH( 'S' ) / EPSSGN = ISGN*K = N1 + N1 + N2 - 2GO TO ( 10, 20, 30, 50 )K** 1 by 1: TL11*X + SGN*X*TR11 = B11*10 CONTINUETAU1 = TL( 1, 1 ) + SGN*TR( 1, 1 )BET = ABS( TAU1 )IF( BET.LE.SMLNUM ) THENTAU1 = SMLNUMBET = SMLNUMINFO = 1END IF*SCALE = ONEGAM = ABS( B( 1, 1 ) )IF( SMLNUM*GAM.GT.BET )$ SCALE = ONE / GAM*X( 1, 1 ) = ( B( 1, 1 )*SCALE ) / TAU1XNORM = ABS( X( 1, 1 ) )RETURN** 1 by 2:* TL11*[X11 X12] + ISGN*[X11 X12]*op[TR11 TR12] = [B11 B12]* [TR21 TR22]*20 CONTINUE*SMIN = MAX( EPS*MAX( ABS( TL( 1, 1 ) ), ABS( TR( 1, 1 ) ),$ ABS( TR( 1, 2 ) ), ABS( TR( 2, 1 ) ), ABS( TR( 2, 2 ) ) ),$ SMLNUM )TMP( 1 ) = TL( 1, 1 ) + SGN*TR( 1, 1 )TMP( 4 ) = TL( 1, 1 ) + SGN*TR( 2, 2 )IF( LTRANR ) THENTMP( 2 ) = SGN*TR( 2, 1 )TMP( 3 ) = SGN*TR( 1, 2 )ELSETMP( 2 ) = SGN*TR( 1, 2 )TMP( 3 ) = SGN*TR( 2, 1 )END IFBTMP( 1 ) = B( 1, 1 )BTMP( 2 ) = B( 1, 2 )GO TO 40** 2 by 1:* op[TL11 TL12]*[X11] + ISGN* [X11]*TR11 = [B11]* [TL21 TL22] [X21] [X21] [B21]*30 CONTINUESMIN = MAX( EPS*MAX( ABS( TR( 1, 1 ) ), ABS( TL( 1, 1 ) ),$ ABS( TL( 1, 2 ) ), ABS( TL( 2, 1 ) ), ABS( TL( 2, 2 ) ) ),$ SMLNUM )TMP( 1 ) = TL( 1, 1 ) + SGN*TR( 1, 1 )TMP( 4 ) = TL( 2, 2 ) + SGN*TR( 1, 1 )IF( LTRANL ) THENTMP( 2 ) = TL( 1, 2 )TMP( 3 ) = TL( 2, 1 )ELSETMP( 2 ) = TL( 2, 1 )TMP( 3 ) = TL( 1, 2 )END IFBTMP( 1 ) = B( 1, 1 )BTMP( 2 ) = B( 2, 1 )40 CONTINUE** Solve 2 by 2 system using complete pivoting.* Set pivots less than SMIN to SMIN.*IPIV = IDAMAX( 4, TMP, 1 )U11 = TMP( IPIV )IF( ABS( U11 ).LE.SMIN ) THENINFO = 1U11 = SMINEND IFU12 = TMP( LOCU12( IPIV ) )L21 = TMP( LOCL21( IPIV ) ) / U11U22 = TMP( LOCU22( IPIV ) ) - U12*L21XSWAP = XSWPIV( IPIV )BSWAP = BSWPIV( IPIV )IF( ABS( U22 ).LE.SMIN ) THENINFO = 1U22 = SMINEND IFIF( BSWAP ) THENTEMP = BTMP( 2 )BTMP( 2 ) = BTMP( 1 ) - L21*TEMPBTMP( 1 ) = TEMPELSEBTMP( 2 ) = BTMP( 2 ) - L21*BTMP( 1 )END IFSCALE = ONEIF( ( TWO*SMLNUM )*ABS( BTMP( 2 ) ).GT.ABS( U22 ) .OR.$ ( TWO*SMLNUM )*ABS( BTMP( 1 ) ).GT.ABS( U11 ) ) THENSCALE = HALF / MAX( ABS( BTMP( 1 ) ), ABS( BTMP( 2 ) ) )BTMP( 1 ) = BTMP( 1 )*SCALEBTMP( 2 ) = BTMP( 2 )*SCALEEND IFX2( 2 ) = BTMP( 2 ) / U22X2( 1 ) = BTMP( 1 ) / U11 - ( U12 / U11 )*X2( 2 )IF( XSWAP ) THENTEMP = X2( 2 )X2( 2 ) = X2( 1 )X2( 1 ) = TEMPEND IFX( 1, 1 ) = X2( 1 )IF( N1.EQ.1 ) THENX( 1, 2 ) = X2( 2 )XNORM = ABS( X( 1, 1 ) ) + ABS( X( 1, 2 ) )ELSEX( 2, 1 ) = X2( 2 )XNORM = MAX( ABS( X( 1, 1 ) ), ABS( X( 2, 1 ) ) )END IFRETURN** 2 by 2:* op[TL11 TL12]*[X11 X12] +ISGN* [X11 X12]*op[TR11 TR12] = [B11 B12]* [TL21 TL22] [X21 X22] [X21 X22] [TR21 TR22] [B21 B22]** Solve equivalent 4 by 4 system using complete pivoting.* Set pivots less than SMIN to SMIN.*50 CONTINUESMIN = MAX( ABS( TR( 1, 1 ) ), ABS( TR( 1, 2 ) ),$ ABS( TR( 2, 1 ) ), ABS( TR( 2, 2 ) ) )SMIN = MAX( SMIN, ABS( TL( 1, 1 ) ), ABS( TL( 1, 2 ) ),$ ABS( TL( 2, 1 ) ), ABS( TL( 2, 2 ) ) )SMIN = MAX( EPS*SMIN, SMLNUM )BTMP( 1 ) = ZEROCALL DCOPY( 16, BTMP, 0, T16, 1 )T16( 1, 1 ) = TL( 1, 1 ) + SGN*TR( 1, 1 )T16( 2, 2 ) = TL( 2, 2 ) + SGN*TR( 1, 1 )T16( 3, 3 ) = TL( 1, 1 ) + SGN*TR( 2, 2 )T16( 4, 4 ) = TL( 2, 2 ) + SGN*TR( 2, 2 )IF( LTRANL ) THENT16( 1, 2 ) = TL( 2, 1 )T16( 2, 1 ) = TL( 1, 2 )T16( 3, 4 ) = TL( 2, 1 )T16( 4, 3 ) = TL( 1, 2 )ELSET16( 1, 2 ) = TL( 1, 2 )T16( 2, 1 ) = TL( 2, 1 )T16( 3, 4 ) = TL( 1, 2 )T16( 4, 3 ) = TL( 2, 1 )END IFIF( LTRANR ) THENT16( 1, 3 ) = SGN*TR( 1, 2 )T16( 2, 4 ) = SGN*TR( 1, 2 )T16( 3, 1 ) = SGN*TR( 2, 1 )T16( 4, 2 ) = SGN*TR( 2, 1 )ELSET16( 1, 3 ) = SGN*TR( 2, 1 )T16( 2, 4 ) = SGN*TR( 2, 1 )T16( 3, 1 ) = SGN*TR( 1, 2 )T16( 4, 2 ) = SGN*TR( 1, 2 )END IFBTMP( 1 ) = B( 1, 1 )BTMP( 2 ) = B( 2, 1 )BTMP( 3 ) = B( 1, 2 )BTMP( 4 ) = B( 2, 2 )** Perform elimination*DO 100 I = 1, 3XMAX = ZERODO 70 IP = I, 4DO 60 JP = I, 4IF( ABS( T16( IP, JP ) ).GE.XMAX ) THENXMAX = ABS( T16( IP, JP ) )IPSV = IPJPSV = JPEND IF60 CONTINUE70 CONTINUEIF( IPSV.NE.I ) THENCALL DSWAP( 4, T16( IPSV, 1 ), 4, T16( I, 1 ), 4 )TEMP = BTMP( I )BTMP( I ) = BTMP( IPSV )BTMP( IPSV ) = TEMPEND IFIF( JPSV.NE.I )$ CALL DSWAP( 4, T16( 1, JPSV ), 1, T16( 1, I ), 1 )JPIV( I ) = JPSVIF( ABS( T16( I, I ) ).LT.SMIN ) THENINFO = 1T16( I, I ) = SMINEND IFDO 90 J = I + 1, 4T16( J, I ) = T16( J, I ) / T16( I, I )BTMP( J ) = BTMP( J ) - T16( J, I )*BTMP( I )DO 80 K = I + 1, 4T16( J, K ) = T16( J, K ) - T16( J, I )*T16( I, K )80 CONTINUE90 CONTINUE100 CONTINUEIF( ABS( T16( 4, 4 ) ).LT.SMIN )$ T16( 4, 4 ) = SMINSCALE = ONEIF( ( EIGHT*SMLNUM )*ABS( BTMP( 1 ) ).GT.ABS( T16( 1, 1 ) ) .OR.$ ( EIGHT*SMLNUM )*ABS( BTMP( 2 ) ).GT.ABS( T16( 2, 2 ) ) .OR.$ ( EIGHT*SMLNUM )*ABS( BTMP( 3 ) ).GT.ABS( T16( 3, 3 ) ) .OR.$ ( EIGHT*SMLNUM )*ABS( BTMP( 4 ) ).GT.ABS( T16( 4, 4 ) ) ) THENSCALE = ( ONE / EIGHT ) / MAX( ABS( BTMP( 1 ) ),$ ABS( BTMP( 2 ) ), ABS( BTMP( 3 ) ), ABS( BTMP( 4 ) ) )BTMP( 1 ) = BTMP( 1 )*SCALEBTMP( 2 ) = BTMP( 2 )*SCALEBTMP( 3 ) = BTMP( 3 )*SCALEBTMP( 4 ) = BTMP( 4 )*SCALEEND IFDO 120 I = 1, 4K = 5 - ITEMP = ONE / T16( K, K )TMP( K ) = BTMP( K )*TEMPDO 110 J = K + 1, 4TMP( K ) = TMP( K ) - ( TEMP*T16( K, J ) )*TMP( J )110 CONTINUE120 CONTINUEDO 130 I = 1, 3IF( JPIV( 4-I ).NE.4-I ) THENTEMP = TMP( 4-I )TMP( 4-I ) = TMP( JPIV( 4-I ) )TMP( JPIV( 4-I ) ) = TEMPEND IF130 CONTINUEX( 1, 1 ) = TMP( 1 )X( 2, 1 ) = TMP( 2 )X( 1, 2 ) = TMP( 3 )X( 2, 2 ) = TMP( 4 )XNORM = MAX( ABS( TMP( 1 ) )+ABS( TMP( 3 ) ),$ ABS( TMP( 2 ) )+ABS( TMP( 4 ) ) )RETURN** End of DLASY2*ENDSUBROUTINE DLATDF( IJOB, N, Z, LDZ, RHS, RDSUM, RDSCAL, IPIV,$ JPIV )** -- LAPACK auxiliary 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 IJOB, LDZ, NDOUBLE PRECISION RDSCAL, RDSUM* ..* .. Array Arguments ..INTEGER IPIV( * ), JPIV( * )DOUBLE PRECISION RHS( * ), Z( LDZ, * )* ..** Purpose* =======** DLATDF uses the LU factorization of the n-by-n matrix Z computed by* DGETC2 and computes a contribution to the reciprocal Dif-estimate* by solving Z * x = b for x, and choosing the r.h.s. b such that* the norm of x is as large as possible. On entry RHS = b holds the* contribution from earlier solved sub-systems, and on return RHS = x.** The factorization of Z returned by DGETC2 has the form Z = P*L*U*Q,* where P and Q are permutation matrices. L is lower triangular with* unit diagonal elements and U is upper triangular.** Arguments* =========** IJOB (input) INTEGER* IJOB = 2: First compute an approximative null-vector e* of Z using DGECON, e is normalized and solve for* Zx = +-e - f with the sign giving the greater value* of 2-norm(x). About 5 times as expensive as Default.* IJOB .ne. 2: Local look ahead strategy where all entries of* the r.h.s. b is choosen as either +1 or -1 (Default).** N (input) INTEGER* The number of columns of the matrix Z.** Z (input) DOUBLE PRECISION array, dimension (LDZ, N)* On entry, the LU part of the factorization of the n-by-n* matrix Z computed by DGETC2: Z = P * L * U * Q** LDZ (input) INTEGER* The leading dimension of the array Z. LDA >= max(1, N).** RHS (input/output) DOUBLE PRECISION array, dimension N.* On entry, RHS contains contributions from other subsystems.* On exit, RHS contains the solution of the subsystem with* entries acoording to the value of IJOB (see above).** RDSUM (input/output) DOUBLE PRECISION* On entry, the sum of squares of computed contributions to* the Dif-estimate under computation by DTGSYL, where the* scaling factor RDSCAL (see below) has been factored out.* On exit, the corresponding sum of squares updated with the* contributions from the current sub-system.* If TRANS = 'T' RDSUM is not touched.* NOTE: RDSUM only makes sense when DTGSY2 is called by STGSYL.** RDSCAL (input/output) DOUBLE PRECISION* On entry, scaling factor used to prevent overflow in RDSUM.* On exit, RDSCAL is updated w.r.t. the current contributions* in RDSUM.* If TRANS = 'T', RDSCAL is not touched.* NOTE: RDSCAL only makes sense when DTGSY2 is called by* DTGSYL.** IPIV (input) INTEGER array, dimension (N).* The pivot indices; for 1 <= i <= N, row i of the* matrix has been interchanged with row IPIV(i).** JPIV (input) INTEGER array, dimension (N).* The pivot indices; for 1 <= j <= N, column j of the* matrix has been interchanged with column JPIV(j).** Further Details* ===============** Based on contributions by* Bo Kagstrom and Peter Poromaa, Department of Computing Science,* Umea University, S-901 87 Umea, Sweden.** This routine is a further developed implementation of algorithm* BSOLVE in [1] using complete pivoting in the LU factorization.** [1] Bo Kagstrom and Lars Westin,* Generalized Schur Methods with Condition Estimators for* Solving the Generalized Sylvester Equation, IEEE Transactions* on Automatic Control, Vol. 34, No. 7, July 1989, pp 745-751.** [2] Peter Poromaa,* On Efficient and Robust Estimators for the Separation* between two Regular Matrix Pairs with Applications in* Condition Estimation. Report IMINF-95.05, Departement of* Computing Science, Umea University, S-901 87 Umea, Sweden, 1995.** =====================================================================** .. Parameters ..INTEGER MAXDIMPARAMETER ( MAXDIM = 8 )DOUBLE PRECISION ZERO, ONEPARAMETER ( ZERO = 0.0D+0, ONE = 1.0D+0 )* ..* .. Local Scalars ..INTEGER I, INFO, J, KDOUBLE PRECISION BM, BP, PMONE, SMINU, SPLUS, TEMP* ..* .. Local Arrays ..INTEGER IWORK( MAXDIM )DOUBLE PRECISION WORK( 4*MAXDIM ), XM( MAXDIM ), XP( MAXDIM )* ..* .. External Subroutines ..EXTERNAL DAXPY, DCOPY, DGECON, DGESC2, DLASSQ, DLASWP,$ DSCAL* ..* .. External Functions ..DOUBLE PRECISION DASUM, DDOTEXTERNAL DASUM, DDOT* ..* .. Intrinsic Functions ..INTRINSIC ABS, SQRT* ..* .. Executable Statements ..*IF( IJOB.NE.2 ) THEN** Apply permutations IPIV to RHS*CALL DLASWP( 1, RHS, LDZ, 1, N-1, IPIV, 1 )** Solve for L-part choosing RHS either to +1 or -1.*PMONE = -ONE*DO 10 J = 1, N - 1BP = RHS( J ) + ONEBM = RHS( J ) - ONESPLUS = ONE** Look-ahead for L-part RHS(1:N-1) = + or -1, SPLUS and* SMIN computed more efficiently than in BSOLVE [1].*SPLUS = SPLUS + DDOT( N-J, Z( J+1, J ), 1, Z( J+1, J ), 1 )SMINU = DDOT( N-J, Z( J+1, J ), 1, RHS( J+1 ), 1 )SPLUS = SPLUS*RHS( J )IF( SPLUS.GT.SMINU ) THENRHS( J ) = BPELSE IF( SMINU.GT.SPLUS ) THENRHS( J ) = BMELSE** In this case the updating sums are equal and we can* choose RHS(J) +1 or -1. The first time this happens* we choose -1, thereafter +1. This is a simple way to* get good estimates of matrices like Byers well-known* example (see [1]). (Not done in BSOLVE.)*RHS( J ) = RHS( J ) + PMONEPMONE = ONEEND IF** Compute the remaining r.h.s.*TEMP = -RHS( J )CALL DAXPY( N-J, TEMP, Z( J+1, J ), 1, RHS( J+1 ), 1 )*10 CONTINUE** Solve for U-part, look-ahead for RHS(N) = +-1. This is not done* in BSOLVE and will hopefully give us a better estimate because* any ill-conditioning of the original matrix is transfered to U* and not to L. U(N, N) is an approximation to sigma_min(LU).*CALL DCOPY( N-1, RHS, 1, XP, 1 )XP( N ) = RHS( N ) + ONERHS( N ) = RHS( N ) - ONESPLUS = ZEROSMINU = ZERODO 30 I = N, 1, -1TEMP = ONE / Z( I, I )XP( I ) = XP( I )*TEMPRHS( I ) = RHS( I )*TEMPDO 20 K = I + 1, NXP( I ) = XP( I ) - XP( K )*( Z( I, K )*TEMP )RHS( I ) = RHS( I ) - RHS( K )*( Z( I, K )*TEMP )20 CONTINUESPLUS = SPLUS + ABS( XP( I ) )SMINU = SMINU + ABS( RHS( I ) )30 CONTINUEIF( SPLUS.GT.SMINU )$ CALL DCOPY( N, XP, 1, RHS, 1 )** Apply the permutations JPIV to the computed solution (RHS)*CALL DLASWP( 1, RHS, LDZ, 1, N-1, JPIV, -1 )** Compute the sum of squares*CALL DLASSQ( N, RHS, 1, RDSCAL, RDSUM )*ELSE** IJOB = 2, Compute approximate nullvector XM of Z*CALL DGECON( 'I', N, Z, LDZ, ONE, TEMP, WORK, IWORK, INFO )CALL DCOPY( N, WORK( N+1 ), 1, XM, 1 )** Compute RHS*CALL DLASWP( 1, XM, LDZ, 1, N-1, IPIV, -1 )TEMP = ONE / SQRT( DDOT( N, XM, 1, XM, 1 ) )CALL DSCAL( N, TEMP, XM, 1 )CALL DCOPY( N, XM, 1, XP, 1 )CALL DAXPY( N, ONE, RHS, 1, XP, 1 )CALL DAXPY( N, -ONE, XM, 1, RHS, 1 )CALL DGESC2( N, Z, LDZ, RHS, IPIV, JPIV, TEMP )CALL DGESC2( N, Z, LDZ, XP, IPIV, JPIV, TEMP )IF( DASUM( N, XP, 1 ).GT.DASUM( N, RHS, 1 ) )$ CALL DCOPY( N, XP, 1, RHS, 1 )** Compute the sum of squares*CALL DLASSQ( N, RHS, 1, RDSCAL, RDSUM )*END IF*RETURN** End of DLATDF*ENDSUBROUTINE DLATRD( UPLO, N, NB, A, LDA, E, TAU, W, LDW )** -- LAPACK auxiliary routine (version 3.0) --* Univ. of Tennessee, Univ. of California Berkeley, NAG Ltd.,* Courant Institute, Argonne National Lab, and Rice University* October 31, 1992** .. Scalar Arguments ..CHARACTER UPLOINTEGER LDA, LDW, N, NB* ..* .. Array Arguments ..DOUBLE PRECISION A( LDA, * ), E( * ), TAU( * ), W( LDW, * )* ..** Purpose* =======** DLATRD reduces NB rows and columns of a real symmetric matrix A to* symmetric tridiagonal form by an orthogonal similarity* transformation Q' * A * Q, and returns the matrices V and W which are* needed to apply the transformation to the unreduced part of A.** If UPLO = 'U', DLATRD reduces the last NB rows and columns of a* matrix, of which the upper triangle is supplied;* if UPLO = 'L', DLATRD reduces the first NB rows and columns of a* matrix, of which the lower triangle is supplied.** This is an auxiliary routine called by DSYTRD.** Arguments* =========** UPLO (input) CHARACTER* Specifies whether the upper or lower triangular part of the* symmetric matrix A is stored:* = 'U': Upper triangular* = 'L': Lower triangular** N (input) INTEGER* The order of the matrix A.** NB (input) INTEGER* The number of rows and columns to be reduced.** A (input/output) DOUBLE PRECISION array, dimension (LDA,N)* On entry, the symmetric matrix A. If UPLO = 'U', the leading* n-by-n upper triangular part of A contains the upper* triangular part of the matrix A, and the strictly lower* triangular part of A is not referenced. If UPLO = 'L', the* leading n-by-n lower triangular part of A contains the lower* triangular part of the matrix A, and the strictly upper* triangular part of A is not referenced.* On exit:* if UPLO = 'U', the last NB columns have been reduced to* tridiagonal form, with the diagonal elements overwriting* the diagonal elements of A; the elements above the diagonal* with the array TAU, represent the orthogonal matrix Q as a* product of elementary reflectors;* if UPLO = 'L', the first NB columns have been reduced to* tridiagonal form, with the diagonal elements overwriting* the diagonal elements of A; the elements below the diagonal* with the array TAU, represent the orthogonal matrix Q as a* product of elementary reflectors.* See Further Details.** LDA (input) INTEGER* The leading dimension of the array A. LDA >= (1,N).** E (output) DOUBLE PRECISION array, dimension (N-1)* If UPLO = 'U', E(n-nb:n-1) contains the superdiagonal* elements of the last NB columns of the reduced matrix;* if UPLO = 'L', E(1:nb) contains the subdiagonal elements of* the first NB columns of the reduced matrix.** TAU (output) DOUBLE PRECISION array, dimension (N-1)* The scalar factors of the elementary reflectors, stored in* TAU(n-nb:n-1) if UPLO = 'U', and in TAU(1:nb) if UPLO = 'L'.* See Further Details.** W (output) DOUBLE PRECISION array, dimension (LDW,NB)* The n-by-nb matrix W required to update the unreduced part* of A.** LDW (input) INTEGER* The leading dimension of the array W. LDW >= max(1,N).** Further Details* ===============** If UPLO = 'U', the matrix Q is represented as a product of elementary* reflectors** Q = H(n) H(n-1) . . . H(n-nb+1).** Each H(i) has the form** H(i) = I - tau * v * v'** where tau is a real scalar, and v is a real vector with* v(i:n) = 0 and v(i-1) = 1; v(1:i-1) is stored on exit in A(1:i-1,i),* and tau in TAU(i-1).** If UPLO = 'L', the matrix Q is represented as a product of elementary* reflectors** Q = H(1) H(2) . . . H(nb).** Each H(i) has the form** H(i) = I - tau * v * v'** where tau is a real scalar, and v is a real vector with* v(1:i) = 0 and v(i+1) = 1; v(i+1:n) is stored on exit in A(i+1:n,i),* and tau in TAU(i).** The elements of the vectors v together form the n-by-nb matrix V* which is needed, with W, to apply the transformation to the unreduced* part of the matrix, using a symmetric rank-2k update of the form:* A := A - V*W' - W*V'.** The contents of A on exit are illustrated by the following examples* with n = 5 and nb = 2:** if UPLO = 'U': if UPLO = 'L':** ( a a a v4 v5 ) ( d )* ( a a v4 v5 ) ( 1 d )* ( a 1 v5 ) ( v1 1 a )* ( d 1 ) ( v1 v2 a a )* ( d ) ( v1 v2 a a a )** where d denotes a diagonal element of the reduced matrix, a denotes* an element of the original matrix that is unchanged, and vi denotes* an element of the vector defining H(i).** =====================================================================** .. Parameters ..DOUBLE PRECISION ZERO, ONE, HALFPARAMETER ( ZERO = 0.0D+0, ONE = 1.0D+0, HALF = 0.5D+0 )* ..* .. Local Scalars ..INTEGER I, IWDOUBLE PRECISION ALPHA* ..* .. External Subroutines ..EXTERNAL DAXPY, DGEMV, DLARFG, DSCAL, DSYMV* ..* .. External Functions ..LOGICAL LSAMEDOUBLE PRECISION DDOTEXTERNAL LSAME, DDOT* ..* .. Intrinsic Functions ..INTRINSIC MIN* ..* .. Executable Statements ..** Quick return if possible*IF( N.LE.0 )$ RETURN*IF( LSAME( UPLO, 'U' ) ) THEN** Reduce last NB columns of upper triangle*DO 10 I = N, N - NB + 1, -1IW = I - N + NBIF( I.LT.N ) THEN** Update A(1:i,i)*CALL DGEMV( 'No transpose', I, N-I, -ONE, A( 1, I+1 ),$ LDA, W( I, IW+1 ), LDW, ONE, A( 1, I ), 1 )CALL DGEMV( 'No transpose', I, N-I, -ONE, W( 1, IW+1 ),$ LDW, A( I, I+1 ), LDA, ONE, A( 1, I ), 1 )END IFIF( I.GT.1 ) THEN** Generate elementary reflector H(i) to annihilate* A(1:i-2,i)*CALL DLARFG( I-1, A( I-1, I ), A( 1, I ), 1, TAU( I-1 ) )E( I-1 ) = A( I-1, I )A( I-1, I ) = ONE** Compute W(1:i-1,i)*CALL DSYMV( 'Upper', I-1, ONE, A, LDA, A( 1, I ), 1,$ ZERO, W( 1, IW ), 1 )IF( I.LT.N ) THENCALL DGEMV( 'Transpose', I-1, N-I, ONE, W( 1, IW+1 ),$ LDW, A( 1, I ), 1, ZERO, W( I+1, IW ), 1 )CALL DGEMV( 'No transpose', I-1, N-I, -ONE,$ A( 1, I+1 ), LDA, W( I+1, IW ), 1, ONE,$ W( 1, IW ), 1 )CALL DGEMV( 'Transpose', I-1, N-I, ONE, A( 1, I+1 ),$ LDA, A( 1, I ), 1, ZERO, W( I+1, IW ), 1 )CALL DGEMV( 'No transpose', I-1, N-I, -ONE,$ W( 1, IW+1 ), LDW, W( I+1, IW ), 1, ONE,$ W( 1, IW ), 1 )END IFCALL DSCAL( I-1, TAU( I-1 ), W( 1, IW ), 1 )ALPHA = -HALF*TAU( I-1 )*DDOT( I-1, W( 1, IW ), 1,$ A( 1, I ), 1 )CALL DAXPY( I-1, ALPHA, A( 1, I ), 1, W( 1, IW ), 1 )END IF*10 CONTINUEELSE** Reduce first NB columns of lower triangle*DO 20 I = 1, NB** Update A(i:n,i)*CALL DGEMV( 'No transpose', N-I+1, I-1, -ONE, A( I, 1 ),$ LDA, W( I, 1 ), LDW, ONE, A( I, I ), 1 )CALL DGEMV( 'No transpose', N-I+1, I-1, -ONE, W( I, 1 ),$ LDW, A( I, 1 ), LDA, ONE, A( I, I ), 1 )IF( I.LT.N ) THEN** Generate elementary reflector H(i) to annihilate* A(i+2:n,i)*CALL DLARFG( N-I, A( I+1, I ), A( MIN( I+2, N ), I ), 1,$ TAU( I ) )E( I ) = A( I+1, I )A( I+1, I ) = ONE** Compute W(i+1:n,i)*CALL DSYMV( 'Lower', N-I, ONE, A( I+1, I+1 ), LDA,$ A( I+1, I ), 1, ZERO, W( I+1, I ), 1 )CALL DGEMV( 'Transpose', N-I, I-1, ONE, W( I+1, 1 ), LDW,$ A( I+1, I ), 1, ZERO, W( 1, I ), 1 )CALL DGEMV( 'No transpose', N-I, I-1, -ONE, A( I+1, 1 ),$ LDA, W( 1, I ), 1, ONE, W( I+1, I ), 1 )CALL DGEMV( 'Transpose', N-I, I-1, ONE, A( I+1, 1 ), LDA,$ A( I+1, I ), 1, ZERO, W( 1, I ), 1 )CALL DGEMV( 'No transpose', N-I, I-1, -ONE, W( I+1, 1 ),$ LDW, W( 1, I ), 1, ONE, W( I+1, I ), 1 )CALL DSCAL( N-I, TAU( I ), W( I+1, I ), 1 )ALPHA = -HALF*TAU( I )*DDOT( N-I, W( I+1, I ), 1,$ A( I+1, I ), 1 )CALL DAXPY( N-I, ALPHA, A( I+1, I ), 1, W( I+1, I ), 1 )END IF*20 CONTINUEEND IF*RETURN** End of DLATRD*ENDSUBROUTINE DLATRS( UPLO, TRANS, DIAG, NORMIN, N, A, LDA, X, SCALE,$ CNORM, INFO )** -- LAPACK auxiliary routine (version 3.0) --* Univ. of Tennessee, Univ. of California Berkeley, NAG Ltd.,* Courant Institute, Argonne National Lab, and Rice University* June 30, 1992** .. Scalar Arguments ..CHARACTER DIAG, NORMIN, TRANS, UPLOINTEGER INFO, LDA, NDOUBLE PRECISION SCALE* ..* .. Array Arguments ..DOUBLE PRECISION A( LDA, * ), CNORM( * ), X( * )* ..** Purpose* =======** DLATRS solves one of the triangular systems** A *x = s*b or A'*x = s*b** with scaling to prevent overflow. Here A is an upper or lower* triangular matrix, A' denotes the transpose of A, x and b are* n-element vectors, and s is a scaling factor, usually less than* or equal to 1, chosen so that the components of x will be less than* the overflow threshold. If the unscaled problem will not cause* overflow, the Level 2 BLAS routine DTRSV is called. If the matrix A* is singular (A(j,j) = 0 for some j), then s is set to 0 and a* non-trivial solution to A*x = 0 is returned.** Arguments* =========** UPLO (input) CHARACTER*1* Specifies whether the matrix A is upper or lower triangular.* = 'U': Upper triangular* = 'L': Lower triangular** TRANS (input) CHARACTER*1* Specifies the operation applied to A.* = 'N': Solve A * x = s*b (No transpose)* = 'T': Solve A'* x = s*b (Transpose)* = 'C': Solve A'* x = s*b (Conjugate transpose = Transpose)** DIAG (input) CHARACTER*1* Specifies whether or not the matrix A is unit triangular.* = 'N': Non-unit triangular* = 'U': Unit triangular** NORMIN (input) CHARACTER*1* Specifies whether CNORM has been set or not.* = 'Y': CNORM contains the column norms on entry* = 'N': CNORM is not set on entry. On exit, the norms will* be computed and stored in CNORM.** N (input) INTEGER* The order of the matrix A. N >= 0.** A (input) DOUBLE PRECISION array, dimension (LDA,N)* The triangular matrix A. If UPLO = 'U', the leading n by n* upper triangular part of the array A contains the upper* triangular matrix, and the strictly lower triangular part of* A is not referenced. If UPLO = 'L', the leading n by n lower* triangular part of the array A contains the lower triangular* matrix, and the strictly upper triangular part of A is not* referenced. If DIAG = 'U', the diagonal elements of A are* also not referenced and are assumed to be 1.** LDA (input) INTEGER* The leading dimension of the array A. LDA >= max (1,N).** X (input/output) DOUBLE PRECISION array, dimension (N)* On entry, the right hand side b of the triangular system.* On exit, X is overwritten by the solution vector x.** SCALE (output) DOUBLE PRECISION* The scaling factor s for the triangular system* A * x = s*b or A'* x = s*b.* If SCALE = 0, the matrix A is singular or badly scaled, and* the vector x is an exact or approximate solution to A*x = 0.** CNORM (input or output) DOUBLE PRECISION array, dimension (N)** If NORMIN = 'Y', CNORM is an input argument and CNORM(j)* contains the norm of the off-diagonal part of the j-th column* of A. If TRANS = 'N', CNORM(j) must be greater than or equal* to the infinity-norm, and if TRANS = 'T' or 'C', CNORM(j)* must be greater than or equal to the 1-norm.** If NORMIN = 'N', CNORM is an output argument and CNORM(j)* returns the 1-norm of the offdiagonal part of the j-th column* of A.** INFO (output) INTEGER* = 0: successful exit* < 0: if INFO = -k, the k-th argument had an illegal value** Further Details* ======= =======** A rough bound on x is computed; if that is less than overflow, DTRSV* is called, otherwise, specific code is used which checks for possible* overflow or divide-by-zero at every operation.** A columnwise scheme is used for solving A*x = b. The basic algorithm* if A is lower triangular is** x[1:n] := b[1:n]* for j = 1, ..., n* x(j) := x(j) / A(j,j)* x[j+1:n] := x[j+1:n] - x(j) * A[j+1:n,j]* end** Define bounds on the components of x after j iterations of the loop:* M(j) = bound on x[1:j]* G(j) = bound on x[j+1:n]* Initially, let M(0) = 0 and G(0) = max{x(i), i=1,...,n}.** Then for iteration j+1 we have* M(j+1) <= G(j) / | A(j+1,j+1) |* G(j+1) <= G(j) + M(j+1) * | A[j+2:n,j+1] |* <= G(j) ( 1 + CNORM(j+1) / | A(j+1,j+1) | )** where CNORM(j+1) is greater than or equal to the infinity-norm of* column j+1 of A, not counting the diagonal. Hence** G(j) <= G(0) product ( 1 + CNORM(i) / | A(i,i) | )* 1<=i<=j* and** |x(j)| <= ( G(0) / |A(j,j)| ) product ( 1 + CNORM(i) / |A(i,i)| )* 1<=i< j** Since |x(j)| <= M(j), we use the Level 2 BLAS routine DTRSV if the* reciprocal of the largest M(j), j=1,..,n, is larger than* max(underflow, 1/overflow).** The bound on x(j) is also used to determine when a step in the* columnwise method can be performed without fear of overflow. If* the computed bound is greater than a large constant, x is scaled to* prevent overflow, but if the bound overflows, x is set to 0, x(j) to* 1, and scale to 0, and a non-trivial solution to A*x = 0 is found.** Similarly, a row-wise scheme is used to solve A'*x = b. The basic* algorithm for A upper triangular is** for j = 1, ..., n* x(j) := ( b(j) - A[1:j-1,j]' * x[1:j-1] ) / A(j,j)* end** We simultaneously compute two bounds* G(j) = bound on ( b(i) - A[1:i-1,i]' * x[1:i-1] ), 1<=i<=j* M(j) = bound on x(i), 1<=i<=j** The initial values are G(0) = 0, M(0) = max{b(i), i=1,..,n}, and we* add the constraint G(j) >= G(j-1) and M(j) >= M(j-1) for j >= 1.* Then the bound on x(j) is** M(j) <= M(j-1) * ( 1 + CNORM(j) ) / | A(j,j) |** <= M(0) * product ( ( 1 + CNORM(i) ) / |A(i,i)| )* 1<=i<=j** and we can safely call DTRSV if 1/M(n) and 1/G(n) are both greater* than max(underflow, 1/overflow).** =====================================================================** .. Parameters ..DOUBLE PRECISION ZERO, HALF, ONEPARAMETER ( ZERO = 0.0D+0, HALF = 0.5D+0, ONE = 1.0D+0 )* ..* .. Local Scalars ..LOGICAL NOTRAN, NOUNIT, UPPERINTEGER I, IMAX, J, JFIRST, JINC, JLASTDOUBLE PRECISION BIGNUM, GROW, REC, SMLNUM, SUMJ, TJJ, TJJS,$ TMAX, TSCAL, USCAL, XBND, XJ, XMAX* ..* .. External Functions ..LOGICAL LSAMEINTEGER IDAMAXDOUBLE PRECISION DASUM, DDOT, DLAMCHEXTERNAL LSAME, IDAMAX, DASUM, DDOT, DLAMCH* ..* .. External Subroutines ..EXTERNAL DAXPY, DSCAL, DTRSV, XERBLA* ..* .. Intrinsic Functions ..INTRINSIC ABS, MAX, MIN* ..* .. Executable Statements ..*INFO = 0UPPER = LSAME( UPLO, 'U' )NOTRAN = LSAME( TRANS, 'N' )NOUNIT = LSAME( DIAG, 'N' )** Test the input parameters.*IF( .NOT.UPPER .AND. .NOT.LSAME( UPLO, 'L' ) ) THENINFO = -1ELSE IF( .NOT.NOTRAN .AND. .NOT.LSAME( TRANS, 'T' ) .AND. .NOT.$ LSAME( TRANS, 'C' ) ) THENINFO = -2ELSE IF( .NOT.NOUNIT .AND. .NOT.LSAME( DIAG, 'U' ) ) THENINFO = -3ELSE IF( .NOT.LSAME( NORMIN, 'Y' ) .AND. .NOT.$ LSAME( NORMIN, 'N' ) ) THENINFO = -4ELSE IF( N.LT.0 ) THENINFO = -5ELSE IF( LDA.LT.MAX( 1, N ) ) THENINFO = -7END IFIF( INFO.NE.0 ) THENCALL XERBLA( 'DLATRS', -INFO )RETURNEND IF** Quick return if possible*IF( N.EQ.0 )$ RETURN** Determine machine dependent parameters to control overflow.*SMLNUM = DLAMCH( 'Safe minimum' ) / DLAMCH( 'Precision' )BIGNUM = ONE / SMLNUMSCALE = ONE*IF( LSAME( NORMIN, 'N' ) ) THEN** Compute the 1-norm of each column, not including the diagonal.*IF( UPPER ) THEN** A is upper triangular.*DO 10 J = 1, NCNORM( J ) = DASUM( J-1, A( 1, J ), 1 )10 CONTINUEELSE** A is lower triangular.*DO 20 J = 1, N - 1CNORM( J ) = DASUM( N-J, A( J+1, J ), 1 )20 CONTINUECNORM( N ) = ZEROEND IFEND IF** Scale the column norms by TSCAL if the maximum element in CNORM is* greater than BIGNUM.*IMAX = IDAMAX( N, CNORM, 1 )TMAX = CNORM( IMAX )IF( TMAX.LE.BIGNUM ) THENTSCAL = ONEELSETSCAL = ONE / ( SMLNUM*TMAX )CALL DSCAL( N, TSCAL, CNORM, 1 )END IF** Compute a bound on the computed solution vector to see if the* Level 2 BLAS routine DTRSV can be used.*J = IDAMAX( N, X, 1 )XMAX = ABS( X( J ) )XBND = XMAXIF( NOTRAN ) THEN** Compute the growth in A * x = b.*IF( UPPER ) THENJFIRST = NJLAST = 1JINC = -1ELSEJFIRST = 1JLAST = NJINC = 1END IF*IF( TSCAL.NE.ONE ) THENGROW = ZEROGO TO 50END IF*IF( NOUNIT ) THEN** A is non-unit triangular.** Compute GROW = 1/G(j) and XBND = 1/M(j).* Initially, G(0) = max{x(i), i=1,...,n}.*GROW = ONE / MAX( XBND, SMLNUM )XBND = GROWDO 30 J = JFIRST, JLAST, JINC** Exit the loop if the growth factor is too small.*IF( GROW.LE.SMLNUM )$ GO TO 50** M(j) = G(j-1) / abs(A(j,j))*TJJ = ABS( A( J, J ) )XBND = MIN( XBND, MIN( ONE, TJJ )*GROW )IF( TJJ+CNORM( J ).GE.SMLNUM ) THEN** G(j) = G(j-1)*( 1 + CNORM(j) / abs(A(j,j)) )*GROW = GROW*( TJJ / ( TJJ+CNORM( J ) ) )ELSE** G(j) could overflow, set GROW to 0.*GROW = ZEROEND IF30 CONTINUEGROW = XBNDELSE** A is unit triangular.** Compute GROW = 1/G(j), where G(0) = max{x(i), i=1,...,n}.*GROW = MIN( ONE, ONE / MAX( XBND, SMLNUM ) )DO 40 J = JFIRST, JLAST, JINC** Exit the loop if the growth factor is too small.*IF( GROW.LE.SMLNUM )$ GO TO 50** G(j) = G(j-1)*( 1 + CNORM(j) )*GROW = GROW*( ONE / ( ONE+CNORM( J ) ) )40 CONTINUEEND IF50 CONTINUE*ELSE** Compute the growth in A' * x = b.*IF( UPPER ) THENJFIRST = 1JLAST = NJINC = 1ELSEJFIRST = NJLAST = 1JINC = -1END IF*IF( TSCAL.NE.ONE ) THENGROW = ZEROGO TO 80END IF*IF( NOUNIT ) THEN** A is non-unit triangular.** Compute GROW = 1/G(j) and XBND = 1/M(j).* Initially, M(0) = max{x(i), i=1,...,n}.*GROW = ONE / MAX( XBND, SMLNUM )XBND = GROWDO 60 J = JFIRST, JLAST, JINC** Exit the loop if the growth factor is too small.*IF( GROW.LE.SMLNUM )$ GO TO 80** G(j) = max( G(j-1), M(j-1)*( 1 + CNORM(j) ) )*XJ = ONE + CNORM( J )GROW = MIN( GROW, XBND / XJ )** M(j) = M(j-1)*( 1 + CNORM(j) ) / abs(A(j,j))*TJJ = ABS( A( J, J ) )IF( XJ.GT.TJJ )$ XBND = XBND*( TJJ / XJ )60 CONTINUEGROW = MIN( GROW, XBND )ELSE** A is unit triangular.** Compute GROW = 1/G(j), where G(0) = max{x(i), i=1,...,n}.*GROW = MIN( ONE, ONE / MAX( XBND, SMLNUM ) )DO 70 J = JFIRST, JLAST, JINC** Exit the loop if the growth factor is too small.*IF( GROW.LE.SMLNUM )$ GO TO 80** G(j) = ( 1 + CNORM(j) )*G(j-1)*XJ = ONE + CNORM( J )GROW = GROW / XJ70 CONTINUEEND IF80 CONTINUEEND IF*IF( ( GROW*TSCAL ).GT.SMLNUM ) THEN** Use the Level 2 BLAS solve if the reciprocal of the bound on* elements of X is not too small.*CALL DTRSV( UPLO, TRANS, DIAG, N, A, LDA, X, 1 )ELSE** Use a Level 1 BLAS solve, scaling intermediate results.*IF( XMAX.GT.BIGNUM ) THEN** Scale X so that its components are less than or equal to* BIGNUM in absolute value.*SCALE = BIGNUM / XMAXCALL DSCAL( N, SCALE, X, 1 )XMAX = BIGNUMEND IF*IF( NOTRAN ) THEN** Solve A * x = b*DO 110 J = JFIRST, JLAST, JINC** Compute x(j) = b(j) / A(j,j), scaling x if necessary.*XJ = ABS( X( J ) )IF( NOUNIT ) THENTJJS = A( J, J )*TSCALELSETJJS = TSCALIF( TSCAL.EQ.ONE )$ GO TO 100END IFTJJ = ABS( TJJS )IF( TJJ.GT.SMLNUM ) THEN** abs(A(j,j)) > SMLNUM:*IF( TJJ.LT.ONE ) THENIF( XJ.GT.TJJ*BIGNUM ) THEN** Scale x by 1/b(j).*REC = ONE / XJCALL DSCAL( N, REC, X, 1 )SCALE = SCALE*RECXMAX = XMAX*RECEND IFEND IFX( J ) = X( J ) / TJJSXJ = ABS( X( J ) )ELSE IF( TJJ.GT.ZERO ) THEN** 0 < abs(A(j,j)) <= SMLNUM:*IF( XJ.GT.TJJ*BIGNUM ) THEN** Scale x by (1/abs(x(j)))*abs(A(j,j))*BIGNUM* to avoid overflow when dividing by A(j,j).*REC = ( TJJ*BIGNUM ) / XJIF( CNORM( J ).GT.ONE ) THEN** Scale by 1/CNORM(j) to avoid overflow when* multiplying x(j) times column j.*REC = REC / CNORM( J )END IFCALL DSCAL( N, REC, X, 1 )SCALE = SCALE*RECXMAX = XMAX*RECEND IFX( J ) = X( J ) / TJJSXJ = ABS( X( J ) )ELSE** A(j,j) = 0: Set x(1:n) = 0, x(j) = 1, and* scale = 0, and compute a solution to A*x = 0.*DO 90 I = 1, NX( I ) = ZERO90 CONTINUEX( J ) = ONEXJ = ONESCALE = ZEROXMAX = ZEROEND IF100 CONTINUE** Scale x if necessary to avoid overflow when adding a* multiple of column j of A.*IF( XJ.GT.ONE ) THENREC = ONE / XJIF( CNORM( J ).GT.( BIGNUM-XMAX )*REC ) THEN** Scale x by 1/(2*abs(x(j))).*REC = REC*HALFCALL DSCAL( N, REC, X, 1 )SCALE = SCALE*RECEND IFELSE IF( XJ*CNORM( J ).GT.( BIGNUM-XMAX ) ) THEN** Scale x by 1/2.*CALL DSCAL( N, HALF, X, 1 )SCALE = SCALE*HALFEND IF*IF( UPPER ) THENIF( J.GT.1 ) THEN** Compute the update* x(1:j-1) := x(1:j-1) - x(j) * A(1:j-1,j)*CALL DAXPY( J-1, -X( J )*TSCAL, A( 1, J ), 1, X,$ 1 )I = IDAMAX( J-1, X, 1 )XMAX = ABS( X( I ) )END IFELSEIF( J.LT.N ) THEN** Compute the update* x(j+1:n) := x(j+1:n) - x(j) * A(j+1:n,j)*CALL DAXPY( N-J, -X( J )*TSCAL, A( J+1, J ), 1,$ X( J+1 ), 1 )I = J + IDAMAX( N-J, X( J+1 ), 1 )XMAX = ABS( X( I ) )END IFEND IF110 CONTINUE*ELSE** Solve A' * x = b*DO 160 J = JFIRST, JLAST, JINC** Compute x(j) = b(j) - sum A(k,j)*x(k).* k<>j*XJ = ABS( X( J ) )USCAL = TSCALREC = ONE / MAX( XMAX, ONE )IF( CNORM( J ).GT.( BIGNUM-XJ )*REC ) THEN** If x(j) could overflow, scale x by 1/(2*XMAX).*REC = REC*HALFIF( NOUNIT ) THENTJJS = A( J, J )*TSCALELSETJJS = TSCALEND IFTJJ = ABS( TJJS )IF( TJJ.GT.ONE ) THEN** Divide by A(j,j) when scaling x if A(j,j) > 1.*REC = MIN( ONE, REC*TJJ )USCAL = USCAL / TJJSEND IFIF( REC.LT.ONE ) THENCALL DSCAL( N, REC, X, 1 )SCALE = SCALE*RECXMAX = XMAX*RECEND IFEND IF*SUMJ = ZEROIF( USCAL.EQ.ONE ) THEN** If the scaling needed for A in the dot product is 1,* call DDOT to perform the dot product.*IF( UPPER ) THENSUMJ = DDOT( J-1, A( 1, J ), 1, X, 1 )ELSE IF( J.LT.N ) THENSUMJ = DDOT( N-J, A( J+1, J ), 1, X( J+1 ), 1 )END IFELSE** Otherwise, use in-line code for the dot product.*IF( UPPER ) THENDO 120 I = 1, J - 1SUMJ = SUMJ + ( A( I, J )*USCAL )*X( I )120 CONTINUEELSE IF( J.LT.N ) THENDO 130 I = J + 1, NSUMJ = SUMJ + ( A( I, J )*USCAL )*X( I )130 CONTINUEEND IFEND IF*IF( USCAL.EQ.TSCAL ) THEN** Compute x(j) := ( x(j) - sumj ) / A(j,j) if 1/A(j,j)* was not used to scale the dotproduct.*X( J ) = X( J ) - SUMJXJ = ABS( X( J ) )IF( NOUNIT ) THENTJJS = A( J, J )*TSCALELSETJJS = TSCALIF( TSCAL.EQ.ONE )$ GO TO 150END IF** Compute x(j) = x(j) / A(j,j), scaling if necessary.*TJJ = ABS( TJJS )IF( TJJ.GT.SMLNUM ) THEN** abs(A(j,j)) > SMLNUM:*IF( TJJ.LT.ONE ) THENIF( XJ.GT.TJJ*BIGNUM ) THEN** Scale X by 1/abs(x(j)).*REC = ONE / XJCALL DSCAL( N, REC, X, 1 )SCALE = SCALE*RECXMAX = XMAX*RECEND IFEND IFX( J ) = X( J ) / TJJSELSE IF( TJJ.GT.ZERO ) THEN** 0 < abs(A(j,j)) <= SMLNUM:*IF( XJ.GT.TJJ*BIGNUM ) THEN** Scale x by (1/abs(x(j)))*abs(A(j,j))*BIGNUM.*REC = ( TJJ*BIGNUM ) / XJCALL DSCAL( N, REC, X, 1 )SCALE = SCALE*RECXMAX = XMAX*RECEND IFX( J ) = X( J ) / TJJSELSE** A(j,j) = 0: Set x(1:n) = 0, x(j) = 1, and* scale = 0, and compute a solution to A'*x = 0.*DO 140 I = 1, NX( I ) = ZERO140 CONTINUEX( J ) = ONESCALE = ZEROXMAX = ZEROEND IF150 CONTINUEELSE** Compute x(j) := x(j) / A(j,j) - sumj if the dot* product has already been divided by 1/A(j,j).*X( J ) = X( J ) / TJJS - SUMJEND IFXMAX = MAX( XMAX, ABS( X( J ) ) )160 CONTINUEEND IFSCALE = SCALE / TSCALEND IF** Scale the column norms by 1/TSCAL for return.*IF( TSCAL.NE.ONE ) THENCALL DSCAL( N, ONE / TSCAL, CNORM, 1 )END IF*RETURN** End of DLATRS*ENDSUBROUTINE DORG2L( M, N, K, A, LDA, TAU, WORK, INFO )** -- LAPACK routine (version 3.0) --* Univ. of Tennessee, Univ. of California Berkeley, NAG Ltd.,* Courant Institute, Argonne National Lab, and Rice University* February 29, 1992** .. Scalar Arguments ..INTEGER INFO, K, LDA, M, N* ..* .. Array Arguments ..DOUBLE PRECISION A( LDA, * ), TAU( * ), WORK( * )* ..** Purpose* =======** DORG2L generates an m by n real matrix Q with orthonormal columns,* which is defined as the last n columns of a product of k elementary* reflectors of order m** Q = H(k) . . . H(2) H(1)** as returned by DGEQLF.** Arguments* =========** M (input) INTEGER* The number of rows of the matrix Q. M >= 0.** N (input) INTEGER* The number of columns of the matrix Q. M >= N >= 0.** K (input) INTEGER* The number of elementary reflectors whose product defines the* matrix Q. N >= K >= 0.** A (input/output) DOUBLE PRECISION array, dimension (LDA,N)* On entry, the (n-k+i)-th column must contain the vector which* defines the elementary reflector H(i), for i = 1,2,...,k, as* returned by DGEQLF in the last k columns of its array* argument A.* On exit, the m by n matrix Q.** LDA (input) INTEGER* The first dimension of the array A. LDA >= max(1,M).** TAU (input) DOUBLE PRECISION array, dimension (K)* TAU(i) must contain the scalar factor of the elementary* reflector H(i), as returned by DGEQLF.** WORK (workspace) DOUBLE PRECISION array, dimension (N)** INFO (output) INTEGER* = 0: successful exit* < 0: if INFO = -i, the i-th argument has an illegal value** =====================================================================** .. Parameters ..DOUBLE PRECISION ONE, ZEROPARAMETER ( ONE = 1.0D+0, ZERO = 0.0D+0 )* ..* .. Local Scalars ..INTEGER I, II, J, L* ..* .. External Subroutines ..EXTERNAL DLARF, DSCAL, XERBLA* ..* .. Intrinsic Functions ..INTRINSIC MAX* ..* .. Executable Statements ..** Test the input arguments*INFO = 0IF( M.LT.0 ) THENINFO = -1ELSE IF( N.LT.0 .OR. N.GT.M ) THENINFO = -2ELSE IF( K.LT.0 .OR. K.GT.N ) THENINFO = -3ELSE IF( LDA.LT.MAX( 1, M ) ) THENINFO = -5END IFIF( INFO.NE.0 ) THENCALL XERBLA( 'DORG2L', -INFO )RETURNEND IF** Quick return if possible*IF( N.LE.0 )$ RETURN** Initialise columns 1:n-k to columns of the unit matrix*DO 20 J = 1, N - KDO 10 L = 1, MA( L, J ) = ZERO10 CONTINUEA( M-N+J, J ) = ONE20 CONTINUE*DO 40 I = 1, KII = N - K + I** Apply H(i) to A(1:m-k+i,1:n-k+i) from the left*A( M-N+II, II ) = ONECALL DLARF( 'Left', M-N+II, II-1, A( 1, II ), 1, TAU( I ), A,$ LDA, WORK )CALL DSCAL( M-N+II-1, -TAU( I ), A( 1, II ), 1 )A( M-N+II, II ) = ONE - TAU( I )** Set A(m-k+i+1:m,n-k+i) to zero*DO 30 L = M - N + II + 1, MA( L, II ) = ZERO30 CONTINUE40 CONTINUERETURN** End of DORG2L*ENDSUBROUTINE DORG2R( M, N, K, A, LDA, TAU, WORK, INFO )** -- LAPACK routine (version 3.0) --* Univ. of Tennessee, Univ. of California Berkeley, NAG Ltd.,* Courant Institute, Argonne National Lab, and Rice University* February 29, 1992** .. Scalar Arguments ..INTEGER INFO, K, LDA, M, N* ..* .. Array Arguments ..DOUBLE PRECISION A( LDA, * ), TAU( * ), WORK( * )* ..** Purpose* =======** DORG2R generates an m by n real matrix Q with orthonormal columns,* which is defined as the first n columns of a product of k elementary* reflectors of order m** Q = H(1) H(2) . . . H(k)** as returned by DGEQRF.** Arguments* =========** M (input) INTEGER* The number of rows of the matrix Q. M >= 0.** N (input) INTEGER* The number of columns of the matrix Q. M >= N >= 0.** K (input) INTEGER* The number of elementary reflectors whose product defines the* matrix Q. N >= K >= 0.** A (input/output) DOUBLE PRECISION array, dimension (LDA,N)* On entry, the i-th column must contain the vector which* defines the elementary reflector H(i), for i = 1,2,...,k, as* returned by DGEQRF in the first k columns of its array* argument A.* On exit, the m-by-n matrix Q.** LDA (input) INTEGER* The first dimension of the array A. LDA >= max(1,M).** TAU (input) DOUBLE PRECISION array, dimension (K)* TAU(i) must contain the scalar factor of the elementary* reflector H(i), as returned by DGEQRF.** WORK (workspace) DOUBLE PRECISION array, dimension (N)** INFO (output) INTEGER* = 0: successful exit* < 0: if INFO = -i, the i-th argument has an illegal value** =====================================================================** .. Parameters ..DOUBLE PRECISION ONE, ZEROPARAMETER ( ONE = 1.0D+0, ZERO = 0.0D+0 )* ..* .. Local Scalars ..INTEGER I, J, L* ..* .. External Subroutines ..EXTERNAL DLARF, DSCAL, XERBLA* ..* .. Intrinsic Functions ..INTRINSIC MAX* ..* .. Executable Statements ..** Test the input arguments*INFO = 0IF( M.LT.0 ) THENINFO = -1ELSE IF( N.LT.0 .OR. N.GT.M ) THENINFO = -2ELSE IF( K.LT.0 .OR. K.GT.N ) THENINFO = -3ELSE IF( LDA.LT.MAX( 1, M ) ) THENINFO = -5END IFIF( INFO.NE.0 ) THENCALL XERBLA( 'DORG2R', -INFO )RETURNEND IF** Quick return if possible*IF( N.LE.0 )$ RETURN** Initialise columns k+1:n to columns of the unit matrix*DO 20 J = K + 1, NDO 10 L = 1, MA( L, J ) = ZERO10 CONTINUEA( J, J ) = ONE20 CONTINUE*DO 40 I = K, 1, -1** Apply H(i) to A(i:m,i:n) from the left*IF( I.LT.N ) THENA( I, I ) = ONECALL DLARF( 'Left', M-I+1, N-I, A( I, I ), 1, TAU( I ),$ A( I, I+1 ), LDA, WORK )END IFIF( I.LT.M )$ CALL DSCAL( M-I, -TAU( I ), A( I+1, I ), 1 )A( I, I ) = ONE - TAU( I )** Set A(1:i-1,i) to zero*DO 30 L = 1, I - 1A( L, I ) = ZERO30 CONTINUE40 CONTINUERETURN** End of DORG2R*ENDSUBROUTINE DORGBR( VECT, M, N, K, A, LDA, TAU, WORK, LWORK, INFO )** -- LAPACK routine (version 3.0) --* Univ. of Tennessee, Univ. of California Berkeley, NAG Ltd.,* Courant Institute, Argonne National Lab, and Rice University* June 30, 1999** .. Scalar Arguments ..CHARACTER VECTINTEGER INFO, K, LDA, LWORK, M, N* ..* .. Array Arguments ..DOUBLE PRECISION A( LDA, * ), TAU( * ), WORK( * )* ..** Purpose* =======** DORGBR generates one of the real orthogonal matrices Q or P**T* determined by DGEBRD when reducing a real matrix A to bidiagonal* form: A = Q * B * P**T. Q and P**T are defined as products of* elementary reflectors H(i) or G(i) respectively.** If VECT = 'Q', A is assumed to have been an M-by-K matrix, and Q* is of order M:* if m >= k, Q = H(1) H(2) . . . H(k) and DORGBR returns the first n* columns of Q, where m >= n >= k;* if m < k, Q = H(1) H(2) . . . H(m-1) and DORGBR returns Q as an* M-by-M matrix.** If VECT = 'P', A is assumed to have been a K-by-N matrix, and P**T* is of order N:* if k < n, P**T = G(k) . . . G(2) G(1) and DORGBR returns the first m* rows of P**T, where n >= m >= k;* if k >= n, P**T = G(n-1) . . . G(2) G(1) and DORGBR returns P**T as* an N-by-N matrix.** Arguments* =========** VECT (input) CHARACTER*1* Specifies whether the matrix Q or the matrix P**T is* required, as defined in the transformation applied by DGEBRD:* = 'Q': generate Q;* = 'P': generate P**T.** M (input) INTEGER* The number of rows of the matrix Q or P**T to be returned.* M >= 0.** N (input) INTEGER* The number of columns of the matrix Q or P**T to be returned.* N >= 0.* If VECT = 'Q', M >= N >= min(M,K);* if VECT = 'P', N >= M >= min(N,K).** K (input) INTEGER* If VECT = 'Q', the number of columns in the original M-by-K* matrix reduced by DGEBRD.* If VECT = 'P', the number of rows in the original K-by-N* matrix reduced by DGEBRD.* K >= 0.** A (input/output) DOUBLE PRECISION array, dimension (LDA,N)* On entry, the vectors which define the elementary reflectors,* as returned by DGEBRD.* On exit, the M-by-N matrix Q or P**T.** LDA (input) INTEGER* The leading dimension of the array A. LDA >= max(1,M).** TAU (input) DOUBLE PRECISION array, dimension* (min(M,K)) if VECT = 'Q'* (min(N,K)) if VECT = 'P'* TAU(i) must contain the scalar factor of the elementary* reflector H(i) or G(i), which determines Q or P**T, as* returned by DGEBRD in its array argument TAUQ or TAUP.** WORK (workspace/output) DOUBLE PRECISION array, dimension (LWORK)* On exit, if INFO = 0, WORK(1) returns the optimal LWORK.** LWORK (input) INTEGER* The dimension of the array WORK. LWORK >= max(1,min(M,N)).* For optimum performance LWORK >= min(M,N)*NB, where NB* is the optimal blocksize.** If LWORK = -1, then a workspace query is assumed; the routine* only calculates the optimal size of the WORK array, returns* this value as the first entry of the WORK array, and no error* message related to LWORK is issued by XERBLA.** INFO (output) INTEGER* = 0: successful exit* < 0: if INFO = -i, the i-th argument had an illegal value** =====================================================================** .. Parameters ..DOUBLE PRECISION ZERO, ONEPARAMETER ( ZERO = 0.0D+0, ONE = 1.0D+0 )* ..* .. Local Scalars ..LOGICAL LQUERY, WANTQINTEGER I, IINFO, J, LWKOPT, MN, NB* ..* .. External Functions ..LOGICAL LSAMEINTEGER ILAENVEXTERNAL LSAME, ILAENV* ..* .. External Subroutines ..EXTERNAL DORGLQ, DORGQR, XERBLA* ..* .. Intrinsic Functions ..INTRINSIC MAX, MIN* ..* .. Executable Statements ..** Test the input arguments*INFO = 0WANTQ = LSAME( VECT, 'Q' )MN = MIN( M, N )LQUERY = ( LWORK.EQ.-1 )IF( .NOT.WANTQ .AND. .NOT.LSAME( VECT, 'P' ) ) THENINFO = -1ELSE IF( M.LT.0 ) THENINFO = -2ELSE IF( N.LT.0 .OR. ( WANTQ .AND. ( N.GT.M .OR. N.LT.MIN( M,$ K ) ) ) .OR. ( .NOT.WANTQ .AND. ( M.GT.N .OR. M.LT.$ MIN( N, K ) ) ) ) THENINFO = -3ELSE IF( K.LT.0 ) THENINFO = -4ELSE IF( LDA.LT.MAX( 1, M ) ) THENINFO = -6ELSE IF( LWORK.LT.MAX( 1, MN ) .AND. .NOT.LQUERY ) THENINFO = -9END IF*IF( INFO.EQ.0 ) THENIF( WANTQ ) THENNB = ILAENV( 1, 'DORGQR', ' ', M, N, K, -1 )ELSENB = ILAENV( 1, 'DORGLQ', ' ', M, N, K, -1 )END IFLWKOPT = MAX( 1, MN )*NBWORK( 1 ) = LWKOPTEND IF*IF( INFO.NE.0 ) THENCALL XERBLA( 'DORGBR', -INFO )RETURNELSE IF( LQUERY ) THENRETURNEND IF** Quick return if possible*IF( M.EQ.0 .OR. N.EQ.0 ) THENWORK( 1 ) = 1RETURNEND IF*IF( WANTQ ) THEN** Form Q, determined by a call to DGEBRD to reduce an m-by-k* matrix*IF( M.GE.K ) THEN** If m >= k, assume m >= n >= k*CALL DORGQR( M, N, K, A, LDA, TAU, WORK, LWORK, IINFO )*ELSE** If m < k, assume m = n** Shift the vectors which define the elementary reflectors one* column to the right, and set the first row and column of Q* to those of the unit matrix*DO 20 J = M, 2, -1A( 1, J ) = ZERODO 10 I = J + 1, MA( I, J ) = A( I, J-1 )10 CONTINUE20 CONTINUEA( 1, 1 ) = ONEDO 30 I = 2, MA( I, 1 ) = ZERO30 CONTINUEIF( M.GT.1 ) THEN** Form Q(2:m,2:m)*CALL DORGQR( M-1, M-1, M-1, A( 2, 2 ), LDA, TAU, WORK,$ LWORK, IINFO )END IFEND IFELSE** Form P', determined by a call to DGEBRD to reduce a k-by-n* matrix*IF( K.LT.N ) THEN** If k < n, assume k <= m <= n*CALL DORGLQ( M, N, K, A, LDA, TAU, WORK, LWORK, IINFO )*ELSE** If k >= n, assume m = n** Shift the vectors which define the elementary reflectors one* row downward, and set the first row and column of P' to* those of the unit matrix*A( 1, 1 ) = ONEDO 40 I = 2, NA( I, 1 ) = ZERO40 CONTINUEDO 60 J = 2, NDO 50 I = J - 1, 2, -1A( I, J ) = A( I-1, J )50 CONTINUEA( 1, J ) = ZERO60 CONTINUEIF( N.GT.1 ) THEN** Form P'(2:n,2:n)*CALL DORGLQ( N-1, N-1, N-1, A( 2, 2 ), LDA, TAU, WORK,$ LWORK, IINFO )END IFEND IFEND IFWORK( 1 ) = LWKOPTRETURN** End of DORGBR*ENDSUBROUTINE DORGHR( N, ILO, IHI, A, LDA, TAU, WORK, LWORK, INFO )** -- LAPACK routine (version 3.0) --* Univ. of Tennessee, Univ. of California Berkeley, NAG Ltd.,* Courant Institute, Argonne National Lab, and Rice University* June 30, 1999** .. Scalar Arguments ..INTEGER IHI, ILO, INFO, LDA, LWORK, N* ..* .. Array Arguments ..DOUBLE PRECISION A( LDA, * ), TAU( * ), WORK( * )* ..** Purpose* =======** DORGHR generates a real orthogonal matrix Q which is defined as the* product of IHI-ILO elementary reflectors of order N, as returned by* DGEHRD:** Q = H(ilo) H(ilo+1) . . . H(ihi-1).** Arguments* =========** N (input) INTEGER* The order of the matrix Q. N >= 0.** ILO (input) INTEGER* IHI (input) INTEGER* ILO and IHI must have the same values as in the previous call* of DGEHRD. Q is equal to the unit matrix except in the* submatrix Q(ilo+1:ihi,ilo+1:ihi).* 1 <= ILO <= IHI <= N, if N > 0; ILO=1 and IHI=0, if N=0.** A (input/output) DOUBLE PRECISION array, dimension (LDA,N)* On entry, the vectors which define the elementary reflectors,* as returned by DGEHRD.* On exit, the N-by-N orthogonal matrix Q.** LDA (input) INTEGER* The leading dimension of the array A. LDA >= max(1,N).** TAU (input) DOUBLE PRECISION array, dimension (N-1)* TAU(i) must contain the scalar factor of the elementary* reflector H(i), as returned by DGEHRD.** WORK (workspace/output) DOUBLE PRECISION array, dimension (LWORK)* On exit, if INFO = 0, WORK(1) returns the optimal LWORK.** LWORK (input) INTEGER* The dimension of the array WORK. LWORK >= IHI-ILO.* For optimum performance LWORK >= (IHI-ILO)*NB, where NB is* the optimal blocksize.** If LWORK = -1, then a workspace query is assumed; the routine* only calculates the optimal size of the WORK array, returns* this value as the first entry of the WORK array, and no error* message related to LWORK is issued by XERBLA.** INFO (output) INTEGER* = 0: successful exit* < 0: if INFO = -i, the i-th argument had an illegal value** =====================================================================** .. Parameters ..DOUBLE PRECISION ZERO, ONEPARAMETER ( ZERO = 0.0D+0, ONE = 1.0D+0 )* ..* .. Local Scalars ..LOGICAL LQUERYINTEGER I, IINFO, J, LWKOPT, NB, NH* ..* .. External Subroutines ..EXTERNAL DORGQR, XERBLA* ..* .. External Functions ..INTEGER ILAENVEXTERNAL ILAENV* ..* .. Intrinsic Functions ..INTRINSIC MAX, MIN* ..* .. Executable Statements ..** Test the input arguments*INFO = 0NH = IHI - ILOLQUERY = ( LWORK.EQ.-1 )IF( N.LT.0 ) THENINFO = -1ELSE IF( ILO.LT.1 .OR. ILO.GT.MAX( 1, N ) ) THENINFO = -2ELSE IF( IHI.LT.MIN( ILO, N ) .OR. IHI.GT.N ) THENINFO = -3ELSE IF( LDA.LT.MAX( 1, N ) ) THENINFO = -5ELSE IF( LWORK.LT.MAX( 1, NH ) .AND. .NOT.LQUERY ) THENINFO = -8END IF*IF( INFO.EQ.0 ) THENNB = ILAENV( 1, 'DORGQR', ' ', NH, NH, NH, -1 )LWKOPT = MAX( 1, NH )*NBWORK( 1 ) = LWKOPTEND IF*IF( INFO.NE.0 ) THENCALL XERBLA( 'DORGHR', -INFO )RETURNELSE IF( LQUERY ) THENRETURNEND IF** Quick return if possible*IF( N.EQ.0 ) THENWORK( 1 ) = 1RETURNEND IF** Shift the vectors which define the elementary reflectors one* column to the right, and set the first ilo and the last n-ihi* rows and columns to those of the unit matrix*DO 40 J = IHI, ILO + 1, -1DO 10 I = 1, J - 1A( I, J ) = ZERO10 CONTINUEDO 20 I = J + 1, IHIA( I, J ) = A( I, J-1 )20 CONTINUEDO 30 I = IHI + 1, NA( I, J ) = ZERO30 CONTINUE40 CONTINUEDO 60 J = 1, ILODO 50 I = 1, NA( I, J ) = ZERO50 CONTINUEA( J, J ) = ONE60 CONTINUEDO 80 J = IHI + 1, NDO 70 I = 1, NA( I, J ) = ZERO70 CONTINUEA( J, J ) = ONE80 CONTINUE*IF( NH.GT.0 ) THEN** Generate Q(ilo+1:ihi,ilo+1:ihi)*CALL DORGQR( NH, NH, NH, A( ILO+1, ILO+1 ), LDA, TAU( ILO ),$ WORK, LWORK, IINFO )END IFWORK( 1 ) = LWKOPTRETURN** End of DORGHR*ENDSUBROUTINE DORGL2( M, N, K, A, LDA, TAU, WORK, INFO )** -- LAPACK routine (version 3.0) --* Univ. of Tennessee, Univ. of California Berkeley, NAG Ltd.,* Courant Institute, Argonne National Lab, and Rice University* June 30, 1999** .. Scalar Arguments ..INTEGER INFO, K, LDA, M, N* ..* .. Array Arguments ..DOUBLE PRECISION A( LDA, * ), TAU( * ), WORK( * )* ..** Purpose* =======** DORGL2 generates an m by n real matrix Q with orthonormal rows,* which is defined as the first m rows of a product of k elementary* reflectors of order n** Q = H(k) . . . H(2) H(1)** as returned by DGELQF.** Arguments* =========** M (input) INTEGER* The number of rows of the matrix Q. M >= 0.** N (input) INTEGER* The number of columns of the matrix Q. N >= M.** K (input) INTEGER* The number of elementary reflectors whose product defines the* matrix Q. M >= K >= 0.** A (input/output) DOUBLE PRECISION array, dimension (LDA,N)* On entry, the i-th row must contain the vector which defines* the elementary reflector H(i), for i = 1,2,...,k, as returned* by DGELQF in the first k rows of its array argument A.* On exit, the m-by-n matrix Q.** LDA (input) INTEGER* The first dimension of the array A. LDA >= max(1,M).** TAU (input) DOUBLE PRECISION array, dimension (K)* TAU(i) must contain the scalar factor of the elementary* reflector H(i), as returned by DGELQF.** WORK (workspace) DOUBLE PRECISION array, dimension (M)** INFO (output) INTEGER* = 0: successful exit* < 0: if INFO = -i, the i-th argument has an illegal value** =====================================================================** .. Parameters ..DOUBLE PRECISION ONE, ZEROPARAMETER ( ONE = 1.0D+0, ZERO = 0.0D+0 )* ..* .. Local Scalars ..INTEGER I, J, L* ..* .. External Subroutines ..EXTERNAL DLARF, DSCAL, XERBLA* ..* .. Intrinsic Functions ..INTRINSIC MAX* ..* .. Executable Statements ..** Test the input arguments*INFO = 0IF( M.LT.0 ) THENINFO = -1ELSE IF( N.LT.M ) THENINFO = -2ELSE IF( K.LT.0 .OR. K.GT.M ) THENINFO = -3ELSE IF( LDA.LT.MAX( 1, M ) ) THENINFO = -5END IFIF( INFO.NE.0 ) THENCALL XERBLA( 'DORGL2', -INFO )RETURNEND IF** Quick return if possible*IF( M.LE.0 )$ RETURN*IF( K.LT.M ) THEN** Initialise rows k+1:m to rows of the unit matrix*DO 20 J = 1, NDO 10 L = K + 1, MA( L, J ) = ZERO10 CONTINUEIF( J.GT.K .AND. J.LE.M )$ A( J, J ) = ONE20 CONTINUEEND IF*DO 40 I = K, 1, -1** Apply H(i) to A(i:m,i:n) from the right*IF( I.LT.N ) THENIF( I.LT.M ) THENA( I, I ) = ONECALL DLARF( 'Right', M-I, N-I+1, A( I, I ), LDA,$ TAU( I ), A( I+1, I ), LDA, WORK )END IFCALL DSCAL( N-I, -TAU( I ), A( I, I+1 ), LDA )END IFA( I, I ) = ONE - TAU( I )** Set A(i,1:i-1) to zero*DO 30 L = 1, I - 1A( I, L ) = ZERO30 CONTINUE40 CONTINUERETURN** End of DORGL2*ENDSUBROUTINE DORGLQ( M, N, K, A, LDA, TAU, WORK, LWORK, INFO )** -- LAPACK routine (version 3.0) --* Univ. of Tennessee, Univ. of California Berkeley, NAG Ltd.,* Courant Institute, Argonne National Lab, and Rice University* June 30, 1999** .. Scalar Arguments ..INTEGER INFO, K, LDA, LWORK, M, N* ..* .. Array Arguments ..DOUBLE PRECISION A( LDA, * ), TAU( * ), WORK( * )* ..** Purpose* =======** DORGLQ generates an M-by-N real matrix Q with orthonormal rows,* which is defined as the first M rows of a product of K elementary* reflectors of order N** Q = H(k) . . . H(2) H(1)** as returned by DGELQF.** Arguments* =========** M (input) INTEGER* The number of rows of the matrix Q. M >= 0.** N (input) INTEGER* The number of columns of the matrix Q. N >= M.** K (input) INTEGER* The number of elementary reflectors whose product defines the* matrix Q. M >= K >= 0.** A (input/output) DOUBLE PRECISION array, dimension (LDA,N)* On entry, the i-th row must contain the vector which defines* the elementary reflector H(i), for i = 1,2,...,k, as returned* by DGELQF in the first k rows of its array argument A.* On exit, the M-by-N matrix Q.** LDA (input) INTEGER* The first dimension of the array A. LDA >= max(1,M).** TAU (input) DOUBLE PRECISION array, dimension (K)* TAU(i) must contain the scalar factor of the elementary* reflector H(i), as returned by DGELQF.** WORK (workspace/output) DOUBLE PRECISION array, dimension (LWORK)* On exit, if INFO = 0, WORK(1) returns the optimal LWORK.** LWORK (input) INTEGER* The dimension of the array WORK. LWORK >= max(1,M).* For optimum performance LWORK >= M*NB, where NB is* the optimal blocksize.** If LWORK = -1, then a workspace query is assumed; the routine* only calculates the optimal size of the WORK array, returns* this value as the first entry of the WORK array, and no error* message related to LWORK is issued by XERBLA.** INFO (output) INTEGER* = 0: successful exit* < 0: if INFO = -i, the i-th argument has an illegal value** =====================================================================** .. Parameters ..DOUBLE PRECISION ZEROPARAMETER ( ZERO = 0.0D+0 )* ..* .. Local Scalars ..LOGICAL LQUERYINTEGER I, IB, IINFO, IWS, J, KI, KK, L, LDWORK,$ LWKOPT, NB, NBMIN, NX* ..* .. External Subroutines ..EXTERNAL DLARFB, DLARFT, DORGL2, XERBLA* ..* .. Intrinsic Functions ..INTRINSIC MAX, MIN* ..* .. External Functions ..INTEGER ILAENVEXTERNAL ILAENV* ..* .. Executable Statements ..** Test the input arguments*INFO = 0NB = ILAENV( 1, 'DORGLQ', ' ', M, N, K, -1 )LWKOPT = MAX( 1, M )*NBWORK( 1 ) = LWKOPTLQUERY = ( LWORK.EQ.-1 )IF( M.LT.0 ) THENINFO = -1ELSE IF( N.LT.M ) THENINFO = -2ELSE IF( K.LT.0 .OR. K.GT.M ) THENINFO = -3ELSE IF( LDA.LT.MAX( 1, M ) ) THENINFO = -5ELSE IF( LWORK.LT.MAX( 1, M ) .AND. .NOT.LQUERY ) THENINFO = -8END IFIF( INFO.NE.0 ) THENCALL XERBLA( 'DORGLQ', -INFO )RETURNELSE IF( LQUERY ) THENRETURNEND IF** Quick return if possible*IF( M.LE.0 ) THENWORK( 1 ) = 1RETURNEND IF*NBMIN = 2NX = 0IWS = MIF( NB.GT.1 .AND. NB.LT.K ) THEN** Determine when to cross over from blocked to unblocked code.*NX = MAX( 0, ILAENV( 3, 'DORGLQ', ' ', M, N, K, -1 ) )IF( NX.LT.K ) THEN** Determine if workspace is large enough for blocked code.*LDWORK = MIWS = LDWORK*NBIF( LWORK.LT.IWS ) THEN** Not enough workspace to use optimal NB: reduce NB and* determine the minimum value of NB.*NB = LWORK / LDWORKNBMIN = MAX( 2, ILAENV( 2, 'DORGLQ', ' ', M, N, K, -1 ) )END IFEND IFEND IF*IF( NB.GE.NBMIN .AND. NB.LT.K .AND. NX.LT.K ) THEN** Use blocked code after the last block.* The first kk rows are handled by the block method.*KI = ( ( K-NX-1 ) / NB )*NBKK = MIN( K, KI+NB )** Set A(kk+1:m,1:kk) to zero.*DO 20 J = 1, KKDO 10 I = KK + 1, MA( I, J ) = ZERO10 CONTINUE20 CONTINUEELSEKK = 0END IF** Use unblocked code for the last or only block.*IF( KK.LT.M )$ CALL DORGL2( M-KK, N-KK, K-KK, A( KK+1, KK+1 ), LDA,$ TAU( KK+1 ), WORK, IINFO )*IF( KK.GT.0 ) THEN** Use blocked code*DO 50 I = KI + 1, 1, -NBIB = MIN( NB, K-I+1 )IF( I+IB.LE.M ) THEN** Form the triangular factor of the block reflector* H = H(i) H(i+1) . . . H(i+ib-1)*CALL DLARFT( 'Forward', 'Rowwise', N-I+1, IB, A( I, I ),$ LDA, TAU( I ), WORK, LDWORK )** Apply H' to A(i+ib:m,i:n) from the right*CALL DLARFB( 'Right', 'Transpose', 'Forward', 'Rowwise',$ M-I-IB+1, N-I+1, IB, A( I, I ), LDA, WORK,$ LDWORK, A( I+IB, I ), LDA, WORK( IB+1 ),$ LDWORK )END IF** Apply H' to columns i:n of current block*CALL DORGL2( IB, N-I+1, IB, A( I, I ), LDA, TAU( I ), WORK,$ IINFO )** Set columns 1:i-1 of current block to zero*DO 40 J = 1, I - 1DO 30 L = I, I + IB - 1A( L, J ) = ZERO30 CONTINUE40 CONTINUE50 CONTINUEEND IF*WORK( 1 ) = IWSRETURN** End of DORGLQ*ENDSUBROUTINE DORGQL( M, N, K, A, LDA, TAU, WORK, LWORK, INFO )** -- LAPACK routine (version 3.0) --* Univ. of Tennessee, Univ. of California Berkeley, NAG Ltd.,* Courant Institute, Argonne National Lab, and Rice University* June 30, 1999** .. Scalar Arguments ..INTEGER INFO, K, LDA, LWORK, M, N* ..* .. Array Arguments ..DOUBLE PRECISION A( LDA, * ), TAU( * ), WORK( * )* ..** Purpose* =======** DORGQL generates an M-by-N real matrix Q with orthonormal columns,* which is defined as the last N columns of a product of K elementary* reflectors of order M** Q = H(k) . . . H(2) H(1)** as returned by DGEQLF.** Arguments* =========** M (input) INTEGER* The number of rows of the matrix Q. M >= 0.** N (input) INTEGER* The number of columns of the matrix Q. M >= N >= 0.** K (input) INTEGER* The number of elementary reflectors whose product defines the* matrix Q. N >= K >= 0.** A (input/output) DOUBLE PRECISION array, dimension (LDA,N)* On entry, the (n-k+i)-th column must contain the vector which* defines the elementary reflector H(i), for i = 1,2,...,k, as* returned by DGEQLF in the last k columns of its array* argument A.* On exit, the M-by-N matrix Q.** LDA (input) INTEGER* The first dimension of the array A. LDA >= max(1,M).** TAU (input) DOUBLE PRECISION array, dimension (K)* TAU(i) must contain the scalar factor of the elementary* reflector H(i), as returned by DGEQLF.** WORK (workspace/output) DOUBLE PRECISION array, dimension (LWORK)* On exit, if INFO = 0, WORK(1) returns the optimal LWORK.** LWORK (input) INTEGER* The dimension of the array WORK. LWORK >= max(1,N).* For optimum performance LWORK >= N*NB, where NB is the* optimal blocksize.** If LWORK = -1, then a workspace query is assumed; the routine* only calculates the optimal size of the WORK array, returns* this value as the first entry of the WORK array, and no error* message related to LWORK is issued by XERBLA.** INFO (output) INTEGER* = 0: successful exit* < 0: if INFO = -i, the i-th argument has an illegal value** =====================================================================** .. Parameters ..DOUBLE PRECISION ZEROPARAMETER ( ZERO = 0.0D+0 )* ..* .. Local Scalars ..LOGICAL LQUERYINTEGER I, IB, IINFO, IWS, J, KK, L, LDWORK, LWKOPT,$ NB, NBMIN, NX* ..* .. External Subroutines ..EXTERNAL DLARFB, DLARFT, DORG2L, XERBLA* ..* .. Intrinsic Functions ..INTRINSIC MAX, MIN* ..* .. External Functions ..INTEGER ILAENVEXTERNAL ILAENV* ..* .. Executable Statements ..** Test the input arguments*INFO = 0NB = ILAENV( 1, 'DORGQL', ' ', M, N, K, -1 )LWKOPT = MAX( 1, N )*NBWORK( 1 ) = LWKOPTLQUERY = ( LWORK.EQ.-1 )IF( M.LT.0 ) THENINFO = -1ELSE IF( N.LT.0 .OR. N.GT.M ) THENINFO = -2ELSE IF( K.LT.0 .OR. K.GT.N ) THENINFO = -3ELSE IF( LDA.LT.MAX( 1, M ) ) THENINFO = -5ELSE IF( LWORK.LT.MAX( 1, N ) .AND. .NOT.LQUERY ) THENINFO = -8END IFIF( INFO.NE.0 ) THENCALL XERBLA( 'DORGQL', -INFO )RETURNELSE IF( LQUERY ) THENRETURNEND IF** Quick return if possible*IF( N.LE.0 ) THENWORK( 1 ) = 1RETURNEND IF*NBMIN = 2NX = 0IWS = NIF( NB.GT.1 .AND. NB.LT.K ) THEN** Determine when to cross over from blocked to unblocked code.*NX = MAX( 0, ILAENV( 3, 'DORGQL', ' ', M, N, K, -1 ) )IF( NX.LT.K ) THEN** Determine if workspace is large enough for blocked code.*LDWORK = NIWS = LDWORK*NBIF( LWORK.LT.IWS ) THEN** Not enough workspace to use optimal NB: reduce NB and* determine the minimum value of NB.*NB = LWORK / LDWORKNBMIN = MAX( 2, ILAENV( 2, 'DORGQL', ' ', M, N, K, -1 ) )END IFEND IFEND IF*IF( NB.GE.NBMIN .AND. NB.LT.K .AND. NX.LT.K ) THEN** Use blocked code after the first block.* The last kk columns are handled by the block method.*KK = MIN( K, ( ( K-NX+NB-1 ) / NB )*NB )** Set A(m-kk+1:m,1:n-kk) to zero.*DO 20 J = 1, N - KKDO 10 I = M - KK + 1, MA( I, J ) = ZERO10 CONTINUE20 CONTINUEELSEKK = 0END IF** Use unblocked code for the first or only block.*CALL DORG2L( M-KK, N-KK, K-KK, A, LDA, TAU, WORK, IINFO )*IF( KK.GT.0 ) THEN** Use blocked code*DO 50 I = K - KK + 1, K, NBIB = MIN( NB, K-I+1 )IF( N-K+I.GT.1 ) THEN** Form the triangular factor of the block reflector* H = H(i+ib-1) . . . H(i+1) H(i)*CALL DLARFT( 'Backward', 'Columnwise', M-K+I+IB-1, IB,$ A( 1, N-K+I ), LDA, TAU( I ), WORK, LDWORK )** Apply H to A(1:m-k+i+ib-1,1:n-k+i-1) from the left*CALL DLARFB( 'Left', 'No transpose', 'Backward',$ 'Columnwise', M-K+I+IB-1, N-K+I-1, IB,$ A( 1, N-K+I ), LDA, WORK, LDWORK, A, LDA,$ WORK( IB+1 ), LDWORK )END IF** Apply H to rows 1:m-k+i+ib-1 of current block*CALL DORG2L( M-K+I+IB-1, IB, IB, A( 1, N-K+I ), LDA,$ TAU( I ), WORK, IINFO )** Set rows m-k+i+ib:m of current block to zero*DO 40 J = N - K + I, N - K + I + IB - 1DO 30 L = M - K + I + IB, MA( L, J ) = ZERO30 CONTINUE40 CONTINUE50 CONTINUEEND IF*WORK( 1 ) = IWSRETURN** End of DORGQL*ENDSUBROUTINE DORGQR( M, N, K, A, LDA, TAU, WORK, LWORK, INFO )** -- LAPACK routine (version 3.0) --* Univ. of Tennessee, Univ. of California Berkeley, NAG Ltd.,* Courant Institute, Argonne National Lab, and Rice University* June 30, 1999** .. Scalar Arguments ..INTEGER INFO, K, LDA, LWORK, M, N* ..* .. Array Arguments ..DOUBLE PRECISION A( LDA, * ), TAU( * ), WORK( * )* ..** Purpose* =======** DORGQR generates an M-by-N real matrix Q with orthonormal columns,* which is defined as the first N columns of a product of K elementary* reflectors of order M** Q = H(1) H(2) . . . H(k)** as returned by DGEQRF.** Arguments* =========** M (input) INTEGER* The number of rows of the matrix Q. M >= 0.** N (input) INTEGER* The number of columns of the matrix Q. M >= N >= 0.** K (input) INTEGER* The number of elementary reflectors whose product defines the* matrix Q. N >= K >= 0.** A (input/output) DOUBLE PRECISION array, dimension (LDA,N)* On entry, the i-th column must contain the vector which* defines the elementary reflector H(i), for i = 1,2,...,k, as* returned by DGEQRF in the first k columns of its array* argument A.* On exit, the M-by-N matrix Q.** LDA (input) INTEGER* The first dimension of the array A. LDA >= max(1,M).** TAU (input) DOUBLE PRECISION array, dimension (K)* TAU(i) must contain the scalar factor of the elementary* reflector H(i), as returned by DGEQRF.** WORK (workspace/output) DOUBLE PRECISION array, dimension (LWORK)* On exit, if INFO = 0, WORK(1) returns the optimal LWORK.** LWORK (input) INTEGER* The dimension of the array WORK. LWORK >= max(1,N).* For optimum performance LWORK >= N*NB, where NB is the* optimal blocksize.** If LWORK = -1, then a workspace query is assumed; the routine* only calculates the optimal size of the WORK array, returns* this value as the first entry of the WORK array, and no error* message related to LWORK is issued by XERBLA.** INFO (output) INTEGER* = 0: successful exit* < 0: if INFO = -i, the i-th argument has an illegal value** =====================================================================** .. Parameters ..DOUBLE PRECISION ZEROPARAMETER ( ZERO = 0.0D+0 )* ..* .. Local Scalars ..LOGICAL LQUERYINTEGER I, IB, IINFO, IWS, J, KI, KK, L, LDWORK,$ LWKOPT, NB, NBMIN, NX* ..* .. External Subroutines ..EXTERNAL DLARFB, DLARFT, DORG2R, XERBLA* ..* .. Intrinsic Functions ..INTRINSIC MAX, MIN* ..* .. External Functions ..INTEGER ILAENVEXTERNAL ILAENV* ..* .. Executable Statements ..** Test the input arguments*INFO = 0NB = ILAENV( 1, 'DORGQR', ' ', M, N, K, -1 )LWKOPT = MAX( 1, N )*NBWORK( 1 ) = LWKOPTLQUERY = ( LWORK.EQ.-1 )IF( M.LT.0 ) THENINFO = -1ELSE IF( N.LT.0 .OR. N.GT.M ) THENINFO = -2ELSE IF( K.LT.0 .OR. K.GT.N ) THENINFO = -3ELSE IF( LDA.LT.MAX( 1, M ) ) THENINFO = -5ELSE IF( LWORK.LT.MAX( 1, N ) .AND. .NOT.LQUERY ) THENINFO = -8END IFIF( INFO.NE.0 ) THENCALL XERBLA( 'DORGQR', -INFO )RETURNELSE IF( LQUERY ) THENRETURNEND IF** Quick return if possible*IF( N.LE.0 ) THENWORK( 1 ) = 1RETURNEND IF*NBMIN = 2NX = 0IWS = NIF( NB.GT.1 .AND. NB.LT.K ) THEN** Determine when to cross over from blocked to unblocked code.*NX = MAX( 0, ILAENV( 3, 'DORGQR', ' ', M, N, K, -1 ) )IF( NX.LT.K ) THEN** Determine if workspace is large enough for blocked code.*LDWORK = NIWS = LDWORK*NBIF( LWORK.LT.IWS ) THEN** Not enough workspace to use optimal NB: reduce NB and* determine the minimum value of NB.*NB = LWORK / LDWORKNBMIN = MAX( 2, ILAENV( 2, 'DORGQR', ' ', M, N, K, -1 ) )END IFEND IFEND IF*IF( NB.GE.NBMIN .AND. NB.LT.K .AND. NX.LT.K ) THEN** Use blocked code after the last block.* The first kk columns are handled by the block method.*KI = ( ( K-NX-1 ) / NB )*NBKK = MIN( K, KI+NB )** Set A(1:kk,kk+1:n) to zero.*DO 20 J = KK + 1, NDO 10 I = 1, KKA( I, J ) = ZERO10 CONTINUE20 CONTINUEELSEKK = 0END IF** Use unblocked code for the last or only block.*IF( KK.LT.N )$ CALL DORG2R( M-KK, N-KK, K-KK, A( KK+1, KK+1 ), LDA,$ TAU( KK+1 ), WORK, IINFO )*IF( KK.GT.0 ) THEN** Use blocked code*DO 50 I = KI + 1, 1, -NBIB = MIN( NB, K-I+1 )IF( I+IB.LE.N ) THEN** Form the triangular factor of the block reflector* H = H(i) H(i+1) . . . H(i+ib-1)*CALL DLARFT( 'Forward', 'Columnwise', M-I+1, IB,$ A( I, I ), LDA, TAU( I ), WORK, LDWORK )** Apply H to A(i:m,i+ib:n) from the left*CALL DLARFB( 'Left', 'No transpose', 'Forward',$ 'Columnwise', M-I+1, N-I-IB+1, IB,$ A( I, I ), LDA, WORK, LDWORK, A( I, I+IB ),$ LDA, WORK( IB+1 ), LDWORK )END IF** Apply H to rows i:m of current block*CALL DORG2R( M-I+1, IB, IB, A( I, I ), LDA, TAU( I ), WORK,$ IINFO )** Set rows 1:i-1 of current block to zero*DO 40 J = I, I + IB - 1DO 30 L = 1, I - 1A( L, J ) = ZERO30 CONTINUE40 CONTINUE50 CONTINUEEND IF*WORK( 1 ) = IWSRETURN** End of DORGQR*ENDSUBROUTINE DORGTR( UPLO, N, A, LDA, TAU, WORK, LWORK, INFO )** -- LAPACK routine (version 3.0) --* Univ. of Tennessee, Univ. of California Berkeley, NAG Ltd.,* Courant Institute, Argonne National Lab, and Rice University* June 30, 1999** .. Scalar Arguments ..CHARACTER UPLOINTEGER INFO, LDA, LWORK, N* ..* .. Array Arguments ..DOUBLE PRECISION A( LDA, * ), TAU( * ), WORK( * )* ..** Purpose* =======** DORGTR generates a real orthogonal matrix Q which is defined as the* product of n-1 elementary reflectors of order N, as returned by* DSYTRD:** if UPLO = 'U', Q = H(n-1) . . . H(2) H(1),** if UPLO = 'L', Q = H(1) H(2) . . . H(n-1).** Arguments* =========** UPLO (input) CHARACTER*1* = 'U': Upper triangle of A contains elementary reflectors* from DSYTRD;* = 'L': Lower triangle of A contains elementary reflectors* from DSYTRD.** N (input) INTEGER* The order of the matrix Q. N >= 0.** A (input/output) DOUBLE PRECISION array, dimension (LDA,N)* On entry, the vectors which define the elementary reflectors,* as returned by DSYTRD.* On exit, the N-by-N orthogonal matrix Q.** LDA (input) INTEGER* The leading dimension of the array A. LDA >= max(1,N).** TAU (input) DOUBLE PRECISION array, dimension (N-1)* TAU(i) must contain the scalar factor of the elementary* reflector H(i), as returned by DSYTRD.** WORK (workspace/output) DOUBLE PRECISION array, dimension (LWORK)* On exit, if INFO = 0, WORK(1) returns the optimal LWORK.** LWORK (input) INTEGER* The dimension of the array WORK. LWORK >= max(1,N-1).* For optimum performance LWORK >= (N-1)*NB, where NB is* the optimal blocksize.** If LWORK = -1, then a workspace query is assumed; the routine* only calculates the optimal size of the WORK array, returns* this value as the first entry of the WORK array, and no error* message related to LWORK is issued by XERBLA.** INFO (output) INTEGER* = 0: successful exit* < 0: if INFO = -i, the i-th argument had an illegal value** =====================================================================** .. Parameters ..DOUBLE PRECISION ZERO, ONEPARAMETER ( ZERO = 0.0D+0, ONE = 1.0D+0 )* ..* .. Local Scalars ..LOGICAL LQUERY, UPPERINTEGER I, IINFO, J, LWKOPT, NB* ..* .. External Functions ..LOGICAL LSAMEINTEGER ILAENVEXTERNAL LSAME, ILAENV* ..* .. External Subroutines ..EXTERNAL DORGQL, DORGQR, XERBLA* ..* .. Intrinsic Functions ..INTRINSIC MAX* ..* .. Executable Statements ..** Test the input arguments*INFO = 0LQUERY = ( LWORK.EQ.-1 )UPPER = LSAME( UPLO, 'U' )IF( .NOT.UPPER .AND. .NOT.LSAME( UPLO, 'L' ) ) THENINFO = -1ELSE IF( N.LT.0 ) THENINFO = -2ELSE IF( LDA.LT.MAX( 1, N ) ) THENINFO = -4ELSE IF( LWORK.LT.MAX( 1, N-1 ) .AND. .NOT.LQUERY ) THENINFO = -7END IF*IF( INFO.EQ.0 ) THENIF( UPPER ) THENNB = ILAENV( 1, 'DORGQL', ' ', N-1, N-1, N-1, -1 )ELSENB = ILAENV( 1, 'DORGQR', ' ', N-1, N-1, N-1, -1 )END IFLWKOPT = MAX( 1, N-1 )*NBWORK( 1 ) = LWKOPTEND IF*IF( INFO.NE.0 ) THENCALL XERBLA( 'DORGTR', -INFO )RETURNELSE IF( LQUERY ) THENRETURNEND IF** Quick return if possible*IF( N.EQ.0 ) THENWORK( 1 ) = 1RETURNEND IF*IF( UPPER ) THEN** Q was determined by a call to DSYTRD with UPLO = 'U'** Shift the vectors which define the elementary reflectors one* column to the left, and set the last row and column of Q to* those of the unit matrix*DO 20 J = 1, N - 1DO 10 I = 1, J - 1A( I, J ) = A( I, J+1 )10 CONTINUEA( N, J ) = ZERO20 CONTINUEDO 30 I = 1, N - 1A( I, N ) = ZERO30 CONTINUEA( N, N ) = ONE** Generate Q(1:n-1,1:n-1)*CALL DORGQL( N-1, N-1, N-1, A, LDA, TAU, WORK, LWORK, IINFO )*ELSE** Q was determined by a call to DSYTRD with UPLO = 'L'.** Shift the vectors which define the elementary reflectors one* column to the right, and set the first row and column of Q to* those of the unit matrix*DO 50 J = N, 2, -1A( 1, J ) = ZERODO 40 I = J + 1, NA( I, J ) = A( I, J-1 )40 CONTINUE50 CONTINUEA( 1, 1 ) = ONEDO 60 I = 2, NA( I, 1 ) = ZERO60 CONTINUEIF( N.GT.1 ) THEN** Generate Q(2:n,2:n)*CALL DORGQR( N-1, N-1, N-1, A( 2, 2 ), LDA, TAU, WORK,$ LWORK, IINFO )END IFEND IFWORK( 1 ) = LWKOPTRETURN** End of DORGTR*ENDSUBROUTINE DORM2R( SIDE, TRANS, M, N, K, A, LDA, TAU, C, LDC,$ WORK, INFO )** -- LAPACK routine (version 3.0) --* Univ. of Tennessee, Univ. of California Berkeley, NAG Ltd.,* Courant Institute, Argonne National Lab, and Rice University* February 29, 1992** .. Scalar Arguments ..CHARACTER SIDE, TRANSINTEGER INFO, K, LDA, LDC, M, N* ..* .. Array Arguments ..DOUBLE PRECISION A( LDA, * ), C( LDC, * ), TAU( * ), WORK( * )* ..** Purpose* =======** DORM2R overwrites the general real m by n matrix C with** Q * C if SIDE = 'L' and TRANS = 'N', or** Q'* C if SIDE = 'L' and TRANS = 'T', or** C * Q if SIDE = 'R' and TRANS = 'N', or** C * Q' if SIDE = 'R' and TRANS = 'T',** where Q is a real orthogonal matrix defined as the product of k* elementary reflectors** Q = H(1) H(2) . . . H(k)** as returned by DGEQRF. Q is of order m if SIDE = 'L' and of order n* if SIDE = 'R'.** Arguments* =========** SIDE (input) CHARACTER*1* = 'L': apply Q or Q' from the Left* = 'R': apply Q or Q' from the Right** TRANS (input) CHARACTER*1* = 'N': apply Q (No transpose)* = 'T': apply Q' (Transpose)** M (input) INTEGER* The number of rows of the matrix C. M >= 0.** N (input) INTEGER* The number of columns of the matrix C. N >= 0.** K (input) INTEGER* The number of elementary reflectors whose product defines* the matrix Q.* If SIDE = 'L', M >= K >= 0;* if SIDE = 'R', N >= K >= 0.** A (input) DOUBLE PRECISION array, dimension (LDA,K)* The i-th column must contain the vector which defines the* elementary reflector H(i), for i = 1,2,...,k, as returned by* DGEQRF in the first k columns of its array argument A.* A is modified by the routine but restored on exit.** LDA (input) INTEGER* The leading dimension of the array A.* If SIDE = 'L', LDA >= max(1,M);* if SIDE = 'R', LDA >= max(1,N).** TAU (input) DOUBLE PRECISION array, dimension (K)* TAU(i) must contain the scalar factor of the elementary* reflector H(i), as returned by DGEQRF.** C (input/output) DOUBLE PRECISION array, dimension (LDC,N)* On entry, the m by n matrix C.* On exit, C is overwritten by Q*C or Q'*C or C*Q' or C*Q.** LDC (input) INTEGER* The leading dimension of the array C. LDC >= max(1,M).** WORK (workspace) DOUBLE PRECISION array, dimension* (N) if SIDE = 'L',* (M) if SIDE = 'R'** INFO (output) INTEGER* = 0: successful exit* < 0: if INFO = -i, the i-th argument had an illegal value** =====================================================================** .. Parameters ..DOUBLE PRECISION ONEPARAMETER ( ONE = 1.0D+0 )* ..* .. Local Scalars ..LOGICAL LEFT, NOTRANINTEGER I, I1, I2, I3, IC, JC, MI, NI, NQDOUBLE PRECISION AII* ..* .. External Functions ..LOGICAL LSAMEEXTERNAL LSAME* ..* .. External Subroutines ..EXTERNAL DLARF, XERBLA* ..* .. Intrinsic Functions ..INTRINSIC MAX* ..* .. Executable Statements ..** Test the input arguments*INFO = 0LEFT = LSAME( SIDE, 'L' )NOTRAN = LSAME( TRANS, 'N' )** NQ is the order of Q*IF( LEFT ) THENNQ = MELSENQ = NEND IFIF( .NOT.LEFT .AND. .NOT.LSAME( SIDE, 'R' ) ) THENINFO = -1ELSE IF( .NOT.NOTRAN .AND. .NOT.LSAME( TRANS, 'T' ) ) THENINFO = -2ELSE IF( M.LT.0 ) THENINFO = -3ELSE IF( N.LT.0 ) THENINFO = -4ELSE IF( K.LT.0 .OR. K.GT.NQ ) THENINFO = -5ELSE IF( LDA.LT.MAX( 1, NQ ) ) THENINFO = -7ELSE IF( LDC.LT.MAX( 1, M ) ) THENINFO = -10END IFIF( INFO.NE.0 ) THENCALL XERBLA( 'DORM2R', -INFO )RETURNEND IF** Quick return if possible*IF( M.EQ.0 .OR. N.EQ.0 .OR. K.EQ.0 )$ RETURN*IF( ( LEFT .AND. .NOT.NOTRAN ) .OR. ( .NOT.LEFT .AND. NOTRAN ) )$ THENI1 = 1I2 = KI3 = 1ELSEI1 = KI2 = 1I3 = -1END IF*IF( LEFT ) THENNI = NJC = 1ELSEMI = MIC = 1END IF*DO 10 I = I1, I2, I3IF( LEFT ) THEN** H(i) is applied to C(i:m,1:n)*MI = M - I + 1IC = IELSE** H(i) is applied to C(1:m,i:n)*NI = N - I + 1JC = IEND IF** Apply H(i)*AII = A( I, I )A( I, I ) = ONECALL DLARF( SIDE, MI, NI, A( I, I ), 1, TAU( I ), C( IC, JC ),$ LDC, WORK )A( I, I ) = AII10 CONTINUERETURN** End of DORM2R*ENDSUBROUTINE DORMBR( VECT, SIDE, TRANS, M, N, K, A, LDA, TAU, C,$ LDC, WORK, LWORK, INFO )** -- LAPACK routine (version 3.0) --* Univ. of Tennessee, Univ. of California Berkeley, NAG Ltd.,* Courant Institute, Argonne National Lab, and Rice University* June 30, 1999** .. Scalar Arguments ..CHARACTER SIDE, TRANS, VECTINTEGER INFO, K, LDA, LDC, LWORK, M, N* ..* .. Array Arguments ..DOUBLE PRECISION A( LDA, * ), C( LDC, * ), TAU( * ), WORK( * )* ..** Purpose* =======** If VECT = 'Q', DORMBR overwrites the general real M-by-N matrix C* with* SIDE = 'L' SIDE = 'R'* TRANS = 'N': Q * C C * Q* TRANS = 'T': Q**T * C C * Q**T** If VECT = 'P', DORMBR overwrites the general real M-by-N matrix C* with* SIDE = 'L' SIDE = 'R'* TRANS = 'N': P * C C * P* TRANS = 'T': P**T * C C * P**T** Here Q and P**T are the orthogonal matrices determined by DGEBRD when* reducing a real matrix A to bidiagonal form: A = Q * B * P**T. Q and* P**T are defined as products of elementary reflectors H(i) and G(i)* respectively.** Let nq = m if SIDE = 'L' and nq = n if SIDE = 'R'. Thus nq is the* order of the orthogonal matrix Q or P**T that is applied.** If VECT = 'Q', A is assumed to have been an NQ-by-K matrix:* if nq >= k, Q = H(1) H(2) . . . H(k);* if nq < k, Q = H(1) H(2) . . . H(nq-1).** If VECT = 'P', A is assumed to have been a K-by-NQ matrix:* if k < nq, P = G(1) G(2) . . . G(k);* if k >= nq, P = G(1) G(2) . . . G(nq-1).** Arguments* =========** VECT (input) CHARACTER*1* = 'Q': apply Q or Q**T;* = 'P': apply P or P**T.** SIDE (input) CHARACTER*1* = 'L': apply Q, Q**T, P or P**T from the Left;* = 'R': apply Q, Q**T, P or P**T from the Right.** TRANS (input) CHARACTER*1* = 'N': No transpose, apply Q or P;* = 'T': Transpose, apply Q**T or P**T.** M (input) INTEGER* The number of rows of the matrix C. M >= 0.** N (input) INTEGER* The number of columns of the matrix C. N >= 0.** K (input) INTEGER* If VECT = 'Q', the number of columns in the original* matrix reduced by DGEBRD.* If VECT = 'P', the number of rows in the original* matrix reduced by DGEBRD.* K >= 0.** A (input) DOUBLE PRECISION array, dimension* (LDA,min(nq,K)) if VECT = 'Q'* (LDA,nq) if VECT = 'P'* The vectors which define the elementary reflectors H(i) and* G(i), whose products determine the matrices Q and P, as* returned by DGEBRD.** LDA (input) INTEGER* The leading dimension of the array A.* If VECT = 'Q', LDA >= max(1,nq);* if VECT = 'P', LDA >= max(1,min(nq,K)).** TAU (input) DOUBLE PRECISION array, dimension (min(nq,K))* TAU(i) must contain the scalar factor of the elementary* reflector H(i) or G(i) which determines Q or P, as returned* by DGEBRD in the array argument TAUQ or TAUP.** C (input/output) DOUBLE PRECISION array, dimension (LDC,N)* On entry, the M-by-N matrix C.* On exit, C is overwritten by Q*C or Q**T*C or C*Q**T or C*Q* or P*C or P**T*C or C*P or C*P**T.** LDC (input) INTEGER* The leading dimension of the array C. LDC >= max(1,M).** WORK (workspace/output) DOUBLE PRECISION array, dimension (LWORK)* On exit, if INFO = 0, WORK(1) returns the optimal LWORK.** LWORK (input) INTEGER* The dimension of the array WORK.* If SIDE = 'L', LWORK >= max(1,N);* if SIDE = 'R', LWORK >= max(1,M).* For optimum performance LWORK >= N*NB if SIDE = 'L', and* LWORK >= M*NB if SIDE = 'R', where NB is the optimal* blocksize.** If LWORK = -1, then a workspace query is assumed; the routine* only calculates the optimal size of the WORK array, returns* this value as the first entry of the WORK array, and no error* message related to LWORK is issued by XERBLA.** INFO (output) INTEGER* = 0: successful exit* < 0: if INFO = -i, the i-th argument had an illegal value** =====================================================================** .. Local Scalars ..LOGICAL APPLYQ, LEFT, LQUERY, NOTRANCHARACTER TRANSTINTEGER I1, I2, IINFO, LWKOPT, MI, NB, NI, NQ, NW* ..* .. External Functions ..LOGICAL LSAMEINTEGER ILAENVEXTERNAL LSAME, ILAENV* ..* .. External Subroutines ..EXTERNAL DORMLQ, DORMQR, XERBLA* ..* .. Intrinsic Functions ..INTRINSIC MAX, MIN* ..* .. Executable Statements ..** Test the input arguments*INFO = 0APPLYQ = LSAME( VECT, 'Q' )LEFT = LSAME( SIDE, 'L' )NOTRAN = LSAME( TRANS, 'N' )LQUERY = ( LWORK.EQ.-1 )** NQ is the order of Q or P and NW is the minimum dimension of WORK*IF( LEFT ) THENNQ = MNW = NELSENQ = NNW = MEND IFIF( .NOT.APPLYQ .AND. .NOT.LSAME( VECT, 'P' ) ) THENINFO = -1ELSE IF( .NOT.LEFT .AND. .NOT.LSAME( SIDE, 'R' ) ) THENINFO = -2ELSE IF( .NOT.NOTRAN .AND. .NOT.LSAME( TRANS, 'T' ) ) THENINFO = -3ELSE IF( M.LT.0 ) THENINFO = -4ELSE IF( N.LT.0 ) THENINFO = -5ELSE IF( K.LT.0 ) THENINFO = -6ELSE IF( ( APPLYQ .AND. LDA.LT.MAX( 1, NQ ) ) .OR.$ ( .NOT.APPLYQ .AND. LDA.LT.MAX( 1, MIN( NQ, K ) ) ) )$ THENINFO = -8ELSE IF( LDC.LT.MAX( 1, M ) ) THENINFO = -11ELSE IF( LWORK.LT.MAX( 1, NW ) .AND. .NOT.LQUERY ) THENINFO = -13END IF*IF( INFO.EQ.0 ) THENIF( APPLYQ ) THENIF( LEFT ) THENNB = ILAENV( 1, 'DORMQR', SIDE // TRANS, M-1, N, M-1,$ -1 )ELSENB = ILAENV( 1, 'DORMQR', SIDE // TRANS, M, N-1, N-1,$ -1 )END IFELSEIF( LEFT ) THENNB = ILAENV( 1, 'DORMLQ', SIDE // TRANS, M-1, N, M-1,$ -1 )ELSENB = ILAENV( 1, 'DORMLQ', SIDE // TRANS, M, N-1, N-1,$ -1 )END IFEND IFLWKOPT = MAX( 1, NW )*NBWORK( 1 ) = LWKOPTEND IF*IF( INFO.NE.0 ) THENCALL XERBLA( 'DORMBR', -INFO )RETURNELSE IF( LQUERY ) THENRETURNEND IF** Quick return if possible*WORK( 1 ) = 1IF( M.EQ.0 .OR. N.EQ.0 )$ RETURN*IF( APPLYQ ) THEN** Apply Q*IF( NQ.GE.K ) THEN** Q was determined by a call to DGEBRD with nq >= k*CALL DORMQR( SIDE, TRANS, M, N, K, A, LDA, TAU, C, LDC,$ WORK, LWORK, IINFO )ELSE IF( NQ.GT.1 ) THEN** Q was determined by a call to DGEBRD with nq < k*IF( LEFT ) THENMI = M - 1NI = NI1 = 2I2 = 1ELSEMI = MNI = N - 1I1 = 1I2 = 2END IFCALL DORMQR( SIDE, TRANS, MI, NI, NQ-1, A( 2, 1 ), LDA, TAU,$ C( I1, I2 ), LDC, WORK, LWORK, IINFO )END IFELSE** Apply P*IF( NOTRAN ) THENTRANST = 'T'ELSETRANST = 'N'END IFIF( NQ.GT.K ) THEN** P was determined by a call to DGEBRD with nq > k*CALL DORMLQ( SIDE, TRANST, M, N, K, A, LDA, TAU, C, LDC,$ WORK, LWORK, IINFO )ELSE IF( NQ.GT.1 ) THEN** P was determined by a call to DGEBRD with nq <= k*IF( LEFT ) THENMI = M - 1NI = NI1 = 2I2 = 1ELSEMI = MNI = N - 1I1 = 1I2 = 2END IFCALL DORMLQ( SIDE, TRANST, MI, NI, NQ-1, A( 1, 2 ), LDA,$ TAU, C( I1, I2 ), LDC, WORK, LWORK, IINFO )END IFEND IFWORK( 1 ) = LWKOPTRETURN** End of DORMBR*ENDSUBROUTINE DORML2( SIDE, TRANS, M, N, K, A, LDA, TAU, C, LDC,$ WORK, INFO )** -- LAPACK routine (version 3.0) --* Univ. of Tennessee, Univ. of California Berkeley, NAG Ltd.,* Courant Institute, Argonne National Lab, and Rice University* February 29, 1992** .. Scalar Arguments ..CHARACTER SIDE, TRANSINTEGER INFO, K, LDA, LDC, M, N* ..* .. Array Arguments ..DOUBLE PRECISION A( LDA, * ), C( LDC, * ), TAU( * ), WORK( * )* ..** Purpose* =======** DORML2 overwrites the general real m by n matrix C with** Q * C if SIDE = 'L' and TRANS = 'N', or** Q'* C if SIDE = 'L' and TRANS = 'T', or** C * Q if SIDE = 'R' and TRANS = 'N', or** C * Q' if SIDE = 'R' and TRANS = 'T',** where Q is a real orthogonal matrix defined as the product of k* elementary reflectors** Q = H(k) . . . H(2) H(1)** as returned by DGELQF. Q is of order m if SIDE = 'L' and of order n* if SIDE = 'R'.** Arguments* =========** SIDE (input) CHARACTER*1* = 'L': apply Q or Q' from the Left* = 'R': apply Q or Q' from the Right** TRANS (input) CHARACTER*1* = 'N': apply Q (No transpose)* = 'T': apply Q' (Transpose)** M (input) INTEGER* The number of rows of the matrix C. M >= 0.** N (input) INTEGER* The number of columns of the matrix C. N >= 0.** K (input) INTEGER* The number of elementary reflectors whose product defines* the matrix Q.* If SIDE = 'L', M >= K >= 0;* if SIDE = 'R', N >= K >= 0.** A (input) DOUBLE PRECISION array, dimension* (LDA,M) if SIDE = 'L',* (LDA,N) if SIDE = 'R'* The i-th row must contain the vector which defines the* elementary reflector H(i), for i = 1,2,...,k, as returned by* DGELQF in the first k rows of its array argument A.* A is modified by the routine but restored on exit.** LDA (input) INTEGER* The leading dimension of the array A. LDA >= max(1,K).** TAU (input) DOUBLE PRECISION array, dimension (K)* TAU(i) must contain the scalar factor of the elementary* reflector H(i), as returned by DGELQF.** C (input/output) DOUBLE PRECISION array, dimension (LDC,N)* On entry, the m by n matrix C.* On exit, C is overwritten by Q*C or Q'*C or C*Q' or C*Q.** LDC (input) INTEGER* The leading dimension of the array C. LDC >= max(1,M).** WORK (workspace) DOUBLE PRECISION array, dimension* (N) if SIDE = 'L',* (M) if SIDE = 'R'** INFO (output) INTEGER* = 0: successful exit* < 0: if INFO = -i, the i-th argument had an illegal value** =====================================================================** .. Parameters ..DOUBLE PRECISION ONEPARAMETER ( ONE = 1.0D+0 )* ..* .. Local Scalars ..LOGICAL LEFT, NOTRANINTEGER I, I1, I2, I3, IC, JC, MI, NI, NQDOUBLE PRECISION AII* ..* .. External Functions ..LOGICAL LSAMEEXTERNAL LSAME* ..* .. External Subroutines ..EXTERNAL DLARF, XERBLA* ..* .. Intrinsic Functions ..INTRINSIC MAX* ..* .. Executable Statements ..** Test the input arguments*INFO = 0LEFT = LSAME( SIDE, 'L' )NOTRAN = LSAME( TRANS, 'N' )** NQ is the order of Q*IF( LEFT ) THENNQ = MELSENQ = NEND IFIF( .NOT.LEFT .AND. .NOT.LSAME( SIDE, 'R' ) ) THENINFO = -1ELSE IF( .NOT.NOTRAN .AND. .NOT.LSAME( TRANS, 'T' ) ) THENINFO = -2ELSE IF( M.LT.0 ) THENINFO = -3ELSE IF( N.LT.0 ) THENINFO = -4ELSE IF( K.LT.0 .OR. K.GT.NQ ) THENINFO = -5ELSE IF( LDA.LT.MAX( 1, K ) ) THENINFO = -7ELSE IF( LDC.LT.MAX( 1, M ) ) THENINFO = -10END IFIF( INFO.NE.0 ) THENCALL XERBLA( 'DORML2', -INFO )RETURNEND IF** Quick return if possible*IF( M.EQ.0 .OR. N.EQ.0 .OR. K.EQ.0 )$ RETURN*IF( ( LEFT .AND. NOTRAN ) .OR. ( .NOT.LEFT .AND. .NOT.NOTRAN ) )$ THENI1 = 1I2 = KI3 = 1ELSEI1 = KI2 = 1I3 = -1END IF*IF( LEFT ) THENNI = NJC = 1ELSEMI = MIC = 1END IF*DO 10 I = I1, I2, I3IF( LEFT ) THEN** H(i) is applied to C(i:m,1:n)*MI = M - I + 1IC = IELSE** H(i) is applied to C(1:m,i:n)*NI = N - I + 1JC = IEND IF** Apply H(i)*AII = A( I, I )A( I, I ) = ONECALL DLARF( SIDE, MI, NI, A( I, I ), LDA, TAU( I ),$ C( IC, JC ), LDC, WORK )A( I, I ) = AII10 CONTINUERETURN** End of DORML2*ENDSUBROUTINE DORMLQ( SIDE, TRANS, M, N, K, A, LDA, TAU, C, LDC,$ WORK, LWORK, INFO )** -- LAPACK routine (version 3.0) --* Univ. of Tennessee, Univ. of California Berkeley, NAG Ltd.,* Courant Institute, Argonne National Lab, and Rice University* June 30, 1999** .. Scalar Arguments ..CHARACTER SIDE, TRANSINTEGER INFO, K, LDA, LDC, LWORK, M, N* ..* .. Array Arguments ..DOUBLE PRECISION A( LDA, * ), C( LDC, * ), TAU( * ), WORK( * )* ..** Purpose* =======** DORMLQ overwrites the general real M-by-N matrix C with** SIDE = 'L' SIDE = 'R'* TRANS = 'N': Q * C C * Q* TRANS = 'T': Q**T * C C * Q**T** where Q is a real orthogonal matrix defined as the product of k* elementary reflectors** Q = H(k) . . . H(2) H(1)** as returned by DGELQF. Q is of order M if SIDE = 'L' and of order N* if SIDE = 'R'.** Arguments* =========** SIDE (input) CHARACTER*1* = 'L': apply Q or Q**T from the Left;* = 'R': apply Q or Q**T from the Right.** TRANS (input) CHARACTER*1* = 'N': No transpose, apply Q;* = 'T': Transpose, apply Q**T.** M (input) INTEGER* The number of rows of the matrix C. M >= 0.** N (input) INTEGER* The number of columns of the matrix C. N >= 0.** K (input) INTEGER* The number of elementary reflectors whose product defines* the matrix Q.* If SIDE = 'L', M >= K >= 0;* if SIDE = 'R', N >= K >= 0.** A (input) DOUBLE PRECISION array, dimension* (LDA,M) if SIDE = 'L',* (LDA,N) if SIDE = 'R'* The i-th row must contain the vector which defines the* elementary reflector H(i), for i = 1,2,...,k, as returned by* DGELQF in the first k rows of its array argument A.* A is modified by the routine but restored on exit.** LDA (input) INTEGER* The leading dimension of the array A. LDA >= max(1,K).** TAU (input) DOUBLE PRECISION array, dimension (K)* TAU(i) must contain the scalar factor of the elementary* reflector H(i), as returned by DGELQF.** C (input/output) DOUBLE PRECISION array, dimension (LDC,N)* On entry, the M-by-N matrix C.* On exit, C is overwritten by Q*C or Q**T*C or C*Q**T or C*Q.** LDC (input) INTEGER* The leading dimension of the array C. LDC >= max(1,M).** WORK (workspace/output) DOUBLE PRECISION array, dimension (LWORK)* On exit, if INFO = 0, WORK(1) returns the optimal LWORK.** LWORK (input) INTEGER* The dimension of the array WORK.* If SIDE = 'L', LWORK >= max(1,N);* if SIDE = 'R', LWORK >= max(1,M).* For optimum performance LWORK >= N*NB if SIDE = 'L', and* LWORK >= M*NB if SIDE = 'R', where NB is the optimal* blocksize.** If LWORK = -1, then a workspace query is assumed; the routine* only calculates the optimal size of the WORK array, returns* this value as the first entry of the WORK array, and no error* message related to LWORK is issued by XERBLA.** INFO (output) INTEGER* = 0: successful exit* < 0: if INFO = -i, the i-th argument had an illegal value** =====================================================================** .. Parameters ..INTEGER NBMAX, LDTPARAMETER ( NBMAX = 64, LDT = NBMAX+1 )* ..* .. Local Scalars ..LOGICAL LEFT, LQUERY, NOTRANCHARACTER TRANSTINTEGER I, I1, I2, I3, IB, IC, IINFO, IWS, JC, LDWORK,$ LWKOPT, MI, NB, NBMIN, NI, NQ, NW* ..* .. Local Arrays ..DOUBLE PRECISION T( LDT, NBMAX )* ..* .. External Functions ..LOGICAL LSAMEINTEGER ILAENVEXTERNAL LSAME, ILAENV* ..* .. External Subroutines ..EXTERNAL DLARFB, DLARFT, DORML2, XERBLA* ..* .. Intrinsic Functions ..INTRINSIC MAX, MIN* ..* .. Executable Statements ..** Test the input arguments*INFO = 0LEFT = LSAME( SIDE, 'L' )NOTRAN = LSAME( TRANS, 'N' )LQUERY = ( LWORK.EQ.-1 )** NQ is the order of Q and NW is the minimum dimension of WORK*IF( LEFT ) THENNQ = MNW = NELSENQ = NNW = MEND IFIF( .NOT.LEFT .AND. .NOT.LSAME( SIDE, 'R' ) ) THENINFO = -1ELSE IF( .NOT.NOTRAN .AND. .NOT.LSAME( TRANS, 'T' ) ) THENINFO = -2ELSE IF( M.LT.0 ) THENINFO = -3ELSE IF( N.LT.0 ) THENINFO = -4ELSE IF( K.LT.0 .OR. K.GT.NQ ) THENINFO = -5ELSE IF( LDA.LT.MAX( 1, K ) ) THENINFO = -7ELSE IF( LDC.LT.MAX( 1, M ) ) THENINFO = -10ELSE IF( LWORK.LT.MAX( 1, NW ) .AND. .NOT.LQUERY ) THENINFO = -12END IF*IF( INFO.EQ.0 ) THEN** Determine the block size. NB may be at most NBMAX, where NBMAX* is used to define the local array T.*NB = MIN( NBMAX, ILAENV( 1, 'DORMLQ', SIDE // TRANS, M, N, K,$ -1 ) )LWKOPT = MAX( 1, NW )*NBWORK( 1 ) = LWKOPTEND IF*IF( INFO.NE.0 ) THENCALL XERBLA( 'DORMLQ', -INFO )RETURNELSE IF( LQUERY ) THENRETURNEND IF** Quick return if possible*IF( M.EQ.0 .OR. N.EQ.0 .OR. K.EQ.0 ) THENWORK( 1 ) = 1RETURNEND IF*NBMIN = 2LDWORK = NWIF( NB.GT.1 .AND. NB.LT.K ) THENIWS = NW*NBIF( LWORK.LT.IWS ) THENNB = LWORK / LDWORKNBMIN = MAX( 2, ILAENV( 2, 'DORMLQ', SIDE // TRANS, M, N, K,$ -1 ) )END IFELSEIWS = NWEND IF*IF( NB.LT.NBMIN .OR. NB.GE.K ) THEN** Use unblocked code*CALL DORML2( SIDE, TRANS, M, N, K, A, LDA, TAU, C, LDC, WORK,$ IINFO )ELSE** Use blocked code*IF( ( LEFT .AND. NOTRAN ) .OR.$ ( .NOT.LEFT .AND. .NOT.NOTRAN ) ) THENI1 = 1I2 = KI3 = NBELSEI1 = ( ( K-1 ) / NB )*NB + 1I2 = 1I3 = -NBEND IF*IF( LEFT ) THENNI = NJC = 1ELSEMI = MIC = 1END IF*IF( NOTRAN ) THENTRANST = 'T'ELSETRANST = 'N'END IF*DO 10 I = I1, I2, I3IB = MIN( NB, K-I+1 )** Form the triangular factor of the block reflector* H = H(i) H(i+1) . . . H(i+ib-1)*CALL DLARFT( 'Forward', 'Rowwise', NQ-I+1, IB, A( I, I ),$ LDA, TAU( I ), T, LDT )IF( LEFT ) THEN** H or H' is applied to C(i:m,1:n)*MI = M - I + 1IC = IELSE** H or H' is applied to C(1:m,i:n)*NI = N - I + 1JC = IEND IF** Apply H or H'*CALL DLARFB( SIDE, TRANST, 'Forward', 'Rowwise', MI, NI, IB,$ A( I, I ), LDA, T, LDT, C( IC, JC ), LDC, WORK,$ LDWORK )10 CONTINUEEND IFWORK( 1 ) = LWKOPTRETURN** End of DORMLQ*ENDSUBROUTINE DORMQR( SIDE, TRANS, M, N, K, A, LDA, TAU, C, LDC,$ WORK, LWORK, INFO )** -- LAPACK routine (version 3.0) --* Univ. of Tennessee, Univ. of California Berkeley, NAG Ltd.,* Courant Institute, Argonne National Lab, and Rice University* June 30, 1999** .. Scalar Arguments ..CHARACTER SIDE, TRANSINTEGER INFO, K, LDA, LDC, LWORK, M, N* ..* .. Array Arguments ..DOUBLE PRECISION A( LDA, * ), C( LDC, * ), TAU( * ), WORK( * )* ..** Purpose* =======** DORMQR overwrites the general real M-by-N matrix C with** SIDE = 'L' SIDE = 'R'* TRANS = 'N': Q * C C * Q* TRANS = 'T': Q**T * C C * Q**T** where Q is a real orthogonal matrix defined as the product of k* elementary reflectors** Q = H(1) H(2) . . . H(k)** as returned by DGEQRF. Q is of order M if SIDE = 'L' and of order N* if SIDE = 'R'.** Arguments* =========** SIDE (input) CHARACTER*1* = 'L': apply Q or Q**T from the Left;* = 'R': apply Q or Q**T from the Right.** TRANS (input) CHARACTER*1* = 'N': No transpose, apply Q;* = 'T': Transpose, apply Q**T.** M (input) INTEGER* The number of rows of the matrix C. M >= 0.** N (input) INTEGER* The number of columns of the matrix C. N >= 0.** K (input) INTEGER* The number of elementary reflectors whose product defines* the matrix Q.* If SIDE = 'L', M >= K >= 0;* if SIDE = 'R', N >= K >= 0.** A (input) DOUBLE PRECISION array, dimension (LDA,K)* The i-th column must contain the vector which defines the* elementary reflector H(i), for i = 1,2,...,k, as returned by* DGEQRF in the first k columns of its array argument A.* A is modified by the routine but restored on exit.** LDA (input) INTEGER* The leading dimension of the array A.* If SIDE = 'L', LDA >= max(1,M);* if SIDE = 'R', LDA >= max(1,N).** TAU (input) DOUBLE PRECISION array, dimension (K)* TAU(i) must contain the scalar factor of the elementary* reflector H(i), as returned by DGEQRF.** C (input/output) DOUBLE PRECISION array, dimension (LDC,N)* On entry, the M-by-N matrix C.* On exit, C is overwritten by Q*C or Q**T*C or C*Q**T or C*Q.** LDC (input) INTEGER* The leading dimension of the array C. LDC >= max(1,M).** WORK (workspace/output) DOUBLE PRECISION array, dimension (LWORK)* On exit, if INFO = 0, WORK(1) returns the optimal LWORK.** LWORK (input) INTEGER* The dimension of the array WORK.* If SIDE = 'L', LWORK >= max(1,N);* if SIDE = 'R', LWORK >= max(1,M).* For optimum performance LWORK >= N*NB if SIDE = 'L', and* LWORK >= M*NB if SIDE = 'R', where NB is the optimal* blocksize.** If LWORK = -1, then a workspace query is assumed; the routine* only calculates the optimal size of the WORK array, returns* this value as the first entry of the WORK array, and no error* message related to LWORK is issued by XERBLA.** INFO (output) INTEGER* = 0: successful exit* < 0: if INFO = -i, the i-th argument had an illegal value** =====================================================================** .. Parameters ..INTEGER NBMAX, LDTPARAMETER ( NBMAX = 64, LDT = NBMAX+1 )* ..* .. Local Scalars ..LOGICAL LEFT, LQUERY, NOTRANINTEGER I, I1, I2, I3, IB, IC, IINFO, IWS, JC, LDWORK,$ LWKOPT, MI, NB, NBMIN, NI, NQ, NW* ..* .. Local Arrays ..DOUBLE PRECISION T( LDT, NBMAX )* ..* .. External Functions ..LOGICAL LSAMEINTEGER ILAENVEXTERNAL LSAME, ILAENV* ..* .. External Subroutines ..EXTERNAL DLARFB, DLARFT, DORM2R, XERBLA* ..* .. Intrinsic Functions ..INTRINSIC MAX, MIN* ..* .. Executable Statements ..** Test the input arguments*INFO = 0LEFT = LSAME( SIDE, 'L' )NOTRAN = LSAME( TRANS, 'N' )LQUERY = ( LWORK.EQ.-1 )** NQ is the order of Q and NW is the minimum dimension of WORK*IF( LEFT ) THENNQ = MNW = NELSENQ = NNW = MEND IFIF( .NOT.LEFT .AND. .NOT.LSAME( SIDE, 'R' ) ) THENINFO = -1ELSE IF( .NOT.NOTRAN .AND. .NOT.LSAME( TRANS, 'T' ) ) THENINFO = -2ELSE IF( M.LT.0 ) THENINFO = -3ELSE IF( N.LT.0 ) THENINFO = -4ELSE IF( K.LT.0 .OR. K.GT.NQ ) THENINFO = -5ELSE IF( LDA.LT.MAX( 1, NQ ) ) THENINFO = -7ELSE IF( LDC.LT.MAX( 1, M ) ) THENINFO = -10ELSE IF( LWORK.LT.MAX( 1, NW ) .AND. .NOT.LQUERY ) THENINFO = -12END IF*IF( INFO.EQ.0 ) THEN** Determine the block size. NB may be at most NBMAX, where NBMAX* is used to define the local array T.*NB = MIN( NBMAX, ILAENV( 1, 'DORMQR', SIDE // TRANS, M, N, K,$ -1 ) )LWKOPT = MAX( 1, NW )*NBWORK( 1 ) = LWKOPTEND IF*IF( INFO.NE.0 ) THENCALL XERBLA( 'DORMQR', -INFO )RETURNELSE IF( LQUERY ) THENRETURNEND IF** Quick return if possible*IF( M.EQ.0 .OR. N.EQ.0 .OR. K.EQ.0 ) THENWORK( 1 ) = 1RETURNEND IF*NBMIN = 2LDWORK = NWIF( NB.GT.1 .AND. NB.LT.K ) THENIWS = NW*NBIF( LWORK.LT.IWS ) THENNB = LWORK / LDWORKNBMIN = MAX( 2, ILAENV( 2, 'DORMQR', SIDE // TRANS, M, N, K,$ -1 ) )END IFELSEIWS = NWEND IF*IF( NB.LT.NBMIN .OR. NB.GE.K ) THEN** Use unblocked code*CALL DORM2R( SIDE, TRANS, M, N, K, A, LDA, TAU, C, LDC, WORK,$ IINFO )ELSE** Use blocked code*IF( ( LEFT .AND. .NOT.NOTRAN ) .OR.$ ( .NOT.LEFT .AND. NOTRAN ) ) THENI1 = 1I2 = KI3 = NBELSEI1 = ( ( K-1 ) / NB )*NB + 1I2 = 1I3 = -NBEND IF*IF( LEFT ) THENNI = NJC = 1ELSEMI = MIC = 1END IF*DO 10 I = I1, I2, I3IB = MIN( NB, K-I+1 )** Form the triangular factor of the block reflector* H = H(i) H(i+1) . . . H(i+ib-1)*CALL DLARFT( 'Forward', 'Columnwise', NQ-I+1, IB, A( I, I ),$ LDA, TAU( I ), T, LDT )IF( LEFT ) THEN** H or H' is applied to C(i:m,1:n)*MI = M - I + 1IC = IELSE** H or H' is applied to C(1:m,i:n)*NI = N - I + 1JC = IEND IF** Apply H or H'*CALL DLARFB( SIDE, TRANS, 'Forward', 'Columnwise', MI, NI,$ IB, A( I, I ), LDA, T, LDT, C( IC, JC ), LDC,$ WORK, LDWORK )10 CONTINUEEND IFWORK( 1 ) = LWKOPTRETURN** End of DORMQR*ENDSUBROUTINE DRSCL( N, SA, SX, INCX )** -- LAPACK auxiliary routine (version 3.0) --* Univ. of Tennessee, Univ. of California Berkeley, NAG Ltd.,* Courant Institute, Argonne National Lab, and Rice University* September 30, 1994** .. Scalar Arguments ..INTEGER INCX, NDOUBLE PRECISION SA* ..* .. Array Arguments ..DOUBLE PRECISION SX( * )* ..** Purpose* =======** DRSCL multiplies an n-element real vector x by the real scalar 1/a.* This is done without overflow or underflow as long as* the final result x/a does not overflow or underflow.** Arguments* =========** N (input) INTEGER* The number of components of the vector x.** SA (input) DOUBLE PRECISION* The scalar a which is used to divide each component of x.* SA must be >= 0, or the subroutine will divide by zero.** SX (input/output) DOUBLE PRECISION array, dimension* (1+(N-1)*abs(INCX))* The n-element vector x.** INCX (input) INTEGER* The increment between successive values of the vector SX.* > 0: SX(1) = X(1) and SX(1+(i-1)*INCX) = x(i), 1< i<= n** =====================================================================** .. Parameters ..DOUBLE PRECISION ONE, ZEROPARAMETER ( ONE = 1.0D+0, ZERO = 0.0D+0 )* ..* .. Local Scalars ..LOGICAL DONEDOUBLE PRECISION BIGNUM, CDEN, CDEN1, CNUM, CNUM1, MUL, SMLNUM* ..* .. External Functions ..DOUBLE PRECISION DLAMCHEXTERNAL DLAMCH* ..* .. External Subroutines ..EXTERNAL DSCAL* ..* .. Intrinsic Functions ..INTRINSIC ABS* ..* .. Executable Statements ..** Quick return if possible*IF( N.LE.0 )$ RETURN** Get machine parameters*SMLNUM = DLAMCH( 'S' )BIGNUM = ONE / SMLNUMCALL DLABAD( SMLNUM, BIGNUM )** Initialize the denominator to SA and the numerator to 1.*CDEN = SACNUM = ONE*10 CONTINUECDEN1 = CDEN*SMLNUMCNUM1 = CNUM / BIGNUMIF( ABS( CDEN1 ).GT.ABS( CNUM ) .AND. CNUM.NE.ZERO ) THEN** Pre-multiply X by SMLNUM if CDEN is large compared to CNUM.*MUL = SMLNUMDONE = .FALSE.CDEN = CDEN1ELSE IF( ABS( CNUM1 ).GT.ABS( CDEN ) ) THEN** Pre-multiply X by BIGNUM if CDEN is small compared to CNUM.*MUL = BIGNUMDONE = .FALSE.CNUM = CNUM1ELSE** Multiply X by CNUM / CDEN and return.*MUL = CNUM / CDENDONE = .TRUE.END IF** Scale the vector X by MUL*CALL DSCAL( N, MUL, SX, INCX )*IF( .NOT.DONE )$ GO TO 10*RETURN** End of DRSCL*ENDSUBROUTINE DSTEQR( COMPZ, N, D, E, Z, LDZ, WORK, INFO )** -- LAPACK routine (version 3.0) --* Univ. of Tennessee, Univ. of California Berkeley, NAG Ltd.,* Courant Institute, Argonne National Lab, and Rice University* September 30, 1994** .. Scalar Arguments ..CHARACTER COMPZINTEGER INFO, LDZ, N* ..* .. Array Arguments ..DOUBLE PRECISION D( * ), E( * ), WORK( * ), Z( LDZ, * )* ..** Purpose* =======** DSTEQR computes all eigenvalues and, optionally, eigenvectors of a* symmetric tridiagonal matrix using the implicit QL or QR method.* The eigenvectors of a full or band symmetric matrix can also be found* if DSYTRD or DSPTRD or DSBTRD has been used to reduce this matrix to* tridiagonal form.** Arguments* =========** COMPZ (input) CHARACTER*1* = 'N': Compute eigenvalues only.* = 'V': Compute eigenvalues and eigenvectors of the original* symmetric matrix. On entry, Z must contain the* orthogonal matrix used to reduce the original matrix* to tridiagonal form.* = 'I': Compute eigenvalues and eigenvectors of the* tridiagonal matrix. Z is initialized to the identity* matrix.** N (input) INTEGER* The order of the matrix. N >= 0.** D (input/output) DOUBLE PRECISION array, dimension (N)* On entry, the diagonal elements of the tridiagonal matrix.* On exit, if INFO = 0, the eigenvalues in ascending order.** E (input/output) DOUBLE PRECISION array, dimension (N-1)* On entry, the (n-1) subdiagonal elements of the tridiagonal* matrix.* On exit, E has been destroyed.** Z (input/output) DOUBLE PRECISION array, dimension (LDZ, N)* On entry, if COMPZ = 'V', then Z contains the orthogonal* matrix used in the reduction to tridiagonal form.* On exit, if INFO = 0, then if COMPZ = 'V', Z contains the* orthonormal eigenvectors of the original symmetric matrix,* and if COMPZ = 'I', Z contains the orthonormal eigenvectors* of the symmetric tridiagonal matrix.* If COMPZ = 'N', then Z is not referenced.** LDZ (input) INTEGER* The leading dimension of the array Z. LDZ >= 1, and if* eigenvectors are desired, then LDZ >= max(1,N).** WORK (workspace) DOUBLE PRECISION array, dimension (max(1,2*N-2))* If COMPZ = 'N', then WORK is not referenced.** INFO (output) INTEGER* = 0: successful exit* < 0: if INFO = -i, the i-th argument had an illegal value* > 0: the algorithm has failed to find all the eigenvalues in* a total of 30*N iterations; if INFO = i, then i* elements of E have not converged to zero; on exit, D* and E contain the elements of a symmetric tridiagonal* matrix which is orthogonally similar to the original* matrix.** =====================================================================** .. Parameters ..DOUBLE PRECISION ZERO, ONE, TWO, THREEPARAMETER ( ZERO = 0.0D0, ONE = 1.0D0, TWO = 2.0D0,$ THREE = 3.0D0 )INTEGER MAXITPARAMETER ( MAXIT = 30 )* ..* .. Local Scalars ..INTEGER I, ICOMPZ, II, ISCALE, J, JTOT, K, L, L1, LEND,$ LENDM1, LENDP1, LENDSV, LM1, LSV, M, MM, MM1,$ NM1, NMAXITDOUBLE PRECISION ANORM, B, C, EPS, EPS2, F, G, P, R, RT1, RT2,$ S, SAFMAX, SAFMIN, SSFMAX, SSFMIN, TST* ..* .. External Functions ..LOGICAL LSAMEDOUBLE PRECISION DLAMCH, DLANST, DLAPY2EXTERNAL LSAME, DLAMCH, DLANST, DLAPY2* ..* .. External Subroutines ..EXTERNAL DLAE2, DLAEV2, DLARTG, DLASCL, DLASET, DLASR,$ DLASRT, DSWAP, XERBLA* ..* .. Intrinsic Functions ..INTRINSIC ABS, MAX, SIGN, SQRT* ..* .. Executable Statements ..** Test the input parameters.*INFO = 0*IF( LSAME( COMPZ, 'N' ) ) THENICOMPZ = 0ELSE IF( LSAME( COMPZ, 'V' ) ) THENICOMPZ = 1ELSE IF( LSAME( COMPZ, 'I' ) ) THENICOMPZ = 2ELSEICOMPZ = -1END IFIF( ICOMPZ.LT.0 ) THENINFO = -1ELSE IF( N.LT.0 ) THENINFO = -2ELSE IF( ( LDZ.LT.1 ) .OR. ( ICOMPZ.GT.0 .AND. LDZ.LT.MAX( 1,$ N ) ) ) THENINFO = -6END IFIF( INFO.NE.0 ) THENCALL XERBLA( 'DSTEQR', -INFO )RETURNEND IF** Quick return if possible*IF( N.EQ.0 )$ RETURN*IF( N.EQ.1 ) THENIF( ICOMPZ.EQ.2 )$ Z( 1, 1 ) = ONERETURNEND IF** Determine the unit roundoff and over/underflow thresholds.*EPS = DLAMCH( 'E' )EPS2 = EPS**2SAFMIN = DLAMCH( 'S' )SAFMAX = ONE / SAFMINSSFMAX = SQRT( SAFMAX ) / THREESSFMIN = SQRT( SAFMIN ) / EPS2** Compute the eigenvalues and eigenvectors of the tridiagonal* matrix.*IF( ICOMPZ.EQ.2 )$ CALL DLASET( 'Full', N, N, ZERO, ONE, Z, LDZ )*NMAXIT = N*MAXITJTOT = 0** Determine where the matrix splits and choose QL or QR iteration* for each block, according to whether top or bottom diagonal* element is smaller.*L1 = 1NM1 = N - 1*10 CONTINUEIF( L1.GT.N )$ GO TO 160IF( L1.GT.1 )$ E( L1-1 ) = ZEROIF( L1.LE.NM1 ) THENDO 20 M = L1, NM1TST = ABS( E( M ) )IF( TST.EQ.ZERO )$ GO TO 30IF( TST.LE.( SQRT( ABS( D( M ) ) )*SQRT( ABS( D( M+$ 1 ) ) ) )*EPS ) THENE( M ) = ZEROGO TO 30END IF20 CONTINUEEND IFM = N*30 CONTINUEL = L1LSV = LLEND = MLENDSV = LENDL1 = M + 1IF( LEND.EQ.L )$ GO TO 10** Scale submatrix in rows and columns L to LEND*ANORM = DLANST( 'I', LEND-L+1, D( L ), E( L ) )ISCALE = 0IF( ANORM.EQ.ZERO )$ GO TO 10IF( ANORM.GT.SSFMAX ) THENISCALE = 1CALL DLASCL( 'G', 0, 0, ANORM, SSFMAX, LEND-L+1, 1, D( L ), N,$ INFO )CALL DLASCL( 'G', 0, 0, ANORM, SSFMAX, LEND-L, 1, E( L ), N,$ INFO )ELSE IF( ANORM.LT.SSFMIN ) THENISCALE = 2CALL DLASCL( 'G', 0, 0, ANORM, SSFMIN, LEND-L+1, 1, D( L ), N,$ INFO )CALL DLASCL( 'G', 0, 0, ANORM, SSFMIN, LEND-L, 1, E( L ), N,$ INFO )END IF** Choose between QL and QR iteration*IF( ABS( D( LEND ) ).LT.ABS( D( L ) ) ) THENLEND = LSVL = LENDSVEND IF*IF( LEND.GT.L ) THEN** QL Iteration** Look for small subdiagonal element.*40 CONTINUEIF( L.NE.LEND ) THENLENDM1 = LEND - 1DO 50 M = L, LENDM1TST = ABS( E( M ) )**2IF( TST.LE.( EPS2*ABS( D( M ) ) )*ABS( D( M+1 ) )+$ SAFMIN )GO TO 6050 CONTINUEEND IF*M = LEND*60 CONTINUEIF( M.LT.LEND )$ E( M ) = ZEROP = D( L )IF( M.EQ.L )$ GO TO 80** If remaining matrix is 2-by-2, use DLAE2 or SLAEV2* to compute its eigensystem.*IF( M.EQ.L+1 ) THENIF( ICOMPZ.GT.0 ) THENCALL DLAEV2( D( L ), E( L ), D( L+1 ), RT1, RT2, C, S )WORK( L ) = CWORK( N-1+L ) = SCALL DLASR( 'R', 'V', 'B', N, 2, WORK( L ),$ WORK( N-1+L ), Z( 1, L ), LDZ )ELSECALL DLAE2( D( L ), E( L ), D( L+1 ), RT1, RT2 )END IFD( L ) = RT1D( L+1 ) = RT2E( L ) = ZEROL = L + 2IF( L.LE.LEND )$ GO TO 40GO TO 140END IF*IF( JTOT.EQ.NMAXIT )$ GO TO 140JTOT = JTOT + 1** Form shift.*G = ( D( L+1 )-P ) / ( TWO*E( L ) )R = DLAPY2( G, ONE )G = D( M ) - P + ( E( L ) / ( G+SIGN( R, G ) ) )*S = ONEC = ONEP = ZERO** Inner loop*MM1 = M - 1DO 70 I = MM1, L, -1F = S*E( I )B = C*E( I )CALL DLARTG( G, F, C, S, R )IF( I.NE.M-1 )$ E( I+1 ) = RG = D( I+1 ) - PR = ( D( I )-G )*S + TWO*C*BP = S*RD( I+1 ) = G + PG = C*R - B** If eigenvectors are desired, then save rotations.*IF( ICOMPZ.GT.0 ) THENWORK( I ) = CWORK( N-1+I ) = -SEND IF*70 CONTINUE** If eigenvectors are desired, then apply saved rotations.*IF( ICOMPZ.GT.0 ) THENMM = M - L + 1CALL DLASR( 'R', 'V', 'B', N, MM, WORK( L ), WORK( N-1+L ),$ Z( 1, L ), LDZ )END IF*D( L ) = D( L ) - PE( L ) = GGO TO 40** Eigenvalue found.*80 CONTINUED( L ) = P*L = L + 1IF( L.LE.LEND )$ GO TO 40GO TO 140*ELSE** QR Iteration** Look for small superdiagonal element.*90 CONTINUEIF( L.NE.LEND ) THENLENDP1 = LEND + 1DO 100 M = L, LENDP1, -1TST = ABS( E( M-1 ) )**2IF( TST.LE.( EPS2*ABS( D( M ) ) )*ABS( D( M-1 ) )+$ SAFMIN )GO TO 110100 CONTINUEEND IF*M = LEND*110 CONTINUEIF( M.GT.LEND )$ E( M-1 ) = ZEROP = D( L )IF( M.EQ.L )$ GO TO 130** If remaining matrix is 2-by-2, use DLAE2 or SLAEV2* to compute its eigensystem.*IF( M.EQ.L-1 ) THENIF( ICOMPZ.GT.0 ) THENCALL DLAEV2( D( L-1 ), E( L-1 ), D( L ), RT1, RT2, C, S )WORK( M ) = CWORK( N-1+M ) = SCALL DLASR( 'R', 'V', 'F', N, 2, WORK( M ),$ WORK( N-1+M ), Z( 1, L-1 ), LDZ )ELSECALL DLAE2( D( L-1 ), E( L-1 ), D( L ), RT1, RT2 )END IFD( L-1 ) = RT1D( L ) = RT2E( L-1 ) = ZEROL = L - 2IF( L.GE.LEND )$ GO TO 90GO TO 140END IF*IF( JTOT.EQ.NMAXIT )$ GO TO 140JTOT = JTOT + 1** Form shift.*G = ( D( L-1 )-P ) / ( TWO*E( L-1 ) )R = DLAPY2( G, ONE )G = D( M ) - P + ( E( L-1 ) / ( G+SIGN( R, G ) ) )*S = ONEC = ONEP = ZERO** Inner loop*LM1 = L - 1DO 120 I = M, LM1F = S*E( I )B = C*E( I )CALL DLARTG( G, F, C, S, R )IF( I.NE.M )$ E( I-1 ) = RG = D( I ) - PR = ( D( I+1 )-G )*S + TWO*C*BP = S*RD( I ) = G + PG = C*R - B** If eigenvectors are desired, then save rotations.*IF( ICOMPZ.GT.0 ) THENWORK( I ) = CWORK( N-1+I ) = SEND IF*120 CONTINUE** If eigenvectors are desired, then apply saved rotations.*IF( ICOMPZ.GT.0 ) THENMM = L - M + 1CALL DLASR( 'R', 'V', 'F', N, MM, WORK( M ), WORK( N-1+M ),$ Z( 1, M ), LDZ )END IF*D( L ) = D( L ) - PE( LM1 ) = GGO TO 90** Eigenvalue found.*130 CONTINUED( L ) = P*L = L - 1IF( L.GE.LEND )$ GO TO 90GO TO 140*END IF** Undo scaling if necessary*140 CONTINUEIF( ISCALE.EQ.1 ) THENCALL DLASCL( 'G', 0, 0, SSFMAX, ANORM, LENDSV-LSV+1, 1,$ D( LSV ), N, INFO )CALL DLASCL( 'G', 0, 0, SSFMAX, ANORM, LENDSV-LSV, 1, E( LSV ),$ N, INFO )ELSE IF( ISCALE.EQ.2 ) THENCALL DLASCL( 'G', 0, 0, SSFMIN, ANORM, LENDSV-LSV+1, 1,$ D( LSV ), N, INFO )CALL DLASCL( 'G', 0, 0, SSFMIN, ANORM, LENDSV-LSV, 1, E( LSV ),$ N, INFO )END IF** Check for no convergence to an eigenvalue after a total* of N*MAXIT iterations.*IF( JTOT.LT.NMAXIT )$ GO TO 10DO 150 I = 1, N - 1IF( E( I ).NE.ZERO )$ INFO = INFO + 1150 CONTINUEGO TO 190** Order eigenvalues and eigenvectors.*160 CONTINUEIF( ICOMPZ.EQ.0 ) THEN** Use Quick Sort*CALL DLASRT( 'I', N, D, INFO )*ELSE** Use Selection Sort to minimize swaps of eigenvectors*DO 180 II = 2, NI = II - 1K = IP = D( I )DO 170 J = II, NIF( D( J ).LT.P ) THENK = JP = D( J )END IF170 CONTINUEIF( K.NE.I ) THEND( K ) = D( I )D( I ) = PCALL DSWAP( N, Z( 1, I ), 1, Z( 1, K ), 1 )END IF180 CONTINUEEND IF*190 CONTINUERETURN** End of DSTEQR*ENDSUBROUTINE DSTERF( N, D, E, INFO )** -- LAPACK routine (version 3.0) --* Univ. of Tennessee, Univ. of California Berkeley, NAG Ltd.,* Courant Institute, Argonne National Lab, and Rice University* June 30, 1999** .. Scalar Arguments ..INTEGER INFO, N* ..* .. Array Arguments ..DOUBLE PRECISION D( * ), E( * )* ..** Purpose* =======** DSTERF computes all eigenvalues of a symmetric tridiagonal matrix* using the Pal-Walker-Kahan variant of the QL or QR algorithm.** Arguments* =========** N (input) INTEGER* The order of the matrix. N >= 0.** D (input/output) DOUBLE PRECISION array, dimension (N)* On entry, the n diagonal elements of the tridiagonal matrix.* On exit, if INFO = 0, the eigenvalues in ascending order.** E (input/output) DOUBLE PRECISION array, dimension (N-1)* On entry, the (n-1) subdiagonal elements of the tridiagonal* matrix.* On exit, E has been destroyed.** INFO (output) INTEGER* = 0: successful exit* < 0: if INFO = -i, the i-th argument had an illegal value* > 0: the algorithm failed to find all of the eigenvalues in* a total of 30*N iterations; if INFO = i, then i* elements of E have not converged to zero.** =====================================================================** .. Parameters ..DOUBLE PRECISION ZERO, ONE, TWO, THREEPARAMETER ( ZERO = 0.0D0, ONE = 1.0D0, TWO = 2.0D0,$ THREE = 3.0D0 )INTEGER MAXITPARAMETER ( MAXIT = 30 )* ..* .. Local Scalars ..INTEGER I, ISCALE, JTOT, L, L1, LEND, LENDSV, LSV, M,$ NMAXITDOUBLE PRECISION ALPHA, ANORM, BB, C, EPS, EPS2, GAMMA, OLDC,$ OLDGAM, P, R, RT1, RT2, RTE, S, SAFMAX, SAFMIN,$ SIGMA, SSFMAX, SSFMIN* ..* .. External Functions ..DOUBLE PRECISION DLAMCH, DLANST, DLAPY2EXTERNAL DLAMCH, DLANST, DLAPY2* ..* .. External Subroutines ..EXTERNAL DLAE2, DLASCL, DLASRT, XERBLA* ..* .. Intrinsic Functions ..INTRINSIC ABS, SIGN, SQRT* ..* .. Executable Statements ..** Test the input parameters.*INFO = 0** Quick return if possible*IF( N.LT.0 ) THENINFO = -1CALL XERBLA( 'DSTERF', -INFO )RETURNEND IFIF( N.LE.1 )$ RETURN** Determine the unit roundoff for this environment.*EPS = DLAMCH( 'E' )EPS2 = EPS**2SAFMIN = DLAMCH( 'S' )SAFMAX = ONE / SAFMINSSFMAX = SQRT( SAFMAX ) / THREESSFMIN = SQRT( SAFMIN ) / EPS2** Compute the eigenvalues of the tridiagonal matrix.*NMAXIT = N*MAXITSIGMA = ZEROJTOT = 0** Determine where the matrix splits and choose QL or QR iteration* for each block, according to whether top or bottom diagonal* element is smaller.*L1 = 1*10 CONTINUEIF( L1.GT.N )$ GO TO 170IF( L1.GT.1 )$ E( L1-1 ) = ZERODO 20 M = L1, N - 1IF( ABS( E( M ) ).LE.( SQRT( ABS( D( M ) ) )*SQRT( ABS( D( M+$ 1 ) ) ) )*EPS ) THENE( M ) = ZEROGO TO 30END IF20 CONTINUEM = N*30 CONTINUEL = L1LSV = LLEND = MLENDSV = LENDL1 = M + 1IF( LEND.EQ.L )$ GO TO 10** Scale submatrix in rows and columns L to LEND*ANORM = DLANST( 'I', LEND-L+1, D( L ), E( L ) )ISCALE = 0IF( ANORM.GT.SSFMAX ) THENISCALE = 1CALL DLASCL( 'G', 0, 0, ANORM, SSFMAX, LEND-L+1, 1, D( L ), N,$ INFO )CALL DLASCL( 'G', 0, 0, ANORM, SSFMAX, LEND-L, 1, E( L ), N,$ INFO )ELSE IF( ANORM.LT.SSFMIN ) THENISCALE = 2CALL DLASCL( 'G', 0, 0, ANORM, SSFMIN, LEND-L+1, 1, D( L ), N,$ INFO )CALL DLASCL( 'G', 0, 0, ANORM, SSFMIN, LEND-L, 1, E( L ), N,$ INFO )END IF*DO 40 I = L, LEND - 1E( I ) = E( I )**240 CONTINUE** Choose between QL and QR iteration*IF( ABS( D( LEND ) ).LT.ABS( D( L ) ) ) THENLEND = LSVL = LENDSVEND IF*IF( LEND.GE.L ) THEN** QL Iteration** Look for small subdiagonal element.*50 CONTINUEIF( L.NE.LEND ) THENDO 60 M = L, LEND - 1IF( ABS( E( M ) ).LE.EPS2*ABS( D( M )*D( M+1 ) ) )$ GO TO 7060 CONTINUEEND IFM = LEND*70 CONTINUEIF( M.LT.LEND )$ E( M ) = ZEROP = D( L )IF( M.EQ.L )$ GO TO 90** If remaining matrix is 2 by 2, use DLAE2 to compute its* eigenvalues.*IF( M.EQ.L+1 ) THENRTE = SQRT( E( L ) )CALL DLAE2( D( L ), RTE, D( L+1 ), RT1, RT2 )D( L ) = RT1D( L+1 ) = RT2E( L ) = ZEROL = L + 2IF( L.LE.LEND )$ GO TO 50GO TO 150END IF*IF( JTOT.EQ.NMAXIT )$ GO TO 150JTOT = JTOT + 1** Form shift.*RTE = SQRT( E( L ) )SIGMA = ( D( L+1 )-P ) / ( TWO*RTE )R = DLAPY2( SIGMA, ONE )SIGMA = P - ( RTE / ( SIGMA+SIGN( R, SIGMA ) ) )*C = ONES = ZEROGAMMA = D( M ) - SIGMAP = GAMMA*GAMMA** Inner loop*DO 80 I = M - 1, L, -1BB = E( I )R = P + BBIF( I.NE.M-1 )$ E( I+1 ) = S*ROLDC = CC = P / RS = BB / ROLDGAM = GAMMAALPHA = D( I )GAMMA = C*( ALPHA-SIGMA ) - S*OLDGAMD( I+1 ) = OLDGAM + ( ALPHA-GAMMA )IF( C.NE.ZERO ) THENP = ( GAMMA*GAMMA ) / CELSEP = OLDC*BBEND IF80 CONTINUE*E( L ) = S*PD( L ) = SIGMA + GAMMAGO TO 50** Eigenvalue found.*90 CONTINUED( L ) = P*L = L + 1IF( L.LE.LEND )$ GO TO 50GO TO 150*ELSE** QR Iteration** Look for small superdiagonal element.*100 CONTINUEDO 110 M = L, LEND + 1, -1IF( ABS( E( M-1 ) ).LE.EPS2*ABS( D( M )*D( M-1 ) ) )$ GO TO 120110 CONTINUEM = LEND*120 CONTINUEIF( M.GT.LEND )$ E( M-1 ) = ZEROP = D( L )IF( M.EQ.L )$ GO TO 140** If remaining matrix is 2 by 2, use DLAE2 to compute its* eigenvalues.*IF( M.EQ.L-1 ) THENRTE = SQRT( E( L-1 ) )CALL DLAE2( D( L ), RTE, D( L-1 ), RT1, RT2 )D( L ) = RT1D( L-1 ) = RT2E( L-1 ) = ZEROL = L - 2IF( L.GE.LEND )$ GO TO 100GO TO 150END IF*IF( JTOT.EQ.NMAXIT )$ GO TO 150JTOT = JTOT + 1** Form shift.*RTE = SQRT( E( L-1 ) )SIGMA = ( D( L-1 )-P ) / ( TWO*RTE )R = DLAPY2( SIGMA, ONE )SIGMA = P - ( RTE / ( SIGMA+SIGN( R, SIGMA ) ) )*C = ONES = ZEROGAMMA = D( M ) - SIGMAP = GAMMA*GAMMA** Inner loop*DO 130 I = M, L - 1BB = E( I )R = P + BBIF( I.NE.M )$ E( I-1 ) = S*ROLDC = CC = P / RS = BB / ROLDGAM = GAMMAALPHA = D( I+1 )GAMMA = C*( ALPHA-SIGMA ) - S*OLDGAMD( I ) = OLDGAM + ( ALPHA-GAMMA )IF( C.NE.ZERO ) THENP = ( GAMMA*GAMMA ) / CELSEP = OLDC*BBEND IF130 CONTINUE*E( L-1 ) = S*PD( L ) = SIGMA + GAMMAGO TO 100** Eigenvalue found.*140 CONTINUED( L ) = P*L = L - 1IF( L.GE.LEND )$ GO TO 100GO TO 150*END IF** Undo scaling if necessary*150 CONTINUEIF( ISCALE.EQ.1 )$ CALL DLASCL( 'G', 0, 0, SSFMAX, ANORM, LENDSV-LSV+1, 1,$ D( LSV ), N, INFO )IF( ISCALE.EQ.2 )$ CALL DLASCL( 'G', 0, 0, SSFMIN, ANORM, LENDSV-LSV+1, 1,$ D( LSV ), N, INFO )** Check for no convergence to an eigenvalue after a total* of N*MAXIT iterations.*IF( JTOT.LT.NMAXIT )$ GO TO 10DO 160 I = 1, N - 1IF( E( I ).NE.ZERO )$ INFO = INFO + 1160 CONTINUEGO TO 180** Sort eigenvalues in increasing order.*170 CONTINUECALL DLASRT( 'I', N, D, INFO )*180 CONTINUERETURN** End of DSTERF*ENDSUBROUTINE RSYEV( 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 DSYTD2( UPLO, N, A, LDA, D, E, TAU, INFO )** -- LAPACK routine (version 3.0) --* Univ. of Tennessee, Univ. of California Berkeley, NAG Ltd.,* Courant Institute, Argonne National Lab, and Rice University* October 31, 1992** .. Scalar Arguments ..CHARACTER UPLOINTEGER INFO, LDA, N* ..* .. Array Arguments ..DOUBLE PRECISION A( LDA, * ), D( * ), E( * ), TAU( * )* ..** Purpose* =======** DSYTD2 reduces a real symmetric matrix A to symmetric tridiagonal* form T by an orthogonal similarity transformation: Q' * A * Q = T.** Arguments* =========** UPLO (input) CHARACTER*1* Specifies whether the upper or lower triangular part of the* symmetric matrix A is stored:* = 'U': Upper triangular* = 'L': Lower triangular** N (input) INTEGER* The order of the matrix A. N >= 0.** A (input/output) DOUBLE PRECISION array, dimension (LDA,N)* On entry, the symmetric matrix A. If UPLO = 'U', the leading* n-by-n upper triangular part of A contains the upper* triangular part of the matrix A, and the strictly lower* triangular part of A is not referenced. If UPLO = 'L', the* leading n-by-n lower triangular part of A contains the lower* triangular part of the matrix A, and the strictly upper* triangular part of A is not referenced.* On exit, if UPLO = 'U', the diagonal and first superdiagonal* of A are overwritten by the corresponding elements of the* tridiagonal matrix T, and the elements above the first* superdiagonal, with the array TAU, represent the orthogonal* matrix Q as a product of elementary reflectors; if UPLO* = 'L', the diagonal and first subdiagonal of A are over-* written by the corresponding elements of the tridiagonal* matrix T, and the elements below the first subdiagonal, with* the array TAU, represent the orthogonal matrix Q as a product* of elementary reflectors. See Further Details.** LDA (input) INTEGER* The leading dimension of the array A. LDA >= max(1,N).** D (output) DOUBLE PRECISION array, dimension (N)* The diagonal elements of the tridiagonal matrix T:* D(i) = A(i,i).** E (output) DOUBLE PRECISION array, dimension (N-1)* The off-diagonal elements of the tridiagonal matrix T:* E(i) = A(i,i+1) if UPLO = 'U', E(i) = A(i+1,i) if UPLO = 'L'.** TAU (output) DOUBLE PRECISION array, dimension (N-1)* The scalar factors of the elementary reflectors (see Further* Details).** INFO (output) INTEGER* = 0: successful exit* < 0: if INFO = -i, the i-th argument had an illegal value.** Further Details* ===============** If UPLO = 'U', the matrix Q is represented as a product of elementary* reflectors** Q = H(n-1) . . . H(2) H(1).** Each H(i) has the form** H(i) = I - tau * v * v'** where tau is a real scalar, and v is a real vector with* v(i+1:n) = 0 and v(i) = 1; v(1:i-1) is stored on exit in* A(1:i-1,i+1), and tau in TAU(i).** If UPLO = 'L', the matrix Q is represented as a product of elementary* reflectors** Q = H(1) H(2) . . . H(n-1).** Each H(i) has the form** H(i) = I - tau * v * v'** where tau is a real scalar, and v is a real vector with* v(1:i) = 0 and v(i+1) = 1; v(i+2:n) is stored on exit in A(i+2:n,i),* and tau in TAU(i).** The contents of A on exit are illustrated by the following examples* with n = 5:** if UPLO = 'U': if UPLO = 'L':** ( d e v2 v3 v4 ) ( d )* ( d e v3 v4 ) ( e d )* ( d e v4 ) ( v1 e d )* ( d e ) ( v1 v2 e d )* ( d ) ( v1 v2 v3 e d )** where d and e denote diagonal and off-diagonal elements of T, and vi* denotes an element of the vector defining H(i).** =====================================================================** .. Parameters ..DOUBLE PRECISION ONE, ZERO, HALFPARAMETER ( ONE = 1.0D0, ZERO = 0.0D0,$ HALF = 1.0D0 / 2.0D0 )* ..* .. Local Scalars ..LOGICAL UPPERINTEGER IDOUBLE PRECISION ALPHA, TAUI* ..* .. External Subroutines ..EXTERNAL DAXPY, DLARFG, DSYMV, DSYR2, XERBLA* ..* .. External Functions ..LOGICAL LSAMEDOUBLE PRECISION DDOTEXTERNAL LSAME, DDOT* ..* .. Intrinsic Functions ..INTRINSIC MAX, MIN* ..* .. Executable Statements ..** Test the input parameters*INFO = 0UPPER = LSAME( UPLO, 'U' )IF( .NOT.UPPER .AND. .NOT.LSAME( UPLO, 'L' ) ) THENINFO = -1ELSE IF( N.LT.0 ) THENINFO = -2ELSE IF( LDA.LT.MAX( 1, N ) ) THENINFO = -4END IFIF( INFO.NE.0 ) THENCALL XERBLA( 'DSYTD2', -INFO )RETURNEND IF** Quick return if possible*IF( N.LE.0 )$ RETURN*IF( UPPER ) THEN** Reduce the upper triangle of A*DO 10 I = N - 1, 1, -1** Generate elementary reflector H(i) = I - tau * v * v'* to annihilate A(1:i-1,i+1)*CALL DLARFG( I, A( I, I+1 ), A( 1, I+1 ), 1, TAUI )E( I ) = A( I, I+1 )*IF( TAUI.NE.ZERO ) THEN** Apply H(i) from both sides to A(1:i,1:i)*A( I, I+1 ) = ONE** Compute x := tau * A * v storing x in TAU(1:i)*CALL DSYMV( UPLO, I, TAUI, A, LDA, A( 1, I+1 ), 1, ZERO,$ TAU, 1 )** Compute w := x - 1/2 * tau * (x'*v) * v*ALPHA = -HALF*TAUI*DDOT( I, TAU, 1, A( 1, I+1 ), 1 )CALL DAXPY( I, ALPHA, A( 1, I+1 ), 1, TAU, 1 )** Apply the transformation as a rank-2 update:* A := A - v * w' - w * v'*CALL DSYR2( UPLO, I, -ONE, A( 1, I+1 ), 1, TAU, 1, A,$ LDA )*A( I, I+1 ) = E( I )END IFD( I+1 ) = A( I+1, I+1 )TAU( I ) = TAUI10 CONTINUED( 1 ) = A( 1, 1 )ELSE** Reduce the lower triangle of A*DO 20 I = 1, N - 1** Generate elementary reflector H(i) = I - tau * v * v'* to annihilate A(i+2:n,i)*CALL DLARFG( N-I, A( I+1, I ), A( MIN( I+2, N ), I ), 1,$ TAUI )E( I ) = A( I+1, I )*IF( TAUI.NE.ZERO ) THEN** Apply H(i) from both sides to A(i+1:n,i+1:n)*A( I+1, I ) = ONE** Compute x := tau * A * v storing y in TAU(i:n-1)*CALL DSYMV( UPLO, N-I, TAUI, A( I+1, I+1 ), LDA,$ A( I+1, I ), 1, ZERO, TAU( I ), 1 )** Compute w := x - 1/2 * tau * (x'*v) * v*ALPHA = -HALF*TAUI*DDOT( N-I, TAU( I ), 1, A( I+1, I ),$ 1 )CALL DAXPY( N-I, ALPHA, A( I+1, I ), 1, TAU( I ), 1 )** Apply the transformation as a rank-2 update:* A := A - v * w' - w * v'*CALL DSYR2( UPLO, N-I, -ONE, A( I+1, I ), 1, TAU( I ), 1,$ A( I+1, I+1 ), LDA )*A( I+1, I ) = E( I )END IFD( I ) = A( I, I )TAU( I ) = TAUI20 CONTINUED( N ) = A( N, N )END IF*RETURN** End of DSYTD2*ENDSUBROUTINE DSYTRD( UPLO, N, A, LDA, D, E, TAU, WORK, LWORK, INFO )** -- LAPACK routine (version 3.0) --* Univ. of Tennessee, Univ. of California Berkeley, NAG Ltd.,* Courant Institute, Argonne National Lab, and Rice University* June 30, 1999** .. Scalar Arguments ..CHARACTER UPLOINTEGER INFO, LDA, LWORK, N* ..* .. Array Arguments ..DOUBLE PRECISION A( LDA, * ), D( * ), E( * ), TAU( * ),$ WORK( * )* ..** Purpose* =======** DSYTRD reduces a real symmetric matrix A to real symmetric* tridiagonal form T by an orthogonal similarity transformation:* Q**T * A * Q = T.** Arguments* =========** UPLO (input) CHARACTER*1* = 'U': Upper triangle of A is stored;* = 'L': Lower triangle of A is stored.** N (input) INTEGER* The order of the matrix A. N >= 0.** A (input/output) DOUBLE PRECISION array, dimension (LDA,N)* On entry, the symmetric matrix A. If UPLO = 'U', the leading* N-by-N upper triangular part of A contains the upper* triangular part of the matrix A, and the strictly lower* triangular part of A is not referenced. If UPLO = 'L', the* leading N-by-N lower triangular part of A contains the lower* triangular part of the matrix A, and the strictly upper* triangular part of A is not referenced.* On exit, if UPLO = 'U', the diagonal and first superdiagonal* of A are overwritten by the corresponding elements of the* tridiagonal matrix T, and the elements above the first* superdiagonal, with the array TAU, represent the orthogonal* matrix Q as a product of elementary reflectors; if UPLO* = 'L', the diagonal and first subdiagonal of A are over-* written by the corresponding elements of the tridiagonal* matrix T, and the elements below the first subdiagonal, with* the array TAU, represent the orthogonal matrix Q as a product* of elementary reflectors. See Further Details.** LDA (input) INTEGER* The leading dimension of the array A. LDA >= max(1,N).** D (output) DOUBLE PRECISION array, dimension (N)* The diagonal elements of the tridiagonal matrix T:* D(i) = A(i,i).** E (output) DOUBLE PRECISION array, dimension (N-1)* The off-diagonal elements of the tridiagonal matrix T:* E(i) = A(i,i+1) if UPLO = 'U', E(i) = A(i+1,i) if UPLO = 'L'.** TAU (output) DOUBLE PRECISION array, dimension (N-1)* The scalar factors of the elementary reflectors (see Further* Details).** WORK (workspace/output) DOUBLE PRECISION array, dimension (LWORK)* On exit, if INFO = 0, WORK(1) returns the optimal LWORK.** LWORK (input) INTEGER* The dimension of the array WORK. LWORK >= 1.* For optimum performance LWORK >= N*NB, where NB is the* optimal blocksize.** If LWORK = -1, then a workspace query is assumed; the routine* only calculates the optimal size of the WORK array, returns* this value as the first entry of the WORK array, and no error* message related to LWORK is issued by XERBLA.** INFO (output) INTEGER* = 0: successful exit* < 0: if INFO = -i, the i-th argument had an illegal value** Further Details* ===============** If UPLO = 'U', the matrix Q is represented as a product of elementary* reflectors** Q = H(n-1) . . . H(2) H(1).** Each H(i) has the form** H(i) = I - tau * v * v'** where tau is a real scalar, and v is a real vector with* v(i+1:n) = 0 and v(i) = 1; v(1:i-1) is stored on exit in* A(1:i-1,i+1), and tau in TAU(i).** If UPLO = 'L', the matrix Q is represented as a product of elementary* reflectors** Q = H(1) H(2) . . . H(n-1).** Each H(i) has the form** H(i) = I - tau * v * v'** where tau is a real scalar, and v is a real vector with* v(1:i) = 0 and v(i+1) = 1; v(i+2:n) is stored on exit in A(i+2:n,i),* and tau in TAU(i).** The contents of A on exit are illustrated by the following examples* with n = 5:** if UPLO = 'U': if UPLO = 'L':** ( d e v2 v3 v4 ) ( d )* ( d e v3 v4 ) ( e d )* ( d e v4 ) ( v1 e d )* ( d e ) ( v1 v2 e d )* ( d ) ( v1 v2 v3 e d )** where d and e denote diagonal and off-diagonal elements of T, and vi* denotes an element of the vector defining H(i).** =====================================================================** .. Parameters ..DOUBLE PRECISION ONEPARAMETER ( ONE = 1.0D+0 )* ..* .. Local Scalars ..LOGICAL LQUERY, UPPERINTEGER I, IINFO, IWS, J, KK, LDWORK, LWKOPT, NB,$ NBMIN, NX* ..* .. External Subroutines ..EXTERNAL DLATRD, DSYR2K, DSYTD2, XERBLA* ..* .. Intrinsic Functions ..INTRINSIC MAX* ..* .. External Functions ..LOGICAL LSAMEINTEGER ILAENVEXTERNAL LSAME, ILAENV* ..* .. Executable Statements ..** Test the input parameters*INFO = 0UPPER = LSAME( UPLO, 'U' )LQUERY = ( LWORK.EQ.-1 )IF( .NOT.UPPER .AND. .NOT.LSAME( UPLO, 'L' ) ) THENINFO = -1ELSE IF( N.LT.0 ) THENINFO = -2ELSE IF( LDA.LT.MAX( 1, N ) ) THENINFO = -4ELSE IF( LWORK.LT.1 .AND. .NOT.LQUERY ) THENINFO = -9END IF*IF( INFO.EQ.0 ) THEN** Determine the block size.*NB = ILAENV( 1, 'DSYTRD', UPLO, N, -1, -1, -1 )LWKOPT = N*NBWORK( 1 ) = LWKOPTEND IF*IF( INFO.NE.0 ) THENCALL XERBLA( 'DSYTRD', -INFO )RETURNELSE IF( LQUERY ) THENRETURNEND IF** Quick return if possible*IF( N.EQ.0 ) THENWORK( 1 ) = 1RETURNEND IF*NX = NIWS = 1IF( NB.GT.1 .AND. NB.LT.N ) THEN** Determine when to cross over from blocked to unblocked code* (last block is always handled by unblocked code).*NX = MAX( NB, ILAENV( 3, 'DSYTRD', UPLO, N, -1, -1, -1 ) )IF( NX.LT.N ) THEN** Determine if workspace is large enough for blocked code.*LDWORK = NIWS = LDWORK*NBIF( LWORK.LT.IWS ) THEN** Not enough workspace to use optimal NB: determine the* minimum value of NB, and reduce NB or force use of* unblocked code by setting NX = N.*NB = MAX( LWORK / LDWORK, 1 )NBMIN = ILAENV( 2, 'DSYTRD', UPLO, N, -1, -1, -1 )IF( NB.LT.NBMIN )$ NX = NEND IFELSENX = NEND IFELSENB = 1END IF*IF( UPPER ) THEN** Reduce the upper triangle of A.* Columns 1:kk are handled by the unblocked method.*KK = N - ( ( N-NX+NB-1 ) / NB )*NBDO 20 I = N - NB + 1, KK + 1, -NB** Reduce columns i:i+nb-1 to tridiagonal form and form the* matrix W which is needed to update the unreduced part of* the matrix*CALL DLATRD( UPLO, I+NB-1, NB, A, LDA, E, TAU, WORK,$ LDWORK )** Update the unreduced submatrix A(1:i-1,1:i-1), using an* update of the form: A := A - V*W' - W*V'*CALL DSYR2K( UPLO, 'No transpose', I-1, NB, -ONE, A( 1, I ),$ LDA, WORK, LDWORK, ONE, A, LDA )** Copy superdiagonal elements back into A, and diagonal* elements into D*DO 10 J = I, I + NB - 1A( J-1, J ) = E( J-1 )D( J ) = A( J, J )10 CONTINUE20 CONTINUE** Use unblocked code to reduce the last or only block*CALL DSYTD2( UPLO, KK, A, LDA, D, E, TAU, IINFO )ELSE** Reduce the lower triangle of A*DO 40 I = 1, N - NX, NB** Reduce columns i:i+nb-1 to tridiagonal form and form the* matrix W which is needed to update the unreduced part of* the matrix*CALL DLATRD( UPLO, N-I+1, NB, A( I, I ), LDA, E( I ),$ TAU( I ), WORK, LDWORK )** Update the unreduced submatrix A(i+ib:n,i+ib:n), using* an update of the form: A := A - V*W' - W*V'*CALL DSYR2K( UPLO, 'No transpose', N-I-NB+1, NB, -ONE,$ A( I+NB, I ), LDA, WORK( NB+1 ), LDWORK, ONE,$ A( I+NB, I+NB ), LDA )** Copy subdiagonal elements back into A, and diagonal* elements into D*DO 30 J = I, I + NB - 1A( J+1, J ) = E( J )D( J ) = A( J, J )30 CONTINUE40 CONTINUE** Use unblocked code to reduce the last or only block*CALL DSYTD2( UPLO, N-I+1, A( I, I ), LDA, D( I ), E( I ),$ TAU( I ), IINFO )END IF*WORK( 1 ) = LWKOPTRETURN** End of DSYTRD*ENDSUBROUTINE DTREVC( SIDE, HOWMNY, SELECT, N, T, LDT, VL, LDVL, VR,$ LDVR, MM, M, WORK, INFO )** -- LAPACK routine (version 3.0) --* Univ. of Tennessee, Univ. of California Berkeley, NAG Ltd.,* Courant Institute, Argonne National Lab, and Rice University* June 30, 1999** .. Scalar Arguments ..CHARACTER HOWMNY, SIDEINTEGER INFO, LDT, LDVL, LDVR, M, MM, N* ..* .. Array Arguments ..LOGICAL SELECT( * )DOUBLE PRECISION T( LDT, * ), VL( LDVL, * ), VR( LDVR, * ),$ WORK( * )* ..** Purpose* =======** DTREVC computes some or all of the right and/or left eigenvectors of* a real upper quasi-triangular matrix T.** The right eigenvector x and the left eigenvector y of T corresponding* to an eigenvalue w are defined by:** T*x = w*x, y'*T = w*y'** where y' denotes the conjugate transpose of the vector y.** If all eigenvectors are requested, the routine may either return the* matrices X and/or Y of right or left eigenvectors of T, or the* products Q*X and/or Q*Y, where Q is an input orthogonal* matrix. If T was obtained from the real-Schur factorization of an* original matrix A = Q*T*Q', then Q*X and Q*Y are the matrices of* right or left eigenvectors of A.** T must be in Schur canonical form (as returned by DHSEQR), that is,* block upper triangular with 1-by-1 and 2-by-2 diagonal blocks; each* 2-by-2 diagonal block has its diagonal elements equal and its* off-diagonal elements of opposite sign. Corresponding to each 2-by-2* diagonal block is a complex conjugate pair of eigenvalues and* eigenvectors; only one eigenvector of the pair is computed, namely* the one corresponding to the eigenvalue with positive imaginary part.** Arguments* =========** SIDE (input) CHARACTER*1* = 'R': compute right eigenvectors only;* = 'L': compute left eigenvectors only;* = 'B': compute both right and left eigenvectors.** HOWMNY (input) CHARACTER*1* = 'A': compute all right and/or left eigenvectors;* = 'B': compute all right and/or left eigenvectors,* and backtransform them using the input matrices* supplied in VR and/or VL;* = 'S': compute selected right and/or left eigenvectors,* specified by the logical array SELECT.** SELECT (input/output) LOGICAL array, dimension (N)* If HOWMNY = 'S', SELECT specifies the eigenvectors to be* computed.* If HOWMNY = 'A' or 'B', SELECT is not referenced.* To select the real eigenvector corresponding to a real* eigenvalue w(j), SELECT(j) must be set to .TRUE.. To select* the complex eigenvector corresponding to a complex conjugate* pair w(j) and w(j+1), either SELECT(j) or SELECT(j+1) must be* set to .TRUE.; then on exit SELECT(j) is .TRUE. and* SELECT(j+1) is .FALSE..** N (input) INTEGER* The order of the matrix T. N >= 0.** T (input) DOUBLE PRECISION array, dimension (LDT,N)* The upper quasi-triangular matrix T in Schur canonical form.** LDT (input) INTEGER* The leading dimension of the array T. LDT >= max(1,N).** VL (input/output) DOUBLE PRECISION array, dimension (LDVL,MM)* On entry, if SIDE = 'L' or 'B' and HOWMNY = 'B', VL must* contain an N-by-N matrix Q (usually the orthogonal matrix Q* of Schur vectors returned by DHSEQR).* On exit, if SIDE = 'L' or 'B', VL contains:* if HOWMNY = 'A', the matrix Y of left eigenvectors of T;* VL has the same quasi-lower triangular form* as T'. If T(i,i) is a real eigenvalue, then* the i-th column VL(i) of VL is its* corresponding eigenvector. If T(i:i+1,i:i+1)* is a 2-by-2 block whose eigenvalues are* complex-conjugate eigenvalues of T, then* VL(i)+sqrt(-1)*VL(i+1) is the complex* eigenvector corresponding to the eigenvalue* with positive real part.* if HOWMNY = 'B', the matrix Q*Y;* if HOWMNY = 'S', the left eigenvectors of T specified by* SELECT, stored consecutively in the columns* of VL, in the same order as their* eigenvalues.* A complex eigenvector corresponding to a complex eigenvalue* is stored in two consecutive columns, the first holding the* real part, and the second the imaginary part.* If SIDE = 'R', VL is not referenced.** LDVL (input) INTEGER* The leading dimension of the array VL. LDVL >= max(1,N) if* SIDE = 'L' or 'B'; LDVL >= 1 otherwise.** VR (input/output) DOUBLE PRECISION array, dimension (LDVR,MM)* On entry, if SIDE = 'R' or 'B' and HOWMNY = 'B', VR must* contain an N-by-N matrix Q (usually the orthogonal matrix Q* of Schur vectors returned by DHSEQR).* On exit, if SIDE = 'R' or 'B', VR contains:* if HOWMNY = 'A', the matrix X of right eigenvectors of T;* VR has the same quasi-upper triangular form* as T. If T(i,i) is a real eigenvalue, then* the i-th column VR(i) of VR is its* corresponding eigenvector. If T(i:i+1,i:i+1)* is a 2-by-2 block whose eigenvalues are* complex-conjugate eigenvalues of T, then* VR(i)+sqrt(-1)*VR(i+1) is the complex* eigenvector corresponding to the eigenvalue* with positive real part.* if HOWMNY = 'B', the matrix Q*X;* if HOWMNY = 'S', the right eigenvectors of T specified by* SELECT, stored consecutively in the columns* of VR, in the same order as their* eigenvalues.* A complex eigenvector corresponding to a complex eigenvalue* is stored in two consecutive columns, the first holding the* real part and the second the imaginary part.* If SIDE = 'L', VR is not referenced.** LDVR (input) INTEGER* The leading dimension of the array VR. LDVR >= max(1,N) if* SIDE = 'R' or 'B'; LDVR >= 1 otherwise.** MM (input) INTEGER* The number of columns in the arrays VL and/or VR. MM >= M.** M (output) INTEGER* The number of columns in the arrays VL and/or VR actually* used to store the eigenvectors.* If HOWMNY = 'A' or 'B', M is set to N.* Each selected real eigenvector occupies one column and each* selected complex eigenvector occupies two columns.** WORK (workspace) DOUBLE PRECISION array, dimension (3*N)** INFO (output) INTEGER* = 0: successful exit* < 0: if INFO = -i, the i-th argument had an illegal value** Further Details* ===============** The algorithm used in this program is basically backward (forward)* substitution, with scaling to make the the code robust against* possible overflow.** Each eigenvector is normalized so that the element of largest* magnitude has magnitude 1; here the magnitude of a complex number* (x,y) is taken to be |x| + |y|.** =====================================================================** .. Parameters ..DOUBLE PRECISION ZERO, ONEPARAMETER ( ZERO = 0.0D+0, ONE = 1.0D+0 )* ..* .. Local Scalars ..LOGICAL ALLV, BOTHV, LEFTV, OVER, PAIR, RIGHTV, SOMEVINTEGER I, IERR, II, IP, IS, J, J1, J2, JNXT, K, KI, N2DOUBLE PRECISION BETA, BIGNUM, EMAX, OVFL, REC, REMAX, SCALE,$ SMIN, SMLNUM, ULP, UNFL, VCRIT, VMAX, WI, WR,$ XNORM* ..* .. External Functions ..LOGICAL LSAMEINTEGER IDAMAXDOUBLE PRECISION DDOT, DLAMCHEXTERNAL LSAME, IDAMAX, DDOT, DLAMCH* ..* .. External Subroutines ..EXTERNAL DAXPY, DCOPY, DGEMV, DLALN2, DSCAL, XERBLA* ..* .. Intrinsic Functions ..INTRINSIC ABS, MAX, SQRT* ..* .. Local Arrays ..DOUBLE PRECISION X( 2, 2 )* ..* .. Executable Statements ..** Decode and test the input parameters*BOTHV = LSAME( SIDE, 'B' )RIGHTV = LSAME( SIDE, 'R' ) .OR. BOTHVLEFTV = LSAME( SIDE, 'L' ) .OR. BOTHV*ALLV = LSAME( HOWMNY, 'A' )OVER = LSAME( HOWMNY, 'B' )SOMEV = LSAME( HOWMNY, 'S' )*INFO = 0IF( .NOT.RIGHTV .AND. .NOT.LEFTV ) THENINFO = -1ELSE IF( .NOT.ALLV .AND. .NOT.OVER .AND. .NOT.SOMEV ) THENINFO = -2ELSE IF( N.LT.0 ) THENINFO = -4ELSE IF( LDT.LT.MAX( 1, N ) ) THENINFO = -6ELSE IF( LDVL.LT.1 .OR. ( LEFTV .AND. LDVL.LT.N ) ) THENINFO = -8ELSE IF( LDVR.LT.1 .OR. ( RIGHTV .AND. LDVR.LT.N ) ) THENINFO = -10ELSE** Set M to the number of columns required to store the selected* eigenvectors, standardize the array SELECT if necessary, and* test MM.*IF( SOMEV ) THENM = 0PAIR = .FALSE.DO 10 J = 1, NIF( PAIR ) THENPAIR = .FALSE.SELECT( J ) = .FALSE.ELSEIF( J.LT.N ) THENIF( T( J+1, J ).EQ.ZERO ) THENIF( SELECT( J ) )$ M = M + 1ELSEPAIR = .TRUE.IF( SELECT( J ) .OR. SELECT( J+1 ) ) THENSELECT( J ) = .TRUE.M = M + 2END IFEND IFELSEIF( SELECT( N ) )$ M = M + 1END IFEND IF10 CONTINUEELSEM = NEND IF*IF( MM.LT.M ) THENINFO = -11END IFEND IFIF( INFO.NE.0 ) THENCALL XERBLA( 'DTREVC', -INFO )RETURNEND IF** Quick return if possible.*IF( N.EQ.0 )$ RETURN** Set the constants to control overflow.*UNFL = DLAMCH( 'Safe minimum' )OVFL = ONE / UNFLCALL DLABAD( UNFL, OVFL )ULP = DLAMCH( 'Precision' )SMLNUM = UNFL*( N / ULP )BIGNUM = ( ONE-ULP ) / SMLNUM** Compute 1-norm of each column of strictly upper triangular* part of T to control overflow in triangular solver.*WORK( 1 ) = ZERODO 30 J = 2, NWORK( J ) = ZERODO 20 I = 1, J - 1WORK( J ) = WORK( J ) + ABS( T( I, J ) )20 CONTINUE30 CONTINUE** Index IP is used to specify the real or complex eigenvalue:* IP = 0, real eigenvalue,* 1, first of conjugate complex pair: (wr,wi)* -1, second of conjugate complex pair: (wr,wi)*N2 = 2*N*IF( RIGHTV ) THEN** Compute right eigenvectors.*IP = 0IS = MDO 140 KI = N, 1, -1*IF( IP.EQ.1 )$ GO TO 130IF( KI.EQ.1 )$ GO TO 40IF( T( KI, KI-1 ).EQ.ZERO )$ GO TO 40IP = -1*40 CONTINUEIF( SOMEV ) THENIF( IP.EQ.0 ) THENIF( .NOT.SELECT( KI ) )$ GO TO 130ELSEIF( .NOT.SELECT( KI-1 ) )$ GO TO 130END IFEND IF** Compute the KI-th eigenvalue (WR,WI).*WR = T( KI, KI )WI = ZEROIF( IP.NE.0 )$ WI = SQRT( ABS( T( KI, KI-1 ) ) )*$ SQRT( ABS( T( KI-1, KI ) ) )SMIN = MAX( ULP*( ABS( WR )+ABS( WI ) ), SMLNUM )*IF( IP.EQ.0 ) THEN** Real right eigenvector*WORK( KI+N ) = ONE** Form right-hand side*DO 50 K = 1, KI - 1WORK( K+N ) = -T( K, KI )50 CONTINUE** Solve the upper quasi-triangular system:* (T(1:KI-1,1:KI-1) - WR)*X = SCALE*WORK.*JNXT = KI - 1DO 60 J = KI - 1, 1, -1IF( J.GT.JNXT )$ GO TO 60J1 = JJ2 = JJNXT = J - 1IF( J.GT.1 ) THENIF( T( J, J-1 ).NE.ZERO ) THENJ1 = J - 1JNXT = J - 2END IFEND IF*IF( J1.EQ.J2 ) THEN** 1-by-1 diagonal block*CALL DLALN2( .FALSE., 1, 1, SMIN, ONE, T( J, J ),$ LDT, ONE, ONE, WORK( J+N ), N, WR,$ ZERO, X, 2, SCALE, XNORM, IERR )** Scale X(1,1) to avoid overflow when updating* the right-hand side.*IF( XNORM.GT.ONE ) THENIF( WORK( J ).GT.BIGNUM / XNORM ) THENX( 1, 1 ) = X( 1, 1 ) / XNORMSCALE = SCALE / XNORMEND IFEND IF** Scale if necessary*IF( SCALE.NE.ONE )$ CALL DSCAL( KI, SCALE, WORK( 1+N ), 1 )WORK( J+N ) = X( 1, 1 )** Update right-hand side*CALL DAXPY( J-1, -X( 1, 1 ), T( 1, J ), 1,$ WORK( 1+N ), 1 )*ELSE** 2-by-2 diagonal block*CALL DLALN2( .FALSE., 2, 1, SMIN, ONE,$ T( J-1, J-1 ), LDT, ONE, ONE,$ WORK( J-1+N ), N, WR, ZERO, X, 2,$ SCALE, XNORM, IERR )** Scale X(1,1) and X(2,1) to avoid overflow when* updating the right-hand side.*IF( XNORM.GT.ONE ) THENBETA = MAX( WORK( J-1 ), WORK( J ) )IF( BETA.GT.BIGNUM / XNORM ) THENX( 1, 1 ) = X( 1, 1 ) / XNORMX( 2, 1 ) = X( 2, 1 ) / XNORMSCALE = SCALE / XNORMEND IFEND IF** Scale if necessary*IF( SCALE.NE.ONE )$ CALL DSCAL( KI, SCALE, WORK( 1+N ), 1 )WORK( J-1+N ) = X( 1, 1 )WORK( J+N ) = X( 2, 1 )** Update right-hand side*CALL DAXPY( J-2, -X( 1, 1 ), T( 1, J-1 ), 1,$ WORK( 1+N ), 1 )CALL DAXPY( J-2, -X( 2, 1 ), T( 1, J ), 1,$ WORK( 1+N ), 1 )END IF60 CONTINUE** Copy the vector x or Q*x to VR and normalize.*IF( .NOT.OVER ) THENCALL DCOPY( KI, WORK( 1+N ), 1, VR( 1, IS ), 1 )*II = IDAMAX( KI, VR( 1, IS ), 1 )REMAX = ONE / ABS( VR( II, IS ) )CALL DSCAL( KI, REMAX, VR( 1, IS ), 1 )*DO 70 K = KI + 1, NVR( K, IS ) = ZERO70 CONTINUEELSEIF( KI.GT.1 )$ CALL DGEMV( 'N', N, KI-1, ONE, VR, LDVR,$ WORK( 1+N ), 1, WORK( KI+N ),$ VR( 1, KI ), 1 )*II = IDAMAX( N, VR( 1, KI ), 1 )REMAX = ONE / ABS( VR( II, KI ) )CALL DSCAL( N, REMAX, VR( 1, KI ), 1 )END IF*ELSE** Complex right eigenvector.** Initial solve* [ (T(KI-1,KI-1) T(KI-1,KI) ) - (WR + I* WI)]*X = 0.* [ (T(KI,KI-1) T(KI,KI) ) ]*IF( ABS( T( KI-1, KI ) ).GE.ABS( T( KI, KI-1 ) ) ) THENWORK( KI-1+N ) = ONEWORK( KI+N2 ) = WI / T( KI-1, KI )ELSEWORK( KI-1+N ) = -WI / T( KI, KI-1 )WORK( KI+N2 ) = ONEEND IFWORK( KI+N ) = ZEROWORK( KI-1+N2 ) = ZERO** Form right-hand side*DO 80 K = 1, KI - 2WORK( K+N ) = -WORK( KI-1+N )*T( K, KI-1 )WORK( K+N2 ) = -WORK( KI+N2 )*T( K, KI )80 CONTINUE** Solve upper quasi-triangular system:* (T(1:KI-2,1:KI-2) - (WR+i*WI))*X = SCALE*(WORK+i*WORK2)*JNXT = KI - 2DO 90 J = KI - 2, 1, -1IF( J.GT.JNXT )$ GO TO 90J1 = JJ2 = JJNXT = J - 1IF( J.GT.1 ) THENIF( T( J, J-1 ).NE.ZERO ) THENJ1 = J - 1JNXT = J - 2END IFEND IF*IF( J1.EQ.J2 ) THEN** 1-by-1 diagonal block*CALL DLALN2( .FALSE., 1, 2, SMIN, ONE, T( J, J ),$ LDT, ONE, ONE, WORK( J+N ), N, WR, WI,$ X, 2, SCALE, XNORM, IERR )** Scale X(1,1) and X(1,2) to avoid overflow when* updating the right-hand side.*IF( XNORM.GT.ONE ) THENIF( WORK( J ).GT.BIGNUM / XNORM ) THENX( 1, 1 ) = X( 1, 1 ) / XNORMX( 1, 2 ) = X( 1, 2 ) / XNORMSCALE = SCALE / XNORMEND IFEND IF** Scale if necessary*IF( SCALE.NE.ONE ) THENCALL DSCAL( KI, SCALE, WORK( 1+N ), 1 )CALL DSCAL( KI, SCALE, WORK( 1+N2 ), 1 )END IFWORK( J+N ) = X( 1, 1 )WORK( J+N2 ) = X( 1, 2 )** Update the right-hand side*CALL DAXPY( J-1, -X( 1, 1 ), T( 1, J ), 1,$ WORK( 1+N ), 1 )CALL DAXPY( J-1, -X( 1, 2 ), T( 1, J ), 1,$ WORK( 1+N2 ), 1 )*ELSE** 2-by-2 diagonal block*CALL DLALN2( .FALSE., 2, 2, SMIN, ONE,$ T( J-1, J-1 ), LDT, ONE, ONE,$ WORK( J-1+N ), N, WR, WI, X, 2, SCALE,$ XNORM, IERR )** Scale X to avoid overflow when updating* the right-hand side.*IF( XNORM.GT.ONE ) THENBETA = MAX( WORK( J-1 ), WORK( J ) )IF( BETA.GT.BIGNUM / XNORM ) THENREC = ONE / XNORMX( 1, 1 ) = X( 1, 1 )*RECX( 1, 2 ) = X( 1, 2 )*RECX( 2, 1 ) = X( 2, 1 )*RECX( 2, 2 ) = X( 2, 2 )*RECSCALE = SCALE*RECEND IFEND IF** Scale if necessary*IF( SCALE.NE.ONE ) THENCALL DSCAL( KI, SCALE, WORK( 1+N ), 1 )CALL DSCAL( KI, SCALE, WORK( 1+N2 ), 1 )END IFWORK( J-1+N ) = X( 1, 1 )WORK( J+N ) = X( 2, 1 )WORK( J-1+N2 ) = X( 1, 2 )WORK( J+N2 ) = X( 2, 2 )** Update the right-hand side*CALL DAXPY( J-2, -X( 1, 1 ), T( 1, J-1 ), 1,$ WORK( 1+N ), 1 )CALL DAXPY( J-2, -X( 2, 1 ), T( 1, J ), 1,$ WORK( 1+N ), 1 )CALL DAXPY( J-2, -X( 1, 2 ), T( 1, J-1 ), 1,$ WORK( 1+N2 ), 1 )CALL DAXPY( J-2, -X( 2, 2 ), T( 1, J ), 1,$ WORK( 1+N2 ), 1 )END IF90 CONTINUE** Copy the vector x or Q*x to VR and normalize.*IF( .NOT.OVER ) THENCALL DCOPY( KI, WORK( 1+N ), 1, VR( 1, IS-1 ), 1 )CALL DCOPY( KI, WORK( 1+N2 ), 1, VR( 1, IS ), 1 )*EMAX = ZERODO 100 K = 1, KIEMAX = MAX( EMAX, ABS( VR( K, IS-1 ) )+$ ABS( VR( K, IS ) ) )100 CONTINUE*REMAX = ONE / EMAXCALL DSCAL( KI, REMAX, VR( 1, IS-1 ), 1 )CALL DSCAL( KI, REMAX, VR( 1, IS ), 1 )*DO 110 K = KI + 1, NVR( K, IS-1 ) = ZEROVR( K, IS ) = ZERO110 CONTINUE*ELSE*IF( KI.GT.2 ) THENCALL DGEMV( 'N', N, KI-2, ONE, VR, LDVR,$ WORK( 1+N ), 1, WORK( KI-1+N ),$ VR( 1, KI-1 ), 1 )CALL DGEMV( 'N', N, KI-2, ONE, VR, LDVR,$ WORK( 1+N2 ), 1, WORK( KI+N2 ),$ VR( 1, KI ), 1 )ELSECALL DSCAL( N, WORK( KI-1+N ), VR( 1, KI-1 ), 1 )CALL DSCAL( N, WORK( KI+N2 ), VR( 1, KI ), 1 )END IF*EMAX = ZERODO 120 K = 1, NEMAX = MAX( EMAX, ABS( VR( K, KI-1 ) )+$ ABS( VR( K, KI ) ) )120 CONTINUEREMAX = ONE / EMAXCALL DSCAL( N, REMAX, VR( 1, KI-1 ), 1 )CALL DSCAL( N, REMAX, VR( 1, KI ), 1 )END IFEND IF*IS = IS - 1IF( IP.NE.0 )$ IS = IS - 1130 CONTINUEIF( IP.EQ.1 )$ IP = 0IF( IP.EQ.-1 )$ IP = 1140 CONTINUEEND IF*IF( LEFTV ) THEN** Compute left eigenvectors.*IP = 0IS = 1DO 260 KI = 1, N*IF( IP.EQ.-1 )$ GO TO 250IF( KI.EQ.N )$ GO TO 150IF( T( KI+1, KI ).EQ.ZERO )$ GO TO 150IP = 1*150 CONTINUEIF( SOMEV ) THENIF( .NOT.SELECT( KI ) )$ GO TO 250END IF** Compute the KI-th eigenvalue (WR,WI).*WR = T( KI, KI )WI = ZEROIF( IP.NE.0 )$ WI = SQRT( ABS( T( KI, KI+1 ) ) )*$ SQRT( ABS( T( KI+1, KI ) ) )SMIN = MAX( ULP*( ABS( WR )+ABS( WI ) ), SMLNUM )*IF( IP.EQ.0 ) THEN** Real left eigenvector.*WORK( KI+N ) = ONE** Form right-hand side*DO 160 K = KI + 1, NWORK( K+N ) = -T( KI, K )160 CONTINUE** Solve the quasi-triangular system:* (T(KI+1:N,KI+1:N) - WR)'*X = SCALE*WORK*VMAX = ONEVCRIT = BIGNUM*JNXT = KI + 1DO 170 J = KI + 1, NIF( J.LT.JNXT )$ GO TO 170J1 = JJ2 = JJNXT = J + 1IF( J.LT.N ) THENIF( T( J+1, J ).NE.ZERO ) THENJ2 = J + 1JNXT = J + 2END IFEND IF*IF( J1.EQ.J2 ) THEN** 1-by-1 diagonal block** Scale if necessary to avoid overflow when forming* the right-hand side.*IF( WORK( J ).GT.VCRIT ) THENREC = ONE / VMAXCALL DSCAL( N-KI+1, REC, WORK( KI+N ), 1 )VMAX = ONEVCRIT = BIGNUMEND IF*WORK( J+N ) = WORK( J+N ) -$ DDOT( J-KI-1, T( KI+1, J ), 1,$ WORK( KI+1+N ), 1 )** Solve (T(J,J)-WR)'*X = WORK*CALL DLALN2( .FALSE., 1, 1, SMIN, ONE, T( J, J ),$ LDT, ONE, ONE, WORK( J+N ), N, WR,$ ZERO, X, 2, SCALE, XNORM, IERR )** Scale if necessary*IF( SCALE.NE.ONE )$ CALL DSCAL( N-KI+1, SCALE, WORK( KI+N ), 1 )WORK( J+N ) = X( 1, 1 )VMAX = MAX( ABS( WORK( J+N ) ), VMAX )VCRIT = BIGNUM / VMAX*ELSE** 2-by-2 diagonal block** Scale if necessary to avoid overflow when forming* the right-hand side.*BETA = MAX( WORK( J ), WORK( J+1 ) )IF( BETA.GT.VCRIT ) THENREC = ONE / VMAXCALL DSCAL( N-KI+1, REC, WORK( KI+N ), 1 )VMAX = ONEVCRIT = BIGNUMEND IF*WORK( J+N ) = WORK( J+N ) -$ DDOT( J-KI-1, T( KI+1, J ), 1,$ WORK( KI+1+N ), 1 )*WORK( J+1+N ) = WORK( J+1+N ) -$ DDOT( J-KI-1, T( KI+1, J+1 ), 1,$ WORK( KI+1+N ), 1 )** Solve* [T(J,J)-WR T(J,J+1) ]'* X = SCALE*( WORK1 )* [T(J+1,J) T(J+1,J+1)-WR] ( WORK2 )*CALL DLALN2( .TRUE., 2, 1, SMIN, ONE, T( J, J ),$ LDT, ONE, ONE, WORK( J+N ), N, WR,$ ZERO, X, 2, SCALE, XNORM, IERR )** Scale if necessary*IF( SCALE.NE.ONE )$ CALL DSCAL( N-KI+1, SCALE, WORK( KI+N ), 1 )WORK( J+N ) = X( 1, 1 )WORK( J+1+N ) = X( 2, 1 )*VMAX = MAX( ABS( WORK( J+N ) ),$ ABS( WORK( J+1+N ) ), VMAX )VCRIT = BIGNUM / VMAX*END IF170 CONTINUE** Copy the vector x or Q*x to VL and normalize.*IF( .NOT.OVER ) THENCALL DCOPY( N-KI+1, WORK( KI+N ), 1, VL( KI, IS ), 1 )*II = IDAMAX( N-KI+1, VL( KI, IS ), 1 ) + KI - 1REMAX = ONE / ABS( VL( II, IS ) )CALL DSCAL( N-KI+1, REMAX, VL( KI, IS ), 1 )*DO 180 K = 1, KI - 1VL( K, IS ) = ZERO180 CONTINUE*ELSE*IF( KI.LT.N )$ CALL DGEMV( 'N', N, N-KI, ONE, VL( 1, KI+1 ), LDVL,$ WORK( KI+1+N ), 1, WORK( KI+N ),$ VL( 1, KI ), 1 )*II = IDAMAX( N, VL( 1, KI ), 1 )REMAX = ONE / ABS( VL( II, KI ) )CALL DSCAL( N, REMAX, VL( 1, KI ), 1 )*END IF*ELSE** Complex left eigenvector.** Initial solve:* ((T(KI,KI) T(KI,KI+1) )' - (WR - I* WI))*X = 0.* ((T(KI+1,KI) T(KI+1,KI+1)) )*IF( ABS( T( KI, KI+1 ) ).GE.ABS( T( KI+1, KI ) ) ) THENWORK( KI+N ) = WI / T( KI, KI+1 )WORK( KI+1+N2 ) = ONEELSEWORK( KI+N ) = ONEWORK( KI+1+N2 ) = -WI / T( KI+1, KI )END IFWORK( KI+1+N ) = ZEROWORK( KI+N2 ) = ZERO** Form right-hand side*DO 190 K = KI + 2, NWORK( K+N ) = -WORK( KI+N )*T( KI, K )WORK( K+N2 ) = -WORK( KI+1+N2 )*T( KI+1, K )190 CONTINUE** Solve complex quasi-triangular system:* ( T(KI+2,N:KI+2,N) - (WR-i*WI) )*X = WORK1+i*WORK2*VMAX = ONEVCRIT = BIGNUM*JNXT = KI + 2DO 200 J = KI + 2, NIF( J.LT.JNXT )$ GO TO 200J1 = JJ2 = JJNXT = J + 1IF( J.LT.N ) THENIF( T( J+1, J ).NE.ZERO ) THENJ2 = J + 1JNXT = J + 2END IFEND IF*IF( J1.EQ.J2 ) THEN** 1-by-1 diagonal block** Scale if necessary to avoid overflow when* forming the right-hand side elements.*IF( WORK( J ).GT.VCRIT ) THENREC = ONE / VMAXCALL DSCAL( N-KI+1, REC, WORK( KI+N ), 1 )CALL DSCAL( N-KI+1, REC, WORK( KI+N2 ), 1 )VMAX = ONEVCRIT = BIGNUMEND IF*WORK( J+N ) = WORK( J+N ) -$ DDOT( J-KI-2, T( KI+2, J ), 1,$ WORK( KI+2+N ), 1 )WORK( J+N2 ) = WORK( J+N2 ) -$ DDOT( J-KI-2, T( KI+2, J ), 1,$ WORK( KI+2+N2 ), 1 )** Solve (T(J,J)-(WR-i*WI))*(X11+i*X12)= WK+I*WK2*CALL DLALN2( .FALSE., 1, 2, SMIN, ONE, T( J, J ),$ LDT, ONE, ONE, WORK( J+N ), N, WR,$ -WI, X, 2, SCALE, XNORM, IERR )** Scale if necessary*IF( SCALE.NE.ONE ) THENCALL DSCAL( N-KI+1, SCALE, WORK( KI+N ), 1 )CALL DSCAL( N-KI+1, SCALE, WORK( KI+N2 ), 1 )END IFWORK( J+N ) = X( 1, 1 )WORK( J+N2 ) = X( 1, 2 )VMAX = MAX( ABS( WORK( J+N ) ),$ ABS( WORK( J+N2 ) ), VMAX )VCRIT = BIGNUM / VMAX*ELSE** 2-by-2 diagonal block** Scale if necessary to avoid overflow when forming* the right-hand side elements.*BETA = MAX( WORK( J ), WORK( J+1 ) )IF( BETA.GT.VCRIT ) THENREC = ONE / VMAXCALL DSCAL( N-KI+1, REC, WORK( KI+N ), 1 )CALL DSCAL( N-KI+1, REC, WORK( KI+N2 ), 1 )VMAX = ONEVCRIT = BIGNUMEND IF*WORK( J+N ) = WORK( J+N ) -$ DDOT( J-KI-2, T( KI+2, J ), 1,$ WORK( KI+2+N ), 1 )*WORK( J+N2 ) = WORK( J+N2 ) -$ DDOT( J-KI-2, T( KI+2, J ), 1,$ WORK( KI+2+N2 ), 1 )*WORK( J+1+N ) = WORK( J+1+N ) -$ DDOT( J-KI-2, T( KI+2, J+1 ), 1,$ WORK( KI+2+N ), 1 )*WORK( J+1+N2 ) = WORK( J+1+N2 ) -$ DDOT( J-KI-2, T( KI+2, J+1 ), 1,$ WORK( KI+2+N2 ), 1 )** Solve 2-by-2 complex linear equation* ([T(j,j) T(j,j+1) ]'-(wr-i*wi)*I)*X = SCALE*B* ([T(j+1,j) T(j+1,j+1)] )*CALL DLALN2( .TRUE., 2, 2, SMIN, ONE, T( J, J ),$ LDT, ONE, ONE, WORK( J+N ), N, WR,$ -WI, X, 2, SCALE, XNORM, IERR )** Scale if necessary*IF( SCALE.NE.ONE ) THENCALL DSCAL( N-KI+1, SCALE, WORK( KI+N ), 1 )CALL DSCAL( N-KI+1, SCALE, WORK( KI+N2 ), 1 )END IFWORK( J+N ) = X( 1, 1 )WORK( J+N2 ) = X( 1, 2 )WORK( J+1+N ) = X( 2, 1 )WORK( J+1+N2 ) = X( 2, 2 )VMAX = MAX( ABS( X( 1, 1 ) ), ABS( X( 1, 2 ) ),$ ABS( X( 2, 1 ) ), ABS( X( 2, 2 ) ), VMAX )VCRIT = BIGNUM / VMAX*END IF200 CONTINUE** Copy the vector x or Q*x to VL and normalize.*210 CONTINUEIF( .NOT.OVER ) THENCALL DCOPY( N-KI+1, WORK( KI+N ), 1, VL( KI, IS ), 1 )CALL DCOPY( N-KI+1, WORK( KI+N2 ), 1, VL( KI, IS+1 ),$ 1 )*EMAX = ZERODO 220 K = KI, NEMAX = MAX( EMAX, ABS( VL( K, IS ) )+$ ABS( VL( K, IS+1 ) ) )220 CONTINUEREMAX = ONE / EMAXCALL DSCAL( N-KI+1, REMAX, VL( KI, IS ), 1 )CALL DSCAL( N-KI+1, REMAX, VL( KI, IS+1 ), 1 )*DO 230 K = 1, KI - 1VL( K, IS ) = ZEROVL( K, IS+1 ) = ZERO230 CONTINUEELSEIF( KI.LT.N-1 ) THENCALL DGEMV( 'N', N, N-KI-1, ONE, VL( 1, KI+2 ),$ LDVL, WORK( KI+2+N ), 1, WORK( KI+N ),$ VL( 1, KI ), 1 )CALL DGEMV( 'N', N, N-KI-1, ONE, VL( 1, KI+2 ),$ LDVL, WORK( KI+2+N2 ), 1,$ WORK( KI+1+N2 ), VL( 1, KI+1 ), 1 )ELSECALL DSCAL( N, WORK( KI+N ), VL( 1, KI ), 1 )CALL DSCAL( N, WORK( KI+1+N2 ), VL( 1, KI+1 ), 1 )END IF*EMAX = ZERODO 240 K = 1, NEMAX = MAX( EMAX, ABS( VL( K, KI ) )+$ ABS( VL( K, KI+1 ) ) )240 CONTINUEREMAX = ONE / EMAXCALL DSCAL( N, REMAX, VL( 1, KI ), 1 )CALL DSCAL( N, REMAX, VL( 1, KI+1 ), 1 )*END IF*END IF*IS = IS + 1IF( IP.NE.0 )$ IS = IS + 1250 CONTINUEIF( IP.EQ.-1 )$ IP = 0IF( IP.EQ.1 )$ IP = -1*260 CONTINUE*END IF*RETURN** End of DTREVC*ENDSUBROUTINE DTREXC( COMPQ, N, T, LDT, Q, LDQ, IFST, ILST, WORK,$ INFO )** -- LAPACK routine (version 3.0) --* Univ. of Tennessee, Univ. of California Berkeley, NAG Ltd.,* Courant Institute, Argonne National Lab, and Rice University* March 31, 1993** .. Scalar Arguments ..CHARACTER COMPQINTEGER IFST, ILST, INFO, LDQ, LDT, N* ..* .. Array Arguments ..DOUBLE PRECISION Q( LDQ, * ), T( LDT, * ), WORK( * )* ..** Purpose* =======** DTREXC reorders the real Schur factorization of a real matrix* A = Q*T*Q**T, so that the diagonal block of T with row index IFST is* moved to row ILST.** The real Schur form T is reordered by an orthogonal similarity* transformation Z**T*T*Z, and optionally the matrix Q of Schur vectors* is updated by postmultiplying it with Z.** T must be in Schur canonical form (as returned by DHSEQR), that is,* block upper triangular with 1-by-1 and 2-by-2 diagonal blocks; each* 2-by-2 diagonal block has its diagonal elements equal and its* off-diagonal elements of opposite sign.** Arguments* =========** COMPQ (input) CHARACTER*1* = 'V': update the matrix Q of Schur vectors;* = 'N': do not update Q.** N (input) INTEGER* The order of the matrix T. N >= 0.** T (input/output) DOUBLE PRECISION array, dimension (LDT,N)* On entry, the upper quasi-triangular matrix T, in Schur* Schur canonical form.* On exit, the reordered upper quasi-triangular matrix, again* in Schur canonical form.** LDT (input) INTEGER* The leading dimension of the array T. LDT >= max(1,N).** Q (input/output) DOUBLE PRECISION array, dimension (LDQ,N)* On entry, if COMPQ = 'V', the matrix Q of Schur vectors.* On exit, if COMPQ = 'V', Q has been postmultiplied by the* orthogonal transformation matrix Z which reorders T.* If COMPQ = 'N', Q is not referenced.** LDQ (input) INTEGER* The leading dimension of the array Q. LDQ >= max(1,N).** IFST (input/output) INTEGER* ILST (input/output) INTEGER* Specify the reordering of the diagonal blocks of T.* The block with row index IFST is moved to row ILST, by a* sequence of transpositions between adjacent blocks.* On exit, if IFST pointed on entry to the second row of a* 2-by-2 block, it is changed to point to the first row; ILST* always points to the first row of the block in its final* position (which may differ from its input value by +1 or -1).* 1 <= IFST <= N; 1 <= ILST <= N.** WORK (workspace) DOUBLE PRECISION array, dimension (N)** INFO (output) INTEGER* = 0: successful exit* < 0: if INFO = -i, the i-th argument had an illegal value* = 1: two adjacent blocks were too close to swap (the problem* is very ill-conditioned); T may have been partially* reordered, and ILST points to the first row of the* current position of the block being moved.** =====================================================================** .. Parameters ..DOUBLE PRECISION ZEROPARAMETER ( ZERO = 0.0D+0 )* ..* .. Local Scalars ..LOGICAL WANTQINTEGER HERE, NBF, NBL, NBNEXT* ..* .. External Functions ..LOGICAL LSAMEEXTERNAL LSAME* ..* .. External Subroutines ..EXTERNAL DLAEXC, XERBLA* ..* .. Intrinsic Functions ..INTRINSIC MAX* ..* .. Executable Statements ..** Decode and test the input arguments.*INFO = 0WANTQ = LSAME( COMPQ, 'V' )IF( .NOT.WANTQ .AND. .NOT.LSAME( COMPQ, 'N' ) ) THENINFO = -1ELSE IF( N.LT.0 ) THENINFO = -2ELSE IF( LDT.LT.MAX( 1, N ) ) THENINFO = -4ELSE IF( LDQ.LT.1 .OR. ( WANTQ .AND. LDQ.LT.MAX( 1, N ) ) ) THENINFO = -6ELSE IF( IFST.LT.1 .OR. IFST.GT.N ) THENINFO = -7ELSE IF( ILST.LT.1 .OR. ILST.GT.N ) THENINFO = -8END IFIF( INFO.NE.0 ) THENCALL XERBLA( 'DTREXC', -INFO )RETURNEND IF** Quick return if possible*IF( N.LE.1 )$ RETURN** Determine the first row of specified block* and find out it is 1 by 1 or 2 by 2.*IF( IFST.GT.1 ) THENIF( T( IFST, IFST-1 ).NE.ZERO )$ IFST = IFST - 1END IFNBF = 1IF( IFST.LT.N ) THENIF( T( IFST+1, IFST ).NE.ZERO )$ NBF = 2END IF** Determine the first row of the final block* and find out it is 1 by 1 or 2 by 2.*IF( ILST.GT.1 ) THENIF( T( ILST, ILST-1 ).NE.ZERO )$ ILST = ILST - 1END IFNBL = 1IF( ILST.LT.N ) THENIF( T( ILST+1, ILST ).NE.ZERO )$ NBL = 2END IF*IF( IFST.EQ.ILST )$ RETURN*IF( IFST.LT.ILST ) THEN** Update ILST*IF( NBF.EQ.2 .AND. NBL.EQ.1 )$ ILST = ILST - 1IF( NBF.EQ.1 .AND. NBL.EQ.2 )$ ILST = ILST + 1*HERE = IFST*10 CONTINUE** Swap block with next one below*IF( NBF.EQ.1 .OR. NBF.EQ.2 ) THEN** Current block either 1 by 1 or 2 by 2*NBNEXT = 1IF( HERE+NBF+1.LE.N ) THENIF( T( HERE+NBF+1, HERE+NBF ).NE.ZERO )$ NBNEXT = 2END IFCALL DLAEXC( WANTQ, N, T, LDT, Q, LDQ, HERE, NBF, NBNEXT,$ WORK, INFO )IF( INFO.NE.0 ) THENILST = HERERETURNEND IFHERE = HERE + NBNEXT** Test if 2 by 2 block breaks into two 1 by 1 blocks*IF( NBF.EQ.2 ) THENIF( T( HERE+1, HERE ).EQ.ZERO )$ NBF = 3END IF*ELSE** Current block consists of two 1 by 1 blocks each of which* must be swapped individually*NBNEXT = 1IF( HERE+3.LE.N ) THENIF( T( HERE+3, HERE+2 ).NE.ZERO )$ NBNEXT = 2END IFCALL DLAEXC( WANTQ, N, T, LDT, Q, LDQ, HERE+1, 1, NBNEXT,$ WORK, INFO )IF( INFO.NE.0 ) THENILST = HERERETURNEND IFIF( NBNEXT.EQ.1 ) THEN** Swap two 1 by 1 blocks, no problems possible*CALL DLAEXC( WANTQ, N, T, LDT, Q, LDQ, HERE, 1, NBNEXT,$ WORK, INFO )HERE = HERE + 1ELSE** Recompute NBNEXT in case 2 by 2 split*IF( T( HERE+2, HERE+1 ).EQ.ZERO )$ NBNEXT = 1IF( NBNEXT.EQ.2 ) THEN** 2 by 2 Block did not split*CALL DLAEXC( WANTQ, N, T, LDT, Q, LDQ, HERE, 1,$ NBNEXT, WORK, INFO )IF( INFO.NE.0 ) THENILST = HERERETURNEND IFHERE = HERE + 2ELSE** 2 by 2 Block did split*CALL DLAEXC( WANTQ, N, T, LDT, Q, LDQ, HERE, 1, 1,$ WORK, INFO )CALL DLAEXC( WANTQ, N, T, LDT, Q, LDQ, HERE+1, 1, 1,$ WORK, INFO )HERE = HERE + 2END IFEND IFEND IFIF( HERE.LT.ILST )$ GO TO 10*ELSE*HERE = IFST20 CONTINUE** Swap block with next one above*IF( NBF.EQ.1 .OR. NBF.EQ.2 ) THEN** Current block either 1 by 1 or 2 by 2*NBNEXT = 1IF( HERE.GE.3 ) THENIF( T( HERE-1, HERE-2 ).NE.ZERO )$ NBNEXT = 2END IFCALL DLAEXC( WANTQ, N, T, LDT, Q, LDQ, HERE-NBNEXT, NBNEXT,$ NBF, WORK, INFO )IF( INFO.NE.0 ) THENILST = HERERETURNEND IFHERE = HERE - NBNEXT** Test if 2 by 2 block breaks into two 1 by 1 blocks*IF( NBF.EQ.2 ) THENIF( T( HERE+1, HERE ).EQ.ZERO )$ NBF = 3END IF*ELSE** Current block consists of two 1 by 1 blocks each of which* must be swapped individually*NBNEXT = 1IF( HERE.GE.3 ) THENIF( T( HERE-1, HERE-2 ).NE.ZERO )$ NBNEXT = 2END IFCALL DLAEXC( WANTQ, N, T, LDT, Q, LDQ, HERE-NBNEXT, NBNEXT,$ 1, WORK, INFO )IF( INFO.NE.0 ) THENILST = HERERETURNEND IFIF( NBNEXT.EQ.1 ) THEN** Swap two 1 by 1 blocks, no problems possible*CALL DLAEXC( WANTQ, N, T, LDT, Q, LDQ, HERE, NBNEXT, 1,$ WORK, INFO )HERE = HERE - 1ELSE** Recompute NBNEXT in case 2 by 2 split*IF( T( HERE, HERE-1 ).EQ.ZERO )$ NBNEXT = 1IF( NBNEXT.EQ.2 ) THEN** 2 by 2 Block did not split*CALL DLAEXC( WANTQ, N, T, LDT, Q, LDQ, HERE-1, 2, 1,$ WORK, INFO )IF( INFO.NE.0 ) THENILST = HERERETURNEND IFHERE = HERE - 2ELSE** 2 by 2 Block did split*CALL DLAEXC( WANTQ, N, T, LDT, Q, LDQ, HERE, 1, 1,$ WORK, INFO )CALL DLAEXC( WANTQ, N, T, LDT, Q, LDQ, HERE-1, 1, 1,$ WORK, INFO )HERE = HERE - 2END IFEND IFEND IFIF( HERE.GT.ILST )$ GO TO 20END IFILST = HERE*RETURN** End of DTREXC*ENDSUBROUTINE DTRSEN( JOB, COMPQ, SELECT, N, T, LDT, Q, LDQ, WR, WI,$ M, S, SEP, WORK, LWORK, IWORK, LIWORK, INFO )** -- LAPACK routine (version 3.0) --* Univ. of Tennessee, Univ. of California Berkeley, NAG Ltd.,* Courant Institute, Argonne National Lab, and Rice University* June 30, 1999** .. Scalar Arguments ..CHARACTER COMPQ, JOBINTEGER INFO, LDQ, LDT, LIWORK, LWORK, M, NDOUBLE PRECISION S, SEP* ..* .. Array Arguments ..LOGICAL SELECT( * )INTEGER IWORK( * )DOUBLE PRECISION Q( LDQ, * ), T( LDT, * ), WI( * ), WORK( * ),$ WR( * )* ..** Purpose* =======** DTRSEN reorders the real Schur factorization of a real matrix* A = Q*T*Q**T, so that a selected cluster of eigenvalues appears in* the leading diagonal blocks of the upper quasi-triangular matrix T,* and the leading columns of Q form an orthonormal basis of the* corresponding right invariant subspace.** Optionally the routine computes the reciprocal condition numbers of* the cluster of eigenvalues and/or the invariant subspace.** T must be in Schur canonical form (as returned by DHSEQR), that is,* block upper triangular with 1-by-1 and 2-by-2 diagonal blocks; each* 2-by-2 diagonal block has its diagonal elemnts equal and its* off-diagonal elements of opposite sign.** Arguments* =========** JOB (input) CHARACTER*1* Specifies whether condition numbers are required for the* cluster of eigenvalues (S) or the invariant subspace (SEP):* = 'N': none;* = 'E': for eigenvalues only (S);* = 'V': for invariant subspace only (SEP);* = 'B': for both eigenvalues and invariant subspace (S and* SEP).** COMPQ (input) CHARACTER*1* = 'V': update the matrix Q of Schur vectors;* = 'N': do not update Q.** SELECT (input) LOGICAL array, dimension (N)* SELECT specifies the eigenvalues in the selected cluster. To* select a real eigenvalue w(j), SELECT(j) must be set to* .TRUE.. To select a complex conjugate pair of eigenvalues* w(j) and w(j+1), corresponding to a 2-by-2 diagonal block,* either SELECT(j) or SELECT(j+1) or both must be set to* .TRUE.; a complex conjugate pair of eigenvalues must be* either both included in the cluster or both excluded.** N (input) INTEGER* The order of the matrix T. N >= 0.** T (input/output) DOUBLE PRECISION array, dimension (LDT,N)* On entry, the upper quasi-triangular matrix T, in Schur* canonical form.* On exit, T is overwritten by the reordered matrix T, again in* Schur canonical form, with the selected eigenvalues in the* leading diagonal blocks.** LDT (input) INTEGER* The leading dimension of the array T. LDT >= max(1,N).** Q (input/output) DOUBLE PRECISION array, dimension (LDQ,N)* On entry, if COMPQ = 'V', the matrix Q of Schur vectors.* On exit, if COMPQ = 'V', Q has been postmultiplied by the* orthogonal transformation matrix which reorders T; the* leading M columns of Q form an orthonormal basis for the* specified invariant subspace.* If COMPQ = 'N', Q is not referenced.** LDQ (input) INTEGER* The leading dimension of the array Q.* LDQ >= 1; and if COMPQ = 'V', LDQ >= N.** WR (output) DOUBLE PRECISION array, dimension (N)* WI (output) DOUBLE PRECISION array, dimension (N)* The real and imaginary parts, respectively, of the reordered* eigenvalues of T. The eigenvalues are stored in the same* order as on the diagonal of T, with WR(i) = T(i,i) and, if* T(i:i+1,i:i+1) is a 2-by-2 diagonal block, WI(i) > 0 and* WI(i+1) = -WI(i). Note that if a complex eigenvalue is* sufficiently ill-conditioned, then its value may differ* significantly from its value before reordering.** M (output) INTEGER* The dimension of the specified invariant subspace.* 0 < = M <= N.** S (output) DOUBLE PRECISION* If JOB = 'E' or 'B', S is a lower bound on the reciprocal* condition number for the selected cluster of eigenvalues.* S cannot underestimate the true reciprocal condition number* by more than a factor of sqrt(N). If M = 0 or N, S = 1.* If JOB = 'N' or 'V', S is not referenced.** SEP (output) DOUBLE PRECISION* If JOB = 'V' or 'B', SEP is the estimated reciprocal* condition number of the specified invariant subspace. If* M = 0 or N, SEP = norm(T).* If JOB = 'N' or 'E', SEP is not referenced.** WORK (workspace/output) DOUBLE PRECISION array, dimension (LWORK)* On exit, if INFO = 0, WORK(1) returns the optimal LWORK.** LWORK (input) INTEGER* The dimension of the array WORK.* If JOB = 'N', LWORK >= max(1,N);* if JOB = 'E', LWORK >= M*(N-M);* if JOB = 'V' or 'B', LWORK >= 2*M*(N-M).** If LWORK = -1, then a workspace query is assumed; the routine* only calculates the optimal size of the WORK array, returns* this value as the first entry of the WORK array, and no error* message related to LWORK is issued by XERBLA.** IWORK (workspace) INTEGER array, dimension (LIWORK)* IF JOB = 'N' or 'E', IWORK is not referenced.** LIWORK (input) INTEGER* The dimension of the array IWORK.* If JOB = 'N' or 'E', LIWORK >= 1;* if JOB = 'V' or 'B', LIWORK >= M*(N-M).** If LIWORK = -1, then a workspace query is assumed; the* routine only calculates the optimal size of the IWORK array,* returns this value as the first entry of the IWORK array, and* no error message related to LIWORK is issued by XERBLA.** INFO (output) INTEGER* = 0: successful exit* < 0: if INFO = -i, the i-th argument had an illegal value* = 1: reordering of T failed because some eigenvalues are too* close to separate (the problem is very ill-conditioned);* T may have been partially reordered, and WR and WI* contain the eigenvalues in the same order as in T; S and* SEP (if requested) are set to zero.** Further Details* ===============** DTRSEN first collects the selected eigenvalues by computing an* orthogonal transformation Z to move them to the top left corner of T.* In other words, the selected eigenvalues are the eigenvalues of T11* in:** Z'*T*Z = ( T11 T12 ) n1* ( 0 T22 ) n2* n1 n2** where N = n1+n2 and Z' means the transpose of Z. The first n1 columns* of Z span the specified invariant subspace of T.** If T has been obtained from the real Schur factorization of a matrix* A = Q*T*Q', then the reordered real Schur factorization of A is given* by A = (Q*Z)*(Z'*T*Z)*(Q*Z)', and the first n1 columns of Q*Z span* the corresponding invariant subspace of A.** The reciprocal condition number of the average of the eigenvalues of* T11 may be returned in S. S lies between 0 (very badly conditioned)* and 1 (very well conditioned). It is computed as follows. First we* compute R so that** P = ( I R ) n1* ( 0 0 ) n2* n1 n2** is the projector on the invariant subspace associated with T11.* R is the solution of the Sylvester equation:** T11*R - R*T22 = T12.** Let F-norm(M) denote the Frobenius-norm of M and 2-norm(M) denote* the two-norm of M. Then S is computed as the lower bound** (1 + F-norm(R)**2)**(-1/2)** on the reciprocal of 2-norm(P), the true reciprocal condition number.* S cannot underestimate 1 / 2-norm(P) by more than a factor of* sqrt(N).** An approximate error bound for the computed average of the* eigenvalues of T11 is** EPS * norm(T) / S** where EPS is the machine precision.** The reciprocal condition number of the right invariant subspace* spanned by the first n1 columns of Z (or of Q*Z) is returned in SEP.* SEP is defined as the separation of T11 and T22:** sep( T11, T22 ) = sigma-min( C )** where sigma-min(C) is the smallest singular value of the* n1*n2-by-n1*n2 matrix** C = kprod( I(n2), T11 ) - kprod( transpose(T22), I(n1) )** I(m) is an m by m identity matrix, and kprod denotes the Kronecker* product. We estimate sigma-min(C) by the reciprocal of an estimate of* the 1-norm of inverse(C). The true reciprocal 1-norm of inverse(C)* cannot differ from sigma-min(C) by more than a factor of sqrt(n1*n2).** When SEP is small, small changes in T can cause large changes in* the invariant subspace. An approximate bound on the maximum angular* error in the computed right invariant subspace is** EPS * norm(T) / SEP** =====================================================================** .. Parameters ..DOUBLE PRECISION ZERO, ONEPARAMETER ( ZERO = 0.0D+0, ONE = 1.0D+0 )* ..* .. Local Scalars ..LOGICAL LQUERY, PAIR, SWAP, WANTBH, WANTQ, WANTS,$ WANTSPINTEGER IERR, K, KASE, KK, KS, LIWMIN, LWMIN, N1, N2,$ NNDOUBLE PRECISION EST, RNORM, SCALE* ..* .. External Functions ..LOGICAL LSAMEDOUBLE PRECISION DLANGEEXTERNAL LSAME, DLANGE* ..* .. External Subroutines ..EXTERNAL DLACON, DLACPY, DTREXC, DTRSYL, XERBLA* ..* .. Intrinsic Functions ..INTRINSIC ABS, MAX, SQRT* ..* .. Executable Statements ..** Decode and test the input parameters*WANTBH = LSAME( JOB, 'B' )WANTS = LSAME( JOB, 'E' ) .OR. WANTBHWANTSP = LSAME( JOB, 'V' ) .OR. WANTBHWANTQ = LSAME( COMPQ, 'V' )*INFO = 0LQUERY = ( LWORK.EQ.-1 )IF( .NOT.LSAME( JOB, 'N' ) .AND. .NOT.WANTS .AND. .NOT.WANTSP )$ THENINFO = -1ELSE IF( .NOT.LSAME( COMPQ, 'N' ) .AND. .NOT.WANTQ ) THENINFO = -2ELSE IF( N.LT.0 ) THENINFO = -4ELSE IF( LDT.LT.MAX( 1, N ) ) THENINFO = -6ELSE IF( LDQ.LT.1 .OR. ( WANTQ .AND. LDQ.LT.N ) ) THENINFO = -8ELSE** Set M to the dimension of the specified invariant subspace,* and test LWORK and LIWORK.*M = 0PAIR = .FALSE.DO 10 K = 1, NIF( PAIR ) THENPAIR = .FALSE.ELSEIF( K.LT.N ) THENIF( T( K+1, K ).EQ.ZERO ) THENIF( SELECT( K ) )$ M = M + 1ELSEPAIR = .TRUE.IF( SELECT( K ) .OR. SELECT( K+1 ) )$ M = M + 2END IFELSEIF( SELECT( N ) )$ M = M + 1END IFEND IF10 CONTINUE*N1 = MN2 = N - MNN = N1*N2*IF( WANTSP ) THENLWMIN = MAX( 1, 2*NN )LIWMIN = MAX( 1, NN )ELSE IF( LSAME( JOB, 'N' ) ) THENLWMIN = MAX( 1, N )LIWMIN = 1ELSE IF( LSAME( JOB, 'E' ) ) THENLWMIN = MAX( 1, NN )LIWMIN = 1END IF*IF( LWORK.LT.LWMIN .AND. .NOT.LQUERY ) THENINFO = -15ELSE IF( LIWORK.LT.LIWMIN .AND. .NOT.LQUERY ) THENINFO = -17END IFEND IF*IF( INFO.EQ.0 ) THENWORK( 1 ) = LWMINIWORK( 1 ) = LIWMINEND IF*IF( INFO.NE.0 ) THENCALL XERBLA( 'DTRSEN', -INFO )RETURNELSE IF( LQUERY ) THENRETURNEND IF** Quick return if possible.*IF( M.EQ.N .OR. M.EQ.0 ) THENIF( WANTS )$ S = ONEIF( WANTSP )$ SEP = DLANGE( '1', N, N, T, LDT, WORK )GO TO 40END IF** Collect the selected blocks at the top-left corner of T.*KS = 0PAIR = .FALSE.DO 20 K = 1, NIF( PAIR ) THENPAIR = .FALSE.ELSESWAP = SELECT( K )IF( K.LT.N ) THENIF( T( K+1, K ).NE.ZERO ) THENPAIR = .TRUE.SWAP = SWAP .OR. SELECT( K+1 )END IFEND IFIF( SWAP ) THENKS = KS + 1** Swap the K-th block to position KS.*IERR = 0KK = KIF( K.NE.KS )$ CALL DTREXC( COMPQ, N, T, LDT, Q, LDQ, KK, KS, WORK,$ IERR )IF( IERR.EQ.1 .OR. IERR.EQ.2 ) THEN** Blocks too close to swap: exit.*INFO = 1IF( WANTS )$ S = ZEROIF( WANTSP )$ SEP = ZEROGO TO 40END IFIF( PAIR )$ KS = KS + 1END IFEND IF20 CONTINUE*IF( WANTS ) THEN** Solve Sylvester equation for R:** T11*R - R*T22 = scale*T12*CALL DLACPY( 'F', N1, N2, T( 1, N1+1 ), LDT, WORK, N1 )CALL DTRSYL( 'N', 'N', -1, N1, N2, T, LDT, T( N1+1, N1+1 ),$ LDT, WORK, N1, SCALE, IERR )** Estimate the reciprocal of the condition number of the cluster* of eigenvalues.*RNORM = DLANGE( 'F', N1, N2, WORK, N1, WORK )IF( RNORM.EQ.ZERO ) THENS = ONEELSES = SCALE / ( SQRT( SCALE*SCALE / RNORM+RNORM )*$ SQRT( RNORM ) )END IFEND IF*IF( WANTSP ) THEN** Estimate sep(T11,T22).*EST = ZEROKASE = 030 CONTINUECALL DLACON( NN, WORK( NN+1 ), WORK, IWORK, EST, KASE )IF( KASE.NE.0 ) THENIF( KASE.EQ.1 ) THEN** Solve T11*R - R*T22 = scale*X.*CALL DTRSYL( 'N', 'N', -1, N1, N2, T, LDT,$ T( N1+1, N1+1 ), LDT, WORK, N1, SCALE,$ IERR )ELSE** Solve T11'*R - R*T22' = scale*X.*CALL DTRSYL( 'T', 'T', -1, N1, N2, T, LDT,$ T( N1+1, N1+1 ), LDT, WORK, N1, SCALE,$ IERR )END IFGO TO 30END IF*SEP = SCALE / ESTEND IF*40 CONTINUE** Store the output eigenvalues in WR and WI.*DO 50 K = 1, NWR( K ) = T( K, K )WI( K ) = ZERO50 CONTINUEDO 60 K = 1, N - 1IF( T( K+1, K ).NE.ZERO ) THENWI( K ) = SQRT( ABS( T( K, K+1 ) ) )*$ SQRT( ABS( T( K+1, K ) ) )WI( K+1 ) = -WI( K )END IF60 CONTINUE*WORK( 1 ) = LWMINIWORK( 1 ) = LIWMIN*RETURN** End of DTRSEN*ENDSUBROUTINE DTRSNA( JOB, HOWMNY, SELECT, N, T, LDT, VL, LDVL, VR,$ LDVR, S, SEP, MM, M, WORK, LDWORK, IWORK,$ INFO )** -- LAPACK routine (version 3.0) --* Univ. of Tennessee, Univ. of California Berkeley, NAG Ltd.,* Courant Institute, Argonne National Lab, and Rice University* September 30, 1994** .. Scalar Arguments ..CHARACTER HOWMNY, JOBINTEGER INFO, LDT, LDVL, LDVR, LDWORK, M, MM, N* ..* .. Array Arguments ..LOGICAL SELECT( * )INTEGER IWORK( * )DOUBLE PRECISION S( * ), SEP( * ), T( LDT, * ), VL( LDVL, * ),$ VR( LDVR, * ), WORK( LDWORK, * )* ..** Purpose* =======** DTRSNA estimates reciprocal condition numbers for specified* eigenvalues and/or right eigenvectors of a real upper* quasi-triangular matrix T (or of any matrix Q*T*Q**T with Q* orthogonal).** T must be in Schur canonical form (as returned by DHSEQR), that is,* block upper triangular with 1-by-1 and 2-by-2 diagonal blocks; each* 2-by-2 diagonal block has its diagonal elements equal and its* off-diagonal elements of opposite sign.** Arguments* =========** JOB (input) CHARACTER*1* Specifies whether condition numbers are required for* eigenvalues (S) or eigenvectors (SEP):* = 'E': for eigenvalues only (S);* = 'V': for eigenvectors only (SEP);* = 'B': for both eigenvalues and eigenvectors (S and SEP).** HOWMNY (input) CHARACTER*1* = 'A': compute condition numbers for all eigenpairs;* = 'S': compute condition numbers for selected eigenpairs* specified by the array SELECT.** SELECT (input) LOGICAL array, dimension (N)* If HOWMNY = 'S', SELECT specifies the eigenpairs for which* condition numbers are required. To select condition numbers* for the eigenpair corresponding to a real eigenvalue w(j),* SELECT(j) must be set to .TRUE.. To select condition numbers* corresponding to a complex conjugate pair of eigenvalues w(j)* and w(j+1), either SELECT(j) or SELECT(j+1) or both, must be* set to .TRUE..* If HOWMNY = 'A', SELECT is not referenced.** N (input) INTEGER* The order of the matrix T. N >= 0.** T (input) DOUBLE PRECISION array, dimension (LDT,N)* The upper quasi-triangular matrix T, in Schur canonical form.** LDT (input) INTEGER* The leading dimension of the array T. LDT >= max(1,N).** VL (input) DOUBLE PRECISION array, dimension (LDVL,M)* If JOB = 'E' or 'B', VL must contain left eigenvectors of T* (or of any Q*T*Q**T with Q orthogonal), corresponding to the* eigenpairs specified by HOWMNY and SELECT. The eigenvectors* must be stored in consecutive columns of VL, as returned by* DHSEIN or DTREVC.* If JOB = 'V', VL is not referenced.** LDVL (input) INTEGER* The leading dimension of the array VL.* LDVL >= 1; and if JOB = 'E' or 'B', LDVL >= N.** VR (input) DOUBLE PRECISION array, dimension (LDVR,M)* If JOB = 'E' or 'B', VR must contain right eigenvectors of T* (or of any Q*T*Q**T with Q orthogonal), corresponding to the* eigenpairs specified by HOWMNY and SELECT. The eigenvectors* must be stored in consecutive columns of VR, as returned by* DHSEIN or DTREVC.* If JOB = 'V', VR is not referenced.** LDVR (input) INTEGER* The leading dimension of the array VR.* LDVR >= 1; and if JOB = 'E' or 'B', LDVR >= N.** S (output) DOUBLE PRECISION array, dimension (MM)* If JOB = 'E' or 'B', the reciprocal condition numbers of the* selected eigenvalues, stored in consecutive elements of the* array. For a complex conjugate pair of eigenvalues two* consecutive elements of S are set to the same value. Thus* S(j), SEP(j), and the j-th columns of VL and VR all* correspond to the same eigenpair (but not in general the* j-th eigenpair, unless all eigenpairs are selected).* If JOB = 'V', S is not referenced.** SEP (output) DOUBLE PRECISION array, dimension (MM)* If JOB = 'V' or 'B', the estimated reciprocal condition* numbers of the selected eigenvectors, stored in consecutive* elements of the array. For a complex eigenvector two* consecutive elements of SEP are set to the same value. If* the eigenvalues cannot be reordered to compute SEP(j), SEP(j)* is set to 0; this can only occur when the true value would be* very small anyway.* If JOB = 'E', SEP is not referenced.** MM (input) INTEGER* The number of elements in the arrays S (if JOB = 'E' or 'B')* and/or SEP (if JOB = 'V' or 'B'). MM >= M.** M (output) INTEGER* The number of elements of the arrays S and/or SEP actually* used to store the estimated condition numbers.* If HOWMNY = 'A', M is set to N.** WORK (workspace) DOUBLE PRECISION array, dimension (LDWORK,N+1)* If JOB = 'E', WORK is not referenced.** LDWORK (input) INTEGER* The leading dimension of the array WORK.* LDWORK >= 1; and if JOB = 'V' or 'B', LDWORK >= N.** IWORK (workspace) INTEGER array, dimension (N)* If JOB = 'E', IWORK is not referenced.** INFO (output) INTEGER* = 0: successful exit* < 0: if INFO = -i, the i-th argument had an illegal value** Further Details* ===============** The reciprocal of the condition number of an eigenvalue lambda is* defined as** S(lambda) = |v'*u| / (norm(u)*norm(v))** where u and v are the right and left eigenvectors of T corresponding* to lambda; v' denotes the conjugate-transpose of v, and norm(u)* denotes the Euclidean norm. These reciprocal condition numbers always* lie between zero (very badly conditioned) and one (very well* conditioned). If n = 1, S(lambda) is defined to be 1.** An approximate error bound for a computed eigenvalue W(i) is given by** EPS * norm(T) / S(i)** where EPS is the machine precision.** The reciprocal of the condition number of the right eigenvector u* corresponding to lambda is defined as follows. Suppose** T = ( lambda c )* ( 0 T22 )** Then the reciprocal condition number is** SEP( lambda, T22 ) = sigma-min( T22 - lambda*I )** where sigma-min denotes the smallest singular value. We approximate* the smallest singular value by the reciprocal of an estimate of the* one-norm of the inverse of T22 - lambda*I. If n = 1, SEP(1) is* defined to be abs(T(1,1)).** An approximate error bound for a computed right eigenvector VR(i)* is given by** EPS * norm(T) / SEP(i)** =====================================================================** .. Parameters ..DOUBLE PRECISION ZERO, ONE, TWOPARAMETER ( ZERO = 0.0D+0, ONE = 1.0D+0, TWO = 2.0D+0 )* ..* .. Local Scalars ..LOGICAL PAIR, SOMCON, WANTBH, WANTS, WANTSPINTEGER I, IERR, IFST, ILST, J, K, KASE, KS, N2, NNDOUBLE PRECISION BIGNUM, COND, CS, DELTA, DUMM, EPS, EST, LNRM,$ MU, PROD, PROD1, PROD2, RNRM, SCALE, SMLNUM, SN* ..* .. Local Arrays ..DOUBLE PRECISION DUMMY( 1 )* ..* .. External Functions ..LOGICAL LSAMEDOUBLE PRECISION DDOT, DLAMCH, DLAPY2, DNRM2EXTERNAL LSAME, DDOT, DLAMCH, DLAPY2, DNRM2* ..* .. External Subroutines ..EXTERNAL DLACON, DLACPY, DLAQTR, DTREXC, XERBLA* ..* .. Intrinsic Functions ..INTRINSIC ABS, MAX, SQRT* ..* .. Executable Statements ..** Decode and test the input parameters*WANTBH = LSAME( JOB, 'B' )WANTS = LSAME( JOB, 'E' ) .OR. WANTBHWANTSP = LSAME( JOB, 'V' ) .OR. WANTBH*SOMCON = LSAME( HOWMNY, 'S' )*INFO = 0IF( .NOT.WANTS .AND. .NOT.WANTSP ) THENINFO = -1ELSE IF( .NOT.LSAME( HOWMNY, 'A' ) .AND. .NOT.SOMCON ) THENINFO = -2ELSE IF( N.LT.0 ) THENINFO = -4ELSE IF( LDT.LT.MAX( 1, N ) ) THENINFO = -6ELSE IF( LDVL.LT.1 .OR. ( WANTS .AND. LDVL.LT.N ) ) THENINFO = -8ELSE IF( LDVR.LT.1 .OR. ( WANTS .AND. LDVR.LT.N ) ) THENINFO = -10ELSE** Set M to the number of eigenpairs for which condition numbers* are required, and test MM.*IF( SOMCON ) THENM = 0PAIR = .FALSE.DO 10 K = 1, NIF( PAIR ) THENPAIR = .FALSE.ELSEIF( K.LT.N ) THENIF( T( K+1, K ).EQ.ZERO ) THENIF( SELECT( K ) )$ M = M + 1ELSEPAIR = .TRUE.IF( SELECT( K ) .OR. SELECT( K+1 ) )$ M = M + 2END IFELSEIF( SELECT( N ) )$ M = M + 1END IFEND IF10 CONTINUEELSEM = NEND IF*IF( MM.LT.M ) THENINFO = -13ELSE IF( LDWORK.LT.1 .OR. ( WANTSP .AND. LDWORK.LT.N ) ) THENINFO = -16END IFEND IFIF( INFO.NE.0 ) THENCALL XERBLA( 'DTRSNA', -INFO )RETURNEND IF** Quick return if possible*IF( N.EQ.0 )$ RETURN*IF( N.EQ.1 ) THENIF( SOMCON ) THENIF( .NOT.SELECT( 1 ) )$ RETURNEND IFIF( WANTS )$ S( 1 ) = ONEIF( WANTSP )$ SEP( 1 ) = ABS( T( 1, 1 ) )RETURNEND IF** Get machine constants*EPS = DLAMCH( 'P' )SMLNUM = DLAMCH( 'S' ) / EPSBIGNUM = ONE / SMLNUMCALL DLABAD( SMLNUM, BIGNUM )*KS = 0PAIR = .FALSE.DO 60 K = 1, N** Determine whether T(k,k) begins a 1-by-1 or 2-by-2 block.*IF( PAIR ) THENPAIR = .FALSE.GO TO 60ELSEIF( K.LT.N )$ PAIR = T( K+1, K ).NE.ZEROEND IF** Determine whether condition numbers are required for the k-th* eigenpair.*IF( SOMCON ) THENIF( PAIR ) THENIF( .NOT.SELECT( K ) .AND. .NOT.SELECT( K+1 ) )$ GO TO 60ELSEIF( .NOT.SELECT( K ) )$ GO TO 60END IFEND IF*KS = KS + 1*IF( WANTS ) THEN** Compute the reciprocal condition number of the k-th* eigenvalue.*IF( .NOT.PAIR ) THEN** Real eigenvalue.*PROD = DDOT( N, VR( 1, KS ), 1, VL( 1, KS ), 1 )RNRM = DNRM2( N, VR( 1, KS ), 1 )LNRM = DNRM2( N, VL( 1, KS ), 1 )S( KS ) = ABS( PROD ) / ( RNRM*LNRM )ELSE** Complex eigenvalue.*PROD1 = DDOT( N, VR( 1, KS ), 1, VL( 1, KS ), 1 )PROD1 = PROD1 + DDOT( N, VR( 1, KS+1 ), 1, VL( 1, KS+1 ),$ 1 )PROD2 = DDOT( N, VL( 1, KS ), 1, VR( 1, KS+1 ), 1 )PROD2 = PROD2 - DDOT( N, VL( 1, KS+1 ), 1, VR( 1, KS ),$ 1 )RNRM = DLAPY2( DNRM2( N, VR( 1, KS ), 1 ),$ DNRM2( N, VR( 1, KS+1 ), 1 ) )LNRM = DLAPY2( DNRM2( N, VL( 1, KS ), 1 ),$ DNRM2( N, VL( 1, KS+1 ), 1 ) )COND = DLAPY2( PROD1, PROD2 ) / ( RNRM*LNRM )S( KS ) = CONDS( KS+1 ) = CONDEND IFEND IF*IF( WANTSP ) THEN** Estimate the reciprocal condition number of the k-th* eigenvector.** Copy the matrix T to the array WORK and swap the diagonal* block beginning at T(k,k) to the (1,1) position.*CALL DLACPY( 'Full', N, N, T, LDT, WORK, LDWORK )IFST = KILST = 1CALL DTREXC( 'No Q', N, WORK, LDWORK, DUMMY, 1, IFST, ILST,$ WORK( 1, N+1 ), IERR )*IF( IERR.EQ.1 .OR. IERR.EQ.2 ) THEN** Could not swap because blocks not well separated*SCALE = ONEEST = BIGNUMELSE** Reordering successful*IF( WORK( 2, 1 ).EQ.ZERO ) THEN** Form C = T22 - lambda*I in WORK(2:N,2:N).*DO 20 I = 2, NWORK( I, I ) = WORK( I, I ) - WORK( 1, 1 )20 CONTINUEN2 = 1NN = N - 1ELSE** Triangularize the 2 by 2 block by unitary* transformation U = [ cs i*ss ]* [ i*ss cs ].* such that the (1,1) position of WORK is complex* eigenvalue lambda with positive imaginary part. (2,2)* position of WORK is the complex eigenvalue lambda* with negative imaginary part.*MU = SQRT( ABS( WORK( 1, 2 ) ) )*$ SQRT( ABS( WORK( 2, 1 ) ) )DELTA = DLAPY2( MU, WORK( 2, 1 ) )CS = MU / DELTASN = -WORK( 2, 1 ) / DELTA** Form** C' = WORK(2:N,2:N) + i*[rwork(1) ..... rwork(n-1) ]* [ mu ]* [ .. ]* [ .. ]* [ mu ]* where C' is conjugate transpose of complex matrix C,* and RWORK is stored starting in the N+1-st column of* WORK.*DO 30 J = 3, NWORK( 2, J ) = CS*WORK( 2, J )WORK( J, J ) = WORK( J, J ) - WORK( 1, 1 )30 CONTINUEWORK( 2, 2 ) = ZERO*WORK( 1, N+1 ) = TWO*MUDO 40 I = 2, N - 1WORK( I, N+1 ) = SN*WORK( 1, I+1 )40 CONTINUEN2 = 2NN = 2*( N-1 )END IF** Estimate norm(inv(C'))*EST = ZEROKASE = 050 CONTINUECALL DLACON( NN, WORK( 1, N+2 ), WORK( 1, N+4 ), IWORK,$ EST, KASE )IF( KASE.NE.0 ) THENIF( KASE.EQ.1 ) THENIF( N2.EQ.1 ) THEN** Real eigenvalue: solve C'*x = scale*c.*CALL DLAQTR( .TRUE., .TRUE., N-1, WORK( 2, 2 ),$ LDWORK, DUMMY, DUMM, SCALE,$ WORK( 1, N+4 ), WORK( 1, N+6 ),$ IERR )ELSE** Complex eigenvalue: solve* C'*(p+iq) = scale*(c+id) in real arithmetic.*CALL DLAQTR( .TRUE., .FALSE., N-1, WORK( 2, 2 ),$ LDWORK, WORK( 1, N+1 ), MU, SCALE,$ WORK( 1, N+4 ), WORK( 1, N+6 ),$ IERR )END IFELSEIF( N2.EQ.1 ) THEN** Real eigenvalue: solve C*x = scale*c.*CALL DLAQTR( .FALSE., .TRUE., N-1, WORK( 2, 2 ),$ LDWORK, DUMMY, DUMM, SCALE,$ WORK( 1, N+4 ), WORK( 1, N+6 ),$ IERR )ELSE** Complex eigenvalue: solve* C*(p+iq) = scale*(c+id) in real arithmetic.*CALL DLAQTR( .FALSE., .FALSE., N-1,$ WORK( 2, 2 ), LDWORK,$ WORK( 1, N+1 ), MU, SCALE,$ WORK( 1, N+4 ), WORK( 1, N+6 ),$ IERR )*END IFEND IF*GO TO 50END IFEND IF*SEP( KS ) = SCALE / MAX( EST, SMLNUM )IF( PAIR )$ SEP( KS+1 ) = SEP( KS )END IF*IF( PAIR )$ KS = KS + 1*60 CONTINUERETURN** End of DTRSNA*ENDSUBROUTINE DTRSYL( TRANA, TRANB, ISGN, M, N, A, LDA, B, LDB, C,$ LDC, SCALE, INFO )** -- LAPACK routine (version 3.0) --* Univ. of Tennessee, Univ. of California Berkeley, NAG Ltd.,* Courant Institute, Argonne National Lab, and Rice University* March 31, 1993** .. Scalar Arguments ..CHARACTER TRANA, TRANBINTEGER INFO, ISGN, LDA, LDB, LDC, M, NDOUBLE PRECISION SCALE* ..* .. Array Arguments ..DOUBLE PRECISION A( LDA, * ), B( LDB, * ), C( LDC, * )* ..** Purpose* =======** DTRSYL solves the real Sylvester matrix equation:** op(A)*X + X*op(B) = scale*C or* op(A)*X - X*op(B) = scale*C,** where op(A) = A or A**T, and A and B are both upper quasi-* triangular. A is M-by-M and B is N-by-N; the right hand side C and* the solution X are M-by-N; and scale is an output scale factor, set* <= 1 to avoid overflow in X.** A and B must be in Schur canonical form (as returned by DHSEQR), that* is, block upper triangular with 1-by-1 and 2-by-2 diagonal blocks;* each 2-by-2 diagonal block has its diagonal elements equal and its* off-diagonal elements of opposite sign.** Arguments* =========** TRANA (input) CHARACTER*1* Specifies the option op(A):* = 'N': op(A) = A (No transpose)* = 'T': op(A) = A**T (Transpose)* = 'C': op(A) = A**H (Conjugate transpose = Transpose)** TRANB (input) CHARACTER*1* Specifies the option op(B):* = 'N': op(B) = B (No transpose)* = 'T': op(B) = B**T (Transpose)* = 'C': op(B) = B**H (Conjugate transpose = Transpose)** ISGN (input) INTEGER* Specifies the sign in the equation:* = +1: solve op(A)*X + X*op(B) = scale*C* = -1: solve op(A)*X - X*op(B) = scale*C** M (input) INTEGER* The order of the matrix A, and the number of rows in the* matrices X and C. M >= 0.** N (input) INTEGER* The order of the matrix B, and the number of columns in the* matrices X and C. N >= 0.** A (input) DOUBLE PRECISION array, dimension (LDA,M)* The upper quasi-triangular matrix A, in Schur canonical form.** LDA (input) INTEGER* The leading dimension of the array A. LDA >= max(1,M).** B (input) DOUBLE PRECISION array, dimension (LDB,N)* The upper quasi-triangular matrix B, in Schur canonical form.** LDB (input) INTEGER* The leading dimension of the array B. LDB >= max(1,N).** C (input/output) DOUBLE PRECISION array, dimension (LDC,N)* On entry, the M-by-N right hand side matrix C.* On exit, C is overwritten by the solution matrix X.** LDC (input) INTEGER* The leading dimension of the array C. LDC >= max(1,M)** SCALE (output) DOUBLE PRECISION* The scale factor, scale, set <= 1 to avoid overflow in X.** INFO (output) INTEGER* = 0: successful exit* < 0: if INFO = -i, the i-th argument had an illegal value* = 1: A and B have common or very close eigenvalues; perturbed* values were used to solve the equation (but the matrices* A and B are unchanged).** =====================================================================** .. Parameters ..DOUBLE PRECISION ZERO, ONEPARAMETER ( ZERO = 0.0D+0, ONE = 1.0D+0 )* ..* .. Local Scalars ..LOGICAL NOTRNA, NOTRNBINTEGER IERR, J, K, K1, K2, KNEXT, L, L1, L2, LNEXTDOUBLE PRECISION A11, BIGNUM, DA11, DB, EPS, SCALOC, SGN, SMIN,$ SMLNUM, SUML, SUMR, XNORM* ..* .. Local Arrays ..DOUBLE PRECISION DUM( 1 ), VEC( 2, 2 ), X( 2, 2 )* ..* .. External Functions ..LOGICAL LSAMEDOUBLE PRECISION DDOT, DLAMCH, DLANGEEXTERNAL LSAME, DDOT, DLAMCH, DLANGE* ..* .. External Subroutines ..EXTERNAL DLALN2, DLASY2, DSCAL, XERBLA* ..* .. Intrinsic Functions ..INTRINSIC ABS, DBLE, MAX, MIN* ..* .. Executable Statements ..** Decode and Test input parameters*NOTRNA = LSAME( TRANA, 'N' )NOTRNB = LSAME( TRANB, 'N' )*INFO = 0IF( .NOT.NOTRNA .AND. .NOT.LSAME( TRANA, 'T' ) .AND. .NOT.$ LSAME( TRANA, 'C' ) ) THENINFO = -1ELSE IF( .NOT.NOTRNB .AND. .NOT.LSAME( TRANB, 'T' ) .AND. .NOT.$ LSAME( TRANB, 'C' ) ) THENINFO = -2ELSE IF( ISGN.NE.1 .AND. ISGN.NE.-1 ) THENINFO = -3ELSE IF( M.LT.0 ) THENINFO = -4ELSE IF( N.LT.0 ) THENINFO = -5ELSE IF( LDA.LT.MAX( 1, M ) ) THENINFO = -7ELSE IF( LDB.LT.MAX( 1, N ) ) THENINFO = -9ELSE IF( LDC.LT.MAX( 1, M ) ) THENINFO = -11END IFIF( INFO.NE.0 ) THENCALL XERBLA( 'DTRSYL', -INFO )RETURNEND IF** Quick return if possible*IF( M.EQ.0 .OR. N.EQ.0 )$ RETURN** Set constants to control overflow*EPS = DLAMCH( 'P' )SMLNUM = DLAMCH( 'S' )BIGNUM = ONE / SMLNUMCALL DLABAD( SMLNUM, BIGNUM )SMLNUM = SMLNUM*DBLE( M*N ) / EPSBIGNUM = ONE / SMLNUM*SMIN = MAX( SMLNUM, EPS*DLANGE( 'M', M, M, A, LDA, DUM ),$ EPS*DLANGE( 'M', N, N, B, LDB, DUM ) )*SCALE = ONESGN = ISGN*IF( NOTRNA .AND. NOTRNB ) THEN** Solve A*X + ISGN*X*B = scale*C.** The (K,L)th block of X is determined starting from* bottom-left corner column by column by** A(K,K)*X(K,L) + ISGN*X(K,L)*B(L,L) = C(K,L) - R(K,L)** Where* M L-1* R(K,L) = SUM [A(K,I)*X(I,L)] + ISGN*SUM [X(K,J)*B(J,L)].* I=K+1 J=1** Start column loop (index = L)* L1 (L2) : column index of the first (first) row of X(K,L).*LNEXT = 1DO 60 L = 1, NIF( L.LT.LNEXT )$ GO TO 60IF( L.EQ.N ) THENL1 = LL2 = LELSEIF( B( L+1, L ).NE.ZERO ) THENL1 = LL2 = L + 1LNEXT = L + 2ELSEL1 = LL2 = LLNEXT = L + 1END IFEND IF** Start row loop (index = K)* K1 (K2): row index of the first (last) row of X(K,L).*KNEXT = MDO 50 K = M, 1, -1IF( K.GT.KNEXT )$ GO TO 50IF( K.EQ.1 ) THENK1 = KK2 = KELSEIF( A( K, K-1 ).NE.ZERO ) THENK1 = K - 1K2 = KKNEXT = K - 2ELSEK1 = KK2 = KKNEXT = K - 1END IFEND IF*IF( L1.EQ.L2 .AND. K1.EQ.K2 ) THENSUML = DDOT( M-K1, A( K1, MIN( K1+1, M ) ), LDA,$ C( MIN( K1+1, M ), L1 ), 1 )SUMR = DDOT( L1-1, C( K1, 1 ), LDC, B( 1, L1 ), 1 )VEC( 1, 1 ) = C( K1, L1 ) - ( SUML+SGN*SUMR )SCALOC = ONE*A11 = A( K1, K1 ) + SGN*B( L1, L1 )DA11 = ABS( A11 )IF( DA11.LE.SMIN ) THENA11 = SMINDA11 = SMININFO = 1END IFDB = ABS( VEC( 1, 1 ) )IF( DA11.LT.ONE .AND. DB.GT.ONE ) THENIF( DB.GT.BIGNUM*DA11 )$ SCALOC = ONE / DBEND IFX( 1, 1 ) = ( VEC( 1, 1 )*SCALOC ) / A11*IF( SCALOC.NE.ONE ) THENDO 10 J = 1, NCALL DSCAL( M, SCALOC, C( 1, J ), 1 )10 CONTINUESCALE = SCALE*SCALOCEND IFC( K1, L1 ) = X( 1, 1 )*ELSE IF( L1.EQ.L2 .AND. K1.NE.K2 ) THEN*SUML = DDOT( M-K2, A( K1, MIN( K2+1, M ) ), LDA,$ C( MIN( K2+1, M ), L1 ), 1 )SUMR = DDOT( L1-1, C( K1, 1 ), LDC, B( 1, L1 ), 1 )VEC( 1, 1 ) = C( K1, L1 ) - ( SUML+SGN*SUMR )*SUML = DDOT( M-K2, A( K2, MIN( K2+1, M ) ), LDA,$ C( MIN( K2+1, M ), L1 ), 1 )SUMR = DDOT( L1-1, C( K2, 1 ), LDC, B( 1, L1 ), 1 )VEC( 2, 1 ) = C( K2, L1 ) - ( SUML+SGN*SUMR )*CALL DLALN2( .FALSE., 2, 1, SMIN, ONE, A( K1, K1 ),$ LDA, ONE, ONE, VEC, 2, -SGN*B( L1, L1 ),$ ZERO, X, 2, SCALOC, XNORM, IERR )IF( IERR.NE.0 )$ INFO = 1*IF( SCALOC.NE.ONE ) THENDO 20 J = 1, NCALL DSCAL( M, SCALOC, C( 1, J ), 1 )20 CONTINUESCALE = SCALE*SCALOCEND IFC( K1, L1 ) = X( 1, 1 )C( K2, L1 ) = X( 2, 1 )*ELSE IF( L1.NE.L2 .AND. K1.EQ.K2 ) THEN*SUML = DDOT( M-K1, A( K1, MIN( K1+1, M ) ), LDA,$ C( MIN( K1+1, M ), L1 ), 1 )SUMR = DDOT( L1-1, C( K1, 1 ), LDC, B( 1, L1 ), 1 )VEC( 1, 1 ) = SGN*( C( K1, L1 )-( SUML+SGN*SUMR ) )*SUML = DDOT( M-K1, A( K1, MIN( K1+1, M ) ), LDA,$ C( MIN( K1+1, M ), L2 ), 1 )SUMR = DDOT( L1-1, C( K1, 1 ), LDC, B( 1, L2 ), 1 )VEC( 2, 1 ) = SGN*( C( K1, L2 )-( SUML+SGN*SUMR ) )*CALL DLALN2( .TRUE., 2, 1, SMIN, ONE, B( L1, L1 ),$ LDB, ONE, ONE, VEC, 2, -SGN*A( K1, K1 ),$ ZERO, X, 2, SCALOC, XNORM, IERR )IF( IERR.NE.0 )$ INFO = 1*IF( SCALOC.NE.ONE ) THENDO 30 J = 1, NCALL DSCAL( M, SCALOC, C( 1, J ), 1 )30 CONTINUESCALE = SCALE*SCALOCEND IFC( K1, L1 ) = X( 1, 1 )C( K1, L2 ) = X( 2, 1 )*ELSE IF( L1.NE.L2 .AND. K1.NE.K2 ) THEN*SUML = DDOT( M-K2, A( K1, MIN( K2+1, M ) ), LDA,$ C( MIN( K2+1, M ), L1 ), 1 )SUMR = DDOT( L1-1, C( K1, 1 ), LDC, B( 1, L1 ), 1 )VEC( 1, 1 ) = C( K1, L1 ) - ( SUML+SGN*SUMR )*SUML = DDOT( M-K2, A( K1, MIN( K2+1, M ) ), LDA,$ C( MIN( K2+1, M ), L2 ), 1 )SUMR = DDOT( L1-1, C( K1, 1 ), LDC, B( 1, L2 ), 1 )VEC( 1, 2 ) = C( K1, L2 ) - ( SUML+SGN*SUMR )*SUML = DDOT( M-K2, A( K2, MIN( K2+1, M ) ), LDA,$ C( MIN( K2+1, M ), L1 ), 1 )SUMR = DDOT( L1-1, C( K2, 1 ), LDC, B( 1, L1 ), 1 )VEC( 2, 1 ) = C( K2, L1 ) - ( SUML+SGN*SUMR )*SUML = DDOT( M-K2, A( K2, MIN( K2+1, M ) ), LDA,$ C( MIN( K2+1, M ), L2 ), 1 )SUMR = DDOT( L1-1, C( K2, 1 ), LDC, B( 1, L2 ), 1 )VEC( 2, 2 ) = C( K2, L2 ) - ( SUML+SGN*SUMR )*CALL DLASY2( .FALSE., .FALSE., ISGN, 2, 2,$ A( K1, K1 ), LDA, B( L1, L1 ), LDB, VEC,$ 2, SCALOC, X, 2, XNORM, IERR )IF( IERR.NE.0 )$ INFO = 1*IF( SCALOC.NE.ONE ) THENDO 40 J = 1, NCALL DSCAL( M, SCALOC, C( 1, J ), 1 )40 CONTINUESCALE = SCALE*SCALOCEND IFC( K1, L1 ) = X( 1, 1 )C( K1, L2 ) = X( 1, 2 )C( K2, L1 ) = X( 2, 1 )C( K2, L2 ) = X( 2, 2 )END IF*50 CONTINUE*60 CONTINUE*ELSE IF( .NOT.NOTRNA .AND. NOTRNB ) THEN** Solve A' *X + ISGN*X*B = scale*C.** The (K,L)th block of X is determined starting from* upper-left corner column by column by** A(K,K)'*X(K,L) + ISGN*X(K,L)*B(L,L) = C(K,L) - R(K,L)** Where* K-1 L-1* R(K,L) = SUM [A(I,K)'*X(I,L)] +ISGN*SUM [X(K,J)*B(J,L)]* I=1 J=1** Start column loop (index = L)* L1 (L2): column index of the first (last) row of X(K,L)*LNEXT = 1DO 120 L = 1, NIF( L.LT.LNEXT )$ GO TO 120IF( L.EQ.N ) THENL1 = LL2 = LELSEIF( B( L+1, L ).NE.ZERO ) THENL1 = LL2 = L + 1LNEXT = L + 2ELSEL1 = LL2 = LLNEXT = L + 1END IFEND IF** Start row loop (index = K)* K1 (K2): row index of the first (last) row of X(K,L)*KNEXT = 1DO 110 K = 1, MIF( K.LT.KNEXT )$ GO TO 110IF( K.EQ.M ) THENK1 = KK2 = KELSEIF( A( K+1, K ).NE.ZERO ) THENK1 = KK2 = K + 1KNEXT = K + 2ELSEK1 = KK2 = KKNEXT = K + 1END IFEND IF*IF( L1.EQ.L2 .AND. K1.EQ.K2 ) THENSUML = DDOT( K1-1, A( 1, K1 ), 1, C( 1, L1 ), 1 )SUMR = DDOT( L1-1, C( K1, 1 ), LDC, B( 1, L1 ), 1 )VEC( 1, 1 ) = C( K1, L1 ) - ( SUML+SGN*SUMR )SCALOC = ONE*A11 = A( K1, K1 ) + SGN*B( L1, L1 )DA11 = ABS( A11 )IF( DA11.LE.SMIN ) THENA11 = SMINDA11 = SMININFO = 1END IFDB = ABS( VEC( 1, 1 ) )IF( DA11.LT.ONE .AND. DB.GT.ONE ) THENIF( DB.GT.BIGNUM*DA11 )$ SCALOC = ONE / DBEND IFX( 1, 1 ) = ( VEC( 1, 1 )*SCALOC ) / A11*IF( SCALOC.NE.ONE ) THENDO 70 J = 1, NCALL DSCAL( M, SCALOC, C( 1, J ), 1 )70 CONTINUESCALE = SCALE*SCALOCEND IFC( K1, L1 ) = X( 1, 1 )*ELSE IF( L1.EQ.L2 .AND. K1.NE.K2 ) THEN*SUML = DDOT( K1-1, A( 1, K1 ), 1, C( 1, L1 ), 1 )SUMR = DDOT( L1-1, C( K1, 1 ), LDC, B( 1, L1 ), 1 )VEC( 1, 1 ) = C( K1, L1 ) - ( SUML+SGN*SUMR )*SUML = DDOT( K1-1, A( 1, K2 ), 1, C( 1, L1 ), 1 )SUMR = DDOT( L1-1, C( K2, 1 ), LDC, B( 1, L1 ), 1 )VEC( 2, 1 ) = C( K2, L1 ) - ( SUML+SGN*SUMR )*CALL DLALN2( .TRUE., 2, 1, SMIN, ONE, A( K1, K1 ),$ LDA, ONE, ONE, VEC, 2, -SGN*B( L1, L1 ),$ ZERO, X, 2, SCALOC, XNORM, IERR )IF( IERR.NE.0 )$ INFO = 1*IF( SCALOC.NE.ONE ) THENDO 80 J = 1, NCALL DSCAL( M, SCALOC, C( 1, J ), 1 )80 CONTINUESCALE = SCALE*SCALOCEND IFC( K1, L1 ) = X( 1, 1 )C( K2, L1 ) = X( 2, 1 )*ELSE IF( L1.NE.L2 .AND. K1.EQ.K2 ) THEN*SUML = DDOT( K1-1, A( 1, K1 ), 1, C( 1, L1 ), 1 )SUMR = DDOT( L1-1, C( K1, 1 ), LDC, B( 1, L1 ), 1 )VEC( 1, 1 ) = SGN*( C( K1, L1 )-( SUML+SGN*SUMR ) )*SUML = DDOT( K1-1, A( 1, K1 ), 1, C( 1, L2 ), 1 )SUMR = DDOT( L1-1, C( K1, 1 ), LDC, B( 1, L2 ), 1 )VEC( 2, 1 ) = SGN*( C( K1, L2 )-( SUML+SGN*SUMR ) )*CALL DLALN2( .TRUE., 2, 1, SMIN, ONE, B( L1, L1 ),$ LDB, ONE, ONE, VEC, 2, -SGN*A( K1, K1 ),$ ZERO, X, 2, SCALOC, XNORM, IERR )IF( IERR.NE.0 )$ INFO = 1*IF( SCALOC.NE.ONE ) THENDO 90 J = 1, NCALL DSCAL( M, SCALOC, C( 1, J ), 1 )90 CONTINUESCALE = SCALE*SCALOCEND IFC( K1, L1 ) = X( 1, 1 )C( K1, L2 ) = X( 2, 1 )*ELSE IF( L1.NE.L2 .AND. K1.NE.K2 ) THEN*SUML = DDOT( K1-1, A( 1, K1 ), 1, C( 1, L1 ), 1 )SUMR = DDOT( L1-1, C( K1, 1 ), LDC, B( 1, L1 ), 1 )VEC( 1, 1 ) = C( K1, L1 ) - ( SUML+SGN*SUMR )*SUML = DDOT( K1-1, A( 1, K1 ), 1, C( 1, L2 ), 1 )SUMR = DDOT( L1-1, C( K1, 1 ), LDC, B( 1, L2 ), 1 )VEC( 1, 2 ) = C( K1, L2 ) - ( SUML+SGN*SUMR )*SUML = DDOT( K1-1, A( 1, K2 ), 1, C( 1, L1 ), 1 )SUMR = DDOT( L1-1, C( K2, 1 ), LDC, B( 1, L1 ), 1 )VEC( 2, 1 ) = C( K2, L1 ) - ( SUML+SGN*SUMR )*SUML = DDOT( K1-1, A( 1, K2 ), 1, C( 1, L2 ), 1 )SUMR = DDOT( L1-1, C( K2, 1 ), LDC, B( 1, L2 ), 1 )VEC( 2, 2 ) = C( K2, L2 ) - ( SUML+SGN*SUMR )*CALL DLASY2( .TRUE., .FALSE., ISGN, 2, 2, A( K1, K1 ),$ LDA, B( L1, L1 ), LDB, VEC, 2, SCALOC, X,$ 2, XNORM, IERR )IF( IERR.NE.0 )$ INFO = 1*IF( SCALOC.NE.ONE ) THENDO 100 J = 1, NCALL DSCAL( M, SCALOC, C( 1, J ), 1 )100 CONTINUESCALE = SCALE*SCALOCEND IFC( K1, L1 ) = X( 1, 1 )C( K1, L2 ) = X( 1, 2 )C( K2, L1 ) = X( 2, 1 )C( K2, L2 ) = X( 2, 2 )END IF*110 CONTINUE120 CONTINUE*ELSE IF( .NOT.NOTRNA .AND. .NOT.NOTRNB ) THEN** Solve A'*X + ISGN*X*B' = scale*C.** The (K,L)th block of X is determined starting from* top-right corner column by column by** A(K,K)'*X(K,L) + ISGN*X(K,L)*B(L,L)' = C(K,L) - R(K,L)** Where* K-1 N* R(K,L) = SUM [A(I,K)'*X(I,L)] + ISGN*SUM [X(K,J)*B(L,J)'].* I=1 J=L+1** Start column loop (index = L)* L1 (L2): column index of the first (last) row of X(K,L)*LNEXT = NDO 180 L = N, 1, -1IF( L.GT.LNEXT )$ GO TO 180IF( L.EQ.1 ) THENL1 = LL2 = LELSEIF( B( L, L-1 ).NE.ZERO ) THENL1 = L - 1L2 = LLNEXT = L - 2ELSEL1 = LL2 = LLNEXT = L - 1END IFEND IF** Start row loop (index = K)* K1 (K2): row index of the first (last) row of X(K,L)*KNEXT = 1DO 170 K = 1, MIF( K.LT.KNEXT )$ GO TO 170IF( K.EQ.M ) THENK1 = KK2 = KELSEIF( A( K+1, K ).NE.ZERO ) THENK1 = KK2 = K + 1KNEXT = K + 2ELSEK1 = KK2 = KKNEXT = K + 1END IFEND IF*IF( L1.EQ.L2 .AND. K1.EQ.K2 ) THENSUML = DDOT( K1-1, A( 1, K1 ), 1, C( 1, L1 ), 1 )SUMR = DDOT( N-L1, C( K1, MIN( L1+1, N ) ), LDC,$ B( L1, MIN( L1+1, N ) ), LDB )VEC( 1, 1 ) = C( K1, L1 ) - ( SUML+SGN*SUMR )SCALOC = ONE*A11 = A( K1, K1 ) + SGN*B( L1, L1 )DA11 = ABS( A11 )IF( DA11.LE.SMIN ) THENA11 = SMINDA11 = SMININFO = 1END IFDB = ABS( VEC( 1, 1 ) )IF( DA11.LT.ONE .AND. DB.GT.ONE ) THENIF( DB.GT.BIGNUM*DA11 )$ SCALOC = ONE / DBEND IFX( 1, 1 ) = ( VEC( 1, 1 )*SCALOC ) / A11*IF( SCALOC.NE.ONE ) THENDO 130 J = 1, NCALL DSCAL( M, SCALOC, C( 1, J ), 1 )130 CONTINUESCALE = SCALE*SCALOCEND IFC( K1, L1 ) = X( 1, 1 )*ELSE IF( L1.EQ.L2 .AND. K1.NE.K2 ) THEN*SUML = DDOT( K1-1, A( 1, K1 ), 1, C( 1, L1 ), 1 )SUMR = DDOT( N-L2, C( K1, MIN( L2+1, N ) ), LDC,$ B( L1, MIN( L2+1, N ) ), LDB )VEC( 1, 1 ) = C( K1, L1 ) - ( SUML+SGN*SUMR )*SUML = DDOT( K1-1, A( 1, K2 ), 1, C( 1, L1 ), 1 )SUMR = DDOT( N-L2, C( K2, MIN( L2+1, N ) ), LDC,$ B( L1, MIN( L2+1, N ) ), LDB )VEC( 2, 1 ) = C( K2, L1 ) - ( SUML+SGN*SUMR )*CALL DLALN2( .TRUE., 2, 1, SMIN, ONE, A( K1, K1 ),$ LDA, ONE, ONE, VEC, 2, -SGN*B( L1, L1 ),$ ZERO, X, 2, SCALOC, XNORM, IERR )IF( IERR.NE.0 )$ INFO = 1*IF( SCALOC.NE.ONE ) THENDO 140 J = 1, NCALL DSCAL( M, SCALOC, C( 1, J ), 1 )140 CONTINUESCALE = SCALE*SCALOCEND IFC( K1, L1 ) = X( 1, 1 )C( K2, L1 ) = X( 2, 1 )*ELSE IF( L1.NE.L2 .AND. K1.EQ.K2 ) THEN*SUML = DDOT( K1-1, A( 1, K1 ), 1, C( 1, L1 ), 1 )SUMR = DDOT( N-L2, C( K1, MIN( L2+1, N ) ), LDC,$ B( L1, MIN( L2+1, N ) ), LDB )VEC( 1, 1 ) = SGN*( C( K1, L1 )-( SUML+SGN*SUMR ) )*SUML = DDOT( K1-1, A( 1, K1 ), 1, C( 1, L2 ), 1 )SUMR = DDOT( N-L2, C( K1, MIN( L2+1, N ) ), LDC,$ B( L2, MIN( L2+1, N ) ), LDB )VEC( 2, 1 ) = SGN*( C( K1, L2 )-( SUML+SGN*SUMR ) )*CALL DLALN2( .FALSE., 2, 1, SMIN, ONE, B( L1, L1 ),$ LDB, ONE, ONE, VEC, 2, -SGN*A( K1, K1 ),$ ZERO, X, 2, SCALOC, XNORM, IERR )IF( IERR.NE.0 )$ INFO = 1*IF( SCALOC.NE.ONE ) THENDO 150 J = 1, NCALL DSCAL( M, SCALOC, C( 1, J ), 1 )150 CONTINUESCALE = SCALE*SCALOCEND IFC( K1, L1 ) = X( 1, 1 )C( K1, L2 ) = X( 2, 1 )*ELSE IF( L1.NE.L2 .AND. K1.NE.K2 ) THEN*SUML = DDOT( K1-1, A( 1, K1 ), 1, C( 1, L1 ), 1 )SUMR = DDOT( N-L2, C( K1, MIN( L2+1, N ) ), LDC,$ B( L1, MIN( L2+1, N ) ), LDB )VEC( 1, 1 ) = C( K1, L1 ) - ( SUML+SGN*SUMR )*SUML = DDOT( K1-1, A( 1, K1 ), 1, C( 1, L2 ), 1 )SUMR = DDOT( N-L2, C( K1, MIN( L2+1, N ) ), LDC,$ B( L2, MIN( L2+1, N ) ), LDB )VEC( 1, 2 ) = C( K1, L2 ) - ( SUML+SGN*SUMR )*SUML = DDOT( K1-1, A( 1, K2 ), 1, C( 1, L1 ), 1 )SUMR = DDOT( N-L2, C( K2, MIN( L2+1, N ) ), LDC,$ B( L1, MIN( L2+1, N ) ), LDB )VEC( 2, 1 ) = C( K2, L1 ) - ( SUML+SGN*SUMR )*SUML = DDOT( K1-1, A( 1, K2 ), 1, C( 1, L2 ), 1 )SUMR = DDOT( N-L2, C( K2, MIN( L2+1, N ) ), LDC,$ B( L2, MIN( L2+1, N ) ), LDB )VEC( 2, 2 ) = C( K2, L2 ) - ( SUML+SGN*SUMR )*CALL DLASY2( .TRUE., .TRUE., ISGN, 2, 2, A( K1, K1 ),$ LDA, B( L1, L1 ), LDB, VEC, 2, SCALOC, X,$ 2, XNORM, IERR )IF( IERR.NE.0 )$ INFO = 1*IF( SCALOC.NE.ONE ) THENDO 160 J = 1, NCALL DSCAL( M, SCALOC, C( 1, J ), 1 )160 CONTINUESCALE = SCALE*SCALOCEND IFC( K1, L1 ) = X( 1, 1 )C( K1, L2 ) = X( 1, 2 )C( K2, L1 ) = X( 2, 1 )C( K2, L2 ) = X( 2, 2 )END IF*170 CONTINUE180 CONTINUE*ELSE IF( NOTRNA .AND. .NOT.NOTRNB ) THEN** Solve A*X + ISGN*X*B' = scale*C.** The (K,L)th block of X is determined starting from* bottom-right corner column by column by** A(K,K)*X(K,L) + ISGN*X(K,L)*B(L,L)' = C(K,L) - R(K,L)** Where* M N* R(K,L) = SUM [A(K,I)*X(I,L)] + ISGN*SUM [X(K,J)*B(L,J)'].* I=K+1 J=L+1** Start column loop (index = L)* L1 (L2): column index of the first (last) row of X(K,L)*LNEXT = NDO 240 L = N, 1, -1IF( L.GT.LNEXT )$ GO TO 240IF( L.EQ.1 ) THENL1 = LL2 = LELSEIF( B( L, L-1 ).NE.ZERO ) THENL1 = L - 1L2 = LLNEXT = L - 2ELSEL1 = LL2 = LLNEXT = L - 1END IFEND IF** Start row loop (index = K)* K1 (K2): row index of the first (last) row of X(K,L)*KNEXT = MDO 230 K = M, 1, -1IF( K.GT.KNEXT )$ GO TO 230IF( K.EQ.1 ) THENK1 = KK2 = KELSEIF( A( K, K-1 ).NE.ZERO ) THENK1 = K - 1K2 = KKNEXT = K - 2ELSEK1 = KK2 = KKNEXT = K - 1END IFEND IF*IF( L1.EQ.L2 .AND. K1.EQ.K2 ) THENSUML = DDOT( M-K1, A( K1, MIN( K1+1, M ) ), LDA,$ C( MIN( K1+1, M ), L1 ), 1 )SUMR = DDOT( N-L1, C( K1, MIN( L1+1, N ) ), LDC,$ B( L1, MIN( L1+1, N ) ), LDB )VEC( 1, 1 ) = C( K1, L1 ) - ( SUML+SGN*SUMR )SCALOC = ONE*A11 = A( K1, K1 ) + SGN*B( L1, L1 )DA11 = ABS( A11 )IF( DA11.LE.SMIN ) THENA11 = SMINDA11 = SMININFO = 1END IFDB = ABS( VEC( 1, 1 ) )IF( DA11.LT.ONE .AND. DB.GT.ONE ) THENIF( DB.GT.BIGNUM*DA11 )$ SCALOC = ONE / DBEND IFX( 1, 1 ) = ( VEC( 1, 1 )*SCALOC ) / A11*IF( SCALOC.NE.ONE ) THENDO 190 J = 1, NCALL DSCAL( M, SCALOC, C( 1, J ), 1 )190 CONTINUESCALE = SCALE*SCALOCEND IFC( K1, L1 ) = X( 1, 1 )*ELSE IF( L1.EQ.L2 .AND. K1.NE.K2 ) THEN*SUML = DDOT( M-K2, A( K1, MIN( K2+1, M ) ), LDA,$ C( MIN( K2+1, M ), L1 ), 1 )SUMR = DDOT( N-L2, C( K1, MIN( L2+1, N ) ), LDC,$ B( L1, MIN( L2+1, N ) ), LDB )VEC( 1, 1 ) = C( K1, L1 ) - ( SUML+SGN*SUMR )*SUML = DDOT( M-K2, A( K2, MIN( K2+1, M ) ), LDA,$ C( MIN( K2+1, M ), L1 ), 1 )SUMR = DDOT( N-L2, C( K2, MIN( L2+1, N ) ), LDC,$ B( L1, MIN( L2+1, N ) ), LDB )VEC( 2, 1 ) = C( K2, L1 ) - ( SUML+SGN*SUMR )*CALL DLALN2( .FALSE., 2, 1, SMIN, ONE, A( K1, K1 ),$ LDA, ONE, ONE, VEC, 2, -SGN*B( L1, L1 ),$ ZERO, X, 2, SCALOC, XNORM, IERR )IF( IERR.NE.0 )$ INFO = 1*IF( SCALOC.NE.ONE ) THENDO 200 J = 1, NCALL DSCAL( M, SCALOC, C( 1, J ), 1 )200 CONTINUESCALE = SCALE*SCALOCEND IFC( K1, L1 ) = X( 1, 1 )C( K2, L1 ) = X( 2, 1 )*ELSE IF( L1.NE.L2 .AND. K1.EQ.K2 ) THEN*SUML = DDOT( M-K1, A( K1, MIN( K1+1, M ) ), LDA,$ C( MIN( K1+1, M ), L1 ), 1 )SUMR = DDOT( N-L2, C( K1, MIN( L2+1, N ) ), LDC,$ B( L1, MIN( L2+1, N ) ), LDB )VEC( 1, 1 ) = SGN*( C( K1, L1 )-( SUML+SGN*SUMR ) )*SUML = DDOT( M-K1, A( K1, MIN( K1+1, M ) ), LDA,$ C( MIN( K1+1, M ), L2 ), 1 )SUMR = DDOT( N-L2, C( K1, MIN( L2+1, N ) ), LDC,$ B( L2, MIN( L2+1, N ) ), LDB )VEC( 2, 1 ) = SGN*( C( K1, L2 )-( SUML+SGN*SUMR ) )*CALL DLALN2( .FALSE., 2, 1, SMIN, ONE, B( L1, L1 ),$ LDB, ONE, ONE, VEC, 2, -SGN*A( K1, K1 ),$ ZERO, X, 2, SCALOC, XNORM, IERR )IF( IERR.NE.0 )$ INFO = 1*IF( SCALOC.NE.ONE ) THENDO 210 J = 1, NCALL DSCAL( M, SCALOC, C( 1, J ), 1 )210 CONTINUESCALE = SCALE*SCALOCEND IFC( K1, L1 ) = X( 1, 1 )C( K1, L2 ) = X( 2, 1 )*ELSE IF( L1.NE.L2 .AND. K1.NE.K2 ) THEN*SUML = DDOT( M-K2, A( K1, MIN( K2+1, M ) ), LDA,$ C( MIN( K2+1, M ), L1 ), 1 )SUMR = DDOT( N-L2, C( K1, MIN( L2+1, N ) ), LDC,$ B( L1, MIN( L2+1, N ) ), LDB )VEC( 1, 1 ) = C( K1, L1 ) - ( SUML+SGN*SUMR )*SUML = DDOT( M-K2, A( K1, MIN( K2+1, M ) ), LDA,$ C( MIN( K2+1, M ), L2 ), 1 )SUMR = DDOT( N-L2, C( K1, MIN( L2+1, N ) ), LDC,$ B( L2, MIN( L2+1, N ) ), LDB )VEC( 1, 2 ) = C( K1, L2 ) - ( SUML+SGN*SUMR )*SUML = DDOT( M-K2, A( K2, MIN( K2+1, M ) ), LDA,$ C( MIN( K2+1, M ), L1 ), 1 )SUMR = DDOT( N-L2, C( K2, MIN( L2+1, N ) ), LDC,$ B( L1, MIN( L2+1, N ) ), LDB )VEC( 2, 1 ) = C( K2, L1 ) - ( SUML+SGN*SUMR )*SUML = DDOT( M-K2, A( K2, MIN( K2+1, M ) ), LDA,$ C( MIN( K2+1, M ), L2 ), 1 )SUMR = DDOT( N-L2, C( K2, MIN( L2+1, N ) ), LDC,$ B( L2, MIN( L2+1, N ) ), LDB )VEC( 2, 2 ) = C( K2, L2 ) - ( SUML+SGN*SUMR )*CALL DLASY2( .FALSE., .TRUE., ISGN, 2, 2, A( K1, K1 ),$ LDA, B( L1, L1 ), LDB, VEC, 2, SCALOC, X,$ 2, XNORM, IERR )IF( IERR.NE.0 )$ INFO = 1*IF( SCALOC.NE.ONE ) THENDO 220 J = 1, NCALL DSCAL( M, SCALOC, C( 1, J ), 1 )220 CONTINUESCALE = SCALE*SCALOCEND IFC( K1, L1 ) = X( 1, 1 )C( K1, L2 ) = X( 1, 2 )C( K2, L1 ) = X( 2, 1 )C( K2, L2 ) = X( 2, 2 )END IF*230 CONTINUE240 CONTINUE*END IF*RETURN** End of DTRSYL*ENDINTEGER FUNCTION IEEECK( ISPEC, ZERO, ONE )** -- LAPACK auxiliary routine (version 3.0) --* Univ. of Tennessee, Univ. of California Berkeley, NAG Ltd.,* Courant Institute, Argonne National Lab, and Rice University* June 30, 1998** .. Scalar Arguments ..INTEGER ISPECREAL ONE, ZERO* ..** Purpose* =======** IEEECK is called from the ILAENV to verify that Infinity and* possibly NaN arithmetic is safe (i.e. will not trap).** Arguments* =========** ISPEC (input) INTEGER* Specifies whether to test just for inifinity arithmetic* or whether to test for infinity and NaN arithmetic.* = 0: Verify infinity arithmetic only.* = 1: Verify infinity and NaN arithmetic.** ZERO (input) REAL* Must contain the value 0.0* This is passed to prevent the compiler from optimizing* away this code.** ONE (input) REAL* Must contain the value 1.0* This is passed to prevent the compiler from optimizing* away this code.** RETURN VALUE: INTEGER* = 0: Arithmetic failed to produce the correct answers* = 1: Arithmetic produced the correct answers** .. Local Scalars ..REAL NAN1, NAN2, NAN3, NAN4, NAN5, NAN6, NEGINF,$ NEGZRO, NEWZRO, POSINF* ..* .. Executable Statements ..IEEECK = 1*POSINF = ONE / ZEROIF( POSINF.LE.ONE ) THENIEEECK = 0RETURNEND IF*NEGINF = -ONE / ZEROIF( NEGINF.GE.ZERO ) THENIEEECK = 0RETURNEND IF*NEGZRO = ONE / ( NEGINF+ONE )IF( NEGZRO.NE.ZERO ) THENIEEECK = 0RETURNEND IF*NEGINF = ONE / NEGZROIF( NEGINF.GE.ZERO ) THENIEEECK = 0RETURNEND IF*NEWZRO = NEGZRO + ZEROIF( NEWZRO.NE.ZERO ) THENIEEECK = 0RETURNEND IF*POSINF = ONE / NEWZROIF( POSINF.LE.ONE ) THENIEEECK = 0RETURNEND IF*NEGINF = NEGINF*POSINFIF( NEGINF.GE.ZERO ) THENIEEECK = 0RETURNEND IF*POSINF = POSINF*POSINFIF( POSINF.LE.ONE ) THENIEEECK = 0RETURNEND IF***** Return if we were only asked to check infinity arithmetic*IF( ISPEC.EQ.0 )$ RETURN*NAN1 = POSINF + NEGINF*NAN2 = POSINF / NEGINF*NAN3 = POSINF / POSINF*NAN4 = POSINF*ZERO*NAN5 = NEGINF*NEGZRO*NAN6 = NAN5*0.0*IF( NAN1.EQ.NAN1 ) THENIEEECK = 0RETURNEND IF*IF( NAN2.EQ.NAN2 ) THENIEEECK = 0RETURNEND IF*IF( NAN3.EQ.NAN3 ) THENIEEECK = 0RETURNEND IF*IF( NAN4.EQ.NAN4 ) THENIEEECK = 0RETURNEND IF*IF( NAN5.EQ.NAN5 ) THENIEEECK = 0RETURNEND IF*IF( NAN6.EQ.NAN6 ) THENIEEECK = 0RETURNEND IF*RETURNENDINTEGER FUNCTION ILAENV( ISPEC, NAME, OPTS, N1, N2, N3,$ N4 )** -- LAPACK auxiliary 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*( * ) NAME, OPTSINTEGER ISPEC, N1, N2, N3, N4* ..** Purpose* =======** ILAENV is called from the LAPACK routines to choose problem-dependent* parameters for the local environment. See ISPEC for a description of* the parameters.** This version provides a set of parameters which should give good,* but not optimal, performance on many of the currently available* computers. Users are encouraged to modify this subroutine to set* the tuning parameters for their particular machine using the option* and problem size information in the arguments.** This routine will not function correctly if it is converted to all* lower case. Converting it to all upper case is allowed.** Arguments* =========** ISPEC (input) INTEGER* Specifies the parameter to be returned as the value of* ILAENV.* = 1: the optimal blocksize; if this value is 1, an unblocked* algorithm will give the best performance.* = 2: the minimum block size for which the block routine* should be used; if the usable block size is less than* this value, an unblocked routine should be used.* = 3: the crossover point (in a block routine, for N less* than this value, an unblocked routine should be used)* = 4: the number of shifts, used in the nonsymmetric* eigenvalue routines* = 5: the minimum column dimension for blocking to be used;* rectangular blocks must have dimension at least k by m,* where k is given by ILAENV(2,...) and m by ILAENV(5,...)* = 6: the crossover point for the SVD (when reducing an m by n* matrix to bidiagonal form, if max(m,n)/min(m,n) exceeds* this value, a QR factorization is used first to reduce* the matrix to a triangular form.)* = 7: the number of processors* = 8: the crossover point for the multishift QR and QZ methods* for nonsymmetric eigenvalue problems.* = 9: maximum size of the subproblems at the bottom of the* computation tree in the divide-and-conquer algorithm* (used by xGELSD and xGESDD)* =10: ieee NaN arithmetic can be trusted not to trap* =11: infinity arithmetic can be trusted not to trap** NAME (input) CHARACTER*(*)* The name of the calling subroutine, in either upper case or* lower case.** OPTS (input) CHARACTER*(*)* The character options to the subroutine NAME, concatenated* into a single character string. For example, UPLO = 'U',* TRANS = 'T', and DIAG = 'N' for a triangular routine would* be specified as OPTS = 'UTN'.** N1 (input) INTEGER* N2 (input) INTEGER* N3 (input) INTEGER* N4 (input) INTEGER* Problem dimensions for the subroutine NAME; these may not all* be required.** (ILAENV) (output) INTEGER* >= 0: the value of the parameter specified by ISPEC* < 0: if ILAENV = -k, the k-th argument had an illegal value.** Further Details* ===============** The following conventions have been used when calling ILAENV from the* LAPACK routines:* 1) OPTS is a concatenation of all of the character options to* subroutine NAME, in the same order that they appear in the* argument list for NAME, even if they are not used in determining* the value of the parameter specified by ISPEC.* 2) The problem dimensions N1, N2, N3, N4 are specified in the order* that they appear in the argument list for NAME. N1 is used* first, N2 second, and so on, and unused problem dimensions are* passed a value of -1.* 3) The parameter value returned by ILAENV is checked for validity in* the calling subroutine. For example, ILAENV is used to retrieve* the optimal blocksize for STRTRI as follows:** NB = ILAENV( 1, 'STRTRI', UPLO // DIAG, N, -1, -1, -1 )* IF( NB.LE.1 ) NB = MAX( 1, N )** =====================================================================** .. Local Scalars ..LOGICAL CNAME, SNAMECHARACTER*1 C1CHARACTER*2 C2, C4CHARACTER*3 C3CHARACTER*6 SUBNAMINTEGER I, IC, IZ, NB, NBMIN, NX* ..* .. Intrinsic Functions ..INTRINSIC CHAR, ICHAR, INT, MIN, REAL* ..* .. External Functions ..INTEGER IEEECKEXTERNAL IEEECK* ..* .. Executable Statements ..*GO TO ( 100, 100, 100, 400, 500, 600, 700, 800, 900, 1000,$ 1100 ) ISPEC** Invalid value for ISPEC*ILAENV = -1RETURN*100 CONTINUE** Convert NAME to upper case if the first character is lower case.*ILAENV = 1SUBNAM = NAMEIC = ICHAR( SUBNAM( 1:1 ) )IZ = ICHAR( 'Z' )IF( IZ.EQ.90 .OR. IZ.EQ.122 ) THEN** ASCII character set*IF( IC.GE.97 .AND. IC.LE.122 ) THENSUBNAM( 1:1 ) = CHAR( IC-32 )DO 10 I = 2, 6IC = ICHAR( SUBNAM( I:I ) )IF( IC.GE.97 .AND. IC.LE.122 )$ SUBNAM( I:I ) = CHAR( IC-32 )10 CONTINUEEND IF*ELSE IF( IZ.EQ.233 .OR. IZ.EQ.169 ) THEN** EBCDIC character set*IF( ( IC.GE.129 .AND. IC.LE.137 ) .OR.$ ( IC.GE.145 .AND. IC.LE.153 ) .OR.$ ( IC.GE.162 .AND. IC.LE.169 ) ) THENSUBNAM( 1:1 ) = CHAR( IC+64 )DO 20 I = 2, 6IC = ICHAR( SUBNAM( I:I ) )IF( ( IC.GE.129 .AND. IC.LE.137 ) .OR.$ ( IC.GE.145 .AND. IC.LE.153 ) .OR.$ ( IC.GE.162 .AND. IC.LE.169 ) )$ SUBNAM( I:I ) = CHAR( IC+64 )20 CONTINUEEND IF*ELSE IF( IZ.EQ.218 .OR. IZ.EQ.250 ) THEN** Prime machines: ASCII+128*IF( IC.GE.225 .AND. IC.LE.250 ) THENSUBNAM( 1:1 ) = CHAR( IC-32 )DO 30 I = 2, 6IC = ICHAR( SUBNAM( I:I ) )IF( IC.GE.225 .AND. IC.LE.250 )$ SUBNAM( I:I ) = CHAR( IC-32 )30 CONTINUEEND IFEND IF*C1 = SUBNAM( 1:1 )SNAME = C1.EQ.'S' .OR. C1.EQ.'D'CNAME = C1.EQ.'C' .OR. C1.EQ.'Z'IF( .NOT.( CNAME .OR. SNAME ) )$ RETURNC2 = SUBNAM( 2:3 )C3 = SUBNAM( 4:6 )C4 = C3( 2:3 )*GO TO ( 110, 200, 300 ) ISPEC*110 CONTINUE** ISPEC = 1: block size** In these examples, separate code is provided for setting NB for* real and complex. We assume that NB will take the same value in* single or double precision.*NB = 1*IF( C2.EQ.'GE' ) THENIF( C3.EQ.'TRF' ) THENIF( SNAME ) THENNB = 64ELSENB = 64END IFELSE IF( C3.EQ.'QRF' .OR. C3.EQ.'RQF' .OR. C3.EQ.'LQF' .OR.$ C3.EQ.'QLF' ) THENIF( SNAME ) THENNB = 32ELSENB = 32END IFELSE IF( C3.EQ.'HRD' ) THENIF( SNAME ) THENNB = 32ELSENB = 32END IFELSE IF( C3.EQ.'BRD' ) THENIF( SNAME ) THENNB = 32ELSENB = 32END IFELSE IF( C3.EQ.'TRI' ) THENIF( SNAME ) THENNB = 64ELSENB = 64END IFEND IFELSE IF( C2.EQ.'PO' ) THENIF( C3.EQ.'TRF' ) THENIF( SNAME ) THENNB = 64ELSENB = 64END IFEND IFELSE IF( C2.EQ.'SY' ) THENIF( C3.EQ.'TRF' ) THENIF( SNAME ) THENNB = 64ELSENB = 64END IFELSE IF( SNAME .AND. C3.EQ.'TRD' ) THENNB = 32ELSE IF( SNAME .AND. C3.EQ.'GST' ) THENNB = 64END IFELSE IF( CNAME .AND. C2.EQ.'HE' ) THENIF( C3.EQ.'TRF' ) THENNB = 64ELSE IF( C3.EQ.'TRD' ) THENNB = 32ELSE IF( C3.EQ.'GST' ) THENNB = 64END IFELSE IF( SNAME .AND. C2.EQ.'OR' ) THENIF( C3( 1:1 ).EQ.'G' ) THENIF( C4.EQ.'QR' .OR. C4.EQ.'RQ' .OR. C4.EQ.'LQ' .OR.$ C4.EQ.'QL' .OR. C4.EQ.'HR' .OR. C4.EQ.'TR' .OR.$ C4.EQ.'BR' ) THENNB = 32END IFELSE IF( C3( 1:1 ).EQ.'M' ) THENIF( C4.EQ.'QR' .OR. C4.EQ.'RQ' .OR. C4.EQ.'LQ' .OR.$ C4.EQ.'QL' .OR. C4.EQ.'HR' .OR. C4.EQ.'TR' .OR.$ C4.EQ.'BR' ) THENNB = 32END IFEND IFELSE IF( CNAME .AND. C2.EQ.'UN' ) THENIF( C3( 1:1 ).EQ.'G' ) THENIF( C4.EQ.'QR' .OR. C4.EQ.'RQ' .OR. C4.EQ.'LQ' .OR.$ C4.EQ.'QL' .OR. C4.EQ.'HR' .OR. C4.EQ.'TR' .OR.$ C4.EQ.'BR' ) THENNB = 32END IFELSE IF( C3( 1:1 ).EQ.'M' ) THENIF( C4.EQ.'QR' .OR. C4.EQ.'RQ' .OR. C4.EQ.'LQ' .OR.$ C4.EQ.'QL' .OR. C4.EQ.'HR' .OR. C4.EQ.'TR' .OR.$ C4.EQ.'BR' ) THENNB = 32END IFEND IFELSE IF( C2.EQ.'GB' ) THENIF( C3.EQ.'TRF' ) THENIF( SNAME ) THENIF( N4.LE.64 ) THENNB = 1ELSENB = 32END IFELSEIF( N4.LE.64 ) THENNB = 1ELSENB = 32END IFEND IFEND IFELSE IF( C2.EQ.'PB' ) THENIF( C3.EQ.'TRF' ) THENIF( SNAME ) THENIF( N2.LE.64 ) THENNB = 1ELSENB = 32END IFELSEIF( N2.LE.64 ) THENNB = 1ELSENB = 32END IFEND IFEND IFELSE IF( C2.EQ.'TR' ) THENIF( C3.EQ.'TRI' ) THENIF( SNAME ) THENNB = 64ELSENB = 64END IFEND IFELSE IF( C2.EQ.'LA' ) THENIF( C3.EQ.'UUM' ) THENIF( SNAME ) THENNB = 64ELSENB = 64END IFEND IFELSE IF( SNAME .AND. C2.EQ.'ST' ) THENIF( C3.EQ.'EBZ' ) THENNB = 1END IFEND IFILAENV = NBRETURN*200 CONTINUE** ISPEC = 2: minimum block size*NBMIN = 2IF( C2.EQ.'GE' ) THENIF( C3.EQ.'QRF' .OR. C3.EQ.'RQF' .OR. C3.EQ.'LQF' .OR.$ C3.EQ.'QLF' ) THENIF( SNAME ) THENNBMIN = 2ELSENBMIN = 2END IFELSE IF( C3.EQ.'HRD' ) THENIF( SNAME ) THENNBMIN = 2ELSENBMIN = 2END IFELSE IF( C3.EQ.'BRD' ) THENIF( SNAME ) THENNBMIN = 2ELSENBMIN = 2END IFELSE IF( C3.EQ.'TRI' ) THENIF( SNAME ) THENNBMIN = 2ELSENBMIN = 2END IFEND IFELSE IF( C2.EQ.'SY' ) THENIF( C3.EQ.'TRF' ) THENIF( SNAME ) THENNBMIN = 8ELSENBMIN = 8END IFELSE IF( SNAME .AND. C3.EQ.'TRD' ) THENNBMIN = 2END IFELSE IF( CNAME .AND. C2.EQ.'HE' ) THENIF( C3.EQ.'TRD' ) THENNBMIN = 2END IFELSE IF( SNAME .AND. C2.EQ.'OR' ) THENIF( C3( 1:1 ).EQ.'G' ) THENIF( C4.EQ.'QR' .OR. C4.EQ.'RQ' .OR. C4.EQ.'LQ' .OR.$ C4.EQ.'QL' .OR. C4.EQ.'HR' .OR. C4.EQ.'TR' .OR.$ C4.EQ.'BR' ) THENNBMIN = 2END IFELSE IF( C3( 1:1 ).EQ.'M' ) THENIF( C4.EQ.'QR' .OR. C4.EQ.'RQ' .OR. C4.EQ.'LQ' .OR.$ C4.EQ.'QL' .OR. C4.EQ.'HR' .OR. C4.EQ.'TR' .OR.$ C4.EQ.'BR' ) THENNBMIN = 2END IFEND IFELSE IF( CNAME .AND. C2.EQ.'UN' ) THENIF( C3( 1:1 ).EQ.'G' ) THENIF( C4.EQ.'QR' .OR. C4.EQ.'RQ' .OR. C4.EQ.'LQ' .OR.$ C4.EQ.'QL' .OR. C4.EQ.'HR' .OR. C4.EQ.'TR' .OR.$ C4.EQ.'BR' ) THENNBMIN = 2END IFELSE IF( C3( 1:1 ).EQ.'M' ) THENIF( C4.EQ.'QR' .OR. C4.EQ.'RQ' .OR. C4.EQ.'LQ' .OR.$ C4.EQ.'QL' .OR. C4.EQ.'HR' .OR. C4.EQ.'TR' .OR.$ C4.EQ.'BR' ) THENNBMIN = 2END IFEND IFEND IFILAENV = NBMINRETURN*300 CONTINUE** ISPEC = 3: crossover point*NX = 0IF( C2.EQ.'GE' ) THENIF( C3.EQ.'QRF' .OR. C3.EQ.'RQF' .OR. C3.EQ.'LQF' .OR.$ C3.EQ.'QLF' ) THENIF( SNAME ) THENNX = 128ELSENX = 128END IFELSE IF( C3.EQ.'HRD' ) THENIF( SNAME ) THENNX = 128ELSENX = 128END IFELSE IF( C3.EQ.'BRD' ) THENIF( SNAME ) THENNX = 128ELSENX = 128END IFEND IFELSE IF( C2.EQ.'SY' ) THENIF( SNAME .AND. C3.EQ.'TRD' ) THENNX = 32END IFELSE IF( CNAME .AND. C2.EQ.'HE' ) THENIF( C3.EQ.'TRD' ) THENNX = 32END IFELSE IF( SNAME .AND. C2.EQ.'OR' ) THENIF( C3( 1:1 ).EQ.'G' ) THENIF( C4.EQ.'QR' .OR. C4.EQ.'RQ' .OR. C4.EQ.'LQ' .OR.$ C4.EQ.'QL' .OR. C4.EQ.'HR' .OR. C4.EQ.'TR' .OR.$ C4.EQ.'BR' ) THENNX = 128END IFEND IFELSE IF( CNAME .AND. C2.EQ.'UN' ) THENIF( C3( 1:1 ).EQ.'G' ) THENIF( C4.EQ.'QR' .OR. C4.EQ.'RQ' .OR. C4.EQ.'LQ' .OR.$ C4.EQ.'QL' .OR. C4.EQ.'HR' .OR. C4.EQ.'TR' .OR.$ C4.EQ.'BR' ) THENNX = 128END IFEND IFEND IFILAENV = NXRETURN*400 CONTINUE** ISPEC = 4: number of shifts (used by xHSEQR)*ILAENV = 6RETURN*500 CONTINUE** ISPEC = 5: minimum column dimension (not used)*ILAENV = 2RETURN*600 CONTINUE** ISPEC = 6: crossover point for SVD (used by xGELSS and xGESVD)*ILAENV = INT( REAL( MIN( N1, N2 ) )*1.6E0 )RETURN*700 CONTINUE** ISPEC = 7: number of processors (not used)*ILAENV = 1RETURN*800 CONTINUE** ISPEC = 8: crossover point for multishift (used by xHSEQR)*ILAENV = 50RETURN*900 CONTINUE** ISPEC = 9: maximum size of the subproblems at the bottom of the* computation tree in the divide-and-conquer algorithm* (used by xGELSD and xGESDD)*ILAENV = 25RETURN*1000 CONTINUE** ISPEC = 10: ieee NaN arithmetic can be trusted not to trap*C ILAENV = 0ILAENV = 1IF( ILAENV.EQ.1 ) THENILAENV = IEEECK( 0, 0.0, 1.0 )END IFRETURN*1100 CONTINUE** ISPEC = 11: infinity arithmetic can be trusted not to trap*C ILAENV = 0ILAENV = 1IF( ILAENV.EQ.1 ) THENILAENV = IEEECK( 1, 0.0, 1.0 )END IFRETURN** End of ILAENV*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 DBDSDC( UPLO, COMPQ, N, D, E, U, LDU, VT, LDVT, Q, IQ,$ WORK, IWORK, INFO )** -- LAPACK routine (version 3.0) --* Univ. of Tennessee, Univ. of California Berkeley, NAG Ltd.,* Courant Institute, Argonne National Lab, and Rice University* December 1, 1999** .. Scalar Arguments ..CHARACTER COMPQ, UPLOINTEGER INFO, LDU, LDVT, N* ..* .. Array Arguments ..INTEGER IQ( * ), IWORK( * )DOUBLE PRECISION D( * ), E( * ), Q( * ), U( LDU, * ),$ VT( LDVT, * ), WORK( * )* ..** Purpose* =======** DBDSDC computes the singular value decomposition (SVD) of a real* N-by-N (upper or lower) bidiagonal matrix B: B = U * S * VT,* using a divide and conquer method, where S is a diagonal matrix* with non-negative diagonal elements (the singular values of B), and* U and VT are orthogonal matrices of left and right singular vectors,* respectively. DBDSDC can be used to compute all singular values,* and optionally, singular vectors or singular vectors in compact 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 DLASD3 for details.** The code currently call DLASDQ if singular values only are desired.* However, it can be slightly modified to compute singular values* using the divide and conquer method.** Arguments* =========** UPLO (input) CHARACTER*1* = 'U': B is upper bidiagonal.* = 'L': B is lower bidiagonal.** COMPQ (input) CHARACTER*1* Specifies whether singular vectors are to be computed* as follows:* = 'N': Compute singular values only;* = 'P': Compute singular values and compute singular* vectors in compact form;* = 'I': Compute singular values and singular vectors.** N (input) INTEGER* The order of the matrix B. N >= 0.** D (input/output) DOUBLE PRECISION array, dimension (N)* On entry, the n diagonal elements of the bidiagonal matrix B.* On exit, if INFO=0, the singular values of B.** E (input/output) DOUBLE PRECISION array, dimension (N)* On entry, the elements of E contain the offdiagonal* elements of the bidiagonal matrix whose SVD is desired.* On exit, E has been destroyed.** U (output) DOUBLE PRECISION array, dimension (LDU,N)* If COMPQ = 'I', then:* On exit, if INFO = 0, U contains the left singular vectors* of the bidiagonal matrix.* For other values of COMPQ, U is not referenced.** LDU (input) INTEGER* The leading dimension of the array U. LDU >= 1.* If singular vectors are desired, then LDU >= max( 1, N ).** VT (output) DOUBLE PRECISION array, dimension (LDVT,N)* If COMPQ = 'I', then:* On exit, if INFO = 0, VT' contains the right singular* vectors of the bidiagonal matrix.* For other values of COMPQ, VT is not referenced.** LDVT (input) INTEGER* The leading dimension of the array VT. LDVT >= 1.* If singular vectors are desired, then LDVT >= max( 1, N ).** Q (output) DOUBLE PRECISION array, dimension (LDQ)* If COMPQ = 'P', then:* On exit, if INFO = 0, Q and IQ contain the left* and right singular vectors in a compact form,* requiring O(N log N) space instead of 2*N**2.* In particular, Q contains all the DOUBLE PRECISION data in* LDQ >= N*(11 + 2*SMLSIZ + 8*INT(LOG_2(N/(SMLSIZ+1))))* words of memory, where 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).* For other values of COMPQ, Q is not referenced.** IQ (output) INTEGER array, dimension (LDIQ)* If COMPQ = 'P', then:* On exit, if INFO = 0, Q and IQ contain the left* and right singular vectors in a compact form,* requiring O(N log N) space instead of 2*N**2.* In particular, IQ contains all INTEGER data in* LDIQ >= N*(3 + 3*INT(LOG_2(N/(SMLSIZ+1))))* words of memory, where 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).* For other values of COMPQ, IQ is not referenced.** WORK (workspace) DOUBLE PRECISION array, dimension (LWORK)* If COMPQ = 'N' then LWORK >= (4 * N).* If COMPQ = 'P' then LWORK >= (6 * N).* If COMPQ = 'I' then LWORK >= (3 * N**2 + 4 * N).** IWORK (workspace) INTEGER array, dimension (8*N)** 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 singular value.* The update process of divide and conquer 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, ONE, TWOPARAMETER ( ZERO = 0.0D+0, ONE = 1.0D+0, TWO = 2.0D+0 )* ..* .. Local Scalars ..INTEGER DIFL, DIFR, GIVCOL, GIVNUM, GIVPTR, I, IC,$ ICOMPQ, IERR, II, IS, IU, IUPLO, IVT, J, K, KK,$ MLVL, NM1, NSIZE, PERM, POLES, QSTART, SMLSIZ,$ SMLSZP, SQRE, START, WSTART, ZDOUBLE PRECISION CS, EPS, ORGNRM, P, R, SN* ..* .. External Functions ..LOGICAL LSAMEINTEGER ILAENVDOUBLE PRECISION DLAMCH, DLANSTEXTERNAL LSAME, ILAENV, DLAMCH, DLANST* ..* .. External Subroutines ..EXTERNAL DCOPY, DLARTG, DLASCL, DLASD0, DLASDA, DLASDQ,$ DLASET, DLASR, DSWAP, XERBLA* ..* .. Intrinsic Functions ..INTRINSIC ABS, DBLE, INT, LOG, SIGN* ..* .. Executable Statements ..** Test the input parameters.*INFO = 0*IUPLO = 0IF( LSAME( UPLO, 'U' ) )$ IUPLO = 1IF( LSAME( UPLO, 'L' ) )$ IUPLO = 2IF( LSAME( COMPQ, 'N' ) ) THENICOMPQ = 0ELSE IF( LSAME( COMPQ, 'P' ) ) THENICOMPQ = 1ELSE IF( LSAME( COMPQ, 'I' ) ) THENICOMPQ = 2ELSEICOMPQ = -1END IFIF( IUPLO.EQ.0 ) THENINFO = -1ELSE IF( ICOMPQ.LT.0 ) THENINFO = -2ELSE IF( N.LT.0 ) THENINFO = -3ELSE IF( ( LDU.LT.1 ) .OR. ( ( ICOMPQ.EQ.2 ) .AND. ( LDU.LT.$ N ) ) ) THENINFO = -7ELSE IF( ( LDVT.LT.1 ) .OR. ( ( ICOMPQ.EQ.2 ) .AND. ( LDVT.LT.$ N ) ) ) THENINFO = -9END IFIF( INFO.NE.0 ) THENCALL XERBLA( 'DBDSDC', -INFO )RETURNEND IF** Quick return if possible*IF( N.EQ.0 )$ RETURNSMLSIZ = ILAENV( 9, 'DBDSDC', ' ', 0, 0, 0, 0 )IF( N.EQ.1 ) THENIF( ICOMPQ.EQ.1 ) THENQ( 1 ) = SIGN( ONE, D( 1 ) )Q( 1+SMLSIZ*N ) = ONEELSE IF( ICOMPQ.EQ.2 ) THENU( 1, 1 ) = SIGN( ONE, D( 1 ) )VT( 1, 1 ) = ONEEND IFD( 1 ) = ABS( D( 1 ) )RETURNEND IFNM1 = N - 1** If matrix lower bidiagonal, rotate to be upper bidiagonal* by applying Givens rotations on the left*WSTART = 1QSTART = 3IF( ICOMPQ.EQ.1 ) THENCALL DCOPY( N, D, 1, Q( 1 ), 1 )CALL DCOPY( N-1, E, 1, Q( N+1 ), 1 )END IFIF( IUPLO.EQ.2 ) THENQSTART = 5WSTART = 2*N - 1DO 10 I = 1, N - 1CALL DLARTG( D( I ), E( I ), CS, SN, R )D( I ) = RE( I ) = SN*D( I+1 )D( I+1 ) = CS*D( I+1 )IF( ICOMPQ.EQ.1 ) THENQ( I+2*N ) = CSQ( I+3*N ) = SNELSE IF( ICOMPQ.EQ.2 ) THENWORK( I ) = CSWORK( NM1+I ) = -SNEND IF10 CONTINUEEND IF** If ICOMPQ = 0, use DLASDQ to compute the singular values.*IF( ICOMPQ.EQ.0 ) THENCALL DLASDQ( 'U', 0, N, 0, 0, 0, D, E, VT, LDVT, U, LDU, U,$ LDU, WORK( WSTART ), INFO )GO TO 40END IF** If N is smaller than the minimum divide size SMLSIZ, then solve* the problem with another solver.*IF( N.LE.SMLSIZ ) THENIF( ICOMPQ.EQ.2 ) THENCALL DLASET( 'A', N, N, ZERO, ONE, U, LDU )CALL DLASET( 'A', N, N, ZERO, ONE, VT, LDVT )CALL DLASDQ( 'U', 0, N, N, N, 0, D, E, VT, LDVT, U, LDU, U,$ LDU, WORK( WSTART ), INFO )ELSE IF( ICOMPQ.EQ.1 ) THENIU = 1IVT = IU + NCALL DLASET( 'A', N, N, ZERO, ONE, Q( IU+( QSTART-1 )*N ),$ N )CALL DLASET( 'A', N, N, ZERO, ONE, Q( IVT+( QSTART-1 )*N ),$ N )CALL DLASDQ( 'U', 0, N, N, N, 0, D, E,$ Q( IVT+( QSTART-1 )*N ), N,$ Q( IU+( QSTART-1 )*N ), N,$ Q( IU+( QSTART-1 )*N ), N, WORK( WSTART ),$ INFO )END IFGO TO 40END IF*IF( ICOMPQ.EQ.2 ) THENCALL DLASET( 'A', N, N, ZERO, ONE, U, LDU )CALL DLASET( 'A', N, N, ZERO, ONE, VT, LDVT )END IF** Scale.*ORGNRM = DLANST( 'M', N, D, E )IF( ORGNRM.EQ.ZERO )$ RETURNCALL DLASCL( 'G', 0, 0, ORGNRM, ONE, N, 1, D, N, IERR )CALL DLASCL( 'G', 0, 0, ORGNRM, ONE, NM1, 1, E, NM1, IERR )*EPS = DLAMCH( 'Epsilon' )*MLVL = INT( LOG( DBLE( N ) / DBLE( SMLSIZ+1 ) ) / LOG( TWO ) ) + 1SMLSZP = SMLSIZ + 1*IF( ICOMPQ.EQ.1 ) THENIU = 1IVT = 1 + SMLSIZDIFL = IVT + SMLSZPDIFR = DIFL + MLVLZ = DIFR + MLVL*2IC = Z + MLVLIS = IC + 1POLES = IS + 1GIVNUM = POLES + 2*MLVL*K = 1GIVPTR = 2PERM = 3GIVCOL = PERM + MLVLEND IF*DO 20 I = 1, NIF( ABS( D( I ) ).LT.EPS ) THEND( I ) = SIGN( EPS, D( I ) )END IF20 CONTINUE*START = 1SQRE = 0*DO 30 I = 1, NM1IF( ( ABS( E( I ) ).LT.EPS ) .OR. ( I.EQ.NM1 ) ) THEN** Subproblem found. First determine its size and then* apply divide and conquer on it.*IF( I.LT.NM1 ) THEN** A subproblem with E(I) small for I < NM1.*NSIZE = I - START + 1ELSE IF( ABS( E( I ) ).GE.EPS ) THEN** A subproblem with E(NM1) not too small but I = NM1.*NSIZE = N - START + 1ELSE** A subproblem with E(NM1) small. This implies an* 1-by-1 subproblem at D(N). Solve this 1-by-1 problem* first.*NSIZE = I - START + 1IF( ICOMPQ.EQ.2 ) THENU( N, N ) = SIGN( ONE, D( N ) )VT( N, N ) = ONEELSE IF( ICOMPQ.EQ.1 ) THENQ( N+( QSTART-1 )*N ) = SIGN( ONE, D( N ) )Q( N+( SMLSIZ+QSTART-1 )*N ) = ONEEND IFD( N ) = ABS( D( N ) )END IFIF( ICOMPQ.EQ.2 ) THENCALL DLASD0( NSIZE, SQRE, D( START ), E( START ),$ U( START, START ), LDU, VT( START, START ),$ LDVT, SMLSIZ, IWORK, WORK( WSTART ), INFO )ELSECALL DLASDA( ICOMPQ, SMLSIZ, NSIZE, SQRE, D( START ),$ E( START ), Q( START+( IU+QSTART-2 )*N ), N,$ Q( START+( IVT+QSTART-2 )*N ),$ IQ( START+K*N ), Q( START+( DIFL+QSTART-2 )*$ N ), Q( START+( DIFR+QSTART-2 )*N ),$ Q( START+( Z+QSTART-2 )*N ),$ Q( START+( POLES+QSTART-2 )*N ),$ IQ( START+GIVPTR*N ), IQ( START+GIVCOL*N ),$ N, IQ( START+PERM*N ),$ Q( START+( GIVNUM+QSTART-2 )*N ),$ Q( START+( IC+QSTART-2 )*N ),$ Q( START+( IS+QSTART-2 )*N ),$ WORK( WSTART ), IWORK, INFO )IF( INFO.NE.0 ) THENRETURNEND IFEND IFSTART = I + 1END IF30 CONTINUE** Unscale*CALL DLASCL( 'G', 0, 0, ONE, ORGNRM, N, 1, D, N, IERR )40 CONTINUE** Use Selection Sort to minimize swaps of singular vectors*DO 60 II = 2, NI = II - 1KK = IP = D( I )DO 50 J = II, NIF( D( J ).GT.P ) THENKK = JP = D( J )END IF50 CONTINUEIF( KK.NE.I ) THEND( KK ) = D( I )D( I ) = PIF( ICOMPQ.EQ.1 ) THENIQ( I ) = KKELSE IF( ICOMPQ.EQ.2 ) THENCALL DSWAP( N, U( 1, I ), 1, U( 1, KK ), 1 )CALL DSWAP( N, VT( I, 1 ), LDVT, VT( KK, 1 ), LDVT )END IFELSE IF( ICOMPQ.EQ.1 ) THENIQ( I ) = IEND IF60 CONTINUE** If ICOMPQ = 1, use IQ(N,1) as the indicator for UPLO*IF( ICOMPQ.EQ.1 ) THENIF( IUPLO.EQ.1 ) THENIQ( N ) = 1ELSEIQ( N ) = 0END IFEND IF** If B is lower bidiagonal, update U by those Givens rotations* which rotated B to be upper bidiagonal*IF( ( IUPLO.EQ.2 ) .AND. ( ICOMPQ.EQ.2 ) )$ CALL DLASR( 'L', 'V', 'B', N, N, WORK( 1 ), WORK( N ), U, LDU )*RETURN** End of DBDSDC*ENDSUBROUTINE DLASDQ( UPLO, SQRE, N, NCVT, NRU, NCC, D, E, VT, LDVT,$ U, LDU, C, LDC, WORK, INFO )** -- LAPACK auxiliary 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 UPLOINTEGER INFO, LDC, LDU, LDVT, N, NCC, NCVT, NRU, SQRE* ..* .. Array Arguments ..DOUBLE PRECISION C( LDC, * ), D( * ), E( * ), U( LDU, * ),$ VT( LDVT, * ), WORK( * )* ..** Purpose* =======** DLASDQ computes the singular value decomposition (SVD) of a real* (upper or lower) bidiagonal matrix with diagonal D and offdiagonal* E, accumulating the transformations if desired. Letting B denote* the input bidiagonal matrix, the algorithm computes orthogonal* matrices Q and P such that B = Q * S * P' (P' denotes the transpose* of P). The singular values S are overwritten on D.** The input matrix U is changed to U * Q if desired.* The input matrix VT is changed to P' * VT if desired.* The input matrix C is changed to Q' * C if desired.** See "Computing Small Singular Values of Bidiagonal Matrices With* Guaranteed High Relative Accuracy," by J. Demmel and W. Kahan,* LAPACK Working Note #3, for a detailed description of the algorithm.** Arguments* =========** UPLO (input) CHARACTER*1* On entry, UPLO specifies whether the input bidiagonal matrix* is upper or lower bidiagonal, and wether it is square are* not.* UPLO = 'U' or 'u' B is upper bidiagonal.* UPLO = 'L' or 'l' B is lower bidiagonal.** SQRE (input) INTEGER* = 0: then the input matrix is N-by-N.* = 1: then the input matrix is N-by-(N+1) if UPLU = 'U' and* (N+1)-by-N if UPLU = 'L'.** The bidiagonal matrix has* N = NL + NR + 1 rows and* M = N + SQRE >= N columns.** N (input) INTEGER* On entry, N specifies the number of rows and columns* in the matrix. N must be at least 0.** NCVT (input) INTEGER* On entry, NCVT specifies the number of columns of* the matrix VT. NCVT must be at least 0.** NRU (input) INTEGER* On entry, NRU specifies the number of rows of* the matrix U. NRU must be at least 0.** NCC (input) INTEGER* On entry, NCC specifies the number of columns of* the matrix C. NCC must be at least 0.** D (input/output) DOUBLE PRECISION array, dimension (N)* On entry, D contains the diagonal entries of the* bidiagonal matrix whose SVD is desired. On normal exit,* D contains the singular values in ascending order.** E (input/output) DOUBLE PRECISION array.* dimension is (N-1) if SQRE = 0 and N if SQRE = 1.* On entry, the entries of E contain the offdiagonal entries* of the bidiagonal matrix whose SVD is desired. On normal* exit, E will contain 0. If the algorithm does not converge,* D and E will contain the diagonal and superdiagonal entries* of a bidiagonal matrix orthogonally equivalent to the one* given as input.** VT (input/output) DOUBLE PRECISION array, dimension (LDVT, NCVT)* On entry, contains a matrix which on exit has been* premultiplied by P', dimension N-by-NCVT if SQRE = 0* and (N+1)-by-NCVT if SQRE = 1 (not referenced if NCVT=0).** LDVT (input) INTEGER* On entry, LDVT specifies the leading dimension of VT as* declared in the calling (sub) program. LDVT must be at* least 1. If NCVT is nonzero LDVT must also be at least N.** U (input/output) DOUBLE PRECISION array, dimension (LDU, N)* On entry, contains a matrix which on exit has been* postmultiplied by Q, dimension NRU-by-N if SQRE = 0* and NRU-by-(N+1) if SQRE = 1 (not referenced if NRU=0).** LDU (input) INTEGER* On entry, LDU specifies the leading dimension of U as* declared in the calling (sub) program. LDU must be at* least max( 1, NRU ) .** C (input/output) DOUBLE PRECISION array, dimension (LDC, NCC)* On entry, contains an N-by-NCC matrix which on exit* has been premultiplied by Q' dimension N-by-NCC if SQRE = 0* and (N+1)-by-NCC if SQRE = 1 (not referenced if NCC=0).** LDC (input) INTEGER* On entry, LDC specifies the leading dimension of C as* declared in the calling (sub) program. LDC must be at* least 1. If NCC is nonzero, LDC must also be at least N.** WORK (workspace) DOUBLE PRECISION array, dimension (4*N)* Workspace. Only referenced if one of NCVT, NRU, or NCC is* nonzero, and if N is at least 2.** INFO (output) INTEGER* On exit, a value of 0 indicates a successful exit.* If INFO < 0, argument number -INFO is illegal.* If INFO > 0, the algorithm did not converge, and INFO* specifies how many superdiagonals did not converge.** Further Details* ===============** Based on contributions by* Ming Gu and Huan Ren, Computer Science Division, University of* California at Berkeley, USA** =====================================================================** .. Parameters ..DOUBLE PRECISION ZEROPARAMETER ( ZERO = 0.0D+0 )* ..* .. Local Scalars ..LOGICAL ROTATEINTEGER I, ISUB, IUPLO, J, NP1, SQRE1DOUBLE PRECISION CS, R, SMIN, SN* ..* .. External Subroutines ..EXTERNAL DBDSQR, DLARTG, DLASR, DSWAP, XERBLA* ..* .. External Functions ..LOGICAL LSAMEEXTERNAL LSAME* ..* .. Intrinsic Functions ..INTRINSIC MAX* ..* .. Executable Statements ..** Test the input parameters.*INFO = 0IUPLO = 0IF( LSAME( UPLO, 'U' ) )$ IUPLO = 1IF( LSAME( UPLO, 'L' ) )$ IUPLO = 2IF( IUPLO.EQ.0 ) THENINFO = -1ELSE IF( ( SQRE.LT.0 ) .OR. ( SQRE.GT.1 ) ) THENINFO = -2ELSE IF( N.LT.0 ) THENINFO = -3ELSE IF( NCVT.LT.0 ) THENINFO = -4ELSE IF( NRU.LT.0 ) THENINFO = -5ELSE IF( NCC.LT.0 ) THENINFO = -6ELSE IF( ( NCVT.EQ.0 .AND. LDVT.LT.1 ) .OR.$ ( NCVT.GT.0 .AND. LDVT.LT.MAX( 1, N ) ) ) THENINFO = -10ELSE IF( LDU.LT.MAX( 1, NRU ) ) THENINFO = -12ELSE IF( ( NCC.EQ.0 .AND. LDC.LT.1 ) .OR.$ ( NCC.GT.0 .AND. LDC.LT.MAX( 1, N ) ) ) THENINFO = -14END IFIF( INFO.NE.0 ) THENCALL XERBLA( 'DLASDQ', -INFO )RETURNEND IFIF( N.EQ.0 )$ RETURN** ROTATE is true if any singular vectors desired, false otherwise*ROTATE = ( NCVT.GT.0 ) .OR. ( NRU.GT.0 ) .OR. ( NCC.GT.0 )NP1 = N + 1SQRE1 = SQRE** If matrix non-square upper bidiagonal, rotate to be lower* bidiagonal. The rotations are on the right.*IF( ( IUPLO.EQ.1 ) .AND. ( SQRE1.EQ.1 ) ) THENDO 10 I = 1, N - 1CALL DLARTG( D( I ), E( I ), CS, SN, R )D( I ) = RE( I ) = SN*D( I+1 )D( I+1 ) = CS*D( I+1 )IF( ROTATE ) THENWORK( I ) = CSWORK( N+I ) = SNEND IF10 CONTINUECALL DLARTG( D( N ), E( N ), CS, SN, R )D( N ) = RE( N ) = ZEROIF( ROTATE ) THENWORK( N ) = CSWORK( N+N ) = SNEND IFIUPLO = 2SQRE1 = 0** Update singular vectors if desired.*IF( NCVT.GT.0 )$ CALL DLASR( 'L', 'V', 'F', NP1, NCVT, WORK( 1 ),$ WORK( NP1 ), VT, LDVT )END IF** If matrix lower bidiagonal, rotate to be upper bidiagonal* by applying Givens rotations on the left.*IF( IUPLO.EQ.2 ) THENDO 20 I = 1, N - 1CALL DLARTG( D( I ), E( I ), CS, SN, R )D( I ) = RE( I ) = SN*D( I+1 )D( I+1 ) = CS*D( I+1 )IF( ROTATE ) THENWORK( I ) = CSWORK( N+I ) = SNEND IF20 CONTINUE** If matrix (N+1)-by-N lower bidiagonal, one additional* rotation is needed.*IF( SQRE1.EQ.1 ) THENCALL DLARTG( D( N ), E( N ), CS, SN, R )D( N ) = RIF( ROTATE ) THENWORK( N ) = CSWORK( N+N ) = SNEND IFEND IF** Update singular vectors if desired.*IF( NRU.GT.0 ) THENIF( SQRE1.EQ.0 ) THENCALL DLASR( 'R', 'V', 'F', NRU, N, WORK( 1 ),$ WORK( NP1 ), U, LDU )ELSECALL DLASR( 'R', 'V', 'F', NRU, NP1, WORK( 1 ),$ WORK( NP1 ), U, LDU )END IFEND IFIF( NCC.GT.0 ) THENIF( SQRE1.EQ.0 ) THENCALL DLASR( 'L', 'V', 'F', N, NCC, WORK( 1 ),$ WORK( NP1 ), C, LDC )ELSECALL DLASR( 'L', 'V', 'F', NP1, NCC, WORK( 1 ),$ WORK( NP1 ), C, LDC )END IFEND IFEND IF** Call DBDSQR to compute the SVD of the reduced real* N-by-N upper bidiagonal matrix.*CALL DBDSQR( 'U', N, NCVT, NRU, NCC, D, E, VT, LDVT, U, LDU, C,$ LDC, WORK, INFO )** Sort the singular values into ascending order (insertion sort on* singular values, but only one transposition per singular vector)*DO 40 I = 1, N** Scan for smallest D(I).*ISUB = ISMIN = D( I )DO 30 J = I + 1, NIF( D( J ).LT.SMIN ) THENISUB = JSMIN = D( J )END IF30 CONTINUEIF( ISUB.NE.I ) THEN** Swap singular values and vectors.*D( ISUB ) = D( I )D( I ) = SMINIF( NCVT.GT.0 )$ CALL DSWAP( NCVT, VT( ISUB, 1 ), LDVT, VT( I, 1 ), LDVT )IF( NRU.GT.0 )$ CALL DSWAP( NRU, U( 1, ISUB ), 1, U( 1, I ), 1 )IF( NCC.GT.0 )$ CALL DSWAP( NCC, C( ISUB, 1 ), LDC, C( I, 1 ), LDC )END IF40 CONTINUE*RETURN** End of DLASDQ*ENDSUBROUTINE DLASD0( N, SQRE, D, E, U, LDU, VT, LDVT, SMLSIZ, IWORK,$ WORK, INFO )** -- LAPACK auxiliary 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, LDU, LDVT, N, SMLSIZ, SQRE* ..* .. Array Arguments ..INTEGER IWORK( * )DOUBLE PRECISION D( * ), E( * ), U( LDU, * ), VT( LDVT, * ),$ WORK( * )* ..** Purpose* =======** Using a divide and conquer approach, DLASD0 computes the singular* value decomposition (SVD) of a real upper bidiagonal N-by-M* matrix B with diagonal D and offdiagonal E, where M = N + SQRE.* The algorithm computes orthogonal matrices U and VT such that* B = U * S * VT. The singular values S are overwritten on D.** A related subroutine, DLASDA, computes only the singular values,* and optionally, the singular vectors in compact form.** Arguments* =========** N (input) INTEGER* On entry, the row dimension of the upper bidiagonal matrix.* This is also the dimension of the main diagonal array D.** SQRE (input) INTEGER* Specifies the column dimension of the bidiagonal matrix.* = 0: The bidiagonal matrix has column dimension M = N;* = 1: The bidiagonal matrix has column dimension M = N+1;** D (input/output) DOUBLE PRECISION array, dimension (N)* On entry D contains the main diagonal of the bidiagonal* matrix.* On exit D, if INFO = 0, contains its singular values.** E (input) DOUBLE PRECISION array, dimension (M-1)* Contains the subdiagonal entries of the bidiagonal matrix.* On exit, E has been destroyed.** U (output) DOUBLE PRECISION array, dimension at least (LDQ, N)* On exit, U contains the left singular vectors.** LDU (input) INTEGER* On entry, leading dimension of U.** VT (output) DOUBLE PRECISION array, dimension at least (LDVT, M)* On exit, VT' contains the right singular vectors.** LDVT (input) INTEGER* On entry, leading dimension of VT.** SMLSIZ (input) INTEGER* On entry, maximum size of the subproblems at the* bottom of the computation tree.** IWORK INTEGER work array.* Dimension must be at least (8 * N)** WORK DOUBLE PRECISION work array.* Dimension must be at least (3 * M**2 + 2 * M)** INFO (output) INTEGER* = 0: successful exit.* < 0: if INFO = -i, the i-th argument had an illegal value.* > 0: if INFO = 1, an singular value did not converge** Further Details* ===============** Based on contributions by* Ming Gu and Huan Ren, Computer Science Division, University of* California at Berkeley, USA** =====================================================================** .. Local Scalars ..INTEGER I, I1, IC, IDXQ, IDXQC, IM1, INODE, ITEMP, IWK,$ J, LF, LL, LVL, M, NCC, ND, NDB1, NDIML, NDIMR,$ NL, NLF, NLP1, NLVL, NR, NRF, NRP1, SQREIDOUBLE PRECISION ALPHA, BETA* ..* .. External Subroutines ..EXTERNAL DLASD1, DLASDQ, DLASDT, XERBLA* ..* .. Executable Statements ..** Test the input parameters.*INFO = 0*IF( N.LT.0 ) THENINFO = -1ELSE IF( ( SQRE.LT.0 ) .OR. ( SQRE.GT.1 ) ) THENINFO = -2END IF*M = N + SQRE*IF( LDU.LT.N ) THENINFO = -6ELSE IF( LDVT.LT.M ) THENINFO = -8ELSE IF( SMLSIZ.LT.3 ) THENINFO = -9END IFIF( INFO.NE.0 ) THENCALL XERBLA( 'DLASD0', -INFO )RETURNEND IF** If the input matrix is too small, call DLASDQ to find the SVD.*IF( N.LE.SMLSIZ ) THENCALL DLASDQ( 'U', SQRE, N, M, N, 0, D, E, VT, LDVT, U, LDU, U,$ LDU, WORK, INFO )RETURNEND IF** Set up the computation tree.*INODE = 1NDIML = INODE + NNDIMR = NDIML + NIDXQ = NDIMR + NIWK = IDXQ + NCALL DLASDT( N, NLVL, ND, IWORK( INODE ), IWORK( NDIML ),$ IWORK( NDIMR ), SMLSIZ )** For the nodes on bottom level of the tree, solve* their subproblems by DLASDQ.*NDB1 = ( ND+1 ) / 2NCC = 0DO 30 I = NDB1, ND** IC : center row of each node* NL : number of rows of left subproblem* NR : number of rows of right subproblem* NLF: starting row of the left subproblem* NRF: starting row of the right subproblem*I1 = I - 1IC = IWORK( INODE+I1 )NL = IWORK( NDIML+I1 )NLP1 = NL + 1NR = IWORK( NDIMR+I1 )NRP1 = NR + 1NLF = IC - NLNRF = IC + 1SQREI = 1CALL DLASDQ( 'U', SQREI, NL, NLP1, NL, NCC, D( NLF ), E( NLF ),$ VT( NLF, NLF ), LDVT, U( NLF, NLF ), LDU,$ U( NLF, NLF ), LDU, WORK, INFO )IF( INFO.NE.0 ) THENRETURNEND IFITEMP = IDXQ + NLF - 2DO 10 J = 1, NLIWORK( ITEMP+J ) = J10 CONTINUEIF( I.EQ.ND ) THENSQREI = SQREELSESQREI = 1END IFNRP1 = NR + SQREICALL DLASDQ( 'U', SQREI, NR, NRP1, NR, NCC, D( NRF ), E( NRF ),$ VT( NRF, NRF ), LDVT, U( NRF, NRF ), LDU,$ U( NRF, NRF ), LDU, WORK, INFO )IF( INFO.NE.0 ) THENRETURNEND IFITEMP = IDXQ + ICDO 20 J = 1, NRIWORK( ITEMP+J-1 ) = J20 CONTINUE30 CONTINUE** Now conquer each subproblem bottom-up.*DO 50 LVL = NLVL, 1, -1** Find the first node LF and last node LL on the* current level LVL.*IF( LVL.EQ.1 ) THENLF = 1LL = 1ELSELF = 2**( LVL-1 )LL = 2*LF - 1END IFDO 40 I = LF, LLIM1 = I - 1IC = IWORK( INODE+IM1 )NL = IWORK( NDIML+IM1 )NR = IWORK( NDIMR+IM1 )NLF = IC - NLIF( ( SQRE.EQ.0 ) .AND. ( I.EQ.LL ) ) THENSQREI = SQREELSESQREI = 1END IFIDXQC = IDXQ + NLF - 1ALPHA = D( IC )BETA = E( IC )CALL DLASD1( NL, NR, SQREI, D( NLF ), ALPHA, BETA,$ U( NLF, NLF ), LDU, VT( NLF, NLF ), LDVT,$ IWORK( IDXQC ), IWORK( IWK ), WORK, INFO )IF( INFO.NE.0 ) THENRETURNEND IF40 CONTINUE50 CONTINUE*RETURN** End of DLASD0*ENDSUBROUTINE DLASDA( ICOMPQ, SMLSIZ, N, SQRE, D, E, U, LDU, VT, K,$ DIFL, DIFR, Z, POLES, GIVPTR, GIVCOL, LDGCOL,$ PERM, GIVNUM, C, S, WORK, IWORK, INFO )** -- LAPACK auxiliary 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 ICOMPQ, INFO, LDGCOL, LDU, N, SMLSIZ, SQRE* ..* .. Array Arguments ..INTEGER GIVCOL( LDGCOL, * ), GIVPTR( * ), IWORK( * ),$ K( * ), PERM( LDGCOL, * )DOUBLE PRECISION C( * ), D( * ), DIFL( LDU, * ), DIFR( LDU, * ),$ E( * ), GIVNUM( LDU, * ), POLES( LDU, * ),$ S( * ), U( LDU, * ), VT( LDU, * ), WORK( * ),$ Z( LDU, * )* ..** Purpose* =======** Using a divide and conquer approach, DLASDA computes the singular* value decomposition (SVD) of a real upper bidiagonal N-by-M matrix* B with diagonal D and offdiagonal E, where M = N + SQRE. The* algorithm computes the singular values in the SVD B = U * S * VT.* The orthogonal matrices U and VT are optionally computed in* compact form.** A related subroutine, DLASD0, computes the singular values and* the singular vectors in explicit form.** Arguments* =========** ICOMPQ (input) INTEGER* Specifies whether singular vectors are to be computed* in compact form, as follows* = 0: Compute singular values only.* = 1: Compute singular vectors of upper bidiagonal* matrix in compact form.** SMLSIZ (input) INTEGER* The maximum size of the subproblems at the bottom of the* computation tree.** N (input) INTEGER* The row dimension of the upper bidiagonal matrix. This is* also the dimension of the main diagonal array D.** SQRE (input) INTEGER* Specifies the column dimension of the bidiagonal matrix.* = 0: The bidiagonal matrix has column dimension M = N;* = 1: The bidiagonal matrix has column dimension M = N + 1.** D (input/output) DOUBLE PRECISION array, dimension ( N )* On entry D contains the main diagonal of the bidiagonal* matrix. On exit D, if INFO = 0, contains its singular values.** E (input) DOUBLE PRECISION array, dimension ( M-1 )* Contains the subdiagonal entries of the bidiagonal matrix.* On exit, E has been destroyed.** U (output) DOUBLE PRECISION array,* dimension ( LDU, SMLSIZ ) if ICOMPQ = 1, and not referenced* if ICOMPQ = 0. If ICOMPQ = 1, on exit, U contains the left* singular vector matrices of all subproblems at the bottom* level.** LDU (input) INTEGER, LDU = > N.* The leading dimension of arrays U, VT, DIFL, DIFR, POLES,* GIVNUM, and Z.** VT (output) DOUBLE PRECISION array,* dimension ( LDU, SMLSIZ+1 ) if ICOMPQ = 1, and not referenced* if ICOMPQ = 0. If ICOMPQ = 1, on exit, VT' contains the right* singular vector matrices of all subproblems at the bottom* level.** K (output) INTEGER array,* dimension ( N ) if ICOMPQ = 1 and dimension 1 if ICOMPQ = 0.* If ICOMPQ = 1, on exit, K(I) is the dimension of the I-th* secular equation on the computation tree.** DIFL (output) DOUBLE PRECISION array, dimension ( LDU, NLVL ),* where NLVL = floor(log_2 (N/SMLSIZ))).** DIFR (output) DOUBLE PRECISION array,* dimension ( LDU, 2 * NLVL ) if ICOMPQ = 1 and* dimension ( N ) if ICOMPQ = 0.* If ICOMPQ = 1, on exit, DIFL(1:N, I) and DIFR(1:N, 2 * I - 1)* record distances between singular values on the I-th* level and singular values on the (I -1)-th level, and* DIFR(1:N, 2 * I ) contains the normalizing factors for* the right singular vector matrix. See DLASD8 for details.** Z (output) DOUBLE PRECISION array,* dimension ( LDU, NLVL ) if ICOMPQ = 1 and* dimension ( N ) if ICOMPQ = 0.* The first K elements of Z(1, I) contain the components of* the deflation-adjusted updating row vector for subproblems* on the I-th level.** POLES (output) DOUBLE PRECISION array,* dimension ( LDU, 2 * NLVL ) if ICOMPQ = 1, and not referenced* if ICOMPQ = 0. If ICOMPQ = 1, on exit, POLES(1, 2*I - 1) and* POLES(1, 2*I) contain the new and old singular values* involved in the secular equations on the I-th level.** GIVPTR (output) INTEGER array,* dimension ( N ) if ICOMPQ = 1, and not referenced if* ICOMPQ = 0. If ICOMPQ = 1, on exit, GIVPTR( I ) records* the number of Givens rotations performed on the I-th* problem on the computation tree.** GIVCOL (output) INTEGER array,* dimension ( LDGCOL, 2 * NLVL ) if ICOMPQ = 1, and not* referenced if ICOMPQ = 0. If ICOMPQ = 1, on exit, for each I,* GIVCOL(1, 2 *I - 1) and GIVCOL(1, 2 *I) record the locations* of Givens rotations performed on the I-th level on the* computation tree.** LDGCOL (input) INTEGER, LDGCOL = > N.* The leading dimension of arrays GIVCOL and PERM.** PERM (output) INTEGER array,* dimension ( LDGCOL, NLVL ) if ICOMPQ = 1, and not referenced* if ICOMPQ = 0. If ICOMPQ = 1, on exit, PERM(1, I) records* permutations done on the I-th level of the computation tree.** GIVNUM (output) DOUBLE PRECISION array,* dimension ( LDU, 2 * NLVL ) if ICOMPQ = 1, and not* referenced if ICOMPQ = 0. If ICOMPQ = 1, on exit, for each I,* GIVNUM(1, 2 *I - 1) and GIVNUM(1, 2 *I) record the C- and S-* values of Givens rotations performed on the I-th level on* the computation tree.** C (output) DOUBLE PRECISION array,* dimension ( N ) if ICOMPQ = 1, and dimension 1 if ICOMPQ = 0.* If ICOMPQ = 1 and the I-th subproblem is not square, on exit,* C( I ) contains the C-value of a Givens rotation related to* the right null space of the I-th subproblem.** S (output) DOUBLE PRECISION array, dimension ( N ) if* ICOMPQ = 1, and dimension 1 if ICOMPQ = 0. If ICOMPQ = 1* and the I-th subproblem is not square, on exit, S( I )* contains the S-value of a Givens rotation related to* the right null space of the I-th subproblem.** WORK (workspace) DOUBLE PRECISION array, dimension* (6 * N + (SMLSIZ + 1)*(SMLSIZ + 1)).** IWORK (workspace) INTEGER array.* Dimension must be at least (7 * N).** INFO (output) INTEGER* = 0: successful exit.* < 0: if INFO = -i, the i-th argument had an illegal value.* > 0: if INFO = 1, an singular value did not converge** 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.0D+0, ONE = 1.0D+0 )* ..* .. Local Scalars ..INTEGER I, I1, IC, IDXQ, IDXQI, IM1, INODE, ITEMP, IWK,$ J, LF, LL, LVL, LVL2, M, NCC, ND, NDB1, NDIML,$ NDIMR, NL, NLF, NLP1, NLVL, NR, NRF, NRP1, NRU,$ NWORK1, NWORK2, SMLSZP, SQREI, VF, VFI, VL, VLIDOUBLE PRECISION ALPHA, BETA* ..* .. External Subroutines ..EXTERNAL DCOPY, DLASD6, DLASDQ, DLASDT, DLASET, XERBLA* ..* .. Executable Statements ..** Test the input parameters.*INFO = 0*IF( ( ICOMPQ.LT.0 ) .OR. ( ICOMPQ.GT.1 ) ) THENINFO = -1ELSE IF( SMLSIZ.LT.3 ) THENINFO = -2ELSE IF( N.LT.0 ) THENINFO = -3ELSE IF( ( SQRE.LT.0 ) .OR. ( SQRE.GT.1 ) ) THENINFO = -4ELSE IF( LDU.LT.( N+SQRE ) ) THENINFO = -8ELSE IF( LDGCOL.LT.N ) THENINFO = -17END IFIF( INFO.NE.0 ) THENCALL XERBLA( 'DLASDA', -INFO )RETURNEND IF*M = N + SQRE** If the input matrix is too small, call DLASDQ to find the SVD.*IF( N.LE.SMLSIZ ) THENIF( ICOMPQ.EQ.0 ) THENCALL DLASDQ( 'U', SQRE, N, 0, 0, 0, D, E, VT, LDU, U, LDU,$ U, LDU, WORK, INFO )ELSECALL DLASDQ( 'U', SQRE, N, M, N, 0, D, E, VT, LDU, U, LDU,$ U, LDU, WORK, INFO )END IFRETURNEND IF** Book-keeping and set up the computation tree.*INODE = 1NDIML = INODE + NNDIMR = NDIML + NIDXQ = NDIMR + NIWK = IDXQ + N*NCC = 0NRU = 0*SMLSZP = SMLSIZ + 1VF = 1VL = VF + MNWORK1 = VL + MNWORK2 = NWORK1 + SMLSZP*SMLSZP*CALL DLASDT( N, NLVL, ND, IWORK( INODE ), IWORK( NDIML ),$ IWORK( NDIMR ), SMLSIZ )** for the nodes on bottom level of the tree, solve* their subproblems by DLASDQ.*NDB1 = ( ND+1 ) / 2DO 30 I = NDB1, ND** IC : center row of each node* NL : number of rows of left subproblem* NR : number of rows of right subproblem* NLF: starting row of the left subproblem* NRF: starting row of the right subproblem*I1 = I - 1IC = IWORK( INODE+I1 )NL = IWORK( NDIML+I1 )NLP1 = NL + 1NR = IWORK( NDIMR+I1 )NLF = IC - NLNRF = IC + 1IDXQI = IDXQ + NLF - 2VFI = VF + NLF - 1VLI = VL + NLF - 1SQREI = 1IF( ICOMPQ.EQ.0 ) THENCALL DLASET( 'A', NLP1, NLP1, ZERO, ONE, WORK( NWORK1 ),$ SMLSZP )CALL DLASDQ( 'U', SQREI, NL, NLP1, NRU, NCC, D( NLF ),$ E( NLF ), WORK( NWORK1 ), SMLSZP,$ WORK( NWORK2 ), NL, WORK( NWORK2 ), NL,$ WORK( NWORK2 ), INFO )ITEMP = NWORK1 + NL*SMLSZPCALL DCOPY( NLP1, WORK( NWORK1 ), 1, WORK( VFI ), 1 )CALL DCOPY( NLP1, WORK( ITEMP ), 1, WORK( VLI ), 1 )ELSECALL DLASET( 'A', NL, NL, ZERO, ONE, U( NLF, 1 ), LDU )CALL DLASET( 'A', NLP1, NLP1, ZERO, ONE, VT( NLF, 1 ), LDU )CALL DLASDQ( 'U', SQREI, NL, NLP1, NL, NCC, D( NLF ),$ E( NLF ), VT( NLF, 1 ), LDU, U( NLF, 1 ), LDU,$ U( NLF, 1 ), LDU, WORK( NWORK1 ), INFO )CALL DCOPY( NLP1, VT( NLF, 1 ), 1, WORK( VFI ), 1 )CALL DCOPY( NLP1, VT( NLF, NLP1 ), 1, WORK( VLI ), 1 )END IFIF( INFO.NE.0 ) THENRETURNEND IFDO 10 J = 1, NLIWORK( IDXQI+J ) = J10 CONTINUEIF( ( I.EQ.ND ) .AND. ( SQRE.EQ.0 ) ) THENSQREI = 0ELSESQREI = 1END IFIDXQI = IDXQI + NLP1VFI = VFI + NLP1VLI = VLI + NLP1NRP1 = NR + SQREIIF( ICOMPQ.EQ.0 ) THENCALL DLASET( 'A', NRP1, NRP1, ZERO, ONE, WORK( NWORK1 ),$ SMLSZP )CALL DLASDQ( 'U', SQREI, NR, NRP1, NRU, NCC, D( NRF ),$ E( NRF ), WORK( NWORK1 ), SMLSZP,$ WORK( NWORK2 ), NR, WORK( NWORK2 ), NR,$ WORK( NWORK2 ), INFO )ITEMP = NWORK1 + ( NRP1-1 )*SMLSZPCALL DCOPY( NRP1, WORK( NWORK1 ), 1, WORK( VFI ), 1 )CALL DCOPY( NRP1, WORK( ITEMP ), 1, WORK( VLI ), 1 )ELSECALL DLASET( 'A', NR, NR, ZERO, ONE, U( NRF, 1 ), LDU )CALL DLASET( 'A', NRP1, NRP1, ZERO, ONE, VT( NRF, 1 ), LDU )CALL DLASDQ( 'U', SQREI, NR, NRP1, NR, NCC, D( NRF ),$ E( NRF ), VT( NRF, 1 ), LDU, U( NRF, 1 ), LDU,$ U( NRF, 1 ), LDU, WORK( NWORK1 ), INFO )CALL DCOPY( NRP1, VT( NRF, 1 ), 1, WORK( VFI ), 1 )CALL DCOPY( NRP1, VT( NRF, NRP1 ), 1, WORK( VLI ), 1 )END IFIF( INFO.NE.0 ) THENRETURNEND IFDO 20 J = 1, NRIWORK( IDXQI+J ) = J20 CONTINUE30 CONTINUE** Now conquer each subproblem bottom-up.*J = 2**NLVLDO 50 LVL = NLVL, 1, -1LVL2 = LVL*2 - 1** Find the first node LF and last node LL on* the current level LVL.*IF( LVL.EQ.1 ) THENLF = 1LL = 1ELSELF = 2**( LVL-1 )LL = 2*LF - 1END IFDO 40 I = LF, LLIM1 = I - 1IC = IWORK( INODE+IM1 )NL = IWORK( NDIML+IM1 )NR = IWORK( NDIMR+IM1 )NLF = IC - NLNRF = IC + 1IF( I.EQ.LL ) THENSQREI = SQREELSESQREI = 1END IFVFI = VF + NLF - 1VLI = VL + NLF - 1IDXQI = IDXQ + NLF - 1ALPHA = D( IC )BETA = E( IC )IF( ICOMPQ.EQ.0 ) THENCALL DLASD6( ICOMPQ, NL, NR, SQREI, D( NLF ),$ WORK( VFI ), WORK( VLI ), ALPHA, BETA,$ IWORK( IDXQI ), PERM, GIVPTR( 1 ), GIVCOL,$ LDGCOL, GIVNUM, LDU, POLES, DIFL, DIFR, Z,$ K( 1 ), C( 1 ), S( 1 ), WORK( NWORK1 ),$ IWORK( IWK ), INFO )ELSEJ = J - 1CALL DLASD6( ICOMPQ, NL, NR, SQREI, D( NLF ),$ WORK( VFI ), WORK( VLI ), ALPHA, BETA,$ IWORK( IDXQI ), PERM( NLF, LVL ),$ GIVPTR( J ), GIVCOL( NLF, LVL2 ), LDGCOL,$ GIVNUM( NLF, LVL2 ), LDU,$ POLES( NLF, LVL2 ), DIFL( NLF, LVL ),$ DIFR( NLF, LVL2 ), Z( NLF, LVL ), K( J ),$ C( J ), S( J ), WORK( NWORK1 ),$ IWORK( IWK ), INFO )END IFIF( INFO.NE.0 ) THENRETURNEND IF40 CONTINUE50 CONTINUE*RETURN** End of DLASDA*ENDSUBROUTINE DLASDT( N, LVL, ND, INODE, NDIML, NDIMR, MSUB )** -- LAPACK auxiliary 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 LVL, MSUB, N, ND* ..* .. Array Arguments ..INTEGER INODE( * ), NDIML( * ), NDIMR( * )* ..** Purpose* =======** DLASDT creates a tree of subproblems for bidiagonal divide and* conquer.** Arguments* =========** N (input) INTEGER* On entry, the number of diagonal elements of the* bidiagonal matrix.** LVL (output) INTEGER* On exit, the number of levels on the computation tree.** ND (output) INTEGER* On exit, the number of nodes on the tree.** INODE (output) INTEGER array, dimension ( N )* On exit, centers of subproblems.** NDIML (output) INTEGER array, dimension ( N )* On exit, row dimensions of left children.** NDIMR (output) INTEGER array, dimension ( N )* On exit, row dimensions of right children.** MSUB (input) INTEGER.* On entry, the maximum row dimension each subproblem at the* bottom of the tree can be of.** Further Details* ===============** Based on contributions by* Ming Gu and Huan Ren, Computer Science Division, University of* California at Berkeley, USA** =====================================================================** .. Parameters ..DOUBLE PRECISION TWOPARAMETER ( TWO = 2.0D+0 )* ..* .. Local Scalars ..INTEGER I, IL, IR, LLST, MAXN, NCRNT, NLVLDOUBLE PRECISION TEMP* ..* .. Intrinsic Functions ..INTRINSIC DBLE, INT, LOG, MAX* ..* .. Executable Statements ..** Find the number of levels on the tree.*MAXN = MAX( 1, N )TEMP = LOG( DBLE( MAXN ) / DBLE( MSUB+1 ) ) / LOG( TWO )LVL = INT( TEMP ) + 1*I = N / 2INODE( 1 ) = I + 1NDIML( 1 ) = INDIMR( 1 ) = N - I - 1IL = 0IR = 1LLST = 1DO 20 NLVL = 1, LVL - 1** Constructing the tree at (NLVL+1)-st level. The number of* nodes created on this level is LLST * 2.*DO 10 I = 0, LLST - 1IL = IL + 2IR = IR + 2NCRNT = LLST + INDIML( IL ) = NDIML( NCRNT ) / 2NDIMR( IL ) = NDIML( NCRNT ) - NDIML( IL ) - 1INODE( IL ) = INODE( NCRNT ) - NDIMR( IL ) - 1NDIML( IR ) = NDIMR( NCRNT ) / 2NDIMR( IR ) = NDIMR( NCRNT ) - NDIML( IR ) - 1INODE( IR ) = INODE( NCRNT ) + NDIML( IR ) + 110 CONTINUELLST = LLST*220 CONTINUEND = LLST*2 - 1*RETURN** End of DLASDT*ENDSUBROUTINE DLASD1( NL, NR, SQRE, D, ALPHA, BETA, U, LDU, VT, LDVT,$ IDXQ, IWORK, WORK, INFO )** -- LAPACK auxiliary 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, LDU, LDVT, NL, NR, SQREDOUBLE PRECISION ALPHA, BETA* ..* .. Array Arguments ..INTEGER IDXQ( * ), IWORK( * )DOUBLE PRECISION D( * ), U( LDU, * ), VT( LDVT, * ), WORK( * )* ..** Purpose* =======** DLASD1 computes the SVD of an upper bidiagonal N-by-M matrix B,* where N = NL + NR + 1 and M = N + SQRE. DLASD1 is called from DLASD0.** A related subroutine DLASD7 handles the case in which the singular* values (and the singular vectors in factored form) are desired.** DLASD1 computes the SVD as follows:** ( D1(in) 0 0 0 )* B = U(in) * ( Z1' a Z2' b ) * VT(in)* ( 0 0 D2(in) 0 )** = U(out) * ( D(out) 0) * VT(out)** where Z' = (Z1' a Z2' b) = u' VT', and u is a vector of dimension M* with ALPHA and BETA in the NL+1 and NL+2 th entries and zeros* elsewhere; and the entry b is empty if SQRE = 0.** The left singular vectors of the original matrix are stored in U, and* the transpose of the right singular vectors are stored in VT, and the* singular values are in D. The algorithm consists of three stages:** The first stage consists of deflating the size of the problem* when there are multiple singular values or when there are zeros in* the Z vector. For each such occurence the dimension of the* secular equation problem is reduced by one. This stage is* performed by the routine DLASD2.** The second stage consists of calculating the updated* singular values. This is done by finding the square roots of the* roots of the secular equation via the routine DLASD4 (as called* by DLASD3). This routine also calculates the singular vectors of* the current problem.** The final stage consists of computing the updated singular vectors* directly using the updated singular values. The singular vectors* for the current problem are multiplied with the singular vectors* from the overall problem.** Arguments* =========** NL (input) INTEGER* The row dimension of the upper block. NL >= 1.** NR (input) INTEGER* The row dimension of the lower block. NR >= 1.** SQRE (input) INTEGER* = 0: the lower block is an NR-by-NR square matrix.* = 1: the lower block is an NR-by-(NR+1) rectangular matrix.** The bidiagonal matrix has row dimension N = NL + NR + 1,* and column dimension M = N + SQRE.** D (input/output) DOUBLE PRECISION array,* dimension (N = NL+NR+1).* On entry D(1:NL,1:NL) contains the singular values of the* upper block; and D(NL+2:N) contains the singular values of* the lower block. On exit D(1:N) contains the singular values* of the modified matrix.** ALPHA (input) DOUBLE PRECISION* Contains the diagonal element associated with the added row.** BETA (input) DOUBLE PRECISION* Contains the off-diagonal element associated with the added* row.** U (input/output) DOUBLE PRECISION array, dimension(LDU,N)* On entry U(1:NL, 1:NL) contains the left singular vectors of* the upper block; U(NL+2:N, NL+2:N) contains the left singular* vectors of the lower block. On exit U contains the left* singular vectors of the bidiagonal matrix.** LDU (input) INTEGER* The leading dimension of the array U. LDU >= max( 1, N ).** VT (input/output) DOUBLE PRECISION array, dimension(LDVT,M)* where M = N + SQRE.* On entry VT(1:NL+1, 1:NL+1)' contains the right singular* vectors of the upper block; VT(NL+2:M, NL+2:M)' contains* the right singular vectors of the lower block. On exit* VT' contains the right singular vectors of the* bidiagonal matrix.** LDVT (input) INTEGER* The leading dimension of the array VT. LDVT >= max( 1, M ).** IDXQ (output) INTEGER array, dimension(N)* This contains the permutation which will reintegrate the* subproblem just solved back into sorted order, i.e.* D( IDXQ( I = 1, N ) ) will be in ascending order.** IWORK (workspace) INTEGER array, dimension( 4 * N )** WORK (workspace) DOUBLE PRECISION array, dimension( 3*M**2 + 2*M )** INFO (output) INTEGER* = 0: successful exit.* < 0: if INFO = -i, the i-th argument had an illegal value.* > 0: if INFO = 1, an singular value did not converge** Further Details* ===============** Based on contributions by* Ming Gu and Huan Ren, Computer Science Division, University of* California at Berkeley, USA** =====================================================================** .. Parameters ..*DOUBLE PRECISION ONE, ZEROPARAMETER ( ONE = 1.0D+0, ZERO = 0.0D+0 )* ..* .. Local Scalars ..INTEGER COLTYP, I, IDX, IDXC, IDXP, IQ, ISIGMA, IU2,$ IVT2, IZ, K, LDQ, LDU2, LDVT2, M, N, N1, N2DOUBLE PRECISION ORGNRM* ..* .. External Subroutines ..EXTERNAL DLAMRG, DLASCL, DLASD2, DLASD3, XERBLA* ..* .. Intrinsic Functions ..INTRINSIC ABS, MAX* ..* .. Executable Statements ..** Test the input parameters.*INFO = 0*IF( NL.LT.1 ) THENINFO = -1ELSE IF( NR.LT.1 ) THENINFO = -2ELSE IF( ( SQRE.LT.0 ) .OR. ( SQRE.GT.1 ) ) THENINFO = -3END IFIF( INFO.NE.0 ) THENCALL XERBLA( 'DLASD1', -INFO )RETURNEND IF*N = NL + NR + 1M = N + SQRE** The following values are for bookkeeping purposes only. They are* integer pointers which indicate the portion of the workspace* used by a particular array in DLASD2 and DLASD3.*LDU2 = NLDVT2 = M*IZ = 1ISIGMA = IZ + MIU2 = ISIGMA + NIVT2 = IU2 + LDU2*NIQ = IVT2 + LDVT2*M*IDX = 1IDXC = IDX + NCOLTYP = IDXC + NIDXP = COLTYP + N** Scale.*ORGNRM = MAX( ABS( ALPHA ), ABS( BETA ) )D( NL+1 ) = ZERODO 10 I = 1, NIF( ABS( D( I ) ).GT.ORGNRM ) THENORGNRM = ABS( D( I ) )END IF10 CONTINUECALL DLASCL( 'G', 0, 0, ORGNRM, ONE, N, 1, D, N, INFO )ALPHA = ALPHA / ORGNRMBETA = BETA / ORGNRM** Deflate singular values.*CALL DLASD2( NL, NR, SQRE, K, D, WORK( IZ ), ALPHA, BETA, U, LDU,$ VT, LDVT, WORK( ISIGMA ), WORK( IU2 ), LDU2,$ WORK( IVT2 ), LDVT2, IWORK( IDXP ), IWORK( IDX ),$ IWORK( IDXC ), IDXQ, IWORK( COLTYP ), INFO )** Solve Secular Equation and update singular vectors.*LDQ = KCALL DLASD3( NL, NR, SQRE, K, D, WORK( IQ ), LDQ, WORK( ISIGMA ),$ U, LDU, WORK( IU2 ), LDU2, VT, LDVT, WORK( IVT2 ),$ LDVT2, IWORK( IDXC ), IWORK( COLTYP ), WORK( IZ ),$ INFO )IF( INFO.NE.0 ) THENRETURNEND IF** Unscale.*CALL DLASCL( 'G', 0, 0, ONE, ORGNRM, N, 1, D, N, INFO )** Prepare the IDXQ sorting permutation.*N1 = KN2 = N - KCALL DLAMRG( N1, N2, D, 1, -1, IDXQ )*RETURN** End of DLASD1*ENDSUBROUTINE DLASD6( ICOMPQ, NL, NR, SQRE, D, VF, VL, ALPHA, BETA,$ IDXQ, PERM, GIVPTR, GIVCOL, LDGCOL, GIVNUM,$ LDGNUM, POLES, DIFL, DIFR, Z, K, C, S, WORK,$ IWORK, INFO )** -- LAPACK auxiliary 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 GIVPTR, ICOMPQ, INFO, K, LDGCOL, LDGNUM, NL,$ NR, SQREDOUBLE PRECISION ALPHA, BETA, C, S* ..* .. Array Arguments ..INTEGER GIVCOL( LDGCOL, * ), IDXQ( * ), IWORK( * ),$ PERM( * )DOUBLE PRECISION D( * ), DIFL( * ), DIFR( * ),$ GIVNUM( LDGNUM, * ), POLES( LDGNUM, * ),$ VF( * ), VL( * ), WORK( * ), Z( * )* ..** Purpose* =======** DLASD6 computes the SVD of an updated upper bidiagonal matrix B* obtained by merging two smaller ones by appending a row. This* routine is used only for the problem which requires all singular* values and optionally singular vector matrices in factored form.* B is an N-by-M matrix with N = NL + NR + 1 and M = N + SQRE.* A related subroutine, DLASD1, handles the case in which all singular* values and singular vectors of the bidiagonal matrix are desired.** DLASD6 computes the SVD as follows:** ( D1(in) 0 0 0 )* B = U(in) * ( Z1' a Z2' b ) * VT(in)* ( 0 0 D2(in) 0 )** = U(out) * ( D(out) 0) * VT(out)** where Z' = (Z1' a Z2' b) = u' VT', and u is a vector of dimension M* with ALPHA and BETA in the NL+1 and NL+2 th entries and zeros* elsewhere; and the entry b is empty if SQRE = 0.** The singular values of B can be computed using D1, D2, the first* components of all the right singular vectors of the lower block, and* the last components of all the right singular vectors of the upper* block. These components are stored and updated in VF and VL,* respectively, in DLASD6. Hence U and VT are not explicitly* referenced.** The singular values are stored in D. The algorithm consists of two* stages:** The first stage consists of deflating the size of the problem* when there are multiple singular values or if there is a zero* in the Z vector. For each such occurence the dimension of the* secular equation problem is reduced by one. This stage is* performed by the routine DLASD7.** The second stage consists of calculating the updated* singular values. This is done by finding the roots of the* secular equation via the routine DLASD4 (as called by DLASD8).* This routine also updates VF and VL and computes the distances* between the updated singular values and the old singular* values.** DLASD6 is called from DLASDA.** Arguments* =========** ICOMPQ (input) INTEGER* Specifies whether singular vectors are to be computed in* factored form:* = 0: Compute singular values only.* = 1: Compute singular vectors in factored form as well.** NL (input) INTEGER* The row dimension of the upper block. NL >= 1.** NR (input) INTEGER* The row dimension of the lower block. NR >= 1.** SQRE (input) INTEGER* = 0: the lower block is an NR-by-NR square matrix.* = 1: the lower block is an NR-by-(NR+1) rectangular matrix.** The bidiagonal matrix has row dimension N = NL + NR + 1,* and column dimension M = N + SQRE.** D (input/output) DOUBLE PRECISION array, dimension ( NL+NR+1 ).* On entry D(1:NL,1:NL) contains the singular values of the* upper block, and D(NL+2:N) contains the singular values* of the lower block. On exit D(1:N) contains the singular* values of the modified matrix.** VF (input/output) DOUBLE PRECISION array, dimension ( M )* On entry, VF(1:NL+1) contains the first components of all* right singular vectors of the upper block; and VF(NL+2:M)* contains the first components of all right singular vectors* of the lower block. On exit, VF contains the first components* of all right singular vectors of the bidiagonal matrix.** VL (input/output) DOUBLE PRECISION array, dimension ( M )* On entry, VL(1:NL+1) contains the last components of all* right singular vectors of the upper block; and VL(NL+2:M)* contains the last components of all right singular vectors of* the lower block. On exit, VL contains the last components of* all right singular vectors of the bidiagonal matrix.** ALPHA (input) DOUBLE PRECISION* Contains the diagonal element associated with the added row.** BETA (input) DOUBLE PRECISION* Contains the off-diagonal element associated with the added* row.** IDXQ (output) INTEGER array, dimension ( N )* This contains the permutation which will reintegrate the* subproblem just solved back into sorted order, i.e.* D( IDXQ( I = 1, N ) ) will be in ascending order.** PERM (output) INTEGER array, dimension ( N )* The permutations (from deflation and sorting) to be applied* to each block. Not referenced if ICOMPQ = 0.** GIVPTR (output) INTEGER* The number of Givens rotations which took place in this* subproblem. Not referenced if ICOMPQ = 0.** GIVCOL (output) INTEGER array, dimension ( LDGCOL, 2 )* Each pair of numbers indicates a pair of columns to take place* in a Givens rotation. Not referenced if ICOMPQ = 0.** LDGCOL (input) INTEGER* leading dimension of GIVCOL, must be at least N.** GIVNUM (output) DOUBLE PRECISION array, dimension ( LDGNUM, 2 )* Each number indicates the C or S value to be used in the* corresponding Givens rotation. Not referenced if ICOMPQ = 0.** LDGNUM (input) INTEGER* The leading dimension of GIVNUM and POLES, must be at least N.** POLES (output) DOUBLE PRECISION array, dimension ( LDGNUM, 2 )* On exit, POLES(1,*) is an array containing the new singular* values obtained from solving the secular equation, and* POLES(2,*) is an array containing the poles in the secular* equation. Not referenced if ICOMPQ = 0.** DIFL (output) DOUBLE PRECISION array, dimension ( N )* On exit, DIFL(I) is the distance between I-th updated* (undeflated) singular value and the I-th (undeflated) old* singular value.** DIFR (output) DOUBLE PRECISION array,* dimension ( LDGNUM, 2 ) if ICOMPQ = 1 and* dimension ( N ) if ICOMPQ = 0.* On exit, DIFR(I, 1) is the distance between I-th updated* (undeflated) singular value and the I+1-th (undeflated) old* singular value.** If ICOMPQ = 1, DIFR(1:K,2) is an array containing the* normalizing factors for the right singular vector matrix.** See DLASD8 for details on DIFL and DIFR.** Z (output) DOUBLE PRECISION array, dimension ( M )* The first elements of this array contain the components* of the deflation-adjusted updating row vector.** K (output) INTEGER* Contains the dimension of the non-deflated matrix,* This is the order of the related secular equation. 1 <= K <=N.** C (output) DOUBLE PRECISION* C contains garbage if SQRE =0 and the C-value of a Givens* rotation related to the right null space if SQRE = 1.** S (output) DOUBLE PRECISION* S contains garbage if SQRE =0 and the S-value of a Givens* rotation related to the right null space if SQRE = 1.** WORK (workspace) DOUBLE PRECISION array, dimension ( 4 * M )** IWORK (workspace) INTEGER array, dimension ( 3 * N )** INFO (output) INTEGER* = 0: successful exit.* < 0: if INFO = -i, the i-th argument had an illegal value.* > 0: if INFO = 1, an singular value did not converge** Further Details* ===============** Based on contributions by* Ming Gu and Huan Ren, Computer Science Division, University of* California at Berkeley, USA** =====================================================================** .. Parameters ..DOUBLE PRECISION ONE, ZEROPARAMETER ( ONE = 1.0D+0, ZERO = 0.0D+0 )* ..* .. Local Scalars ..INTEGER I, IDX, IDXC, IDXP, ISIGMA, IVFW, IVLW, IW, M,$ N, N1, N2DOUBLE PRECISION ORGNRM* ..* .. External Subroutines ..EXTERNAL DCOPY, DLAMRG, DLASCL, DLASD7, DLASD8, XERBLA* ..* .. Intrinsic Functions ..INTRINSIC ABS, MAX* ..* .. Executable Statements ..** Test the input parameters.*INFO = 0N = NL + NR + 1M = N + SQRE*IF( ( ICOMPQ.LT.0 ) .OR. ( ICOMPQ.GT.1 ) ) THENINFO = -1ELSE IF( NL.LT.1 ) THENINFO = -2ELSE IF( NR.LT.1 ) THENINFO = -3ELSE IF( ( SQRE.LT.0 ) .OR. ( SQRE.GT.1 ) ) THENINFO = -4ELSE IF( LDGCOL.LT.N ) THENINFO = -14ELSE IF( LDGNUM.LT.N ) THENINFO = -16END IFIF( INFO.NE.0 ) THENCALL XERBLA( 'DLASD6', -INFO )RETURNEND IF** The following values are for bookkeeping purposes only. They are* integer pointers which indicate the portion of the workspace* used by a particular array in DLASD7 and DLASD8.*ISIGMA = 1IW = ISIGMA + NIVFW = IW + MIVLW = IVFW + M*IDX = 1IDXC = IDX + NIDXP = IDXC + N** Scale.*ORGNRM = MAX( ABS( ALPHA ), ABS( BETA ) )D( NL+1 ) = ZERODO 10 I = 1, NIF( ABS( D( I ) ).GT.ORGNRM ) THENORGNRM = ABS( D( I ) )END IF10 CONTINUECALL DLASCL( 'G', 0, 0, ORGNRM, ONE, N, 1, D, N, INFO )ALPHA = ALPHA / ORGNRMBETA = BETA / ORGNRM** Sort and Deflate singular values.*CALL DLASD7( ICOMPQ, NL, NR, SQRE, K, D, Z, WORK( IW ), VF,$ WORK( IVFW ), VL, WORK( IVLW ), ALPHA, BETA,$ WORK( ISIGMA ), IWORK( IDX ), IWORK( IDXP ), IDXQ,$ PERM, GIVPTR, GIVCOL, LDGCOL, GIVNUM, LDGNUM, C, S,$ INFO )** Solve Secular Equation, compute DIFL, DIFR, and update VF, VL.*CALL DLASD8( ICOMPQ, K, D, Z, VF, VL, DIFL, DIFR, LDGNUM,$ WORK( ISIGMA ), WORK( IW ), INFO )** Save the poles if ICOMPQ = 1.*IF( ICOMPQ.EQ.1 ) THENCALL DCOPY( K, D, 1, POLES( 1, 1 ), 1 )CALL DCOPY( K, WORK( ISIGMA ), 1, POLES( 1, 2 ), 1 )END IF** Unscale.*CALL DLASCL( 'G', 0, 0, ONE, ORGNRM, N, 1, D, N, INFO )** Prepare the IDXQ sorting permutation.*N1 = KN2 = N - KCALL DLAMRG( N1, N2, D, 1, -1, IDXQ )*RETURN** End of DLASD6*ENDSUBROUTINE DLASD2( NL, NR, SQRE, K, D, Z, ALPHA, BETA, U, LDU, VT,$ LDVT, DSIGMA, U2, LDU2, VT2, LDVT2, IDXP, IDX,$ IDXC, IDXQ, COLTYP, INFO )** -- LAPACK auxiliary routine (version 3.0) --* Univ. of Tennessee, Oak Ridge National Lab, Argonne National Lab,* Courant Institute, NAG Ltd., and Rice University* October 31, 1999** .. Scalar Arguments ..INTEGER INFO, K, LDU, LDU2, LDVT, LDVT2, NL, NR, SQREDOUBLE PRECISION ALPHA, BETA* ..* .. Array Arguments ..INTEGER COLTYP( * ), IDX( * ), IDXC( * ), IDXP( * ),$ IDXQ( * )DOUBLE PRECISION D( * ), DSIGMA( * ), U( LDU, * ),$ U2( LDU2, * ), VT( LDVT, * ), VT2( LDVT2, * ),$ Z( * )* ..** Purpose* =======** DLASD2 merges the two sets of singular values together into a single* sorted set. Then it tries to deflate the size of the problem.* There are two ways in which deflation can occur: when two or more* singular values are close together or if there is a tiny entry in the* Z vector. For each such occurrence the order of the related secular* equation problem is reduced by one.** DLASD2 is called from DLASD1.** Arguments* =========** NL (input) INTEGER* The row dimension of the upper block. NL >= 1.** NR (input) INTEGER* The row dimension of the lower block. NR >= 1.** SQRE (input) INTEGER* = 0: the lower block is an NR-by-NR square matrix.* = 1: the lower block is an NR-by-(NR+1) rectangular matrix.** The bidiagonal matrix has N = NL + NR + 1 rows and* M = N + SQRE >= N columns.** K (output) INTEGER* Contains the dimension of the non-deflated matrix,* This is the order of the related secular equation. 1 <= K <=N.** D (input/output) DOUBLE PRECISION array, dimension(N)* On entry D contains the singular values of the two submatrices* to be combined. On exit D contains the trailing (N-K) updated* singular values (those which were deflated) sorted into* increasing order.** ALPHA (input) DOUBLE PRECISION* Contains the diagonal element associated with the added row.** BETA (input) DOUBLE PRECISION* Contains the off-diagonal element associated with the added* row.** U (input/output) DOUBLE PRECISION array, dimension(LDU,N)* On entry U contains the left singular vectors of two* submatrices in the two square blocks with corners at (1,1),* (NL, NL), and (NL+2, NL+2), (N,N).* On exit U contains the trailing (N-K) updated left singular* vectors (those which were deflated) in its last N-K columns.** LDU (input) INTEGER* The leading dimension of the array U. LDU >= N.** Z (output) DOUBLE PRECISION array, dimension(N)* On exit Z contains the updating row vector in the secular* equation.** DSIGMA (output) DOUBLE PRECISION array, dimension (N)* Contains a copy of the diagonal elements (K-1 singular values* and one zero) in the secular equation.** U2 (output) DOUBLE PRECISION array, dimension(LDU2,N)* Contains a copy of the first K-1 left singular vectors which* will be used by DLASD3 in a matrix multiply (DGEMM) to solve* for the new left singular vectors. U2 is arranged into four* blocks. The first block contains a column with 1 at NL+1 and* zero everywhere else; the second block contains non-zero* entries only at and above NL; the third contains non-zero* entries only below NL+1; and the fourth is dense.** LDU2 (input) INTEGER* The leading dimension of the array U2. LDU2 >= N.** VT (input/output) DOUBLE PRECISION array, dimension(LDVT,M)* On entry VT' contains the right singular vectors of two* submatrices in the two square blocks with corners at (1,1),* (NL+1, NL+1), and (NL+2, NL+2), (M,M).* On exit VT' contains the trailing (N-K) updated right singular* vectors (those which were deflated) in its last N-K columns.* In case SQRE =1, the last row of VT spans the right null* space.** LDVT (input) INTEGER* The leading dimension of the array VT. LDVT >= M.** VT2 (output) DOUBLE PRECISION array, dimension(LDVT2,N)* VT2' contains a copy of the first K right singular vectors* which will be used by DLASD3 in a matrix multiply (DGEMM) to* solve for the new right singular vectors. VT2 is arranged into* three blocks. The first block contains a row that corresponds* to the special 0 diagonal element in SIGMA; the second block* contains non-zeros only at and before NL +1; the third block* contains non-zeros only at and after NL +2.** LDVT2 (input) INTEGER* The leading dimension of the array VT2. LDVT2 >= M.** IDXP (workspace) INTEGER array, dimension(N)* This will contain the permutation used to place deflated* values of D at the end of the array. On output IDXP(2:K)* points to the nondeflated D-values and IDXP(K+1:N)* points to the deflated singular values.** IDX (workspace) INTEGER array, dimension(N)* This will contain the permutation used to sort the contents of* D into ascending order.** IDXC (output) INTEGER array, dimension(N)* This will contain the permutation used to arrange the columns* of the deflated U matrix into three groups: the first group* contains non-zero entries only at and above NL, the second* contains non-zero entries only below NL+2, and the third is* dense.** COLTYP (workspace/output) INTEGER array, dimension(N)* As workspace, this will contain a label which will indicate* which of the following types a column in the U2 matrix or a* row in the VT2 matrix is:* 1 : non-zero in the upper half only* 2 : non-zero in the lower half only* 3 : dense* 4 : deflated** On exit, it is an array of dimension 4, with COLTYP(I) being* the dimension of the I-th type columns.** IDXQ (input) INTEGER array, dimension(N)* This contains the permutation which separately sorts the two* sub-problems in D into ascending order. Note that entries in* the first hlaf of this permutation must first be moved one* position backward; and entries in the second half* must first have NL+1 added to their values.** INFO (output) INTEGER* = 0: successful exit.* < 0: if INFO = -i, the i-th argument had an illegal value.** Further Details* ===============** Based on contributions by* Ming Gu and Huan Ren, Computer Science Division, University of* California at Berkeley, USA** =====================================================================** .. Parameters ..DOUBLE PRECISION ZERO, ONE, TWO, EIGHTPARAMETER ( ZERO = 0.0D+0, ONE = 1.0D+0, TWO = 2.0D+0,$ EIGHT = 8.0D+0 )* ..* .. Local Arrays ..INTEGER CTOT( 4 ), PSM( 4 )* ..* .. Local Scalars ..INTEGER CT, I, IDXI, IDXJ, IDXJP, J, JP, JPREV, K2, M,$ N, NLP1, NLP2DOUBLE PRECISION C, EPS, HLFTOL, S, TAU, TOL, Z1* ..* .. External Functions ..DOUBLE PRECISION DLAMCH, DLAPY2EXTERNAL DLAMCH, DLAPY2* ..* .. External Subroutines ..EXTERNAL DCOPY, DLACPY, DLAMRG, DLASET, DROT, XERBLA* ..* .. Intrinsic Functions ..INTRINSIC ABS, MAX* ..* .. Executable Statements ..** Test the input parameters.*INFO = 0*IF( NL.LT.1 ) THENINFO = -1ELSE IF( NR.LT.1 ) THENINFO = -2ELSE IF( ( SQRE.NE.1 ) .AND. ( SQRE.NE.0 ) ) THENINFO = -3END IF*N = NL + NR + 1M = N + SQRE*IF( LDU.LT.N ) THENINFO = -10ELSE IF( LDVT.LT.M ) THENINFO = -12ELSE IF( LDU2.LT.N ) THENINFO = -15ELSE IF( LDVT2.LT.M ) THENINFO = -17END IFIF( INFO.NE.0 ) THENCALL XERBLA( 'DLASD2', -INFO )RETURNEND IF*NLP1 = NL + 1NLP2 = NL + 2** Generate the first part of the vector Z; and move the singular* values in the first part of D one position backward.*Z1 = ALPHA*VT( NLP1, NLP1 )Z( 1 ) = Z1DO 10 I = NL, 1, -1Z( I+1 ) = ALPHA*VT( I, NLP1 )D( I+1 ) = D( I )IDXQ( I+1 ) = IDXQ( I ) + 110 CONTINUE** Generate the second part of the vector Z.*DO 20 I = NLP2, MZ( I ) = BETA*VT( I, NLP2 )20 CONTINUE** Initialize some reference arrays.*DO 30 I = 2, NLP1COLTYP( I ) = 130 CONTINUEDO 40 I = NLP2, NCOLTYP( I ) = 240 CONTINUE** Sort the singular values into increasing order*DO 50 I = NLP2, NIDXQ( I ) = IDXQ( I ) + NLP150 CONTINUE** DSIGMA, IDXC, IDXC, and the first column of U2* are used as storage space.*DO 60 I = 2, NDSIGMA( I ) = D( IDXQ( I ) )U2( I, 1 ) = Z( IDXQ( I ) )IDXC( I ) = COLTYP( IDXQ( I ) )60 CONTINUE*CALL DLAMRG( NL, NR, DSIGMA( 2 ), 1, 1, IDX( 2 ) )*DO 70 I = 2, NIDXI = 1 + IDX( I )D( I ) = DSIGMA( IDXI )Z( I ) = U2( IDXI, 1 )COLTYP( I ) = IDXC( IDXI )70 CONTINUE** Calculate the allowable deflation tolerance*EPS = DLAMCH( 'Epsilon' )TOL = MAX( ABS( ALPHA ), ABS( BETA ) )TOL = EIGHT*EPS*MAX( ABS( D( N ) ), TOL )** There are 2 kinds of deflation -- first a value in the z-vector* is small, second two (or more) singular values are very close* together (their difference is small).** If the value in the z-vector is small, we simply permute the* array so that the corresponding singular value is moved to the* end.** If two values in the D-vector are close, we perform a two-sided* rotation designed to make one of the corresponding z-vector* entries zero, and then permute the array so that the deflated* singular value is moved to the end.** If there are multiple singular values then the problem deflates.* Here the number of equal singular values are found. As each equal* singular value is found, an elementary reflector is computed to* rotate the corresponding singular subspace so that the* corresponding components of Z are zero in this new basis.*K = 1K2 = N + 1DO 80 J = 2, NIF( ABS( Z( J ) ).LE.TOL ) THEN** Deflate due to small z component.*K2 = K2 - 1IDXP( K2 ) = JCOLTYP( J ) = 4IF( J.EQ.N )$ GO TO 120ELSEJPREV = JGO TO 90END IF80 CONTINUE90 CONTINUEJ = JPREV100 CONTINUEJ = J + 1IF( J.GT.N )$ GO TO 110IF( ABS( Z( J ) ).LE.TOL ) THEN** Deflate due to small z component.*K2 = K2 - 1IDXP( K2 ) = JCOLTYP( J ) = 4ELSE** Check if singular values are close enough to allow deflation.*IF( ABS( D( J )-D( JPREV ) ).LE.TOL ) THEN** Deflation is possible.*S = Z( JPREV )C = Z( J )** Find sqrt(a**2+b**2) without overflow or* destructive underflow.*TAU = DLAPY2( C, S )C = C / TAUS = -S / TAUZ( J ) = TAUZ( JPREV ) = ZERO** Apply back the Givens rotation to the left and right* singular vector matrices.*IDXJP = IDXQ( IDX( JPREV )+1 )IDXJ = IDXQ( IDX( J )+1 )IF( IDXJP.LE.NLP1 ) THENIDXJP = IDXJP - 1END IFIF( IDXJ.LE.NLP1 ) THENIDXJ = IDXJ - 1END IFCALL DROT( N, U( 1, IDXJP ), 1, U( 1, IDXJ ), 1, C, S )CALL DROT( M, VT( IDXJP, 1 ), LDVT, VT( IDXJ, 1 ), LDVT, C,$ S )IF( COLTYP( J ).NE.COLTYP( JPREV ) ) THENCOLTYP( J ) = 3END IFCOLTYP( JPREV ) = 4K2 = K2 - 1IDXP( K2 ) = JPREVJPREV = JELSEK = K + 1U2( K, 1 ) = Z( JPREV )DSIGMA( K ) = D( JPREV )IDXP( K ) = JPREVJPREV = JEND IFEND IFGO TO 100110 CONTINUE** Record the last singular value.*K = K + 1U2( K, 1 ) = Z( JPREV )DSIGMA( K ) = D( JPREV )IDXP( K ) = JPREV*120 CONTINUE** Count up the total number of the various types of columns, then* form a permutation which positions the four column types into* four groups of uniform structure (although one or more of these* groups may be empty).*DO 130 J = 1, 4CTOT( J ) = 0130 CONTINUEDO 140 J = 2, NCT = COLTYP( J )CTOT( CT ) = CTOT( CT ) + 1140 CONTINUE** PSM(*) = Position in SubMatrix (of types 1 through 4)*PSM( 1 ) = 2PSM( 2 ) = 2 + CTOT( 1 )PSM( 3 ) = PSM( 2 ) + CTOT( 2 )PSM( 4 ) = PSM( 3 ) + CTOT( 3 )** Fill out the IDXC array so that the permutation which it induces* will place all type-1 columns first, all type-2 columns next,* then all type-3's, and finally all type-4's, starting from the* second column. This applies similarly to the rows of VT.*DO 150 J = 2, NJP = IDXP( J )CT = COLTYP( JP )IDXC( PSM( CT ) ) = JPSM( CT ) = PSM( CT ) + 1150 CONTINUE** Sort the singular values and corresponding singular vectors into* DSIGMA, U2, and VT2 respectively. The singular values/vectors* which were not deflated go into the first K slots of DSIGMA, U2,* and VT2 respectively, while those which were deflated go into the* last N - K slots, except that the first column/row will be treated* separately.*DO 160 J = 2, NJP = IDXP( J )DSIGMA( J ) = D( JP )IDXJ = IDXQ( IDX( IDXP( IDXC( J ) ) )+1 )IF( IDXJ.LE.NLP1 ) THENIDXJ = IDXJ - 1END IFCALL DCOPY( N, U( 1, IDXJ ), 1, U2( 1, J ), 1 )CALL DCOPY( M, VT( IDXJ, 1 ), LDVT, VT2( J, 1 ), LDVT2 )160 CONTINUE** Determine DSIGMA(1), DSIGMA(2) and Z(1)*DSIGMA( 1 ) = ZEROHLFTOL = TOL / TWOIF( ABS( DSIGMA( 2 ) ).LE.HLFTOL )$ DSIGMA( 2 ) = HLFTOLIF( M.GT.N ) THENZ( 1 ) = DLAPY2( Z1, Z( M ) )IF( Z( 1 ).LE.TOL ) THENC = ONES = ZEROZ( 1 ) = TOLELSEC = Z1 / Z( 1 )S = Z( M ) / Z( 1 )END IFELSEIF( ABS( Z1 ).LE.TOL ) THENZ( 1 ) = TOLELSEZ( 1 ) = Z1END IFEND IF** Move the rest of the updating row to Z.*CALL DCOPY( K-1, U2( 2, 1 ), 1, Z( 2 ), 1 )** Determine the first column of U2, the first row of VT2 and the* last row of VT.*CALL DLASET( 'A', N, 1, ZERO, ZERO, U2, LDU2 )U2( NLP1, 1 ) = ONEIF( M.GT.N ) THENDO 170 I = 1, NLP1VT( M, I ) = -S*VT( NLP1, I )VT2( 1, I ) = C*VT( NLP1, I )170 CONTINUEDO 180 I = NLP2, MVT2( 1, I ) = S*VT( M, I )VT( M, I ) = C*VT( M, I )180 CONTINUEELSECALL DCOPY( M, VT( NLP1, 1 ), LDVT, VT2( 1, 1 ), LDVT2 )END IFIF( M.GT.N ) THENCALL DCOPY( M, VT( M, 1 ), LDVT, VT2( M, 1 ), LDVT2 )END IF** The deflated singular values and their corresponding vectors go* into the back of D, U, and V respectively.*IF( N.GT.K ) THENCALL DCOPY( N-K, DSIGMA( K+1 ), 1, D( K+1 ), 1 )CALL DLACPY( 'A', N, N-K, U2( 1, K+1 ), LDU2, U( 1, K+1 ),$ LDU )CALL DLACPY( 'A', N-K, M, VT2( K+1, 1 ), LDVT2, VT( K+1, 1 ),$ LDVT )END IF** Copy CTOT into COLTYP for referencing in DLASD3.*DO 190 J = 1, 4COLTYP( J ) = CTOT( J )190 CONTINUE*RETURN** End of DLASD2*ENDSUBROUTINE DLASD3( NL, NR, SQRE, K, D, Q, LDQ, DSIGMA, U, LDU, U2,$ LDU2, VT, LDVT, VT2, LDVT2, IDXC, CTOT, Z,$ INFO )** -- LAPACK auxiliary routine (version 3.0) --* Univ. of Tennessee, Oak Ridge National Lab, Argonne National Lab,* Courant Institute, NAG Ltd., and Rice University* October 31, 1999** .. Scalar Arguments ..INTEGER INFO, K, LDQ, LDU, LDU2, LDVT, LDVT2, NL, NR,$ SQRE* ..* .. Array Arguments ..INTEGER CTOT( * ), IDXC( * )DOUBLE PRECISION D( * ), DSIGMA( * ), Q( LDQ, * ), U( LDU, * ),$ U2( LDU2, * ), VT( LDVT, * ), VT2( LDVT2, * ),$ Z( * )* ..** Purpose* =======** DLASD3 finds all the square roots of the roots of the secular* equation, as defined by the values in D and Z. It makes the* appropriate calls to DLASD4 and then updates the singular* vectors by matrix multiplication.** 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 XMP, Cray YMP, Cray C 90, or Cray 2.* It could conceivably fail on hexadecimal or decimal machines* without guard digits, but we know of none.** DLASD3 is called from DLASD1.** Arguments* =========** NL (input) INTEGER* The row dimension of the upper block. NL >= 1.** NR (input) INTEGER* The row dimension of the lower block. NR >= 1.** SQRE (input) INTEGER* = 0: the lower block is an NR-by-NR square matrix.* = 1: the lower block is an NR-by-(NR+1) rectangular matrix.** The bidiagonal matrix has N = NL + NR + 1 rows and* M = N + SQRE >= N columns.** K (input) INTEGER* The size of the secular equation, 1 =< K = < N.** D (output) DOUBLE PRECISION array, dimension(K)* On exit the square roots of the roots of the secular equation,* in ascending order.** Q (workspace) DOUBLE PRECISION array,* dimension at least (LDQ,K).** LDQ (input) INTEGER* The leading dimension of the array Q. LDQ >= K.** DSIGMA (input) DOUBLE PRECISION array, dimension(K)* The first K elements of this array contain the old roots* of the deflated updating problem. These are the poles* of the secular equation.** U (input) DOUBLE PRECISION array, dimension (LDU, N)* The last N - K columns of this matrix contain the deflated* left singular vectors.** LDU (input) INTEGER* The leading dimension of the array U. LDU >= N.** U2 (input) DOUBLE PRECISION array, dimension (LDU2, N)* The first K columns of this matrix contain the non-deflated* left singular vectors for the split problem.** LDU2 (input) INTEGER* The leading dimension of the array U2. LDU2 >= N.** VT (input) DOUBLE PRECISION array, dimension (LDVT, M)* The last M - K columns of VT' contain the deflated* right singular vectors.** LDVT (input) INTEGER* The leading dimension of the array VT. LDVT >= N.** VT2 (input) DOUBLE PRECISION array, dimension (LDVT2, N)* The first K columns of VT2' contain the non-deflated* right singular vectors for the split problem.** LDVT2 (input) INTEGER* The leading dimension of the array VT2. LDVT2 >= N.** IDXC (input) INTEGER array, dimension ( N )* The permutation used to arrange the columns of U (and rows of* VT) into three groups: the first group contains non-zero* entries only at and above (or before) NL +1; the second* contains non-zero entries only at and below (or after) NL+2;* and the third is dense. The first column of U and the row of* VT are treated separately, however.** The rows of the singular vectors found by DLASD4* must be likewise permuted before the matrix multiplies can* take place.** CTOT (input) INTEGER array, dimension ( 4 )* A count of the total number of the various types of columns* in U (or rows in VT), as described in IDXC. The fourth column* type is any column which has been deflated.** Z (input) DOUBLE PRECISION array, dimension (K)* The first K elements of this array contain the components* of the deflation-adjusted updating row vector.** INFO (output) INTEGER* = 0: successful exit.* < 0: if INFO = -i, the i-th argument had an illegal value.* > 0: if INFO = 1, an singular value did not converge** Further Details* ===============** Based on contributions by* Ming Gu and Huan Ren, Computer Science Division, University of* California at Berkeley, USA** =====================================================================** .. Parameters ..DOUBLE PRECISION ONE, ZERO, NEGONEPARAMETER ( ONE = 1.0D+0, ZERO = 0.0D+0,$ NEGONE = -1.0D+0 )* ..* .. Local Scalars ..INTEGER CTEMP, I, J, JC, KTEMP, M, N, NLP1, NLP2, NRP1DOUBLE PRECISION RHO, TEMP* ..* .. External Functions ..DOUBLE PRECISION DLAMC3, DNRM2EXTERNAL DLAMC3, DNRM2* ..* .. External Subroutines ..EXTERNAL DCOPY, DGEMM, DLACPY, DLASCL, DLASD4, XERBLA* ..* .. Intrinsic Functions ..INTRINSIC ABS, SIGN, SQRT* ..* .. Executable Statements ..** Test the input parameters.*INFO = 0*IF( NL.LT.1 ) THENINFO = -1ELSE IF( NR.LT.1 ) THENINFO = -2ELSE IF( ( SQRE.NE.1 ) .AND. ( SQRE.NE.0 ) ) THENINFO = -3END IF*N = NL + NR + 1M = N + SQRENLP1 = NL + 1NLP2 = NL + 2*IF( ( K.LT.1 ) .OR. ( K.GT.N ) ) THENINFO = -4ELSE IF( LDQ.LT.K ) THENINFO = -7ELSE IF( LDU.LT.N ) THENINFO = -10ELSE IF( LDU2.LT.N ) THENINFO = -12ELSE IF( LDVT.LT.M ) THENINFO = -14ELSE IF( LDVT2.LT.M ) THENINFO = -16END IFIF( INFO.NE.0 ) THENCALL XERBLA( 'DLASD3', -INFO )RETURNEND IF** Quick return if possible*IF( K.EQ.1 ) THEND( 1 ) = ABS( Z( 1 ) )CALL DCOPY( M, VT2( 1, 1 ), LDVT2, VT( 1, 1 ), LDVT )IF( Z( 1 ).GT.ZERO ) THENCALL DCOPY( N, U2( 1, 1 ), 1, U( 1, 1 ), 1 )ELSEDO 10 I = 1, NU( I, 1 ) = -U2( I, 1 )10 CONTINUEEND IFRETURNEND IF** Modify values DSIGMA(i) to make sure all DSIGMA(i)-DSIGMA(j) can* be computed with high relative accuracy (barring over/underflow).* This is a problem on machines without a guard digit in* add/subtract (Cray XMP, Cray YMP, Cray C 90 and Cray 2).* The following code replaces DSIGMA(I) by 2*DSIGMA(I)-DSIGMA(I),* which on any of these machines zeros out the bottommost* bit of DSIGMA(I) if it is 1; this makes the subsequent* subtractions DSIGMA(I)-DSIGMA(J) unproblematic when cancellation* occurs. On binary machines with a guard digit (almost all* machines) it does not change DSIGMA(I) at all. On hexadecimal* and decimal machines with a guard digit, it slightly* changes the bottommost bits of DSIGMA(I). It does not account* for hexadecimal or decimal machines without guard digits* (we know of none). We use a subroutine call to compute* 2*DLAMBDA(I) to prevent optimizing compilers from eliminating* this code.*DO 20 I = 1, KDSIGMA( I ) = DLAMC3( DSIGMA( I ), DSIGMA( I ) ) - DSIGMA( I )20 CONTINUE** Keep a copy of Z.*CALL DCOPY( K, Z, 1, Q, 1 )** Normalize Z.*RHO = DNRM2( K, Z, 1 )CALL DLASCL( 'G', 0, 0, RHO, ONE, K, 1, Z, K, INFO )RHO = RHO*RHO** Find the new singular values.*DO 30 J = 1, KCALL DLASD4( K, J, DSIGMA, Z, U( 1, J ), RHO, D( J ),$ VT( 1, J ), INFO )** If the zero finder fails, the computation is terminated.*IF( INFO.NE.0 ) THENRETURNEND IF30 CONTINUE** Compute updated Z.*DO 60 I = 1, KZ( I ) = U( I, K )*VT( I, K )DO 40 J = 1, I - 1Z( I ) = Z( I )*( U( I, J )*VT( I, J ) /$ ( DSIGMA( I )-DSIGMA( J ) ) /$ ( DSIGMA( I )+DSIGMA( J ) ) )40 CONTINUEDO 50 J = I, K - 1Z( I ) = Z( I )*( U( I, J )*VT( I, J ) /$ ( DSIGMA( I )-DSIGMA( J+1 ) ) /$ ( DSIGMA( I )+DSIGMA( J+1 ) ) )50 CONTINUEZ( I ) = SIGN( SQRT( ABS( Z( I ) ) ), Q( I, 1 ) )60 CONTINUE** Compute left singular vectors of the modified diagonal matrix,* and store related information for the right singular vectors.*DO 90 I = 1, KVT( 1, I ) = Z( 1 ) / U( 1, I ) / VT( 1, I )U( 1, I ) = NEGONEDO 70 J = 2, KVT( J, I ) = Z( J ) / U( J, I ) / VT( J, I )U( J, I ) = DSIGMA( J )*VT( J, I )70 CONTINUETEMP = DNRM2( K, U( 1, I ), 1 )Q( 1, I ) = U( 1, I ) / TEMPDO 80 J = 2, KJC = IDXC( J )Q( J, I ) = U( JC, I ) / TEMP80 CONTINUE90 CONTINUE** Update the left singular vector matrix.*IF( K.EQ.2 ) THENCALL DGEMM( 'N', 'N', N, K, K, ONE, U2, LDU2, Q, LDQ, ZERO, U,$ LDU )GO TO 100END IFIF( CTOT( 1 ).GT.0 ) THENCALL DGEMM( 'N', 'N', NL, K, CTOT( 1 ), ONE, U2( 1, 2 ), LDU2,$ Q( 2, 1 ), LDQ, ZERO, U( 1, 1 ), LDU )IF( CTOT( 3 ).GT.0 ) THENKTEMP = 2 + CTOT( 1 ) + CTOT( 2 )CALL DGEMM( 'N', 'N', NL, K, CTOT( 3 ), ONE, U2( 1, KTEMP ),$ LDU2, Q( KTEMP, 1 ), LDQ, ONE, U( 1, 1 ), LDU )END IFELSE IF( CTOT( 3 ).GT.0 ) THENKTEMP = 2 + CTOT( 1 ) + CTOT( 2 )CALL DGEMM( 'N', 'N', NL, K, CTOT( 3 ), ONE, U2( 1, KTEMP ),$ LDU2, Q( KTEMP, 1 ), LDQ, ZERO, U( 1, 1 ), LDU )ELSECALL DLACPY( 'F', NL, K, U2, LDU2, U, LDU )END IFCALL DCOPY( K, Q( 1, 1 ), LDQ, U( NLP1, 1 ), LDU )KTEMP = 2 + CTOT( 1 )CTEMP = CTOT( 2 ) + CTOT( 3 )CALL DGEMM( 'N', 'N', NR, K, CTEMP, ONE, U2( NLP2, KTEMP ), LDU2,$ Q( KTEMP, 1 ), LDQ, ZERO, U( NLP2, 1 ), LDU )** Generate the right singular vectors.*100 CONTINUEDO 120 I = 1, KTEMP = DNRM2( K, VT( 1, I ), 1 )Q( I, 1 ) = VT( 1, I ) / TEMPDO 110 J = 2, KJC = IDXC( J )Q( I, J ) = VT( JC, I ) / TEMP110 CONTINUE120 CONTINUE** Update the right singular vector matrix.*IF( K.EQ.2 ) THENCALL DGEMM( 'N', 'N', K, M, K, ONE, Q, LDQ, VT2, LDVT2, ZERO,$ VT, LDVT )RETURNEND IFKTEMP = 1 + CTOT( 1 )CALL DGEMM( 'N', 'N', K, NLP1, KTEMP, ONE, Q( 1, 1 ), LDQ,$ VT2( 1, 1 ), LDVT2, ZERO, VT( 1, 1 ), LDVT )KTEMP = 2 + CTOT( 1 ) + CTOT( 2 )IF( KTEMP.LE.LDVT2 )$ CALL DGEMM( 'N', 'N', K, NLP1, CTOT( 3 ), ONE, Q( 1, KTEMP ),$ LDQ, VT2( KTEMP, 1 ), LDVT2, ONE, VT( 1, 1 ),$ LDVT )*KTEMP = CTOT( 1 ) + 1NRP1 = NR + SQREIF( KTEMP.GT.1 ) THENDO 130 I = 1, KQ( I, KTEMP ) = Q( I, 1 )130 CONTINUEDO 140 I = NLP2, MVT2( KTEMP, I ) = VT2( 1, I )140 CONTINUEEND IFCTEMP = 1 + CTOT( 2 ) + CTOT( 3 )CALL DGEMM( 'N', 'N', K, NRP1, CTEMP, ONE, Q( 1, KTEMP ), LDQ,$ VT2( KTEMP, NLP2 ), LDVT2, ZERO, VT( 1, NLP2 ), LDVT )*RETURN** End of DLASD3*ENDSUBROUTINE DLASD7( ICOMPQ, NL, NR, SQRE, K, D, Z, ZW, VF, VFW, VL,$ VLW, ALPHA, BETA, DSIGMA, IDX, IDXP, IDXQ,$ PERM, GIVPTR, GIVCOL, LDGCOL, GIVNUM, LDGNUM,$ C, S, INFO )** -- LAPACK auxiliary routine (version 3.0) --* Univ. of Tennessee, Oak Ridge National Lab, Argonne National Lab,* Courant Institute, NAG Ltd., and Rice University* June 30, 1999** .. Scalar Arguments ..INTEGER GIVPTR, ICOMPQ, INFO, K, LDGCOL, LDGNUM, NL,$ NR, SQREDOUBLE PRECISION ALPHA, BETA, C, S* ..* .. Array Arguments ..INTEGER GIVCOL( LDGCOL, * ), IDX( * ), IDXP( * ),$ IDXQ( * ), PERM( * )DOUBLE PRECISION D( * ), DSIGMA( * ), GIVNUM( LDGNUM, * ),$ VF( * ), VFW( * ), VL( * ), VLW( * ), Z( * ),$ ZW( * )* ..** Purpose* =======** DLASD7 merges the two sets of singular values together into a single* sorted set. Then it tries to deflate the size of the problem. There* are two ways in which deflation can occur: when two or more singular* values are close together or if there is a tiny entry in the Z* vector. For each such occurrence the order of the related* secular equation problem is reduced by one.** DLASD7 is called from DLASD6.** Arguments* =========** ICOMPQ (input) INTEGER* Specifies whether singular vectors are to be computed* in compact form, as follows:* = 0: Compute singular values only.* = 1: Compute singular vectors of upper* bidiagonal matrix in compact form.** NL (input) INTEGER* The row dimension of the upper block. NL >= 1.** NR (input) INTEGER* The row dimension of the lower block. NR >= 1.** SQRE (input) INTEGER* = 0: the lower block is an NR-by-NR square matrix.* = 1: the lower block is an NR-by-(NR+1) rectangular matrix.** The bidiagonal matrix has* N = NL + NR + 1 rows and* M = N + SQRE >= N columns.** K (output) INTEGER* Contains the dimension of the non-deflated matrix, this is* the order of the related secular equation. 1 <= K <=N.** D (input/output) DOUBLE PRECISION array, dimension ( N )* On entry D contains the singular values of the two submatrices* to be combined. On exit D contains the trailing (N-K) updated* singular values (those which were deflated) sorted into* increasing order.** Z (output) DOUBLE PRECISION array, dimension ( M )* On exit Z contains the updating row vector in the secular* equation.** ZW (workspace) DOUBLE PRECISION array, dimension ( M )* Workspace for Z.** VF (input/output) DOUBLE PRECISION array, dimension ( M )* On entry, VF(1:NL+1) contains the first components of all* right singular vectors of the upper block; and VF(NL+2:M)* contains the first components of all right singular vectors* of the lower block. On exit, VF contains the first components* of all right singular vectors of the bidiagonal matrix.** VFW (workspace) DOUBLE PRECISION array, dimension ( M )* Workspace for VF.** VL (input/output) DOUBLE PRECISION array, dimension ( M )* On entry, VL(1:NL+1) contains the last components of all* right singular vectors of the upper block; and VL(NL+2:M)* contains the last components of all right singular vectors* of the lower block. On exit, VL contains the last components* of all right singular vectors of the bidiagonal matrix.** VLW (workspace) DOUBLE PRECISION array, dimension ( M )* Workspace for VL.** ALPHA (input) DOUBLE PRECISION* Contains the diagonal element associated with the added row.** BETA (input) DOUBLE PRECISION* Contains the off-diagonal element associated with the added* row.** DSIGMA (output) DOUBLE PRECISION array, dimension ( N )* Contains a copy of the diagonal elements (K-1 singular values* and one zero) in the secular equation.** IDX (workspace) INTEGER array, dimension ( N )* This will contain the permutation used to sort the contents of* D into ascending order.** IDXP (workspace) INTEGER array, dimension ( N )* This will contain the permutation used to place deflated* values of D at the end of the array. On output IDXP(2:K)* points to the nondeflated D-values and IDXP(K+1:N)* points to the deflated singular values.** IDXQ (input) INTEGER array, dimension ( N )* This contains the permutation which separately sorts the two* sub-problems in D into ascending order. Note that entries in* the first half of this permutation must first be moved one* position backward; and entries in the second half* must first have NL+1 added to their values.** PERM (output) INTEGER array, dimension ( N )* The permutations (from deflation and sorting) to be applied* to each singular block. Not referenced if ICOMPQ = 0.** GIVPTR (output) INTEGER* The number of Givens rotations which took place in this* subproblem. Not referenced if ICOMPQ = 0.** GIVCOL (output) INTEGER array, dimension ( LDGCOL, 2 )* Each pair of numbers indicates a pair of columns to take place* in a Givens rotation. Not referenced if ICOMPQ = 0.** LDGCOL (input) INTEGER* The leading dimension of GIVCOL, must be at least N.** GIVNUM (output) DOUBLE PRECISION array, dimension ( LDGNUM, 2 )* Each number indicates the C or S value to be used in the* corresponding Givens rotation. Not referenced if ICOMPQ = 0.** LDGNUM (input) INTEGER* The leading dimension of GIVNUM, must be at least N.** C (output) DOUBLE PRECISION* C contains garbage if SQRE =0 and the C-value of a Givens* rotation related to the right null space if SQRE = 1.** S (output) DOUBLE PRECISION* S contains garbage if SQRE =0 and the S-value of a Givens* rotation related to the right null space if SQRE = 1.** INFO (output) INTEGER* = 0: successful exit.* < 0: if INFO = -i, the i-th argument had an illegal value.** Further Details* ===============** Based on contributions by* Ming Gu and Huan Ren, Computer Science Division, University of* California at Berkeley, USA** =====================================================================** .. Parameters ..DOUBLE PRECISION ZERO, ONE, TWO, EIGHTPARAMETER ( ZERO = 0.0D+0, ONE = 1.0D+0, TWO = 2.0D+0,$ EIGHT = 8.0D+0 )* ..* .. Local Scalars ..*INTEGER I, IDXI, IDXJ, IDXJP, J, JP, JPREV, K2, M, N,$ NLP1, NLP2DOUBLE PRECISION EPS, HLFTOL, TAU, TOL, Z1* ..* .. External Subroutines ..EXTERNAL DCOPY, DLAMRG, DROT, XERBLA* ..* .. External Functions ..DOUBLE PRECISION DLAMCH, DLAPY2EXTERNAL DLAMCH, DLAPY2* ..* .. Intrinsic Functions ..INTRINSIC ABS, MAX* ..* .. Executable Statements ..** Test the input parameters.*INFO = 0N = NL + NR + 1M = N + SQRE*IF( ( ICOMPQ.LT.0 ) .OR. ( ICOMPQ.GT.1 ) ) THENINFO = -1ELSE IF( NL.LT.1 ) THENINFO = -2ELSE IF( NR.LT.1 ) THENINFO = -3ELSE IF( ( SQRE.LT.0 ) .OR. ( SQRE.GT.1 ) ) THENINFO = -4ELSE IF( LDGCOL.LT.N ) THENINFO = -22ELSE IF( LDGNUM.LT.N ) THENINFO = -24END IFIF( INFO.NE.0 ) THENCALL XERBLA( 'DLASD7', -INFO )RETURNEND IF*NLP1 = NL + 1NLP2 = NL + 2IF( ICOMPQ.EQ.1 ) THENGIVPTR = 0END IF** Generate the first part of the vector Z and move the singular* values in the first part of D one position backward.*Z1 = ALPHA*VL( NLP1 )VL( NLP1 ) = ZEROTAU = VF( NLP1 )DO 10 I = NL, 1, -1Z( I+1 ) = ALPHA*VL( I )VL( I ) = ZEROVF( I+1 ) = VF( I )D( I+1 ) = D( I )IDXQ( I+1 ) = IDXQ( I ) + 110 CONTINUEVF( 1 ) = TAU** Generate the second part of the vector Z.*DO 20 I = NLP2, MZ( I ) = BETA*VF( I )VF( I ) = ZERO20 CONTINUE** Sort the singular values into increasing order*DO 30 I = NLP2, NIDXQ( I ) = IDXQ( I ) + NLP130 CONTINUE** DSIGMA, IDXC, IDXC, and ZW are used as storage space.*DO 40 I = 2, NDSIGMA( I ) = D( IDXQ( I ) )ZW( I ) = Z( IDXQ( I ) )VFW( I ) = VF( IDXQ( I ) )VLW( I ) = VL( IDXQ( I ) )40 CONTINUE*CALL DLAMRG( NL, NR, DSIGMA( 2 ), 1, 1, IDX( 2 ) )*DO 50 I = 2, NIDXI = 1 + IDX( I )D( I ) = DSIGMA( IDXI )Z( I ) = ZW( IDXI )VF( I ) = VFW( IDXI )VL( I ) = VLW( IDXI )50 CONTINUE** Calculate the allowable deflation tolerence*EPS = DLAMCH( 'Epsilon' )TOL = MAX( ABS( ALPHA ), ABS( BETA ) )TOL = EIGHT*EIGHT*EPS*MAX( ABS( D( N ) ), TOL )** There are 2 kinds of deflation -- first a value in the z-vector* is small, second two (or more) singular values are very close* together (their difference is small).** If the value in the z-vector is small, we simply permute the* array so that the corresponding singular value is moved to the* end.** If two values in the D-vector are close, we perform a two-sided* rotation designed to make one of the corresponding z-vector* entries zero, and then permute the array so that the deflated* singular value is moved to the end.** If there are multiple singular values then the problem deflates.* Here the number of equal singular values are found. As each equal* singular value is found, an elementary reflector is computed to* rotate the corresponding singular subspace so that the* corresponding components of Z are zero in this new basis.*K = 1K2 = N + 1DO 60 J = 2, NIF( ABS( Z( J ) ).LE.TOL ) THEN** Deflate due to small z component.*K2 = K2 - 1IDXP( K2 ) = JIF( J.EQ.N )$ GO TO 100ELSEJPREV = JGO TO 70END IF60 CONTINUE70 CONTINUEJ = JPREV80 CONTINUEJ = J + 1IF( J.GT.N )$ GO TO 90IF( ABS( Z( J ) ).LE.TOL ) THEN** Deflate due to small z component.*K2 = K2 - 1IDXP( K2 ) = JELSE** Check if singular values are close enough to allow deflation.*IF( ABS( D( J )-D( JPREV ) ).LE.TOL ) THEN** Deflation is possible.*S = Z( JPREV )C = Z( J )** Find sqrt(a**2+b**2) without overflow or* destructive underflow.*TAU = DLAPY2( C, S )Z( J ) = TAUZ( JPREV ) = ZEROC = C / TAUS = -S / TAU** Record the appropriate Givens rotation*IF( ICOMPQ.EQ.1 ) THENGIVPTR = GIVPTR + 1IDXJP = IDXQ( IDX( JPREV )+1 )IDXJ = IDXQ( IDX( J )+1 )IF( IDXJP.LE.NLP1 ) THENIDXJP = IDXJP - 1END IFIF( IDXJ.LE.NLP1 ) THENIDXJ = IDXJ - 1END IFGIVCOL( GIVPTR, 2 ) = IDXJPGIVCOL( GIVPTR, 1 ) = IDXJGIVNUM( GIVPTR, 2 ) = CGIVNUM( GIVPTR, 1 ) = SEND IFCALL DROT( 1, VF( JPREV ), 1, VF( J ), 1, C, S )CALL DROT( 1, VL( JPREV ), 1, VL( J ), 1, C, S )K2 = K2 - 1IDXP( K2 ) = JPREVJPREV = JELSEK = K + 1ZW( K ) = Z( JPREV )DSIGMA( K ) = D( JPREV )IDXP( K ) = JPREVJPREV = JEND IFEND IFGO TO 8090 CONTINUE** Record the last singular value.*K = K + 1ZW( K ) = Z( JPREV )DSIGMA( K ) = D( JPREV )IDXP( K ) = JPREV*100 CONTINUE** Sort the singular values into DSIGMA. The singular values which* were not deflated go into the first K slots of DSIGMA, except* that DSIGMA(1) is treated separately.*DO 110 J = 2, NJP = IDXP( J )DSIGMA( J ) = D( JP )VFW( J ) = VF( JP )VLW( J ) = VL( JP )110 CONTINUEIF( ICOMPQ.EQ.1 ) THENDO 120 J = 2, NJP = IDXP( J )PERM( J ) = IDXQ( IDX( JP )+1 )IF( PERM( J ).LE.NLP1 ) THENPERM( J ) = PERM( J ) - 1END IF120 CONTINUEEND IF** The deflated singular values go back into the last N - K slots of* D.*CALL DCOPY( N-K, DSIGMA( K+1 ), 1, D( K+1 ), 1 )** Determine DSIGMA(1), DSIGMA(2), Z(1), VF(1), VL(1), VF(M), and* VL(M).*DSIGMA( 1 ) = ZEROHLFTOL = TOL / TWOIF( ABS( DSIGMA( 2 ) ).LE.HLFTOL )$ DSIGMA( 2 ) = HLFTOLIF( M.GT.N ) THENZ( 1 ) = DLAPY2( Z1, Z( M ) )IF( Z( 1 ).LE.TOL ) THENC = ONES = ZEROZ( 1 ) = TOLELSEC = Z1 / Z( 1 )S = -Z( M ) / Z( 1 )END IFCALL DROT( 1, VF( M ), 1, VF( 1 ), 1, C, S )CALL DROT( 1, VL( M ), 1, VL( 1 ), 1, C, S )ELSEIF( ABS( Z1 ).LE.TOL ) THENZ( 1 ) = TOLELSEZ( 1 ) = Z1END IFEND IF** Restore Z, VF, and VL.*CALL DCOPY( K-1, ZW( 2 ), 1, Z( 2 ), 1 )CALL DCOPY( N-1, VFW( 2 ), 1, VF( 2 ), 1 )CALL DCOPY( N-1, VLW( 2 ), 1, VL( 2 ), 1 )*RETURN** End of DLASD7*ENDSUBROUTINE DLASD8( ICOMPQ, K, D, Z, VF, VL, DIFL, DIFR, LDDIFR,$ DSIGMA, WORK, INFO )** -- LAPACK auxiliary routine (version 3.0) --* Univ. of Tennessee, Oak Ridge National Lab, Argonne National Lab,* Courant Institute, NAG Ltd., and Rice University* June 30, 1999** .. Scalar Arguments ..INTEGER ICOMPQ, INFO, K, LDDIFR* ..* .. Array Arguments ..DOUBLE PRECISION D( * ), DIFL( * ), DIFR( LDDIFR, * ),$ DSIGMA( * ), VF( * ), VL( * ), WORK( * ),$ Z( * )* ..** Purpose* =======** DLASD8 finds the square roots of the roots of the secular equation,* as defined by the values in DSIGMA and Z. It makes the appropriate* calls to DLASD4, and stores, for each element in D, the distance* to its two nearest poles (elements in DSIGMA). It also updates* the arrays VF and VL, the first and last components of all the* right singular vectors of the original bidiagonal matrix.** DLASD8 is called from DLASD6.** Arguments* =========** ICOMPQ (input) INTEGER* Specifies whether singular vectors are to be computed in* factored form in the calling routine:* = 0: Compute singular values only.* = 1: Compute singular vectors in factored form as well.** K (input) INTEGER* The number of terms in the rational function to be solved* by DLASD4. K >= 1.** D (output) DOUBLE PRECISION array, dimension ( K )* On output, D contains the updated singular values.** Z (input) DOUBLE PRECISION array, dimension ( K )* The first K elements of this array contain the components* of the deflation-adjusted updating row vector.** VF (input/output) DOUBLE PRECISION array, dimension ( K )* On entry, VF contains information passed through DBEDE8.* On exit, VF contains the first K components of the first* components of all right singular vectors of the bidiagonal* matrix.** VL (input/output) DOUBLE PRECISION array, dimension ( K )* On entry, VL contains information passed through DBEDE8.* On exit, VL contains the first K components of the last* components of all right singular vectors of the bidiagonal* matrix.** DIFL (output) DOUBLE PRECISION array, dimension ( K )* On exit, DIFL(I) = D(I) - DSIGMA(I).** DIFR (output) DOUBLE PRECISION array,* dimension ( LDDIFR, 2 ) if ICOMPQ = 1 and* dimension ( K ) if ICOMPQ = 0.* On exit, DIFR(I,1) = D(I) - DSIGMA(I+1), DIFR(K,1) is not* defined and will not be referenced.** If ICOMPQ = 1, DIFR(1:K,2) is an array containing the* normalizing factors for the right singular vector matrix.** LDDIFR (input) INTEGER* The leading dimension of DIFR, must be at least K.** DSIGMA (input) DOUBLE PRECISION array, dimension ( K )* The first K elements of this array contain the old roots* of the deflated updating problem. These are the poles* of the secular equation.** WORK (workspace) DOUBLE PRECISION array, dimension at least 3 * K** INFO (output) INTEGER* = 0: successful exit.* < 0: if INFO = -i, the i-th argument had an illegal value.* > 0: if INFO = 1, an singular value did not converge** Further Details* ===============** Based on contributions by* Ming Gu and Huan Ren, Computer Science Division, University of* California at Berkeley, USA** =====================================================================** .. Parameters ..DOUBLE PRECISION ONEPARAMETER ( ONE = 1.0D+0 )* ..* .. Local Scalars ..INTEGER I, IWK1, IWK2, IWK2I, IWK3, IWK3I, JDOUBLE PRECISION DIFLJ, DIFRJ, DJ, DSIGJ, DSIGJP, RHO, TEMP* ..* .. External Subroutines ..EXTERNAL DCOPY, DLASCL, DLASD4, DLASET, XERBLA* ..* .. External Functions ..DOUBLE PRECISION DDOT, DLAMC3, DNRM2EXTERNAL DDOT, DLAMC3, DNRM2* ..* .. Intrinsic Functions ..INTRINSIC ABS, SIGN, SQRT* ..* .. Executable Statements ..** Test the input parameters.*INFO = 0*IF( ( ICOMPQ.LT.0 ) .OR. ( ICOMPQ.GT.1 ) ) THENINFO = -1ELSE IF( K.LT.1 ) THENINFO = -2ELSE IF( LDDIFR.LT.K ) THENINFO = -9END IFIF( INFO.NE.0 ) THENCALL XERBLA( 'DLASD8', -INFO )RETURNEND IF** Quick return if possible*IF( K.EQ.1 ) THEND( 1 ) = ABS( Z( 1 ) )DIFL( 1 ) = D( 1 )IF( ICOMPQ.EQ.1 ) THENDIFL( 2 ) = ONEDIFR( 1, 2 ) = ONEEND IFRETURNEND IF** Modify values DSIGMA(i) to make sure all DSIGMA(i)-DSIGMA(j) can* be computed with high relative accuracy (barring over/underflow).* This is a problem on machines without a guard digit in* add/subtract (Cray XMP, Cray YMP, Cray C 90 and Cray 2).* The following code replaces DSIGMA(I) by 2*DSIGMA(I)-DSIGMA(I),* which on any of these machines zeros out the bottommost* bit of DSIGMA(I) if it is 1; this makes the subsequent* subtractions DSIGMA(I)-DSIGMA(J) unproblematic when cancellation* occurs. On binary machines with a guard digit (almost all* machines) it does not change DSIGMA(I) at all. On hexadecimal* and decimal machines with a guard digit, it slightly* changes the bottommost bits of DSIGMA(I). It does not account* for hexadecimal or decimal machines without guard digits* (we know of none). We use a subroutine call to compute* 2*DLAMBDA(I) to prevent optimizing compilers from eliminating* this code.*DO 10 I = 1, KDSIGMA( I ) = DLAMC3( DSIGMA( I ), DSIGMA( I ) ) - DSIGMA( I )10 CONTINUE** Book keeping.*IWK1 = 1IWK2 = IWK1 + KIWK3 = IWK2 + KIWK2I = IWK2 - 1IWK3I = IWK3 - 1** Normalize Z.*RHO = DNRM2( K, Z, 1 )CALL DLASCL( 'G', 0, 0, RHO, ONE, K, 1, Z, K, INFO )RHO = RHO*RHO** Initialize WORK(IWK3).*CALL DLASET( 'A', K, 1, ONE, ONE, WORK( IWK3 ), K )** Compute the updated singular values, the arrays DIFL, DIFR,* and the updated Z.*DO 40 J = 1, KCALL DLASD4( K, J, DSIGMA, Z, WORK( IWK1 ), RHO, D( J ),$ WORK( IWK2 ), INFO )** If the root finder fails, the computation is terminated.*IF( INFO.NE.0 ) THENRETURNEND IFWORK( IWK3I+J ) = WORK( IWK3I+J )*WORK( J )*WORK( IWK2I+J )DIFL( J ) = -WORK( J )DIFR( J, 1 ) = -WORK( J+1 )DO 20 I = 1, J - 1WORK( IWK3I+I ) = WORK( IWK3I+I )*WORK( I )*$ WORK( IWK2I+I ) / ( DSIGMA( I )-$ DSIGMA( J ) ) / ( DSIGMA( I )+$ DSIGMA( J ) )20 CONTINUEDO 30 I = J + 1, KWORK( IWK3I+I ) = WORK( IWK3I+I )*WORK( I )*$ WORK( IWK2I+I ) / ( DSIGMA( I )-$ DSIGMA( J ) ) / ( DSIGMA( I )+$ DSIGMA( J ) )30 CONTINUE40 CONTINUE** Compute updated Z.*DO 50 I = 1, KZ( I ) = SIGN( SQRT( ABS( WORK( IWK3I+I ) ) ), Z( I ) )50 CONTINUE** Update VF and VL.*DO 80 J = 1, KDIFLJ = DIFL( J )DJ = D( J )DSIGJ = -DSIGMA( J )IF( J.LT.K ) THENDIFRJ = -DIFR( J, 1 )DSIGJP = -DSIGMA( J+1 )END IFWORK( J ) = -Z( J ) / DIFLJ / ( DSIGMA( J )+DJ )DO 60 I = 1, J - 1WORK( I ) = Z( I ) / ( DLAMC3( DSIGMA( I ), DSIGJ )-DIFLJ )$ / ( DSIGMA( I )+DJ )60 CONTINUEDO 70 I = J + 1, KWORK( I ) = Z( I ) / ( DLAMC3( DSIGMA( I ), DSIGJP )+DIFRJ )$ / ( DSIGMA( I )+DJ )70 CONTINUETEMP = DNRM2( K, WORK, 1 )WORK( IWK2I+J ) = DDOT( K, WORK, 1, VF, 1 ) / TEMPWORK( IWK3I+J ) = DDOT( K, WORK, 1, VL, 1 ) / TEMPIF( ICOMPQ.EQ.1 ) THENDIFR( J, 2 ) = TEMPEND IF80 CONTINUE*CALL DCOPY( K, WORK( IWK2 ), 1, VF, 1 )CALL DCOPY( K, WORK( IWK3 ), 1, VL, 1 )*RETURN** End of DLASD8*ENDSUBROUTINE DLAMRG( N1, N2, A, DTRD1, DTRD2, INDEX )** -- LAPACK routine (version 3.0) --* Univ. of Tennessee, Univ. of California Berkeley, NAG Ltd.,* Courant Institute, Argonne National Lab, and Rice University* September 30, 1994** .. Scalar Arguments ..INTEGER DTRD1, DTRD2, N1, N2* ..* .. Array Arguments ..INTEGER INDEX( * )DOUBLE PRECISION A( * )* ..** Purpose* =======** DLAMRG will create a permutation list which will merge the elements* of A (which is composed of two independently sorted sets) into a* single set which is sorted in ascending order.** Arguments* =========** N1 (input) INTEGER* N2 (input) INTEGER* These arguements contain the respective lengths of the two* sorted lists to be merged.** A (input) DOUBLE PRECISION array, dimension (N1+N2)* The first N1 elements of A contain a list of numbers which* are sorted in either ascending or descending order. Likewise* for the final N2 elements.** DTRD1 (input) INTEGER* DTRD2 (input) INTEGER* These are the strides to be taken through the array A.* Allowable strides are 1 and -1. They indicate whether a* subset of A is sorted in ascending (DTRDx = 1) or descending* (DTRDx = -1) order.** INDEX (output) INTEGER array, dimension (N1+N2)* On exit this array will contain a permutation such that* if B( I ) = A( INDEX( I ) ) for I=1,N1+N2, then B will be* sorted in ascending order.** =====================================================================** .. Local Scalars ..INTEGER I, IND1, IND2, N1SV, N2SV* ..* .. Executable Statements ..*N1SV = N1N2SV = N2IF( DTRD1.GT.0 ) THENIND1 = 1ELSEIND1 = N1END IFIF( DTRD2.GT.0 ) THENIND2 = 1 + N1ELSEIND2 = N1 + N2END IFI = 1* while ( (N1SV > 0) & (N2SV > 0) )10 CONTINUEIF( N1SV.GT.0 .AND. N2SV.GT.0 ) THENIF( A( IND1 ).LE.A( IND2 ) ) THENINDEX( I ) = IND1I = I + 1IND1 = IND1 + DTRD1N1SV = N1SV - 1ELSEINDEX( I ) = IND2I = I + 1IND2 = IND2 + DTRD2N2SV = N2SV - 1END IFGO TO 10END IF* end whileIF( N1SV.EQ.0 ) THENDO 20 N1SV = 1, N2SVINDEX( I ) = IND2I = I + 1IND2 = IND2 + DTRD220 CONTINUEELSE* N2SV .EQ. 0DO 30 N2SV = 1, N1SVINDEX( I ) = IND1I = I + 1IND1 = IND1 + DTRD130 CONTINUEEND IF*RETURN** End of DLAMRG*ENDSUBROUTINE DLASD4( N, I, D, Z, DELTA, RHO, SIGMA, WORK, INFO )** -- LAPACK auxiliary routine (version 3.0) --* Univ. of Tennessee, Oak Ridge National Lab, Argonne National Lab,* Courant Institute, NAG Ltd., and Rice University* October 31, 1999** .. Scalar Arguments ..INTEGER I, INFO, NDOUBLE PRECISION RHO, SIGMA* ..* .. Array Arguments ..DOUBLE PRECISION D( * ), DELTA( * ), WORK( * ), Z( * )* ..** Purpose* =======** This subroutine computes the square root of the I-th updated* eigenvalue of a positive symmetric rank-one modification to* a positive diagonal matrix whose entries are given as the squares* of the corresponding entries in the array d, and that** 0 <= D(i) < D(j) for i < j** and that RHO > 0. This is arranged by the calling routine, and is* no loss in generality. The rank-one modified system is thus** diag( D ) * diag( D ) + RHO * Z * Z_transpose.** where we assume the Euclidean norm of Z is 1.** The method consists of approximating the rational functions in the* secular equation by simpler interpolating rational functions.** Arguments* =========** N (input) INTEGER* The length of all arrays.** I (input) INTEGER* The index of the eigenvalue to be computed. 1 <= I <= N.** D (input) DOUBLE PRECISION array, dimension ( N )* The original eigenvalues. It is assumed that they are in* order, 0 <= D(I) < D(J) for I < J.** Z (input) DOUBLE PRECISION array, dimension ( N )* The components of the updating vector.** DELTA (output) DOUBLE PRECISION array, dimension ( N )* If N .ne. 1, DELTA contains (D(j) - sigma_I) in its j-th* component. If N = 1, then DELTA(1) = 1. The vector DELTA* contains the information necessary to construct the* (singular) eigenvectors.** RHO (input) DOUBLE PRECISION* The scalar in the symmetric updating formula.** SIGMA (output) DOUBLE PRECISION* The computed lambda_I, the I-th updated eigenvalue.** WORK (workspace) DOUBLE PRECISION array, dimension ( N )* If N .ne. 1, WORK contains (D(j) + sigma_I) in its j-th* component. If N = 1, then WORK( 1 ) = 1.** INFO (output) INTEGER* = 0: successful exit* > 0: if INFO = 1, the updating process failed.** Internal Parameters* ===================** Logical variable ORGATI (origin-at-i?) is used for distinguishing* whether D(i) or D(i+1) is treated as the origin.** ORGATI = .true. origin at i* ORGATI = .false. origin at i+1** Logical variable SWTCH3 (switch-for-3-poles?) is for noting* if we are working with THREE poles!** MAXIT is the maximum number of iterations allowed for each* eigenvalue.** Further Details* ===============** Based on contributions by* Ren-Cang Li, Computer Science Division, University of California* at Berkeley, USA** =====================================================================** .. Parameters ..INTEGER MAXITPARAMETER ( MAXIT = 20 )DOUBLE PRECISION ZERO, ONE, TWO, THREE, FOUR, EIGHT, TENPARAMETER ( ZERO = 0.0D+0, ONE = 1.0D+0, TWO = 2.0D+0,$ THREE = 3.0D+0, FOUR = 4.0D+0, EIGHT = 8.0D+0,$ TEN = 10.0D+0 )* ..* .. Local Scalars ..LOGICAL ORGATI, SWTCH, SWTCH3INTEGER II, IIM1, IIP1, IP1, ITER, J, NITERDOUBLE PRECISION A, B, C, DELSQ, DELSQ2, DPHI, DPSI, DTIIM,$ DTIIP, DTIPSQ, DTISQ, DTNSQ, DTNSQ1, DW, EPS,$ ERRETM, ETA, PHI, PREW, PSI, RHOINV, SG2LB,$ SG2UB, TAU, TEMP, TEMP1, TEMP2, W* ..* .. Local Arrays ..DOUBLE PRECISION DD( 3 ), ZZ( 3 )* ..* .. External Subroutines ..EXTERNAL DLAED6, DLASD5* ..* .. External Functions ..DOUBLE PRECISION DLAMCHEXTERNAL DLAMCH* ..* .. Intrinsic Functions ..INTRINSIC ABS, MAX, MIN, SQRT* ..* .. Executable Statements ..** Since this routine is called in an inner loop, we do no argument* checking.** Quick return for N=1 and 2.*INFO = 0IF( N.EQ.1 ) THEN** Presumably, I=1 upon entry*SIGMA = SQRT( D( 1 )*D( 1 )+RHO*Z( 1 )*Z( 1 ) )DELTA( 1 ) = ONEWORK( 1 ) = ONERETURNEND IFIF( N.EQ.2 ) THENCALL DLASD5( I, D, Z, DELTA, RHO, SIGMA, WORK )RETURNEND IF** Compute machine epsilon*EPS = DLAMCH( 'Epsilon' )RHOINV = ONE / RHO** The case I = N*IF( I.EQ.N ) THEN** Initialize some basic variables*II = N - 1NITER = 1** Calculate initial guess*TEMP = RHO / TWO** If ||Z||_2 is not one, then TEMP should be set to* RHO * ||Z||_2^2 / TWO*TEMP1 = TEMP / ( D( N )+SQRT( D( N )*D( N )+TEMP ) )DO 10 J = 1, NWORK( J ) = D( J ) + D( N ) + TEMP1DELTA( J ) = ( D( J )-D( N ) ) - TEMP110 CONTINUE*PSI = ZERODO 20 J = 1, N - 2PSI = PSI + Z( J )*Z( J ) / ( DELTA( J )*WORK( J ) )20 CONTINUE*C = RHOINV + PSIW = C + Z( II )*Z( II ) / ( DELTA( II )*WORK( II ) ) +$ Z( N )*Z( N ) / ( DELTA( N )*WORK( N ) )*IF( W.LE.ZERO ) THENTEMP1 = SQRT( D( N )*D( N )+RHO )TEMP = Z( N-1 )*Z( N-1 ) / ( ( D( N-1 )+TEMP1 )*$ ( D( N )-D( N-1 )+RHO / ( D( N )+TEMP1 ) ) ) +$ Z( N )*Z( N ) / RHO** The following TAU is to approximate* SIGMA_n^2 - D( N )*D( N )*IF( C.LE.TEMP ) THENTAU = RHOELSEDELSQ = ( D( N )-D( N-1 ) )*( D( N )+D( N-1 ) )A = -C*DELSQ + Z( N-1 )*Z( N-1 ) + Z( N )*Z( N )B = Z( N )*Z( N )*DELSQIF( A.LT.ZERO ) THENTAU = TWO*B / ( SQRT( A*A+FOUR*B*C )-A )ELSETAU = ( A+SQRT( A*A+FOUR*B*C ) ) / ( TWO*C )END IFEND IF** It can be proved that* D(N)^2+RHO/2 <= SIGMA_n^2 < D(N)^2+TAU <= D(N)^2+RHO*ELSEDELSQ = ( D( N )-D( N-1 ) )*( D( N )+D( N-1 ) )A = -C*DELSQ + Z( N-1 )*Z( N-1 ) + Z( N )*Z( N )B = Z( N )*Z( N )*DELSQ** The following TAU is to approximate* SIGMA_n^2 - D( N )*D( N )*IF( A.LT.ZERO ) THENTAU = TWO*B / ( SQRT( A*A+FOUR*B*C )-A )ELSETAU = ( A+SQRT( A*A+FOUR*B*C ) ) / ( TWO*C )END IF** It can be proved that* D(N)^2 < D(N)^2+TAU < SIGMA(N)^2 < D(N)^2+RHO/2*END IF** The following ETA is to approximate SIGMA_n - D( N )*ETA = TAU / ( D( N )+SQRT( D( N )*D( N )+TAU ) )*SIGMA = D( N ) + ETADO 30 J = 1, NDELTA( J ) = ( D( J )-D( I ) ) - ETAWORK( J ) = D( J ) + D( I ) + ETA30 CONTINUE** Evaluate PSI and the derivative DPSI*DPSI = ZEROPSI = ZEROERRETM = ZERODO 40 J = 1, IITEMP = Z( J ) / ( DELTA( J )*WORK( J ) )PSI = PSI + Z( J )*TEMPDPSI = DPSI + TEMP*TEMPERRETM = ERRETM + PSI40 CONTINUEERRETM = ABS( ERRETM )** Evaluate PHI and the derivative DPHI*TEMP = Z( N ) / ( DELTA( N )*WORK( N ) )PHI = Z( N )*TEMPDPHI = TEMP*TEMPERRETM = EIGHT*( -PHI-PSI ) + ERRETM - PHI + RHOINV +$ ABS( TAU )*( DPSI+DPHI )*W = RHOINV + PHI + PSI** Test for convergence*IF( ABS( W ).LE.EPS*ERRETM ) THENGO TO 240END IF** Calculate the new step*NITER = NITER + 1DTNSQ1 = WORK( N-1 )*DELTA( N-1 )DTNSQ = WORK( N )*DELTA( N )C = W - DTNSQ1*DPSI - DTNSQ*DPHIA = ( DTNSQ+DTNSQ1 )*W - DTNSQ*DTNSQ1*( DPSI+DPHI )B = DTNSQ*DTNSQ1*WIF( C.LT.ZERO )$ C = ABS( C )IF( C.EQ.ZERO ) THENETA = RHO - SIGMA*SIGMAELSE IF( A.GE.ZERO ) THENETA = ( A+SQRT( ABS( A*A-FOUR*B*C ) ) ) / ( TWO*C )ELSEETA = TWO*B / ( A-SQRT( ABS( A*A-FOUR*B*C ) ) )END IF** Note, eta should be positive if w is negative, and* eta should be negative otherwise. However,* if for some reason caused by roundoff, eta*w > 0,* we simply use one Newton step instead. This way* will guarantee eta*w < 0.*IF( W*ETA.GT.ZERO )$ ETA = -W / ( DPSI+DPHI )TEMP = ETA - DTNSQIF( TEMP.GT.RHO )$ ETA = RHO + DTNSQ*TAU = TAU + ETAETA = ETA / ( SIGMA+SQRT( ETA+SIGMA*SIGMA ) )DO 50 J = 1, NDELTA( J ) = DELTA( J ) - ETAWORK( J ) = WORK( J ) + ETA50 CONTINUE*SIGMA = SIGMA + ETA** Evaluate PSI and the derivative DPSI*DPSI = ZEROPSI = ZEROERRETM = ZERODO 60 J = 1, IITEMP = Z( J ) / ( WORK( J )*DELTA( J ) )PSI = PSI + Z( J )*TEMPDPSI = DPSI + TEMP*TEMPERRETM = ERRETM + PSI60 CONTINUEERRETM = ABS( ERRETM )** Evaluate PHI and the derivative DPHI*TEMP = Z( N ) / ( WORK( N )*DELTA( N ) )PHI = Z( N )*TEMPDPHI = TEMP*TEMPERRETM = EIGHT*( -PHI-PSI ) + ERRETM - PHI + RHOINV +$ ABS( TAU )*( DPSI+DPHI )*W = RHOINV + PHI + PSI** Main loop to update the values of the array DELTA*ITER = NITER + 1*DO 90 NITER = ITER, MAXIT** Test for convergence*IF( ABS( W ).LE.EPS*ERRETM ) THENGO TO 240END IF** Calculate the new step*DTNSQ1 = WORK( N-1 )*DELTA( N-1 )DTNSQ = WORK( N )*DELTA( N )C = W - DTNSQ1*DPSI - DTNSQ*DPHIA = ( DTNSQ+DTNSQ1 )*W - DTNSQ1*DTNSQ*( DPSI+DPHI )B = DTNSQ1*DTNSQ*WIF( A.GE.ZERO ) THENETA = ( A+SQRT( ABS( A*A-FOUR*B*C ) ) ) / ( TWO*C )ELSEETA = TWO*B / ( A-SQRT( ABS( A*A-FOUR*B*C ) ) )END IF** Note, eta should be positive if w is negative, and* eta should be negative otherwise. However,* if for some reason caused by roundoff, eta*w > 0,* we simply use one Newton step instead. This way* will guarantee eta*w < 0.*IF( W*ETA.GT.ZERO )$ ETA = -W / ( DPSI+DPHI )TEMP = ETA - DTNSQIF( TEMP.LE.ZERO )$ ETA = ETA / TWO*TAU = TAU + ETAETA = ETA / ( SIGMA+SQRT( ETA+SIGMA*SIGMA ) )DO 70 J = 1, NDELTA( J ) = DELTA( J ) - ETAWORK( J ) = WORK( J ) + ETA70 CONTINUE*SIGMA = SIGMA + ETA** Evaluate PSI and the derivative DPSI*DPSI = ZEROPSI = ZEROERRETM = ZERODO 80 J = 1, IITEMP = Z( J ) / ( WORK( J )*DELTA( J ) )PSI = PSI + Z( J )*TEMPDPSI = DPSI + TEMP*TEMPERRETM = ERRETM + PSI80 CONTINUEERRETM = ABS( ERRETM )** Evaluate PHI and the derivative DPHI*TEMP = Z( N ) / ( WORK( N )*DELTA( N ) )PHI = Z( N )*TEMPDPHI = TEMP*TEMPERRETM = EIGHT*( -PHI-PSI ) + ERRETM - PHI + RHOINV +$ ABS( TAU )*( DPSI+DPHI )*W = RHOINV + PHI + PSI90 CONTINUE** Return with INFO = 1, NITER = MAXIT and not converged*INFO = 1GO TO 240** End for the case I = N*ELSE** The case for I < N*NITER = 1IP1 = I + 1** Calculate initial guess*DELSQ = ( D( IP1 )-D( I ) )*( D( IP1 )+D( I ) )DELSQ2 = DELSQ / TWOTEMP = DELSQ2 / ( D( I )+SQRT( D( I )*D( I )+DELSQ2 ) )DO 100 J = 1, NWORK( J ) = D( J ) + D( I ) + TEMPDELTA( J ) = ( D( J )-D( I ) ) - TEMP100 CONTINUE*PSI = ZERODO 110 J = 1, I - 1PSI = PSI + Z( J )*Z( J ) / ( WORK( J )*DELTA( J ) )110 CONTINUE*PHI = ZERODO 120 J = N, I + 2, -1PHI = PHI + Z( J )*Z( J ) / ( WORK( J )*DELTA( J ) )120 CONTINUEC = RHOINV + PSI + PHIW = C + Z( I )*Z( I ) / ( WORK( I )*DELTA( I ) ) +$ Z( IP1 )*Z( IP1 ) / ( WORK( IP1 )*DELTA( IP1 ) )*IF( W.GT.ZERO ) THEN** d(i)^2 < the ith sigma^2 < (d(i)^2+d(i+1)^2)/2** We choose d(i) as origin.*ORGATI = .TRUE.SG2LB = ZEROSG2UB = DELSQ2A = C*DELSQ + Z( I )*Z( I ) + Z( IP1 )*Z( IP1 )B = Z( I )*Z( I )*DELSQIF( A.GT.ZERO ) THENTAU = TWO*B / ( A+SQRT( ABS( A*A-FOUR*B*C ) ) )ELSETAU = ( A-SQRT( ABS( A*A-FOUR*B*C ) ) ) / ( TWO*C )END IF** TAU now is an estimation of SIGMA^2 - D( I )^2. The* following, however, is the corresponding estimation of* SIGMA - D( I ).*ETA = TAU / ( D( I )+SQRT( D( I )*D( I )+TAU ) )ELSE** (d(i)^2+d(i+1)^2)/2 <= the ith sigma^2 < d(i+1)^2/2** We choose d(i+1) as origin.*ORGATI = .FALSE.SG2LB = -DELSQ2SG2UB = ZEROA = C*DELSQ - Z( I )*Z( I ) - Z( IP1 )*Z( IP1 )B = Z( IP1 )*Z( IP1 )*DELSQIF( A.LT.ZERO ) THENTAU = TWO*B / ( A-SQRT( ABS( A*A+FOUR*B*C ) ) )ELSETAU = -( A+SQRT( ABS( A*A+FOUR*B*C ) ) ) / ( TWO*C )END IF** TAU now is an estimation of SIGMA^2 - D( IP1 )^2. The* following, however, is the corresponding estimation of* SIGMA - D( IP1 ).*ETA = TAU / ( D( IP1 )+SQRT( ABS( D( IP1 )*D( IP1 )+$ TAU ) ) )END IF*IF( ORGATI ) THENII = ISIGMA = D( I ) + ETADO 130 J = 1, NWORK( J ) = D( J ) + D( I ) + ETADELTA( J ) = ( D( J )-D( I ) ) - ETA130 CONTINUEELSEII = I + 1SIGMA = D( IP1 ) + ETADO 140 J = 1, NWORK( J ) = D( J ) + D( IP1 ) + ETADELTA( J ) = ( D( J )-D( IP1 ) ) - ETA140 CONTINUEEND IFIIM1 = II - 1IIP1 = II + 1** Evaluate PSI and the derivative DPSI*DPSI = ZEROPSI = ZEROERRETM = ZERODO 150 J = 1, IIM1TEMP = Z( J ) / ( WORK( J )*DELTA( J ) )PSI = PSI + Z( J )*TEMPDPSI = DPSI + TEMP*TEMPERRETM = ERRETM + PSI150 CONTINUEERRETM = ABS( ERRETM )** Evaluate PHI and the derivative DPHI*DPHI = ZEROPHI = ZERODO 160 J = N, IIP1, -1TEMP = Z( J ) / ( WORK( J )*DELTA( J ) )PHI = PHI + Z( J )*TEMPDPHI = DPHI + TEMP*TEMPERRETM = ERRETM + PHI160 CONTINUE*W = RHOINV + PHI + PSI** W is the value of the secular function with* its ii-th element removed.*SWTCH3 = .FALSE.IF( ORGATI ) THENIF( W.LT.ZERO )$ SWTCH3 = .TRUE.ELSEIF( W.GT.ZERO )$ SWTCH3 = .TRUE.END IFIF( II.EQ.1 .OR. II.EQ.N )$ SWTCH3 = .FALSE.*TEMP = Z( II ) / ( WORK( II )*DELTA( II ) )DW = DPSI + DPHI + TEMP*TEMPTEMP = Z( II )*TEMPW = W + TEMPERRETM = EIGHT*( PHI-PSI ) + ERRETM + TWO*RHOINV +$ THREE*ABS( TEMP ) + ABS( TAU )*DW** Test for convergence*IF( ABS( W ).LE.EPS*ERRETM ) THENGO TO 240END IF*IF( W.LE.ZERO ) THENSG2LB = MAX( SG2LB, TAU )ELSESG2UB = MIN( SG2UB, TAU )END IF** Calculate the new step*NITER = NITER + 1IF( .NOT.SWTCH3 ) THENDTIPSQ = WORK( IP1 )*DELTA( IP1 )DTISQ = WORK( I )*DELTA( I )IF( ORGATI ) THENC = W - DTIPSQ*DW + DELSQ*( Z( I ) / DTISQ )**2ELSEC = W - DTISQ*DW - DELSQ*( Z( IP1 ) / DTIPSQ )**2END IFA = ( DTIPSQ+DTISQ )*W - DTIPSQ*DTISQ*DWB = DTIPSQ*DTISQ*WIF( C.EQ.ZERO ) THENIF( A.EQ.ZERO ) THENIF( ORGATI ) THENA = Z( I )*Z( I ) + DTIPSQ*DTIPSQ*( DPSI+DPHI )ELSEA = Z( IP1 )*Z( IP1 ) + DTISQ*DTISQ*( DPSI+DPHI )END IFEND IFETA = B / AELSE IF( A.LE.ZERO ) THENETA = ( A-SQRT( ABS( A*A-FOUR*B*C ) ) ) / ( TWO*C )ELSEETA = TWO*B / ( A+SQRT( ABS( A*A-FOUR*B*C ) ) )END IFELSE** Interpolation using THREE most relevant poles*DTIIM = WORK( IIM1 )*DELTA( IIM1 )DTIIP = WORK( IIP1 )*DELTA( IIP1 )TEMP = RHOINV + PSI + PHIIF( ORGATI ) THENTEMP1 = Z( IIM1 ) / DTIIMTEMP1 = TEMP1*TEMP1C = ( TEMP - DTIIP*( DPSI+DPHI ) ) -$ ( D( IIM1 )-D( IIP1 ) )*( D( IIM1 )+D( IIP1 ) )*TEMP1ZZ( 1 ) = Z( IIM1 )*Z( IIM1 )IF( DPSI.LT.TEMP1 ) THENZZ( 3 ) = DTIIP*DTIIP*DPHIELSEZZ( 3 ) = DTIIP*DTIIP*( ( DPSI-TEMP1 )+DPHI )END IFELSETEMP1 = Z( IIP1 ) / DTIIPTEMP1 = TEMP1*TEMP1C = ( TEMP - DTIIM*( DPSI+DPHI ) ) -$ ( D( IIP1 )-D( IIM1 ) )*( D( IIM1 )+D( IIP1 ) )*TEMP1IF( DPHI.LT.TEMP1 ) THENZZ( 1 ) = DTIIM*DTIIM*DPSIELSEZZ( 1 ) = DTIIM*DTIIM*( DPSI+( DPHI-TEMP1 ) )END IFZZ( 3 ) = Z( IIP1 )*Z( IIP1 )END IFZZ( 2 ) = Z( II )*Z( II )DD( 1 ) = DTIIMDD( 2 ) = DELTA( II )*WORK( II )DD( 3 ) = DTIIPCALL DLAED6( NITER, ORGATI, C, DD, ZZ, W, ETA, INFO )IF( INFO.NE.0 )$ GO TO 240END IF** Note, eta should be positive if w is negative, and* eta should be negative otherwise. However,* if for some reason caused by roundoff, eta*w > 0,* we simply use one Newton step instead. This way* will guarantee eta*w < 0.*IF( W*ETA.GE.ZERO )$ ETA = -W / DWIF( ORGATI ) THENTEMP1 = WORK( I )*DELTA( I )TEMP = ETA - TEMP1ELSETEMP1 = WORK( IP1 )*DELTA( IP1 )TEMP = ETA - TEMP1END IFIF( TEMP.GT.SG2UB .OR. TEMP.LT.SG2LB ) THENIF( W.LT.ZERO ) THENETA = ( SG2UB-TAU ) / TWOELSEETA = ( SG2LB-TAU ) / TWOEND IFEND IF*TAU = TAU + ETAETA = ETA / ( SIGMA+SQRT( SIGMA*SIGMA+ETA ) )*PREW = W*SIGMA = SIGMA + ETADO 170 J = 1, NWORK( J ) = WORK( J ) + ETADELTA( J ) = DELTA( J ) - ETA170 CONTINUE** Evaluate PSI and the derivative DPSI*DPSI = ZEROPSI = ZEROERRETM = ZERODO 180 J = 1, IIM1TEMP = Z( J ) / ( WORK( J )*DELTA( J ) )PSI = PSI + Z( J )*TEMPDPSI = DPSI + TEMP*TEMPERRETM = ERRETM + PSI180 CONTINUEERRETM = ABS( ERRETM )** Evaluate PHI and the derivative DPHI*DPHI = ZEROPHI = ZERODO 190 J = N, IIP1, -1TEMP = Z( J ) / ( WORK( J )*DELTA( J ) )PHI = PHI + Z( J )*TEMPDPHI = DPHI + TEMP*TEMPERRETM = ERRETM + PHI190 CONTINUE*TEMP = Z( II ) / ( WORK( II )*DELTA( II ) )DW = DPSI + DPHI + TEMP*TEMPTEMP = Z( II )*TEMPW = RHOINV + PHI + PSI + TEMPERRETM = EIGHT*( PHI-PSI ) + ERRETM + TWO*RHOINV +$ THREE*ABS( TEMP ) + ABS( TAU )*DW*IF( W.LE.ZERO ) THENSG2LB = MAX( SG2LB, TAU )ELSESG2UB = MIN( SG2UB, TAU )END IF*SWTCH = .FALSE.IF( ORGATI ) THENIF( -W.GT.ABS( PREW ) / TEN )$ SWTCH = .TRUE.ELSEIF( W.GT.ABS( PREW ) / TEN )$ SWTCH = .TRUE.END IF** Main loop to update the values of the array DELTA and WORK*ITER = NITER + 1*DO 230 NITER = ITER, MAXIT** Test for convergence*IF( ABS( W ).LE.EPS*ERRETM ) THENGO TO 240END IF** Calculate the new step*IF( .NOT.SWTCH3 ) THENDTIPSQ = WORK( IP1 )*DELTA( IP1 )DTISQ = WORK( I )*DELTA( I )IF( .NOT.SWTCH ) THENIF( ORGATI ) THENC = W - DTIPSQ*DW + DELSQ*( Z( I ) / DTISQ )**2ELSEC = W - DTISQ*DW - DELSQ*( Z( IP1 ) / DTIPSQ )**2END IFELSETEMP = Z( II ) / ( WORK( II )*DELTA( II ) )IF( ORGATI ) THENDPSI = DPSI + TEMP*TEMPELSEDPHI = DPHI + TEMP*TEMPEND IFC = W - DTISQ*DPSI - DTIPSQ*DPHIEND IFA = ( DTIPSQ+DTISQ )*W - DTIPSQ*DTISQ*DWB = DTIPSQ*DTISQ*WIF( C.EQ.ZERO ) THENIF( A.EQ.ZERO ) THENIF( .NOT.SWTCH ) THENIF( ORGATI ) THENA = Z( I )*Z( I ) + DTIPSQ*DTIPSQ*$ ( DPSI+DPHI )ELSEA = Z( IP1 )*Z( IP1 ) +$ DTISQ*DTISQ*( DPSI+DPHI )END IFELSEA = DTISQ*DTISQ*DPSI + DTIPSQ*DTIPSQ*DPHIEND IFEND IFETA = B / AELSE IF( A.LE.ZERO ) THENETA = ( A-SQRT( ABS( A*A-FOUR*B*C ) ) ) / ( TWO*C )ELSEETA = TWO*B / ( A+SQRT( ABS( A*A-FOUR*B*C ) ) )END IFELSE** Interpolation using THREE most relevant poles*DTIIM = WORK( IIM1 )*DELTA( IIM1 )DTIIP = WORK( IIP1 )*DELTA( IIP1 )TEMP = RHOINV + PSI + PHIIF( SWTCH ) THENC = TEMP - DTIIM*DPSI - DTIIP*DPHIZZ( 1 ) = DTIIM*DTIIM*DPSIZZ( 3 ) = DTIIP*DTIIP*DPHIELSEIF( ORGATI ) THENTEMP1 = Z( IIM1 ) / DTIIMTEMP1 = TEMP1*TEMP1TEMP2 = ( D( IIM1 )-D( IIP1 ) )*$ ( D( IIM1 )+D( IIP1 ) )*TEMP1C = TEMP - DTIIP*( DPSI+DPHI ) - TEMP2ZZ( 1 ) = Z( IIM1 )*Z( IIM1 )IF( DPSI.LT.TEMP1 ) THENZZ( 3 ) = DTIIP*DTIIP*DPHIELSEZZ( 3 ) = DTIIP*DTIIP*( ( DPSI-TEMP1 )+DPHI )END IFELSETEMP1 = Z( IIP1 ) / DTIIPTEMP1 = TEMP1*TEMP1TEMP2 = ( D( IIP1 )-D( IIM1 ) )*$ ( D( IIM1 )+D( IIP1 ) )*TEMP1C = TEMP - DTIIM*( DPSI+DPHI ) - TEMP2IF( DPHI.LT.TEMP1 ) THENZZ( 1 ) = DTIIM*DTIIM*DPSIELSEZZ( 1 ) = DTIIM*DTIIM*( DPSI+( DPHI-TEMP1 ) )END IFZZ( 3 ) = Z( IIP1 )*Z( IIP1 )END IFEND IFDD( 1 ) = DTIIMDD( 2 ) = DELTA( II )*WORK( II )DD( 3 ) = DTIIPCALL DLAED6( NITER, ORGATI, C, DD, ZZ, W, ETA, INFO )IF( INFO.NE.0 )$ GO TO 240END IF** Note, eta should be positive if w is negative, and* eta should be negative otherwise. However,* if for some reason caused by roundoff, eta*w > 0,* we simply use one Newton step instead. This way* will guarantee eta*w < 0.*IF( W*ETA.GE.ZERO )$ ETA = -W / DWIF( ORGATI ) THENTEMP1 = WORK( I )*DELTA( I )TEMP = ETA - TEMP1ELSETEMP1 = WORK( IP1 )*DELTA( IP1 )TEMP = ETA - TEMP1END IFIF( TEMP.GT.SG2UB .OR. TEMP.LT.SG2LB ) THENIF( W.LT.ZERO ) THENETA = ( SG2UB-TAU ) / TWOELSEETA = ( SG2LB-TAU ) / TWOEND IFEND IF*TAU = TAU + ETAETA = ETA / ( SIGMA+SQRT( SIGMA*SIGMA+ETA ) )*SIGMA = SIGMA + ETADO 200 J = 1, NWORK( J ) = WORK( J ) + ETADELTA( J ) = DELTA( J ) - ETA200 CONTINUE*PREW = W** Evaluate PSI and the derivative DPSI*DPSI = ZEROPSI = ZEROERRETM = ZERODO 210 J = 1, IIM1TEMP = Z( J ) / ( WORK( J )*DELTA( J ) )PSI = PSI + Z( J )*TEMPDPSI = DPSI + TEMP*TEMPERRETM = ERRETM + PSI210 CONTINUEERRETM = ABS( ERRETM )** Evaluate PHI and the derivative DPHI*DPHI = ZEROPHI = ZERODO 220 J = N, IIP1, -1TEMP = Z( J ) / ( WORK( J )*DELTA( J ) )PHI = PHI + Z( J )*TEMPDPHI = DPHI + TEMP*TEMPERRETM = ERRETM + PHI220 CONTINUE*TEMP = Z( II ) / ( WORK( II )*DELTA( II ) )DW = DPSI + DPHI + TEMP*TEMPTEMP = Z( II )*TEMPW = RHOINV + PHI + PSI + TEMPERRETM = EIGHT*( PHI-PSI ) + ERRETM + TWO*RHOINV +$ THREE*ABS( TEMP ) + ABS( TAU )*DWIF( W*PREW.GT.ZERO .AND. ABS( W ).GT.ABS( PREW ) / TEN )$ SWTCH = .NOT.SWTCH*IF( W.LE.ZERO ) THENSG2LB = MAX( SG2LB, TAU )ELSESG2UB = MIN( SG2UB, TAU )END IF*230 CONTINUE** Return with INFO = 1, NITER = MAXIT and not converged*INFO = 1*END IF*240 CONTINUERETURN** End of DLASD4*ENDSUBROUTINE DLASD5( I, D, Z, DELTA, RHO, DSIGMA, WORK )** -- LAPACK auxiliary routine (version 3.0) --* Univ. of Tennessee, Oak Ridge National Lab, Argonne National Lab,* Courant Institute, NAG Ltd., and Rice University* June 30, 1999** .. Scalar Arguments ..INTEGER IDOUBLE PRECISION DSIGMA, RHO* ..* .. Array Arguments ..DOUBLE PRECISION D( 2 ), DELTA( 2 ), WORK( 2 ), Z( 2 )* ..** Purpose* =======** This subroutine computes the square root of the I-th eigenvalue* of a positive symmetric rank-one modification of a 2-by-2 diagonal* matrix** diag( D ) * diag( D ) + RHO * Z * transpose(Z) .** The diagonal entries in the array D are assumed to satisfy** 0 <= D(i) < D(j) for i < j .** We also assume RHO > 0 and that the Euclidean norm of the vector* Z is one.** Arguments* =========** I (input) INTEGER* The index of the eigenvalue to be computed. I = 1 or I = 2.** D (input) DOUBLE PRECISION array, dimension ( 2 )* The original eigenvalues. We assume 0 <= D(1) < D(2).** Z (input) DOUBLE PRECISION array, dimension ( 2 )* The components of the updating vector.** DELTA (output) DOUBLE PRECISION array, dimension ( 2 )* Contains (D(j) - lambda_I) in its j-th component.* The vector DELTA contains the information necessary* to construct the eigenvectors.** RHO (input) DOUBLE PRECISION* The scalar in the symmetric updating formula.** DSIGMA (output) DOUBLE PRECISION* The computed lambda_I, the I-th updated eigenvalue.** WORK (workspace) DOUBLE PRECISION array, dimension ( 2 )* WORK contains (D(j) + sigma_I) in its j-th component.** Further Details* ===============** Based on contributions by* Ren-Cang Li, Computer Science Division, University of California* at Berkeley, USA** =====================================================================** .. Parameters ..DOUBLE PRECISION ZERO, ONE, TWO, THREE, FOURPARAMETER ( ZERO = 0.0D+0, ONE = 1.0D+0, TWO = 2.0D+0,$ THREE = 3.0D+0, FOUR = 4.0D+0 )* ..* .. Local Scalars ..DOUBLE PRECISION B, C, DEL, DELSQ, TAU, W* ..* .. Intrinsic Functions ..INTRINSIC ABS, SQRT* ..* .. Executable Statements ..*DEL = D( 2 ) - D( 1 )DELSQ = DEL*( D( 2 )+D( 1 ) )IF( I.EQ.1 ) THENW = ONE + FOUR*RHO*( Z( 2 )*Z( 2 ) / ( D( 1 )+THREE*D( 2 ) )-$ Z( 1 )*Z( 1 ) / ( THREE*D( 1 )+D( 2 ) ) ) / DELIF( W.GT.ZERO ) THENB = DELSQ + RHO*( Z( 1 )*Z( 1 )+Z( 2 )*Z( 2 ) )C = RHO*Z( 1 )*Z( 1 )*DELSQ** B > ZERO, always** The following TAU is DSIGMA * DSIGMA - D( 1 ) * D( 1 )*TAU = TWO*C / ( B+SQRT( ABS( B*B-FOUR*C ) ) )** The following TAU is DSIGMA - D( 1 )*TAU = TAU / ( D( 1 )+SQRT( D( 1 )*D( 1 )+TAU ) )DSIGMA = D( 1 ) + TAUDELTA( 1 ) = -TAUDELTA( 2 ) = DEL - TAUWORK( 1 ) = TWO*D( 1 ) + TAUWORK( 2 ) = ( D( 1 )+TAU ) + D( 2 )* DELTA( 1 ) = -Z( 1 ) / TAU* DELTA( 2 ) = Z( 2 ) / ( DEL-TAU )ELSEB = -DELSQ + RHO*( Z( 1 )*Z( 1 )+Z( 2 )*Z( 2 ) )C = RHO*Z( 2 )*Z( 2 )*DELSQ** The following TAU is DSIGMA * DSIGMA - D( 2 ) * D( 2 )*IF( B.GT.ZERO ) THENTAU = -TWO*C / ( B+SQRT( B*B+FOUR*C ) )ELSETAU = ( B-SQRT( B*B+FOUR*C ) ) / TWOEND IF** The following TAU is DSIGMA - D( 2 )*TAU = TAU / ( D( 2 )+SQRT( ABS( D( 2 )*D( 2 )+TAU ) ) )DSIGMA = D( 2 ) + TAUDELTA( 1 ) = -( DEL+TAU )DELTA( 2 ) = -TAUWORK( 1 ) = D( 1 ) + TAU + D( 2 )WORK( 2 ) = TWO*D( 2 ) + TAU* DELTA( 1 ) = -Z( 1 ) / ( DEL+TAU )* DELTA( 2 ) = -Z( 2 ) / TAUEND IF* TEMP = SQRT( DELTA( 1 )*DELTA( 1 )+DELTA( 2 )*DELTA( 2 ) )* DELTA( 1 ) = DELTA( 1 ) / TEMP* DELTA( 2 ) = DELTA( 2 ) / TEMPELSE** Now I=2*B = -DELSQ + RHO*( Z( 1 )*Z( 1 )+Z( 2 )*Z( 2 ) )C = RHO*Z( 2 )*Z( 2 )*DELSQ** The following TAU is DSIGMA * DSIGMA - D( 2 ) * D( 2 )*IF( B.GT.ZERO ) THENTAU = ( B+SQRT( B*B+FOUR*C ) ) / TWOELSETAU = TWO*C / ( -B+SQRT( B*B+FOUR*C ) )END IF** The following TAU is DSIGMA - D( 2 )*TAU = TAU / ( D( 2 )+SQRT( D( 2 )*D( 2 )+TAU ) )DSIGMA = D( 2 ) + TAUDELTA( 1 ) = -( DEL+TAU )DELTA( 2 ) = -TAUWORK( 1 ) = D( 1 ) + TAU + D( 2 )WORK( 2 ) = TWO*D( 2 ) + TAU* DELTA( 1 ) = -Z( 1 ) / ( DEL+TAU )* DELTA( 2 ) = -Z( 2 ) / TAU* TEMP = SQRT( DELTA( 1 )*DELTA( 1 )+DELTA( 2 )*DELTA( 2 ) )* DELTA( 1 ) = DELTA( 1 ) / TEMP* DELTA( 2 ) = DELTA( 2 ) / TEMPEND IFRETURN** End of DLASD5*ENDSUBROUTINE DLAED6( KNITER, ORGATI, RHO, D, Z, FINIT, TAU, INFO )** -- LAPACK routine (version 3.0) --* Univ. of Tennessee, Oak Ridge National Lab, Argonne National Lab,* Courant Institute, NAG Ltd., and Rice University* June 30, 1999** .. Scalar Arguments ..LOGICAL ORGATIINTEGER INFO, KNITERDOUBLE PRECISION FINIT, RHO, TAU* ..* .. Array Arguments ..DOUBLE PRECISION D( 3 ), Z( 3 )* ..** Purpose* =======** DLAED6 computes the positive or negative root (closest to the origin)* of* z(1) z(2) z(3)* f(x) = rho + --------- + ---------- + ---------* d(1)-x d(2)-x d(3)-x** It is assumed that** if ORGATI = .true. the root is between d(2) and d(3);* otherwise it is between d(1) and d(2)** This routine will be called by DLAED4 when necessary. In most cases,* the root sought is the smallest in magnitude, though it might not be* in some extremely rare situations.** Arguments* =========** KNITER (input) INTEGER* Refer to DLAED4 for its significance.** ORGATI (input) LOGICAL* If ORGATI is true, the needed root is between d(2) and* d(3); otherwise it is between d(1) and d(2). See* DLAED4 for further details.** RHO (input) DOUBLE PRECISION* Refer to the equation f(x) above.** D (input) DOUBLE PRECISION array, dimension (3)* D satisfies d(1) < d(2) < d(3).** Z (input) DOUBLE PRECISION array, dimension (3)* Each of the elements in z must be positive.** FINIT (input) DOUBLE PRECISION* The value of f at 0. It is more accurate than the one* evaluated inside this routine (if someone wants to do* so).** TAU (output) DOUBLE PRECISION* The root of the equation f(x).** INFO (output) INTEGER* = 0: successful exit* > 0: if INFO = 1, failure to converge** Further Details* ===============** Based on contributions by* Ren-Cang Li, Computer Science Division, University of California* at Berkeley, USA** =====================================================================** .. Parameters ..INTEGER MAXITPARAMETER ( MAXIT = 20 )DOUBLE PRECISION ZERO, ONE, TWO, THREE, FOUR, EIGHTPARAMETER ( ZERO = 0.0D0, ONE = 1.0D0, TWO = 2.0D0,$ THREE = 3.0D0, FOUR = 4.0D0, EIGHT = 8.0D0 )* ..* .. External Functions ..DOUBLE PRECISION DLAMCHEXTERNAL DLAMCH* ..* .. Local Arrays ..DOUBLE PRECISION DSCALE( 3 ), ZSCALE( 3 )* ..* .. Local Scalars ..LOGICAL FIRST, SCALEINTEGER I, ITER, NITERDOUBLE PRECISION A, B, BASE, C, DDF, DF, EPS, ERRETM, ETA, F,$ FC, SCLFAC, SCLINV, SMALL1, SMALL2, SMINV1,$ SMINV2, TEMP, TEMP1, TEMP2, TEMP3, TEMP4* ..* .. Save statement ..SAVE FIRST, SMALL1, SMINV1, SMALL2, SMINV2, EPS* ..* .. Intrinsic Functions ..INTRINSIC ABS, INT, LOG, MAX, MIN, SQRT* ..* .. Data statements ..DATA FIRST / .TRUE. /* ..* .. Executable Statements ..*INFO = 0*NITER = 1TAU = ZEROIF( KNITER.EQ.2 ) THENIF( ORGATI ) THENTEMP = ( D( 3 )-D( 2 ) ) / TWOC = RHO + Z( 1 ) / ( ( D( 1 )-D( 2 ) )-TEMP )A = C*( D( 2 )+D( 3 ) ) + Z( 2 ) + Z( 3 )B = C*D( 2 )*D( 3 ) + Z( 2 )*D( 3 ) + Z( 3 )*D( 2 )ELSETEMP = ( D( 1 )-D( 2 ) ) / TWOC = RHO + Z( 3 ) / ( ( D( 3 )-D( 2 ) )-TEMP )A = C*( D( 1 )+D( 2 ) ) + Z( 1 ) + Z( 2 )B = C*D( 1 )*D( 2 ) + Z( 1 )*D( 2 ) + Z( 2 )*D( 1 )END IFTEMP = MAX( ABS( A ), ABS( B ), ABS( C ) )A = A / TEMPB = B / TEMPC = C / TEMPIF( C.EQ.ZERO ) THENTAU = B / AELSE IF( A.LE.ZERO ) THENTAU = ( A-SQRT( ABS( A*A-FOUR*B*C ) ) ) / ( TWO*C )ELSETAU = TWO*B / ( A+SQRT( ABS( A*A-FOUR*B*C ) ) )END IFTEMP = RHO + Z( 1 ) / ( D( 1 )-TAU ) +$ Z( 2 ) / ( D( 2 )-TAU ) + Z( 3 ) / ( D( 3 )-TAU )IF( ABS( FINIT ).LE.ABS( TEMP ) )$ TAU = ZEROEND IF** On first call to routine, get machine parameters for* possible scaling to avoid overflow*IF( FIRST ) THENEPS = DLAMCH( 'Epsilon' )BASE = DLAMCH( 'Base' )SMALL1 = BASE**( INT( LOG( DLAMCH( 'SafMin' ) ) / LOG( BASE ) /$ THREE ) )SMINV1 = ONE / SMALL1SMALL2 = SMALL1*SMALL1SMINV2 = SMINV1*SMINV1FIRST = .FALSE.END IF** Determine if scaling of inputs necessary to avoid overflow* when computing 1/TEMP**3*IF( ORGATI ) THENTEMP = MIN( ABS( D( 2 )-TAU ), ABS( D( 3 )-TAU ) )ELSETEMP = MIN( ABS( D( 1 )-TAU ), ABS( D( 2 )-TAU ) )END IFSCALE = .FALSE.IF( TEMP.LE.SMALL1 ) THENSCALE = .TRUE.IF( TEMP.LE.SMALL2 ) THEN** Scale up by power of radix nearest 1/SAFMIN**(2/3)*SCLFAC = SMINV2SCLINV = SMALL2ELSE** Scale up by power of radix nearest 1/SAFMIN**(1/3)*SCLFAC = SMINV1SCLINV = SMALL1END IF** Scaling up safe because D, Z, TAU scaled elsewhere to be O(1)*DO 10 I = 1, 3DSCALE( I ) = D( I )*SCLFACZSCALE( I ) = Z( I )*SCLFAC10 CONTINUETAU = TAU*SCLFACELSE** Copy D and Z to DSCALE and ZSCALE*DO 20 I = 1, 3DSCALE( I ) = D( I )ZSCALE( I ) = Z( I )20 CONTINUEEND IF*FC = ZERODF = ZERODDF = ZERODO 30 I = 1, 3TEMP = ONE / ( DSCALE( I )-TAU )TEMP1 = ZSCALE( I )*TEMPTEMP2 = TEMP1*TEMPTEMP3 = TEMP2*TEMPFC = FC + TEMP1 / DSCALE( I )DF = DF + TEMP2DDF = DDF + TEMP330 CONTINUEF = FINIT + TAU*FC*IF( ABS( F ).LE.ZERO )$ GO TO 60** Iteration begins** It is not hard to see that** 1) Iterations will go up monotonically* if FINIT < 0;** 2) Iterations will go down monotonically* if FINIT > 0.*ITER = NITER + 1*DO 50 NITER = ITER, MAXIT*IF( ORGATI ) THENTEMP1 = DSCALE( 2 ) - TAUTEMP2 = DSCALE( 3 ) - TAUELSETEMP1 = DSCALE( 1 ) - TAUTEMP2 = DSCALE( 2 ) - TAUEND IFA = ( TEMP1+TEMP2 )*F - TEMP1*TEMP2*DFB = TEMP1*TEMP2*FC = F - ( TEMP1+TEMP2 )*DF + TEMP1*TEMP2*DDFTEMP = MAX( ABS( A ), ABS( B ), ABS( C ) )A = A / TEMPB = B / TEMPC = C / TEMPIF( C.EQ.ZERO ) THENETA = B / AELSE IF( A.LE.ZERO ) THENETA = ( A-SQRT( ABS( A*A-FOUR*B*C ) ) ) / ( TWO*C )ELSEETA = TWO*B / ( A+SQRT( ABS( A*A-FOUR*B*C ) ) )END IFIF( F*ETA.GE.ZERO ) THENETA = -F / DFEND IF*TEMP = ETA + TAUIF( ORGATI ) THENIF( ETA.GT.ZERO .AND. TEMP.GE.DSCALE( 3 ) )$ ETA = ( DSCALE( 3 )-TAU ) / TWOIF( ETA.LT.ZERO .AND. TEMP.LE.DSCALE( 2 ) )$ ETA = ( DSCALE( 2 )-TAU ) / TWOELSEIF( ETA.GT.ZERO .AND. TEMP.GE.DSCALE( 2 ) )$ ETA = ( DSCALE( 2 )-TAU ) / TWOIF( ETA.LT.ZERO .AND. TEMP.LE.DSCALE( 1 ) )$ ETA = ( DSCALE( 1 )-TAU ) / TWOEND IFTAU = TAU + ETA*FC = ZEROERRETM = ZERODF = ZERODDF = ZERODO 40 I = 1, 3TEMP = ONE / ( DSCALE( I )-TAU )TEMP1 = ZSCALE( I )*TEMPTEMP2 = TEMP1*TEMPTEMP3 = TEMP2*TEMPTEMP4 = TEMP1 / DSCALE( I )FC = FC + TEMP4ERRETM = ERRETM + ABS( TEMP4 )DF = DF + TEMP2DDF = DDF + TEMP340 CONTINUEF = FINIT + TAU*FCERRETM = EIGHT*( ABS( FINIT )+ABS( TAU )*ERRETM ) +$ ABS( TAU )*DFIF( ABS( F ).LE.EPS*ERRETM )$ GO TO 6050 CONTINUEINFO = 160 CONTINUE** Undo scaling*IF( SCALE )$ TAU = TAU*SCLINVRETURN** End of DLAED6*ENDSUBROUTINE RSYEVR( 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 DSTEGR( JOBZ, RANGE, N, D, E, VL, VU, IL, IU, ABSTOL,$ M, W, Z, LDZ, ISUPPZ, WORK, LWORK, IWORK,$ LIWORK, INFO )** -- LAPACK computational routine (version 3.0) --* Univ. of Tennessee, Univ. of California Berkeley, NAG Ltd.,* Courant Institute, Argonne National Lab, and Rice University* June 30, 1999** .. Scalar Arguments ..CHARACTER JOBZ, RANGEINTEGER IL, INFO, IU, LDZ, LIWORK, LWORK, M, NDOUBLE PRECISION ABSTOL, VL, VU* ..* .. Array Arguments ..INTEGER ISUPPZ( * ), IWORK( * )DOUBLE PRECISION D( * ), E( * ), W( * ), WORK( * ), Z( LDZ, * )* ..** Purpose* =======** DSTEGR computes selected eigenvalues and, optionally, eigenvectors* of a real symmetric tridiagonal matrix T. Eigenvalues and* eigenvectors can be selected by specifying either a range of values* or a range of indices for the desired eigenvalues. The eigenvalues* are computed by the dqds algorithm, while orthogonal eigenvectors are* computed from various ``good'' L D L^T representations (also known as* Relatively Robust Representations). Gram-Schmidt orthogonalization is* avoided as far as possible. More specifically, the various steps of* the algorithm are as follows. For the i-th unreduced block of T,* (a) Compute T - sigma_i = L_i D_i L_i^T, such that L_i D_i L_i^T* is a relatively robust representation,* (b) Compute the eigenvalues, lambda_j, of L_i D_i L_i^T to high* relative accuracy by the dqds algorithm,* (c) If there is a cluster of close eigenvalues, "choose" sigma_i* close to the cluster, and go to step (a),* (d) Given the approximate eigenvalue lambda_j of L_i D_i L_i^T,* compute the corresponding eigenvector by forming a* rank-revealing twisted factorization.* The desired accuracy of the output can be specified by the input* parameter ABSTOL.** For more details, see "A new O(n^2) algorithm for the symmetric* tridiagonal eigenvalue/eigenvector problem", by Inderjit Dhillon,* Computer Science Division Technical Report No. UCB/CSD-97-971,* UC Berkeley, May 1997.** Note 1 : Currently DSTEGR is only set up to find ALL the n* eigenvalues and eigenvectors of T in O(n^2) time* Note 2 : Currently the routine DSTEIN is called when an appropriate* sigma_i cannot be chosen in step (c) above. DSTEIN invokes modified* Gram-Schmidt when eigenvalues are close.* Note 3 : DSTEGR works only on machines which follow ieee-754* floating-point standard in their handling of infinities and NaNs.* Normal execution of DSTEGR may create NaNs and infinities and hence* may abort due to a floating point exception in environments which* do not conform to the ieee standard.** Arguments* =========** JOBZ (input) CHARACTER*1* = 'N': Compute eigenvalues only;* = 'V': Compute eigenvalues and eigenvectors.** RANGE (input) CHARACTER*1* = 'A': all eigenvalues will be found.* = 'V': all eigenvalues in the half-open interval (VL,VU]* will be found.* = 'I': the IL-th through IU-th eigenvalues will be found.********** Only RANGE = 'A' is currently supported *********************** N (input) INTEGER* The order of the matrix. N >= 0.** D (input/output) DOUBLE PRECISION array, dimension (N)* On entry, the n diagonal elements of the tridiagonal matrix* T. On exit, D is overwritten.** E (input/output) DOUBLE PRECISION array, dimension (N)* On entry, the (n-1) subdiagonal elements of the tridiagonal* matrix T in elements 1 to N-1 of E; E(N) need not be set.* On exit, E is overwritten.** VL (input) DOUBLE PRECISION* VU (input) DOUBLE PRECISION* If RANGE='V', the lower and upper bounds of the interval to* be searched for eigenvalues. VL < VU.* Not referenced if RANGE = 'A' or 'I'.** IL (input) INTEGER* IU (input) INTEGER* If RANGE='I', the indices (in ascending order) of the* smallest and largest eigenvalues to be returned.* 1 <= IL <= IU <= N, if N > 0; IL = 1 and IU = 0 if N = 0.* Not referenced if RANGE = 'A' or 'V'.** ABSTOL (input) DOUBLE PRECISION* The absolute error tolerance for the* eigenvalues/eigenvectors. IF JOBZ = 'V', the eigenvalues and* eigenvectors output have residual norms bounded by ABSTOL,* and the dot products between different eigenvectors are* bounded by ABSTOL. If ABSTOL is less than N*EPS*|T|, then* N*EPS*|T| will be used in its place, where EPS is the* machine precision and |T| is the 1-norm of the tridiagonal* matrix. The eigenvalues are computed to an accuracy of* EPS*|T| irrespective of ABSTOL. If high relative accuracy* is important, set ABSTOL to DLAMCH( 'Safe minimum' ).* See Barlow and Demmel "Computing Accurate Eigensystems of* Scaled Diagonally Dominant Matrices", LAPACK Working Note #7* for a discussion of which matrices define their eigenvalues* to high relative accuracy.** M (output) INTEGER* The total number of eigenvalues found. 0 <= M <= N.* If RANGE = 'A', M = N, and if RANGE = 'I', M = IU-IL+1.** W (output) DOUBLE PRECISION array, dimension (N)* The first M elements contain the selected eigenvalues in* ascending order.** Z (output) DOUBLE PRECISION array, dimension (LDZ, max(1,M) )* If JOBZ = 'V', then if INFO = 0, the first M columns of Z* contain the orthonormal eigenvectors of the matrix T* corresponding to the selected eigenvalues, with the i-th* column of Z holding the eigenvector associated with W(i).* If JOBZ = 'N', then Z is not referenced.* Note: the user must ensure that at least max(1,M) columns are* supplied in the array Z; if RANGE = 'V', the exact value of M* is not known in advance and an upper bound must be used.** LDZ (input) INTEGER* The leading dimension of the array Z. LDZ >= 1, and if* JOBZ = 'V', LDZ >= max(1,N).** ISUPPZ (output) INTEGER ARRAY, dimension ( 2*max(1,M) )* The support of the eigenvectors in Z, i.e., the indices* indicating the nonzero elements in Z. The i-th eigenvector* is nonzero only in elements ISUPPZ( 2*i-1 ) through* ISUPPZ( 2*i ).** WORK (workspace/output) DOUBLE PRECISION array, dimension (LWORK)* On exit, if INFO = 0, WORK(1) returns the optimal* (and minimal) LWORK.** LWORK (input) INTEGER* The dimension of the array WORK. LWORK >= max(1,18*N)** If LWORK = -1, then a workspace query is assumed; the routine* only calculates the optimal size of the WORK array, returns* this value as the first entry of the WORK array, and no error* message related to LWORK is issued by XERBLA.** IWORK (workspace/output) INTEGER array, dimension (LIWORK)* On exit, if INFO = 0, IWORK(1) returns the optimal LIWORK.** LIWORK (input) INTEGER* The dimension of the array IWORK. LIWORK >= max(1,10*N)** If LIWORK = -1, then a workspace query is assumed; the* routine only calculates the optimal size of the IWORK array,* returns this value as the first entry of the IWORK array, and* no error message related to LIWORK is issued by XERBLA.** INFO (output) INTEGER* = 0: successful exit* < 0: if INFO = -i, the i-th argument had an illegal value* > 0: if INFO = 1, internal error in DLARRE,* if INFO = 2, internal error in DLARRV.** Further Details* ===============** Based on contributions by* Inderjit Dhillon, IBM Almaden, USA* Osni Marques, LBNL/NERSC, USA** =====================================================================** .. Parameters ..DOUBLE PRECISION ZERO, ONEPARAMETER ( ZERO = 0.0D0, ONE = 1.0D0 )* ..* .. Local Scalars ..LOGICAL ALLEIG, INDEIG, LQUERY, VALEIG, WANTZINTEGER I, IBEGIN, IEND, IINDBL, IINDWK, IINFO, IINSPL,$ INDGRS, INDWOF, INDWRK, ITMP, J, JJ, LIWMIN,$ LWMIN, NSPLITDOUBLE PRECISION BIGNUM, EPS, RMAX, RMIN, SAFMIN, SCALE, SMLNUM,$ THRESH, TMP, TNRM, TOL* ..* .. External Functions ..LOGICAL LSAMEDOUBLE PRECISION DLAMCH, DLANSTEXTERNAL LSAME, DLAMCH, DLANST* ..* .. External Subroutines ..EXTERNAL DLARRE, DLARRV, DLASET, DSCAL, DSWAP, XERBLA* ..* .. Intrinsic Functions ..INTRINSIC DBLE, MAX, MIN, SQRT* ..* .. Executable Statements ..** Test the input parameters.*WANTZ = LSAME( JOBZ, 'V' )ALLEIG = LSAME( RANGE, 'A' )VALEIG = LSAME( RANGE, 'V' )INDEIG = LSAME( RANGE, 'I' )*LQUERY = ( ( LWORK.EQ.-1 ) .OR. ( LIWORK.EQ.-1 ) )LWMIN = 18*NLIWMIN = 10*N*INFO = 0IF( .NOT.( WANTZ .OR. LSAME( JOBZ, 'N' ) ) ) THENINFO = -1ELSE IF( .NOT.( ALLEIG .OR. VALEIG .OR. INDEIG ) ) THENINFO = -2** The following two lines need to be removed once the* RANGE = 'V' and RANGE = 'I' options are provided.*ELSE IF( VALEIG .OR. INDEIG ) THENINFO = -2ELSE IF( N.LT.0 ) THENINFO = -3ELSE IF( VALEIG .AND. N.GT.0 .AND. VU.LE.VL ) THENINFO = -7ELSE IF( INDEIG .AND. IL.LT.1 ) THENINFO = -8* The following change should be made in DSTEVX also, otherwise* IL can be specified as N+1 and IU as N.* ELSE IF( INDEIG .AND. ( IU.LT.MIN( N, IL ) .OR. IU.GT.N ) ) THENELSE IF( INDEIG .AND. ( IU.LT.IL .OR. IU.GT.N ) ) THENINFO = -9ELSE IF( LDZ.LT.1 .OR. ( WANTZ .AND. LDZ.LT.N ) ) THENINFO = -14ELSE IF( LWORK.LT.LWMIN .AND. .NOT.LQUERY ) THENINFO = -17ELSE IF( LIWORK.LT.LIWMIN .AND. .NOT.LQUERY ) THENINFO = -19END IFIF( INFO.EQ.0 ) THENWORK( 1 ) = LWMINIWORK( 1 ) = LIWMINEND IF*IF( INFO.NE.0 ) THENCALL XERBLA( 'DSTEGR', -INFO )RETURNELSE IF( LQUERY ) THENRETURNEND IF** Quick return if possible*M = 0IF( N.EQ.0 )$ RETURN*IF( N.EQ.1 ) THENIF( ALLEIG .OR. INDEIG ) THENM = 1W( 1 ) = D( 1 )ELSEIF( VL.LT.D( 1 ) .AND. VU.GE.D( 1 ) ) THENM = 1W( 1 ) = D( 1 )END IFEND IFIF( WANTZ )$ Z( 1, 1 ) = ONERETURNEND IF** Get machine constants.*SAFMIN = DLAMCH( 'Safe minimum' )EPS = DLAMCH( 'Precision' )SMLNUM = SAFMIN / EPSBIGNUM = ONE / SMLNUMRMIN = SQRT( SMLNUM )RMAX = MIN( SQRT( BIGNUM ), ONE / SQRT( SQRT( SAFMIN ) ) )** Scale matrix to allowable range, if necessary.*SCALE = ONETNRM = DLANST( 'M', N, D, E )IF( TNRM.GT.ZERO .AND. TNRM.LT.RMIN ) THENSCALE = RMIN / TNRMELSE IF( TNRM.GT.RMAX ) THENSCALE = RMAX / TNRMEND IFIF( SCALE.NE.ONE ) THENCALL DSCAL( N, SCALE, D, 1 )CALL DSCAL( N-1, SCALE, E, 1 )TNRM = TNRM*SCALEEND IFINDGRS = 1INDWOF = 2*N + 1INDWRK = 3*N + 1*IINSPL = 1IINDBL = N + 1IINDWK = 2*N + 1*CALL DLASET( 'Full', N, N, ZERO, ZERO, Z, LDZ )** Compute the desired eigenvalues of the tridiagonal after splitting* into smaller subblocks if the corresponding of-diagonal elements* are small*THRESH = EPS*TNRMCALL DLARRE( N, D, E, THRESH, NSPLIT, IWORK( IINSPL ), M, W,$ WORK( INDWOF ), WORK( INDGRS ), WORK( INDWRK ),$ IINFO )IF( IINFO.NE.0 ) THENINFO = 1RETURNEND IF*IF( WANTZ ) THEN** Compute the desired eigenvectors corresponding to the computed* eigenvalues*TOL = MAX( ABSTOL, DBLE( N )*THRESH )IBEGIN = 1DO 20 I = 1, NSPLITIEND = IWORK( IINSPL+I-1 )DO 10 J = IBEGIN, IENDIWORK( IINDBL+J-1 ) = I10 CONTINUEIBEGIN = IEND + 120 CONTINUE*CALL DLARRV( N, D, E, IWORK( IINSPL ), M, W, IWORK( IINDBL ),$ WORK( INDGRS ), TOL, Z, LDZ, ISUPPZ,$ WORK( INDWRK ), IWORK( IINDWK ), IINFO )IF( IINFO.NE.0 ) THENINFO = 2RETURNEND IF*END IF*IBEGIN = 1DO 40 I = 1, NSPLITIEND = IWORK( IINSPL+I-1 )DO 30 J = IBEGIN, IENDW( J ) = W( J ) + WORK( INDWOF+I-1 )30 CONTINUEIBEGIN = IEND + 140 CONTINUE** If matrix was scaled, then rescale eigenvalues appropriately.*IF( SCALE.NE.ONE ) THENCALL DSCAL( M, ONE / SCALE, W, 1 )END IF** If eigenvalues are not in order, then sort them, along with* eigenvectors.*IF( NSPLIT.GT.1 ) THENDO 60 J = 1, M - 1I = 0TMP = W( J )DO 50 JJ = J + 1, MIF( W( JJ ).LT.TMP ) THENI = JJTMP = W( JJ )END IF50 CONTINUEIF( I.NE.0 ) THENW( I ) = W( J )W( J ) = TMPIF( WANTZ ) THENCALL DSWAP( N, Z( 1, I ), 1, Z( 1, J ), 1 )ITMP = ISUPPZ( 2*I-1 )ISUPPZ( 2*I-1 ) = ISUPPZ( 2*J-1 )ISUPPZ( 2*J-1 ) = ITMPITMP = ISUPPZ( 2*I )ISUPPZ( 2*I ) = ISUPPZ( 2*J )ISUPPZ( 2*J ) = ITMPEND IFEND IF60 CONTINUEEND IF*WORK( 1 ) = LWMINIWORK( 1 ) = LIWMINRETURN** End of DSTEGR*ENDSUBROUTINE DORMTR( SIDE, UPLO, TRANS, M, N, A, LDA, TAU, C, LDC,$ WORK, LWORK, INFO )** -- LAPACK routine (version 3.0) --* Univ. of Tennessee, Univ. of California Berkeley, NAG Ltd.,* Courant Institute, Argonne National Lab, and Rice University* June 30, 1999** .. Scalar Arguments ..CHARACTER SIDE, TRANS, UPLOINTEGER INFO, LDA, LDC, LWORK, M, N* ..* .. Array Arguments ..DOUBLE PRECISION A( LDA, * ), C( LDC, * ), TAU( * ), WORK( * )* ..** Purpose* =======** DORMTR overwrites the general real M-by-N matrix C with** SIDE = 'L' SIDE = 'R'* TRANS = 'N': Q * C C * Q* TRANS = 'T': Q**T * C C * Q**T** where Q is a real orthogonal matrix of order nq, with nq = m if* SIDE = 'L' and nq = n if SIDE = 'R'. Q is defined as the product of* nq-1 elementary reflectors, as returned by DSYTRD:** if UPLO = 'U', Q = H(nq-1) . . . H(2) H(1);** if UPLO = 'L', Q = H(1) H(2) . . . H(nq-1).** Arguments* =========** SIDE (input) CHARACTER*1* = 'L': apply Q or Q**T from the Left;* = 'R': apply Q or Q**T from the Right.** UPLO (input) CHARACTER*1* = 'U': Upper triangle of A contains elementary reflectors* from DSYTRD;* = 'L': Lower triangle of A contains elementary reflectors* from DSYTRD.** TRANS (input) CHARACTER*1* = 'N': No transpose, apply Q;* = 'T': Transpose, apply Q**T.** M (input) INTEGER* The number of rows of the matrix C. M >= 0.** N (input) INTEGER* The number of columns of the matrix C. N >= 0.** A (input) DOUBLE PRECISION array, dimension* (LDA,M) if SIDE = 'L'* (LDA,N) if SIDE = 'R'* The vectors which define the elementary reflectors, as* returned by DSYTRD.** LDA (input) INTEGER* The leading dimension of the array A.* LDA >= max(1,M) if SIDE = 'L'; LDA >= max(1,N) if SIDE = 'R'.** TAU (input) DOUBLE PRECISION array, dimension* (M-1) if SIDE = 'L'* (N-1) if SIDE = 'R'* TAU(i) must contain the scalar factor of the elementary* reflector H(i), as returned by DSYTRD.** C (input/output) DOUBLE PRECISION array, dimension (LDC,N)* On entry, the M-by-N matrix C.* On exit, C is overwritten by Q*C or Q**T*C or C*Q**T or C*Q.** LDC (input) INTEGER* The leading dimension of the array C. LDC >= max(1,M).** WORK (workspace/output) DOUBLE PRECISION array, dimension (LWORK)* On exit, if INFO = 0, WORK(1) returns the optimal LWORK.** LWORK (input) INTEGER* The dimension of the array WORK.* If SIDE = 'L', LWORK >= max(1,N);* if SIDE = 'R', LWORK >= max(1,M).* For optimum performance LWORK >= N*NB if SIDE = 'L', and* LWORK >= M*NB if SIDE = 'R', where NB is the optimal* blocksize.** If LWORK = -1, then a workspace query is assumed; the routine* only calculates the optimal size of the WORK array, returns* this value as the first entry of the WORK array, and no error* message related to LWORK is issued by XERBLA.** INFO (output) INTEGER* = 0: successful exit* < 0: if INFO = -i, the i-th argument had an illegal value** =====================================================================** .. Local Scalars ..LOGICAL LEFT, LQUERY, UPPERINTEGER I1, I2, IINFO, LWKOPT, MI, NB, NI, NQ, NW* ..* .. External Functions ..LOGICAL LSAMEINTEGER ILAENVEXTERNAL LSAME, ILAENV* ..* .. External Subroutines ..EXTERNAL DORMQL, DORMQR, XERBLA* ..* .. Intrinsic Functions ..INTRINSIC MAX* ..* .. Executable Statements ..** Test the input arguments*INFO = 0LEFT = LSAME( SIDE, 'L' )UPPER = LSAME( UPLO, 'U' )LQUERY = ( LWORK.EQ.-1 )** NQ is the order of Q and NW is the minimum dimension of WORK*IF( LEFT ) THENNQ = MNW = NELSENQ = NNW = MEND IFIF( .NOT.LEFT .AND. .NOT.LSAME( SIDE, 'R' ) ) THENINFO = -1ELSE IF( .NOT.UPPER .AND. .NOT.LSAME( UPLO, 'L' ) ) THENINFO = -2ELSE IF( .NOT.LSAME( TRANS, 'N' ) .AND. .NOT.LSAME( TRANS, 'T' ) )$ THENINFO = -3ELSE IF( M.LT.0 ) THENINFO = -4ELSE IF( N.LT.0 ) THENINFO = -5ELSE IF( LDA.LT.MAX( 1, NQ ) ) THENINFO = -7ELSE IF( LDC.LT.MAX( 1, M ) ) THENINFO = -10ELSE IF( LWORK.LT.MAX( 1, NW ) .AND. .NOT.LQUERY ) THENINFO = -12END IF*IF( INFO.EQ.0 ) THENIF( UPPER ) THENIF( LEFT ) THENNB = ILAENV( 1, 'DORMQL', SIDE // TRANS, M-1, N, M-1,$ -1 )ELSENB = ILAENV( 1, 'DORMQL', SIDE // TRANS, M, N-1, N-1,$ -1 )END IFELSEIF( LEFT ) THENNB = ILAENV( 1, 'DORMQR', SIDE // TRANS, M-1, N, M-1,$ -1 )ELSENB = ILAENV( 1, 'DORMQR', SIDE // TRANS, M, N-1, N-1,$ -1 )END IFEND IFLWKOPT = MAX( 1, NW )*NBWORK( 1 ) = LWKOPTEND IF*IF( INFO.NE.0 ) THENCALL XERBLA( 'DORMTR', -INFO )RETURNELSE IF( LQUERY ) THENRETURNEND IF** Quick return if possible*IF( M.EQ.0 .OR. N.EQ.0 .OR. NQ.EQ.1 ) THENWORK( 1 ) = 1RETURNEND IF*IF( LEFT ) THENMI = M - 1NI = NELSEMI = MNI = N - 1END IF*IF( UPPER ) THEN** Q was determined by a call to DSYTRD with UPLO = 'U'*CALL DORMQL( SIDE, TRANS, MI, NI, NQ-1, A( 1, 2 ), LDA, TAU, C,$ LDC, WORK, LWORK, IINFO )ELSE** Q was determined by a call to DSYTRD with UPLO = 'L'*IF( LEFT ) THENI1 = 2I2 = 1ELSEI1 = 1I2 = 2END IFCALL DORMQR( SIDE, TRANS, MI, NI, NQ-1, A( 2, 1 ), LDA, TAU,$ C( I1, I2 ), LDC, WORK, LWORK, IINFO )END IFWORK( 1 ) = LWKOPTRETURN** End of DORMTR*ENDSUBROUTINE DSTEBZ( RANGE, ORDER, N, VL, VU, IL, IU, ABSTOL, D, E,$ M, NSPLIT, W, IBLOCK, ISPLIT, WORK, IWORK,$ INFO )** -- LAPACK routine (version 3.0) --* Univ. of Tennessee, Univ. of California Berkeley, NAG Ltd.,* Courant Institute, Argonne National Lab, and Rice University* June 30, 1999** .. Scalar Arguments ..CHARACTER ORDER, RANGEINTEGER IL, INFO, IU, M, N, NSPLITDOUBLE PRECISION ABSTOL, VL, VU* ..* .. Array Arguments ..INTEGER IBLOCK( * ), ISPLIT( * ), IWORK( * )DOUBLE PRECISION D( * ), E( * ), W( * ), WORK( * )* ..** Purpose* =======** DSTEBZ computes the eigenvalues of a symmetric tridiagonal* matrix T. The user may ask for all eigenvalues, all eigenvalues* in the half-open interval (VL, VU], or the IL-th through IU-th* eigenvalues.** To avoid overflow, the matrix must be scaled so that its* largest element is no greater than overflow**(1/2) ** underflow**(1/4) in absolute value, and for greatest* accuracy, it should not be much smaller than that.** See W. Kahan "Accurate Eigenvalues of a Symmetric Tridiagonal* Matrix", Report CS41, Computer Science Dept., Stanford* University, July 21, 1966.** Arguments* =========** RANGE (input) CHARACTER* = 'A': ("All") all eigenvalues will be found.* = 'V': ("Value") all eigenvalues in the half-open interval* (VL, VU] will be found.* = 'I': ("Index") the IL-th through IU-th eigenvalues (of the* entire matrix) will be found.** ORDER (input) CHARACTER* = 'B': ("By Block") the eigenvalues will be grouped by* split-off block (see IBLOCK, ISPLIT) and* ordered from smallest to largest within* the block.* = 'E': ("Entire matrix")* the eigenvalues for the entire matrix* will be ordered from smallest to* largest.** N (input) INTEGER* The order of the tridiagonal matrix T. N >= 0.** VL (input) DOUBLE PRECISION* VU (input) DOUBLE PRECISION* If RANGE='V', the lower and upper bounds of the interval to* be searched for eigenvalues. Eigenvalues less than or equal* to VL, or greater than VU, will not be returned. VL < VU.* Not referenced if RANGE = 'A' or 'I'.** IL (input) INTEGER* IU (input) INTEGER* If RANGE='I', the indices (in ascending order) of the* smallest and largest eigenvalues to be returned.* 1 <= IL <= IU <= N, if N > 0; IL = 1 and IU = 0 if N = 0.* Not referenced if RANGE = 'A' or 'V'.** ABSTOL (input) DOUBLE PRECISION* The absolute tolerance for the eigenvalues. An eigenvalue* (or cluster) is considered to be located if it has been* determined to lie in an interval whose width is ABSTOL or* less. If ABSTOL is less than or equal to zero, then ULP*|T|* will be used, where |T| means the 1-norm of T.** Eigenvalues will be computed most accurately when ABSTOL is* set to twice the underflow threshold 2*DLAMCH('S'), not zero.** D (input) DOUBLE PRECISION array, dimension (N)* The n diagonal elements of the tridiagonal matrix T.** E (input) DOUBLE PRECISION array, dimension (N-1)* The (n-1) off-diagonal elements of the tridiagonal matrix T.** M (output) INTEGER* The actual number of eigenvalues found. 0 <= M <= N.* (See also the description of INFO=2,3.)** NSPLIT (output) INTEGER* The number of diagonal blocks in the matrix T.* 1 <= NSPLIT <= N.** W (output) DOUBLE PRECISION array, dimension (N)* On exit, the first M elements of W will contain the* eigenvalues. (DSTEBZ may use the remaining N-M elements as* workspace.)** IBLOCK (output) INTEGER array, dimension (N)* At each row/column j where E(j) is zero or small, the* matrix T is considered to split into a block diagonal* matrix. On exit, if INFO = 0, IBLOCK(i) specifies to which* block (from 1 to the number of blocks) the eigenvalue W(i)* belongs. (DSTEBZ may use the remaining N-M elements as* workspace.)** ISPLIT (output) INTEGER array, dimension (N)* The splitting points, at which T breaks up into submatrices.* The first submatrix consists of rows/columns 1 to ISPLIT(1),* the second of rows/columns ISPLIT(1)+1 through ISPLIT(2),* etc., and the NSPLIT-th consists of rows/columns* ISPLIT(NSPLIT-1)+1 through ISPLIT(NSPLIT)=N.* (Only the first NSPLIT elements will actually be used, but* since the user cannot know a priori what value NSPLIT will* have, N words must be reserved for ISPLIT.)** WORK (workspace) DOUBLE PRECISION array, dimension (4*N)** IWORK (workspace) INTEGER array, dimension (3*N)** INFO (output) INTEGER* = 0: successful exit* < 0: if INFO = -i, the i-th argument had an illegal value* > 0: some or all of the eigenvalues failed to converge or* were not computed:* =1 or 3: Bisection failed to converge for some* eigenvalues; these eigenvalues are flagged by a* negative block number. The effect is that the* eigenvalues may not be as accurate as the* absolute and relative tolerances. This is* generally caused by unexpectedly inaccurate* arithmetic.* =2 or 3: RANGE='I' only: Not all of the eigenvalues* IL:IU were found.* Effect: M < IU+1-IL* Cause: non-monotonic arithmetic, causing the* Sturm sequence to be non-monotonic.* Cure: recalculate, using RANGE='A', and pick* out eigenvalues IL:IU. In some cases,* increasing the PARAMETER "FUDGE" may* make things work.* = 4: RANGE='I', and the Gershgorin interval* initially used was too small. No eigenvalues* were computed.* Probable cause: your machine has sloppy* floating-point arithmetic.* Cure: Increase the PARAMETER "FUDGE",* recompile, and try again.** Internal Parameters* ===================** RELFAC DOUBLE PRECISION, default = 2.0e0* The relative tolerance. An interval (a,b] lies within* "relative tolerance" if b-a < RELFAC*ulp*max(|a|,|b|),* where "ulp" is the machine precision (distance from 1 to* the next larger floating point number.)** FUDGE DOUBLE PRECISION, default = 2* A "fudge factor" to widen the Gershgorin intervals. Ideally,* a value of 1 should work, but on machines with sloppy* arithmetic, this needs to be larger. The default for* publicly released versions should be large enough to handle* the worst machine around. Note that this has no effect* on accuracy of the solution.** =====================================================================** .. Parameters ..DOUBLE PRECISION ZERO, ONE, TWO, HALFPARAMETER ( ZERO = 0.0D0, ONE = 1.0D0, TWO = 2.0D0,$ HALF = 1.0D0 / TWO )DOUBLE PRECISION FUDGE, RELFACPARAMETER ( FUDGE = 2.0D0, RELFAC = 2.0D0 )* ..* .. Local Scalars ..LOGICAL NCNVRG, TOOFEWINTEGER IB, IBEGIN, IDISCL, IDISCU, IE, IEND, IINFO,$ IM, IN, IOFF, IORDER, IOUT, IRANGE, ITMAX,$ ITMP1, IW, IWOFF, J, JB, JDISC, JE, NB, NWL,$ NWUDOUBLE PRECISION ATOLI, BNORM, GL, GU, PIVMIN, RTOLI, SAFEMN,$ TMP1, TMP2, TNORM, ULP, WKILL, WL, WLU, WU, WUL* ..* .. Local Arrays ..INTEGER IDUMMA( 1 )* ..* .. External Functions ..LOGICAL LSAMEINTEGER ILAENVDOUBLE PRECISION DLAMCHEXTERNAL LSAME, ILAENV, DLAMCH* ..* .. External Subroutines ..EXTERNAL DLAEBZ, XERBLA* ..* .. Intrinsic Functions ..INTRINSIC ABS, INT, LOG, MAX, MIN, SQRT* ..* .. Executable Statements ..*INFO = 0** Decode RANGE*IF( LSAME( RANGE, 'A' ) ) THENIRANGE = 1ELSE IF( LSAME( RANGE, 'V' ) ) THENIRANGE = 2ELSE IF( LSAME( RANGE, 'I' ) ) THENIRANGE = 3ELSEIRANGE = 0END IF** Decode ORDER*IF( LSAME( ORDER, 'B' ) ) THENIORDER = 2ELSE IF( LSAME( ORDER, 'E' ) ) THENIORDER = 1ELSEIORDER = 0END IF** Check for Errors*IF( IRANGE.LE.0 ) THENINFO = -1ELSE IF( IORDER.LE.0 ) THENINFO = -2ELSE IF( N.LT.0 ) THENINFO = -3ELSE IF( IRANGE.EQ.2 ) THENIF( VL.GE.VU )$ INFO = -5ELSE IF( IRANGE.EQ.3 .AND. ( IL.LT.1 .OR. IL.GT.MAX( 1, N ) ) )$ THENINFO = -6ELSE IF( IRANGE.EQ.3 .AND. ( IU.LT.MIN( N, IL ) .OR. IU.GT.N ) )$ THENINFO = -7END IF*IF( INFO.NE.0 ) THENCALL XERBLA( 'DSTEBZ', -INFO )RETURNEND IF** Initialize error flags*INFO = 0NCNVRG = .FALSE.TOOFEW = .FALSE.** Quick return if possible*M = 0IF( N.EQ.0 )$ RETURN** Simplifications:*IF( IRANGE.EQ.3 .AND. IL.EQ.1 .AND. IU.EQ.N )$ IRANGE = 1** Get machine constants* NB is the minimum vector length for vector bisection, or 0* if only scalar is to be done.*SAFEMN = DLAMCH( 'S' )ULP = DLAMCH( 'P' )RTOLI = ULP*RELFACNB = ILAENV( 1, 'DSTEBZ', ' ', N, -1, -1, -1 )IF( NB.LE.1 )$ NB = 0** Special Case when N=1*IF( N.EQ.1 ) THENNSPLIT = 1ISPLIT( 1 ) = 1IF( IRANGE.EQ.2 .AND. ( VL.GE.D( 1 ) .OR. VU.LT.D( 1 ) ) ) THENM = 0ELSEW( 1 ) = D( 1 )IBLOCK( 1 ) = 1M = 1END IFRETURNEND IF** Compute Splitting Points*NSPLIT = 1WORK( N ) = ZEROPIVMIN = ONE**DIR$ NOVECTORDO 10 J = 2, NTMP1 = E( J-1 )**2IF( ABS( D( J )*D( J-1 ) )*ULP**2+SAFEMN.GT.TMP1 ) THENISPLIT( NSPLIT ) = J - 1NSPLIT = NSPLIT + 1WORK( J-1 ) = ZEROELSEWORK( J-1 ) = TMP1PIVMIN = MAX( PIVMIN, TMP1 )END IF10 CONTINUEISPLIT( NSPLIT ) = NPIVMIN = PIVMIN*SAFEMN** Compute Interval and ATOLI*IF( IRANGE.EQ.3 ) THEN** RANGE='I': Compute the interval containing eigenvalues* IL through IU.** Compute Gershgorin interval for entire (split) matrix* and use it as the initial interval*GU = D( 1 )GL = D( 1 )TMP1 = ZERO*DO 20 J = 1, N - 1TMP2 = SQRT( WORK( J ) )GU = MAX( GU, D( J )+TMP1+TMP2 )GL = MIN( GL, D( J )-TMP1-TMP2 )TMP1 = TMP220 CONTINUE*GU = MAX( GU, D( N )+TMP1 )GL = MIN( GL, D( N )-TMP1 )TNORM = MAX( ABS( GL ), ABS( GU ) )GL = GL - FUDGE*TNORM*ULP*N - FUDGE*TWO*PIVMINGU = GU + FUDGE*TNORM*ULP*N + FUDGE*PIVMIN** Compute Iteration parameters*ITMAX = INT( ( LOG( TNORM+PIVMIN )-LOG( PIVMIN ) ) /$ LOG( TWO ) ) + 2IF( ABSTOL.LE.ZERO ) THENATOLI = ULP*TNORMELSEATOLI = ABSTOLEND IF*WORK( N+1 ) = GLWORK( N+2 ) = GLWORK( N+3 ) = GUWORK( N+4 ) = GUWORK( N+5 ) = GLWORK( N+6 ) = GUIWORK( 1 ) = -1IWORK( 2 ) = -1IWORK( 3 ) = N + 1IWORK( 4 ) = N + 1IWORK( 5 ) = IL - 1IWORK( 6 ) = IU*CALL DLAEBZ( 3, ITMAX, N, 2, 2, NB, ATOLI, RTOLI, PIVMIN, D, E,$ WORK, IWORK( 5 ), WORK( N+1 ), WORK( N+5 ), IOUT,$ IWORK, W, IBLOCK, IINFO )*IF( IWORK( 6 ).EQ.IU ) THENWL = WORK( N+1 )WLU = WORK( N+3 )NWL = IWORK( 1 )WU = WORK( N+4 )WUL = WORK( N+2 )NWU = IWORK( 4 )ELSEWL = WORK( N+2 )WLU = WORK( N+4 )NWL = IWORK( 2 )WU = WORK( N+3 )WUL = WORK( N+1 )NWU = IWORK( 3 )END IF*IF( NWL.LT.0 .OR. NWL.GE.N .OR. NWU.LT.1 .OR. NWU.GT.N ) THENINFO = 4RETURNEND IFELSE** RANGE='A' or 'V' -- Set ATOLI*TNORM = MAX( ABS( D( 1 ) )+ABS( E( 1 ) ),$ ABS( D( N ) )+ABS( E( N-1 ) ) )*DO 30 J = 2, N - 1TNORM = MAX( TNORM, ABS( D( J ) )+ABS( E( J-1 ) )+$ ABS( E( J ) ) )30 CONTINUE*IF( ABSTOL.LE.ZERO ) THENATOLI = ULP*TNORMELSEATOLI = ABSTOLEND IF*IF( IRANGE.EQ.2 ) THENWL = VLWU = VUELSEWL = ZEROWU = ZEROEND IFEND IF** Find Eigenvalues -- Loop Over Blocks and recompute NWL and NWU.* NWL accumulates the number of eigenvalues .le. WL,* NWU accumulates the number of eigenvalues .le. WU*M = 0IEND = 0INFO = 0NWL = 0NWU = 0*DO 70 JB = 1, NSPLITIOFF = IENDIBEGIN = IOFF + 1IEND = ISPLIT( JB )IN = IEND - IOFF*IF( IN.EQ.1 ) THEN** Special Case -- IN=1*IF( IRANGE.EQ.1 .OR. WL.GE.D( IBEGIN )-PIVMIN )$ NWL = NWL + 1IF( IRANGE.EQ.1 .OR. WU.GE.D( IBEGIN )-PIVMIN )$ NWU = NWU + 1IF( IRANGE.EQ.1 .OR. ( WL.LT.D( IBEGIN )-PIVMIN .AND. WU.GE.$ D( IBEGIN )-PIVMIN ) ) THENM = M + 1W( M ) = D( IBEGIN )IBLOCK( M ) = JBEND IFELSE** General Case -- IN > 1** Compute Gershgorin Interval* and use it as the initial interval*GU = D( IBEGIN )GL = D( IBEGIN )TMP1 = ZERO*DO 40 J = IBEGIN, IEND - 1TMP2 = ABS( E( J ) )GU = MAX( GU, D( J )+TMP1+TMP2 )GL = MIN( GL, D( J )-TMP1-TMP2 )TMP1 = TMP240 CONTINUE*GU = MAX( GU, D( IEND )+TMP1 )GL = MIN( GL, D( IEND )-TMP1 )BNORM = MAX( ABS( GL ), ABS( GU ) )GL = GL - FUDGE*BNORM*ULP*IN - FUDGE*PIVMINGU = GU + FUDGE*BNORM*ULP*IN + FUDGE*PIVMIN** Compute ATOLI for the current submatrix*IF( ABSTOL.LE.ZERO ) THENATOLI = ULP*MAX( ABS( GL ), ABS( GU ) )ELSEATOLI = ABSTOLEND IF*IF( IRANGE.GT.1 ) THENIF( GU.LT.WL ) THENNWL = NWL + INNWU = NWU + INGO TO 70END IFGL = MAX( GL, WL )GU = MIN( GU, WU )IF( GL.GE.GU )$ GO TO 70END IF** Set Up Initial Interval*WORK( N+1 ) = GLWORK( N+IN+1 ) = GUCALL DLAEBZ( 1, 0, IN, IN, 1, NB, ATOLI, RTOLI, PIVMIN,$ D( IBEGIN ), E( IBEGIN ), WORK( IBEGIN ),$ IDUMMA, WORK( N+1 ), WORK( N+2*IN+1 ), IM,$ IWORK, W( M+1 ), IBLOCK( M+1 ), IINFO )*NWL = NWL + IWORK( 1 )NWU = NWU + IWORK( IN+1 )IWOFF = M - IWORK( 1 )** Compute Eigenvalues*ITMAX = INT( ( LOG( GU-GL+PIVMIN )-LOG( PIVMIN ) ) /$ LOG( TWO ) ) + 2CALL DLAEBZ( 2, ITMAX, IN, IN, 1, NB, ATOLI, RTOLI, PIVMIN,$ D( IBEGIN ), E( IBEGIN ), WORK( IBEGIN ),$ IDUMMA, WORK( N+1 ), WORK( N+2*IN+1 ), IOUT,$ IWORK, W( M+1 ), IBLOCK( M+1 ), IINFO )** Copy Eigenvalues Into W and IBLOCK* Use -JB for block number for unconverged eigenvalues.*DO 60 J = 1, IOUTTMP1 = HALF*( WORK( J+N )+WORK( J+IN+N ) )** Flag non-convergence.*IF( J.GT.IOUT-IINFO ) THENNCNVRG = .TRUE.IB = -JBELSEIB = JBEND IFDO 50 JE = IWORK( J ) + 1 + IWOFF,$ IWORK( J+IN ) + IWOFFW( JE ) = TMP1IBLOCK( JE ) = IB50 CONTINUE60 CONTINUE*M = M + IMEND IF70 CONTINUE** If RANGE='I', then (WL,WU) contains eigenvalues NWL+1,...,NWU* If NWL+1 < IL or NWU > IU, discard extra eigenvalues.*IF( IRANGE.EQ.3 ) THENIM = 0IDISCL = IL - 1 - NWLIDISCU = NWU - IU*IF( IDISCL.GT.0 .OR. IDISCU.GT.0 ) THENDO 80 JE = 1, MIF( W( JE ).LE.WLU .AND. IDISCL.GT.0 ) THENIDISCL = IDISCL - 1ELSE IF( W( JE ).GE.WUL .AND. IDISCU.GT.0 ) THENIDISCU = IDISCU - 1ELSEIM = IM + 1W( IM ) = W( JE )IBLOCK( IM ) = IBLOCK( JE )END IF80 CONTINUEM = IMEND IFIF( IDISCL.GT.0 .OR. IDISCU.GT.0 ) THEN** Code to deal with effects of bad arithmetic:* Some low eigenvalues to be discarded are not in (WL,WLU],* or high eigenvalues to be discarded are not in (WUL,WU]* so just kill off the smallest IDISCL/largest IDISCU* eigenvalues, by simply finding the smallest/largest* eigenvalue(s).** (If N(w) is monotone non-decreasing, this should never* happen.)*IF( IDISCL.GT.0 ) THENWKILL = WUDO 100 JDISC = 1, IDISCLIW = 0DO 90 JE = 1, MIF( IBLOCK( JE ).NE.0 .AND.$ ( W( JE ).LT.WKILL .OR. IW.EQ.0 ) ) THENIW = JEWKILL = W( JE )END IF90 CONTINUEIBLOCK( IW ) = 0100 CONTINUEEND IFIF( IDISCU.GT.0 ) THEN*WKILL = WLDO 120 JDISC = 1, IDISCUIW = 0DO 110 JE = 1, MIF( IBLOCK( JE ).NE.0 .AND.$ ( W( JE ).GT.WKILL .OR. IW.EQ.0 ) ) THENIW = JEWKILL = W( JE )END IF110 CONTINUEIBLOCK( IW ) = 0120 CONTINUEEND IFIM = 0DO 130 JE = 1, MIF( IBLOCK( JE ).NE.0 ) THENIM = IM + 1W( IM ) = W( JE )IBLOCK( IM ) = IBLOCK( JE )END IF130 CONTINUEM = IMEND IFIF( IDISCL.LT.0 .OR. IDISCU.LT.0 ) THENTOOFEW = .TRUE.END IFEND IF** If ORDER='B', do nothing -- the eigenvalues are already sorted* by block.* If ORDER='E', sort the eigenvalues from smallest to largest*IF( IORDER.EQ.1 .AND. NSPLIT.GT.1 ) THENDO 150 JE = 1, M - 1IE = 0TMP1 = W( JE )DO 140 J = JE + 1, MIF( W( J ).LT.TMP1 ) THENIE = JTMP1 = W( J )END IF140 CONTINUE*IF( IE.NE.0 ) THENITMP1 = IBLOCK( IE )W( IE ) = W( JE )IBLOCK( IE ) = IBLOCK( JE )W( JE ) = TMP1IBLOCK( JE ) = ITMP1END IF150 CONTINUEEND IF*INFO = 0IF( NCNVRG )$ INFO = INFO + 1IF( TOOFEW )$ INFO = INFO + 2RETURN** End of DSTEBZ*ENDSUBROUTINE DSTEIN( N, D, E, M, W, IBLOCK, ISPLIT, Z, LDZ, WORK,$ IWORK, IFAIL, INFO )** -- LAPACK routine (version 3.0) --* Univ. of Tennessee, Univ. of California Berkeley, NAG Ltd.,* Courant Institute, Argonne National Lab, and Rice University* September 30, 1994** .. Scalar Arguments ..INTEGER INFO, LDZ, M, N* ..* .. Array Arguments ..INTEGER IBLOCK( * ), IFAIL( * ), ISPLIT( * ),$ IWORK( * )DOUBLE PRECISION D( * ), E( * ), W( * ), WORK( * ), Z( LDZ, * )* ..** Purpose* =======** DSTEIN computes the eigenvectors of a real symmetric tridiagonal* matrix T corresponding to specified eigenvalues, using inverse* iteration.** The maximum number of iterations allowed for each eigenvector is* specified by an internal parameter MAXITS (currently set to 5).** Arguments* =========** N (input) INTEGER* The order of the matrix. N >= 0.** D (input) DOUBLE PRECISION array, dimension (N)* The n diagonal elements of the tridiagonal matrix T.** E (input) DOUBLE PRECISION array, dimension (N)* The (n-1) subdiagonal elements of the tridiagonal matrix* T, in elements 1 to N-1. E(N) need not be set.** M (input) INTEGER* The number of eigenvectors to be found. 0 <= M <= N.** W (input) DOUBLE PRECISION array, dimension (N)* The first M elements of W contain the eigenvalues for* which eigenvectors are to be computed. The eigenvalues* should be grouped by split-off block and ordered from* smallest to largest within the block. ( The output array* W from DSTEBZ with ORDER = 'B' is expected here. )** IBLOCK (input) INTEGER array, dimension (N)* The submatrix indices associated with the corresponding* eigenvalues in W; IBLOCK(i)=1 if eigenvalue W(i) belongs to* the first submatrix from the top, =2 if W(i) belongs to* the second submatrix, etc. ( The output array IBLOCK* from DSTEBZ is expected here. )** ISPLIT (input) INTEGER array, dimension (N)* The splitting points, at which T breaks up into submatrices.* The first submatrix consists of rows/columns 1 to* ISPLIT( 1 ), the second of rows/columns ISPLIT( 1 )+1* through ISPLIT( 2 ), etc.* ( The output array ISPLIT from DSTEBZ is expected here. )** Z (output) DOUBLE PRECISION array, dimension (LDZ, M)* The computed eigenvectors. The eigenvector associated* with the eigenvalue W(i) is stored in the i-th column of* Z. Any vector which fails to converge is set to its current* iterate after MAXITS iterations.** LDZ (input) INTEGER* The leading dimension of the array Z. LDZ >= max(1,N).** WORK (workspace) DOUBLE PRECISION array, dimension (5*N)** IWORK (workspace) INTEGER array, dimension (N)** IFAIL (output) INTEGER array, dimension (M)* On normal exit, all elements of IFAIL are zero.* If one or more eigenvectors fail to converge after* MAXITS iterations, then their indices are stored in* array IFAIL.** INFO (output) INTEGER* = 0: successful exit.* < 0: if INFO = -i, the i-th argument had an illegal value* > 0: if INFO = i, then i eigenvectors failed to converge* in MAXITS iterations. Their indices are stored in* array IFAIL.** Internal Parameters* ===================** MAXITS INTEGER, default = 5* The maximum number of iterations performed.** EXTRA INTEGER, default = 2* The number of iterations performed after norm growth* criterion is satisfied, should be at least 1.** =====================================================================** .. Parameters ..DOUBLE PRECISION ZERO, ONE, TEN, ODM3, ODM1PARAMETER ( ZERO = 0.0D+0, ONE = 1.0D+0, TEN = 1.0D+1,$ ODM3 = 1.0D-3, ODM1 = 1.0D-1 )INTEGER MAXITS, EXTRAPARAMETER ( MAXITS = 5, EXTRA = 2 )* ..* .. Local Scalars ..INTEGER B1, BLKSIZ, BN, GPIND, I, IINFO, INDRV1,$ INDRV2, INDRV3, INDRV4, INDRV5, ITS, J, J1,$ JBLK, JMAX, NBLK, NRMCHKDOUBLE PRECISION DTPCRT, EPS, EPS1, NRM, ONENRM, ORTOL, PERTOL,$ SCL, SEP, TOL, XJ, XJM, ZTR* ..* .. Local Arrays ..INTEGER ISEED( 4 )* ..* .. External Functions ..INTEGER IDAMAXDOUBLE PRECISION DASUM, DDOT, DLAMCH, DNRM2EXTERNAL IDAMAX, DASUM, DDOT, DLAMCH, DNRM2* ..* .. External Subroutines ..EXTERNAL DAXPY, DCOPY, DLAGTF, DLAGTS, DLARNV, DSCAL,$ XERBLA* ..* .. Intrinsic Functions ..INTRINSIC ABS, MAX, SQRT* ..* .. Executable Statements ..** Test the input parameters.*INFO = 0DO 10 I = 1, MIFAIL( I ) = 010 CONTINUE*IF( N.LT.0 ) THENINFO = -1ELSE IF( M.LT.0 .OR. M.GT.N ) THENINFO = -4ELSE IF( LDZ.LT.MAX( 1, N ) ) THENINFO = -9ELSEDO 20 J = 2, MIF( IBLOCK( J ).LT.IBLOCK( J-1 ) ) THENINFO = -6GO TO 30END IFIF( IBLOCK( J ).EQ.IBLOCK( J-1 ) .AND. W( J ).LT.W( J-1 ) )$ THENINFO = -5GO TO 30END IF20 CONTINUE30 CONTINUEEND IF*IF( INFO.NE.0 ) THENCALL XERBLA( 'DSTEIN', -INFO )RETURNEND IF** Quick return if possible*IF( N.EQ.0 .OR. M.EQ.0 ) THENRETURNELSE IF( N.EQ.1 ) THENZ( 1, 1 ) = ONERETURNEND IF** Get machine constants.*EPS = DLAMCH( 'Precision' )** Initialize seed for random number generator DLARNV.*DO 40 I = 1, 4ISEED( I ) = 140 CONTINUE** Initialize pointers.*INDRV1 = 0INDRV2 = INDRV1 + NINDRV3 = INDRV2 + NINDRV4 = INDRV3 + NINDRV5 = INDRV4 + N** Compute eigenvectors of matrix blocks.*J1 = 1DO 160 NBLK = 1, IBLOCK( M )** Find starting and ending indices of block nblk.*IF( NBLK.EQ.1 ) THENB1 = 1ELSEB1 = ISPLIT( NBLK-1 ) + 1END IFBN = ISPLIT( NBLK )BLKSIZ = BN - B1 + 1IF( BLKSIZ.EQ.1 )$ GO TO 60GPIND = B1** Compute reorthogonalization criterion and stopping criterion.*ONENRM = ABS( D( B1 ) ) + ABS( E( B1 ) )ONENRM = MAX( ONENRM, ABS( D( BN ) )+ABS( E( BN-1 ) ) )DO 50 I = B1 + 1, BN - 1ONENRM = MAX( ONENRM, ABS( D( I ) )+ABS( E( I-1 ) )+$ ABS( E( I ) ) )50 CONTINUEORTOL = ODM3*ONENRM*DTPCRT = SQRT( ODM1 / BLKSIZ )** Loop through eigenvalues of block nblk.*60 CONTINUEJBLK = 0DO 150 J = J1, MIF( IBLOCK( J ).NE.NBLK ) THENJ1 = JGO TO 160END IFJBLK = JBLK + 1XJ = W( J )** Skip all the work if the block size is one.*IF( BLKSIZ.EQ.1 ) THENWORK( INDRV1+1 ) = ONEGO TO 120END IF** If eigenvalues j and j-1 are too close, add a relatively* small perturbation.*IF( JBLK.GT.1 ) THENEPS1 = ABS( EPS*XJ )PERTOL = TEN*EPS1SEP = XJ - XJMIF( SEP.LT.PERTOL )$ XJ = XJM + PERTOLEND IF*ITS = 0NRMCHK = 0** Get random starting vector.*CALL DLARNV( 2, ISEED, BLKSIZ, WORK( INDRV1+1 ) )** Copy the matrix T so it won't be destroyed in factorization.*CALL DCOPY( BLKSIZ, D( B1 ), 1, WORK( INDRV4+1 ), 1 )CALL DCOPY( BLKSIZ-1, E( B1 ), 1, WORK( INDRV2+2 ), 1 )CALL DCOPY( BLKSIZ-1, E( B1 ), 1, WORK( INDRV3+1 ), 1 )** Compute LU factors with partial pivoting ( PT = LU )*TOL = ZEROCALL DLAGTF( BLKSIZ, WORK( INDRV4+1 ), XJ, WORK( INDRV2+2 ),$ WORK( INDRV3+1 ), TOL, WORK( INDRV5+1 ), IWORK,$ IINFO )** Update iteration count.*70 CONTINUEITS = ITS + 1IF( ITS.GT.MAXITS )$ GO TO 100** Normalize and scale the righthand side vector Pb.*SCL = BLKSIZ*ONENRM*MAX( EPS,$ ABS( WORK( INDRV4+BLKSIZ ) ) ) /$ DASUM( BLKSIZ, WORK( INDRV1+1 ), 1 )CALL DSCAL( BLKSIZ, SCL, WORK( INDRV1+1 ), 1 )** Solve the system LU = Pb.*CALL DLAGTS( -1, BLKSIZ, WORK( INDRV4+1 ), WORK( INDRV2+2 ),$ WORK( INDRV3+1 ), WORK( INDRV5+1 ), IWORK,$ WORK( INDRV1+1 ), TOL, IINFO )** Reorthogonalize by modified Gram-Schmidt if eigenvalues are* close enough.*IF( JBLK.EQ.1 )$ GO TO 90IF( ABS( XJ-XJM ).GT.ORTOL )$ GPIND = JIF( GPIND.NE.J ) THENDO 80 I = GPIND, J - 1ZTR = -DDOT( BLKSIZ, WORK( INDRV1+1 ), 1, Z( B1, I ),$ 1 )CALL DAXPY( BLKSIZ, ZTR, Z( B1, I ), 1,$ WORK( INDRV1+1 ), 1 )80 CONTINUEEND IF** Check the infinity norm of the iterate.*90 CONTINUEJMAX = IDAMAX( BLKSIZ, WORK( INDRV1+1 ), 1 )NRM = ABS( WORK( INDRV1+JMAX ) )** Continue for additional iterations after norm reaches* stopping criterion.*IF( NRM.LT.DTPCRT )$ GO TO 70NRMCHK = NRMCHK + 1IF( NRMCHK.LT.EXTRA+1 )$ GO TO 70*GO TO 110** If stopping criterion was not satisfied, update info and* store eigenvector number in array ifail.*100 CONTINUEINFO = INFO + 1IFAIL( INFO ) = J** Accept iterate as jth eigenvector.*110 CONTINUESCL = ONE / DNRM2( BLKSIZ, WORK( INDRV1+1 ), 1 )JMAX = IDAMAX( BLKSIZ, WORK( INDRV1+1 ), 1 )IF( WORK( INDRV1+JMAX ).LT.ZERO )$ SCL = -SCLCALL DSCAL( BLKSIZ, SCL, WORK( INDRV1+1 ), 1 )120 CONTINUEDO 130 I = 1, NZ( I, J ) = ZERO130 CONTINUEDO 140 I = 1, BLKSIZZ( B1+I-1, J ) = WORK( INDRV1+I )140 CONTINUE** Save the shift to check eigenvalue spacing at next* iteration.*XJM = XJ*150 CONTINUE160 CONTINUE*RETURN** End of DSTEIN*ENDSUBROUTINE DORMQL( SIDE, TRANS, M, N, K, A, LDA, TAU, C, LDC,$ WORK, LWORK, INFO )** -- LAPACK routine (version 3.0) --* Univ. of Tennessee, Univ. of California Berkeley, NAG Ltd.,* Courant Institute, Argonne National Lab, and Rice University* June 30, 1999** .. Scalar Arguments ..CHARACTER SIDE, TRANSINTEGER INFO, K, LDA, LDC, LWORK, M, N* ..* .. Array Arguments ..DOUBLE PRECISION A( LDA, * ), C( LDC, * ), TAU( * ), WORK( * )* ..** Purpose* =======** DORMQL overwrites the general real M-by-N matrix C with** SIDE = 'L' SIDE = 'R'* TRANS = 'N': Q * C C * Q* TRANS = 'T': Q**T * C C * Q**T** where Q is a real orthogonal matrix defined as the product of k* elementary reflectors** Q = H(k) . . . H(2) H(1)** as returned by DGEQLF. Q is of order M if SIDE = 'L' and of order N* if SIDE = 'R'.** Arguments* =========** SIDE (input) CHARACTER*1* = 'L': apply Q or Q**T from the Left;* = 'R': apply Q or Q**T from the Right.** TRANS (input) CHARACTER*1* = 'N': No transpose, apply Q;* = 'T': Transpose, apply Q**T.** M (input) INTEGER* The number of rows of the matrix C. M >= 0.** N (input) INTEGER* The number of columns of the matrix C. N >= 0.** K (input) INTEGER* The number of elementary reflectors whose product defines* the matrix Q.* If SIDE = 'L', M >= K >= 0;* if SIDE = 'R', N >= K >= 0.** A (input) DOUBLE PRECISION array, dimension (LDA,K)* The i-th column must contain the vector which defines the* elementary reflector H(i), for i = 1,2,...,k, as returned by* DGEQLF in the last k columns of its array argument A.* A is modified by the routine but restored on exit.** LDA (input) INTEGER* The leading dimension of the array A.* If SIDE = 'L', LDA >= max(1,M);* if SIDE = 'R', LDA >= max(1,N).** TAU (input) DOUBLE PRECISION array, dimension (K)* TAU(i) must contain the scalar factor of the elementary* reflector H(i), as returned by DGEQLF.** C (input/output) DOUBLE PRECISION array, dimension (LDC,N)* On entry, the M-by-N matrix C.* On exit, C is overwritten by Q*C or Q**T*C or C*Q**T or C*Q.** LDC (input) INTEGER* The leading dimension of the array C. LDC >= max(1,M).** WORK (workspace/output) DOUBLE PRECISION array, dimension (LWORK)* On exit, if INFO = 0, WORK(1) returns the optimal LWORK.** LWORK (input) INTEGER* The dimension of the array WORK.* If SIDE = 'L', LWORK >= max(1,N);* if SIDE = 'R', LWORK >= max(1,M).* For optimum performance LWORK >= N*NB if SIDE = 'L', and* LWORK >= M*NB if SIDE = 'R', where NB is the optimal* blocksize.** If LWORK = -1, then a workspace query is assumed; the routine* only calculates the optimal size of the WORK array, returns* this value as the first entry of the WORK array, and no error* message related to LWORK is issued by XERBLA.** INFO (output) INTEGER* = 0: successful exit* < 0: if INFO = -i, the i-th argument had an illegal value** =====================================================================** .. Parameters ..INTEGER NBMAX, LDTPARAMETER ( NBMAX = 64, LDT = NBMAX+1 )* ..* .. Local Scalars ..LOGICAL LEFT, LQUERY, NOTRANINTEGER I, I1, I2, I3, IB, IINFO, IWS, LDWORK, LWKOPT,$ MI, NB, NBMIN, NI, NQ, NW* ..* .. Local Arrays ..DOUBLE PRECISION T( LDT, NBMAX )* ..* .. External Functions ..LOGICAL LSAMEINTEGER ILAENVEXTERNAL LSAME, ILAENV* ..* .. External Subroutines ..EXTERNAL DLARFB, DLARFT, DORM2L, XERBLA* ..* .. Intrinsic Functions ..INTRINSIC MAX, MIN* ..* .. Executable Statements ..** Test the input arguments*INFO = 0LEFT = LSAME( SIDE, 'L' )NOTRAN = LSAME( TRANS, 'N' )LQUERY = ( LWORK.EQ.-1 )** NQ is the order of Q and NW is the minimum dimension of WORK*IF( LEFT ) THENNQ = MNW = NELSENQ = NNW = MEND IFIF( .NOT.LEFT .AND. .NOT.LSAME( SIDE, 'R' ) ) THENINFO = -1ELSE IF( .NOT.NOTRAN .AND. .NOT.LSAME( TRANS, 'T' ) ) THENINFO = -2ELSE IF( M.LT.0 ) THENINFO = -3ELSE IF( N.LT.0 ) THENINFO = -4ELSE IF( K.LT.0 .OR. K.GT.NQ ) THENINFO = -5ELSE IF( LDA.LT.MAX( 1, NQ ) ) THENINFO = -7ELSE IF( LDC.LT.MAX( 1, M ) ) THENINFO = -10ELSE IF( LWORK.LT.MAX( 1, NW ) .AND. .NOT.LQUERY ) THENINFO = -12END IF*IF( INFO.EQ.0 ) THEN** Determine the block size. NB may be at most NBMAX, where NBMAX* is used to define the local array T.*NB = MIN( NBMAX, ILAENV( 1, 'DORMQL', SIDE // TRANS, M, N, K,$ -1 ) )LWKOPT = MAX( 1, NW )*NBWORK( 1 ) = LWKOPTEND IF*IF( INFO.NE.0 ) THENCALL XERBLA( 'DORMQL', -INFO )RETURNELSE IF( LQUERY ) THENRETURNEND IF** Quick return if possible*IF( M.EQ.0 .OR. N.EQ.0 .OR. K.EQ.0 ) THENWORK( 1 ) = 1RETURNEND IF*NBMIN = 2LDWORK = NWIF( NB.GT.1 .AND. NB.LT.K ) THENIWS = NW*NBIF( LWORK.LT.IWS ) THENNB = LWORK / LDWORKNBMIN = MAX( 2, ILAENV( 2, 'DORMQL', SIDE // TRANS, M, N, K,$ -1 ) )END IFELSEIWS = NWEND IF*IF( NB.LT.NBMIN .OR. NB.GE.K ) THEN** Use unblocked code*CALL DORM2L( SIDE, TRANS, M, N, K, A, LDA, TAU, C, LDC, WORK,$ IINFO )ELSE** Use blocked code*IF( ( LEFT .AND. NOTRAN ) .OR.$ ( .NOT.LEFT .AND. .NOT.NOTRAN ) ) THENI1 = 1I2 = KI3 = NBELSEI1 = ( ( K-1 ) / NB )*NB + 1I2 = 1I3 = -NBEND IF*IF( LEFT ) THENNI = NELSEMI = MEND IF*DO 10 I = I1, I2, I3IB = MIN( NB, K-I+1 )** Form the triangular factor of the block reflector* H = H(i+ib-1) . . . H(i+1) H(i)*CALL DLARFT( 'Backward', 'Columnwise', NQ-K+I+IB-1, IB,$ A( 1, I ), LDA, TAU( I ), T, LDT )IF( LEFT ) THEN** H or H' is applied to C(1:m-k+i+ib-1,1:n)*MI = M - K + I + IB - 1ELSE** H or H' is applied to C(1:m,1:n-k+i+ib-1)*NI = N - K + I + IB - 1END IF** Apply H or H'*CALL DLARFB( SIDE, TRANS, 'Backward', 'Columnwise', MI, NI,$ IB, A( 1, I ), LDA, T, LDT, C, LDC, WORK,$ LDWORK )10 CONTINUEEND IFWORK( 1 ) = LWKOPTRETURN** End of DORMQL*ENDSUBROUTINE DLARRE( N, D, E, TOL, NSPLIT, ISPLIT, M, W, WOFF,$ GERSCH, WORK, INFO )** -- LAPACK auxiliary 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, M, N, NSPLITDOUBLE PRECISION TOL* ..* .. Array Arguments ..INTEGER ISPLIT( * )DOUBLE PRECISION D( * ), E( * ), GERSCH( * ), W( * ), WOFF( * ),$ WORK( * )* ..** Purpose* =======** Given the tridiagonal matrix T, DLARRE sets "small" off-diagonal* elements to zero, and for each unreduced block T_i, it finds* (i) the numbers sigma_i* (ii) the base T_i - sigma_i I = L_i D_i L_i^T representations and* (iii) eigenvalues of each L_i D_i L_i^T.* The representations and eigenvalues found are then used by* DSTEGR to compute the eigenvectors of a symmetric tridiagonal* matrix. Currently, the base representations are limited to being* positive or negative definite, and the eigenvalues of the definite* matrices are found by the dqds algorithm (subroutine DLASQ2). As* an added benefit, DLARRE also outputs the n Gerschgorin* intervals for each L_i D_i L_i^T.** Arguments* =========** N (input) INTEGER* The order of the matrix.** D (input/output) DOUBLE PRECISION array, dimension (N)* On entry, the n diagonal elements of the tridiagonal* matrix T.* On exit, the n diagonal elements of the diagonal* matrices D_i.** E (input/output) DOUBLE PRECISION array, dimension (N)* On entry, the (n-1) subdiagonal elements of the tridiagonal* matrix T; E(N) need not be set.* On exit, the subdiagonal elements of the unit bidiagonal* matrices L_i.** TOL (input) DOUBLE PRECISION* The threshold for splitting. If on input |E(i)| < TOL, then* the matrix T is split into smaller blocks.** NSPLIT (input) INTEGER* The number of blocks T splits into. 1 <= NSPLIT <= N.** ISPLIT (output) INTEGER array, dimension (2*N)* The splitting points, at which T breaks up into submatrices.* The first submatrix consists of rows/columns 1 to ISPLIT(1),* the second of rows/columns ISPLIT(1)+1 through ISPLIT(2),* etc., and the NSPLIT-th consists of rows/columns* ISPLIT(NSPLIT-1)+1 through ISPLIT(NSPLIT)=N.** M (output) INTEGER* The total number of eigenvalues (of all the L_i D_i L_i^T)* found.** W (output) DOUBLE PRECISION array, dimension (N)* The first M elements contain the eigenvalues. The* eigenvalues of each of the blocks, L_i D_i L_i^T, are* sorted in ascending order.** WOFF (output) DOUBLE PRECISION array, dimension (N)* The NSPLIT base points sigma_i.** GERSCH (output) DOUBLE PRECISION array, dimension (2*N)* The n Gerschgorin intervals.** WORK (input) DOUBLE PRECISION array, dimension (4*N???)* Workspace.** INFO (output) INTEGER* Output error code from DLASQ2** Further Details* ===============** Based on contributions by* Inderjit Dhillon, IBM Almaden, USA* Osni Marques, LBNL/NERSC, USA** =====================================================================** .. Parameters ..DOUBLE PRECISION ZERO, ONE, TWO, FOUR, FOURTHPARAMETER ( ZERO = 0.0D0, ONE = 1.0D0, TWO = 2.0D0,$ FOUR = 4.0D0, FOURTH = ONE / FOUR )* ..* .. Local Scalars ..INTEGER CNT, I, IBEGIN, IEND, IN, J, JBLK, MAXCNTDOUBLE PRECISION DELTA, EPS, GL, GU, NRM, OFFD, S, SGNDEF,$ SIGMA, TAU, TMP1, WIDTH* ..* .. External Functions ..DOUBLE PRECISION DLAMCHEXTERNAL DLAMCH* ..* .. External Subroutines ..EXTERNAL DCOPY, DLASQ2* ..* .. Intrinsic Functions ..INTRINSIC ABS, MAX, MIN* ..* .. Executable Statements ..*INFO = 0EPS = DLAMCH( 'Precision' )** Compute Splitting Points*NSPLIT = 1DO 10 I = 1, N - 1IF( ABS( E( I ) ).LE.TOL ) THENISPLIT( NSPLIT ) = INSPLIT = NSPLIT + 1END IF10 CONTINUEISPLIT( NSPLIT ) = N*IBEGIN = 1DO 170 JBLK = 1, NSPLITIEND = ISPLIT( JBLK )IF( IBEGIN.EQ.IEND ) THENW( IBEGIN ) = D( IBEGIN )WOFF( JBLK ) = ZEROIBEGIN = IEND + 1GO TO 170END IFIN = IEND - IBEGIN + 1** Form the n Gerschgorin intervals*GL = D( IBEGIN ) - ABS( E( IBEGIN ) )GU = D( IBEGIN ) + ABS( E( IBEGIN ) )GERSCH( 2*IBEGIN-1 ) = GLGERSCH( 2*IBEGIN ) = GUGERSCH( 2*IEND-1 ) = D( IEND ) - ABS( E( IEND-1 ) )GERSCH( 2*IEND ) = D( IEND ) + ABS( E( IEND-1 ) )GL = MIN( GERSCH( 2*IEND-1 ), GL )GU = MAX( GERSCH( 2*IEND ), GU )DO 20 I = IBEGIN + 1, IEND - 1OFFD = ABS( E( I-1 ) ) + ABS( E( I ) )GERSCH( 2*I-1 ) = D( I ) - OFFDGL = MIN( GERSCH( 2*I-1 ), GL )GERSCH( 2*I ) = D( I ) + OFFDGU = MAX( GERSCH( 2*I ), GU )20 CONTINUENRM = MAX( ABS( GL ), ABS( GU ) )** Find the number SIGMA where the base representation* T - sigma I = L D L^T is to be formed.*WIDTH = GU - GLDO 30 I = IBEGIN, IEND - 1WORK( I ) = E( I )*E( I )30 CONTINUEDO 50 J = 1, 2IF( J.EQ.1 ) THENTAU = GL + FOURTH*WIDTHELSETAU = GU - FOURTH*WIDTHEND IFTMP1 = D( IBEGIN ) - TAUIF( TMP1.LT.ZERO ) THENCNT = 1ELSECNT = 0END IFDO 40 I = IBEGIN + 1, IENDTMP1 = D( I ) - TAU - WORK( I-1 ) / TMP1IF( TMP1.LT.ZERO )$ CNT = CNT + 140 CONTINUEIF( CNT.EQ.0 ) THENGL = TAUELSE IF( CNT.EQ.IN ) THENGU = TAUEND IFIF( J.EQ.1 ) THENMAXCNT = CNTSIGMA = GLSGNDEF = ONEELSEIF( IN-CNT.GT.MAXCNT ) THENSIGMA = GUSGNDEF = -ONEEND IFEND IF50 CONTINUE** Find the base L D L^T representation*WORK( 3*IN ) = ONEDELTA = EPSTAU = SGNDEF*NRM60 CONTINUESIGMA = SIGMA - DELTA*TAUWORK( 1 ) = D( IBEGIN ) - SIGMAJ = IBEGINDO 70 I = 1, IN - 1WORK( 2*IN+I ) = ONE / WORK( 2*I-1 )TMP1 = E( J )*WORK( 2*IN+I )WORK( 2*I+1 ) = ( D( J+1 )-SIGMA ) - TMP1*E( J )WORK( 2*I ) = TMP1J = J + 170 CONTINUEDO 80 I = IN, 1, -1TMP1 = SGNDEF*WORK( 2*I-1 )IF( TMP1.LT.ZERO .OR. WORK( 2*IN+I ).EQ.ZERO .OR. .NOT.$ ( TMP1.GT.ZERO .OR. TMP1.LT.ONE ) ) THENDELTA = TWO*DELTAGO TO 60END IFJ = J - 180 CONTINUE*J = IBEGIND( IBEGIN ) = WORK( 1 )WORK( 1 ) = ABS( WORK( 1 ) )DO 90 I = 1, IN - 1TMP1 = E( J )E( J ) = WORK( 2*I )WORK( 2*I ) = ABS( TMP1*WORK( 2*I ) )J = J + 1D( J ) = WORK( 2*I+1 )WORK( 2*I+1 ) = ABS( WORK( 2*I+1 ) )90 CONTINUE*CALL DLASQ2( IN, WORK, INFO )*TAU = SGNDEF*WORK( IN )WORK( 3*IN ) = ONEDELTA = TWO*EPS100 CONTINUETAU = TAU*( ONE-DELTA )*S = -TAUJ = IBEGINDO 110 I = 1, IN - 1WORK( I ) = D( J ) + SWORK( 2*IN+I ) = ONE / WORK( I )* WORK( N+I ) = ( E( I ) * D( I ) ) / WORK( I )WORK( IN+I ) = ( E( J )*D( J ) )*WORK( 2*IN+I )S = S*WORK( IN+I )*E( J ) - TAUJ = J + 1110 CONTINUEWORK( IN ) = D( IEND ) + S** Checking to see if all the diagonal elements of the new* L D L^T representation have the same sign*DO 120 I = IN, 1, -1TMP1 = SGNDEF*WORK( I )IF( TMP1.LT.ZERO .OR. WORK( 2*IN+I ).EQ.ZERO .OR. .NOT.$ ( TMP1.GT.ZERO .OR. TMP1.LT.ONE ) ) THENDELTA = TWO*DELTAGO TO 100END IF120 CONTINUE*SIGMA = SIGMA + TAUCALL DCOPY( IN, WORK, 1, D( IBEGIN ), 1 )CALL DCOPY( IN-1, WORK( IN+1 ), 1, E( IBEGIN ), 1 )WOFF( JBLK ) = SIGMA** Update the n Gerschgorin intervals*DO 130 I = IBEGIN, IENDGERSCH( 2*I-1 ) = GERSCH( 2*I-1 ) - SIGMAGERSCH( 2*I ) = GERSCH( 2*I ) - SIGMA130 CONTINUE** Compute the eigenvalues of L D L^T.*J = IBEGINDO 140 I = 1, IN - 1WORK( 2*I-1 ) = ABS( D( J ) )WORK( 2*I ) = E( J )*E( J )*WORK( 2*I-1 )J = J + 1140 CONTINUEWORK( 2*IN-1 ) = ABS( D( IEND ) )*CALL DLASQ2( IN, WORK, INFO )*J = IBEGINIF( SGNDEF.GT.ZERO ) THENDO 150 I = 1, INW( J ) = WORK( IN-I+1 )J = J + 1150 CONTINUEELSEDO 160 I = 1, INW( J ) = -WORK( I )J = J + 1160 CONTINUEEND IFIBEGIN = IEND + 1170 CONTINUEM = N*RETURN** End of DLARRE*ENDSUBROUTINE DLARRV( N, D, L, ISPLIT, M, W, IBLOCK, GERSCH, TOL, Z,$ LDZ, ISUPPZ, WORK, IWORK, INFO )** -- LAPACK auxiliary 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, LDZ, M, NDOUBLE PRECISION TOL* ..* .. Array Arguments ..INTEGER IBLOCK( * ), ISPLIT( * ), ISUPPZ( * ),$ IWORK( * )DOUBLE PRECISION D( * ), GERSCH( * ), L( * ), W( * ), WORK( * ),$ Z( LDZ, * )* ..** Purpose* =======** DLARRV computes the eigenvectors of the tridiagonal matrix* T = L D L^T given L, D and the eigenvalues of L D L^T.* The input eigenvalues should have high relative accuracy with* respect to the entries of L and D. The desired accuracy of the* output can be specified by the input parameter TOL.** Arguments* =========** N (input) INTEGER* The order of the matrix. N >= 0.** D (input/output) DOUBLE PRECISION array, dimension (N)* On entry, the n diagonal elements of the diagonal matrix D.* On exit, D may be overwritten.** L (input/output) DOUBLE PRECISION array, dimension (N-1)* On entry, the (n-1) subdiagonal elements of the unit* bidiagonal matrix L in elements 1 to N-1 of L. L(N) need* not be set. On exit, L is overwritten.** ISPLIT (input) INTEGER array, dimension (N)* The splitting points, at which T breaks up into submatrices.* The first submatrix consists of rows/columns 1 to* ISPLIT( 1 ), the second of rows/columns ISPLIT( 1 )+1* through ISPLIT( 2 ), etc.** TOL (input) DOUBLE PRECISION* The absolute error tolerance for the* eigenvalues/eigenvectors.* Errors in the input eigenvalues must be bounded by TOL.* The eigenvectors output have residual norms* bounded by TOL, and the dot products between different* eigenvectors are bounded by TOL. TOL must be at least* N*EPS*|T|, where EPS is the machine precision and |T| is* the 1-norm of the tridiagonal matrix.** M (input) INTEGER* The total number of eigenvalues found. 0 <= M <= N.* If RANGE = 'A', M = N, and if RANGE = 'I', M = IU-IL+1.** W (input) DOUBLE PRECISION array, dimension (N)* The first M elements of W contain the eigenvalues for* which eigenvectors are to be computed. The eigenvalues* should be grouped by split-off block and ordered from* smallest to largest within the block ( The output array* W from DLARRE is expected here ).* Errors in W must be bounded by TOL (see above).** IBLOCK (input) INTEGER array, dimension (N)* The submatrix indices associated with the corresponding* eigenvalues in W; IBLOCK(i)=1 if eigenvalue W(i) belongs to* the first submatrix from the top, =2 if W(i) belongs to* the second submatrix, etc.** Z (output) DOUBLE PRECISION array, dimension (LDZ, max(1,M) )* If JOBZ = 'V', then if INFO = 0, the first M columns of Z* contain the orthonormal eigenvectors of the matrix T* corresponding to the selected eigenvalues, with the i-th* column of Z holding the eigenvector associated with W(i).* If JOBZ = 'N', then Z is not referenced.* Note: the user must ensure that at least max(1,M) columns are* supplied in the array Z; if RANGE = 'V', the exact value of M* is not known in advance and an upper bound must be used.** LDZ (input) INTEGER* The leading dimension of the array Z. LDZ >= 1, and if* JOBZ = 'V', LDZ >= max(1,N).** ISUPPZ (output) INTEGER ARRAY, dimension ( 2*max(1,M) )* The support of the eigenvectors in Z, i.e., the indices* indicating the nonzero elements in Z. The i-th eigenvector* is nonzero only in elements ISUPPZ( 2*i-1 ) through* ISUPPZ( 2*i ).** WORK (workspace) DOUBLE PRECISION array, dimension (13*N)** IWORK (workspace) INTEGER array, dimension (6*N)** INFO (output) INTEGER* = 0: successful exit* < 0: if INFO = -i, the i-th argument had an illegal value* > 0: if INFO = 1, internal error in DLARRB* if INFO = 2, internal error in DSTEIN** Further Details* ===============** Based on contributions by* Inderjit Dhillon, IBM Almaden, USA* Osni Marques, LBNL/NERSC, USA** =====================================================================** .. Parameters ..INTEGER MGSSIZPARAMETER ( MGSSIZ = 20 )DOUBLE PRECISION ZERO, ONE, FOURPARAMETER ( ZERO = 0.0D0, ONE = 1.0D0, FOUR = 4.0D0 )* ..* .. Local Scalars ..LOGICAL MGSCLSINTEGER I, IBEGIN, IEND, IINDC1, IINDC2, IINDR, IINDWK,$ IINFO, IM, IN, INDERR, INDGAP, INDLD, INDLLD,$ INDWRK, ITER, ITMP1, ITMP2, J, JBLK, K, KTOT,$ LSBDPT, MAXITR, NCLUS, NDEPTH, NDONE, NEWCLS,$ NEWFRS, NEWFTT, NEWLST, NEWSIZ, NSPLIT, OLDCLS,$ OLDFST, OLDIEN, OLDLST, OLDNCL, P, QDOUBLE PRECISION EPS, GAP, LAMBDA, MGSTOL, MINGMA, MINRGP,$ NRMINV, RELGAP, RELTOL, RESID, RQCORR, SIGMA,$ TMP1, ZTZ* ..* .. External Functions ..DOUBLE PRECISION DDOT, DLAMCH, DNRM2EXTERNAL DDOT, DLAMCH, DNRM2* ..* .. External Subroutines ..EXTERNAL DAXPY, DCOPY, DLAR1V, DLARRB, DLARRF, DLASET,$ DSCAL, DSTEIN* ..* .. Intrinsic Functions ..INTRINSIC ABS, DBLE, MAX, MIN, SQRT* ..* .. Local Arrays ..INTEGER TEMP( 1 )* ..* .. Executable Statements ..** Test the input parameters.*INDERR = N + 1INDLD = 2*NINDLLD = 3*NINDGAP = 4*NINDWRK = 5*N + 1*IINDR = NIINDC1 = 2*NIINDC2 = 3*NIINDWK = 4*N + 1*EPS = DLAMCH( 'Precision' )*DO 10 I = 1, 2*NIWORK( I ) = 010 CONTINUEDO 20 I = 1, MWORK( INDERR+I-1 ) = EPS*ABS( W( I ) )20 CONTINUECALL DLASET( 'Full', N, N, ZERO, ZERO, Z, LDZ )MGSTOL = 5.0D0*EPS*NSPLIT = IBLOCK( M )IBEGIN = 1DO 170 JBLK = 1, NSPLITIEND = ISPLIT( JBLK )** Find the eigenvectors of the submatrix indexed IBEGIN* through IEND.*IF( IBEGIN.EQ.IEND ) THENZ( IBEGIN, IBEGIN ) = ONEISUPPZ( 2*IBEGIN-1 ) = IBEGINISUPPZ( 2*IBEGIN ) = IBEGINIBEGIN = IEND + 1GO TO 170END IFOLDIEN = IBEGIN - 1IN = IEND - OLDIENRELTOL = MIN( 1.0D-2, ONE / DBLE( IN ) )IM = INCALL DCOPY( IM, W( IBEGIN ), 1, WORK, 1 )DO 30 I = 1, IN - 1WORK( INDGAP+I ) = WORK( I+1 ) - WORK( I )30 CONTINUEWORK( INDGAP+IN ) = MAX( ABS( WORK( IN ) ), EPS )NDONE = 0*NDEPTH = 0LSBDPT = 1NCLUS = 1IWORK( IINDC1+1 ) = 1IWORK( IINDC1+2 ) = IN** While( NDONE.LT.IM ) do*40 CONTINUEIF( NDONE.LT.IM ) THENOLDNCL = NCLUSNCLUS = 0LSBDPT = 1 - LSBDPTDO 150 I = 1, OLDNCLIF( LSBDPT.EQ.0 ) THENOLDCLS = IINDC1NEWCLS = IINDC2ELSEOLDCLS = IINDC2NEWCLS = IINDC1END IF** If NDEPTH > 1, retrieve the relatively robust* representation (RRR) and perform limited bisection* (if necessary) to get approximate eigenvalues.*J = OLDCLS + 2*IOLDFST = IWORK( J-1 )OLDLST = IWORK( J )IF( NDEPTH.GT.0 ) THENJ = OLDIEN + OLDFSTCALL DCOPY( IN, Z( IBEGIN, J ), 1, D( IBEGIN ), 1 )CALL DCOPY( IN, Z( IBEGIN, J+1 ), 1, L( IBEGIN ), 1 )SIGMA = L( IEND )END IFK = IBEGINDO 50 J = 1, IN - 1WORK( INDLD+J ) = D( K )*L( K )WORK( INDLLD+J ) = WORK( INDLD+J )*L( K )K = K + 150 CONTINUEIF( NDEPTH.GT.0 ) THENCALL DLARRB( IN, D( IBEGIN ), L( IBEGIN ),$ WORK( INDLD+1 ), WORK( INDLLD+1 ),$ OLDFST, OLDLST, SIGMA, RELTOL, WORK,$ WORK( INDGAP+1 ), WORK( INDERR ),$ WORK( INDWRK ), IWORK( IINDWK ), IINFO )IF( IINFO.NE.0 ) THENINFO = 1RETURNEND IFEND IF** Classify eigenvalues of the current representation (RRR)* as (i) isolated, (ii) loosely clustered or (iii) tightly* clustered*NEWFRS = OLDFSTDO 140 J = OLDFST, OLDLSTIF( J.EQ.OLDLST .OR. WORK( INDGAP+J ).GE.RELTOL*$ ABS( WORK( J ) ) ) THENNEWLST = JELSE** continue (to the next loop)*RELGAP = WORK( INDGAP+J ) / ABS( WORK( J ) )IF( J.EQ.NEWFRS ) THENMINRGP = RELGAPELSEMINRGP = MIN( MINRGP, RELGAP )END IFGO TO 140END IFNEWSIZ = NEWLST - NEWFRS + 1MAXITR = 10NEWFTT = OLDIEN + NEWFRSIF( NEWSIZ.GT.1 ) THENMGSCLS = NEWSIZ.LE.MGSSIZ .AND. MINRGP.GE.MGSTOLIF( .NOT.MGSCLS ) THENCALL DLARRF( IN, D( IBEGIN ), L( IBEGIN ),$ WORK( INDLD+1 ), WORK( INDLLD+1 ),$ NEWFRS, NEWLST, WORK,$ Z( IBEGIN, NEWFTT ),$ Z( IBEGIN, NEWFTT+1 ),$ WORK( INDWRK ), IWORK( IINDWK ),$ INFO )IF( INFO.EQ.0 ) THENNCLUS = NCLUS + 1K = NEWCLS + 2*NCLUSIWORK( K-1 ) = NEWFRSIWORK( K ) = NEWLSTELSEINFO = 0IF( MINRGP.GE.MGSTOL ) THENMGSCLS = .TRUE.ELSE** Call DSTEIN to process this tight cluster.* This happens only if MINRGP <= MGSTOL* and DLARRF returns INFO = 1. The latter* means that a new RRR to "break" the* cluster could not be found.*WORK( INDWRK ) = D( IBEGIN )DO 60 K = 1, IN - 1WORK( INDWRK+K ) = D( IBEGIN+K ) +$ WORK( INDLLD+K )60 CONTINUEDO 70 K = 1, NEWSIZIWORK( IINDWK+K-1 ) = 170 CONTINUEDO 80 K = NEWFRS, NEWLSTISUPPZ( 2*( IBEGIN+K )-3 ) = 1ISUPPZ( 2*( IBEGIN+K )-2 ) = IN80 CONTINUETEMP( 1 ) = INCALL DSTEIN( IN, WORK( INDWRK ),$ WORK( INDLD+1 ), NEWSIZ,$ WORK( NEWFRS ),$ IWORK( IINDWK ), TEMP( 1 ),$ Z( IBEGIN, NEWFTT ), LDZ,$ WORK( INDWRK+IN ),$ IWORK( IINDWK+IN ),$ IWORK( IINDWK+2*IN ), IINFO )IF( IINFO.NE.0 ) THENINFO = 2RETURNEND IFNDONE = NDONE + NEWSIZEND IFEND IFEND IFELSEMGSCLS = .FALSE.END IFIF( NEWSIZ.EQ.1 .OR. MGSCLS ) THENKTOT = NEWFTTDO 100 K = NEWFRS, NEWLSTITER = 090 CONTINUELAMBDA = WORK( K )CALL DLAR1V( IN, 1, IN, LAMBDA, D( IBEGIN ),$ L( IBEGIN ), WORK( INDLD+1 ),$ WORK( INDLLD+1 ),$ GERSCH( 2*OLDIEN+1 ),$ Z( IBEGIN, KTOT ), ZTZ, MINGMA,$ IWORK( IINDR+KTOT ),$ ISUPPZ( 2*KTOT-1 ),$ WORK( INDWRK ) )TMP1 = ONE / ZTZNRMINV = SQRT( TMP1 )RESID = ABS( MINGMA )*NRMINVRQCORR = MINGMA*TMP1IF( K.EQ.IN ) THENGAP = WORK( INDGAP+K-1 )ELSE IF( K.EQ.1 ) THENGAP = WORK( INDGAP+K )ELSEGAP = MIN( WORK( INDGAP+K-1 ),$ WORK( INDGAP+K ) )END IFITER = ITER + 1IF( RESID.GT.TOL*GAP .AND. ABS( RQCORR ).GT.$ FOUR*EPS*ABS( LAMBDA ) ) THENWORK( K ) = LAMBDA + RQCORRIF( ITER.LT.MAXITR ) THENGO TO 90END IFEND IFIWORK( KTOT ) = 1IF( NEWSIZ.EQ.1 )$ NDONE = NDONE + 1CALL DSCAL( IN, NRMINV, Z( IBEGIN, KTOT ), 1 )KTOT = KTOT + 1100 CONTINUEIF( NEWSIZ.GT.1 ) THENITMP1 = ISUPPZ( 2*NEWFTT-1 )ITMP2 = ISUPPZ( 2*NEWFTT )KTOT = OLDIEN + NEWLSTDO 120 P = NEWFTT + 1, KTOTDO 110 Q = NEWFTT, P - 1TMP1 = -DDOT( IN, Z( IBEGIN, P ), 1,$ Z( IBEGIN, Q ), 1 )CALL DAXPY( IN, TMP1, Z( IBEGIN, Q ), 1,$ Z( IBEGIN, P ), 1 )110 CONTINUETMP1 = ONE / DNRM2( IN, Z( IBEGIN, P ), 1 )CALL DSCAL( IN, TMP1, Z( IBEGIN, P ), 1 )ITMP1 = MIN( ITMP1, ISUPPZ( 2*P-1 ) )ITMP2 = MAX( ITMP2, ISUPPZ( 2*P ) )120 CONTINUEDO 130 P = NEWFTT, KTOTISUPPZ( 2*P-1 ) = ITMP1ISUPPZ( 2*P ) = ITMP2130 CONTINUENDONE = NDONE + NEWSIZEND IFEND IFNEWFRS = J + 1140 CONTINUE150 CONTINUENDEPTH = NDEPTH + 1GO TO 40END IFJ = 2*IBEGINDO 160 I = IBEGIN, IENDISUPPZ( J-1 ) = ISUPPZ( J-1 ) + OLDIENISUPPZ( J ) = ISUPPZ( J ) + OLDIENJ = J + 2160 CONTINUEIBEGIN = IEND + 1170 CONTINUE*RETURN** End of DLARRV*ENDSUBROUTINE DLAEBZ( IJOB, NITMAX, N, MMAX, MINP, NBMIN, ABSTOL,$ RELTOL, PIVMIN, D, E, E2, NVAL, AB, C, MOUT,$ NAB, WORK, IWORK, INFO )** -- LAPACK auxiliary routine (version 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 IJOB, INFO, MINP, MMAX, MOUT, N, NBMIN, NITMAXDOUBLE PRECISION ABSTOL, PIVMIN, RELTOL* ..* .. Array Arguments ..INTEGER IWORK( * ), NAB( MMAX, * ), NVAL( * )DOUBLE PRECISION AB( MMAX, * ), C( * ), D( * ), E( * ), E2( * ),$ WORK( * )* ..** Purpose* =======** DLAEBZ contains the iteration loops which compute and use the* function N(w), which is the count of eigenvalues of a symmetric* tridiagonal matrix T less than or equal to its argument w. It* performs a choice of two types of loops:** IJOB=1, followed by* IJOB=2: It takes as input a list of intervals and returns a list of* sufficiently small intervals whose union contains the same* eigenvalues as the union of the original intervals.* The input intervals are (AB(j,1),AB(j,2)], j=1,...,MINP.* The output interval (AB(j,1),AB(j,2)] will contain* eigenvalues NAB(j,1)+1,...,NAB(j,2), where 1 <= j <= MOUT.** IJOB=3: It performs a binary search in each input interval* (AB(j,1),AB(j,2)] for a point w(j) such that* N(w(j))=NVAL(j), and uses C(j) as the starting point of* the search. If such a w(j) is found, then on output* AB(j,1)=AB(j,2)=w. If no such w(j) is found, then on output* (AB(j,1),AB(j,2)] will be a small interval containing the* point where N(w) jumps through NVAL(j), unless that point* lies outside the initial interval.** Note that the intervals are in all cases half-open intervals,* i.e., of the form (a,b] , which includes b but not a .** To avoid underflow, the matrix should be scaled so that its largest* element is no greater than overflow**(1/2) * underflow**(1/4)* in absolute value. To assure the most accurate computation* of small eigenvalues, the matrix should be scaled to be* not much smaller than that, either.** See W. Kahan "Accurate Eigenvalues of a Symmetric Tridiagonal* Matrix", Report CS41, Computer Science Dept., Stanford* University, July 21, 1966** Note: the arguments are, in general, *not* checked for unreasonable* values.** Arguments* =========** IJOB (input) INTEGER* Specifies what is to be done:* = 1: Compute NAB for the initial intervals.* = 2: Perform bisection iteration to find eigenvalues of T.* = 3: Perform bisection iteration to invert N(w), i.e.,* to find a point which has a specified number of* eigenvalues of T to its left.* Other values will cause DLAEBZ to return with INFO=-1.** NITMAX (input) INTEGER* The maximum number of "levels" of bisection to be* performed, i.e., an interval of width W will not be made* smaller than 2^(-NITMAX) * W. If not all intervals* have converged after NITMAX iterations, then INFO is set* to the number of non-converged intervals.** N (input) INTEGER* The dimension n of the tridiagonal matrix T. It must be at* least 1.** MMAX (input) INTEGER* The maximum number of intervals. If more than MMAX intervals* are generated, then DLAEBZ will quit with INFO=MMAX+1.** MINP (input) INTEGER* The initial number of intervals. It may not be greater than* MMAX.** NBMIN (input) INTEGER* The smallest number of intervals that should be processed* using a vector loop. If zero, then only the scalar loop* will be used.** ABSTOL (input) DOUBLE PRECISION* The minimum (absolute) width of an interval. When an* interval is narrower than ABSTOL, or than RELTOL times the* larger (in magnitude) endpoint, then it is considered to be* sufficiently small, i.e., converged. This must be at least* zero.** RELTOL (input) DOUBLE PRECISION* The minimum relative width of an interval. When an interval* is narrower than ABSTOL, or than RELTOL times the larger (in* magnitude) endpoint, then it is considered to be* sufficiently small, i.e., converged. Note: this should* always be at least radix*machine epsilon.** PIVMIN (input) DOUBLE PRECISION* The minimum absolute value of a "pivot" in the Sturm* sequence loop. This *must* be at least max |e(j)**2| ** safe_min and at least safe_min, where safe_min is at least* the smallest number that can divide one without overflow.** D (input) DOUBLE PRECISION array, dimension (N)* The diagonal elements of the tridiagonal matrix T.** E (input) DOUBLE PRECISION array, dimension (N)* The offdiagonal elements of the tridiagonal matrix T in* positions 1 through N-1. E(N) is arbitrary.** E2 (input) DOUBLE PRECISION array, dimension (N)* The squares of the offdiagonal elements of the tridiagonal* matrix T. E2(N) is ignored.** NVAL (input/output) INTEGER array, dimension (MINP)* If IJOB=1 or 2, not referenced.* If IJOB=3, the desired values of N(w). The elements of NVAL* will be reordered to correspond with the intervals in AB.* Thus, NVAL(j) on output will not, in general be the same as* NVAL(j) on input, but it will correspond with the interval* (AB(j,1),AB(j,2)] on output.** AB (input/output) DOUBLE PRECISION array, dimension (MMAX,2)* The endpoints of the intervals. AB(j,1) is a(j), the left* endpoint of the j-th interval, and AB(j,2) is b(j), the* right endpoint of the j-th interval. The input intervals* will, in general, be modified, split, and reordered by the* calculation.** C (input/output) DOUBLE PRECISION array, dimension (MMAX)* If IJOB=1, ignored.* If IJOB=2, workspace.* If IJOB=3, then on input C(j) should be initialized to the* first search point in the binary search.** MOUT (output) INTEGER* If IJOB=1, the number of eigenvalues in the intervals.* If IJOB=2 or 3, the number of intervals output.* If IJOB=3, MOUT will equal MINP.** NAB (input/output) INTEGER array, dimension (MMAX,2)* If IJOB=1, then on output NAB(i,j) will be set to N(AB(i,j)).* If IJOB=2, then on input, NAB(i,j) should be set. It must* satisfy the condition:* N(AB(i,1)) <= NAB(i,1) <= NAB(i,2) <= N(AB(i,2)),* which means that in interval i only eigenvalues* NAB(i,1)+1,...,NAB(i,2) will be considered. Usually,* NAB(i,j)=N(AB(i,j)), from a previous call to DLAEBZ with* IJOB=1.* On output, NAB(i,j) will contain* max(na(k),min(nb(k),N(AB(i,j)))), where k is the index of* the input interval that the output interval* (AB(j,1),AB(j,2)] came from, and na(k) and nb(k) are the* the input values of NAB(k,1) and NAB(k,2).* If IJOB=3, then on output, NAB(i,j) contains N(AB(i,j)),* unless N(w) > NVAL(i) for all search points w , in which* case NAB(i,1) will not be modified, i.e., the output* value will be the same as the input value (modulo* reorderings -- see NVAL and AB), or unless N(w) < NVAL(i)* for all search points w , in which case NAB(i,2) will* not be modified. Normally, NAB should be set to some* distinctive value(s) before DLAEBZ is called.** WORK (workspace) DOUBLE PRECISION array, dimension (MMAX)* Workspace.** IWORK (workspace) INTEGER array, dimension (MMAX)* Workspace.** INFO (output) INTEGER* = 0: All intervals converged.* = 1--MMAX: The last INFO intervals did not converge.* = MMAX+1: More than MMAX intervals were generated.** Further Details* ===============** This routine is intended to be called only by other LAPACK* routines, thus the interface is less user-friendly. It is intended* for two purposes:** (a) finding eigenvalues. In this case, DLAEBZ should have one or* more initial intervals set up in AB, and DLAEBZ should be called* with IJOB=1. This sets up NAB, and also counts the eigenvalues.* Intervals with no eigenvalues would usually be thrown out at* this point. Also, if not all the eigenvalues in an interval i* are desired, NAB(i,1) can be increased or NAB(i,2) decreased.* For example, set NAB(i,1)=NAB(i,2)-1 to get the largest* eigenvalue. DLAEBZ is then called with IJOB=2 and MMAX* no smaller than the value of MOUT returned by the call with* IJOB=1. After this (IJOB=2) call, eigenvalues NAB(i,1)+1* through NAB(i,2) are approximately AB(i,1) (or AB(i,2)) to the* tolerance specified by ABSTOL and RELTOL.** (b) finding an interval (a',b'] containing eigenvalues w(f),...,w(l).* In this case, start with a Gershgorin interval (a,b). Set up* AB to contain 2 search intervals, both initially (a,b). One* NVAL element should contain f-1 and the other should contain l* , while C should contain a and b, resp. NAB(i,1) should be -1* and NAB(i,2) should be N+1, to flag an error if the desired* interval does not lie in (a,b). DLAEBZ is then called with* IJOB=3. On exit, if w(f-1) < w(f), then one of the intervals --* j -- will have AB(j,1)=AB(j,2) and NAB(j,1)=NAB(j,2)=f-1, while* if, to the specified tolerance, w(f-k)=...=w(f+r), k > 0 and r* >= 0, then the interval will have N(AB(j,1))=NAB(j,1)=f-k and* N(AB(j,2))=NAB(j,2)=f+r. The cases w(l) < w(l+1) and* w(l-r)=...=w(l+k) are handled similarly.** =====================================================================** .. Parameters ..DOUBLE PRECISION ZERO, TWO, HALFPARAMETER ( ZERO = 0.0D0, TWO = 2.0D0,$ HALF = 1.0D0 / TWO )* ..* .. Local Scalars ..INTEGER ITMP1, ITMP2, J, JI, JIT, JP, KF, KFNEW, KL,$ KLNEWDOUBLE PRECISION TMP1, TMP2* ..* .. Intrinsic Functions ..INTRINSIC ABS, MAX, MIN* ..* .. Executable Statements ..** Check for Errors*INFO = 0IF( IJOB.LT.1 .OR. IJOB.GT.3 ) THENINFO = -1RETURNEND IF** Initialize NAB*IF( IJOB.EQ.1 ) THEN** Compute the number of eigenvalues in the initial intervals.*MOUT = 0*DIR$ NOVECTORDO 30 JI = 1, MINPDO 20 JP = 1, 2TMP1 = D( 1 ) - AB( JI, JP )IF( ABS( TMP1 ).LT.PIVMIN )$ TMP1 = -PIVMINNAB( JI, JP ) = 0IF( TMP1.LE.ZERO )$ NAB( JI, JP ) = 1*DO 10 J = 2, NTMP1 = D( J ) - E2( J-1 ) / TMP1 - AB( JI, JP )IF( ABS( TMP1 ).LT.PIVMIN )$ TMP1 = -PIVMINIF( TMP1.LE.ZERO )$ NAB( JI, JP ) = NAB( JI, JP ) + 110 CONTINUE20 CONTINUEMOUT = MOUT + NAB( JI, 2 ) - NAB( JI, 1 )30 CONTINUERETURNEND IF** Initialize for loop** KF and KL have the following meaning:* Intervals 1,...,KF-1 have converged.* Intervals KF,...,KL still need to be refined.*KF = 1KL = MINP** If IJOB=2, initialize C.* If IJOB=3, use the user-supplied starting point.*IF( IJOB.EQ.2 ) THENDO 40 JI = 1, MINPC( JI ) = HALF*( AB( JI, 1 )+AB( JI, 2 ) )40 CONTINUEEND IF** Iteration loop*DO 130 JIT = 1, NITMAX** Loop over intervals*IF( KL-KF+1.GE.NBMIN .AND. NBMIN.GT.0 ) THEN** Begin of Parallel Version of the loop*DO 60 JI = KF, KL** Compute N(c), the number of eigenvalues less than c*WORK( JI ) = D( 1 ) - C( JI )IWORK( JI ) = 0IF( WORK( JI ).LE.PIVMIN ) THENIWORK( JI ) = 1WORK( JI ) = MIN( WORK( JI ), -PIVMIN )END IF*DO 50 J = 2, NWORK( JI ) = D( J ) - E2( J-1 ) / WORK( JI ) - C( JI )IF( WORK( JI ).LE.PIVMIN ) THENIWORK( JI ) = IWORK( JI ) + 1WORK( JI ) = MIN( WORK( JI ), -PIVMIN )END IF50 CONTINUE60 CONTINUE*IF( IJOB.LE.2 ) THEN** IJOB=2: Choose all intervals containing eigenvalues.*KLNEW = KLDO 70 JI = KF, KL** Insure that N(w) is monotone*IWORK( JI ) = MIN( NAB( JI, 2 ),$ MAX( NAB( JI, 1 ), IWORK( JI ) ) )** Update the Queue -- add intervals if both halves* contain eigenvalues.*IF( IWORK( JI ).EQ.NAB( JI, 2 ) ) THEN** No eigenvalue in the upper interval:* just use the lower interval.*AB( JI, 2 ) = C( JI )*ELSE IF( IWORK( JI ).EQ.NAB( JI, 1 ) ) THEN** No eigenvalue in the lower interval:* just use the upper interval.*AB( JI, 1 ) = C( JI )ELSEKLNEW = KLNEW + 1IF( KLNEW.LE.MMAX ) THEN** Eigenvalue in both intervals -- add upper to* queue.*AB( KLNEW, 2 ) = AB( JI, 2 )NAB( KLNEW, 2 ) = NAB( JI, 2 )AB( KLNEW, 1 ) = C( JI )NAB( KLNEW, 1 ) = IWORK( JI )AB( JI, 2 ) = C( JI )NAB( JI, 2 ) = IWORK( JI )ELSEINFO = MMAX + 1END IFEND IF70 CONTINUEIF( INFO.NE.0 )$ RETURNKL = KLNEWELSE** IJOB=3: Binary search. Keep only the interval containing* w s.t. N(w) = NVAL*DO 80 JI = KF, KLIF( IWORK( JI ).LE.NVAL( JI ) ) THENAB( JI, 1 ) = C( JI )NAB( JI, 1 ) = IWORK( JI )END IFIF( IWORK( JI ).GE.NVAL( JI ) ) THENAB( JI, 2 ) = C( JI )NAB( JI, 2 ) = IWORK( JI )END IF80 CONTINUEEND IF*ELSE** End of Parallel Version of the loop** Begin of Serial Version of the loop*KLNEW = KLDO 100 JI = KF, KL** Compute N(w), the number of eigenvalues less than w*TMP1 = C( JI )TMP2 = D( 1 ) - TMP1ITMP1 = 0IF( TMP2.LE.PIVMIN ) THENITMP1 = 1TMP2 = MIN( TMP2, -PIVMIN )END IF** A series of compiler directives to defeat vectorization* for the next loop**$PL$ CMCHAR=' 'CDIR$ NEXTSCALARC$DIR SCALARCDIR$ NEXT SCALARCVD$L NOVECTORCDEC$ NOVECTORCVD$ NOVECTOR*VDIR NOVECTOR*VOCL LOOP,SCALARCIBM PREFER SCALAR*$PL$ CMCHAR='*'*DO 90 J = 2, NTMP2 = D( J ) - E2( J-1 ) / TMP2 - TMP1IF( TMP2.LE.PIVMIN ) THENITMP1 = ITMP1 + 1TMP2 = MIN( TMP2, -PIVMIN )END IF90 CONTINUE*IF( IJOB.LE.2 ) THEN** IJOB=2: Choose all intervals containing eigenvalues.** Insure that N(w) is monotone*ITMP1 = MIN( NAB( JI, 2 ),$ MAX( NAB( JI, 1 ), ITMP1 ) )** Update the Queue -- add intervals if both halves* contain eigenvalues.*IF( ITMP1.EQ.NAB( JI, 2 ) ) THEN** No eigenvalue in the upper interval:* just use the lower interval.*AB( JI, 2 ) = TMP1*ELSE IF( ITMP1.EQ.NAB( JI, 1 ) ) THEN** No eigenvalue in the lower interval:* just use the upper interval.*AB( JI, 1 ) = TMP1ELSE IF( KLNEW.LT.MMAX ) THEN** Eigenvalue in both intervals -- add upper to queue.*KLNEW = KLNEW + 1AB( KLNEW, 2 ) = AB( JI, 2 )NAB( KLNEW, 2 ) = NAB( JI, 2 )AB( KLNEW, 1 ) = TMP1NAB( KLNEW, 1 ) = ITMP1AB( JI, 2 ) = TMP1NAB( JI, 2 ) = ITMP1ELSEINFO = MMAX + 1RETURNEND IFELSE** IJOB=3: Binary search. Keep only the interval* containing w s.t. N(w) = NVAL*IF( ITMP1.LE.NVAL( JI ) ) THENAB( JI, 1 ) = TMP1NAB( JI, 1 ) = ITMP1END IFIF( ITMP1.GE.NVAL( JI ) ) THENAB( JI, 2 ) = TMP1NAB( JI, 2 ) = ITMP1END IFEND IF100 CONTINUEKL = KLNEW** End of Serial Version of the loop*END IF** Check for convergence*KFNEW = KFDO 110 JI = KF, KLTMP1 = ABS( AB( JI, 2 )-AB( JI, 1 ) )TMP2 = MAX( ABS( AB( JI, 2 ) ), ABS( AB( JI, 1 ) ) )IF( TMP1.LT.MAX( ABSTOL, PIVMIN, RELTOL*TMP2 ) .OR.$ NAB( JI, 1 ).GE.NAB( JI, 2 ) ) THEN** Converged -- Swap with position KFNEW,* then increment KFNEW*IF( JI.GT.KFNEW ) THENTMP1 = AB( JI, 1 )TMP2 = AB( JI, 2 )ITMP1 = NAB( JI, 1 )ITMP2 = NAB( JI, 2 )AB( JI, 1 ) = AB( KFNEW, 1 )AB( JI, 2 ) = AB( KFNEW, 2 )NAB( JI, 1 ) = NAB( KFNEW, 1 )NAB( JI, 2 ) = NAB( KFNEW, 2 )AB( KFNEW, 1 ) = TMP1AB( KFNEW, 2 ) = TMP2NAB( KFNEW, 1 ) = ITMP1NAB( KFNEW, 2 ) = ITMP2IF( IJOB.EQ.3 ) THENITMP1 = NVAL( JI )NVAL( JI ) = NVAL( KFNEW )NVAL( KFNEW ) = ITMP1END IFEND IFKFNEW = KFNEW + 1END IF110 CONTINUEKF = KFNEW** Choose Midpoints*DO 120 JI = KF, KLC( JI ) = HALF*( AB( JI, 1 )+AB( JI, 2 ) )120 CONTINUE** If no more intervals to refine, quit.*IF( KF.GT.KL )$ GO TO 140130 CONTINUE** Converged*140 CONTINUEINFO = MAX( KL+1-KF, 0 )MOUT = KL*RETURN** End of DLAEBZ*ENDSUBROUTINE DLARNV( IDIST, ISEED, N, X )** -- LAPACK auxiliary routine (version 3.0) --* Univ. of Tennessee, Univ. of California Berkeley, NAG Ltd.,* Courant Institute, Argonne National Lab, and Rice University* September 30, 1994** .. Scalar Arguments ..INTEGER IDIST, N* ..* .. Array Arguments ..INTEGER ISEED( 4 )DOUBLE PRECISION X( * )* ..** Purpose* =======** DLARNV returns a vector of n random real numbers from a uniform or* normal distribution.** Arguments* =========** IDIST (input) INTEGER* Specifies the distribution of the random numbers:* = 1: uniform (0,1)* = 2: uniform (-1,1)* = 3: normal (0,1)** ISEED (input/output) INTEGER array, dimension (4)* On entry, the seed of the random number generator; the array* elements must be between 0 and 4095, and ISEED(4) must be* odd.* On exit, the seed is updated.** N (input) INTEGER* The number of random numbers to be generated.** X (output) DOUBLE PRECISION array, dimension (N)* The generated random numbers.** Further Details* ===============** This routine calls the auxiliary routine DLARUV to generate random* real numbers from a uniform (0,1) distribution, in batches of up to* 128 using vectorisable code. The Box-Muller method is used to* transform numbers from a uniform to a normal distribution.** =====================================================================** .. Parameters ..DOUBLE PRECISION ONE, TWOPARAMETER ( ONE = 1.0D+0, TWO = 2.0D+0 )INTEGER LVPARAMETER ( LV = 128 )DOUBLE PRECISION TWOPIPARAMETER ( TWOPI = 6.2831853071795864769252867663D+0 )* ..* .. Local Scalars ..INTEGER I, IL, IL2, IV* ..* .. Local Arrays ..DOUBLE PRECISION U( LV )* ..* .. Intrinsic Functions ..INTRINSIC COS, LOG, MIN, SQRT* ..* .. External Subroutines ..EXTERNAL DLARUV* ..* .. Executable Statements ..*DO 40 IV = 1, N, LV / 2IL = MIN( LV / 2, N-IV+1 )IF( IDIST.EQ.3 ) THENIL2 = 2*ILELSEIL2 = ILEND IF** Call DLARUV to generate IL2 numbers from a uniform (0,1)* distribution (IL2 <= LV)*CALL DLARUV( ISEED, IL2, U )*IF( IDIST.EQ.1 ) THEN** Copy generated numbers*DO 10 I = 1, ILX( IV+I-1 ) = U( I )10 CONTINUEELSE IF( IDIST.EQ.2 ) THEN** Convert generated numbers to uniform (-1,1) distribution*DO 20 I = 1, ILX( IV+I-1 ) = TWO*U( I ) - ONE20 CONTINUEELSE IF( IDIST.EQ.3 ) THEN** Convert generated numbers to normal (0,1) distribution*DO 30 I = 1, ILX( IV+I-1 ) = SQRT( -TWO*LOG( U( 2*I-1 ) ) )*$ COS( TWOPI*U( 2*I ) )30 CONTINUEEND IF40 CONTINUERETURN** End of DLARNV*ENDSUBROUTINE DLAGTF( N, A, LAMBDA, B, C, TOL, D, IN, INFO )** -- LAPACK routine (version 3.0) --* Univ. of Tennessee, Univ. of California Berkeley, NAG Ltd.,* Courant Institute, Argonne National Lab, and Rice University* June 30, 1999** .. Scalar Arguments ..INTEGER INFO, NDOUBLE PRECISION LAMBDA, TOL* ..* .. Array Arguments ..INTEGER IN( * )DOUBLE PRECISION A( * ), B( * ), C( * ), D( * )* ..** Purpose* =======** DLAGTF factorizes the matrix (T - lambda*I), where T is an n by n* tridiagonal matrix and lambda is a scalar, as** T - lambda*I = PLU,** where P is a permutation matrix, L is a unit lower tridiagonal matrix* with at most one non-zero sub-diagonal elements per column and U is* an upper triangular matrix with at most two non-zero super-diagonal* elements per column.** The factorization is obtained by Gaussian elimination with partial* pivoting and implicit row scaling.** The parameter LAMBDA is included in the routine so that DLAGTF may* be used, in conjunction with DLAGTS, to obtain eigenvectors of T by* inverse iteration.** Arguments* =========** N (input) INTEGER* The order of the matrix T.** A (input/output) DOUBLE PRECISION array, dimension (N)* On entry, A must contain the diagonal elements of T.** On exit, A is overwritten by the n diagonal elements of the* upper triangular matrix U of the factorization of T.** LAMBDA (input) DOUBLE PRECISION* On entry, the scalar lambda.** B (input/output) DOUBLE PRECISION array, dimension (N-1)* On entry, B must contain the (n-1) super-diagonal elements of* T.** On exit, B is overwritten by the (n-1) super-diagonal* elements of the matrix U of the factorization of T.** C (input/output) DOUBLE PRECISION array, dimension (N-1)* On entry, C must contain the (n-1) sub-diagonal elements of* T.** On exit, C is overwritten by the (n-1) sub-diagonal elements* of the matrix L of the factorization of T.** TOL (input) DOUBLE PRECISION* On entry, a relative tolerance used to indicate whether or* not the matrix (T - lambda*I) is nearly singular. TOL should* normally be chose as approximately the largest relative error* in the elements of T. For example, if the elements of T are* correct to about 4 significant figures, then TOL should be* set to about 5*10**(-4). If TOL is supplied as less than eps,* where eps is the relative machine precision, then the value* eps is used in place of TOL.** D (output) DOUBLE PRECISION array, dimension (N-2)* On exit, D is overwritten by the (n-2) second super-diagonal* elements of the matrix U of the factorization of T.** IN (output) INTEGER array, dimension (N)* On exit, IN contains details of the permutation matrix P. If* an interchange occurred at the kth step of the elimination,* then IN(k) = 1, otherwise IN(k) = 0. The element IN(n)* returns the smallest positive integer j such that** abs( u(j,j) ).le. norm( (T - lambda*I)(j) )*TOL,** where norm( A(j) ) denotes the sum of the absolute values of* the jth row of the matrix A. If no such j exists then IN(n)* is returned as zero. If IN(n) is returned as positive, then a* diagonal element of U is small, indicating that* (T - lambda*I) is singular or nearly singular,** INFO (output) INTEGER* = 0 : successful exit* .lt. 0: if INFO = -k, the kth argument had an illegal value** =====================================================================** .. Parameters ..DOUBLE PRECISION ZEROPARAMETER ( ZERO = 0.0D+0 )* ..* .. Local Scalars ..INTEGER KDOUBLE PRECISION EPS, MULT, PIV1, PIV2, SCALE1, SCALE2, TEMP, TL* ..* .. Intrinsic Functions ..INTRINSIC ABS, MAX* ..* .. External Functions ..DOUBLE PRECISION DLAMCHEXTERNAL DLAMCH* ..* .. External Subroutines ..EXTERNAL XERBLA* ..* .. Executable Statements ..*INFO = 0IF( N.LT.0 ) THENINFO = -1CALL XERBLA( 'DLAGTF', -INFO )RETURNEND IF*IF( N.EQ.0 )$ RETURN*A( 1 ) = A( 1 ) - LAMBDAIN( N ) = 0IF( N.EQ.1 ) THENIF( A( 1 ).EQ.ZERO )$ IN( 1 ) = 1RETURNEND IF*EPS = DLAMCH( 'Epsilon' )*TL = MAX( TOL, EPS )SCALE1 = ABS( A( 1 ) ) + ABS( B( 1 ) )DO 10 K = 1, N - 1A( K+1 ) = A( K+1 ) - LAMBDASCALE2 = ABS( C( K ) ) + ABS( A( K+1 ) )IF( K.LT.( N-1 ) )$ SCALE2 = SCALE2 + ABS( B( K+1 ) )IF( A( K ).EQ.ZERO ) THENPIV1 = ZEROELSEPIV1 = ABS( A( K ) ) / SCALE1END IFIF( C( K ).EQ.ZERO ) THENIN( K ) = 0PIV2 = ZEROSCALE1 = SCALE2IF( K.LT.( N-1 ) )$ D( K ) = ZEROELSEPIV2 = ABS( C( K ) ) / SCALE2IF( PIV2.LE.PIV1 ) THENIN( K ) = 0SCALE1 = SCALE2C( K ) = C( K ) / A( K )A( K+1 ) = A( K+1 ) - C( K )*B( K )IF( K.LT.( N-1 ) )$ D( K ) = ZEROELSEIN( K ) = 1MULT = A( K ) / C( K )A( K ) = C( K )TEMP = A( K+1 )A( K+1 ) = B( K ) - MULT*TEMPIF( K.LT.( N-1 ) ) THEND( K ) = B( K+1 )B( K+1 ) = -MULT*D( K )END IFB( K ) = TEMPC( K ) = MULTEND IFEND IFIF( ( MAX( PIV1, PIV2 ).LE.TL ) .AND. ( IN( N ).EQ.0 ) )$ IN( N ) = K10 CONTINUEIF( ( ABS( A( N ) ).LE.SCALE1*TL ) .AND. ( IN( N ).EQ.0 ) )$ IN( N ) = N*RETURN** End of DLAGTF*ENDSUBROUTINE DLAGTS( JOB, N, A, B, C, D, IN, Y, TOL, INFO )** -- LAPACK auxiliary routine (version 3.0) --* Univ. of Tennessee, Univ. of California Berkeley, NAG Ltd.,* Courant Institute, Argonne National Lab, and Rice University* October 31, 1992** .. Scalar Arguments ..INTEGER INFO, JOB, NDOUBLE PRECISION TOL* ..* .. Array Arguments ..INTEGER IN( * )DOUBLE PRECISION A( * ), B( * ), C( * ), D( * ), Y( * )* ..** Purpose* =======** DLAGTS may be used to solve one of the systems of equations** (T - lambda*I)*x = y or (T - lambda*I)'*x = y,** where T is an n by n tridiagonal matrix, for x, following the* factorization of (T - lambda*I) as** (T - lambda*I) = P*L*U ,** by routine DLAGTF. The choice of equation to be solved is* controlled by the argument JOB, and in each case there is an option* to perturb zero or very small diagonal elements of U, this option* being intended for use in applications such as inverse iteration.** Arguments* =========** JOB (input) INTEGER* Specifies the job to be performed by DLAGTS as follows:* = 1: The equations (T - lambda*I)x = y are to be solved,* but diagonal elements of U are not to be perturbed.* = -1: The equations (T - lambda*I)x = y are to be solved* and, if overflow would otherwise occur, the diagonal* elements of U are to be perturbed. See argument TOL* below.* = 2: The equations (T - lambda*I)'x = y are to be solved,* but diagonal elements of U are not to be perturbed.* = -2: The equations (T - lambda*I)'x = y are to be solved* and, if overflow would otherwise occur, the diagonal* elements of U are to be perturbed. See argument TOL* below.** N (input) INTEGER* The order of the matrix T.** A (input) DOUBLE PRECISION array, dimension (N)* On entry, A must contain the diagonal elements of U as* returned from DLAGTF.** B (input) DOUBLE PRECISION array, dimension (N-1)* On entry, B must contain the first super-diagonal elements of* U as returned from DLAGTF.** C (input) DOUBLE PRECISION array, dimension (N-1)* On entry, C must contain the sub-diagonal elements of L as* returned from DLAGTF.** D (input) DOUBLE PRECISION array, dimension (N-2)* On entry, D must contain the second super-diagonal elements* of U as returned from DLAGTF.** IN (input) INTEGER array, dimension (N)* On entry, IN must contain details of the matrix P as returned* from DLAGTF.** Y (input/output) DOUBLE PRECISION array, dimension (N)* On entry, the right hand side vector y.* On exit, Y is overwritten by the solution vector x.** TOL (input/output) DOUBLE PRECISION* On entry, with JOB .lt. 0, TOL should be the minimum* perturbation to be made to very small diagonal elements of U.* TOL should normally be chosen as about eps*norm(U), where eps* is the relative machine precision, but if TOL is supplied as* non-positive, then it is reset to eps*max( abs( u(i,j) ) ).* If JOB .gt. 0 then TOL is not referenced.** On exit, TOL is changed as described above, only if TOL is* non-positive on entry. Otherwise TOL is unchanged.** INFO (output) INTEGER* = 0 : successful exit* .lt. 0: if INFO = -i, the i-th argument had an illegal value* .gt. 0: overflow would occur when computing the INFO(th)* element of the solution vector x. This can only occur* when JOB is supplied as positive and either means* that a diagonal element of U is very small, or that* the elements of the right-hand side vector y are very* large.** =====================================================================** .. Parameters ..DOUBLE PRECISION ONE, ZEROPARAMETER ( ONE = 1.0D+0, ZERO = 0.0D+0 )* ..* .. Local Scalars ..INTEGER KDOUBLE PRECISION ABSAK, AK, BIGNUM, EPS, PERT, SFMIN, TEMP* ..* .. Intrinsic Functions ..INTRINSIC ABS, MAX, SIGN* ..* .. External Functions ..DOUBLE PRECISION DLAMCHEXTERNAL DLAMCH* ..* .. External Subroutines ..EXTERNAL XERBLA* ..* .. Executable Statements ..*INFO = 0IF( ( ABS( JOB ).GT.2 ) .OR. ( JOB.EQ.0 ) ) THENINFO = -1ELSE IF( N.LT.0 ) THENINFO = -2END IFIF( INFO.NE.0 ) THENCALL XERBLA( 'DLAGTS', -INFO )RETURNEND IF*IF( N.EQ.0 )$ RETURN*EPS = DLAMCH( 'Epsilon' )SFMIN = DLAMCH( 'Safe minimum' )BIGNUM = ONE / SFMIN*IF( JOB.LT.0 ) THENIF( TOL.LE.ZERO ) THENTOL = ABS( A( 1 ) )IF( N.GT.1 )$ TOL = MAX( TOL, ABS( A( 2 ) ), ABS( B( 1 ) ) )DO 10 K = 3, NTOL = MAX( TOL, ABS( A( K ) ), ABS( B( K-1 ) ),$ ABS( D( K-2 ) ) )10 CONTINUETOL = TOL*EPSIF( TOL.EQ.ZERO )$ TOL = EPSEND IFEND IF*IF( ABS( JOB ).EQ.1 ) THENDO 20 K = 2, NIF( IN( K-1 ).EQ.0 ) THENY( K ) = Y( K ) - C( K-1 )*Y( K-1 )ELSETEMP = Y( K-1 )Y( K-1 ) = Y( K )Y( K ) = TEMP - C( K-1 )*Y( K )END IF20 CONTINUEIF( JOB.EQ.1 ) THENDO 30 K = N, 1, -1IF( K.LE.N-2 ) THENTEMP = Y( K ) - B( K )*Y( K+1 ) - D( K )*Y( K+2 )ELSE IF( K.EQ.N-1 ) THENTEMP = Y( K ) - B( K )*Y( K+1 )ELSETEMP = Y( K )END IFAK = A( K )ABSAK = ABS( AK )IF( ABSAK.LT.ONE ) THENIF( ABSAK.LT.SFMIN ) THENIF( ABSAK.EQ.ZERO .OR. ABS( TEMP )*SFMIN.GT.ABSAK )$ THENINFO = KRETURNELSETEMP = TEMP*BIGNUMAK = AK*BIGNUMEND IFELSE IF( ABS( TEMP ).GT.ABSAK*BIGNUM ) THENINFO = KRETURNEND IFEND IFY( K ) = TEMP / AK30 CONTINUEELSEDO 50 K = N, 1, -1IF( K.LE.N-2 ) THENTEMP = Y( K ) - B( K )*Y( K+1 ) - D( K )*Y( K+2 )ELSE IF( K.EQ.N-1 ) THENTEMP = Y( K ) - B( K )*Y( K+1 )ELSETEMP = Y( K )END IFAK = A( K )PERT = SIGN( TOL, AK )40 CONTINUEABSAK = ABS( AK )IF( ABSAK.LT.ONE ) THENIF( ABSAK.LT.SFMIN ) THENIF( ABSAK.EQ.ZERO .OR. ABS( TEMP )*SFMIN.GT.ABSAK )$ THENAK = AK + PERTPERT = 2*PERTGO TO 40ELSETEMP = TEMP*BIGNUMAK = AK*BIGNUMEND IFELSE IF( ABS( TEMP ).GT.ABSAK*BIGNUM ) THENAK = AK + PERTPERT = 2*PERTGO TO 40END IFEND IFY( K ) = TEMP / AK50 CONTINUEEND IFELSE** Come to here if JOB = 2 or -2*IF( JOB.EQ.2 ) THENDO 60 K = 1, NIF( K.GE.3 ) THENTEMP = Y( K ) - B( K-1 )*Y( K-1 ) - D( K-2 )*Y( K-2 )ELSE IF( K.EQ.2 ) THENTEMP = Y( K ) - B( K-1 )*Y( K-1 )ELSETEMP = Y( K )END IFAK = A( K )ABSAK = ABS( AK )IF( ABSAK.LT.ONE ) THENIF( ABSAK.LT.SFMIN ) THENIF( ABSAK.EQ.ZERO .OR. ABS( TEMP )*SFMIN.GT.ABSAK )$ THENINFO = KRETURNELSETEMP = TEMP*BIGNUMAK = AK*BIGNUMEND IFELSE IF( ABS( TEMP ).GT.ABSAK*BIGNUM ) THENINFO = KRETURNEND IFEND IFY( K ) = TEMP / AK60 CONTINUEELSEDO 80 K = 1, NIF( K.GE.3 ) THENTEMP = Y( K ) - B( K-1 )*Y( K-1 ) - D( K-2 )*Y( K-2 )ELSE IF( K.EQ.2 ) THENTEMP = Y( K ) - B( K-1 )*Y( K-1 )ELSETEMP = Y( K )END IFAK = A( K )PERT = SIGN( TOL, AK )70 CONTINUEABSAK = ABS( AK )IF( ABSAK.LT.ONE ) THENIF( ABSAK.LT.SFMIN ) THENIF( ABSAK.EQ.ZERO .OR. ABS( TEMP )*SFMIN.GT.ABSAK )$ THENAK = AK + PERTPERT = 2*PERTGO TO 70ELSETEMP = TEMP*BIGNUMAK = AK*BIGNUMEND IFELSE IF( ABS( TEMP ).GT.ABSAK*BIGNUM ) THENAK = AK + PERTPERT = 2*PERTGO TO 70END IFEND IFY( K ) = TEMP / AK80 CONTINUEEND IF*DO 90 K = N, 2, -1IF( IN( K-1 ).EQ.0 ) THENY( K-1 ) = Y( K-1 ) - C( K-1 )*Y( K )ELSETEMP = Y( K-1 )Y( K-1 ) = Y( K )Y( K ) = TEMP - C( K-1 )*Y( K )END IF90 CONTINUEEND IF** End of DLAGTS*ENDSUBROUTINE DORM2L( SIDE, TRANS, M, N, K, A, LDA, TAU, C, LDC,$ WORK, INFO )** -- LAPACK routine (version 3.0) --* Univ. of Tennessee, Univ. of California Berkeley, NAG Ltd.,* Courant Institute, Argonne National Lab, and Rice University* February 29, 1992** .. Scalar Arguments ..CHARACTER SIDE, TRANSINTEGER INFO, K, LDA, LDC, M, N* ..* .. Array Arguments ..DOUBLE PRECISION A( LDA, * ), C( LDC, * ), TAU( * ), WORK( * )* ..** Purpose* =======** DORM2L overwrites the general real m by n matrix C with** Q * C if SIDE = 'L' and TRANS = 'N', or** Q'* C if SIDE = 'L' and TRANS = 'T', or** C * Q if SIDE = 'R' and TRANS = 'N', or** C * Q' if SIDE = 'R' and TRANS = 'T',** where Q is a real orthogonal matrix defined as the product of k* elementary reflectors** Q = H(k) . . . H(2) H(1)** as returned by DGEQLF. Q is of order m if SIDE = 'L' and of order n* if SIDE = 'R'.** Arguments* =========** SIDE (input) CHARACTER*1* = 'L': apply Q or Q' from the Left* = 'R': apply Q or Q' from the Right** TRANS (input) CHARACTER*1* = 'N': apply Q (No transpose)* = 'T': apply Q' (Transpose)** M (input) INTEGER* The number of rows of the matrix C. M >= 0.** N (input) INTEGER* The number of columns of the matrix C. N >= 0.** K (input) INTEGER* The number of elementary reflectors whose product defines* the matrix Q.* If SIDE = 'L', M >= K >= 0;* if SIDE = 'R', N >= K >= 0.** A (input) DOUBLE PRECISION array, dimension (LDA,K)* The i-th column must contain the vector which defines the* elementary reflector H(i), for i = 1,2,...,k, as returned by* DGEQLF in the last k columns of its array argument A.* A is modified by the routine but restored on exit.** LDA (input) INTEGER* The leading dimension of the array A.* If SIDE = 'L', LDA >= max(1,M);* if SIDE = 'R', LDA >= max(1,N).** TAU (input) DOUBLE PRECISION array, dimension (K)* TAU(i) must contain the scalar factor of the elementary* reflector H(i), as returned by DGEQLF.** C (input/output) DOUBLE PRECISION array, dimension (LDC,N)* On entry, the m by n matrix C.* On exit, C is overwritten by Q*C or Q'*C or C*Q' or C*Q.** LDC (input) INTEGER* The leading dimension of the array C. LDC >= max(1,M).** WORK (workspace) DOUBLE PRECISION array, dimension* (N) if SIDE = 'L',* (M) if SIDE = 'R'** INFO (output) INTEGER* = 0: successful exit* < 0: if INFO = -i, the i-th argument had an illegal value** =====================================================================** .. Parameters ..DOUBLE PRECISION ONEPARAMETER ( ONE = 1.0D+0 )* ..* .. Local Scalars ..LOGICAL LEFT, NOTRANINTEGER I, I1, I2, I3, MI, NI, NQDOUBLE PRECISION AII* ..* .. External Functions ..LOGICAL LSAMEEXTERNAL LSAME* ..* .. External Subroutines ..EXTERNAL DLARF, XERBLA* ..* .. Intrinsic Functions ..INTRINSIC MAX* ..* .. Executable Statements ..** Test the input arguments*INFO = 0LEFT = LSAME( SIDE, 'L' )NOTRAN = LSAME( TRANS, 'N' )** NQ is the order of Q*IF( LEFT ) THENNQ = MELSENQ = NEND IFIF( .NOT.LEFT .AND. .NOT.LSAME( SIDE, 'R' ) ) THENINFO = -1ELSE IF( .NOT.NOTRAN .AND. .NOT.LSAME( TRANS, 'T' ) ) THENINFO = -2ELSE IF( M.LT.0 ) THENINFO = -3ELSE IF( N.LT.0 ) THENINFO = -4ELSE IF( K.LT.0 .OR. K.GT.NQ ) THENINFO = -5ELSE IF( LDA.LT.MAX( 1, NQ ) ) THENINFO = -7ELSE IF( LDC.LT.MAX( 1, M ) ) THENINFO = -10END IFIF( INFO.NE.0 ) THENCALL XERBLA( 'DORM2L', -INFO )RETURNEND IF** Quick return if possible*IF( M.EQ.0 .OR. N.EQ.0 .OR. K.EQ.0 )$ RETURN*IF( ( LEFT .AND. NOTRAN ) .OR. ( .NOT.LEFT .AND. .NOT.NOTRAN ) )$ THENI1 = 1I2 = KI3 = 1ELSEI1 = KI2 = 1I3 = -1END IF*IF( LEFT ) THENNI = NELSEMI = MEND IF*DO 10 I = I1, I2, I3IF( LEFT ) THEN** H(i) is applied to C(1:m-k+i,1:n)*MI = M - K + IELSE** H(i) is applied to C(1:m,1:n-k+i)*NI = N - K + IEND IF** Apply H(i)*AII = A( NQ-K+I, I )A( NQ-K+I, I ) = ONECALL DLARF( SIDE, MI, NI, A( 1, I ), 1, TAU( I ), C, LDC,$ WORK )A( NQ-K+I, I ) = AII10 CONTINUERETURN** End of DORM2L*ENDSUBROUTINE DLARRB( N, D, L, LD, LLD, IFIRST, ILAST, SIGMA, RELTOL,$ W, WGAP, WERR, WORK, IWORK, INFO )** -- LAPACK auxiliary 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 IFIRST, ILAST, INFO, NDOUBLE PRECISION RELTOL, SIGMA* ..* .. Array Arguments ..INTEGER IWORK( * )DOUBLE PRECISION D( * ), L( * ), LD( * ), LLD( * ), W( * ),$ WERR( * ), WGAP( * ), WORK( * )* ..** Purpose* =======** Given the relatively robust representation(RRR) L D L^T, DLARRB* does ``limited'' bisection to locate the eigenvalues of L D L^T,* W( IFIRST ) thru' W( ILAST ), to more accuracy. Intervals* [left, right] are maintained by storing their mid-points and* semi-widths in the arrays W and WERR respectively.** Arguments* =========** N (input) INTEGER* The order of the matrix.** D (input) DOUBLE PRECISION array, dimension (N)* The n diagonal elements of the diagonal matrix D.** L (input) DOUBLE PRECISION array, dimension (N-1)* The n-1 subdiagonal elements of the unit bidiagonal matrix L.** LD (input) DOUBLE PRECISION array, dimension (N-1)* The n-1 elements L(i)*D(i).** LLD (input) DOUBLE PRECISION array, dimension (N-1)* The n-1 elements L(i)*L(i)*D(i).** IFIRST (input) INTEGER* The index of the first eigenvalue in the cluster.** ILAST (input) INTEGER* The index of the last eigenvalue in the cluster.** SIGMA (input) DOUBLE PRECISION* The shift used to form L D L^T (see DLARRF).** RELTOL (input) DOUBLE PRECISION* The relative tolerance.** W (input/output) DOUBLE PRECISION array, dimension (N)* On input, W( IFIRST ) thru' W( ILAST ) are estimates of the* corresponding eigenvalues of L D L^T.* On output, these estimates are ``refined''.** WGAP (input/output) DOUBLE PRECISION array, dimension (N)* The gaps between the eigenvalues of L D L^T. Very small* gaps are changed on output.** WERR (input/output) DOUBLE PRECISION array, dimension (N)* On input, WERR( IFIRST ) thru' WERR( ILAST ) are the errors* in the estimates W( IFIRST ) thru' W( ILAST ).* On output, these are the ``refined'' errors.******Reminder to Inder --- WORK is never used in this subroutine ****** WORK (input) DOUBLE PRECISION array, dimension (???)* Workspace.** IWORK (input) INTEGER array, dimension (2*N)* Workspace.******Reminder to Inder --- INFO is never set in this subroutine ******* INFO (output) INTEGER* Error flag.** Further Details* ===============** Based on contributions by* Inderjit Dhillon, IBM Almaden, USA* Osni Marques, LBNL/NERSC, USA** =====================================================================** .. Parameters ..DOUBLE PRECISION ZERO, TWO, HALFPARAMETER ( ZERO = 0.0D0, TWO = 2.0D0, HALF = 0.5D0 )* ..* .. Local Scalars ..INTEGER CNT, I, I1, I2, INITI1, INITI2, J, K, NCNVRG,$ NEIG, NINT, NRIGHT, OLNINTDOUBLE PRECISION DELTA, EPS, GAP, LEFT, MID, PERT, RIGHT, S,$ THRESH, TMP, WIDTH* ..* .. External Functions ..DOUBLE PRECISION DLAMCHEXTERNAL DLAMCH* ..* .. Intrinsic Functions ..INTRINSIC ABS, MAX, MIN* ..* .. Executable Statements ..*EPS = DLAMCH( 'Precision' )I1 = IFIRSTI2 = IFIRSTNEIG = ILAST - IFIRST + 1NCNVRG = 0THRESH = RELTOLDO 10 I = IFIRST, ILASTIWORK( I ) = 0PERT = EPS*( ABS( SIGMA )+ABS( W( I ) ) )WERR( I ) = WERR( I ) + PERTIF( WGAP( I ).LT.PERT )$ WGAP( I ) = PERT10 CONTINUEDO 20 I = I1, ILASTIF( I.EQ.1 ) THENGAP = WGAP( I )ELSE IF( I.EQ.N ) THENGAP = WGAP( I-1 )ELSEGAP = MIN( WGAP( I-1 ), WGAP( I ) )END IFIF( WERR( I ).LT.THRESH*GAP ) THENNCNVRG = NCNVRG + 1IWORK( I ) = 1IF( I1.EQ.I )$ I1 = I1 + 1ELSEI2 = IEND IF20 CONTINUE** Initialize the unconverged intervals.*I = I1NINT = 0RIGHT = ZERO30 CONTINUEIF( I.LE.I2 ) THENIF( IWORK( I ).EQ.0 ) THENDELTA = EPSLEFT = W( I ) - WERR( I )** Do while( CNT(LEFT).GT.I-1 )*40 CONTINUEIF( I.GT.I1 .AND. LEFT.LE.RIGHT ) THENLEFT = RIGHTCNT = I - 1ELSES = -LEFTCNT = 0DO 50 J = 1, N - 1TMP = D( J ) + SS = S*( LD( J ) / TMP )*L( J ) - LEFTIF( TMP.LT.ZERO )$ CNT = CNT + 150 CONTINUETMP = D( N ) + SIF( TMP.LT.ZERO )$ CNT = CNT + 1IF( CNT.GT.I-1 ) THENDELTA = TWO*DELTALEFT = LEFT - ( ABS( SIGMA )+ABS( LEFT ) )*DELTAGO TO 40END IFEND IFDELTA = EPSRIGHT = W( I ) + WERR( I )** Do while( CNT(RIGHT).LT.I )*60 CONTINUES = -RIGHTCNT = 0DO 70 J = 1, N - 1TMP = D( J ) + SS = S*( LD( J ) / TMP )*L( J ) - RIGHTIF( TMP.LT.ZERO )$ CNT = CNT + 170 CONTINUETMP = D( N ) + SIF( TMP.LT.ZERO )$ CNT = CNT + 1IF( CNT.LT.I ) THENDELTA = TWO*DELTARIGHT = RIGHT + ( ABS( SIGMA )+ABS( RIGHT ) )*DELTAGO TO 60END IFWERR( I ) = LEFTW( I ) = RIGHTIWORK( N+I ) = CNTNINT = NINT + 1I = CNT + 1ELSEI = I + 1END IFGO TO 30END IF** While( NCNVRG.LT.NEIG )*INITI1 = I1INITI2 = I280 CONTINUEIF( NCNVRG.LT.NEIG ) THENOLNINT = NINTI = I1DO 100 K = 1, OLNINTNRIGHT = IWORK( N+I )IF( IWORK( I ).EQ.0 ) THENMID = HALF*( WERR( I )+W( I ) )S = -MIDCNT = 0DO 90 J = 1, N - 1TMP = D( J ) + SS = S*( LD( J ) / TMP )*L( J ) - MIDIF( TMP.LT.ZERO )$ CNT = CNT + 190 CONTINUETMP = D( N ) + SIF( TMP.LT.ZERO )$ CNT = CNT + 1CNT = MAX( I-1, MIN( NRIGHT, CNT ) )IF( I.EQ.NRIGHT ) THENIF( I.EQ.IFIRST ) THENGAP = WERR( I+1 ) - W( I )ELSE IF( I.EQ.ILAST ) THENGAP = WERR( I ) - W( I-1 )ELSEGAP = MIN( WERR( I+1 )-W( I ), WERR( I )-W( I-1 ) )END IFWIDTH = W( I ) - MIDIF( WIDTH.LT.THRESH*GAP ) THENNCNVRG = NCNVRG + 1IWORK( I ) = 1IF( I1.EQ.I ) THENI1 = I1 + 1NINT = NINT - 1END IFEND IFEND IFIF( IWORK( I ).EQ.0 )$ I2 = KIF( CNT.EQ.I-1 ) THENWERR( I ) = MIDELSE IF( CNT.EQ.NRIGHT ) THENW( I ) = MIDELSEIWORK( N+I ) = CNTNINT = NINT + 1WERR( CNT+1 ) = MIDW( CNT+1 ) = W( I )W( I ) = MIDI = CNT + 1IWORK( N+I ) = NRIGHTEND IFEND IFI = NRIGHT + 1100 CONTINUENINT = NINT - OLNINT + I2GO TO 80END IFDO 110 I = INITI1, INITI2W( I ) = HALF*( WERR( I )+W( I ) )WERR( I ) = W( I ) - WERR( I )110 CONTINUE*RETURN** End of DLARRB*ENDSUBROUTINE DLARRF( N, D, L, LD, LLD, IFIRST, ILAST, W, DPLUS,$ LPLUS, WORK, IWORK, INFO )** -- LAPACK auxiliary 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 IFIRST, ILAST, INFO, N* ..* .. Array Arguments ..INTEGER IWORK( * )DOUBLE PRECISION D( * ), DPLUS( * ), L( * ), LD( * ), LLD( * ),$ LPLUS( * ), W( * ), WORK( * )* ..** Purpose* =======** Given the initial representation L D L^T and its cluster of close* eigenvalues (in a relative measure), W( IFIRST ), W( IFIRST+1 ), ...* W( ILAST ), DLARRF finds a new relatively robust representation* L D L^T - SIGMA I = L(+) D(+) L(+)^T such that at least one of the* eigenvalues of L(+) D(+) L(+)^T is relatively isolated.** Arguments* =========** N (input) INTEGER* The order of the matrix.** D (input) DOUBLE PRECISION array, dimension (N)* The n diagonal elements of the diagonal matrix D.** L (input) DOUBLE PRECISION array, dimension (N-1)* The (n-1) subdiagonal elements of the unit bidiagonal* matrix L.** LD (input) DOUBLE PRECISION array, dimension (N-1)* The n-1 elements L(i)*D(i).** LLD (input) DOUBLE PRECISION array, dimension (N-1)* The n-1 elements L(i)*L(i)*D(i).** IFIRST (input) INTEGER* The index of the first eigenvalue in the cluster.** ILAST (input) INTEGER* The index of the last eigenvalue in the cluster.** W (input/output) DOUBLE PRECISION array, dimension (N)* On input, the eigenvalues of L D L^T in ascending order.* W( IFIRST ) through W( ILAST ) form the cluster of relatively* close eigenalues.* On output, W( IFIRST ) thru' W( ILAST ) are estimates of the* corresponding eigenvalues of L(+) D(+) L(+)^T.** SIGMA (input) DOUBLE PRECISION* The shift used to form L(+) D(+) L(+)^T.** DPLUS (output) DOUBLE PRECISION array, dimension (N)* The n diagonal elements of the diagonal matrix D(+).** LPLUS (output) DOUBLE PRECISION array, dimension (N)* The first (n-1) elements of LPLUS contain the subdiagonal* elements of the unit bidiagonal matrix L(+). LPLUS( N ) is* set to SIGMA.** WORK (input) DOUBLE PRECISION array, dimension (???)* Workspace.** Further Details* ===============** Based on contributions by* Inderjit Dhillon, IBM Almaden, USA* Osni Marques, LBNL/NERSC, USA** =====================================================================** .. Parameters ..DOUBLE PRECISION ZERO, TWOPARAMETER ( ZERO = 0.0D0, TWO = 2.0D0 )* ..* .. Local Scalars ..INTEGER IDOUBLE PRECISION DELTA, EPS, S, SIGMA* ..* .. External Functions ..DOUBLE PRECISION DLAMCHEXTERNAL DLAMCH* ..* .. Intrinsic Functions ..INTRINSIC ABS* ..* .. Executable Statements ..*INFO = 0EPS = DLAMCH( 'Precision' )IF( IFIRST.EQ.1 ) THENSIGMA = W( IFIRST )ELSE IF( ILAST.EQ.N ) THENSIGMA = W( ILAST )ELSEINFO = 1RETURNEND IF** Compute the new relatively robust representation (RRR)*DELTA = TWO*EPS10 CONTINUEIF( IFIRST.EQ.1 ) THENSIGMA = SIGMA - ABS( SIGMA )*DELTAELSESIGMA = SIGMA + ABS( SIGMA )*DELTAEND IFS = -SIGMADO 20 I = 1, N - 1DPLUS( I ) = D( I ) + SLPLUS( I ) = LD( I ) / DPLUS( I )S = S*LPLUS( I )*L( I ) - SIGMA20 CONTINUEDPLUS( N ) = D( N ) + SIF( IFIRST.EQ.1 ) THENDO 30 I = 1, NIF( DPLUS( I ).LT.ZERO ) THENDELTA = TWO*DELTAGO TO 10END IF30 CONTINUEELSEDO 40 I = 1, NIF( DPLUS( I ).GT.ZERO ) THENDELTA = TWO*DELTAGO TO 10END IF40 CONTINUEEND IFDO 50 I = IFIRST, ILASTW( I ) = W( I ) - SIGMA50 CONTINUELPLUS( N ) = SIGMA*RETURN** End of DLARRF*ENDSUBROUTINE DLAR1V( N, B1, BN, SIGMA, D, L, LD, LLD, GERSCH, Z,$ ZTZ, MINGMA, R, ISUPPZ, WORK )** -- LAPACK auxiliary 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 B1, BN, N, RDOUBLE PRECISION MINGMA, SIGMA, ZTZ* ..* .. Array Arguments ..INTEGER ISUPPZ( * )DOUBLE PRECISION D( * ), GERSCH( * ), L( * ), LD( * ), LLD( * ),$ WORK( * ), Z( * )* ..** Purpose* =======** DLAR1V computes the (scaled) r-th column of the inverse of* the sumbmatrix in rows B1 through BN of the tridiagonal matrix* L D L^T - sigma I. The following steps accomplish this computation :* (a) Stationary qd transform, L D L^T - sigma I = L(+) D(+) L(+)^T,* (b) Progressive qd transform, L D L^T - sigma I = U(-) D(-) U(-)^T,* (c) Computation of the diagonal elements of the inverse of* L D L^T - sigma I by combining the above transforms, and choosing* r as the index where the diagonal of the inverse is (one of the)* largest in magnitude.* (d) Computation of the (scaled) r-th column of the inverse using the* twisted factorization obtained by combining the top part of the* the stationary and the bottom part of the progressive transform.** Arguments* =========** N (input) INTEGER* The order of the matrix L D L^T.** B1 (input) INTEGER* First index of the submatrix of L D L^T.** BN (input) INTEGER* Last index of the submatrix of L D L^T.** SIGMA (input) DOUBLE PRECISION* The shift. Initially, when R = 0, SIGMA should be a good* approximation to an eigenvalue of L D L^T.** L (input) DOUBLE PRECISION array, dimension (N-1)* The (n-1) subdiagonal elements of the unit bidiagonal matrix* L, in elements 1 to N-1.** D (input) DOUBLE PRECISION array, dimension (N)* The n diagonal elements of the diagonal matrix D.** LD (input) DOUBLE PRECISION array, dimension (N-1)* The n-1 elements L(i)*D(i).** LLD (input) DOUBLE PRECISION array, dimension (N-1)* The n-1 elements L(i)*L(i)*D(i).** GERSCH (input) DOUBLE PRECISION array, dimension (2*N)* The n Gerschgorin intervals. These are used to restrict* the initial search for R, when R is input as 0.** Z (output) DOUBLE PRECISION array, dimension (N)* The (scaled) r-th column of the inverse. Z(R) is returned* to be 1.** ZTZ (output) DOUBLE PRECISION* The square of the norm of Z.** MINGMA (output) DOUBLE PRECISION* The reciprocal of the largest (in magnitude) diagonal* element of the inverse of L D L^T - sigma I.** R (input/output) INTEGER* Initially, R should be input to be 0 and is then output as* the index where the diagonal element of the inverse is* largest in magnitude. In later iterations, this same value* of R should be input.** ISUPPZ (output) INTEGER array, dimension (2)* The support of the vector in Z, i.e., the vector Z is* nonzero only in elements ISUPPZ(1) through ISUPPZ( 2 ).** WORK (workspace) DOUBLE PRECISION array, dimension (4*N)** Further Details* ===============** Based on contributions by* Inderjit Dhillon, IBM Almaden, USA* Osni Marques, LBNL/NERSC, USA** =====================================================================** .. Parameters ..INTEGER BLKSIZPARAMETER ( BLKSIZ = 32 )DOUBLE PRECISION ZERO, ONEPARAMETER ( ZERO = 0.0D0, ONE = 1.0D0 )* ..* .. Local Scalars ..LOGICAL SAWNANINTEGER FROM, I, INDP, INDS, INDUMN, J, R1, R2, TODOUBLE PRECISION DMINUS, DPLUS, EPS, S, TMP* ..* .. External Functions ..DOUBLE PRECISION DLAMCHEXTERNAL DLAMCH* ..* .. Intrinsic Functions ..INTRINSIC ABS, MAX, MIN* ..* .. Executable Statements ..*EPS = DLAMCH( 'Precision' )IF( R.EQ.0 ) THEN** Eliminate the top and bottom indices from the possible values* of R where the desired eigenvector is largest in magnitude.*R1 = B1DO 10 I = B1, BNIF( SIGMA.GE.GERSCH( 2*I-1 ) .OR. SIGMA.LE.GERSCH( 2*I ) )$ THENR1 = IGO TO 20END IF10 CONTINUE20 CONTINUER2 = BNDO 30 I = BN, B1, -1IF( SIGMA.GE.GERSCH( 2*I-1 ) .OR. SIGMA.LE.GERSCH( 2*I ) )$ THENR2 = IGO TO 40END IF30 CONTINUE40 CONTINUEELSER1 = RR2 = REND IF*INDUMN = NINDS = 2*N + 1INDP = 3*N + 1SAWNAN = .FALSE.** Compute the stationary transform (using the differential form)* untill the index R2*IF( B1.EQ.1 ) THENWORK( INDS ) = ZEROELSEWORK( INDS ) = LLD( B1-1 )END IFS = WORK( INDS ) - SIGMADO 50 I = B1, R2 - 1DPLUS = D( I ) + SWORK( I ) = LD( I ) / DPLUSWORK( INDS+I ) = S*WORK( I )*L( I )S = WORK( INDS+I ) - SIGMA50 CONTINUE*IF( .NOT.( S.GT.ZERO .OR. S.LT.ONE ) ) THEN** Run a slower version of the above loop if a NaN is detected*SAWNAN = .TRUE.J = B1 + 160 CONTINUEIF( WORK( INDS+J ).GT.ZERO .OR. WORK( INDS+J ).LT.ONE ) THENJ = J + 1GO TO 60END IFWORK( INDS+J ) = LLD( J )S = WORK( INDS+J ) - SIGMADO 70 I = J + 1, R2 - 1DPLUS = D( I ) + SWORK( I ) = LD( I ) / DPLUSIF( WORK( I ).EQ.ZERO ) THENWORK( INDS+I ) = LLD( I )ELSEWORK( INDS+I ) = S*WORK( I )*L( I )END IFS = WORK( INDS+I ) - SIGMA70 CONTINUEEND IFWORK( INDP+BN-1 ) = D( BN ) - SIGMADO 80 I = BN - 1, R1, -1DMINUS = LLD( I ) + WORK( INDP+I )TMP = D( I ) / DMINUSWORK( INDUMN+I ) = L( I )*TMPWORK( INDP+I-1 ) = WORK( INDP+I )*TMP - SIGMA80 CONTINUETMP = WORK( INDP+R1-1 )IF( .NOT.( TMP.GT.ZERO .OR. TMP.LT.ONE ) ) THEN** Run a slower version of the above loop if a NaN is detected*SAWNAN = .TRUE.J = BN - 390 CONTINUEIF( WORK( INDP+J ).GT.ZERO .OR. WORK( INDP+J ).LT.ONE ) THENJ = J - 1GO TO 90END IFWORK( INDP+J ) = D( J+1 ) - SIGMADO 100 I = J, R1, -1DMINUS = LLD( I ) + WORK( INDP+I )TMP = D( I ) / DMINUSWORK( INDUMN+I ) = L( I )*TMPIF( TMP.EQ.ZERO ) THENWORK( INDP+I-1 ) = D( I ) - SIGMAELSEWORK( INDP+I-1 ) = WORK( INDP+I )*TMP - SIGMAEND IF100 CONTINUEEND IF** Find the index (from R1 to R2) of the largest (in magnitude)* diagonal element of the inverse*MINGMA = WORK( INDS+R1-1 ) + WORK( INDP+R1-1 )IF( MINGMA.EQ.ZERO )$ MINGMA = EPS*WORK( INDS+R1-1 )R = R1DO 110 I = R1, R2 - 1TMP = WORK( INDS+I ) + WORK( INDP+I )IF( TMP.EQ.ZERO )$ TMP = EPS*WORK( INDS+I )IF( ABS( TMP ).LT.ABS( MINGMA ) ) THENMINGMA = TMPR = I + 1END IF110 CONTINUE** Compute the (scaled) r-th column of the inverse*ISUPPZ( 1 ) = B1ISUPPZ( 2 ) = BNZ( R ) = ONEZTZ = ONEIF( .NOT.SAWNAN ) THENFROM = R - 1TO = MAX( R-BLKSIZ, B1 )120 CONTINUEIF( FROM.GE.B1 ) THENDO 130 I = FROM, TO, -1Z( I ) = -( WORK( I )*Z( I+1 ) )ZTZ = ZTZ + Z( I )*Z( I )130 CONTINUEIF( ABS( Z( TO ) ).LE.EPS .AND. ABS( Z( TO+1 ) ).LE.EPS )$ THENISUPPZ( 1 ) = TO + 2ELSEFROM = TO - 1TO = MAX( TO-BLKSIZ, B1 )GO TO 120END IFEND IFFROM = R + 1TO = MIN( R+BLKSIZ, BN )140 CONTINUEIF( FROM.LE.BN ) THENDO 150 I = FROM, TOZ( I ) = -( WORK( INDUMN+I-1 )*Z( I-1 ) )ZTZ = ZTZ + Z( I )*Z( I )150 CONTINUEIF( ABS( Z( TO ) ).LE.EPS .AND. ABS( Z( TO-1 ) ).LE.EPS )$ THENISUPPZ( 2 ) = TO - 2ELSEFROM = TO + 1TO = MIN( TO+BLKSIZ, BN )GO TO 140END IFEND IFELSEDO 160 I = R - 1, B1, -1IF( Z( I+1 ).EQ.ZERO ) THENZ( I ) = -( LD( I+1 ) / LD( I ) )*Z( I+2 )ELSE IF( ABS( Z( I+1 ) ).LE.EPS .AND. ABS( Z( I+2 ) ).LE.$ EPS ) THENISUPPZ( 1 ) = I + 3GO TO 170ELSEZ( I ) = -( WORK( I )*Z( I+1 ) )END IFZTZ = ZTZ + Z( I )*Z( I )160 CONTINUE170 CONTINUEDO 180 I = R, BN - 1IF( Z( I ).EQ.ZERO ) THENZ( I+1 ) = -( LD( I-1 ) / LD( I ) )*Z( I-1 )ELSE IF( ABS( Z( I ) ).LE.EPS .AND. ABS( Z( I-1 ) ).LE.EPS )$ THENISUPPZ( 2 ) = I - 2GO TO 190ELSEZ( I+1 ) = -( WORK( INDUMN+I )*Z( I ) )END IFZTZ = ZTZ + Z( I+1 )*Z( I+1 )180 CONTINUE190 CONTINUEEND IFDO 200 I = B1, ISUPPZ( 1 ) - 3Z( I ) = ZERO200 CONTINUEDO 210 I = ISUPPZ( 2 ) + 3, BNZ( I ) = ZERO210 CONTINUE*RETURN** End of DLAR1V*ENDSUBROUTINE DLARUV( ISEED, N, X )** -- LAPACK auxiliary routine (version 3.0) --* Univ. of Tennessee, Univ. of California Berkeley, NAG Ltd.,* Courant Institute, Argonne National Lab, and Rice University* October 31, 1992** .. Scalar Arguments ..INTEGER N* ..* .. Array Arguments ..INTEGER ISEED( 4 )DOUBLE PRECISION X( N )* ..** Purpose* =======** DLARUV returns a vector of n random real numbers from a uniform (0,1)* distribution (n <= 128).** This is an auxiliary routine called by DLARNV and ZLARNV.** Arguments* =========** ISEED (input/output) INTEGER array, dimension (4)* On entry, the seed of the random number generator; the array* elements must be between 0 and 4095, and ISEED(4) must be* odd.* On exit, the seed is updated.** N (input) INTEGER* The number of random numbers to be generated. N <= 128.** X (output) DOUBLE PRECISION array, dimension (N)* The generated random numbers.** Further Details* ===============** This routine uses a multiplicative congruential method with modulus* 2**48 and multiplier 33952834046453 (see G.S.Fishman,* 'Multiplicative congruential random number generators with modulus* 2**b: an exhaustive analysis for b = 32 and a partial analysis for* b = 48', Math. Comp. 189, pp 331-344, 1990).** 48-bit integers are stored in 4 integer array elements with 12 bits* per element. Hence the routine is portable across machines with* integers of 32 bits or more.** =====================================================================** .. Parameters ..DOUBLE PRECISION ONEPARAMETER ( ONE = 1.0D0 )INTEGER LV, IPW2DOUBLE PRECISION RPARAMETER ( LV = 128, IPW2 = 4096, R = ONE / IPW2 )* ..* .. Local Scalars ..INTEGER I, I1, I2, I3, I4, IT1, IT2, IT3, IT4, J* ..* .. Local Arrays ..INTEGER MM( LV, 4 )* ..* .. Intrinsic Functions ..INTRINSIC DBLE, MIN, MOD* ..* .. Data statements ..DATA ( MM( 1, J ), J = 1, 4 ) / 494, 322, 2508,$ 2549 /DATA ( MM( 2, J ), J = 1, 4 ) / 2637, 789, 3754,$ 1145 /DATA ( MM( 3, J ), J = 1, 4 ) / 255, 1440, 1766,$ 2253 /DATA ( MM( 4, J ), J = 1, 4 ) / 2008, 752, 3572,$ 305 /DATA ( MM( 5, J ), J = 1, 4 ) / 1253, 2859, 2893,$ 3301 /DATA ( MM( 6, J ), J = 1, 4 ) / 3344, 123, 307,$ 1065 /DATA ( MM( 7, J ), J = 1, 4 ) / 4084, 1848, 1297,$ 3133 /DATA ( MM( 8, J ), J = 1, 4 ) / 1739, 643, 3966,$ 2913 /DATA ( MM( 9, J ), J = 1, 4 ) / 3143, 2405, 758,$ 3285 /DATA ( MM( 10, J ), J = 1, 4 ) / 3468, 2638, 2598,$ 1241 /DATA ( MM( 11, J ), J = 1, 4 ) / 688, 2344, 3406,$ 1197 /DATA ( MM( 12, J ), J = 1, 4 ) / 1657, 46, 2922,$ 3729 /DATA ( MM( 13, J ), J = 1, 4 ) / 1238, 3814, 1038,$ 2501 /DATA ( MM( 14, J ), J = 1, 4 ) / 3166, 913, 2934,$ 1673 /DATA ( MM( 15, J ), J = 1, 4 ) / 1292, 3649, 2091,$ 541 /DATA ( MM( 16, J ), J = 1, 4 ) / 3422, 339, 2451,$ 2753 /DATA ( MM( 17, J ), J = 1, 4 ) / 1270, 3808, 1580,$ 949 /DATA ( MM( 18, J ), J = 1, 4 ) / 2016, 822, 1958,$ 2361 /DATA ( MM( 19, J ), J = 1, 4 ) / 154, 2832, 2055,$ 1165 /DATA ( MM( 20, J ), J = 1, 4 ) / 2862, 3078, 1507,$ 4081 /DATA ( MM( 21, J ), J = 1, 4 ) / 697, 3633, 1078,$ 2725 /DATA ( MM( 22, J ), J = 1, 4 ) / 1706, 2970, 3273,$ 3305 /DATA ( MM( 23, J ), J = 1, 4 ) / 491, 637, 17,$ 3069 /DATA ( MM( 24, J ), J = 1, 4 ) / 931, 2249, 854,$ 3617 /DATA ( MM( 25, J ), J = 1, 4 ) / 1444, 2081, 2916,$ 3733 /DATA ( MM( 26, J ), J = 1, 4 ) / 444, 4019, 3971,$ 409 /DATA ( MM( 27, J ), J = 1, 4 ) / 3577, 1478, 2889,$ 2157 /DATA ( MM( 28, J ), J = 1, 4 ) / 3944, 242, 3831,$ 1361 /DATA ( MM( 29, J ), J = 1, 4 ) / 2184, 481, 2621,$ 3973 /DATA ( MM( 30, J ), J = 1, 4 ) / 1661, 2075, 1541,$ 1865 /DATA ( MM( 31, J ), J = 1, 4 ) / 3482, 4058, 893,$ 2525 /DATA ( MM( 32, J ), J = 1, 4 ) / 657, 622, 736,$ 1409 /DATA ( MM( 33, J ), J = 1, 4 ) / 3023, 3376, 3992,$ 3445 /DATA ( MM( 34, J ), J = 1, 4 ) / 3618, 812, 787,$ 3577 /DATA ( MM( 35, J ), J = 1, 4 ) / 1267, 234, 2125,$ 77 /DATA ( MM( 36, J ), J = 1, 4 ) / 1828, 641, 2364,$ 3761 /DATA ( MM( 37, J ), J = 1, 4 ) / 164, 4005, 2460,$ 2149 /DATA ( MM( 38, J ), J = 1, 4 ) / 3798, 1122, 257,$ 1449 /DATA ( MM( 39, J ), J = 1, 4 ) / 3087, 3135, 1574,$ 3005 /DATA ( MM( 40, J ), J = 1, 4 ) / 2400, 2640, 3912,$ 225 /DATA ( MM( 41, J ), J = 1, 4 ) / 2870, 2302, 1216,$ 85 /DATA ( MM( 42, J ), J = 1, 4 ) / 3876, 40, 3248,$ 3673 /DATA ( MM( 43, J ), J = 1, 4 ) / 1905, 1832, 3401,$ 3117 /DATA ( MM( 44, J ), J = 1, 4 ) / 1593, 2247, 2124,$ 3089 /DATA ( MM( 45, J ), J = 1, 4 ) / 1797, 2034, 2762,$ 1349 /DATA ( MM( 46, J ), J = 1, 4 ) / 1234, 2637, 149,$ 2057 /DATA ( MM( 47, J ), J = 1, 4 ) / 3460, 1287, 2245,$ 413 /DATA ( MM( 48, J ), J = 1, 4 ) / 328, 1691, 166,$ 65 /DATA ( MM( 49, J ), J = 1, 4 ) / 2861, 496, 466,$ 1845 /DATA ( MM( 50, J ), J = 1, 4 ) / 1950, 1597, 4018,$ 697 /DATA ( MM( 51, J ), J = 1, 4 ) / 617, 2394, 1399,$ 3085 /DATA ( MM( 52, J ), J = 1, 4 ) / 2070, 2584, 190,$ 3441 /DATA ( MM( 53, J ), J = 1, 4 ) / 3331, 1843, 2879,$ 1573 /DATA ( MM( 54, J ), J = 1, 4 ) / 769, 336, 153,$ 3689 /DATA ( MM( 55, J ), J = 1, 4 ) / 1558, 1472, 2320,$ 2941 /DATA ( MM( 56, J ), J = 1, 4 ) / 2412, 2407, 18,$ 929 /DATA ( MM( 57, J ), J = 1, 4 ) / 2800, 433, 712,$ 533 /DATA ( MM( 58, J ), J = 1, 4 ) / 189, 2096, 2159,$ 2841 /DATA ( MM( 59, J ), J = 1, 4 ) / 287, 1761, 2318,$ 4077 /DATA ( MM( 60, J ), J = 1, 4 ) / 2045, 2810, 2091,$ 721 /DATA ( MM( 61, J ), J = 1, 4 ) / 1227, 566, 3443,$ 2821 /DATA ( MM( 62, J ), J = 1, 4 ) / 2838, 442, 1510,$ 2249 /DATA ( MM( 63, J ), J = 1, 4 ) / 209, 41, 449,$ 2397 /DATA ( MM( 64, J ), J = 1, 4 ) / 2770, 1238, 1956,$ 2817 /DATA ( MM( 65, J ), J = 1, 4 ) / 3654, 1086, 2201,$ 245 /DATA ( MM( 66, J ), J = 1, 4 ) / 3993, 603, 3137,$ 1913 /DATA ( MM( 67, J ), J = 1, 4 ) / 192, 840, 3399,$ 1997 /DATA ( MM( 68, J ), J = 1, 4 ) / 2253, 3168, 1321,$ 3121 /DATA ( MM( 69, J ), J = 1, 4 ) / 3491, 1499, 2271,$ 997 /DATA ( MM( 70, J ), J = 1, 4 ) / 2889, 1084, 3667,$ 1833 /DATA ( MM( 71, J ), J = 1, 4 ) / 2857, 3438, 2703,$ 2877 /DATA ( MM( 72, J ), J = 1, 4 ) / 2094, 2408, 629,$ 1633 /DATA ( MM( 73, J ), J = 1, 4 ) / 1818, 1589, 2365,$ 981 /DATA ( MM( 74, J ), J = 1, 4 ) / 688, 2391, 2431,$ 2009 /DATA ( MM( 75, J ), J = 1, 4 ) / 1407, 288, 1113,$ 941 /DATA ( MM( 76, J ), J = 1, 4 ) / 634, 26, 3922,$ 2449 /DATA ( MM( 77, J ), J = 1, 4 ) / 3231, 512, 2554,$ 197 /DATA ( MM( 78, J ), J = 1, 4 ) / 815, 1456, 184,$ 2441 /DATA ( MM( 79, J ), J = 1, 4 ) / 3524, 171, 2099,$ 285 /DATA ( MM( 80, J ), J = 1, 4 ) / 1914, 1677, 3228,$ 1473 /DATA ( MM( 81, J ), J = 1, 4 ) / 516, 2657, 4012,$ 2741 /DATA ( MM( 82, J ), J = 1, 4 ) / 164, 2270, 1921,$ 3129 /DATA ( MM( 83, J ), J = 1, 4 ) / 303, 2587, 3452,$ 909 /DATA ( MM( 84, J ), J = 1, 4 ) / 2144, 2961, 3901,$ 2801 /DATA ( MM( 85, J ), J = 1, 4 ) / 3480, 1970, 572,$ 421 /DATA ( MM( 86, J ), J = 1, 4 ) / 119, 1817, 3309,$ 4073 /DATA ( MM( 87, J ), J = 1, 4 ) / 3357, 676, 3171,$ 2813 /DATA ( MM( 88, J ), J = 1, 4 ) / 837, 1410, 817,$ 2337 /DATA ( MM( 89, J ), J = 1, 4 ) / 2826, 3723, 3039,$ 1429 /DATA ( MM( 90, J ), J = 1, 4 ) / 2332, 2803, 1696,$ 1177 /DATA ( MM( 91, J ), J = 1, 4 ) / 2089, 3185, 1256,$ 1901 /DATA ( MM( 92, J ), J = 1, 4 ) / 3780, 184, 3715,$ 81 /DATA ( MM( 93, J ), J = 1, 4 ) / 1700, 663, 2077,$ 1669 /DATA ( MM( 94, J ), J = 1, 4 ) / 3712, 499, 3019,$ 2633 /DATA ( MM( 95, J ), J = 1, 4 ) / 150, 3784, 1497,$ 2269 /DATA ( MM( 96, J ), J = 1, 4 ) / 2000, 1631, 1101,$ 129 /DATA ( MM( 97, J ), J = 1, 4 ) / 3375, 1925, 717,$ 1141 /DATA ( MM( 98, J ), J = 1, 4 ) / 1621, 3912, 51,$ 249 /DATA ( MM( 99, J ), J = 1, 4 ) / 3090, 1398, 981,$ 3917 /DATA ( MM( 100, J ), J = 1, 4 ) / 3765, 1349, 1978,$ 2481 /DATA ( MM( 101, J ), J = 1, 4 ) / 1149, 1441, 1813,$ 3941 /DATA ( MM( 102, J ), J = 1, 4 ) / 3146, 2224, 3881,$ 2217 /DATA ( MM( 103, J ), J = 1, 4 ) / 33, 2411, 76,$ 2749 /DATA ( MM( 104, J ), J = 1, 4 ) / 3082, 1907, 3846,$ 3041 /DATA ( MM( 105, J ), J = 1, 4 ) / 2741, 3192, 3694,$ 1877 /DATA ( MM( 106, J ), J = 1, 4 ) / 359, 2786, 1682,$ 345 /DATA ( MM( 107, J ), J = 1, 4 ) / 3316, 382, 124,$ 2861 /DATA ( MM( 108, J ), J = 1, 4 ) / 1749, 37, 1660,$ 1809 /DATA ( MM( 109, J ), J = 1, 4 ) / 185, 759, 3997,$ 3141 /DATA ( MM( 110, J ), J = 1, 4 ) / 2784, 2948, 479,$ 2825 /DATA ( MM( 111, J ), J = 1, 4 ) / 2202, 1862, 1141,$ 157 /DATA ( MM( 112, J ), J = 1, 4 ) / 2199, 3802, 886,$ 2881 /DATA ( MM( 113, J ), J = 1, 4 ) / 1364, 2423, 3514,$ 3637 /DATA ( MM( 114, J ), J = 1, 4 ) / 1244, 2051, 1301,$ 1465 /DATA ( MM( 115, J ), J = 1, 4 ) / 2020, 2295, 3604,$ 2829 /DATA ( MM( 116, J ), J = 1, 4 ) / 3160, 1332, 1888,$ 2161 /DATA ( MM( 117, J ), J = 1, 4 ) / 2785, 1832, 1836,$ 3365 /DATA ( MM( 118, J ), J = 1, 4 ) / 2772, 2405, 1990,$ 361 /DATA ( MM( 119, J ), J = 1, 4 ) / 1217, 3638, 2058,$ 2685 /DATA ( MM( 120, J ), J = 1, 4 ) / 1822, 3661, 692,$ 3745 /DATA ( MM( 121, J ), J = 1, 4 ) / 1245, 327, 1194,$ 2325 /DATA ( MM( 122, J ), J = 1, 4 ) / 2252, 3660, 20,$ 3609 /DATA ( MM( 123, J ), J = 1, 4 ) / 3904, 716, 3285,$ 3821 /DATA ( MM( 124, J ), J = 1, 4 ) / 2774, 1842, 2046,$ 3537 /DATA ( MM( 125, J ), J = 1, 4 ) / 997, 3987, 2107,$ 517 /DATA ( MM( 126, J ), J = 1, 4 ) / 2573, 1368, 3508,$ 3017 /DATA ( MM( 127, J ), J = 1, 4 ) / 1148, 1848, 3525,$ 2141 /DATA ( MM( 128, J ), J = 1, 4 ) / 545, 2366, 3801,$ 1537 /* ..* .. Executable Statements ..*I1 = ISEED( 1 )I2 = ISEED( 2 )I3 = ISEED( 3 )I4 = ISEED( 4 )*DO 10 I = 1, MIN( N, LV )** Multiply the seed by i-th power of the multiplier modulo 2**48*IT4 = I4*MM( I, 4 )IT3 = IT4 / IPW2IT4 = IT4 - IPW2*IT3IT3 = IT3 + I3*MM( I, 4 ) + I4*MM( I, 3 )IT2 = IT3 / IPW2IT3 = IT3 - IPW2*IT2IT2 = IT2 + I2*MM( I, 4 ) + I3*MM( I, 3 ) + I4*MM( I, 2 )IT1 = IT2 / IPW2IT2 = IT2 - IPW2*IT1IT1 = IT1 + I1*MM( I, 4 ) + I2*MM( I, 3 ) + I3*MM( I, 2 ) +$ I4*MM( I, 1 )IT1 = MOD( IT1, IPW2 )** Convert 48-bit integer to a real number in the interval (0,1)*X( I ) = R*( DBLE( IT1 )+R*( DBLE( IT2 )+R*( DBLE( IT3 )+R*$ DBLE( IT4 ) ) ) )10 CONTINUE** Return final value of seed*ISEED( 1 ) = IT1ISEED( 2 ) = IT2ISEED( 3 ) = IT3ISEED( 4 ) = IT4RETURN** End of DLARUV*END