diff options
author | jason <jason@8a072113-8704-0410-8d35-dd094bca7971> | 2008-10-28 01:38:50 +0000 |
---|---|---|
committer | jason <jason@8a072113-8704-0410-8d35-dd094bca7971> | 2008-10-28 01:38:50 +0000 |
commit | baba851215b44ac3b60b9248eb02bcce7eb76247 (patch) | |
tree | 8c0f5c006875532a30d4409f5e94b0f310ff00a7 /SRC/zcgesv.f | |
download | lapack-baba851215b44ac3b60b9248eb02bcce7eb76247.tar.gz lapack-baba851215b44ac3b60b9248eb02bcce7eb76247.tar.bz2 lapack-baba851215b44ac3b60b9248eb02bcce7eb76247.zip |
Move LAPACK trunk into position.
Diffstat (limited to 'SRC/zcgesv.f')
-rw-r--r-- | SRC/zcgesv.f | 345 |
1 files changed, 345 insertions, 0 deletions
diff --git a/SRC/zcgesv.f b/SRC/zcgesv.f new file mode 100644 index 00000000..5a6d5c28 --- /dev/null +++ b/SRC/zcgesv.f @@ -0,0 +1,345 @@ + SUBROUTINE ZCGESV( N, NRHS, A, LDA, IPIV, B, LDB, X, LDX, WORK, + + SWORK, ITER, INFO) +* +* -- LAPACK PROTOTYPE driver routine (version 3.1.1) -- +* Univ. of Tennessee, Univ. of California Berkeley and NAG Ltd.. +* January 2007 +* +* .. +* .. WARNING: PROTOTYPE .. +* This is an LAPACK PROTOTYPE routine which means that the +* interface of this routine is likely to be changed in the future +* based on community feedback. +* +* .. +* .. Scalar Arguments .. + INTEGER INFO,ITER,LDA,LDB,LDX,N,NRHS +* .. +* .. Array Arguments .. + INTEGER IPIV(*) + COMPLEX SWORK(*) + COMPLEX*16 A(LDA,*),B(LDB,*),WORK(N,*),X(LDX,*) +* .. +* +* Purpose +* ======= +* +* ZCGESV computes the solution to a real system of linear equations +* A * X = B, +* where A is an N-by-N matrix and X and B are N-by-NRHS matrices. +* +* ZCGESV first attempts to factorize the matrix in SINGLE COMPLEX PRECISION +* and use this factorization within an iterative refinement procedure to +* produce a solution with DOUBLE COMPLEX PRECISION normwise backward error +* quality (see below). If the approach fails the method switches to a +* DOUBLE COMPLEX PRECISION factorization and solve. +* +* The iterative refinement is not going to be a winning strategy if +* the ratio SINGLE PRECISION performance over DOUBLE PRECISION performance +* is too small. A reasonable strategy should take the number of right-hand +* sides and the size of the matrix into account. This might be done with a +* call to ILAENV in the future. Up to now, we always try iterative refinement. +* +* The iterative refinement process is stopped if +* ITER > ITERMAX +* or for all the RHS we have: +* RNRM < SQRT(N)*XNRM*ANRM*EPS*BWDMAX +* where +* o ITER is the number of the current iteration in the iterative +* refinement process +* o RNRM is the infinity-norm of the residual +* o XNRM is the infinity-norm of the solution +* o ANRM is the infinity-operator-norm of the matrix A +* o EPS is the machine epsilon returned by DLAMCH('Epsilon') +* The value ITERMAX and BWDMAX are fixed to 30 and 1.0D+00 respectively. +* +* Arguments +* ========= +* +* N (input) INTEGER +* The number of linear equations, i.e., the order of the +* matrix A. N >= 0. +* +* NRHS (input) INTEGER +* The number of right hand sides, i.e., the number of columns +* of the matrix B. NRHS >= 0. +* +* A (input or input/ouptut) COMPLEX*16 array, +* dimension (LDA,N) +* On entry, the N-by-N coefficient matrix A. +* On exit, if iterative refinement has been successfully used +* (INFO.EQ.0 and ITER.GE.0, see description below), then A is +* unchanged, if double precision factorization has been used +* (INFO.EQ.0 and ITER.LT.0, see description below), then the +* array A contains the factors L and U from the factorization +* A = P*L*U; the unit diagonal elements of L are not stored. +* +* LDA (input) INTEGER +* The leading dimension of the array A. LDA >= max(1,N). +* +* IPIV (output) INTEGER array, dimension (N) +* The pivot indices that define the permutation matrix P; +* row i of the matrix was interchanged with row IPIV(i). +* Corresponds either to the single precision factorization +* (if INFO.EQ.0 and ITER.GE.0) or the double precision +* factorization (if INFO.EQ.0 and ITER.LT.0). +* +* B (input) COMPLEX*16 array, dimension (LDB,NRHS) +* The N-by-NRHS matrix of right hand side matrix B. +* +* LDB (input) INTEGER +* The leading dimension of the array B. LDB >= max(1,N). +* +* X (output) COMPLEX*16 array, dimension (LDX,NRHS) +* If INFO = 0, the N-by-NRHS solution matrix X. +* +* LDX (input) INTEGER +* The leading dimension of the array X. LDX >= max(1,N). +* +* WORK (workspace) COMPLEX*16 array, dimension (N*NRHS) +* This array is used to hold the residual vectors. +* +* SWORK (workspace) COMPLEX array, dimension (N*(N+NRHS)) +* This array is used to use the single precision matrix and the +* right-hand sides or solutions in single precision. +* +* ITER (output) INTEGER +* < 0: iterative refinement has failed, double precision +* factorization has been performed +* -1 : taking into account machine parameters, N, NRHS, it +* is a priori not worth working in SINGLE PRECISION +* -2 : overflow of an entry when moving from double to +* SINGLE PRECISION +* -3 : failure of SGETRF +* -31: stop the iterative refinement after the 30th +* iterations +* > 0: iterative refinement has been sucessfully used. +* Returns the number of iterations +* +* INFO (output) INTEGER +* = 0: successful exit +* < 0: if INFO = -i, the i-th argument had an illegal value +* > 0: if INFO = i, U(i,i) computed in DOUBLE PRECISION is +* exactly zero. The factorization has been completed, +* but the factor U is exactly singular, so the solution +* could not be computed. +* +* ========= +* +* .. Parameters .. + COMPLEX*16 NEGONE,ONE + PARAMETER (NEGONE=(-1.0D+00,0.0D+00),ONE=(1.0D+00,0.0D+00)) +* +* .. Local Scalars .. + LOGICAL DOITREF + INTEGER I,IITER,ITERMAX,OK,PTSA,PTSX + DOUBLE PRECISION ANRM,BWDMAX,CTE,EPS,RNRM,XNRM + COMPLEX*16 ZDUM +* +* .. External Subroutines .. + EXTERNAL CGETRS,CGETRF,CLAG2Z,XERBLA,ZAXPY, + $ ZGEMM,ZLACPY,ZLAG2C +* .. +* .. External Functions .. + INTEGER IZAMAX + DOUBLE PRECISION DLAMCH,ZLANGE + EXTERNAL IZAMAX,DLAMCH,ZLANGE +* .. +* .. Intrinsic Functions .. + INTRINSIC ABS,DBLE,MAX,SQRT +* .. +* .. Statement Functions .. + DOUBLE PRECISION CABS1 +* .. +* .. Statement Function definitions .. + CABS1( ZDUM ) = ABS( DBLE( ZDUM ) ) + ABS( DIMAG( ZDUM ) ) +* .. +* .. Executable Statements .. +* + ITERMAX = 30 + BWDMAX = 1.0E+00 + DOITREF = .TRUE. +* + OK = 0 + INFO = 0 + ITER = 0 +* +* Test the input parameters. +* + IF (N.LT.0) THEN + INFO = -1 + ELSE IF (NRHS.LT.0) THEN + INFO = -2 + ELSE IF (LDA.LT.MAX(1,N)) THEN + INFO = -4 + ELSE IF (LDB.LT.MAX(1,N)) THEN + INFO = -7 + ELSE IF (LDX.LT.MAX(1,N)) THEN + INFO = -9 + END IF + IF (INFO.NE.0) THEN + CALL XERBLA('ZCGESV',-INFO) + RETURN + END IF +* +* Quick return if (N.EQ.0). +* + IF (N.EQ.0) RETURN +* +* Skip single precision iterative refinement if a priori slower +* than double precision factorization. +* + IF (.NOT.DOITREF) THEN + ITER = -1 + GO TO 40 + END IF +* +* Compute some constants. +* + ANRM = ZLANGE('I',N,N,A,LDA,WORK) + EPS = DLAMCH('Epsilon') + CTE = ANRM*EPS*SQRT(DBLE(N))*BWDMAX +* +* Set the pointers PTSA, PTSX for referencing SA and SX in SWORK. +* + PTSA = 1 + PTSX = PTSA + N*N +* +* Convert B from double precision to single precision and store the +* result in SX. +* + CALL ZLAG2C(N,NRHS,B,LDB,SWORK(PTSX),N,INFO) +* + IF (INFO.NE.0) THEN + ITER = -2 + GO TO 40 + END IF +* +* Convert A from double precision to single precision and store the +* result in SA. +* + CALL ZLAG2C(N,N,A,LDA,SWORK(PTSA),N,INFO) +* + IF (INFO.NE.0) THEN + ITER = -2 + GO TO 40 + END IF +* +* Compute the LU factorization of SA. +* + CALL CGETRF(N,N,SWORK(PTSA),N,IPIV,INFO) +* + IF (INFO.NE.0) THEN + ITER = -3 + GO TO 40 + END IF +* +* Solve the system SA*SX = SB. +* + CALL CGETRS('No transpose',N,NRHS,SWORK(PTSA),N,IPIV, + + SWORK(PTSX),N,INFO) +* +* Convert SX back to double precision +* + CALL CLAG2Z(N,NRHS,SWORK(PTSX),N,X,LDX,INFO) +* +* Compute R = B - AX (R is WORK). +* + CALL ZLACPY('All',N,NRHS,B,LDB,WORK,N) +* + CALL ZGEMM('No Transpose','No Transpose',N,NRHS,N,NEGONE,A,LDA,X, + + LDX,ONE,WORK,N) +* +* Check whether the NRHS normwised backward errors satisfy the +* stopping criterion. If yes, set ITER=0 and return. +* + DO I = 1,NRHS + XNRM = CABS1(X(IZAMAX(N,X(1,I),1),I)) + RNRM = CABS1(WORK(IZAMAX(N,WORK(1,I),1),I)) + IF (RNRM.GT.XNRM*CTE) GOTO 10 + END DO +* +* If we are here, the NRHS normwised backward errors satisfy the +* stopping criterion. We are good to exit. +* + ITER = 0 + RETURN +* + 10 CONTINUE +* + DO 30 IITER = 1,ITERMAX +* +* Convert R (in WORK) from double precision to single precision +* and store the result in SX. +* + CALL ZLAG2C(N,NRHS,WORK,N,SWORK(PTSX),N,INFO) +* + IF (INFO.NE.0) THEN + ITER = -2 + GO TO 40 + END IF +* +* Solve the system SA*SX = SR. +* + CALL CGETRS('No transpose',N,NRHS,SWORK(PTSA),N,IPIV, + + SWORK(PTSX),N,INFO) +* +* Convert SX back to double precision and update the current +* iterate. +* + CALL CLAG2Z(N,NRHS,SWORK(PTSX),N,WORK,N,INFO) +* + CALL ZAXPY(N*NRHS,ONE,WORK,1,X,1) +* +* Compute R = B - AX (R is WORK). +* + CALL ZLACPY('All',N,NRHS,B,LDB,WORK,N) +* + CALL ZGEMM('No Transpose','No Transpose',N,NRHS,N,NEGONE,A, + + LDA,X,LDX,ONE,WORK,N) +* +* Check whether the NRHS normwised backward errors satisfy the +* stopping criterion. If yes, set ITER=IITER>0 and return. +* + DO I = 1,NRHS + XNRM = CABS1(X(IZAMAX(N,X(1,I),1),I)) + RNRM = CABS1(WORK(IZAMAX(N,WORK(1,I),1),I)) + IF (RNRM.GT.XNRM*CTE) GOTO 20 + END DO +* +* If we are here, the NRHS normwised backward errors satisfy the +* stopping criterion, we are good to exit. +* + ITER = IITER +* + RETURN +* + 20 CONTINUE +* + 30 CONTINUE +* +* If we are at this place of the code, this is because we have +* performed ITER=ITERMAX iterations and never satisified the stopping +* criterion, set up the ITER flag accordingly and follow up on double +* precision routine. +* + ITER = -ITERMAX - 1 +* + 40 CONTINUE +* +* Single-precision iterative refinement failed to converge to a +* satisfactory solution, so we resort to double precision. +* + CALL ZGETRF(N,N,A,LDA,IPIV,INFO) +* + CALL ZLACPY('All',N,NRHS,B,LDB,X,LDX) +* + IF (INFO.EQ.0) THEN + CALL ZGETRS('No transpose',N,NRHS,A,LDA,IPIV,X,LDX,INFO) + END IF +* + RETURN +* +* End of ZCGESV. +* + END |