1 *> \brief \b ZSYTRI_ROOK
3 * =========== DOCUMENTATION ===========
5 * Online html documentation available at
6 * http://www.netlib.org/lapack/explore-html/
9 *> Download ZSYTRI_ROOK + dependencies
10 *> <a href="http://www.netlib.org/cgi-bin/netlibfiles.tgz?format=tgz&filename=/lapack/lapack_routine/zsytri_rook.f">
12 *> <a href="http://www.netlib.org/cgi-bin/netlibfiles.zip?format=zip&filename=/lapack/lapack_routine/zsytri_rook.f">
14 *> <a href="http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/zsytri_rook.f">
21 * SUBROUTINE ZSYTRI_ROOK( UPLO, N, A, LDA, IPIV, WORK, INFO )
23 * .. Scalar Arguments ..
25 * INTEGER INFO, LDA, N
27 * .. Array Arguments ..
29 * COMPLEX*16 A( LDA, * ), WORK( * )
38 *> ZSYTRI_ROOK computes the inverse of a complex symmetric
39 *> matrix A using the factorization A = U*D*U**T or A = L*D*L**T
40 *> computed by ZSYTRF_ROOK.
48 *> UPLO is CHARACTER*1
49 *> Specifies whether the details of the factorization are stored
50 *> as an upper or lower triangular matrix.
51 *> = 'U': Upper triangular, form is A = U*D*U**T;
52 *> = 'L': Lower triangular, form is A = L*D*L**T.
58 *> The order of the matrix A. N >= 0.
63 *> A is COMPLEX*16 array, dimension (LDA,N)
64 *> On entry, the block diagonal matrix D and the multipliers
65 *> used to obtain the factor U or L as computed by ZSYTRF_ROOK.
67 *> On exit, if INFO = 0, the (symmetric) inverse of the original
68 *> matrix. If UPLO = 'U', the upper triangular part of the
69 *> inverse is formed and the part of A below the diagonal is not
70 *> referenced; if UPLO = 'L' the lower triangular part of the
71 *> inverse is formed and the part of A above the diagonal is
78 *> The leading dimension of the array A. LDA >= max(1,N).
83 *> IPIV is INTEGER array, dimension (N)
84 *> Details of the interchanges and the block structure of D
85 *> as determined by ZSYTRF_ROOK.
90 *> WORK is COMPLEX*16 array, dimension (N)
96 *> = 0: successful exit
97 *> < 0: if INFO = -i, the i-th argument had an illegal value
98 *> > 0: if INFO = i, D(i,i) = 0; the matrix is singular and its
99 *> inverse could not be computed.
105 *> \author Univ. of Tennessee
106 *> \author Univ. of California Berkeley
107 *> \author Univ. of Colorado Denver
110 *> \date November 2015
112 *> \ingroup complex16SYcomputational
114 *> \par Contributors:
119 *> November 2015, Igor Kozachenko,
120 *> Computer Science Division,
121 *> University of California, Berkeley
123 *> September 2007, Sven Hammarling, Nicholas J. Higham, Craig Lucas,
124 *> School of Mathematics,
125 *> University of Manchester
129 * =====================================================================
130 SUBROUTINE ZSYTRI_ROOK( UPLO, N, A, LDA, IPIV, WORK, INFO )
132 * -- LAPACK computational routine (version 3.6.0) --
133 * -- LAPACK is a software package provided by Univ. of Tennessee, --
134 * -- Univ. of California Berkeley, Univ. of Colorado Denver and NAG Ltd..--
137 * .. Scalar Arguments ..
141 * .. Array Arguments ..
143 COMPLEX*16 A( LDA, * ), WORK( * )
146 * =====================================================================
149 COMPLEX*16 CONE, CZERO
150 PARAMETER ( CONE = ( 1.0D+0, 0.0D+0 ),
151 $ CZERO = ( 0.0D+0, 0.0D+0 ) )
153 * .. Local Scalars ..
156 COMPLEX*16 AK, AKKP1, AKP1, D, T, TEMP
158 * .. External Functions ..
161 EXTERNAL LSAME, ZDOTU
163 * .. External Subroutines ..
164 EXTERNAL ZCOPY, ZSWAP, ZSYMV, XERBLA
166 * .. Intrinsic Functions ..
169 * .. Executable Statements ..
171 * Test the input parameters.
174 UPPER = LSAME( UPLO, 'U' )
175 IF( .NOT.UPPER .AND. .NOT.LSAME( UPLO, 'L' ) ) THEN
177 ELSE IF( N.LT.0 ) THEN
179 ELSE IF( LDA.LT.MAX( 1, N ) ) THEN
183 CALL XERBLA( 'ZSYTRI_ROOK', -INFO )
187 * Quick return if possible
192 * Check that the diagonal matrix D is nonsingular.
196 * Upper triangular storage: examine D from bottom to top
198 DO 10 INFO = N, 1, -1
199 IF( IPIV( INFO ).GT.0 .AND. A( INFO, INFO ).EQ.CZERO )
204 * Lower triangular storage: examine D from top to bottom.
207 IF( IPIV( INFO ).GT.0 .AND. A( INFO, INFO ).EQ.CZERO )
215 * Compute inv(A) from the factorization A = U*D*U**T.
217 * K is the main loop index, increasing from 1 to N in steps of
218 * 1 or 2, depending on the size of the diagonal blocks.
223 * If K > N, exit from loop.
228 IF( IPIV( K ).GT.0 ) THEN
230 * 1 x 1 diagonal block
232 * Invert the diagonal block.
234 A( K, K ) = CONE / A( K, K )
236 * Compute column K of the inverse.
239 CALL ZCOPY( K-1, A( 1, K ), 1, WORK, 1 )
240 CALL ZSYMV( UPLO, K-1, -CONE, A, LDA, WORK, 1, CZERO,
242 A( K, K ) = A( K, K ) - ZDOTU( K-1, WORK, 1, A( 1, K ),
248 * 2 x 2 diagonal block
250 * Invert the diagonal block.
254 AKP1 = A( K+1, K+1 ) / T
255 AKKP1 = A( K, K+1 ) / T
256 D = T*( AK*AKP1-CONE )
258 A( K+1, K+1 ) = AK / D
259 A( K, K+1 ) = -AKKP1 / D
261 * Compute columns K and K+1 of the inverse.
264 CALL ZCOPY( K-1, A( 1, K ), 1, WORK, 1 )
265 CALL ZSYMV( UPLO, K-1, -CONE, A, LDA, WORK, 1, CZERO,
267 A( K, K ) = A( K, K ) - ZDOTU( K-1, WORK, 1, A( 1, K ),
269 A( K, K+1 ) = A( K, K+1 ) -
270 $ ZDOTU( K-1, A( 1, K ), 1, A( 1, K+1 ), 1 )
271 CALL ZCOPY( K-1, A( 1, K+1 ), 1, WORK, 1 )
272 CALL ZSYMV( UPLO, K-1, -CONE, A, LDA, WORK, 1, CZERO,
274 A( K+1, K+1 ) = A( K+1, K+1 ) -
275 $ ZDOTU( K-1, WORK, 1, A( 1, K+1 ), 1 )
280 IF( KSTEP.EQ.1 ) THEN
282 * Interchange rows and columns K and IPIV(K) in the leading
283 * submatrix A(1:k+1,1:k+1)
288 $ CALL ZSWAP( KP-1, A( 1, K ), 1, A( 1, KP ), 1 )
289 CALL ZSWAP( K-KP-1, A( KP+1, K ), 1, A( KP, KP+1 ), LDA )
291 A( K, K ) = A( KP, KP )
296 * Interchange rows and columns K and K+1 with -IPIV(K) and
297 * -IPIV(K+1)in the leading submatrix A(1:k+1,1:k+1)
302 $ CALL ZSWAP( KP-1, A( 1, K ), 1, A( 1, KP ), 1 )
303 CALL ZSWAP( K-KP-1, A( KP+1, K ), 1, A( KP, KP+1 ), LDA )
306 A( K, K ) = A( KP, KP )
309 A( K, K+1 ) = A( KP, K+1 )
317 $ CALL ZSWAP( KP-1, A( 1, K ), 1, A( 1, KP ), 1 )
318 CALL ZSWAP( K-KP-1, A( KP+1, K ), 1, A( KP, KP+1 ), LDA )
320 A( K, K ) = A( KP, KP )
331 * Compute inv(A) from the factorization A = L*D*L**T.
333 * K is the main loop index, increasing from 1 to N in steps of
334 * 1 or 2, depending on the size of the diagonal blocks.
339 * If K < 1, exit from loop.
344 IF( IPIV( K ).GT.0 ) THEN
346 * 1 x 1 diagonal block
348 * Invert the diagonal block.
350 A( K, K ) = CONE / A( K, K )
352 * Compute column K of the inverse.
355 CALL ZCOPY( N-K, A( K+1, K ), 1, WORK, 1 )
356 CALL ZSYMV( UPLO, N-K,-CONE, A( K+1, K+1 ), LDA, WORK, 1,
357 $ CZERO, A( K+1, K ), 1 )
358 A( K, K ) = A( K, K ) - ZDOTU( N-K, WORK, 1, A( K+1, K ),
364 * 2 x 2 diagonal block
366 * Invert the diagonal block.
369 AK = A( K-1, K-1 ) / T
371 AKKP1 = A( K, K-1 ) / T
372 D = T*( AK*AKP1-CONE )
373 A( K-1, K-1 ) = AKP1 / D
375 A( K, K-1 ) = -AKKP1 / D
377 * Compute columns K-1 and K of the inverse.
380 CALL ZCOPY( N-K, A( K+1, K ), 1, WORK, 1 )
381 CALL ZSYMV( UPLO, N-K,-CONE, A( K+1, K+1 ), LDA, WORK, 1,
382 $ CZERO, A( K+1, K ), 1 )
383 A( K, K ) = A( K, K ) - ZDOTU( N-K, WORK, 1, A( K+1, K ),
385 A( K, K-1 ) = A( K, K-1 ) -
386 $ ZDOTU( N-K, A( K+1, K ), 1, A( K+1, K-1 ),
388 CALL ZCOPY( N-K, A( K+1, K-1 ), 1, WORK, 1 )
389 CALL ZSYMV( UPLO, N-K,-CONE, A( K+1, K+1 ), LDA, WORK, 1,
390 $ CZERO, A( K+1, K-1 ), 1 )
391 A( K-1, K-1 ) = A( K-1, K-1 ) -
392 $ ZDOTU( N-K, WORK, 1, A( K+1, K-1 ), 1 )
397 IF( KSTEP.EQ.1 ) THEN
399 * Interchange rows and columns K and IPIV(K) in the trailing
400 * submatrix A(k-1:n,k-1:n)
405 $ CALL ZSWAP( N-KP, A( KP+1, K ), 1, A( KP+1, KP ), 1 )
406 CALL ZSWAP( KP-K-1, A( K+1, K ), 1, A( KP, K+1 ), LDA )
408 A( K, K ) = A( KP, KP )
413 * Interchange rows and columns K and K-1 with -IPIV(K) and
414 * -IPIV(K-1) in the trailing submatrix A(k-1:n,k-1:n)
419 $ CALL ZSWAP( N-KP, A( KP+1, K ), 1, A( KP+1, KP ), 1 )
420 CALL ZSWAP( KP-K-1, A( K+1, K ), 1, A( KP, K+1 ), LDA )
423 A( K, K ) = A( KP, KP )
426 A( K, K-1 ) = A( KP, K-1 )
434 $ CALL ZSWAP( N-KP, A( KP+1, K ), 1, A( KP+1, KP ), 1 )
435 CALL ZSWAP( KP-K-1, A( K+1, K ), 1, A( KP, K+1 ), LDA )
437 A( K, K ) = A( KP, KP )