added LAPACK routine (c,z)hetri_rook.f
authorigor175 <igor175@8a072113-8704-0410-8d35-dd094bca7971>
Mon, 22 Apr 2013 07:49:39 +0000 (07:49 +0000)
committerigor175 <igor175@8a072113-8704-0410-8d35-dd094bca7971>
Mon, 22 Apr 2013 07:49:39 +0000 (07:49 +0000)
SRC/chetri_rook.f [new file with mode: 0644]
SRC/zhetri_rook.f [new file with mode: 0644]

diff --git a/SRC/chetri_rook.f b/SRC/chetri_rook.f
new file mode 100644 (file)
index 0000000..394c2ed
--- /dev/null
@@ -0,0 +1,516 @@
+*> \brief \b CHETRI_ROOK computes the inverse of HE matrix using the factorization obtained with the bounded Bunch-Kaufman ("rook") diagonal pivoting method.
+*
+*  =========== DOCUMENTATION ===========
+*
+* Online html documentation available at
+*            http://www.netlib.org/lapack/explore-html/
+*
+*> \htmlonly
+*> Download CHETRI_ROOK + dependencies
+*> <a href="http://www.netlib.org/cgi-bin/netlibfiles.tgz?format=tgz&filename=/lapack/lapack_routine/chetri_rook.f">
+*> [TGZ]</a>
+*> <a href="http://www.netlib.org/cgi-bin/netlibfiles.zip?format=zip&filename=/lapack/lapack_routine/chetri_rook.f">
+*> [ZIP]</a>
+*> <a href="http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/chetri_rook.f">
+*> [TXT]</a>
+*> \endhtmlonly
+*
+*  Definition:
+*  ===========
+*
+*       SUBROUTINE CHETRI_ROOK( UPLO, N, A, LDA, IPIV, WORK, INFO )
+*
+*       .. Scalar Arguments ..
+*       CHARACTER          UPLO
+*       INTEGER            INFO, LDA, N
+*       ..
+*       .. Array Arguments ..
+*       INTEGER            IPIV( * )
+*       COMPLEX            A( LDA, * ), WORK( * )
+*       ..
+*
+*
+*> \par Purpose:
+*  =============
+*>
+*> \verbatim
+*>
+*> CHETRI_ROOK computes the inverse of a complex Hermitian indefinite matrix
+*> A using the factorization A = U*D*U**H or A = L*D*L**H computed by
+*> CHETRF_ROOK.
+*> \endverbatim
+*
+*  Arguments:
+*  ==========
+*
+*> \param[in] UPLO
+*> \verbatim
+*>          UPLO is CHARACTER*1
+*>          Specifies whether the details of the factorization are stored
+*>          as an upper or lower triangular matrix.
+*>          = 'U':  Upper triangular, form is A = U*D*U**H;
+*>          = 'L':  Lower triangular, form is A = L*D*L**H.
+*> \endverbatim
+*>
+*> \param[in] N
+*> \verbatim
+*>          N is INTEGER
+*>          The order of the matrix A.  N >= 0.
+*> \endverbatim
+*>
+*> \param[in,out] A
+*> \verbatim
+*>          A is COMPLEX array, dimension (LDA,N)
+*>          On entry, the block diagonal matrix D and the multipliers
+*>          used to obtain the factor U or L as computed by CHETRF_ROOK.
+*>
+*>          On exit, if INFO = 0, the (Hermitian) inverse of the original
+*>          matrix.  If UPLO = 'U', the upper triangular part of the
+*>          inverse is formed and the part of A below the diagonal is not
+*>          referenced; if UPLO = 'L' the lower triangular part of the
+*>          inverse is formed and the part of A above the diagonal is
+*>          not referenced.
+*> \endverbatim
+*>
+*> \param[in] LDA
+*> \verbatim
+*>          LDA is INTEGER
+*>          The leading dimension of the array A.  LDA >= max(1,N).
+*> \endverbatim
+*>
+*> \param[in] IPIV
+*> \verbatim
+*>          IPIV is INTEGER array, dimension (N)
+*>          Details of the interchanges and the block structure of D
+*>          as determined by CHETRF_ROOK.
+*> \endverbatim
+*>
+*> \param[out] WORK
+*> \verbatim
+*>          WORK is COMPLEX array, dimension (N)
+*> \endverbatim
+*>
+*> \param[out] INFO
+*> \verbatim
+*>          INFO is INTEGER
+*>          = 0: successful exit
+*>          < 0: if INFO = -i, the i-th argument had an illegal value
+*>          > 0: if INFO = i, D(i,i) = 0; the matrix is singular and its
+*>               inverse could not be computed.
+*> \endverbatim
+*
+*  Authors:
+*  ========
+*
+*> \author Univ. of Tennessee
+*> \author Univ. of California Berkeley
+*> \author Univ. of Colorado Denver
+*> \author NAG Ltd.
+*
+*> \date November 2011
+*
+*> \ingroup complexHEcomputational
+*
+*> \par Contributors:
+*  ==================
+*>
+*> \verbatim
+*>
+*>  November 2012,  Igor Kozachenko,
+*>                  Computer Science Division,
+*>                  University of California, Berkeley
+*>
+*>  September 2007, Sven Hammarling, Nicholas J. Higham, Craig Lucas,
+*>                  School of Mathematics,
+*>                  University of Manchester
+*> \endverbatim
+*
+*  =====================================================================
+      SUBROUTINE CHETRI_ROOK( UPLO, N, A, LDA, IPIV, WORK, INFO )
+*
+*  -- LAPACK computational routine (version 3.4.0) --
+*  -- LAPACK is a software package provided by Univ. of Tennessee,    --
+*  -- Univ. of California Berkeley, Univ. of Colorado Denver and NAG Ltd..--
+*     November 2011
+*
+*     .. Scalar Arguments ..
+      CHARACTER          UPLO
+      INTEGER            INFO, LDA, N
+*     ..
+*     .. Array Arguments ..
+      INTEGER            IPIV( * )
+      COMPLEX            A( LDA, * ), WORK( * )
+*     ..
+*
+*  =====================================================================
+*
+*     .. Parameters ..
+      REAL               ONE
+      COMPLEX            CONE, CZERO
+      PARAMETER          ( ONE = 1.0E+0, CONE = ( 1.0E+0, 0.0E+0 ),
+     $                   CZERO = ( 0.0E+0, 0.0E+0 ) )
+*     ..
+*     .. Local Scalars ..
+      LOGICAL            UPPER
+      INTEGER            J, K, KP, KSTEP
+      REAL               AK, AKP1, D, T
+      COMPLEX            AKKP1, TEMP
+*     ..
+*     .. External Functions ..
+      LOGICAL            LSAME
+      COMPLEX            CDOTC
+      EXTERNAL           LSAME, CDOTC
+*     ..
+*     .. External Subroutines ..
+      EXTERNAL           CCOPY, CHEMV, CSWAP, XERBLA
+*     ..
+*     .. Intrinsic Functions ..
+      INTRINSIC          ABS, CONJG, MAX, REAL
+*     ..
+*     .. Executable Statements ..
+*
+*     Test the input parameters.
+*
+      INFO = 0
+      UPPER = LSAME( UPLO, 'U' )
+      IF( .NOT.UPPER .AND. .NOT.LSAME( UPLO, 'L' ) ) THEN
+         INFO = -1
+      ELSE IF( N.LT.0 ) THEN
+         INFO = -2
+      ELSE IF( LDA.LT.MAX( 1, N ) ) THEN
+         INFO = -4
+      END IF
+      IF( INFO.NE.0 ) THEN
+         CALL XERBLA( 'CHETRI_ROOK', -INFO )
+         RETURN
+      END IF
+*
+*     Quick return if possible
+*
+      IF( N.EQ.0 )
+     $   RETURN
+*
+*     Check that the diagonal matrix D is nonsingular.
+*
+      IF( UPPER ) THEN
+*
+*        Upper triangular storage: examine D from bottom to top
+*
+         DO 10 INFO = N, 1, -1
+            IF( IPIV( INFO ).GT.0 .AND. A( INFO, INFO ).EQ.CZERO )
+     $         RETURN
+   10    CONTINUE
+      ELSE
+*
+*        Lower triangular storage: examine D from top to bottom.
+*
+         DO 20 INFO = 1, N
+            IF( IPIV( INFO ).GT.0 .AND. A( INFO, INFO ).EQ.CZERO )
+     $         RETURN
+   20    CONTINUE
+      END IF
+      INFO = 0
+*
+      IF( UPPER ) THEN
+*
+*        Compute inv(A) from the factorization A = U*D*U**H.
+*
+*        K is the main loop index, increasing from 1 to N in steps of
+*        1 or 2, depending on the size of the diagonal blocks.
+*
+         K = 1
+   30    CONTINUE
+*
+*        If K > N, exit from loop.
+*
+         IF( K.GT.N )
+     $      GO TO 70
+*
+         IF( IPIV( K ).GT.0 ) THEN
+*
+*           1 x 1 diagonal block
+*
+*           Invert the diagonal block.
+*
+            A( K, K ) = ONE / REAL( A( K, K ) )
+*
+*           Compute column K of the inverse.
+*
+            IF( K.GT.1 ) THEN
+               CALL CCOPY( K-1, A( 1, K ), 1, WORK, 1 )
+               CALL CHEMV( UPLO, K-1, -CONE, A, LDA, WORK, 1, CZERO,
+     $                     A( 1, K ), 1 )
+               A( K, K ) = A( K, K ) - REAL( CDOTC( K-1, WORK, 1, A( 1,
+     $                     K ), 1 ) )
+            END IF
+            KSTEP = 1
+         ELSE
+*
+*           2 x 2 diagonal block
+*
+*           Invert the diagonal block.
+*
+            T = ABS( A( K, K+1 ) )
+            AK = REAL( A( K, K ) ) / T
+            AKP1 = REAL( A( K+1, K+1 ) ) / T
+            AKKP1 = A( K, K+1 ) / T
+            D = T*( AK*AKP1-ONE )
+            A( K, K ) = AKP1 / D
+            A( K+1, K+1 ) = AK / D
+            A( K, K+1 ) = -AKKP1 / D
+*
+*           Compute columns K and K+1 of the inverse.
+*
+            IF( K.GT.1 ) THEN
+               CALL CCOPY( K-1, A( 1, K ), 1, WORK, 1 )
+               CALL CHEMV( UPLO, K-1, -CONE, A, LDA, WORK, 1, CZERO,
+     $                     A( 1, K ), 1 )
+               A( K, K ) = A( K, K ) - REAL( CDOTC( K-1, WORK, 1, A( 1,
+     $                     K ), 1 ) )
+               A( K, K+1 ) = A( K, K+1 ) -
+     $                       CDOTC( K-1, A( 1, K ), 1, A( 1, K+1 ), 1 )
+               CALL CCOPY( K-1, A( 1, K+1 ), 1, WORK, 1 )
+               CALL CHEMV( UPLO, K-1, -CONE, A, LDA, WORK, 1, CZERO,
+     $                     A( 1, K+1 ), 1 )
+               A( K+1, K+1 ) = A( K+1, K+1 ) -
+     $                         REAL( CDOTC( K-1, WORK, 1, A( 1, K+1 ),
+     $                         1 ) )
+            END IF
+            KSTEP = 2
+         END IF
+*
+         IF( KSTEP.EQ.1 ) THEN
+*
+*           Interchange rows and columns K and IPIV(K) in the leading
+*           submatrix A(1:k,1:k)
+*
+            KP = IPIV( K )
+            IF( KP.NE.K ) THEN
+*
+               IF( KP.GT.1 )
+     $            CALL CSWAP( KP-1, A( 1, K ), 1, A( 1, KP ), 1 )
+*
+               DO 40 J = KP + 1, K - 1
+                  TEMP = CONJG( A( J, K ) )
+                  A( J, K ) = CONJG( A( KP, J ) )
+                  A( KP, J ) = TEMP
+   40          CONTINUE
+*
+               A( KP, K ) = CONJG( A( KP, K ) )
+*
+               TEMP = A( K, K )
+               A( K, K ) = A( KP, KP )
+               A( KP, KP ) = TEMP
+            END IF
+         ELSE
+*
+*           Interchange rows and columns K and K+1 with -IPIV(K) and
+*           -IPIV(K+1) in the trailing submatrix A(k+1:n,k+1:n)
+*
+*           (1) Interchange rows and columns K and -IPIV(K)
+*
+            KP = -IPIV( K )
+            IF( KP.NE.K ) THEN
+*
+               IF( KP.GT.1 )
+     $            CALL CSWAP( KP-1, A( 1, K ), 1, A( 1, KP ), 1 )
+*
+               DO 50 J = KP + 1, K - 1
+                  TEMP = CONJG( A( J, K ) )
+                  A( J, K ) = CONJG( A( KP, J ) )
+                  A( KP, J ) = TEMP
+   50          CONTINUE
+*
+               A( KP, K ) = CONJG( A( KP, K ) )
+*
+               TEMP = A( K, K )
+               A( K, K ) = A( KP, KP )
+               A( KP, KP ) = TEMP
+*
+               TEMP = A( K, K+1 )
+               A( K, K+1 ) = A( KP, K+1 )
+               A( KP, K+1 ) = TEMP
+            END IF
+         END IF
+*
+*           (2) Interchange rows and columns K+1 and -IPIV(K+1)
+*
+            K = K + 1
+            KP = -IPIV( K )
+            IF( KP.NE.K ) THEN
+*
+               IF( KP.GT.1 )
+     $            CALL CSWAP( KP-1, A( 1, K ), 1, A( 1, KP ), 1 )
+*
+               DO 60 J = KP + 1, K - 1
+                  TEMP = CONJG( A( J, K ) )
+                  A( J, K ) = CONJG( A( KP, J ) )
+                  A( KP, J ) = TEMP
+   60          CONTINUE
+*
+               A( KP, K ) = CONJG( A( KP, K ) )
+*
+               TEMP = A( K, K )
+               A( K, K ) = A( KP, KP )
+               A( KP, KP ) = TEMP
+            END IF
+*
+         K = K + 1
+         GO TO 30
+   70    CONTINUE
+*
+      ELSE
+*
+*        Compute inv(A) from the factorization A = L*D*L**H.
+*
+*        K is the main loop index, decreasing from N to 1 in steps of
+*        1 or 2, depending on the size of the diagonal blocks.
+*
+         K = N
+   80    CONTINUE
+*
+*        If K < 1, exit from loop.
+*
+         IF( K.LT.1 )
+     $      GO TO 120
+*
+         IF( IPIV( K ).GT.0 ) THEN
+*
+*           1 x 1 diagonal block
+*
+*           Invert the diagonal block.
+*
+            A( K, K ) = ONE / REAL( A( K, K ) )
+*
+*           Compute column K of the inverse.
+*
+            IF( K.LT.N ) THEN
+               CALL CCOPY( N-K, A( K+1, K ), 1, WORK, 1 )
+               CALL CHEMV( UPLO, N-K, -CONE, A( K+1, K+1 ), LDA, WORK,
+     $                     1, CZERO, A( K+1, K ), 1 )
+               A( K, K ) = A( K, K ) - REAL( CDOTC( N-K, WORK, 1,
+     $                     A( K+1, K ), 1 ) )
+            END IF
+            KSTEP = 1
+         ELSE
+*
+*           2 x 2 diagonal block
+*
+*           Invert the diagonal block.
+*
+            T = ABS( A( K, K-1 ) )
+            AK = REAL( A( K-1, K-1 ) ) / T
+            AKP1 = REAL( A( K, K ) ) / T
+            AKKP1 = A( K, K-1 ) / T
+            D = T*( AK*AKP1-ONE )
+            A( K-1, K-1 ) = AKP1 / D
+            A( K, K ) = AK / D
+            A( K, K-1 ) = -AKKP1 / D
+*
+*           Compute columns K-1 and K of the inverse.
+*
+            IF( K.LT.N ) THEN
+               CALL CCOPY( N-K, A( K+1, K ), 1, WORK, 1 )
+               CALL CHEMV( UPLO, N-K, -CONE, A( K+1, K+1 ), LDA, WORK,
+     $                     1, CZERO, A( K+1, K ), 1 )
+               A( K, K ) = A( K, K ) - REAL( CDOTC( N-K, WORK, 1,
+     $                     A( K+1, K ), 1 ) )
+               A( K, K-1 ) = A( K, K-1 ) -
+     $                       CDOTC( N-K, A( K+1, K ), 1, A( K+1, K-1 ),
+     $                       1 )
+               CALL CCOPY( N-K, A( K+1, K-1 ), 1, WORK, 1 )
+               CALL CHEMV( UPLO, N-K, -CONE, A( K+1, K+1 ), LDA, WORK,
+     $                     1, CZERO, A( K+1, K-1 ), 1 )
+               A( K-1, K-1 ) = A( K-1, K-1 ) -
+     $                         REAL( CDOTC( N-K, WORK, 1, A( K+1, K-1 ),
+     $                         1 ) )
+            END IF
+            KSTEP = 2
+         END IF
+*
+         IF( KSTEP.EQ.1 ) THEN
+*
+*           Interchange rows and columns K and IPIV(K) in the trailing
+*           submatrix A(k:n,k:n)
+*
+            KP = IPIV( K )
+            IF( KP.NE.K ) THEN
+*
+               IF( KP.LT.N )
+     $            CALL CSWAP( N-KP, A( KP+1, K ), 1, A( KP+1, KP ), 1 )
+*
+               DO 90 J = K + 1, KP - 1
+                  TEMP = CONJG( A( J, K ) )
+                  A( J, K ) = CONJG( A( KP, J ) )
+                  A( KP, J ) = TEMP
+   90          CONTINUE
+*
+               A( KP, K ) = CONJG( A( KP, K ) )
+*
+               TEMP = A( K, K )
+               A( K, K ) = A( KP, KP )
+               A( KP, KP ) = TEMP
+            END IF
+         ELSE
+*
+*           Interchange rows and columns K and K-1 with -IPIV(K) and
+*           -IPIV(K-1) in the trailing submatrix A(k-1:n,k-1:n)
+*
+*           (1) Interchange rows and columns K and -IPIV(K)
+*
+            KP = -IPIV( K )
+            IF( KP.NE.K ) THEN
+*
+               IF( KP.LT.N )
+     $            CALL CSWAP( N-KP, A( KP+1, K ), 1, A( KP+1, KP ), 1 )
+*
+               DO 100 J = K + 1, KP - 1
+                  TEMP = CONJG( A( J, K ) )
+                  A( J, K ) = CONJG( A( KP, J ) )
+                  A( KP, J ) = TEMP
+  100         CONTINUE
+*
+               A( KP, K ) = CONJG( A( KP, K ) )
+*
+               TEMP = A( K, K )
+               A( K, K ) = A( KP, KP )
+               A( KP, KP ) = TEMP
+*
+               TEMP = A( K, K-1 )
+               A( K, K-1 ) = A( KP, K-1 )
+               A( KP, K-1 ) = TEMP
+            END IF
+*
+*           (2) Interchange rows and columns K-1 and -IPIV(K-1)
+*
+            K = K - 1
+            KP = -IPIV( K )
+            IF( KP.NE.K ) THEN
+*
+               IF( KP.LT.N )
+     $            CALL CSWAP( N-KP, A( KP+1, K ), 1, A( KP+1, KP ), 1 )
+*
+               DO 110 J = K + 1, KP - 1
+                  TEMP = CONJG( A( J, K ) )
+                  A( J, K ) = CONJG( A( KP, J ) )
+                  A( KP, J ) = TEMP
+  110         CONTINUE
+*
+               A( KP, K ) = CONJG( A( KP, K ) )
+*
+               TEMP = A( K, K )
+               A( K, K ) = A( KP, KP )
+               A( KP, KP ) = TEMP
+            END IF
+         END IF
+*
+         K = K - 1
+         GO TO 80
+  120    CONTINUE
+      END IF
+*
+      RETURN
+*
+*     End of CHETRI_ROOK
+*
+      END
diff --git a/SRC/zhetri_rook.f b/SRC/zhetri_rook.f
new file mode 100644 (file)
index 0000000..3149786
--- /dev/null
@@ -0,0 +1,516 @@
+*> \brief \b ZHETRI_ROOK computes the inverse of HE matrix using the factorization obtained with the bounded Bunch-Kaufman ("rook") diagonal pivoting method.
+*
+*  =========== DOCUMENTATION ===========
+*
+* Online html documentation available at
+*            http://www.netlib.org/lapack/explore-html/
+*
+*> \htmlonly
+*> Download ZHETRI_ROOK + dependencies
+*> <a href="http://www.netlib.org/cgi-bin/netlibfiles.tgz?format=tgz&filename=/lapack/lapack_routine/zhetri_rook.f">
+*> [TGZ]</a>
+*> <a href="http://www.netlib.org/cgi-bin/netlibfiles.zip?format=zip&filename=/lapack/lapack_routine/zhetri_rook.f">
+*> [ZIP]</a>
+*> <a href="http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/zhetri_rook.f">
+*> [TXT]</a>
+*> \endhtmlonly
+*
+*  Definition:
+*  ===========
+*
+*       SUBROUTINE ZHETRI_ROOK( UPLO, N, A, LDA, IPIV, WORK, INFO )
+*
+*       .. Scalar Arguments ..
+*       CHARACTER          UPLO
+*       INTEGER            INFO, LDA, N
+*       ..
+*       .. Array Arguments ..
+*       INTEGER            IPIV( * )
+*       COMPLEX*16         A( LDA, * ), WORK( * )
+*       ..
+*
+*
+*> \par Purpose:
+*  =============
+*>
+*> \verbatim
+*>
+*> ZHETRI_ROOK computes the inverse of a complex Hermitian indefinite matrix
+*> A using the factorization A = U*D*U**H or A = L*D*L**H computed by
+*> ZHETRF_ROOK.
+*> \endverbatim
+*
+*  Arguments:
+*  ==========
+*
+*> \param[in] UPLO
+*> \verbatim
+*>          UPLO is CHARACTER*1
+*>          Specifies whether the details of the factorization are stored
+*>          as an upper or lower triangular matrix.
+*>          = 'U':  Upper triangular, form is A = U*D*U**H;
+*>          = 'L':  Lower triangular, form is A = L*D*L**H.
+*> \endverbatim
+*>
+*> \param[in] N
+*> \verbatim
+*>          N is INTEGER
+*>          The order of the matrix A.  N >= 0.
+*> \endverbatim
+*>
+*> \param[in,out] A
+*> \verbatim
+*>          A is COMPLEX*16 array, dimension (LDA,N)
+*>          On entry, the block diagonal matrix D and the multipliers
+*>          used to obtain the factor U or L as computed by ZHETRF_ROOK.
+*>
+*>          On exit, if INFO = 0, the (Hermitian) inverse of the original
+*>          matrix.  If UPLO = 'U', the upper triangular part of the
+*>          inverse is formed and the part of A below the diagonal is not
+*>          referenced; if UPLO = 'L' the lower triangular part of the
+*>          inverse is formed and the part of A above the diagonal is
+*>          not referenced.
+*> \endverbatim
+*>
+*> \param[in] LDA
+*> \verbatim
+*>          LDA is INTEGER
+*>          The leading dimension of the array A.  LDA >= max(1,N).
+*> \endverbatim
+*>
+*> \param[in] IPIV
+*> \verbatim
+*>          IPIV is INTEGER array, dimension (N)
+*>          Details of the interchanges and the block structure of D
+*>          as determined by ZHETRF_ROOK.
+*> \endverbatim
+*>
+*> \param[out] WORK
+*> \verbatim
+*>          WORK is COMPLEX*16 array, dimension (N)
+*> \endverbatim
+*>
+*> \param[out] INFO
+*> \verbatim
+*>          INFO is INTEGER
+*>          = 0: successful exit
+*>          < 0: if INFO = -i, the i-th argument had an illegal value
+*>          > 0: if INFO = i, D(i,i) = 0; the matrix is singular and its
+*>               inverse could not be computed.
+*> \endverbatim
+*
+*  Authors:
+*  ========
+*
+*> \author Univ. of Tennessee
+*> \author Univ. of California Berkeley
+*> \author Univ. of Colorado Denver
+*> \author NAG Ltd.
+*
+*> \date November 2011
+*
+*> \ingroup complex16HEcomputational
+*
+*> \par Contributors:
+*  ==================
+*>
+*> \verbatim
+*>
+*>  November 2012,  Igor Kozachenko,
+*>                  Computer Science Division,
+*>                  University of California, Berkeley
+*>
+*>  September 2007, Sven Hammarling, Nicholas J. Higham, Craig Lucas,
+*>                  School of Mathematics,
+*>                  University of Manchester
+*> \endverbatim
+*
+*  =====================================================================
+      SUBROUTINE ZHETRI_ROOK( UPLO, N, A, LDA, IPIV, WORK, INFO )
+*
+*  -- LAPACK computational routine (version 3.4.0) --
+*  -- LAPACK is a software package provided by Univ. of Tennessee,    --
+*  -- Univ. of California Berkeley, Univ. of Colorado Denver and NAG Ltd..--
+*     November 2011
+*
+*     .. Scalar Arguments ..
+      CHARACTER          UPLO
+      INTEGER            INFO, LDA, N
+*     ..
+*     .. Array Arguments ..
+      INTEGER            IPIV( * )
+      COMPLEX*16         A( LDA, * ), WORK( * )
+*     ..
+*
+*  =====================================================================
+*
+*     .. Parameters ..
+      DOUBLE PRECISION   ONE
+      COMPLEX*16         CONE, CZERO
+      PARAMETER          ( ONE = 1.0D+0, CONE = ( 1.0D+0, 0.0D+0 ),
+     $                   CZERO = ( 0.0D+0, 0.0D+0 ) )
+*     ..
+*     .. Local Scalars ..
+      LOGICAL            UPPER
+      INTEGER            J, K, KP, KSTEP
+      DOUBLE PRECISION   AK, AKP1, D, T
+      COMPLEX*16         AKKP1, TEMP
+*     ..
+*     .. External Functions ..
+      LOGICAL            LSAME
+      COMPLEX*16         ZDOTC
+      EXTERNAL           LSAME, ZDOTC
+*     ..
+*     .. External Subroutines ..
+      EXTERNAL           ZCOPY, ZHEMV, ZSWAP, XERBLA
+*     ..
+*     .. Intrinsic Functions ..
+      INTRINSIC          ABS, DBLE, DCONJG, MAX
+*     ..
+*     .. Executable Statements ..
+*
+*     Test the input parameters.
+*
+      INFO = 0
+      UPPER = LSAME( UPLO, 'U' )
+      IF( .NOT.UPPER .AND. .NOT.LSAME( UPLO, 'L' ) ) THEN
+         INFO = -1
+      ELSE IF( N.LT.0 ) THEN
+         INFO = -2
+      ELSE IF( LDA.LT.MAX( 1, N ) ) THEN
+         INFO = -4
+      END IF
+      IF( INFO.NE.0 ) THEN
+         CALL XERBLA( 'ZHETRI_ROOK', -INFO )
+         RETURN
+      END IF
+*
+*     Quick return if possible
+*
+      IF( N.EQ.0 )
+     $   RETURN
+*
+*     Check that the diagonal matrix D is nonsingular.
+*
+      IF( UPPER ) THEN
+*
+*        Upper triangular storage: examine D from bottom to top
+*
+         DO 10 INFO = N, 1, -1
+            IF( IPIV( INFO ).GT.0 .AND. A( INFO, INFO ).EQ.CZERO )
+     $         RETURN
+   10    CONTINUE
+      ELSE
+*
+*        Lower triangular storage: examine D from top to bottom.
+*
+         DO 20 INFO = 1, N
+            IF( IPIV( INFO ).GT.0 .AND. A( INFO, INFO ).EQ.CZERO )
+     $         RETURN
+   20    CONTINUE
+      END IF
+      INFO = 0
+*
+      IF( UPPER ) THEN
+*
+*        Compute inv(A) from the factorization A = U*D*U**H.
+*
+*        K is the main loop index, increasing from 1 to N in steps of
+*        1 or 2, depending on the size of the diagonal blocks.
+*
+         K = 1
+   30    CONTINUE
+*
+*        If K > N, exit from loop.
+*
+         IF( K.GT.N )
+     $      GO TO 70
+*
+         IF( IPIV( K ).GT.0 ) THEN
+*
+*           1 x 1 diagonal block
+*
+*           Invert the diagonal block.
+*
+            A( K, K ) = ONE / DBLE( A( K, K ) )
+*
+*           Compute column K of the inverse.
+*
+            IF( K.GT.1 ) THEN
+               CALL ZCOPY( K-1, A( 1, K ), 1, WORK, 1 )
+               CALL ZHEMV( UPLO, K-1, -CONE, A, LDA, WORK, 1, CZERO,
+     $                     A( 1, K ), 1 )
+               A( K, K ) = A( K, K ) - DBLE( ZDOTC( K-1, WORK, 1, A( 1,
+     $                     K ), 1 ) )
+            END IF
+            KSTEP = 1
+         ELSE
+*
+*           2 x 2 diagonal block
+*
+*           Invert the diagonal block.
+*
+            T = ABS( A( K, K+1 ) )
+            AK = DBLE( A( K, K ) ) / T
+            AKP1 = DBLE( A( K+1, K+1 ) ) / T
+            AKKP1 = A( K, K+1 ) / T
+            D = T*( AK*AKP1-ONE )
+            A( K, K ) = AKP1 / D
+            A( K+1, K+1 ) = AK / D
+            A( K, K+1 ) = -AKKP1 / D
+*
+*           Compute columns K and K+1 of the inverse.
+*
+            IF( K.GT.1 ) THEN
+               CALL ZCOPY( K-1, A( 1, K ), 1, WORK, 1 )
+               CALL ZHEMV( UPLO, K-1, -CONE, A, LDA, WORK, 1, CZERO,
+     $                     A( 1, K ), 1 )
+               A( K, K ) = A( K, K ) - DBLE( ZDOTC( K-1, WORK, 1, A( 1,
+     $                     K ), 1 ) )
+               A( K, K+1 ) = A( K, K+1 ) -
+     $                       ZDOTC( K-1, A( 1, K ), 1, A( 1, K+1 ), 1 )
+               CALL ZCOPY( K-1, A( 1, K+1 ), 1, WORK, 1 )
+               CALL ZHEMV( UPLO, K-1, -CONE, A, LDA, WORK, 1, CZERO,
+     $                     A( 1, K+1 ), 1 )
+               A( K+1, K+1 ) = A( K+1, K+1 ) -
+     $                         DBLE( ZDOTC( K-1, WORK, 1, A( 1, K+1 ),
+     $                         1 ) )
+            END IF
+            KSTEP = 2
+         END IF
+*
+         IF( KSTEP.EQ.1 ) THEN
+*
+*           Interchange rows and columns K and IPIV(K) in the leading
+*           submatrix A(1:k,1:k)
+*
+            KP = IPIV( K )
+            IF( KP.NE.K ) THEN
+*
+               IF( KP.GT.1 )
+     $            CALL ZSWAP( KP-1, A( 1, K ), 1, A( 1, KP ), 1 )
+*
+               DO 40 J = KP + 1, K - 1
+                  TEMP = DCONJG( A( J, K ) )
+                  A( J, K ) = DCONJG( A( KP, J ) )
+                  A( KP, J ) = TEMP
+   40          CONTINUE
+*
+               A( KP, K ) = DCONJG( A( KP, K ) )
+*
+               TEMP = A( K, K )
+               A( K, K ) = A( KP, KP )
+               A( KP, KP ) = TEMP
+            END IF
+         ELSE
+*
+*           Interchange rows and columns K and K+1 with -IPIV(K) and
+*           -IPIV(K+1) in the trailing submatrix A(k+1:n,k+1:n)
+*
+*           (1) Interchange rows and columns K and -IPIV(K)
+*
+            KP = -IPIV( K )
+            IF( KP.NE.K ) THEN
+*
+               IF( KP.GT.1 )
+     $            CALL ZSWAP( KP-1, A( 1, K ), 1, A( 1, KP ), 1 )
+*
+               DO 50 J = KP + 1, K - 1
+                  TEMP = DCONJG( A( J, K ) )
+                  A( J, K ) = DCONJG( A( KP, J ) )
+                  A( KP, J ) = TEMP
+   50          CONTINUE
+*
+               A( KP, K ) = DCONJG( A( KP, K ) )
+*
+               TEMP = A( K, K )
+               A( K, K ) = A( KP, KP )
+               A( KP, KP ) = TEMP
+*
+               TEMP = A( K, K+1 )
+               A( K, K+1 ) = A( KP, K+1 )
+               A( KP, K+1 ) = TEMP
+            END IF
+         END IF
+*
+*           (2) Interchange rows and columns K+1 and -IPIV(K+1)
+*
+            K = K + 1
+            KP = -IPIV( K )
+            IF( KP.NE.K ) THEN
+*
+               IF( KP.GT.1 )
+     $            CALL ZSWAP( KP-1, A( 1, K ), 1, A( 1, KP ), 1 )
+*
+               DO 60 J = KP + 1, K - 1
+                  TEMP = DCONJG( A( J, K ) )
+                  A( J, K ) = DCONJG( A( KP, J ) )
+                  A( KP, J ) = TEMP
+   60          CONTINUE
+*
+               A( KP, K ) = DCONJG( A( KP, K ) )
+*
+               TEMP = A( K, K )
+               A( K, K ) = A( KP, KP )
+               A( KP, KP ) = TEMP
+            END IF
+*
+         K = K + 1
+         GO TO 30
+   70    CONTINUE
+*
+      ELSE
+*
+*        Compute inv(A) from the factorization A = L*D*L**H.
+*
+*        K is the main loop index, decreasing from N to 1 in steps of
+*        1 or 2, depending on the size of the diagonal blocks.
+*
+         K = N
+   80    CONTINUE
+*
+*        If K < 1, exit from loop.
+*
+         IF( K.LT.1 )
+     $      GO TO 120
+*
+         IF( IPIV( K ).GT.0 ) THEN
+*
+*           1 x 1 diagonal block
+*
+*           Invert the diagonal block.
+*
+            A( K, K ) = ONE / DBLE( A( K, K ) )
+*
+*           Compute column K of the inverse.
+*
+            IF( K.LT.N ) THEN
+               CALL ZCOPY( N-K, A( K+1, K ), 1, WORK, 1 )
+               CALL ZHEMV( UPLO, N-K, -CONE, A( K+1, K+1 ), LDA, WORK,
+     $                     1, CZERO, A( K+1, K ), 1 )
+               A( K, K ) = A( K, K ) - DBLE( ZDOTC( N-K, WORK, 1,
+     $                     A( K+1, K ), 1 ) )
+            END IF
+            KSTEP = 1
+         ELSE
+*
+*           2 x 2 diagonal block
+*
+*           Invert the diagonal block.
+*
+            T = ABS( A( K, K-1 ) )
+            AK = DBLE( A( K-1, K-1 ) ) / T
+            AKP1 = DBLE( A( K, K ) ) / T
+            AKKP1 = A( K, K-1 ) / T
+            D = T*( AK*AKP1-ONE )
+            A( K-1, K-1 ) = AKP1 / D
+            A( K, K ) = AK / D
+            A( K, K-1 ) = -AKKP1 / D
+*
+*           Compute columns K-1 and K of the inverse.
+*
+            IF( K.LT.N ) THEN
+               CALL ZCOPY( N-K, A( K+1, K ), 1, WORK, 1 )
+               CALL ZHEMV( UPLO, N-K, -CONE, A( K+1, K+1 ), LDA, WORK,
+     $                     1, CZERO, A( K+1, K ), 1 )
+               A( K, K ) = A( K, K ) - DBLE( ZDOTC( N-K, WORK, 1,
+     $                     A( K+1, K ), 1 ) )
+               A( K, K-1 ) = A( K, K-1 ) -
+     $                       ZDOTC( N-K, A( K+1, K ), 1, A( K+1, K-1 ),
+     $                       1 )
+               CALL ZCOPY( N-K, A( K+1, K-1 ), 1, WORK, 1 )
+               CALL ZHEMV( UPLO, N-K, -CONE, A( K+1, K+1 ), LDA, WORK,
+     $                     1, CZERO, A( K+1, K-1 ), 1 )
+               A( K-1, K-1 ) = A( K-1, K-1 ) -
+     $                         DBLE( ZDOTC( N-K, WORK, 1, A( K+1, K-1 ),
+     $                         1 ) )
+            END IF
+            KSTEP = 2
+         END IF
+*
+         IF( KSTEP.EQ.1 ) THEN
+*
+*           Interchange rows and columns K and IPIV(K) in the trailing
+*           submatrix A(k:n,k:n)
+*
+            KP = IPIV( K )
+            IF( KP.NE.K ) THEN
+*
+               IF( KP.LT.N )
+     $            CALL ZSWAP( N-KP, A( KP+1, K ), 1, A( KP+1, KP ), 1 )
+*
+               DO 90 J = K + 1, KP - 1
+                  TEMP = DCONJG( A( J, K ) )
+                  A( J, K ) = DCONJG( A( KP, J ) )
+                  A( KP, J ) = TEMP
+   90          CONTINUE
+*
+               A( KP, K ) = DCONJG( A( KP, K ) )
+*
+               TEMP = A( K, K )
+               A( K, K ) = A( KP, KP )
+               A( KP, KP ) = TEMP
+            END IF
+         ELSE
+*
+*           Interchange rows and columns K and K-1 with -IPIV(K) and
+*           -IPIV(K-1) in the trailing submatrix A(k-1:n,k-1:n)
+*
+*           (1) Interchange rows and columns K and -IPIV(K)
+*
+            KP = -IPIV( K )
+            IF( KP.NE.K ) THEN
+*
+               IF( KP.LT.N )
+     $            CALL ZSWAP( N-KP, A( KP+1, K ), 1, A( KP+1, KP ), 1 )
+*
+               DO 100 J = K + 1, KP - 1
+                  TEMP = DCONJG( A( J, K ) )
+                  A( J, K ) = DCONJG( A( KP, J ) )
+                  A( KP, J ) = TEMP
+  100         CONTINUE
+*
+               A( KP, K ) = DCONJG( A( KP, K ) )
+*
+               TEMP = A( K, K )
+               A( K, K ) = A( KP, KP )
+               A( KP, KP ) = TEMP
+*
+               TEMP = A( K, K-1 )
+               A( K, K-1 ) = A( KP, K-1 )
+               A( KP, K-1 ) = TEMP
+            END IF
+*
+*           (2) Interchange rows and columns K-1 and -IPIV(K-1)
+*
+            K = K - 1
+            KP = -IPIV( K )
+            IF( KP.NE.K ) THEN
+*
+               IF( KP.LT.N )
+     $            CALL ZSWAP( N-KP, A( KP+1, K ), 1, A( KP+1, KP ), 1 )
+*
+               DO 110 J = K + 1, KP - 1
+                  TEMP = DCONJG( A( J, K ) )
+                  A( J, K ) = DCONJG( A( KP, J ) )
+                  A( KP, J ) = TEMP
+  110         CONTINUE
+*
+               A( KP, K ) = DCONJG( A( KP, K ) )
+*
+               TEMP = A( K, K )
+               A( K, K ) = A( KP, KP )
+               A( KP, KP ) = TEMP
+            END IF
+         END IF
+*
+         K = K - 1
+         GO TO 80
+  120    CONTINUE
+      END IF
+*
+      RETURN
+*
+*     End of ZHETRI_ROOK
+*
+      END