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