OpenRadioss 2025.1.11
OpenRadioss project
Loading...
Searching...
No Matches
csytri2x.f
Go to the documentation of this file.
1*> \brief \b CSYTRI2X
2*
3* =========== DOCUMENTATION ===========
4*
5* Online html documentation available at
6* http://www.netlib.org/lapack/explore-html/
7*
8*> \htmlonly
9*> Download CSYTRI2X + dependencies
10*> <a href="http://www.netlib.org/cgi-bin/netlibfiles.tgz?format=tgz&filename=/lapack/lapack_routine/csytri2x.f">
11*> [TGZ]</a>
12*> <a href="http://www.netlib.org/cgi-bin/netlibfiles.zip?format=zip&filename=/lapack/lapack_routine/csytri2x.f">
13*> [ZIP]</a>
14*> <a href="http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/csytri2x.f">
15*> [TXT]</a>
16*> \endhtmlonly
17*
18* Definition:
19* ===========
20*
21* SUBROUTINE CSYTRI2X( 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*> CSYTRI2X computes the inverse of a real symmetric indefinite matrix
39*> A using the factorization A = U*D*U**T or A = L*D*L**T computed by
40*> CSYTRF.
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**T;
52*> = 'L': Lower triangular, form is A = L*D*L**T.
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 CSYTRF.
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 CSYTRF.
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 complexSYcomputational
117*
118* =====================================================================
119 SUBROUTINE csytri2x( 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 COMPLEX ONE, ZERO
138 parameter( one = ( 1.0e+0, 0.0e+0 ),
139 $ zero = ( 0.0e+0, 0.0e+0 ) )
140* ..
141* .. Local Scalars ..
142 LOGICAL UPPER
143 INTEGER I, IINFO, IP, K, CUT, NNB
144 INTEGER COUNT
145 INTEGER J, U11, INVD
146
147 COMPLEX AK, AKKP1, AKP1, D, T
148 COMPLEX U01_I_J, U01_IP1_J
149 COMPLEX U11_I_J, U11_IP1_J
150* ..
151* .. External Functions ..
152 LOGICAL LSAME
153 EXTERNAL lsame
154* ..
155* .. External Subroutines ..
156 EXTERNAL csyconv, xerbla, ctrtri
157 EXTERNAL cgemm, ctrmm, csyswapr
158* ..
159* .. Intrinsic Functions ..
160 INTRINSIC max
161* ..
162* .. Executable Statements ..
163*
164* Test the input parameters.
165*
166 info = 0
167 upper = lsame( uplo, 'u' )
168.NOT..AND..NOT. IF( UPPER LSAME( UPLO, 'l' ) ) THEN
169 INFO = -1
170.LT. ELSE IF( N0 ) THEN
171 INFO = -2
172.LT. ELSE IF( LDAMAX( 1, N ) ) THEN
173 INFO = -4
174 END IF
175*
176* Quick return if possible
177*
178*
179.NE. IF( INFO0 ) THEN
180 CALL XERBLA( 'csytri2x', -INFO )
181 RETURN
182 END IF
183.EQ. IF( N0 )
184 $ RETURN
185*
186* Convert A
187* Workspace got Non-diag elements of D
188*
189 CALL CSYCONV( UPLO, 'c', N, A, LDA, IPIV, WORK, IINFO )
190*
191* Check that the diagonal matrix D is nonsingular.
192*
193 IF( UPPER ) THEN
194*
195* Upper triangular storage: examine D from bottom to top
196*
197 DO INFO = N, 1, -1
198.GT..AND..EQ. IF( IPIV( INFO )0 A( INFO, INFO )ZERO )
199 $ RETURN
200 END DO
201 ELSE
202*
203* Lower triangular storage: examine D from top to bottom.
204*
205 DO INFO = 1, N
206.GT..AND..EQ. IF( IPIV( INFO )0 A( INFO, INFO )ZERO )
207 $ RETURN
208 END DO
209 END IF
210 INFO = 0
211*
212* Splitting Workspace
213* U01 is a block (N,NB+1)
214* The first element of U01 is in WORK(1,1)
215* U11 is a block (NB+1,NB+1)
216* The first element of U11 is in WORK(N+1,1)
217 U11 = N
218* INVD is a block (N,2)
219* The first element of INVD is in WORK(1,INVD)
220 INVD = NB+2
221
222 IF( UPPER ) THEN
223*
224* invA = P * inv(U**T)*inv(D)*inv(U)*P**T.
225*
226 CALL CTRTRI( UPLO, 'u', N, A, LDA, INFO )
227*
228* inv(D) and inv(D)*inv(U)
229*
230 K=1
231.LE. DO WHILE ( K N )
232.GT. IF( IPIV( K )0 ) THEN
233* 1 x 1 diagonal NNB
234 WORK(K,INVD) = ONE / A( K, K )
235 WORK(K,INVD+1) = 0
236 K=K+1
237 ELSE
238* 2 x 2 diagonal NNB
239 T = WORK(K+1,1)
240 AK = A( K, K ) / T
241 AKP1 = A( K+1, K+1 ) / T
242 AKKP1 = WORK(K+1,1) / T
243 D = T*( AK*AKP1-ONE )
244 WORK(K,INVD) = AKP1 / D
245 WORK(K+1,INVD+1) = AK / D
246 WORK(K,INVD+1) = -AKKP1 / D
247 WORK(K+1,INVD) = -AKKP1 / D
248 K=K+2
249 END IF
250 END DO
251*
252* inv(U**T) = (inv(U))**T
253*
254* inv(U**T)*inv(D)*inv(U)
255*
256 CUT=N
257.GT. DO WHILE (CUT 0)
258 NNB=NB
259.LE. IF (CUT NNB) THEN
260 NNB=CUT
261 ELSE
262 COUNT = 0
263* count negative elements,
264 DO I=CUT+1-NNB,CUT
265.LT. IF (IPIV(I) 0) COUNT=COUNT+1
266 END DO
267* need a even number for a clear cut
268.EQ. IF (MOD(COUNT,2) 1) NNB=NNB+1
269 END IF
270
271 CUT=CUT-NNB
272*
273* U01 Block
274*
275 DO I=1,CUT
276 DO J=1,NNB
277 WORK(I,J)=A(I,CUT+J)
278 END DO
279 END DO
280*
281* U11 Block
282*
283 DO I=1,NNB
284 WORK(U11+I,I)=ONE
285 DO J=1,I-1
286 WORK(U11+I,J)=ZERO
287 END DO
288 DO J=I+1,NNB
289 WORK(U11+I,J)=A(CUT+I,CUT+J)
290 END DO
291 END DO
292*
293* invD*U01
294*
295 I=1
296.LE. DO WHILE (I CUT)
297 IF (IPIV(I) > 0) THEN
298 DO J=1,NNB
299 WORK(I,J)=WORK(I,INVD)*WORK(I,J)
300 END DO
301 I=I+1
302 ELSE
303 DO J=1,NNB
304 U01_I_J = WORK(I,J)
305 U01_IP1_J = WORK(I+1,J)
306 WORK(I,J)=WORK(I,INVD)*U01_I_J+
307 $ WORK(I,INVD+1)*U01_IP1_J
308 WORK(I+1,J)=WORK(I+1,INVD)*U01_I_J+
309 $ WORK(I+1,INVD+1)*U01_IP1_J
310 END DO
311 I=I+2
312 END IF
313 END DO
314*
315* invD1*U11
316*
317 I=1
318.LE. DO WHILE (I NNB)
319 IF (IPIV(CUT+I) > 0) THEN
320 DO J=I,NNB
321 WORK(U11+I,J)=WORK(CUT+I,INVD)*WORK(U11+I,J)
322 END DO
323 I=I+1
324 ELSE
325 DO J=I,NNB
326 U11_I_J = WORK(U11+I,J)
327 U11_IP1_J = WORK(U11+I+1,J)
328 WORK(U11+I,J)=WORK(CUT+I,INVD)*WORK(U11+I,J) +
329 $ WORK(CUT+I,INVD+1)*WORK(U11+I+1,J)
330 WORK(U11+I+1,J)=WORK(CUT+I+1,INVD)*U11_I_J+
331 $ WORK(CUT+I+1,INVD+1)*U11_IP1_J
332 END DO
333 I=I+2
334 END IF
335 END DO
336*
337* U11**T*invD1*U11->U11
338*
339 CALL CTRMM('l','u','t','u',NNB, NNB,
340 $ ONE,A(CUT+1,CUT+1),LDA,WORK(U11+1,1),N+NB+1)
341*
342 DO I=1,NNB
343 DO J=I,NNB
344 A(CUT+I,CUT+J)=WORK(U11+I,J)
345 END DO
346 END DO
347*
348* U01**T*invD*U01->A(CUT+I,CUT+J)
349*
350 CALL CGEMM('t','n',NNB,NNB,CUT,ONE,A(1,CUT+1),LDA,
351 $ WORK,N+NB+1, ZERO, WORK(U11+1,1), N+NB+1)
352*
353* U11 = U11**T*invD1*U11 + U01**T*invD*U01
354*
355 DO I=1,NNB
356 DO J=I,NNB
357 A(CUT+I,CUT+J)=A(CUT+I,CUT+J)+WORK(U11+I,J)
358 END DO
359 END DO
360*
361* U01 = U00**T*invD0*U01
362*
363 CALL CTRMM('l',UPLO,'t','u',CUT, NNB,
364 $ ONE,A,LDA,WORK,N+NB+1)
365
366*
367* Update U01
368*
369 DO I=1,CUT
370 DO J=1,NNB
371 A(I,CUT+J)=WORK(I,J)
372 END DO
373 END DO
374*
375* Next Block
376*
377 END DO
378*
379* Apply PERMUTATIONS P and P**T: P * inv(U**T)*inv(D)*inv(U) *P**T
380*
381 I=1
382.LE. DO WHILE ( I N )
383.GT. IF( IPIV(I) 0 ) THEN
384 IP=IPIV(I)
385.LT. IF (I IP) CALL CSYSWAPR( UPLO, N, A, LDA, I ,IP )
386.GT. IF (I IP) CALL CSYSWAPR( UPLO, N, A, LDA, IP ,I )
387 ELSE
388 IP=-IPIV(I)
389 I=I+1
390.LT. IF ( (I-1) IP)
391 $ CALL CSYSWAPR( UPLO, N, A, LDA, I-1 ,IP )
392.GT. IF ( (I-1) IP)
393 $ CALL CSYSWAPR( UPLO, N, A, LDA, IP ,I-1 )
394 ENDIF
395 I=I+1
396 END DO
397 ELSE
398*
399* LOWER...
400*
401* invA = P * inv(U**T)*inv(D)*inv(U)*P**T.
402*
403 CALL CTRTRI( UPLO, 'u', N, A, LDA, INFO )
404*
405* inv(D) and inv(D)*inv(U)
406*
407 K=N
408.GE. DO WHILE ( K 1 )
409.GT. IF( IPIV( K )0 ) THEN
410* 1 x 1 diagonal NNB
411 WORK(K,INVD) = ONE / A( K, K )
412 WORK(K,INVD+1) = 0
413 K=K-1
414 ELSE
415* 2 x 2 diagonal NNB
416 T = WORK(K-1,1)
417 AK = A( K-1, K-1 ) / T
418 AKP1 = A( K, K ) / T
419 AKKP1 = WORK(K-1,1) / T
420 D = T*( AK*AKP1-ONE )
421 WORK(K-1,INVD) = AKP1 / D
422 WORK(K,INVD) = AK / D
423 WORK(K,INVD+1) = -AKKP1 / D
424 WORK(K-1,INVD+1) = -AKKP1 / D
425 K=K-2
426 END IF
427 END DO
428*
429* inv(U**T) = (inv(U))**T
430*
431* inv(U**T)*inv(D)*inv(U)
432*
433 CUT=0
434.LT. DO WHILE (CUT N)
435 NNB=NB
436.GE. IF (CUT + NNB N) THEN
437 NNB=N-CUT
438 ELSE
439 COUNT = 0
440* count negative elements,
441 DO I=CUT+1,CUT+NNB
442.LT. IF (IPIV(I) 0) COUNT=COUNT+1
443 END DO
444* need a even number for a clear cut
445.EQ. IF (MOD(COUNT,2) 1) NNB=NNB+1
446 END IF
447* L21 Block
448 DO I=1,N-CUT-NNB
449 DO J=1,NNB
450 WORK(I,J)=A(CUT+NNB+I,CUT+J)
451 END DO
452 END DO
453* L11 Block
454 DO I=1,NNB
455 WORK(U11+I,I)=ONE
456 DO J=I+1,NNB
457 WORK(U11+I,J)=ZERO
458 END DO
459 DO J=1,I-1
460 WORK(U11+I,J)=A(CUT+I,CUT+J)
461 END DO
462 END DO
463*
464* invD*L21
465*
466 I=N-CUT-NNB
467.GE. DO WHILE (I 1)
468 IF (IPIV(CUT+NNB+I) > 0) THEN
469 DO J=1,NNB
470 WORK(I,J)=WORK(CUT+NNB+I,INVD)*WORK(I,J)
471 END DO
472 I=I-1
473 ELSE
474 DO J=1,NNB
475 U01_I_J = WORK(I,J)
476 U01_IP1_J = WORK(I-1,J)
477 WORK(I,J)=WORK(CUT+NNB+I,INVD)*U01_I_J+
478 $ WORK(CUT+NNB+I,INVD+1)*U01_IP1_J
479 WORK(I-1,J)=WORK(CUT+NNB+I-1,INVD+1)*U01_I_J+
480 $ WORK(CUT+NNB+I-1,INVD)*U01_IP1_J
481 END DO
482 I=I-2
483 END IF
484 END DO
485*
486* invD1*L11
487*
488 I=NNB
489.GE. DO WHILE (I 1)
490 IF (IPIV(CUT+I) > 0) THEN
491 DO J=1,NNB
492 WORK(U11+I,J)=WORK(CUT+I,INVD)*WORK(U11+I,J)
493 END DO
494 I=I-1
495 ELSE
496 DO J=1,NNB
497 U11_I_J = WORK(U11+I,J)
498 U11_IP1_J = WORK(U11+I-1,J)
499 WORK(U11+I,J)=WORK(CUT+I,INVD)*WORK(U11+I,J) +
500 $ WORK(CUT+I,INVD+1)*U11_IP1_J
501 WORK(U11+I-1,J)=WORK(CUT+I-1,INVD+1)*U11_I_J+
502 $ WORK(CUT+I-1,INVD)*U11_IP1_J
503 END DO
504 I=I-2
505 END IF
506 END DO
507*
508* L11**T*invD1*L11->L11
509*
510 CALL CTRMM('l',UPLO,'t','u',NNB, NNB,
511 $ ONE,A(CUT+1,CUT+1),LDA,WORK(U11+1,1),N+NB+1)
512*
513 DO I=1,NNB
514 DO J=1,I
515 A(CUT+I,CUT+J)=WORK(U11+I,J)
516 END DO
517 END DO
518*
519.LT. IF ( (CUT+NNB) N ) THEN
520*
521* L21**T*invD2*L21->A(CUT+I,CUT+J)
522*
523 CALL CGEMM('t','n',NNB,NNB,N-NNB-CUT,ONE,A(CUT+NNB+1,CUT+1)
524 $ ,LDA,WORK,N+NB+1, ZERO, WORK(U11+1,1), N+NB+1)
525
526*
527* L11 = L11**T*invD1*L11 + U01**T*invD*U01
528*
529 DO I=1,NNB
530 DO J=1,I
531 A(CUT+I,CUT+J)=A(CUT+I,CUT+J)+WORK(U11+I,J)
532 END DO
533 END DO
534*
535* L01 = L22**T*invD2*L21
536*
537 CALL CTRMM('l',UPLO,'t','u', n-nnb-cut, nnb,
538 $ one,a(cut+nnb+1,cut+nnb+1),lda,work,n+nb+1)
539
540* Update L21
541 DO i=1,n-cut-nnb
542 DO j=1,nnb
543 a(cut+nnb+i,cut+j)=work(i,j)
544 END DO
545 END DO
546 ELSE
547*
548* L11 = L11**T*invD1*L11
549*
550 DO i=1,nnb
551 DO j=1,i
552 a(cut+i,cut+j)=work(u11+i,j)
553 END DO
554 END DO
555 END IF
556*
557* Next Block
558*
559 cut=cut+nnb
560 END DO
561*
562* Apply PERMUTATIONS P and P**T: P * inv(U**T)*inv(D)*inv(U) *P**T
563*
564 i=n
565 DO WHILE ( i .GE. 1 )
566 IF( ipiv(i) .GT. 0 ) THEN
567 ip=ipiv(i)
568 IF (i .LT. ip) CALL csyswapr( uplo, n, a, lda, i ,ip )
569 IF (i .GT. ip) CALL csyswapr( uplo, n, a, lda, ip ,i )
570 ELSE
571 ip=-ipiv(i)
572 IF ( i .LT. ip) CALL csyswapr( uplo, n, a, lda, i ,ip )
573 IF ( i .GT. ip) CALL csyswapr( uplo, n, a, lda, ip ,i )
574 i=i-1
575 ENDIF
576 i=i-1
577 END DO
578 END IF
579*
580 RETURN
581*
582* End of CSYTRI2X
583*
584 END
585
subroutine xerbla(srname, info)
XERBLA
Definition xerbla.f:60
subroutine ctrtri(uplo, diag, n, a, lda, info)
CTRTRI
Definition ctrtri.f:109
subroutine csyswapr(uplo, n, a, lda, i1, i2)
CSYSWAPR
Definition csyswapr.f:102
subroutine csyconv(uplo, way, n, a, lda, ipiv, e, info)
CSYCONV
Definition csyconv.f:114
subroutine csytri2x(uplo, n, a, lda, ipiv, work, nb, info)
CSYTRI2X
Definition csytri2x.f:120
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