LAPACK 3.3.1
Linear Algebra PACKage

zsytrs2.f

Go to the documentation of this file.
00001       SUBROUTINE ZSYTRS2( UPLO, N, NRHS, A, LDA, IPIV, B, LDB, 
00002      $                    WORK, INFO )
00003 *
00004 *  -- LAPACK PROTOTYPE routine (version 3.3.1) --
00005 *
00006 *  -- Written by Julie Langou of the Univ. of TN    --
00007 *  -- April 2011                                                      --
00008 *
00009 *  -- LAPACK is a software package provided by Univ. of Tennessee,    --
00010 *  -- Univ. of California Berkeley, Univ. of Colorado Denver and NAG Ltd..--
00011 *
00012 *     .. Scalar Arguments ..
00013       CHARACTER          UPLO
00014       INTEGER            INFO, LDA, LDB, N, NRHS
00015 *     ..
00016 *     .. Array Arguments ..
00017       INTEGER            IPIV( * )
00018       DOUBLE COMPLEX   A( LDA, * ), B( LDB, * ), WORK( * )
00019 *     ..
00020 *
00021 *  Purpose
00022 *  =======
00023 *
00024 *  ZSYTRS2 solves a system of linear equations A*X = B with a real
00025 *  symmetric matrix A using the factorization A = U*D*U**T or
00026 *  A = L*D*L**T computed by ZSYTRF and converted by ZSYCONV.
00027 *
00028 *  Arguments
00029 *  =========
00030 *
00031 *  UPLO    (input) CHARACTER*1
00032 *          Specifies whether the details of the factorization are stored
00033 *          as an upper or lower triangular matrix.
00034 *          = 'U':  Upper triangular, form is A = U*D*U**T;
00035 *          = 'L':  Lower triangular, form is A = L*D*L**T.
00036 *
00037 *  N       (input) INTEGER
00038 *          The order of the matrix A.  N >= 0.
00039 *
00040 *  NRHS    (input) INTEGER
00041 *          The number of right hand sides, i.e., the number of columns
00042 *          of the matrix B.  NRHS >= 0.
00043 *
00044 *  A       (input) DOUBLE COMPLEX array, dimension (LDA,N)
00045 *          The block diagonal matrix D and the multipliers used to
00046 *          obtain the factor U or L as computed by ZSYTRF.
00047 *
00048 *  LDA     (input) INTEGER
00049 *          The leading dimension of the array A.  LDA >= max(1,N).
00050 *
00051 *  IPIV    (input) INTEGER array, dimension (N)
00052 *          Details of the interchanges and the block structure of D
00053 *          as determined by ZSYTRF.
00054 *
00055 *  B       (input/output) DOUBLE COMPLEX array, dimension (LDB,NRHS)
00056 *          On entry, the right hand side matrix B.
00057 *          On exit, the solution matrix X.
00058 *
00059 *  LDB     (input) INTEGER
00060 *          The leading dimension of the array B.  LDB >= max(1,N).
00061 *
00062 *  WORK    (workspace) REAL array, dimension (N)
00063 *
00064 *  INFO    (output) INTEGER
00065 *          = 0:  successful exit
00066 *          < 0:  if INFO = -i, the i-th argument had an illegal value
00067 *
00068 *  =====================================================================
00069 *
00070 *     .. Parameters ..
00071       DOUBLE COMPLEX     ONE
00072       PARAMETER          ( ONE = (1.0D+0,0.0D+0) )
00073 *     ..
00074 *     .. Local Scalars ..
00075       LOGICAL            UPPER
00076       INTEGER            I, IINFO, J, K, KP
00077       DOUBLE COMPLEX     AK, AKM1, AKM1K, BK, BKM1, DENOM
00078 *     ..
00079 *     .. External Functions ..
00080       LOGICAL            LSAME
00081       EXTERNAL           LSAME
00082 *     ..
00083 *     .. External Subroutines ..
00084       EXTERNAL           ZSCAL, ZSYCONV, ZSWAP, ZTRSM, XERBLA
00085 *     ..
00086 *     .. Intrinsic Functions ..
00087       INTRINSIC          MAX
00088 *     ..
00089 *     .. Executable Statements ..
00090 *
00091       INFO = 0
00092       UPPER = LSAME( UPLO, 'U' )
00093       IF( .NOT.UPPER .AND. .NOT.LSAME( UPLO, 'L' ) ) THEN
00094          INFO = -1
00095       ELSE IF( N.LT.0 ) THEN
00096          INFO = -2
00097       ELSE IF( NRHS.LT.0 ) THEN
00098          INFO = -3
00099       ELSE IF( LDA.LT.MAX( 1, N ) ) THEN
00100          INFO = -5
00101       ELSE IF( LDB.LT.MAX( 1, N ) ) THEN
00102          INFO = -8
00103       END IF
00104       IF( INFO.NE.0 ) THEN
00105          CALL XERBLA( 'ZSYTRS2', -INFO )
00106          RETURN
00107       END IF
00108 *
00109 *     Quick return if possible
00110 *
00111       IF( N.EQ.0 .OR. NRHS.EQ.0 )
00112      $   RETURN
00113 *
00114 *     Convert A
00115 *
00116       CALL ZSYCONV( UPLO, 'C', N, A, LDA, IPIV, WORK, IINFO )
00117 *
00118       IF( UPPER ) THEN
00119 *
00120 *        Solve A*X = B, where A = U*D*U**T.
00121 *
00122 *       P**T * B  
00123         K=N
00124         DO WHILE ( K .GE. 1 )
00125          IF( IPIV( K ).GT.0 ) THEN
00126 *           1 x 1 diagonal block
00127 *           Interchange rows K and IPIV(K).
00128             KP = IPIV( K )
00129             IF( KP.NE.K )
00130      $         CALL ZSWAP( NRHS, B( K, 1 ), LDB, B( KP, 1 ), LDB )
00131             K=K-1
00132          ELSE
00133 *           2 x 2 diagonal block
00134 *           Interchange rows K-1 and -IPIV(K).
00135             KP = -IPIV( K )
00136             IF( KP.EQ.-IPIV( K-1 ) )
00137      $         CALL ZSWAP( NRHS, B( K-1, 1 ), LDB, B( KP, 1 ), LDB )
00138             K=K-2
00139          END IF
00140         END DO
00141 *
00142 *  Compute (U \P**T * B) -> B    [ (U \P**T * B) ]
00143 *
00144         CALL ZTRSM('L','U','N','U',N,NRHS,ONE,A,LDA,B,LDB)
00145 *
00146 *  Compute D \ B -> B   [ D \ (U \P**T * B) ]
00147 *       
00148          I=N
00149          DO WHILE ( I .GE. 1 )
00150             IF( IPIV(I) .GT. 0 ) THEN
00151               CALL ZSCAL( NRHS, ONE / A( I, I ), B( I, 1 ), LDB )
00152             ELSEIF ( I .GT. 1) THEN
00153                IF ( IPIV(I-1) .EQ. IPIV(I) ) THEN
00154                   AKM1K = WORK(I)
00155                   AKM1 = A( I-1, I-1 ) / AKM1K
00156                   AK = A( I, I ) / AKM1K
00157                   DENOM = AKM1*AK - ONE
00158                   DO 15 J = 1, NRHS
00159                      BKM1 = B( I-1, J ) / AKM1K
00160                      BK = B( I, J ) / AKM1K
00161                      B( I-1, J ) = ( AK*BKM1-BK ) / DENOM
00162                      B( I, J ) = ( AKM1*BK-BKM1 ) / DENOM
00163  15              CONTINUE
00164                I = I - 1
00165                ENDIF
00166             ENDIF
00167             I = I - 1
00168          END DO
00169 *
00170 *      Compute (U**T \ B) -> B   [ U**T \ (D \ (U \P**T * B) ) ]
00171 *
00172          CALL ZTRSM('L','U','T','U',N,NRHS,ONE,A,LDA,B,LDB)
00173 *
00174 *       P * B  [ P * (U**T \ (D \ (U \P**T * B) )) ]
00175 *
00176         K=1
00177         DO WHILE ( K .LE. N )
00178          IF( IPIV( K ).GT.0 ) THEN
00179 *           1 x 1 diagonal block
00180 *           Interchange rows K and IPIV(K).
00181             KP = IPIV( K )
00182             IF( KP.NE.K )
00183      $         CALL ZSWAP( NRHS, B( K, 1 ), LDB, B( KP, 1 ), LDB )
00184             K=K+1
00185          ELSE
00186 *           2 x 2 diagonal block
00187 *           Interchange rows K-1 and -IPIV(K).
00188             KP = -IPIV( K )
00189             IF( K .LT. N .AND. KP.EQ.-IPIV( K+1 ) )
00190      $         CALL ZSWAP( NRHS, B( K, 1 ), LDB, B( KP, 1 ), LDB )
00191             K=K+2
00192          ENDIF
00193         END DO
00194 *
00195       ELSE
00196 *
00197 *        Solve A*X = B, where A = L*D*L**T.
00198 *
00199 *       P**T * B  
00200         K=1
00201         DO WHILE ( K .LE. N )
00202          IF( IPIV( K ).GT.0 ) THEN
00203 *           1 x 1 diagonal block
00204 *           Interchange rows K and IPIV(K).
00205             KP = IPIV( K )
00206             IF( KP.NE.K )
00207      $         CALL ZSWAP( NRHS, B( K, 1 ), LDB, B( KP, 1 ), LDB )
00208             K=K+1
00209          ELSE
00210 *           2 x 2 diagonal block
00211 *           Interchange rows K and -IPIV(K+1).
00212             KP = -IPIV( K+1 )
00213             IF( KP.EQ.-IPIV( K ) )
00214      $         CALL ZSWAP( NRHS, B( K+1, 1 ), LDB, B( KP, 1 ), LDB )
00215             K=K+2
00216          ENDIF
00217         END DO
00218 *
00219 *  Compute (L \P**T * B) -> B    [ (L \P**T * B) ]
00220 *
00221         CALL ZTRSM('L','L','N','U',N,NRHS,ONE,A,LDA,B,LDB)
00222 *
00223 *  Compute D \ B -> B   [ D \ (L \P**T * B) ]
00224 *       
00225          I=1
00226          DO WHILE ( I .LE. N )
00227             IF( IPIV(I) .GT. 0 ) THEN
00228               CALL ZSCAL( NRHS, ONE / A( I, I ), B( I, 1 ), LDB )
00229             ELSE
00230                   AKM1K = WORK(I)
00231                   AKM1 = A( I, I ) / AKM1K
00232                   AK = A( I+1, I+1 ) / AKM1K
00233                   DENOM = AKM1*AK - ONE
00234                   DO 25 J = 1, NRHS
00235                      BKM1 = B( I, J ) / AKM1K
00236                      BK = B( I+1, J ) / AKM1K
00237                      B( I, J ) = ( AK*BKM1-BK ) / DENOM
00238                      B( I+1, J ) = ( AKM1*BK-BKM1 ) / DENOM
00239  25              CONTINUE
00240                   I = I + 1
00241             ENDIF
00242             I = I + 1
00243          END DO
00244 *
00245 *  Compute (L**T \ B) -> B   [ L**T \ (D \ (L \P**T * B) ) ]
00246 * 
00247         CALL ZTRSM('L','L','T','U',N,NRHS,ONE,A,LDA,B,LDB)
00248 *
00249 *       P * B  [ P * (L**T \ (D \ (L \P**T * B) )) ]
00250 *
00251         K=N
00252         DO WHILE ( K .GE. 1 )
00253          IF( IPIV( K ).GT.0 ) THEN
00254 *           1 x 1 diagonal block
00255 *           Interchange rows K and IPIV(K).
00256             KP = IPIV( K )
00257             IF( KP.NE.K )
00258      $         CALL ZSWAP( NRHS, B( K, 1 ), LDB, B( KP, 1 ), LDB )
00259             K=K-1
00260          ELSE
00261 *           2 x 2 diagonal block
00262 *           Interchange rows K-1 and -IPIV(K).
00263             KP = -IPIV( K )
00264             IF( K.GT.1 .AND. KP.EQ.-IPIV( K-1 ) )
00265      $         CALL ZSWAP( NRHS, B( K, 1 ), LDB, B( KP, 1 ), LDB )
00266             K=K-2
00267          ENDIF
00268         END DO
00269 *
00270       END IF
00271 *
00272 *     Revert A
00273 *
00274       CALL ZSYCONV( UPLO, 'R', N, A, LDA, IPIV, WORK, IINFO )
00275 *
00276       RETURN
00277 *
00278 *     End of ZSYTRS2
00279 *
00280       END
 All Files Functions