158
  159
  160
  161
  162
  163
  164      CHARACTER          UPLO
  165      INTEGER            INFO, LDA, N, NB
  166
  167
  168      INTEGER            IPIV( * )
  169      COMPLEX            A( LDA, * ), E( * ), WORK( N+NB+1, * )
  170
  171
  172
  173
  174
  175      REAL               ONE
  176      parameter( one = 1.0e+0 )
  177      COMPLEX            CONE, CZERO
  178      parameter( cone = ( 1.0e+0, 0.0e+0 ),
  179     $                     czero = ( 0.0e+0, 0.0e+0 ) )
  180
  181
  182      LOGICAL            UPPER
  183      INTEGER            CUT, I, ICOUNT, INVD, IP, K, NNB, J, U11
  184      REAL               AK, AKP1, T
  185      COMPLEX            AKKP1, D, U01_I_J, U01_IP1_J, U11_I_J,
  186     $                   U11_IP1_J
  187
  188
  189      LOGICAL            LSAME
  191
  192
  195
  196
  197      INTRINSIC          abs, conjg, max, real
  198
  199
  200
  201
  202
  203      info = 0
  204      upper = 
lsame( uplo, 
'U' )
 
  205      IF( .NOT.upper .AND. .NOT.
lsame( uplo, 
'L' ) ) 
THEN 
  206         info = -1
  207      ELSE IF( n.LT.0 ) THEN
  208         info = -2
  209      ELSE IF( lda.LT.max( 1, n ) ) THEN
  210         info = -4
  211      END IF
  212
  213
  214
  215      IF( info.NE.0 ) THEN
  216         CALL xerbla( 
'CHETRI_3X', -info )
 
  217         RETURN
  218      END IF
  219      IF( n.EQ.0 )
  220     $   RETURN
  221
  222
  223
  224      DO k = 1, n
  225         work( k, 1 ) = e( k )
  226      END DO
  227
  228
  229
  230      IF( upper ) THEN
  231
  232
  233
  234         DO info = n, 1, -1
  235            IF( ipiv( info ).GT.0 .AND. a( info, info ).EQ.czero )
  236     $         RETURN
  237         END DO
  238      ELSE
  239
  240
  241
  242         DO info = 1, n
  243            IF( ipiv( info ).GT.0 .AND. a( info, info ).EQ.czero )
  244     $         RETURN
  245         END DO
  246      END IF
  247
  248      info = 0
  249
  250
  251
  252
  253
  254
  255
  256      u11 = n
  257
  258
  259
  260
  261      invd = nb + 2
  262 
  263      IF( upper ) THEN
  264
  265
  266
  267
  268
  269         CALL ctrtri( uplo, 
'U', n, a, lda, info )
 
  270
  271
  272
  273         k = 1
  274         DO WHILE( k.LE.n )
  275            IF( ipiv( k ).GT.0 ) THEN
  276
  277               work( k, invd ) = one / real( a( k, k ) )
  278               work( k, invd+1 ) = czero
  279            ELSE
  280
  281               t = abs( work( k+1, 1 ) )
  282               ak = real( a( k, k ) ) / t
  283               akp1 = real( a( k+1, k+1 ) ) / t
  284               akkp1 = work( k+1, 1 )  / t
  285               d = t*( ak*akp1-cone )
  286               work( k, invd ) = akp1 / d
  287               work( k+1, invd+1 ) = ak / d
  288               work( k, invd+1 ) = -akkp1 / d
  289               work( k+1, invd ) = conjg( work( k, invd+1 ) )
  290               k = k + 1
  291            END IF
  292            k = k + 1
  293         END DO
  294
  295
  296
  297
  298
  299         cut = n
  300         DO WHILE( cut.GT.0 )
  301            nnb = nb
  302            IF( cut.LE.nnb ) THEN
  303               nnb = cut
  304            ELSE
  305               icount = 0
  306
  307               DO i = cut+1-nnb, cut
  308                  IF( ipiv( i ).LT.0 ) icount = icount + 1
  309               END DO
  310
  311               IF( mod( icount, 2 ).EQ.1 ) nnb = nnb + 1
  312            END IF
  313 
  314            cut = cut - nnb
  315
  316
  317
  318            DO i = 1, cut
  319               DO j = 1, nnb
  320                  work( i, j ) = a( i, cut+j )
  321               END DO
  322            END DO
  323
  324
  325
  326            DO i = 1, nnb
  327               work( u11+i, i ) = cone
  328               DO j = 1, i-1
  329                  work( u11+i, j ) = czero
  330                END DO
  331                DO j = i+1, nnb
  332                   work( u11+i, j ) = a( cut+i, cut+j )
  333                END DO
  334            END DO
  335
  336
  337
  338            i = 1
  339            DO WHILE( i.LE.cut )
  340               IF( ipiv( i ).GT.0 ) THEN
  341                  DO j = 1, nnb
  342                     work( i, j ) = work( i, invd ) * work( i, j )
  343                  END DO
  344               ELSE
  345                  DO j = 1, nnb
  346                     u01_i_j = work( i, j )
  347                     u01_ip1_j = work( i+1, j )
  348                     work( i, j ) = work( i, invd ) * u01_i_j
  349     $                            + work( i, invd+1 ) * u01_ip1_j
  350                     work( i+1, j ) = work( i+1, invd ) * u01_i_j
  351     $                              + work( i+1, invd+1 ) * u01_ip1_j
  352                  END DO
  353                  i = i + 1
  354               END IF
  355               i = i + 1
  356            END DO
  357
  358
  359
  360            i = 1
  361            DO WHILE ( i.LE.nnb )
  362               IF( ipiv( cut+i ).GT.0 ) THEN
  363                  DO j = i, nnb
  364                     work( u11+i, j ) = work(cut+i,invd) * work(u11+i,j)
  365                  END DO
  366               ELSE
  367                  DO j = i, nnb
  368                     u11_i_j = work(u11+i,j)
  369                     u11_ip1_j = work(u11+i+1,j)
  370                     work( u11+i, j ) = work(cut+i,invd) * work(u11+i,j)
  371     $                            + work(cut+i,invd+1) * work(u11+i+1,j)
  372                     work( u11+i+1, j ) = work(cut+i+1,invd) * u11_i_j
  373     $                               + work(cut+i+1,invd+1) * u11_ip1_j
  374                  END DO
  375                  i = i + 1
  376               END IF
  377               i = i + 1
  378            END DO
  379
  380
  381
  382            CALL ctrmm( 
'L', 
'U', 
'C', 
'U', nnb, nnb,
 
  383     $                 cone, a( cut+1, cut+1 ), lda, work( u11+1, 1 ),
  384     $                 n+nb+1 )
  385
  386            DO i = 1, nnb
  387               DO j = i, nnb
  388                  a( cut+i, cut+j ) = work( u11+i, j )
  389               END DO
  390            END DO
  391
  392
  393
  394            CALL cgemm( 
'C', 
'N', nnb, nnb, cut, cone, a( 1, cut+1 ),
 
  395     $                  lda, work, n+nb+1, czero, work(u11+1,1),
  396     $                  n+nb+1 )
  397 
  398
  399
  400
  401            DO i = 1, nnb
  402               DO j = i, nnb
  403                  a( cut+i, cut+j ) = a( cut+i, cut+j ) + work(u11+i,j)
  404               END DO
  405            END DO
  406
  407
  408
  409            CALL ctrmm( 
'L', uplo, 
'C', 
'U', cut, nnb,
 
  410     $                  cone, a, lda, work, n+nb+1 )
  411 
  412
  413
  414
  415            DO i = 1, cut
  416               DO j = 1, nnb
  417                  a( i, cut+j ) = work( i, j )
  418               END DO
  419            END DO
  420
  421
  422
  423         END DO
  424
  425
  426
  427
  428
  429
  430
  431
  432
  433
  434
  435
  436         DO i = 1, n
  437             ip = abs( ipiv( i ) )
  438             IF( ip.NE.i ) THEN
  439                IF (i .LT. ip) 
