LAPACK 3.12.1
LAPACK: Linear Algebra PACKage
Loading...
Searching...
No Matches
csytri_rook.f
Go to the documentation of this file.
1*> \brief \b CSYTRI_ROOK
2*
3* =========== DOCUMENTATION ===========
4*
5* Online html documentation available at
6* http://www.netlib.org/lapack/explore-html/
7*
8*> Download CSYTRI_ROOK + dependencies
9*> <a href="http://www.netlib.org/cgi-bin/netlibfiles.tgz?format=tgz&filename=/lapack/lapack_routine/csytri_rook.f">
10*> [TGZ]</a>
11*> <a href="http://www.netlib.org/cgi-bin/netlibfiles.zip?format=zip&filename=/lapack/lapack_routine/csytri_rook.f">
12*> [ZIP]</a>
13*> <a href="http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/csytri_rook.f">
14*> [TXT]</a>
15*
16* Definition:
17* ===========
18*
19* SUBROUTINE CSYTRI_ROOK( UPLO, N, A, LDA, IPIV, WORK, INFO )
20*
21* .. Scalar Arguments ..
22* CHARACTER UPLO
23* INTEGER INFO, LDA, N
24* ..
25* .. Array Arguments ..
26* INTEGER IPIV( * )
27* COMPLEX A( LDA, * ), WORK( * )
28* ..
29*
30*
31*> \par Purpose:
32* =============
33*>
34*> \verbatim
35*>
36*> CSYTRI_ROOK computes the inverse of a complex symmetric
37*> matrix A using the factorization A = U*D*U**T or A = L*D*L**T
38*> computed by CSYTRF_ROOK.
39*> \endverbatim
40*
41* Arguments:
42* ==========
43*
44*> \param[in] UPLO
45*> \verbatim
46*> UPLO is CHARACTER*1
47*> Specifies whether the details of the factorization are stored
48*> as an upper or lower triangular matrix.
49*> = 'U': Upper triangular, form is A = U*D*U**T;
50*> = 'L': Lower triangular, form is A = L*D*L**T.
51*> \endverbatim
52*>
53*> \param[in] N
54*> \verbatim
55*> N is INTEGER
56*> The order of the matrix A. N >= 0.
57*> \endverbatim
58*>
59*> \param[in,out] A
60*> \verbatim
61*> A is COMPLEX array, dimension (LDA,N)
62*> On entry, the block diagonal matrix D and the multipliers
63*> used to obtain the factor U or L as computed by CSYTRF_ROOK.
64*>
65*> On exit, if INFO = 0, the (symmetric) inverse of the original
66*> matrix. If UPLO = 'U', the upper triangular part of the
67*> inverse is formed and the part of A below the diagonal is not
68*> referenced; if UPLO = 'L' the lower triangular part of the
69*> inverse is formed and the part of A above the diagonal is
70*> not referenced.
71*> \endverbatim
72*>
73*> \param[in] LDA
74*> \verbatim
75*> LDA is INTEGER
76*> The leading dimension of the array A. LDA >= max(1,N).
77*> \endverbatim
78*>
79*> \param[in] IPIV
80*> \verbatim
81*> IPIV is INTEGER array, dimension (N)
82*> Details of the interchanges and the block structure of D
83*> as determined by CSYTRF_ROOK.
84*> \endverbatim
85*>
86*> \param[out] WORK
87*> \verbatim
88*> WORK is COMPLEX array, dimension (N)
89*> \endverbatim
90*>
91*> \param[out] INFO
92*> \verbatim
93*> INFO is INTEGER
94*> = 0: successful exit
95*> < 0: if INFO = -i, the i-th argument had an illegal value
96*> > 0: if INFO = i, D(i,i) = 0; the matrix is singular and its
97*> inverse could not be computed.
98*> \endverbatim
99*
100* Authors:
101* ========
102*
103*> \author Univ. of Tennessee
104*> \author Univ. of California Berkeley
105*> \author Univ. of Colorado Denver
106*> \author NAG Ltd.
107*
108*> \ingroup hetri_rook
109*
110*> \par Contributors:
111* ==================
112*>
113*> \verbatim
114*>
115*> December 2016, Igor Kozachenko,
116*> Computer Science Division,
117*> University of California, Berkeley
118*>
119*> September 2007, Sven Hammarling, Nicholas J. Higham, Craig Lucas,
120*> School of Mathematics,
121*> University of Manchester
122*>
123*> \endverbatim
124*
125* =====================================================================
126 SUBROUTINE csytri_rook( UPLO, N, A, LDA, IPIV, WORK, INFO )
127*
128* -- LAPACK computational routine --
129* -- LAPACK is a software package provided by Univ. of Tennessee, --
130* -- Univ. of California Berkeley, Univ. of Colorado Denver and NAG Ltd..--
131*
132* .. Scalar Arguments ..
133 CHARACTER UPLO
134 INTEGER INFO, LDA, N
135* ..
136* .. Array Arguments ..
137 INTEGER IPIV( * )
138 COMPLEX A( LDA, * ), WORK( * )
139* ..
140*
141* =====================================================================
142*
143* .. Parameters ..
144 COMPLEX CONE, CZERO
145 parameter( cone = ( 1.0e+0, 0.0e+0 ),
146 $ czero = ( 0.0e+0, 0.0e+0 ) )
147* ..
148* .. Local Scalars ..
149 LOGICAL UPPER
150 INTEGER K, KP, KSTEP
151 COMPLEX AK, AKKP1, AKP1, D, T, TEMP
152* ..
153* .. External Functions ..
154 LOGICAL LSAME
155 COMPLEX CDOTU
156 EXTERNAL lsame, cdotu
157* ..
158* .. External Subroutines ..
159 EXTERNAL ccopy, cswap, csymv, xerbla
160* ..
161* .. Intrinsic Functions ..
162 INTRINSIC max
163* ..
164* .. Executable Statements ..
165*
166* Test the input parameters.
167*
168 info = 0
169 upper = lsame( uplo, 'U' )
170 IF( .NOT.upper .AND. .NOT.lsame( uplo, 'L' ) ) THEN
171 info = -1
172 ELSE IF( n.LT.0 ) THEN
173 info = -2
174 ELSE IF( lda.LT.max( 1, n ) ) THEN
175 info = -4
176 END IF
177 IF( info.NE.0 ) THEN
178 CALL xerbla( 'CSYTRI_ROOK', -info )
179 RETURN
180 END IF
181*
182* Quick return if possible
183*
184 IF( n.EQ.0 )
185 $ RETURN
186*
187* Check that the diagonal matrix D is nonsingular.
188*
189 IF( upper ) THEN
190*
191* Upper triangular storage: examine D from bottom to top
192*
193 DO 10 info = n, 1, -1
194 IF( ipiv( info ).GT.0 .AND. a( info, info ).EQ.czero )
195 $ RETURN
196 10 CONTINUE
197 ELSE
198*
199* Lower triangular storage: examine D from top to bottom.
200*
201 DO 20 info = 1, n
202 IF( ipiv( info ).GT.0 .AND. a( info, info ).EQ.czero )
203 $ RETURN
204 20 CONTINUE
205 END IF
206 info = 0
207*
208 IF( upper ) THEN
209*
210* Compute inv(A) from the factorization A = U*D*U**T.
211*
212* K is the main loop index, increasing from 1 to N in steps of
213* 1 or 2, depending on the size of the diagonal blocks.
214*
215 k = 1
216 30 CONTINUE
217*
218* If K > N, exit from loop.
219*
220 IF( k.GT.n )
221 $ GO TO 40
222*
223 IF( ipiv( k ).GT.0 ) THEN
224*
225* 1 x 1 diagonal block
226*
227* Invert the diagonal block.
228*
229 a( k, k ) = cone / a( k, k )
230*
231* Compute column K of the inverse.
232*
233 IF( k.GT.1 ) THEN
234 CALL ccopy( k-1, a( 1, k ), 1, work, 1 )
235 CALL csymv( uplo, k-1, -cone, a, lda, work, 1, czero,
236 $ a( 1, k ), 1 )
237 a( k, k ) = a( k, k ) - cdotu( k-1, work, 1, a( 1,
238 $ k ),
239 $ 1 )
240 END IF
241 kstep = 1
242 ELSE
243*
244* 2 x 2 diagonal block
245*
246* Invert the diagonal block.
247*
248 t = a( k, k+1 )
249 ak = a( k, k ) / t
250 akp1 = a( k+1, k+1 ) / t
251 akkp1 = a( k, k+1 ) / t
252 d = t*( ak*akp1-cone )
253 a( k, k ) = akp1 / d
254 a( k+1, k+1 ) = ak / d
255 a( k, k+1 ) = -akkp1 / d
256*
257* Compute columns K and K+1 of the inverse.
258*
259 IF( k.GT.1 ) THEN
260 CALL ccopy( k-1, a( 1, k ), 1, work, 1 )
261 CALL csymv( uplo, k-1, -cone, a, lda, work, 1, czero,
262 $ a( 1, k ), 1 )
263 a( k, k ) = a( k, k ) - cdotu( k-1, work, 1, a( 1,
264 $ k ),
265 $ 1 )
266 a( k, k+1 ) = a( k, k+1 ) -
267 $ cdotu( k-1, a( 1, k ), 1, a( 1, k+1 ),
268 $ 1 )
269 CALL ccopy( k-1, a( 1, k+1 ), 1, work, 1 )
270 CALL csymv( uplo, k-1, -cone, a, lda, work, 1, czero,
271 $ a( 1, k+1 ), 1 )
272 a( k+1, k+1 ) = a( k+1, k+1 ) -
273 $ cdotu( k-1, work, 1, a( 1, k+1 ), 1 )
274 END IF
275 kstep = 2
276 END IF
277*
278 IF( kstep.EQ.1 ) THEN
279*
280* Interchange rows and columns K and IPIV(K) in the leading
281* submatrix A(1:k+1,1:k+1)
282*
283 kp = ipiv( k )
284 IF( kp.NE.k ) THEN
285 IF( kp.GT.1 )
286 $ CALL cswap( kp-1, a( 1, k ), 1, a( 1, kp ), 1 )
287 CALL cswap( k-kp-1, a( kp+1, k ), 1, a( kp, kp+1 ),
288 $ lda )
289 temp = a( k, k )
290 a( k, k ) = a( kp, kp )
291 a( kp, kp ) = temp
292 END IF
293 ELSE
294*
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)
297*
298 kp = -ipiv( k )
299 IF( kp.NE.k ) THEN
300 IF( kp.GT.1 )
301 $ CALL cswap( kp-1, a( 1, k ), 1, a( 1, kp ), 1 )
302 CALL cswap( k-kp-1, a( kp+1, k ), 1, a( kp, kp+1 ),
303 $ lda )
304*
305 temp = a( k, k )
306 a( k, k ) = a( kp, kp )
307 a( kp, kp ) = temp
308 temp = a( k, k+1 )
309 a( k, k+1 ) = a( kp, k+1 )
310 a( kp, k+1 ) = temp
311 END IF
312*
313 k = k + 1
314 kp = -ipiv( k )
315 IF( kp.NE.k ) THEN
316 IF( kp.GT.1 )
317 $ CALL cswap( kp-1, a( 1, k ), 1, a( 1, kp ), 1 )
318 CALL cswap( k-kp-1, a( kp+1, k ), 1, a( kp, kp+1 ),
319 $ lda )
320 temp = a( k, k )
321 a( k, k ) = a( kp, kp )
322 a( kp, kp ) = temp
323 END IF
324 END IF
325*
326 k = k + 1
327 GO TO 30
328 40 CONTINUE
329*
330 ELSE
331*
332* Compute inv(A) from the factorization A = L*D*L**T.
333*
334* K is the main loop index, increasing from 1 to N in steps of
335* 1 or 2, depending on the size of the diagonal blocks.
336*
337 k = n
338 50 CONTINUE
339*
340* If K < 1, exit from loop.
341*
342 IF( k.LT.1 )
343 $ GO TO 60
344*
345 IF( ipiv( k ).GT.0 ) THEN
346*
347* 1 x 1 diagonal block
348*
349* Invert the diagonal block.
350*
351 a( k, k ) = cone / a( k, k )
352*
353* Compute column K of the inverse.
354*
355 IF( k.LT.n ) THEN
356 CALL ccopy( n-k, a( k+1, k ), 1, work, 1 )
357 CALL csymv( uplo, n-k,-cone, a( k+1, k+1 ), lda, work,
358 $ 1,
359 $ czero, a( k+1, k ), 1 )
360 a( k, k ) = a( k, k ) - cdotu( n-k, work, 1, a( k+1,
361 $ k ),
362 $ 1 )
363 END IF
364 kstep = 1
365 ELSE
366*
367* 2 x 2 diagonal block
368*
369* Invert the diagonal block.
370*
371 t = a( k, k-1 )
372 ak = a( k-1, k-1 ) / t
373 akp1 = a( k, k ) / t
374 akkp1 = a( k, k-1 ) / t
375 d = t*( ak*akp1-cone )
376 a( k-1, k-1 ) = akp1 / d
377 a( k, k ) = ak / d
378 a( k, k-1 ) = -akkp1 / d
379*
380* Compute columns K-1 and K of the inverse.
381*
382 IF( k.LT.n ) THEN
383 CALL ccopy( n-k, a( k+1, k ), 1, work, 1 )
384 CALL csymv( uplo, n-k,-cone, a( k+1, k+1 ), lda, work,
385 $ 1,
386 $ czero, a( k+1, k ), 1 )
387 a( k, k ) = a( k, k ) - cdotu( n-k, work, 1, a( k+1,
388 $ k ),
389 $ 1 )
390 a( k, k-1 ) = a( k, k-1 ) -
391 $ cdotu( n-k, a( k+1, k ), 1, a( k+1,
392 $ k-1 ),
393 $ 1 )
394 CALL ccopy( n-k, a( k+1, k-1 ), 1, work, 1 )
395 CALL csymv( uplo, n-k,-cone, a( k+1, k+1 ), lda, work,
396 $ 1,
397 $ czero, a( k+1, k-1 ), 1 )
398 a( k-1, k-1 ) = a( k-1, k-1 ) -
399 $ cdotu( n-k, work, 1, a( k+1, k-1 ),
400 $ 1 )
401 END IF
402 kstep = 2
403 END IF
404*
405 IF( kstep.EQ.1 ) THEN
406*
407* Interchange rows and columns K and IPIV(K) in the trailing
408* submatrix A(k-1:n,k-1:n)
409*
410 kp = ipiv( k )
411 IF( kp.NE.k ) THEN
412 IF( kp.LT.n )
413 $ CALL cswap( n-kp, a( kp+1, k ), 1, a( kp+1, kp ),
414 $ 1 )
415 CALL cswap( kp-k-1, a( k+1, k ), 1, a( kp, k+1 ),
416 $ lda )
417 temp = a( k, k )
418 a( k, k ) = a( kp, kp )
419 a( kp, kp ) = temp
420 END IF
421 ELSE
422*
423* Interchange rows and columns K and K-1 with -IPIV(K) and
424* -IPIV(K-1) in the trailing submatrix A(k-1:n,k-1:n)
425*
426 kp = -ipiv( k )
427 IF( kp.NE.k ) THEN
428 IF( kp.LT.n )
429 $ CALL cswap( n-kp, a( kp+1, k ), 1, a( kp+1, kp ),
430 $ 1 )
431 CALL cswap( kp-k-1, a( k+1, k ), 1, a( kp, k+1 ),
432 $ lda )
433*
434 temp = a( k, k )
435 a( k, k ) = a( kp, kp )
436 a( kp, kp ) = temp
437 temp = a( k, k-1 )
438 a( k, k-1 ) = a( kp, k-1 )
439 a( kp, k-1 ) = temp
440 END IF
441*
442 k = k - 1
443 kp = -ipiv( k )
444 IF( kp.NE.k ) THEN
445 IF( kp.LT.n )
446 $ CALL cswap( n-kp, a( kp+1, k ), 1, a( kp+1, kp ),
447 $ 1 )
448 CALL cswap( kp-k-1, a( k+1, k ), 1, a( kp, k+1 ),
449 $ lda )
450 temp = a( k, k )
451 a( k, k ) = a( kp, kp )
452 a( kp, kp ) = temp
453 END IF
454 END IF
455*
456 k = k - 1
457 GO TO 50
458 60 CONTINUE
459 END IF
460*
461 RETURN
462*
463* End of CSYTRI_ROOK
464*
465 END
subroutine xerbla(srname, info)
Definition cblat2.f:3285
subroutine ccopy(n, cx, incx, cy, incy)
CCOPY
Definition ccopy.f:81
subroutine csymv(uplo, n, alpha, a, lda, x, incx, beta, y, incy)
CSYMV computes a matrix-vector product for a complex symmetric matrix.
Definition csymv.f:156
subroutine csytri_rook(uplo, n, a, lda, ipiv, work, info)
CSYTRI_ROOK
subroutine cswap(n, cx, incx, cy, incy)
CSWAP
Definition cswap.f:81