1 *> \brief \b SSYTRI_ROOK
3 * =========== DOCUMENTATION ===========
5 * Online html documentation available at
6 * http://www.netlib.org/lapack/explore-html/
9 *> Download SSYTRI_ROOK + dependencies
10 *> <a href="http://www.netlib.org/cgi-bin/netlibfiles.tgz?format=tgz&filename=/lapack/lapack_routine/ssytri_rook.f">
12 *> <a href="http://www.netlib.org/cgi-bin/netlibfiles.zip?format=zip&filename=/lapack/lapack_routine/ssytri_rook.f">
14 *> <a href="http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/ssytri_rook.f">
21 * SUBROUTINE SSYTRI_ROOK( UPLO, N, A, LDA, IPIV, WORK, INFO )
23 * .. Scalar Arguments ..
25 * INTEGER INFO, LDA, N
27 * .. Array Arguments ..
29 * REAL A( LDA, * ), WORK( * )
38 *> SSYTRI_ROOK computes the inverse of a real symmetric
39 *> matrix A using the factorization A = U*D*U**T or A = L*D*L**T
40 *> computed by SSYTRF_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 REAL 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 SSYTRF_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 SSYTRF_ROOK.
90 *> WORK is REAL 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
112 *> \ingroup realSYcomputational
114 *> \par Contributors:
119 *> April 2012, 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 SSYTRI_ROOK( UPLO, N, A, LDA, IPIV, WORK, INFO )
132 * -- LAPACK computational routine (version 3.4.1) --
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 REAL A( LDA, * ), WORK( * )
146 * =====================================================================
150 PARAMETER ( ONE = 1.0E+0, ZERO = 0.0E+0 )
152 * .. Local Scalars ..
155 REAL AK, AKKP1, AKP1, D, T, TEMP
157 * .. External Functions ..
162 * .. External Subroutines ..
163 EXTERNAL SCOPY, SSWAP, SSYMV, XERBLA
165 * .. Intrinsic Functions ..
168 * .. Executable Statements ..
170 * Test the input parameters.
173 UPPER = LSAME( UPLO, 'U' )
174 IF( .NOT.UPPER .AND. .NOT.LSAME( UPLO, 'L' ) ) THEN
176 ELSE IF( N.LT.0 ) THEN
178 ELSE IF( LDA.LT.MAX( 1, N ) ) THEN
182 CALL XERBLA( 'SSYTRI_ROOK', -INFO )
186 * Quick return if possible
191 * Check that the diagonal matrix D is nonsingular.
195 * Upper triangular storage: examine D from bottom to top
197 DO 10 INFO = N, 1, -1
198 IF( IPIV( INFO ).GT.0 .AND. A( INFO, INFO ).EQ.ZERO )
203 * Lower triangular storage: examine D from top to bottom.
206 IF( IPIV( INFO ).GT.0 .AND. A( INFO, INFO ).EQ.ZERO )
214 * Compute inv(A) from the factorization A = U*D*U**T.
216 * K is the main loop index, increasing from 1 to N in steps of
217 * 1 or 2, depending on the size of the diagonal blocks.
222 * If K > N, exit from loop.
227 IF( IPIV( K ).GT.0 ) THEN
229 * 1 x 1 diagonal block
231 * Invert the diagonal block.
233 A( K, K ) = ONE / A( K, K )
235 * Compute column K of the inverse.
238 CALL SCOPY( K-1, A( 1, K ), 1, WORK, 1 )
239 CALL SSYMV( UPLO, K-1, -ONE, A, LDA, WORK, 1, ZERO,
241 A( K, K ) = A( K, K ) - SDOT( K-1, WORK, 1, A( 1, K ),
247 * 2 x 2 diagonal block
249 * Invert the diagonal block.
251 T = ABS( A( K, K+1 ) )
253 AKP1 = A( K+1, K+1 ) / T
254 AKKP1 = A( K, K+1 ) / T
255 D = T*( AK*AKP1-ONE )
257 A( K+1, K+1 ) = AK / D
258 A( K, K+1 ) = -AKKP1 / D
260 * Compute columns K and K+1 of the inverse.
263 CALL SCOPY( K-1, A( 1, K ), 1, WORK, 1 )
264 CALL SSYMV( UPLO, K-1, -ONE, A, LDA, WORK, 1, ZERO,
266 A( K, K ) = A( K, K ) - SDOT( K-1, WORK, 1, A( 1, K ),
268 A( K, K+1 ) = A( K, K+1 ) -
269 $ SDOT( K-1, A( 1, K ), 1, A( 1, K+1 ), 1 )
270 CALL SCOPY( K-1, A( 1, K+1 ), 1, WORK, 1 )
271 CALL SSYMV( UPLO, K-1, -ONE, A, LDA, WORK, 1, ZERO,
273 A( K+1, K+1 ) = A( K+1, K+1 ) -
274 $ SDOT( K-1, WORK, 1, A( 1, K+1 ), 1 )
279 IF( KSTEP.EQ.1 ) THEN
281 * Interchange rows and columns K and IPIV(K) in the leading
282 * submatrix A(1:k+1,1:k+1)
287 $ CALL SSWAP( KP-1, A( 1, K ), 1, A( 1, KP ), 1 )
288 CALL SSWAP( K-KP-1, A( KP+1, K ), 1, A( KP, KP+1 ), LDA )
290 A( K, K ) = A( KP, KP )
295 * Interchange rows and columns K and K+1 with -IPIV(K) and
296 * -IPIV(K+1)in the leading submatrix A(1:k+1,1:k+1)
301 $ CALL SSWAP( KP-1, A( 1, K ), 1, A( 1, KP ), 1 )
302 CALL SSWAP( K-KP-1, A( KP+1, K ), 1, A( KP, KP+1 ), LDA )
305 A( K, K ) = A( KP, KP )
308 A( K, K+1 ) = A( KP, K+1 )
316 $ CALL SSWAP( KP-1, A( 1, K ), 1, A( 1, KP ), 1 )
317 CALL SSWAP( K-KP-1, A( KP+1, K ), 1, A( KP, KP+1 ), LDA )
319 A( K, K ) = A( KP, KP )
330 * Compute inv(A) from the factorization A = L*D*L**T.
332 * K is the main loop index, increasing from 1 to N in steps of
333 * 1 or 2, depending on the size of the diagonal blocks.
338 * If K < 1, exit from loop.
343 IF( IPIV( K ).GT.0 ) THEN
345 * 1 x 1 diagonal block
347 * Invert the diagonal block.
349 A( K, K ) = ONE / A( K, K )
351 * Compute column K of the inverse.
354 CALL SCOPY( N-K, A( K+1, K ), 1, WORK, 1 )
355 CALL SSYMV( UPLO, N-K, -ONE, A( K+1, K+1 ), LDA, WORK, 1,
356 $ ZERO, A( K+1, K ), 1 )
357 A( K, K ) = A( K, K ) - SDOT( N-K, WORK, 1, A( K+1, K ),
363 * 2 x 2 diagonal block
365 * Invert the diagonal block.
367 T = ABS( A( K, K-1 ) )
368 AK = A( K-1, K-1 ) / T
370 AKKP1 = A( K, K-1 ) / T
371 D = T*( AK*AKP1-ONE )
372 A( K-1, K-1 ) = AKP1 / D
374 A( K, K-1 ) = -AKKP1 / D
376 * Compute columns K-1 and K of the inverse.
379 CALL SCOPY( N-K, A( K+1, K ), 1, WORK, 1 )
380 CALL SSYMV( UPLO, N-K, -ONE, A( K+1, K+1 ), LDA, WORK, 1,
381 $ ZERO, A( K+1, K ), 1 )
382 A( K, K ) = A( K, K ) - SDOT( N-K, WORK, 1, A( K+1, K ),
384 A( K, K-1 ) = A( K, K-1 ) -
385 $ SDOT( N-K, A( K+1, K ), 1, A( K+1, K-1 ),
387 CALL SCOPY( N-K, A( K+1, K-1 ), 1, WORK, 1 )
388 CALL SSYMV( UPLO, N-K, -ONE, A( K+1, K+1 ), LDA, WORK, 1,
389 $ ZERO, A( K+1, K-1 ), 1 )
390 A( K-1, K-1 ) = A( K-1, K-1 ) -
391 $ SDOT( N-K, WORK, 1, A( K+1, K-1 ), 1 )
396 IF( KSTEP.EQ.1 ) THEN
398 * Interchange rows and columns K and IPIV(K) in the trailing
399 * submatrix A(k-1:n,k-1:n)
404 $ CALL SSWAP( N-KP, A( KP+1, K ), 1, A( KP+1, KP ), 1 )
405 CALL SSWAP( KP-K-1, A( K+1, K ), 1, A( KP, K+1 ), LDA )
407 A( K, K ) = A( KP, KP )
412 * Interchange rows and columns K and K-1 with -IPIV(K) and
413 * -IPIV(K-1) in the trailing submatrix A(k-1:n,k-1:n)
418 $ CALL SSWAP( N-KP, A( KP+1, K ), 1, A( KP+1, KP ), 1 )
419 CALL SSWAP( KP-K-1, A( K+1, K ), 1, A( KP, K+1 ), LDA )
422 A( K, K ) = A( KP, KP )
425 A( K, K-1 ) = A( KP, K-1 )
433 $ CALL SSWAP( N-KP, A( KP+1, K ), 1, A( KP+1, KP ), 1 )
434 CALL SSWAP( KP-K-1, A( K+1, K ), 1, A( KP, K+1 ), LDA )
436 A( K, K ) = A( KP, KP )