00001 SUBROUTINE CHETRI2X( UPLO, N, A, LDA, IPIV, WORK, NB, INFO )
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011 CHARACTER UPLO
00012 INTEGER INFO, LDA, N, NB
00013
00014
00015 INTEGER IPIV( * )
00016 COMPLEX A( LDA, * ), WORK( N+NB+1,* )
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039
00040
00041
00042
00043
00044
00045
00046
00047
00048
00049
00050
00051
00052
00053
00054
00055
00056
00057
00058
00059
00060
00061
00062
00063
00064
00065
00066
00067
00068
00069
00070 REAL ONE
00071 COMPLEX CONE, ZERO
00072 PARAMETER ( ONE = 1.0E+0,
00073 $ CONE = ( 1.0E+0, 0.0E+0 ),
00074 $ ZERO = ( 0.0E+0, 0.0E+0 ) )
00075
00076
00077 LOGICAL UPPER
00078 INTEGER I, IINFO, IP, K, CUT, NNB
00079 INTEGER COUNT
00080 INTEGER J, U11, INVD
00081
00082 COMPLEX AK, AKKP1, AKP1, D, T
00083 COMPLEX U01_I_J, U01_IP1_J
00084 COMPLEX U11_I_J, U11_IP1_J
00085
00086
00087 LOGICAL LSAME
00088 EXTERNAL LSAME
00089
00090
00091 EXTERNAL CSYCONV, XERBLA, CTRTRI
00092 EXTERNAL CGEMM, CTRMM, CSYSWAPR
00093
00094
00095 INTRINSIC MAX
00096
00097
00098
00099
00100
00101 INFO = 0
00102 UPPER = LSAME( UPLO, 'U' )
00103 IF( .NOT.UPPER .AND. .NOT.LSAME( UPLO, 'L' ) ) THEN
00104 INFO = -1
00105 ELSE IF( N.LT.0 ) THEN
00106 INFO = -2
00107 ELSE IF( LDA.LT.MAX( 1, N ) ) THEN
00108 INFO = -4
00109 END IF
00110
00111
00112
00113
00114 IF( INFO.NE.0 ) THEN
00115 CALL XERBLA( 'CHETRI2X', -INFO )
00116 RETURN
00117 END IF
00118 IF( N.EQ.0 )
00119 $ RETURN
00120
00121
00122
00123
00124 CALL CSYCONV( UPLO, 'C', N, A, LDA, IPIV, WORK, IINFO )
00125
00126
00127
00128 IF( UPPER ) THEN
00129
00130
00131
00132 DO INFO = N, 1, -1
00133 IF( IPIV( INFO ).GT.0 .AND. A( INFO, INFO ).EQ.ZERO )
00134 $ RETURN
00135 END DO
00136 ELSE
00137
00138
00139
00140 DO INFO = 1, N
00141 IF( IPIV( INFO ).GT.0 .AND. A( INFO, INFO ).EQ.ZERO )
00142 $ RETURN
00143 END DO
00144 END IF
00145 INFO = 0
00146
00147
00148
00149
00150
00151
00152 U11 = N
00153
00154
00155 INVD = NB+2
00156
00157 IF( UPPER ) THEN
00158
00159
00160
00161 CALL CTRTRI( UPLO, 'U', N, A, LDA, INFO )
00162
00163
00164
00165 K=1
00166 DO WHILE ( K .LE. N )
00167 IF( IPIV( K ).GT.0 ) THEN
00168
00169 WORK(K,INVD) = ONE / REAL ( A( K, K ) )
00170 WORK(K,INVD+1) = 0
00171 K=K+1
00172 ELSE
00173
00174 T = ABS ( WORK(K+1,1) )
00175 AK = REAL ( A( K, K ) ) / T
00176 AKP1 = REAL ( A( K+1, K+1 ) ) / T
00177 AKKP1 = WORK(K+1,1) / T
00178 D = T*( AK*AKP1-ONE )
00179 WORK(K,INVD) = AKP1 / D
00180 WORK(K+1,INVD+1) = AK / D
00181 WORK(K,INVD+1) = -AKKP1 / D
00182 WORK(K+1,INVD) = -AKKP1 / D
00183 K=K+2
00184 END IF
00185 END DO
00186
00187
00188
00189
00190
00191 CUT=N
00192 DO WHILE (CUT .GT. 0)
00193 NNB=NB
00194 IF (CUT .LE. NNB) THEN
00195 NNB=CUT
00196 ELSE
00197 COUNT = 0
00198
00199 DO I=CUT+1-NNB,CUT
00200 IF (IPIV(I) .LT. 0) COUNT=COUNT+1
00201 END DO
00202
00203 IF (MOD(COUNT,2) .EQ. 1) NNB=NNB+1
00204 END IF
00205
00206 CUT=CUT-NNB
00207
00208
00209
00210 DO I=1,CUT
00211 DO J=1,NNB
00212 WORK(I,J)=A(I,CUT+J)
00213 END DO
00214 END DO
00215
00216
00217
00218 DO I=1,NNB
00219 WORK(U11+I,I)=CONE
00220 DO J=1,I-1
00221 WORK(U11+I,J)=ZERO
00222 END DO
00223 DO J=I+1,NNB
00224 WORK(U11+I,J)=A(CUT+I,CUT+J)
00225 END DO
00226 END DO
00227
00228
00229
00230 I=1
00231 DO WHILE (I .LE. CUT)
00232 IF (IPIV(I) > 0) THEN
00233 DO J=1,NNB
00234 WORK(I,J)=WORK(I,INVD)*WORK(I,J)
00235 END DO
00236 I=I+1
00237 ELSE
00238 DO J=1,NNB
00239 U01_I_J = WORK(I,J)
00240 U01_IP1_J = WORK(I+1,J)
00241 WORK(I,J)=WORK(I,INVD)*U01_I_J+
00242 $ WORK(I,INVD+1)*U01_IP1_J
00243 WORK(I+1,J)=WORK(I+1,INVD)*U01_I_J+
00244 $ WORK(I+1,INVD+1)*U01_IP1_J
00245 END DO
00246 I=I+2
00247 END IF
00248 END DO
00249
00250
00251
00252 I=1
00253 DO WHILE (I .LE. NNB)
00254 IF (IPIV(CUT+I) > 0) THEN
00255 DO J=I,NNB
00256 WORK(U11+I,J)=WORK(CUT+I,INVD)*WORK(U11+I,J)
00257 END DO
00258 I=I+1
00259 ELSE
00260 DO J=I,NNB
00261 U11_I_J = WORK(U11+I,J)
00262 U11_IP1_J = WORK(U11+I+1,J)
00263 WORK(U11+I,J)=WORK(CUT+I,INVD)*WORK(U11+I,J) +
00264 $ WORK(CUT+I,INVD+1)*WORK(U11+I+1,J)
00265 WORK(U11+I+1,J)=WORK(CUT+I+1,INVD)*U11_I_J+
00266 $ WORK(CUT+I+1,INVD+1)*U11_IP1_J
00267 END DO
00268 I=I+2
00269 END IF
00270 END DO
00271
00272
00273
00274 CALL CTRMM('L','U','C','U',NNB, NNB,
00275 $ CONE,A(CUT+1,CUT+1),LDA,WORK(U11+1,1),N+NB+1)
00276
00277
00278
00279 CALL CGEMM('C','N',NNB,NNB,CUT,CONE,A(1,CUT+1),LDA,
00280 $ WORK,N+NB+1, ZERO, A(CUT+1,CUT+1), LDA)
00281
00282
00283
00284 DO I=1,NNB
00285 DO J=I,NNB
00286 A(CUT+I,CUT+J)=A(CUT+I,CUT+J)+WORK(U11+I,J)
00287 END DO
00288 END DO
00289
00290
00291
00292 CALL CTRMM('L',UPLO,'C','U',CUT, NNB,
00293 $ CONE,A,LDA,WORK,N+NB+1)
00294
00295
00296
00297
00298 DO I=1,CUT
00299 DO J=1,NNB
00300 A(I,CUT+J)=WORK(I,J)
00301 END DO
00302 END DO
00303
00304 END DO
00305
00306
00307
00308 I=1
00309 DO WHILE ( I .LE. N )
00310 IF( IPIV(I) .GT. 0 ) THEN
00311 IP=IPIV(I)
00312 IF (I .LT. IP) CALL CSYSWAPR( UPLO, N, A, I ,IP )
00313 IF (I .GT. IP) CALL CSYSWAPR( UPLO, N, A, IP ,I )
00314 ELSE
00315 IP=-IPIV(I)
00316 I=I+1
00317 IF ( (I-1) .LT. IP)
00318 $ CALL CSYSWAPR( UPLO, N, A, I-1 ,IP )
00319 IF ( (I-1) .GT. IP)
00320 $ CALL CSYSWAPR( UPLO, N, A, IP ,I-1 )
00321 ENDIF
00322 I=I+1
00323 END DO
00324
00325 DO I=1,N
00326 DO J=I+1,N
00327 A(J,I)=A(I,J)
00328 END DO
00329 END DO
00330 ELSE
00331
00332
00333
00334
00335
00336 CALL CTRTRI( UPLO, 'U', N, A, LDA, INFO )
00337
00338
00339
00340 K=N
00341 DO WHILE ( K .GE. 1 )
00342 IF( IPIV( K ).GT.0 ) THEN
00343
00344 WORK(K,INVD) = ONE / REAL ( A( K, K ) )
00345 WORK(K,INVD+1) = 0
00346 K=K-1
00347 ELSE
00348
00349 T = ABS ( WORK(K-1,1) )
00350 AK = REAL ( A( K-1, K-1 ) ) / T
00351 AKP1 = REAL ( A( K, K ) ) / T
00352 AKKP1 = WORK(K-1,1) / T
00353 D = T*( AK*AKP1-ONE )
00354 WORK(K-1,INVD) = AKP1 / D
00355 WORK(K,INVD) = AK / D
00356 WORK(K,INVD+1) = -AKKP1 / D
00357 WORK(K-1,INVD+1) = -AKKP1 / D
00358 K=K-2
00359 END IF
00360 END DO
00361
00362
00363
00364
00365
00366 CUT=0
00367 DO WHILE (CUT .LT. N)
00368 NNB=NB
00369 IF (CUT + NNB .GE. N) THEN
00370 NNB=N-CUT
00371 ELSE
00372 COUNT = 0
00373
00374 DO I=CUT+1,CUT+NNB
00375 IF (IPIV(I) .LT. 0) COUNT=COUNT+1
00376 END DO
00377
00378 IF (MOD(COUNT,2) .EQ. 1) NNB=NNB+1
00379 END IF
00380
00381 DO I=1,N-CUT-NNB
00382 DO J=1,NNB
00383 WORK(I,J)=A(CUT+NNB+I,CUT+J)
00384 END DO
00385 END DO
00386
00387 DO I=1,NNB
00388 WORK(U11+I,I)=CONE
00389 DO J=I+1,NNB
00390 WORK(U11+I,J)=ZERO
00391 END DO
00392 DO J=1,I-1
00393 WORK(U11+I,J)=A(CUT+I,CUT+J)
00394 END DO
00395 END DO
00396
00397
00398
00399 I=N-CUT-NNB
00400 DO WHILE (I .GE. 1)
00401 IF (IPIV(CUT+NNB+I) > 0) THEN
00402 DO J=1,NNB
00403 WORK(I,J)=WORK(CUT+NNB+I,INVD)*WORK(I,J)
00404 END DO
00405 I=I-1
00406 ELSE
00407 DO J=1,NNB
00408 U01_I_J = WORK(I,J)
00409 U01_IP1_J = WORK(I-1,J)
00410 WORK(I,J)=WORK(CUT+NNB+I,INVD)*U01_I_J+
00411 $ WORK(CUT+NNB+I,INVD+1)*U01_IP1_J
00412 WORK(I-1,J)=WORK(CUT+NNB+I-1,INVD+1)*U01_I_J+
00413 $ WORK(CUT+NNB+I-1,INVD)*U01_IP1_J
00414 END DO
00415 I=I-2
00416 END IF
00417 END DO
00418
00419
00420
00421 I=NNB
00422 DO WHILE (I .GE. 1)
00423 IF (IPIV(CUT+I) > 0) THEN
00424 DO J=1,NNB
00425 WORK(U11+I,J)=WORK(CUT+I,INVD)*WORK(U11+I,J)
00426 END DO
00427 I=I-1
00428 ELSE
00429 DO J=1,NNB
00430 U11_I_J = WORK(U11+I,J)
00431 U11_IP1_J = WORK(U11+I-1,J)
00432 WORK(U11+I,J)=WORK(CUT+I,INVD)*WORK(U11+I,J) +
00433 $ WORK(CUT+I,INVD+1)*U11_IP1_J
00434 WORK(U11+I-1,J)=WORK(CUT+I-1,INVD+1)*U11_I_J+
00435 $ WORK(CUT+I-1,INVD)*U11_IP1_J
00436 END DO
00437 I=I-2
00438 END IF
00439 END DO
00440
00441
00442
00443 CALL CTRMM('L',UPLO,'C','U',NNB, NNB,
00444 $ CONE,A(CUT+1,CUT+1),LDA,WORK(U11+1,1),N+NB+1)
00445
00446
00447
00448 CALL CGEMM('C','N',NNB,NNB,N-NNB-CUT,CONE,A(CUT+NNB+1,CUT+1)
00449 $ ,LDA,WORK,N+NB+1, ZERO, A(CUT+1,CUT+1), LDA)
00450
00451
00452
00453
00454 DO I=1,NNB
00455 DO J=1,I
00456 A(CUT+I,CUT+J)=A(CUT+I,CUT+J)+WORK(U11+I,J)
00457 END DO
00458 END DO
00459
00460
00461
00462 CALL CTRMM('L',UPLO,'C','U', N-NNB-CUT, NNB,
00463 $ CONE,A(CUT+NNB+1,CUT+NNB+1),LDA,WORK,N+NB+1)
00464
00465
00466 DO I=1,N-CUT-NNB
00467 DO J=1,NNB
00468 A(CUT+NNB+I,CUT+J)=WORK(I,J)
00469 END DO
00470 END DO
00471
00472 CUT=CUT+NNB
00473 END DO
00474
00475
00476
00477 I=N
00478 DO WHILE ( I .GE. 1 )
00479 IF( IPIV(I) .GT. 0 ) THEN
00480 IP=IPIV(I)
00481 IF (I .LT. IP) CALL CSYSWAPR( UPLO, N, A, I ,IP )
00482 IF (I .GT. IP) CALL CSYSWAPR( UPLO, N, A, IP ,I )
00483 ELSE
00484 IP=-IPIV(I)
00485 IF ( I .LT. IP) CALL CSYSWAPR( UPLO, N, A, I ,IP )
00486 IF ( I .GT. IP) CALL CSYSWAPR( UPLO, N, A, IP ,I )
00487 I=I-1
00488 ENDIF
00489 I=I-1
00490 END DO
00491 END IF
00492
00493 RETURN
00494
00495
00496
00497 END
00498