118
119
120
121
122
123
124 CHARACTER UPLO
125 INTEGER INFO, LDA, N, NB
126
127
128 INTEGER IPIV( * )
129 COMPLEX*16 A( LDA, * ), WORK( N+NB+1,* )
130
131
132
133
134
135 COMPLEX*16 ONE, ZERO
136 parameter( one = ( 1.0d+0, 0.0d+0 ),
137 $ zero = ( 0.0d+0, 0.0d+0 ) )
138
139
140 LOGICAL UPPER
141 INTEGER I, IINFO, IP, K, CUT, NNB
142 INTEGER COUNT
143 INTEGER J, U11, INVD
144
145 COMPLEX*16 AK, AKKP1, AKP1, D, T
146 COMPLEX*16 U01_I_J, U01_IP1_J
147 COMPLEX*16 U11_I_J, U11_IP1_J
148
149
150 LOGICAL LSAME
152
153
156
157
158 INTRINSIC max
159
160
161
162
163
164 info = 0
165 upper =
lsame( uplo,
'U' )
166 IF( .NOT.upper .AND. .NOT.
lsame( uplo,
'L' ) )
THEN
167 info = -1
168 ELSE IF( n.LT.0 ) THEN
169 info = -2
170 ELSE IF( lda.LT.max( 1, n ) ) THEN
171 info = -4
172 END IF
173
174
175
176
177 IF( info.NE.0 ) THEN
178 CALL xerbla(
'ZSYTRI2X', -info )
179 RETURN
180 END IF
181 IF( n.EQ.0 )
182 $ RETURN
183
184
185
186
187 CALL zsyconv( uplo,
'C', n, a, lda, ipiv, work, iinfo )
188
189
190
191 IF( upper ) THEN
192
193
194
195 DO info = n, 1, -1
196 IF( ipiv( info ).GT.0 .AND. a( info, info ).EQ.zero )
197 $ RETURN
198 END DO
199 ELSE
200
201
202
203 DO info = 1, n
204 IF( ipiv( info ).GT.0 .AND. a( info, info ).EQ.zero )
205 $ RETURN
206 END DO
207 END IF
208 info = 0
209
210
211
212
213
214
215 u11 = n
216
217
218 invd = nb+2
219
220 IF( upper ) THEN
221
222
223
224 CALL ztrtri( uplo,
'U', n, a, lda, info )
225
226
227
228 k=1
229 DO WHILE ( k .LE. n )
230 IF( ipiv( k ).GT.0 ) THEN
231
232 work(k,invd) = one / a( k, k )
233 work(k,invd+1) = 0
234 k=k+1
235 ELSE
236
237 t = work(k+1,1)
238 ak = a( k, k ) / t
239 akp1 = a( k+1, k+1 ) / t
240 akkp1 = work(k+1,1) / t
241 d = t*( ak*akp1-one )
242 work(k,invd) = akp1 / d
243 work(k+1,invd+1) = ak / d
244 work(k,invd+1) = -akkp1 / d
245 work(k+1,invd) = -akkp1 / d
246 k=k+2
247 END IF
248 END DO
249
250
251
252
253
254 cut=n
255 DO WHILE (cut .GT. 0)
256 nnb=nb
257 IF (cut .LE. nnb) THEN
258 nnb=cut
259 ELSE
260 count = 0
261
262 DO i=cut+1-nnb,cut
263 IF (ipiv(i) .LT. 0) count=count+1
264 END DO
265
266 IF (mod(count,2) .EQ. 1) nnb=nnb+1
267 END IF
268
269 cut=cut-nnb
270
271
272
273 DO i=1,cut
274 DO j=1,nnb
275 work(i,j)=a(i,cut+j)
276 END DO
277 END DO
278
279
280
281 DO i=1,nnb
282 work(u11+i,i)=one
283 DO j=1,i-1
284 work(u11+i,j)=zero
285 END DO
286 DO j=i+1,nnb
287 work(u11+i,j)=a(cut+i,cut+j)
288 END DO
289 END DO
290
291
292
293 i=1
294 DO WHILE (i .LE. cut)
295 IF (ipiv(i) > 0) THEN
296 DO j=1,nnb
297 work(i,j)=work(i,invd)*work(i,j)
298 END DO
299 i=i+1
300 ELSE
301 DO j=1,nnb
302 u01_i_j = work(i,j)
303 u01_ip1_j = work(i+1,j)
304 work(i,j)=work(i,invd)*u01_i_j+
305 $ work(i,invd+1)*u01_ip1_j
306 work(i+1,j)=work(i+1,invd)*u01_i_j+
307 $ work(i+1,invd+1)*u01_ip1_j
308 END DO
309 i=i+2
310 END IF
311 END DO
312
313
314
315 i=1
316 DO WHILE (i .LE. nnb)
317 IF (ipiv(cut+i) > 0) THEN
318 DO j=i,nnb
319 work(u11+i,j)=work(cut+i,invd)*work(u11+i,j)
320 END DO
321 i=i+1
322 ELSE
323 DO j=i,nnb
324 u11_i_j = work(u11+i,j)
325 u11_ip1_j = work(u11+i+1,j)
326 work(u11+i,j)=work(cut+i,invd)*work(u11+i,j) +
327 $ work(cut+i,invd+1)*work(u11+i+1,j)
328 work(u11+i+1,j)=work(cut+i+1,invd)*u11_i_j+
329 $ work(cut+i+1,invd+1)*u11_ip1_j
330 END DO
331 i=i+2
332 END IF
333 END DO
334
335
336
337 CALL ztrmm(
'L',
'U',
'T',
'U',nnb, nnb,
338 $ one,a(cut+1,cut+1),lda,work(u11+1,1),n+nb+1)
339
340 DO i=1,nnb
341 DO j=i,nnb
342 a(cut+i,cut+j)=work(u11+i,j)
343 END DO
344 END DO
345
346
347
348 CALL zgemm(
'T',
'N',nnb,nnb,cut,one,a(1,cut+1),lda,
349 $ work,n+nb+1, zero, work(u11+1,1), n+nb+1)
350
351
352
353 DO i=1,nnb
354 DO j=i,nnb
355 a(cut+i,cut+j)=a(cut+i,cut+j)+work(u11+i,j)
356 END DO
357 END DO
358
359
360
361 CALL ztrmm(
'L',uplo,
'T',
'U',cut, nnb,
362 $ one,a,lda,work,n+nb+1)
363
364
365
366
367 DO i=1,cut
368 DO j=1,nnb
369 a(i,cut+j)=work(i,j)
370 END DO
371 END DO
372
373
374
375 END DO
376
377
378
379 i=1
380 DO WHILE ( i .LE. n )
381 IF( ipiv(i) .GT. 0 ) THEN
382 ip=ipiv(i)
383 IF (i .LT. ip)
CALL zsyswapr( uplo, n, a, lda, i ,
384 $ ip )
385 IF (i .GT. ip)
CALL zsyswapr( uplo, n, a, lda, ip ,
386 $ i )
387 ELSE
388 ip=-ipiv(i)
389 i=i+1
390 IF ( (i-1) .LT. ip)
391 $
CALL zsyswapr( uplo, n, a, lda, i-1 ,ip )
392 IF ( (i-1) .GT. ip)
393 $
CALL zsyswapr( uplo, n, a, lda, ip ,i-1 )
394 ENDIF
395 i=i+1
396 END DO
397 ELSE
398
399
400
401
402
403 CALL ztrtri( uplo,
'U', n, a, lda, info )
404
405
406
407 k=n
408 DO WHILE ( k .GE. 1 )
409 IF( ipiv( k ).GT.0 ) THEN
410
411 work(k,invd) = one / a( k, k )
412 work(k,invd+1) = 0
413 k=k-1
414 ELSE
415
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
430
431
432
433 cut=0
434 DO WHILE (cut .LT. n)
435 nnb=nb
436 IF (cut + nnb .GE. n) THEN
437 nnb=n-cut
438 ELSE
439 count = 0
440
441 DO i=cut+1,cut+nnb
442 IF (ipiv(i) .LT. 0) count=count+1
443 END DO
444
445 IF (mod(count,2) .EQ. 1) nnb=nnb+1
446 END IF
447
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
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
465
466 i=n-cut-nnb
467 DO WHILE (i .GE. 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
487
488 i=nnb
489 DO WHILE (i .GE. 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
509
510 CALL ztrmm(
'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
520 IF ( (cut+nnb) .LT. n ) THEN
521
522
523
524 CALL zgemm(
'T',
'N',nnb,nnb,n-nnb-cut,one,a(cut+nnb+1,cut+1)
525 $ ,lda,work,n+nb+1, zero, work(u11+1,1), n+nb+1)
526
527
528
529
530 DO i=1,nnb
531 DO j=1,i
532 a(cut+i,cut+j)=a(cut+i,cut+j)+work(u11+i,j)
533 END DO
534 END DO
535
536
537
538 CALL ztrmm(
'L',uplo,
'T',
'U', n-nnb-cut, nnb,
539 $ one,a(cut+nnb+1,cut+nnb+1),lda,work,n+nb+1)
540
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 ELSE
548
549
550
551 DO i=1,nnb
552 DO j=1,i
553 a(cut+i,cut+j)=work(u11+i,j)
554 END DO
555 END DO
556 END IF
557
558
559
560 cut=cut+nnb
561 END DO
562
563
564
565 i=n
566 DO WHILE ( i .GE. 1 )
567 IF( ipiv(i) .GT. 0 ) THEN
568 ip=ipiv(i)
569 IF (i .LT. ip)
CALL zsyswapr( uplo, n, a, lda, i ,
570 $ ip )
571 IF (i .GT. ip)
CALL zsyswapr( uplo, n, a, lda, ip ,
572 $ i )
573 ELSE
574 ip=-ipiv(i)
575 IF ( i .LT. ip)
CALL zsyswapr( uplo, n, a, lda, i ,
576 $ ip )
577 IF ( i .GT. ip)
CALL zsyswapr( uplo, n, a, lda, ip ,
578 $ i )
579 i=i-1
580 ENDIF
581 i=i-1
582 END DO
583 END IF
584
585 RETURN
586
587
588
subroutine xerbla(srname, info)
subroutine zgemm(transa, transb, m, n, k, alpha, a, lda, b, ldb, beta, c, ldc)
ZGEMM
subroutine zsyswapr(uplo, n, a, lda, i1, i2)
ZSYSWAPR
logical function lsame(ca, cb)
LSAME
subroutine zsyconv(uplo, way, n, a, lda, ipiv, e, info)
ZSYCONV
subroutine ztrmm(side, uplo, transa, diag, m, n, alpha, a, lda, b, ldb)
ZTRMM
subroutine ztrtri(uplo, diag, n, a, lda, info)
ZTRTRI