158
159
160
161
162
163
164 CHARACTER UPLO
165 INTEGER INFO, LDA, N, NB
166
167
168 INTEGER IPIV( * )
169 COMPLEX*16 A( LDA, * ), E( * ), WORK( N+NB+1, * )
170
171
172
173
174
175 COMPLEX*16 CONE, CZERO
176 parameter( cone = ( 1.0d+0, 0.0d+0 ),
177 $ czero = ( 0.0d+0, 0.0d+0 ) )
178
179
180 LOGICAL UPPER
181 INTEGER CUT, I, ICOUNT, INVD, IP, K, NNB, J, U11
182 COMPLEX*16 AK, AKKP1, AKP1, D, T, U01_I_J, U01_IP1_J,
183 $ U11_I_J, U11_IP1_J
184
185
186 LOGICAL LSAME
188
189
192
193
194 INTRINSIC abs, max, mod
195
196
197
198
199
200 info = 0
201 upper =
lsame( uplo,
'U' )
202 IF( .NOT.upper .AND. .NOT.
lsame( uplo,
'L' ) )
THEN
203 info = -1
204 ELSE IF( n.LT.0 ) THEN
205 info = -2
206 ELSE IF( lda.LT.max( 1, n ) ) THEN
207 info = -4
208 END IF
209
210
211
212 IF( info.NE.0 ) THEN
213 CALL xerbla(
'ZSYTRI_3X', -info )
214 RETURN
215 END IF
216 IF( n.EQ.0 )
217 $ RETURN
218
219
220
221 DO k = 1, n
222 work( k, 1 ) = e( k )
223 END DO
224
225
226
227 IF( upper ) THEN
228
229
230
231 DO info = n, 1, -1
232 IF( ipiv( info ).GT.0 .AND. a( info, info ).EQ.czero )
233 $ RETURN
234 END DO
235 ELSE
236
237
238
239 DO info = 1, n
240 IF( ipiv( info ).GT.0 .AND. a( info, info ).EQ.czero )
241 $ RETURN
242 END DO
243 END IF
244
245 info = 0
246
247
248
249
250
251
252
253 u11 = n
254
255
256
257
258 invd = nb + 2
259
260 IF( upper ) THEN
261
262
263
264
265
266 CALL ztrtri( uplo,
'U', n, a, lda, info )
267
268
269
270 k = 1
271 DO WHILE( k.LE.n )
272 IF( ipiv( k ).GT.0 ) THEN
273
274 work( k, invd ) = cone / a( k, k )
275 work( k, invd+1 ) = czero
276 ELSE
277
278 t = work( k+1, 1 )
279 ak = a( k, k ) / t
280 akp1 = a( k+1, k+1 ) / t
281 akkp1 = work( k+1, 1 ) / t
282 d = t*( ak*akp1-cone )
283 work( k, invd ) = akp1 / d
284 work( k+1, invd+1 ) = ak / d
285 work( k, invd+1 ) = -akkp1 / d
286 work( k+1, invd ) = work( k, invd+1 )
287 k = k + 1
288 END IF
289 k = k + 1
290 END DO
291
292
293
294
295
296 cut = n
297 DO WHILE( cut.GT.0 )
298 nnb = nb
299 IF( cut.LE.nnb ) THEN
300 nnb = cut
301 ELSE
302 icount = 0
303
304 DO i = cut+1-nnb, cut
305 IF( ipiv( i ).LT.0 ) icount = icount + 1
306 END DO
307
308 IF( mod( icount, 2 ).EQ.1 ) nnb = nnb + 1
309 END IF
310
311 cut = cut - nnb
312
313
314
315 DO i = 1, cut
316 DO j = 1, nnb
317 work( i, j ) = a( i, cut+j )
318 END DO
319 END DO
320
321
322
323 DO i = 1, nnb
324 work( u11+i, i ) = cone
325 DO j = 1, i-1
326 work( u11+i, j ) = czero
327 END DO
328 DO j = i+1, nnb
329 work( u11+i, j ) = a( cut+i, cut+j )
330 END DO
331 END DO
332
333
334
335 i = 1
336 DO WHILE( i.LE.cut )
337 IF( ipiv( i ).GT.0 ) THEN
338 DO j = 1, nnb
339 work( i, j ) = work( i, invd ) * work( i, j )
340 END DO
341 ELSE
342 DO j = 1, nnb
343 u01_i_j = work( i, j )
344 u01_ip1_j = work( i+1, j )
345 work( i, j ) = work( i, invd ) * u01_i_j
346 $ + work( i, invd+1 ) * u01_ip1_j
347 work( i+1, j ) = work( i+1, invd ) * u01_i_j
348 $ + work( i+1, invd+1 ) * u01_ip1_j
349 END DO
350 i = i + 1
351 END IF
352 i = i + 1
353 END DO
354
355
356
357 i = 1
358 DO WHILE ( i.LE.nnb )
359 IF( ipiv( cut+i ).GT.0 ) THEN
360 DO j = i, nnb
361 work( u11+i, j ) = work(cut+i,invd) * work(u11+i,j)
362 END DO
363 ELSE
364 DO j = i, nnb
365 u11_i_j = work(u11+i,j)
366 u11_ip1_j = work(u11+i+1,j)
367 work( u11+i, j ) = work(cut+i,invd) * work(u11+i,j)
368 $ + work(cut+i,invd+1) * work(u11+i+1,j)
369 work( u11+i+1, j ) = work(cut+i+1,invd) * u11_i_j
370 $ + work(cut+i+1,invd+1) * u11_ip1_j
371 END DO
372 i = i + 1
373 END IF
374 i = i + 1
375 END DO
376
377
378
379 CALL ztrmm(
'L',
'U',
'T',
'U', nnb, nnb,
380 $ cone, a( cut+1, cut+1 ), lda, work( u11+1, 1 ),
381 $ n+nb+1 )
382
383 DO i = 1, nnb
384 DO j = i, nnb
385 a( cut+i, cut+j ) = work( u11+i, j )
386 END DO
387 END DO
388
389
390
391 CALL zgemm(
'T',
'N', nnb, nnb, cut, cone, a( 1, cut+1 ),
392 $ lda, work, n+nb+1, czero, work(u11+1,1),
393 $ n+nb+1 )
394
395
396
397
398 DO i = 1, nnb
399 DO j = i, nnb
400 a( cut+i, cut+j ) = a( cut+i, cut+j ) + work(u11+i,j)
401 END DO
402 END DO
403
404
405
406 CALL ztrmm(
'L', uplo,
'T',
'U', cut, nnb,
407 $ cone, a, lda, work, n+nb+1 )
408
409
410
411
412 DO i = 1, cut
413 DO j = 1, nnb
414 a( i, cut+j ) = work( i, j )
415 END DO
416 END DO
417
418
419
420 END DO
421
422
423
424
425
426
427
428
429
430
431
432
433 DO i = 1, n
434 ip = abs( ipiv( i ) )
435 IF( ip.NE.i ) THEN
436 IF (i .LT. ip)
CALL zsyswapr( uplo, n, a, lda, i ,
437 $ ip )
438 IF (i .GT. ip)
CALL zsyswapr( uplo, n, a, lda, ip ,
439 $ i )
440 END IF
441 END DO
442
443 ELSE
444
445
446
447
448
449 CALL ztrtri( uplo,
'U', n, a, lda, info )
450
451
452
453 k = n
454 DO WHILE ( k .GE. 1 )
455 IF( ipiv( k ).GT.0 ) THEN
456
457 work( k, invd ) = cone / a( k, k )
458 work( k, invd+1 ) = czero
459 ELSE
460
461 t = work( k-1, 1 )
462 ak = a( k-1, k-1 ) / t
463 akp1 = a( k, k ) / t
464 akkp1 = work( k-1, 1 ) / t
465 d = t*( ak*akp1-cone )
466 work( k-1, invd ) = akp1 / d
467 work( k, invd ) = ak / d
468 work( k, invd+1 ) = -akkp1 / d
469 work( k-1, invd+1 ) = work( k, invd+1 )
470 k = k - 1
471 END IF
472 k = k - 1
473 END DO
474
475
476
477
478
479 cut = 0
480 DO WHILE( cut.LT.n )
481 nnb = nb
482 IF( (cut + nnb).GT.n ) THEN
483 nnb = n - cut
484 ELSE
485 icount = 0
486
487 DO i = cut + 1, cut+nnb
488 IF ( ipiv( i ).LT.0 ) icount = icount + 1
489 END DO
490
491 IF( mod( icount, 2 ).EQ.1 ) nnb = nnb + 1
492 END IF
493
494
495
496 DO i = 1, n-cut-nnb
497 DO j = 1, nnb
498 work( i, j ) = a( cut+nnb+i, cut+j )
499 END DO
500 END DO
501
502
503
504 DO i = 1, nnb
505 work( u11+i, i) = cone
506 DO j = i+1, nnb
507 work( u11+i, j ) = czero
508 END DO
509 DO j = 1, i-1
510 work( u11+i, j ) = a( cut+i, cut+j )
511 END DO
512 END DO
513
514
515
516 i = n-cut-nnb
517 DO WHILE( i.GE.1 )
518 IF( ipiv( cut+nnb+i ).GT.0 ) THEN
519 DO j = 1, nnb
520 work( i, j ) = work( cut+nnb+i, invd) * work( i, j)
521 END DO
522 ELSE
523 DO j = 1, nnb
524 u01_i_j = work(i,j)
525 u01_ip1_j = work(i-1,j)
526 work(i,j)=work(cut+nnb+i,invd)*u01_i_j+
527 $ work(cut+nnb+i,invd+1)*u01_ip1_j
528 work(i-1,j)=work(cut+nnb+i-1,invd+1)*u01_i_j+
529 $ work(cut+nnb+i-1,invd)*u01_ip1_j
530 END DO
531 i = i - 1
532 END IF
533 i = i - 1
534 END DO
535
536
537
538 i = nnb
539 DO WHILE( i.GE.1 )
540 IF( ipiv( cut+i ).GT.0 ) THEN
541 DO j = 1, nnb
542 work( u11+i, j ) = work( cut+i, invd)*work(u11+i,j)
543 END DO
544
545 ELSE
546 DO j = 1, nnb
547 u11_i_j = work( u11+i, j )
548 u11_ip1_j = work( u11+i-1, j )
549 work( u11+i, j ) = work(cut+i,invd) * work(u11+i,j)
550 $ + work(cut+i,invd+1) * u11_ip1_j
551 work( u11+i-1, j ) = work(cut+i-1,invd+1) * u11_i_j
552 $ + work(cut+i-1,invd) * u11_ip1_j
553 END DO
554 i = i - 1
555 END IF
556 i = i - 1
557 END DO
558
559
560
561 CALL ztrmm(
'L', uplo,
'T',
'U', nnb, nnb, cone,
562 $ a( cut+1, cut+1 ), lda, work( u11+1, 1 ),
563 $ n+nb+1 )
564
565
566 DO i = 1, nnb
567 DO j = 1, i
568 a( cut+i, cut+j ) = work( u11+i, j )
569 END DO
570 END DO
571
572 IF( (cut+nnb).LT.n ) THEN
573
574
575
576 CALL zgemm(
'T',
'N', nnb, nnb, n-nnb-cut, cone,
577 $ a( cut+nnb+1, cut+1 ), lda, work, n+nb+1,
578 $ czero, work( u11+1, 1 ), n+nb+1 )
579
580
581
582
583 DO i = 1, nnb
584 DO j = 1, i
585 a( cut+i, cut+j ) = a( cut+i, cut+j )+work(u11+i,j)
586 END DO
587 END DO
588
589
590
591 CALL ztrmm(
'L', uplo,
'T',
'U', n-nnb-cut, nnb, cone,
592 $ a( cut+nnb+1, cut+nnb+1 ), lda, work,
593 $ n+nb+1 )
594
595
596
597 DO i = 1, n-cut-nnb
598 DO j = 1, nnb
599 a( cut+nnb+i, cut+j ) = work( i, j )
600 END DO
601 END DO
602
603 ELSE
604
605
606
607 DO i = 1, nnb
608 DO j = 1, i
609 a( cut+i, cut+j ) = work( u11+i, j )
610 END DO
611 END DO
612 END IF
613
614
615
616 cut = cut + nnb
617
618 END DO
619
620
621
622
623
624
625
626
627
628
629
630
631 DO i = n, 1, -1
632 ip = abs( ipiv( i ) )
633 IF( ip.NE.i ) THEN
634 IF (i .LT. ip)
CALL zsyswapr( uplo, n, a, lda, i ,
635 $ ip )
636 IF (i .GT. ip)
CALL zsyswapr( uplo, n, a, lda, ip ,
637 $ i )
638 END IF
639 END DO
640
641 END IF
642
643 RETURN
644
645
646
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 ztrmm(side, uplo, transa, diag, m, n, alpha, a, lda, b, ldb)
ZTRMM
subroutine ztrtri(uplo, diag, n, a, lda, info)
ZTRTRI