226
227
228
229
230
231 IMPLICIT NONE
232
233
234 CHARACTER COMPQ, COMPZ
235 INTEGER IHI, ILO, INFO, LDA, LDB, LDQ, LDZ, N, LWORK
236
237
238 COMPLEX*16 A( LDA, * ), B( LDB, * ), Q( LDQ, * ),
239 $ Z( LDZ, * ), WORK( * )
240
241
242
243
244
245 COMPLEX*16 CONE, CZERO
246 parameter( cone = ( 1.0d+0, 0.0d+0 ),
247 $ czero = ( 0.0d+0, 0.0d+0 ) )
248
249
250 LOGICAL BLK22, INITQ, INITZ, LQUERY, WANTQ, WANTZ
251 CHARACTER*1 COMPQ2, COMPZ2
252 INTEGER COLA, I, IERR, J, J0, JCOL, JJ, JROW, K,
253 $ KACC22, LEN, LWKOPT, N2NB, NB, NBLST, NBMIN,
254 $ NH, NNB, NX, PPW, PPWO, PW, TOP, TOPQ
255 DOUBLE PRECISION C
256 COMPLEX*16 C1, C2, CTEMP, S, S1, S2, TEMP, TEMP1, TEMP2,
257 $ TEMP3
258
259
260 LOGICAL LSAME
261 INTEGER ILAENV
263
264
268
269
270 INTRINSIC dble, dcmplx, dconjg, max
271
272
273
274
275
276 info = 0
277 nb =
ilaenv( 1,
'ZGGHD3',
' ', n, ilo, ihi, -1 )
278 nh = ihi - ilo + 1
279 IF( nh.LE.1 ) THEN
280 lwkopt = 1
281 ELSE
282 lwkopt = 6*n*nb
283 END IF
284 work( 1 ) = dcmplx( lwkopt )
285 initq =
lsame( compq,
'I' )
286 wantq = initq .OR.
lsame( compq,
'V' )
287 initz =
lsame( compz,
'I' )
288 wantz = initz .OR.
lsame( compz,
'V' )
289 lquery = ( lwork.EQ.-1 )
290
291 IF( .NOT.
lsame( compq,
'N' ) .AND. .NOT.wantq )
THEN
292 info = -1
293 ELSE IF( .NOT.
lsame( compz,
'N' ) .AND. .NOT.wantz )
THEN
294 info = -2
295 ELSE IF( n.LT.0 ) THEN
296 info = -3
297 ELSE IF( ilo.LT.1 ) THEN
298 info = -4
299 ELSE IF( ihi.GT.n .OR. ihi.LT.ilo-1 ) THEN
300 info = -5
301 ELSE IF( lda.LT.max( 1, n ) ) THEN
302 info = -7
303 ELSE IF( ldb.LT.max( 1, n ) ) THEN
304 info = -9
305 ELSE IF( ( wantq .AND. ldq.LT.n ) .OR. ldq.LT.1 ) THEN
306 info = -11
307 ELSE IF( ( wantz .AND. ldz.LT.n ) .OR. ldz.LT.1 ) THEN
308 info = -13
309 ELSE IF( lwork.LT.1 .AND. .NOT.lquery ) THEN
310 info = -15
311 END IF
312 IF( info.NE.0 ) THEN
313 CALL xerbla(
'ZGGHD3', -info )
314 RETURN
315 ELSE IF( lquery ) THEN
316 RETURN
317 END IF
318
319
320
321 IF( initq )
322 $
CALL zlaset(
'All', n, n, czero, cone, q, ldq )
323 IF( initz )
324 $
CALL zlaset(
'All', n, n, czero, cone, z, ldz )
325
326
327
328 IF( n.GT.1 )
329 $
CALL zlaset(
'Lower', n-1, n-1, czero, czero, b(2, 1), ldb )
330
331
332
333 IF( nh.LE.1 ) THEN
334 work( 1 ) = cone
335 RETURN
336 END IF
337
338
339
340 nbmin =
ilaenv( 2,
'ZGGHD3',
' ', n, ilo, ihi, -1 )
341 IF( nb.GT.1 .AND. nb.LT.nh ) THEN
342
343
344
345 nx = max( nb,
ilaenv( 3,
'ZGGHD3',
' ', n, ilo, ihi, -1 ) )
346 IF( nx.LT.nh ) THEN
347
348
349
350 IF( lwork.LT.lwkopt ) THEN
351
352
353
354
355
356 nbmin = max( 2,
ilaenv( 2,
'ZGGHD3',
' ', n, ilo, ihi,
357 $ -1 ) )
358 IF( lwork.GE.6*n*nbmin ) THEN
359 nb = lwork / ( 6*n )
360 ELSE
361 nb = 1
362 END IF
363 END IF
364 END IF
365 END IF
366
367 IF( nb.LT.nbmin .OR. nb.GE.nh ) THEN
368
369
370
371 jcol = ilo
372
373 ELSE
374
375
376
377 kacc22 =
ilaenv( 16,
'ZGGHD3',
' ', n, ilo, ihi, -1 )
378 blk22 = kacc22.EQ.2
379 DO jcol = ilo, ihi-2, nb
380 nnb = min( nb, ihi-jcol-1 )
381
382
383
384
385
386
387
388 n2nb = ( ihi-jcol-1 ) / nnb - 1
389 nblst = ihi - jcol - n2nb*nnb
390 CALL zlaset(
'All', nblst, nblst, czero, cone, work,
391 $ nblst )
392 pw = nblst * nblst + 1
393 DO i = 1, n2nb
394 CALL zlaset(
'All', 2*nnb, 2*nnb, czero, cone,
395 $ work( pw ), 2*nnb )
396 pw = pw + 4*nnb*nnb
397 END DO
398
399
400
401 DO j = jcol, jcol+nnb-1
402
403
404
405
406 DO i = ihi, j+2, -1
407 temp = a( i-1, j )
408 CALL zlartg( temp, a( i, j ), c, s, a( i-1, j ) )
409 a( i, j ) = dcmplx( c )
410 b( i, j ) = s
411 END DO
412
413
414
415 ppw = ( nblst + 1 )*( nblst - 2 ) - j + jcol + 1
416 len = 2 + j - jcol
417 jrow = j + n2nb*nnb + 2
418 DO i = ihi, jrow, -1
419 ctemp = a( i, j )
420 s = b( i, j )
421 DO jj = ppw, ppw+len-1
422 temp = work( jj + nblst )
423 work( jj + nblst ) = ctemp*temp - s*work( jj )
424 work( jj ) = dconjg( s )*temp + ctemp*work( jj )
425 END DO
426 len = len + 1
427 ppw = ppw - nblst - 1
428 END DO
429
430 ppwo = nblst*nblst + ( nnb+j-jcol-1 )*2*nnb + nnb
431 j0 = jrow - nnb
432 DO jrow = j0, j+2, -nnb
433 ppw = ppwo
434 len = 2 + j - jcol
435 DO i = jrow+nnb-1, jrow, -1
436 ctemp = a( i, j )
437 s = b( i, j )
438 DO jj = ppw, ppw+len-1
439 temp = work( jj + 2*nnb )
440 work( jj + 2*nnb ) = ctemp*temp - s*work( jj )
441 work( jj ) = dconjg( s )*temp + ctemp*work( jj )
442 END DO
443 len = len + 1
444 ppw = ppw - 2*nnb - 1
445 END DO
446 ppwo = ppwo + 4*nnb*nnb
447 END DO
448
449
450
451
452 IF( jcol.LE.2 ) THEN
453 top = 0
454 ELSE
455 top = jcol
456 END IF
457
458
459
460
461 DO jj = n, j+1, -1
462
463
464
465 DO i = min( jj+1, ihi ), j+2, -1
466 ctemp = a( i, j )
467 s = b( i, j )
468 temp = b( i, jj )
469 b( i, jj ) = ctemp*temp - dconjg( s )*b( i-1, jj )
470 b( i-1, jj ) = s*temp + ctemp*b( i-1, jj )
471 END DO
472
473
474
475 IF( jj.LT.ihi ) THEN
476 temp = b( jj+1, jj+1 )
477 CALL zlartg( temp, b( jj+1, jj ), c, s,
478 $ b( jj+1, jj+1 ) )
479 b( jj+1, jj ) = czero
480 CALL zrot( jj-top, b( top+1, jj+1 ), 1,
481 $ b( top+1, jj ), 1, c, s )
482 a( jj+1, j ) = dcmplx( c )
483 b( jj+1, j ) = -dconjg( s )
484 END IF
485 END DO
486
487
488
489 jj = mod( ihi-j-1, 3 )
490 DO i = ihi-j-3, jj+1, -3
491 ctemp = a( j+1+i, j )
492 s = -b( j+1+i, j )
493 c1 = a( j+2+i, j )
494 s1 = -b( j+2+i, j )
495 c2 = a( j+3+i, j )
496 s2 = -b( j+3+i, j )
497
498 DO k = top+1, ihi
499 temp = a( k, j+i )
500 temp1 = a( k, j+i+1 )
501 temp2 = a( k, j+i+2 )
502 temp3 = a( k, j+i+3 )
503 a( k, j+i+3 ) = c2*temp3 + dconjg( s2 )*temp2
504 temp2 = -s2*temp3 + c2*temp2
505 a( k, j+i+2 ) = c1*temp2 + dconjg( s1 )*temp1
506 temp1 = -s1*temp2 + c1*temp1
507 a( k, j+i+1 ) = ctemp*temp1 + dconjg( s )*temp
508 a( k, j+i ) = -s*temp1 + ctemp*temp
509 END DO
510 END DO
511
512 IF( jj.GT.0 ) THEN
513 DO i = jj, 1, -1
514 c = dble( a( j+1+i, j ) )
515 CALL zrot( ihi-top, a( top+1, j+i+1 ), 1,
516 $ a( top+1, j+i ), 1, c,
517 $ -dconjg( b( j+1+i, j ) ) )
518 END DO
519 END IF
520
521
522
523 IF ( j .LT. jcol + nnb - 1 ) THEN
524 len = 1 + j - jcol
525
526
527
528
529
530
531
532
533
534
535
536 jrow = ihi - nblst + 1
537 CALL zgemv(
'Conjugate', nblst, len, cone, work,
538 $ nblst, a( jrow, j+1 ), 1, czero,
539 $ work( pw ), 1 )
540 ppw = pw + len
541 DO i = jrow, jrow+nblst-len-1
542 work( ppw ) = a( i, j+1 )
543 ppw = ppw + 1
544 END DO
545 CALL ztrmv(
'Lower',
'Conjugate',
'Non-unit',
546 $ nblst-len, work( len*nblst + 1 ), nblst,
547 $ work( pw+len ), 1 )
548 CALL zgemv(
'Conjugate', len, nblst-len, cone,
549 $ work( (len+1)*nblst - len + 1 ), nblst,
550 $ a( jrow+nblst-len, j+1 ), 1, cone,
551 $ work( pw+len ), 1 )
552 ppw = pw
553 DO i = jrow, jrow+nblst-1
554 a( i, j+1 ) = work( ppw )
555 ppw = ppw + 1
556 END DO
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571 ppwo = 1 + nblst*nblst
572 j0 = jrow - nnb
573 DO jrow = j0, jcol+1, -nnb
574 ppw = pw + len
575 DO i = jrow, jrow+nnb-1
576 work( ppw ) = a( i, j+1 )
577 ppw = ppw + 1
578 END DO
579 ppw = pw
580 DO i = jrow+nnb, jrow+nnb+len-1
581 work( ppw ) = a( i, j+1 )
582 ppw = ppw + 1
583 END DO
584 CALL ztrmv(
'Upper',
'Conjugate',
'Non-unit',
585 $ len,
586 $ work( ppwo + nnb ), 2*nnb, work( pw ),
587 $ 1 )
588 CALL ztrmv(
'Lower',
'Conjugate',
'Non-unit',
589 $ nnb,
590 $ work( ppwo + 2*len*nnb ),
591 $ 2*nnb, work( pw + len ), 1 )
592 CALL zgemv(
'Conjugate', nnb, len, cone,
593 $ work( ppwo ), 2*nnb, a( jrow, j+1 ), 1,
594 $ cone, work( pw ), 1 )
595 CALL zgemv(
'Conjugate', len, nnb, cone,
596 $ work( ppwo + 2*len*nnb + nnb ), 2*nnb,
597 $ a( jrow+nnb, j+1 ), 1, cone,
598 $ work( pw+len ), 1 )
599 ppw = pw
600 DO i = jrow, jrow+len+nnb-1
601 a( i, j+1 ) = work( ppw )
602 ppw = ppw + 1
603 END DO
604 ppwo = ppwo + 4*nnb*nnb
605 END DO
606 END IF
607 END DO
608
609
610
611 cola = n - jcol - nnb + 1
612 j = ihi - nblst + 1
613 CALL zgemm(
'Conjugate',
'No Transpose', nblst,
614 $ cola, nblst, cone, work, nblst,
615 $ a( j, jcol+nnb ), lda, czero, work( pw ),
616 $ nblst )
617 CALL zlacpy(
'All', nblst, cola, work( pw ), nblst,
618 $ a( j, jcol+nnb ), lda )
619 ppwo = nblst*nblst + 1
620 j0 = j - nnb
621 DO j = j0, jcol+1, -nnb
622 IF ( blk22 ) THEN
623
624
625
626
627
628
629
630
631
632
633 CALL zunm22(
'Left',
'Conjugate', 2*nnb, cola, nnb,
634 $ nnb, work( ppwo ), 2*nnb,
635 $ a( j, jcol+nnb ), lda, work( pw ),
636 $ lwork-pw+1, ierr )
637 ELSE
638
639
640
641 CALL zgemm(
'Conjugate',
'No Transpose', 2*nnb,
642 $ cola, 2*nnb, cone, work( ppwo ), 2*nnb,
643 $ a( j, jcol+nnb ), lda, czero, work( pw ),
644 $ 2*nnb )
645 CALL zlacpy(
'All', 2*nnb, cola, work( pw ), 2*nnb,
646 $ a( j, jcol+nnb ), lda )
647 END IF
648 ppwo = ppwo + 4*nnb*nnb
649 END DO
650
651
652
653 IF( wantq ) THEN
654 j = ihi - nblst + 1
655 IF ( initq ) THEN
656 topq = max( 2, j - jcol + 1 )
657 nh = ihi - topq + 1
658 ELSE
659 topq = 1
660 nh = n
661 END IF
662 CALL zgemm(
'No Transpose',
'No Transpose', nh,
663 $ nblst, nblst, cone, q( topq, j ), ldq,
664 $ work, nblst, czero, work( pw ), nh )
665 CALL zlacpy(
'All', nh, nblst, work( pw ), nh,
666 $ q( topq, j ), ldq )
667 ppwo = nblst*nblst + 1
668 j0 = j - nnb
669 DO j = j0, jcol+1, -nnb
670 IF ( initq ) THEN
671 topq = max( 2, j - jcol + 1 )
672 nh = ihi - topq + 1
673 END IF
674 IF ( blk22 ) THEN
675
676
677
678 CALL zunm22(
'Right',
'No Transpose', nh, 2*nnb,
679 $ nnb, nnb, work( ppwo ), 2*nnb,
680 $ q( topq, j ), ldq, work( pw ),
681 $ lwork-pw+1, ierr )
682 ELSE
683
684
685
686 CALL zgemm(
'No Transpose',
'No Transpose', nh,
687 $ 2*nnb, 2*nnb, cone, q( topq, j ), ldq,
688 $ work( ppwo ), 2*nnb, czero, work( pw ),
689 $ nh )
690 CALL zlacpy(
'All', nh, 2*nnb, work( pw ), nh,
691 $ q( topq, j ), ldq )
692 END IF
693 ppwo = ppwo + 4*nnb*nnb
694 END DO
695 END IF
696
697
698
699 IF ( wantz .OR. top.GT.0 ) THEN
700
701
702
703
704 CALL zlaset(
'All', nblst, nblst, czero, cone, work,
705 $ nblst )
706 pw = nblst * nblst + 1
707 DO i = 1, n2nb
708 CALL zlaset(
'All', 2*nnb, 2*nnb, czero, cone,
709 $ work( pw ), 2*nnb )
710 pw = pw + 4*nnb*nnb
711 END DO
712
713
714
715 DO j = jcol, jcol+nnb-1
716 ppw = ( nblst + 1 )*( nblst - 2 ) - j + jcol + 1
717 len = 2 + j - jcol
718 jrow = j + n2nb*nnb + 2
719 DO i = ihi, jrow, -1
720 ctemp = a( i, j )
721 a( i, j ) = czero
722 s = b( i, j )
723 b( i, j ) = czero
724 DO jj = ppw, ppw+len-1
725 temp = work( jj + nblst )
726 work( jj + nblst ) = ctemp*temp -
727 $ dconjg( s )*work( jj )
728 work( jj ) = s*temp + ctemp*work( jj )
729 END DO
730 len = len + 1
731 ppw = ppw - nblst - 1
732 END DO
733
734 ppwo = nblst*nblst + ( nnb+j-jcol-1 )*2*nnb + nnb
735 j0 = jrow - nnb
736 DO jrow = j0, j+2, -nnb
737 ppw = ppwo
738 len = 2 + j - jcol
739 DO i = jrow+nnb-1, jrow, -1
740 ctemp = a( i, j )
741 a( i, j ) = czero
742 s = b( i, j )
743 b( i, j ) = czero
744 DO jj = ppw, ppw+len-1
745 temp = work( jj + 2*nnb )
746 work( jj + 2*nnb ) = ctemp*temp -
747 $ dconjg( s )*work( jj )
748 work( jj ) = s*temp + ctemp*work( jj )
749 END DO
750 len = len + 1
751 ppw = ppw - 2*nnb - 1
752 END DO
753 ppwo = ppwo + 4*nnb*nnb
754 END DO
755 END DO
756 ELSE
757
758 CALL zlaset(
'Lower', ihi - jcol - 1, nnb, czero,
759 $ czero,
760 $ a( jcol + 2, jcol ), lda )
761 CALL zlaset(
'Lower', ihi - jcol - 1, nnb, czero,
762 $ czero,
763 $ b( jcol + 2, jcol ), ldb )
764 END IF
765
766
767
768 IF ( top.GT.0 ) THEN
769 j = ihi - nblst + 1
770 CALL zgemm(
'No Transpose',
'No Transpose', top,
771 $ nblst, nblst, cone, a( 1, j ), lda,
772 $ work, nblst, czero, work( pw ), top )
773 CALL zlacpy(
'All', top, nblst, work( pw ), top,
774 $ a( 1, j ), lda )
775 ppwo = nblst*nblst + 1
776 j0 = j - nnb
777 DO j = j0, jcol+1, -nnb
778 IF ( blk22 ) THEN
779
780
781
782 CALL zunm22(
'Right',
'No Transpose', top,
783 $ 2*nnb,
784 $ nnb, nnb, work( ppwo ), 2*nnb,
785 $ a( 1, j ), lda, work( pw ),
786 $ lwork-pw+1, ierr )
787 ELSE
788
789
790
791 CALL zgemm(
'No Transpose',
'No Transpose', top,
792 $ 2*nnb, 2*nnb, cone, a( 1, j ), lda,
793 $ work( ppwo ), 2*nnb, czero,
794 $ work( pw ), top )
795 CALL zlacpy(
'All', top, 2*nnb, work( pw ), top,
796 $ a( 1, j ), lda )
797 END IF
798 ppwo = ppwo + 4*nnb*nnb
799 END DO
800
801 j = ihi - nblst + 1
802 CALL zgemm(
'No Transpose',
'No Transpose', top,
803 $ nblst, nblst, cone, b( 1, j ), ldb,
804 $ work, nblst, czero, work( pw ), top )
805 CALL zlacpy(
'All', top, nblst, work( pw ), top,
806 $ b( 1, j ), ldb )
807 ppwo = nblst*nblst + 1
808 j0 = j - nnb
809 DO j = j0, jcol+1, -nnb
810 IF ( blk22 ) THEN
811
812
813
814 CALL zunm22(
'Right',
'No Transpose', top,
815 $ 2*nnb,
816 $ nnb, nnb, work( ppwo ), 2*nnb,
817 $ b( 1, j ), ldb, work( pw ),
818 $ lwork-pw+1, ierr )
819 ELSE
820
821
822
823 CALL zgemm(
'No Transpose',
'No Transpose', top,
824 $ 2*nnb, 2*nnb, cone, b( 1, j ), ldb,
825 $ work( ppwo ), 2*nnb, czero,
826 $ work( pw ), top )
827 CALL zlacpy(
'All', top, 2*nnb, work( pw ), top,
828 $ b( 1, j ), ldb )
829 END IF
830 ppwo = ppwo + 4*nnb*nnb
831 END DO
832 END IF
833
834
835
836 IF( wantz ) THEN
837 j = ihi - nblst + 1
838 IF ( initq ) THEN
839 topq = max( 2, j - jcol + 1 )
840 nh = ihi - topq + 1
841 ELSE
842 topq = 1
843 nh = n
844 END IF
845 CALL zgemm(
'No Transpose',
'No Transpose', nh,
846 $ nblst, nblst, cone, z( topq, j ), ldz,
847 $ work, nblst, czero, work( pw ), nh )
848 CALL zlacpy(
'All', nh, nblst, work( pw ), nh,
849 $ z( topq, j ), ldz )
850 ppwo = nblst*nblst + 1
851 j0 = j - nnb
852 DO j = j0, jcol+1, -nnb
853 IF ( initq ) THEN
854 topq = max( 2, j - jcol + 1 )
855 nh = ihi - topq + 1
856 END IF
857 IF ( blk22 ) THEN
858
859
860
861 CALL zunm22(
'Right',
'No Transpose', nh, 2*nnb,
862 $ nnb, nnb, work( ppwo ), 2*nnb,
863 $ z( topq, j ), ldz, work( pw ),
864 $ lwork-pw+1, ierr )
865 ELSE
866
867
868
869 CALL zgemm(
'No Transpose',
'No Transpose', nh,
870 $ 2*nnb, 2*nnb, cone, z( topq, j ), ldz,
871 $ work( ppwo ), 2*nnb, czero, work( pw ),
872 $ nh )
873 CALL zlacpy(
'All', nh, 2*nnb, work( pw ), nh,
874 $ z( topq, j ), ldz )
875 END IF
876 ppwo = ppwo + 4*nnb*nnb
877 END DO
878 END IF
879 END DO
880 END IF
881
882
883
884
885 compq2 = compq
886 compz2 = compz
887 IF ( jcol.NE.ilo ) THEN
888 IF ( wantq )
889 $ compq2 = 'V'
890 IF ( wantz )
891 $ compz2 = 'V'
892 END IF
893
894 IF ( jcol.LT.ihi )
895 $
CALL zgghrd( compq2, compz2, n, jcol, ihi, a, lda, b, ldb,
896 $ q,
897 $ ldq, z, ldz, ierr )
898
899 work( 1 ) = dcmplx( lwkopt )
900
901 RETURN
902
903
904
subroutine xerbla(srname, info)
subroutine zgemm(transa, transb, m, n, k, alpha, a, lda, b, ldb, beta, c, ldc)
ZGEMM
subroutine zgemv(trans, m, n, alpha, a, lda, x, incx, beta, y, incy)
ZGEMV
subroutine zgghrd(compq, compz, n, ilo, ihi, a, lda, b, ldb, q, ldq, z, ldz, info)
ZGGHRD
integer function ilaenv(ispec, name, opts, n1, n2, n3, n4)
ILAENV
subroutine zlacpy(uplo, m, n, a, lda, b, ldb)
ZLACPY copies all or part of one two-dimensional array to another.
subroutine zlartg(f, g, c, s, r)
ZLARTG generates a plane rotation with real cosine and complex sine.
subroutine zlaset(uplo, m, n, alpha, beta, a, lda)
ZLASET initializes the off-diagonal elements and the diagonal elements of a matrix to given values.
logical function lsame(ca, cb)
LSAME
subroutine zrot(n, cx, incx, cy, incy, c, s)
ZROT applies a plane rotation with real cosine and complex sine to a pair of complex vectors.
subroutine ztrmv(uplo, trans, diag, n, a, lda, x, incx)
ZTRMV
subroutine zunm22(side, trans, m, n, n1, n2, q, ldq, c, ldc, work, lwork, info)
ZUNM22 multiplies a general matrix by a banded unitary matrix.