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