CALL cheswapr( uplo, n, a, lda, i ,
 
  440     $               ip )
  441                IF (i .GT. ip) 
CALL cheswapr( uplo, n, a, lda, ip ,
 
  442     $               i )
  443             END IF
  444         END DO
  445
  446      ELSE
  447
  448
  449
  450
  451
  452         CALL ctrtri( uplo, 
'U', n, a, lda, info )
 
  453
  454
  455
  456         k = n
  457         DO WHILE ( k .GE. 1 )
  458            IF( ipiv( k ).GT.0 ) THEN
  459
  460               work( k, invd ) = one / real( a( k, k ) )
  461               work( k, invd+1 ) = czero
  462            ELSE
  463
  464               t = abs( work( k-1, 1 ) )
  465               ak = real( a( k-1, k-1 ) ) / t
  466               akp1 = real( a( k, k ) ) / t
  467               akkp1 = work( k-1, 1 ) / t
  468               d = t*( ak*akp1-cone )
  469               work( k-1, invd ) = akp1 / d
  470               work( k, invd ) = ak / d
  471               work( k, invd+1 ) = -akkp1 / d
  472               work( k-1, invd+1 ) = conjg( work( k, invd+1 ) )
  473               k = k - 1
  474            END IF
  475            k = k - 1
  476         END DO
  477
  478
  479
  480
  481
  482         cut = 0
  483         DO WHILE( cut.LT.n )
  484            nnb = nb
  485            IF( (cut + nnb).GT.n ) THEN
  486               nnb = n - cut
  487            ELSE
  488               icount = 0
  489
  490               DO i = cut + 1, cut+nnb
  491                  IF ( ipiv( i ).LT.0 ) icount = icount + 1
  492               END DO
  493
  494               IF( mod( icount, 2 ).EQ.1 ) nnb = nnb + 1
  495            END IF
  496
  497
  498
  499            DO i = 1, n-cut-nnb
  500               DO j = 1, nnb
  501                 work( i, j ) = a( cut+nnb+i, cut+j )
  502               END DO
  503            END DO
  504
  505
  506
  507            DO i = 1, nnb
  508               work( u11+i, i) = cone
  509               DO j = i+1, nnb
  510                  work( u11+i, j ) = czero
  511               END DO
  512               DO j = 1, i-1
  513                  work( u11+i, j ) = a( cut+i, cut+j )
  514               END DO
  515            END DO
  516
  517
  518
  519            i = n-cut-nnb
  520            DO WHILE( i.GE.1 )
  521               IF( ipiv( cut+nnb+i ).GT.0 ) THEN
  522                  DO j = 1, nnb
  523                     work( i, j ) = work( cut+nnb+i, invd) * work( i, j)
  524                  END DO
  525               ELSE
  526                  DO j = 1, nnb
  527                     u01_i_j = work(i,j)
  528                     u01_ip1_j = work(i-1,j)
  529                     work(i,j)=work(cut+nnb+i,invd)*u01_i_j+
  530     $                        work(cut+nnb+i,invd+1)*u01_ip1_j
  531                     work(i-1,j)=work(cut+nnb+i-1,invd+1)*u01_i_j+
  532     $                        work(cut+nnb+i-1,invd)*u01_ip1_j
  533                  END DO
  534                  i = i - 1
  535               END IF
  536               i = i - 1
  537            END DO
  538
  539
  540
  541            i = nnb
  542            DO WHILE( i.GE.1 )
  543               IF( ipiv( cut+i ).GT.0 ) THEN
  544                  DO j = 1, nnb
  545                     work( u11+i, j ) = work( cut+i, invd)*work(u11+i,j)
  546                  END DO
  547 
  548               ELSE
  549                  DO j = 1, nnb
  550                     u11_i_j = work( u11+i, j )
  551                     u11_ip1_j = work( u11+i-1, j )
  552                     work( u11+i, j ) = work(cut+i,invd) * work(u11+i,j)
  553     $                                + work(cut+i,invd+1) * u11_ip1_j
  554                     work( u11+i-1, j ) = work(cut+i-1,invd+1) * u11_i_j
  555     $                                  + work(cut+i-1,invd) * u11_ip1_j
  556                  END DO
  557                  i = i - 1
  558               END IF
  559               i = i - 1
  560            END DO
  561
  562
  563
  564            CALL ctrmm( 
'L', uplo, 
'C', 
'U', nnb, nnb, cone,
 
  565     $                   a( cut+1, cut+1 ), lda, work( u11+1, 1 ),
  566     $                   n+nb+1 )
  567 
  568
  569            DO i = 1, nnb
  570               DO j = 1, i
  571                  a( cut+i, cut+j ) = work( u11+i, j )
  572               END DO
  573            END DO
  574
  575            IF( (cut+nnb).LT.n ) THEN
  576
  577
  578
  579               CALL cgemm( 
'C', 
'N', nnb, nnb, n-nnb-cut, cone,
 
  580     $                     a( cut+nnb+1, cut+1 ), lda, work, n+nb+1,
  581     $                     czero, work( u11+1, 1 ), n+nb+1 )
  582 
  583
  584
  585
  586               DO i = 1, nnb
  587                  DO j = 1, i
  588                     a( cut+i, cut+j ) = a( cut+i, cut+j )+work(u11+i,j)
  589                  END DO
  590               END DO
  591
  592
  593
  594               CALL ctrmm( 
'L', uplo, 
'C', 
'U', n-nnb-cut, nnb, cone,
 
  595     $                     a( cut+nnb+1, cut+nnb+1 ), lda, work,
  596     $                     n+nb+1 )
  597
  598
  599
  600               DO i = 1, n-cut-nnb
  601                  DO j = 1, nnb
  602                     a( cut+nnb+i, cut+j ) = work( i, j )
  603                  END DO
  604               END DO
  605
  606            ELSE
  607
  608
  609
  610               DO i = 1, nnb
  611                  DO j = 1, i
  612                     a( cut+i, cut+j ) = work( u11+i, j )
  613                  END DO
  614               END DO
  615            END IF
  616
  617
  618
  619            cut = cut + nnb
  620
  621         END DO
  622
  623
  624
  625
  626
  627
  628
  629
  630
  631
  632
  633
  634         DO i = n, 1, -1
  635             ip = abs( ipiv( i ) )
  636             IF( ip.NE.i ) THEN
  637                IF (i .LT. ip) 
CALL cheswapr( uplo, n, a, lda, i ,
 
  638     $               ip )
  639                IF (i .GT. ip) 
CALL cheswapr( uplo, n, a, lda, ip ,
 
  640     $               i )
  641             END IF
  642         END DO
  643
  644      END IF
  645
  646      RETURN
  647
  648
  649
subroutine xerbla(srname, info)
subroutine cgemm(transa, transb, m, n, k, alpha, a, lda, b, ldb, beta, c, ldc)
CGEMM
subroutine cheswapr(uplo, n, a, lda, i1, i2)
CHESWAPR applies an elementary permutation on the rows and columns of a Hermitian matrix.
logical function lsame(ca, cb)
LSAME
subroutine ctrmm(side, uplo, transa, diag, m, n, alpha, a, lda, b, ldb)
CTRMM
subroutine ctrtri(uplo, diag, n, a, lda, info)
CTRTRI