OpenRadioss 2025.1.11
OpenRadioss project
Loading...
Searching...
No Matches
chetri2x.f
Go to the documentation of this file.
1*> \brief \b CHETRI2X
2*
3* =========== DOCUMENTATION ===========
4*
5* Online html documentation available at
6* http://www.netlib.org/lapack/explore-html/
7*
8*> \htmlonly
9*> Download CHETRI2X + dependencies
10*> <a href="http://www.netlib.org/cgi-bin/netlibfiles.tgz?format=tgz&filename=/lapack/lapack_routine/chetri2x.f">
11*> [TGZ]</a>
12*> <a href="http://www.netlib.org/cgi-bin/netlibfiles.zip?format=zip&filename=/lapack/lapack_routine/chetri2x.f">
13*> [ZIP]</a>
14*> <a href="http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/chetri2x.f">
15*> [TXT]</a>
16*> \endhtmlonly
17*
18* Definition:
19* ===========
20*
21* SUBROUTINE CHETRI2X( UPLO, N, A, LDA, IPIV, WORK, NB, INFO )
22*
23* .. Scalar Arguments ..
24* CHARACTER UPLO
25* INTEGER INFO, LDA, N, NB
26* ..
27* .. Array Arguments ..
28* INTEGER IPIV( * )
29* COMPLEX A( LDA, * ), WORK( N+NB+1,* )
30* ..
31*
32*
33*> \par Purpose:
34* =============
35*>
36*> \verbatim
37*>
38*> CHETRI2X computes the inverse of a complex Hermitian indefinite matrix
39*> A using the factorization A = U*D*U**H or A = L*D*L**H computed by
40*> CHETRF.
41*> \endverbatim
42*
43* Arguments:
44* ==========
45*
46*> \param[in] UPLO
47*> \verbatim
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**H;
52*> = 'L': Lower triangular, form is A = L*D*L**H.
53*> \endverbatim
54*>
55*> \param[in] N
56*> \verbatim
57*> N is INTEGER
58*> The order of the matrix A. N >= 0.
59*> \endverbatim
60*>
61*> \param[in,out] A
62*> \verbatim
63*> A is COMPLEX array, dimension (LDA,N)
64*> On entry, the NNB diagonal matrix D and the multipliers
65*> used to obtain the factor U or L as computed by CHETRF.
66*>
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
72*> not referenced.
73*> \endverbatim
74*>
75*> \param[in] LDA
76*> \verbatim
77*> LDA is INTEGER
78*> The leading dimension of the array A. LDA >= max(1,N).
79*> \endverbatim
80*>
81*> \param[in] IPIV
82*> \verbatim
83*> IPIV is INTEGER array, dimension (N)
84*> Details of the interchanges and the NNB structure of D
85*> as determined by CHETRF.
86*> \endverbatim
87*>
88*> \param[out] WORK
89*> \verbatim
90*> WORK is COMPLEX array, dimension (N+NB+1,NB+3)
91*> \endverbatim
92*>
93*> \param[in] NB
94*> \verbatim
95*> NB is INTEGER
96*> Block size
97*> \endverbatim
98*>
99*> \param[out] INFO
100*> \verbatim
101*> INFO is INTEGER
102*> = 0: successful exit
103*> < 0: if INFO = -i, the i-th argument had an illegal value
104*> > 0: if INFO = i, D(i,i) = 0; the matrix is singular and its
105*> inverse could not be computed.
106*> \endverbatim
107*
108* Authors:
109* ========
110*
111*> \author Univ. of Tennessee
112*> \author Univ. of California Berkeley
113*> \author Univ. of Colorado Denver
114*> \author NAG Ltd.
115*
116*> \ingroup complexHEcomputational
117*
118* =====================================================================
119 SUBROUTINE chetri2x( UPLO, N, A, LDA, IPIV, WORK, NB, INFO )
120*
121* -- LAPACK computational routine --
122* -- LAPACK is a software package provided by Univ. of Tennessee, --
123* -- Univ. of California Berkeley, Univ. of Colorado Denver and NAG Ltd..--
124*
125* .. Scalar Arguments ..
126 CHARACTER UPLO
127 INTEGER INFO, LDA, N, NB
128* ..
129* .. Array Arguments ..
130 INTEGER IPIV( * )
131 COMPLEX A( LDA, * ), WORK( N+NB+1,* )
132* ..
133*
134* =====================================================================
135*
136* .. Parameters ..
137 REAL ONE
138 COMPLEX CONE, ZERO
139 parameter( one = 1.0e+0,
140 $ cone = ( 1.0e+0, 0.0e+0 ),
141 $ zero = ( 0.0e+0, 0.0e+0 ) )
142* ..
143* .. Local Scalars ..
144 LOGICAL UPPER
145 INTEGER I, IINFO, IP, K, CUT, NNB
146 INTEGER COUNT
147 INTEGER J, U11, INVD
148
149 COMPLEX AK, AKKP1, AKP1, D, T
150 COMPLEX U01_I_J, U01_IP1_J
151 COMPLEX U11_I_J, U11_IP1_J
152* ..
153* .. External Functions ..
154 LOGICAL LSAME
155 EXTERNAL lsame
156* ..
157* .. External Subroutines ..
158 EXTERNAL csyconv, xerbla, ctrtri
159 EXTERNAL cgemm, ctrmm, cheswapr
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*
178* Quick return if possible
179*
180*
181 IF( info.NE.0 ) THEN
182 CALL xerbla( 'CHETRI2X', -info )
183 RETURN
184 END IF
185 IF( n.EQ.0 )
186 $ RETURN
187*
188* Convert A
189* Workspace got Non-diag elements of D
190*
191 CALL csyconv( uplo, 'C', n, a, lda, ipiv, work, iinfo )
192*
193* Check that the diagonal matrix D is nonsingular.
194*
195 IF( upper ) THEN
196*
197* Upper triangular storage: examine D from bottom to top
198*
199 DO info = n, 1, -1
200 IF( ipiv( info ).GT.0 .AND. a( info, info ).EQ.zero )
201 $ RETURN
202 END DO
203 ELSE
204*
205* Lower triangular storage: examine D from top to bottom.
206*
207 DO info = 1, n
208 IF( ipiv( info ).GT.0 .AND. a( info, info ).EQ.zero )
209 $ RETURN
210 END DO
211 END IF
212 info = 0
213*
214* Splitting Workspace
215* U01 is a block (N,NB+1)
216* The first element of U01 is in WORK(1,1)
217* U11 is a block (NB+1,NB+1)
218* The first element of U11 is in WORK(N+1,1)
219 u11 = n
220* INVD is a block (N,2)
221* The first element of INVD is in WORK(1,INVD)
222 invd = nb+2
223
224 IF( upper ) THEN
225*
226* invA = P * inv(U**H)*inv(D)*inv(U)*P**H.
227*
228 CALL ctrtri( uplo, 'u', N, A, LDA, INFO )
229*
230* inv(D) and inv(D)*inv(U)
231*
232 K=1
233.LE. DO WHILE ( K N )
234.GT. IF( IPIV( K )0 ) THEN
235* 1 x 1 diagonal NNB
236 WORK(K,INVD) = ONE / REAL ( A( K, K ) )
237 WORK(K,INVD+1) = 0
238 K=K+1
239 ELSE
240* 2 x 2 diagonal NNB
241 T = ABS ( WORK(K+1,1) )
242 AK = REAL ( A( K, K ) ) / T
243 AKP1 = REAL ( A( K+1, K+1 ) ) / T
244 AKKP1 = WORK(K+1,1) / T
245 D = T*( AK*AKP1-ONE )
246 WORK(K,INVD) = AKP1 / D
247 WORK(K+1,INVD+1) = AK / D
248 WORK(K,INVD+1) = -AKKP1 / D
249 WORK(K+1,INVD) = CONJG (WORK(K,INVD+1) )
250 K=K+2
251 END IF
252 END DO
253*
254* inv(U**H) = (inv(U))**H
255*
256* inv(U**H)*inv(D)*inv(U)
257*
258 CUT=N
259.GT. DO WHILE (CUT 0)
260 NNB=NB
261.LE. IF (CUT NNB) THEN
262 NNB=CUT
263 ELSE
264 COUNT = 0
265* count negative elements,
266 DO I=CUT+1-NNB,CUT
267.LT. IF (IPIV(I) 0) COUNT=COUNT+1
268 END DO
269* need a even number for a clear cut
270.EQ. IF (MOD(COUNT,2) 1) NNB=NNB+1
271 END IF
272
273 CUT=CUT-NNB
274*
275* U01 Block
276*
277 DO I=1,CUT
278 DO J=1,NNB
279 WORK(I,J)=A(I,CUT+J)
280 END DO
281 END DO
282*
283* U11 Block
284*
285 DO I=1,NNB
286 WORK(U11+I,I)=CONE
287 DO J=1,I-1
288 WORK(U11+I,J)=ZERO
289 END DO
290 DO J=I+1,NNB
291 WORK(U11+I,J)=A(CUT+I,CUT+J)
292 END DO
293 END DO
294*
295* invD*U01
296*
297 I=1
298.LE. DO WHILE (I CUT)
299 IF (IPIV(I) > 0) THEN
300 DO J=1,NNB
301 WORK(I,J)=WORK(I,INVD)*WORK(I,J)
302 END DO
303 I=I+1
304 ELSE
305 DO J=1,NNB
306 U01_I_J = WORK(I,J)
307 U01_IP1_J = WORK(I+1,J)
308 WORK(I,J)=WORK(I,INVD)*U01_I_J+
309 $ WORK(I,INVD+1)*U01_IP1_J
310 WORK(I+1,J)=WORK(I+1,INVD)*U01_I_J+
311 $ WORK(I+1,INVD+1)*U01_IP1_J
312 END DO
313 I=I+2
314 END IF
315 END DO
316*
317* invD1*U11
318*
319 I=1
320.LE. DO WHILE (I NNB)
321 IF (IPIV(CUT+I) > 0) THEN
322 DO J=I,NNB
323 WORK(U11+I,J)=WORK(CUT+I,INVD)*WORK(U11+I,J)
324 END DO
325 I=I+1
326 ELSE
327 DO J=I,NNB
328 U11_I_J = WORK(U11+I,J)
329 U11_IP1_J = WORK(U11+I+1,J)
330 WORK(U11+I,J)=WORK(CUT+I,INVD)*WORK(U11+I,J) +
331 $ WORK(CUT+I,INVD+1)*WORK(U11+I+1,J)
332 WORK(U11+I+1,J)=WORK(CUT+I+1,INVD)*U11_I_J+
333 $ WORK(CUT+I+1,INVD+1)*U11_IP1_J
334 END DO
335 I=I+2
336 END IF
337 END DO
338*
339* U11**H*invD1*U11->U11
340*
341 CALL CTRMM('l','u','c','u',NNB, NNB,
342 $ CONE,A(CUT+1,CUT+1),LDA,WORK(U11+1,1),N+NB+1)
343*
344 DO I=1,NNB
345 DO J=I,NNB
346 A(CUT+I,CUT+J)=WORK(U11+I,J)
347 END DO
348 END DO
349*
350* U01**H*invD*U01->A(CUT+I,CUT+J)
351*
352 CALL CGEMM('c','n',NNB,NNB,CUT,CONE,A(1,CUT+1),LDA,
353 $ WORK,N+NB+1, ZERO, WORK(U11+1,1), N+NB+1)
354*
355* U11 = U11**H*invD1*U11 + U01**H*invD*U01
356*
357 DO I=1,NNB
358 DO J=I,NNB
359 A(CUT+I,CUT+J)=A(CUT+I,CUT+J)+WORK(U11+I,J)
360 END DO
361 END DO
362*
363* U01 = U00**H*invD0*U01
364*
365 CALL CTRMM('l',UPLO,'c','u',CUT, NNB,
366 $ CONE,A,LDA,WORK,N+NB+1)
367
368*
369* Update U01
370*
371 DO I=1,CUT
372 DO J=1,NNB
373 A(I,CUT+J)=WORK(I,J)
374 END DO
375 END DO
376*
377* Next Block
378*
379 END DO
380*
381* Apply PERMUTATIONS P and P**H: P * inv(U**H)*inv(D)*inv(U) *P**H
382*
383 I=1
384.LE. DO WHILE ( I N )
385.GT. IF( IPIV(I) 0 ) THEN
386 IP=IPIV(I)
387.LT. IF (I IP) CALL CHESWAPR( UPLO, N, A, LDA, I ,IP )
388.GT. IF (I IP) CALL CHESWAPR( UPLO, N, A, LDA, IP ,I )
389 ELSE
390 IP=-IPIV(I)
391 I=I+1
392.LT. IF ( (I-1) IP)
393 $ CALL CHESWAPR( UPLO, N, A, LDA, I-1 ,IP )
394.GT. IF ( (I-1) IP)
395 $ CALL CHESWAPR( UPLO, N, A, LDA, IP ,I-1 )
396 ENDIF
397 I=I+1
398 END DO
399 ELSE
400*
401* LOWER...
402*
403* invA = P * inv(U**H)*inv(D)*inv(U)*P**H.
404*
405 CALL CTRTRI( UPLO, 'u', N, A, LDA, INFO )
406*
407* inv(D) and inv(D)*inv(U)
408*
409 K=N
410.GE. DO WHILE ( K 1 )
411.GT. IF( IPIV( K )0 ) THEN
412* 1 x 1 diagonal NNB
413 WORK(K,INVD) = ONE / REAL ( A( K, K ) )
414 WORK(K,INVD+1) = 0
415 K=K-1
416 ELSE
417* 2 x 2 diagonal NNB
418 T = ABS ( WORK(K-1,1) )
419 AK = REAL ( A( K-1, K-1 ) ) / T
420 AKP1 = REAL ( A( K, K ) ) / T
421 AKKP1 = WORK(K-1,1) / T
422 D = T*( AK*AKP1-ONE )
423 WORK(K-1,INVD) = AKP1 / D
424 WORK(K,INVD) = AK / D
425 WORK(K,INVD+1) = -AKKP1 / D
426 WORK(K-1,INVD+1) = CONJG (WORK(K,INVD+1) )
427 K=K-2
428 END IF
429 END DO
430*
431* inv(U**H) = (inv(U))**H
432*
433* inv(U**H)*inv(D)*inv(U)
434*
435 CUT=0
436.LT. DO WHILE (CUT N)
437 NNB=NB
438.GE. IF (CUT + NNB N) THEN
439 NNB=N-CUT
440 ELSE
441 COUNT = 0
442* count negative elements,
443 DO I=CUT+1,CUT+NNB
444.LT. IF (IPIV(I) 0) COUNT=COUNT+1
445 END DO
446* need a even number for a clear cut
447.EQ. IF (MOD(COUNT,2) 1) NNB=NNB+1
448 END IF
449* L21 Block
450 DO I=1,N-CUT-NNB
451 DO J=1,NNB
452 WORK(I,J)=A(CUT+NNB+I,CUT+J)
453 END DO
454 END DO
455* L11 Block
456 DO I=1,NNB
457 WORK(U11+I,I)=CONE
458 DO J=I+1,NNB
459 WORK(U11+I,J)=ZERO
460 END DO
461 DO J=1,I-1
462 WORK(U11+I,J)=A(CUT+I,CUT+J)
463 END DO
464 END DO
465*
466* invD*L21
467*
468 I=N-CUT-NNB
469.GE. DO WHILE (I 1)
470 IF (IPIV(CUT+NNB+I) > 0) THEN
471 DO J=1,NNB
472 WORK(I,J)=WORK(CUT+NNB+I,INVD)*WORK(I,J)
473 END DO
474 I=I-1
475 ELSE
476 DO J=1,NNB
477 U01_I_J = WORK(I,J)
478 U01_IP1_J = WORK(I-1,J)
479 WORK(I,J)=WORK(CUT+NNB+I,INVD)*U01_I_J+
480 $ WORK(CUT+NNB+I,INVD+1)*U01_IP1_J
481 WORK(I-1,J)=WORK(CUT+NNB+I-1,INVD+1)*U01_I_J+
482 $ WORK(CUT+NNB+I-1,INVD)*U01_IP1_J
483 END DO
484 I=I-2
485 END IF
486 END DO
487*
488* invD1*L11
489*
490 I=NNB
491.GE. DO WHILE (I 1)
492 IF (IPIV(CUT+I) > 0) THEN
493 DO J=1,NNB
494 WORK(U11+I,J)=WORK(CUT+I,INVD)*WORK(U11+I,J)
495 END DO
496 I=I-1
497 ELSE
498 DO J=1,NNB
499 U11_I_J = WORK(U11+I,J)
500 U11_IP1_J = WORK(U11+I-1,J)
501 WORK(U11+I,J)=WORK(CUT+I,INVD)*WORK(U11+I,J) +
502 $ WORK(CUT+I,INVD+1)*U11_IP1_J
503 WORK(U11+I-1,J)=WORK(CUT+I-1,INVD+1)*U11_I_J+
504 $ WORK(CUT+I-1,INVD)*U11_IP1_J
505 END DO
506 I=I-2
507 END IF
508 END DO
509*
510* L11**H*invD1*L11->L11
511*
512 CALL CTRMM('l',UPLO,'c','u',NNB, NNB,
513 $ CONE,A(CUT+1,CUT+1),LDA,WORK(U11+1,1),N+NB+1)
514*
515 DO I=1,NNB
516 DO J=1,I
517 A(CUT+I,CUT+J)=WORK(U11+I,J)
518 END DO
519 END DO
520*
521.LT. IF ( (CUT+NNB) N ) THEN
522*
523* L21**H*invD2*L21->A(CUT+I,CUT+J)
524*
525 CALL CGEMM('c','n',NNB,NNB,N-NNB-CUT,CONE,A(CUT+NNB+1,CUT+1)
526 $ ,LDA,WORK,N+NB+1, ZERO, WORK(U11+1,1), N+NB+1)
527
528*
529* L11 = L11**H*invD1*L11 + U01**H*invD*U01
530*
531 DO I=1,NNB
532 DO J=1,I
533 A(CUT+I,CUT+J)=A(CUT+I,CUT+J)+WORK(U11+I,J)
534 END DO
535 END DO
536*
537* L01 = L22**H*invD2*L21
538*
539 CALL CTRMM('l',UPLO,'c','u', N-NNB-CUT, NNB,
540 $ CONE,A(CUT+NNB+1,CUT+NNB+1),LDA,WORK,N+NB+1)
541
542* Update L21
543 DO I=1,N-CUT-NNB
544 DO J=1,NNB
545 A(CUT+NNB+I,CUT+J)=WORK(I,J)
546 END DO
547 END DO
548 ELSE
549*
550* L11 = L11**H*invD1*L11
551*
552 DO I=1,NNB
553 DO J=1,I
554 A(CUT+I,CUT+J)=WORK(U11+I,J)
555 END DO
556 END DO
557 END IF
558*
559* Next Block
560*
561 CUT=CUT+NNB
562 END DO
563*
564* Apply PERMUTATIONS P and P**H: P * inv(U**H)*inv(D)*inv(U) *P**H
565*
566 I=N
567.GE. DO WHILE ( I 1 )
568.GT. IF( IPIV(I) 0 ) THEN
569 IP=IPIV(I)
570.LT. IF (I IP) CALL CHESWAPR( UPLO, N, A, LDA, I ,IP )
571.GT. IF (I IP) CALL CHESWAPR( UPLO, N, A, LDA, IP ,I )
572 ELSE
573 IP=-IPIV(I)
574.LT. IF ( I IP) CALL CHESWAPR( UPLO, N, A, LDA, I ,IP )
575.GT. IF ( I IP) CALL CHESWAPR( UPLO, N, A, LDA, IP ,I )
576 I=I-1
577 ENDIF
578 I=I-1
579 END DO
580 END IF
581*
582 RETURN
583*
584* End of CHETRI2X
585*
586 END
587
subroutine xerbla(srname, info)
XERBLA
Definition xerbla.f:60
logical function lsame(ca, cb)
LSAME
Definition lsame.f:53
subroutine cheswapr(uplo, n, a, lda, i1, i2)
CHESWAPR applies an elementary permutation on the rows and columns of a Hermitian matrix.
Definition cheswapr.f:102
subroutine chetri2x(uplo, n, a, lda, ipiv, work, nb, info)
CHETRI2X
Definition chetri2x.f:120
subroutine ctrtri(uplo, diag, n, a, lda, info)
CTRTRI
Definition ctrtri.f:109
subroutine csyconv(uplo, way, n, a, lda, ipiv, e, info)
CSYCONV
Definition csyconv.f:114
subroutine ctrmm(side, uplo, transa, diag, m, n, alpha, a, lda, b, ldb)
CTRMM
Definition ctrmm.f:177
subroutine cgemm(transa, transb, m, n, k, alpha, a, lda, b, ldb, beta, c, ldc)
CGEMM
Definition cgemm.f:187
#define max(a, b)
Definition macros.h:21