1 SUBROUTINE pchettrd( UPLO, N, A, IA, JA, DESCA, D, E, TAU, WORK,
10 INTEGER IA, INFO, JA, LWORK, N
15 COMPLEX A( * ), TAU( * ), WORK( * )
402 INTEGER BLOCK_CYCLIC_2D, DLEN_, DTYPE_, CTXT_, M_, N_,
403 $ mb_, nb_, rsrc_, csrc_, lld_
404 parameter( block_cyclic_2d = 1, dlen_ = 9, dtype_ = 1,
405 $ ctxt_ = 2, m_ = 3, n_ = 4, mb_ = 5, nb_ = 6,
406 $ rsrc_ = 7, csrc_ = 8, lld_ = 9 )
408 parameter( one = 1.0e0 )
409 COMPLEX Z_ONE, Z_NEGONE, Z_ZERO
410 parameter( z_one = 1.0e0, z_negone = -1.0e0,
413 parameter( zero = 0.0e+0 )
420 LOGICAL BALANCED, INTERLEAVE, TWOGEMMS, UPPER
421 INTEGER ANB, BINDEX, CURCOL, CURROW, I, ICTXT, INDEX,
422 $ indexa, indexinh, indexinv, inh, inhb, inht,
423 $ inhtb, intmp, inv, invb, invt, invtb, j, lda,
424 $ ldv, ldzg, lii, liib, liip1, lij, lijb, lijp1,
425 $ ltlip1, ltnm1, lwmin, maxindex, minindex,
426 $ mycol, myfirstrow, myrow, mysetnum, nbzg, np,
427 $ npb, npcol, npm0, npm1, nprow, nps, npset, nq,
428 $ nqb, nqm1, numrows, nxtcol, nxtrow, pbmax,
429 $ pbmin, pbsize, pnb, rowsperproc
430 REAL NORM, SAFMAX, SAFMIN
431 COMPLEX ALPHA, BETA, C, ONEOVERBETA, TOPH, TOPNV,
432 $ toptau, topv, ttoph, ttopv
439 INTEGER IDUM1( 1 ), IDUM2( 1 )
445 $ cgerv2d, cgesd2d, cgsum2d,
chk1mat, clamov,
452 INTEGER ICEIL, NUMROC, PJLAENV
454 EXTERNAL lsame, iceil, numroc, pjlaenv, pslamch, scnrm2
457 INTRINSIC aimag,
cmplx, conjg, ichar,
max,
min, mod,
464 IF( block_cyclic_2d*csrc_*ctxt_*dlen_*dtype_*lld_*mb_*m_*nb_*n_*
487 ictxt = desca( ctxt_ )
490 safmax = sqrt( pslamch( ictxt,
'O' ) ) / n
491 safmin = sqrt( pslamch( ictxt,
'S' ) )
496 IF( nprow.EQ.-1 )
THEN
497 info = -( 600+ctxt_ )
502 pnb = pjlaenv( ictxt, 2,
'PCHETTRD',
'L', 0, 0, 0, 0 )
503 anb = pjlaenv( ictxt, 3,
'PCHETTRD',
'L', 0, 0, 0, 0 )
505 interleave = ( pjlaenv( ictxt, 4,
'PCHETTRD',
'L', 1, 0, 0,
507 twogemms = ( pjlaenv( ictxt, 4,
'PCHETTRD',
'L', 2, 0, 0,
509 balanced = ( pjlaenv( ictxt, 4,
'PCHETTRD',
'L', 3, 0, 0,
512 CALL chk1mat( n, 2, n, 2, ia, ja, desca, 6, info )
515 upper = lsame( uplo,
'U' )
516 IF( info.EQ.0 .AND. desca( nb_ ).NE.1 )
533 nps =
max( numroc( n, 1, 0, 0, nprow ), 2*anb )
534 lwmin = 2*( anb+1 )*( 4*nps+2 ) + nps
536 work( 1 ) =
cmplx( lwmin )
537 IF( .NOT.lsame( uplo,
'L' ) )
THEN
539 ELSE IF( ia.NE.1 )
THEN
541 ELSE IF( ja.NE.1 )
THEN
543 ELSE IF( nprow.NE.npcol )
THEN
544 info = -( 600+ctxt_ )
545 ELSE IF( desca( dtype_ ).NE.1 )
THEN
546 info = -( 600+dtype_ )
547 ELSE IF( desca( mb_ ).NE.1 )
THEN
549 ELSE IF( desca( nb_ ).NE.1 )
THEN
551 ELSE IF( desca( rsrc_ ).NE.0 )
THEN
552 info = -( 600+rsrc_ )
553 ELSE IF( desca( csrc_ ).NE.0 )
THEN
554 info = -( 600+csrc_ )
555 ELSE IF( lwork.LT.lwmin )
THEN
560 idum1( 1 ) = ichar(
'U' )
562 idum1( 1 ) = ichar(
'L' )
566 CALL pchk1mat( n, 2, n, 2, ia, ja, desca, 6, 1, idum1, idum2,
571 CALL pxerbla( ictxt,
'PCHETTRD', -info )
583 np = numroc( n, 1, myrow, 0, nprow )
584 nq = numroc( n, 1, mycol, 0, npcol )
595 ictxt = desca( ctxt_ )
616 IF( interleave )
THEN
632 ldv = 4*(
max( npm1, nqm1 ) ) + 2
637 invt = inh + ( anb+1 )*ldv
639 inht = invt + ldv / 2
640 intmp = invt + ldv*( anb+1 )
643 ldv =
max( npm1, nqm1 )
645 inht = inh + ldv*( anb+1 )
646 inv = inht + ldv*( anb+1 )
654 invt = inv + ldv*( anb+1 ) + 1
655 intmp = invt + ldv*( 2*anb )
660 CALL pxerbla( ictxt,
'PCHETTRD', -info )
661 work( 1 ) =
cmplx( lwmin )
677 work( inh+i-1 ) = z_zero
678 work( inv+i-1 ) = z_zero
681 work( inht+i-1 ) = z_zero
690 IF( mycol.GT.myrow )
THEN
696 DO 210 minindex = 1, n - 1, anb
699 maxindex =
min( minindex+anb-1, n )
700 lijb = numroc( maxindex, 1, mycol, 0, npcol ) + 1
701 liib = numroc( maxindex, 1, myrow, 0, nprow ) + 1
705 inhtb = inht + lijb - 1
706 invtb = invt + lijb - 1
707 inhb = inh + liib - 1
708 invb = inv + liib - 1
713 DO 160 index = minindex,
min( maxindex, n-1 )
715 bindex = index - minindex
720 nxtrow = mod( currow+1, nprow )
721 nxtcol = mod( curcol+1, npcol )
727 IF( myrow.EQ.currow )
THEN
731 IF( mycol.EQ.curcol )
THEN
747 IF( mycol.EQ.curcol )
THEN
749 indexa = lii + ( lij-1 )*lda
750 indexinv = inv + lii - 1 + ( bindex-1 )*ldv
751 indexinh = inh + lii - 1 + ( bindex-1 )*ldv
752 ttoph = conjg( work( inht+lij-1+bindex*ldv ) )
755 IF( index.GT.1 )
THEN
756 DO 30 i = 0, npm0 - 1
758 a( indexa+i ) = a( indexa+i ) -
759 $ work( indexinv+ldv+i )*ttoph -
760 $ work( indexinh+ldv+i )*ttopv
768 IF( mycol.EQ.curcol )
THEN
772 IF( myrow.EQ.currow )
THEN
773 dtmp( 2 ) = real( a( lii+( lij-1 )*lda ) )
777 IF( myrow.EQ.nxtrow )
THEN
778 dtmp( 3 ) = real( a( liip1+( lij-1 )*lda ) )
779 dtmp( 4 ) = aimag( a( liip1+( lij-1 )*lda ) )
785 norm = scnrm2( npm1, a( liip1+( lij-1 )*lda ), 1 )
793 IF( dtmp( 1 ).GE.safmax .OR. dtmp( 1 ).LT.safmin )
THEN
798 dtmp( 1 ) = dtmp( 1 )*dtmp( 1 )
799 CALL sgsum2d( ictxt, 'c
', ' ', 5, 1, DTMP, 5, -1,
801.EQ.
IF( DTMP( 5 )ZERO ) THEN
802 DTMP( 1 ) = SQRT( DTMP( 1 ) )
805 CALL PSTREECOMB( ICTXT, 'c
', 1, DTMP, -1, MYCOL,
812.EQ..AND..EQ.
IF( MYROWCURROW MYCOLCURCOL ) THEN
813 A( LII+( LIJ-1 )*LDA ) = CMPLX( D( LIJ ), ZERO )
817 ALPHA = CMPLX( DTMP( 3 ), DTMP( 4 ) )
819 NORM = SIGN( NORM, REAL( ALPHA ) )
821.EQ.
IF( NORMZERO ) THEN
826 ONEOVERBETA = 1.0E0 / BETA
828 CALL CSCAL( NPM1, ONEOVERBETA,
829 $ A( LIIP1+( LIJ-1 )*LDA ), 1 )
832.EQ.
IF( MYROWNXTROW ) THEN
833 A( LIIP1+( LIJ-1 )*LDA ) = Z_ONE
844 DO 40 I = 0, NPM1 - 1
845 WORK( INV+LIIP1-1+BINDEX*LDV+NPM1+I ) = A( LIIP1+I+
849.EQ.
IF( MYCOLCURCOL ) THEN
850 WORK( INV+LIIP1-1+BINDEX*LDV+NPM1+NPM1 ) = TOPTAU
851 CALL CGEBS2D( ICTXT, 'r
', ' ', NPM1+NPM1+1, 1,
852 $ WORK( INV+LIIP1-1+BINDEX*LDV ),
855 CALL CGEBR2D( ICTXT, 'r
', ' ', NPM1+NPM1+1, 1,
856 $ WORK( INV+LIIP1-1+BINDEX*LDV ),
857 $ NPM1+NPM1+1, MYROW, CURCOL )
858 TOPTAU = WORK( INV+LIIP1-1+BINDEX*LDV+NPM1+NPM1 )
860 DO 50 I = 0, NPM1 - 1
861 WORK( INH+LIIP1-1+( BINDEX+1 )*LDV+I ) = WORK( INV+LIIP1-
862 $ 1+BINDEX*LDV+NPM1+I )
865.LT.
IF( INDEXN ) THEN
866.EQ..AND..EQ.
IF( MYROWNXTROW MYCOLCURCOL )
867 $ A( LIIP1+( LIJ-1 )*LDA ) = E( LIJ )
873.EQ.
IF( MYROWMYCOL ) THEN
874 DO 60 I = 0, NPM1 + NPM1
875 WORK( INVT+LIJP1-1+BINDEX*LDV+I ) = WORK( INV+LIIP1-1+
879 CALL CGESD2D( ICTXT, NPM1+NPM1, 1,
880 $ WORK( INV+LIIP1-1+BINDEX*LDV ), NPM1+NPM1,
882 CALL CGERV2D( ICTXT, NQM1+NQM1, 1,
883 $ WORK( INVT+LIJP1-1+BINDEX*LDV ), NQM1+NQM1,
887 DO 70 I = 0, NQM1 - 1
888 WORK( INHT+LIJP1-1+( BINDEX+1 )*LDV+I ) = WORK( INVT+
889 $ LIJP1-1+BINDEX*LDV+NQM1+I )
895.GT.
IF( INDEX1 ) THEN
896 DO 90 J = LIJP1, LIJB - 1
897 DO 80 I = 0, NPM1 - 1
899 A( LIIP1+I+( J-1 )*LDA ) = A( LIIP1+I+( J-1 )*LDA )
900 $ - WORK( INV+LIIP1-1+BINDEX*LDV+I )*
901 $ CONJG( WORK( INHT+J-1+BINDEX*LDV ) ) -
902 $ WORK( INH+LIIP1-1+BINDEX*LDV+I )*
903 $ CONJG( WORK( INVT+J-1+BINDEX*LDV ) )
920 WORK( INV+LIIP1-1+( BINDEX+1 )*LDV ) = Z_ZERO
921 WORK( INVT+LIJP1-1+( BINDEX+1 )*LDV+NQM1-1 ) = Z_ZERO
924.EQ.
IF( MYROWMYCOL ) THEN
925.GT.
IF( LTNM11 ) THEN
926 CALL CTRMVT( 'l
', LTNM1-1,
927 $ A( LTLIP1+1+( LIJP1-1 )*LDA ), LDA,
928 $ WORK( INVT+LIJP1-1+( BINDEX+1 )*LDV ), 1,
929 $ WORK( INH+LTLIP1+1-1+( BINDEX+1 )*LDV ),
930 $ 1, WORK( INV+LTLIP1+1-1+( BINDEX+1 )*
931 $ LDV ), 1, WORK( INHT+LIJP1-1+( BINDEX+
935 WORK( INVT+LIJP1+I-1-1+( BINDEX+1 )*LDV )
936 $ = WORK( INVT+LIJP1+I-1-1+( BINDEX+1 )*LDV ) +
937 $ A( LTLIP1+I-1+( LIJP1+I-1-1 )*LDA )*
938 $ WORK( INH+LTLIP1+I-1-1+( BINDEX+1 )*LDV )
942 $ CALL CTRMVT( 'l
', LTNM1, A( LTLIP1+( LIJP1-1 )*LDA ),
943 $ LDA, WORK( INVT+LIJP1-1+( BINDEX+1 )*
944 $ LDV ), 1, WORK( INH+LTLIP1-1+( BINDEX+
945 $ 1 )*LDV ), 1, WORK( INV+LTLIP1-1+
946 $ ( BINDEX+1 )*LDV ), 1,
947 $ WORK( INHT+LIJP1-1+( BINDEX+1 )*LDV ),
966 DO 110 I = 1, 2*( BINDEX+1 )
967 WORK( INTMP-1+I ) = 0
973 ROWSPERPROC = ICEIL( NQB, NPSET )
974 MYFIRSTROW = MIN( NQB+1, 1+ROWSPERPROC*MYSETNUM )
975 NUMROWS = MIN( ROWSPERPROC, NQB-MYFIRSTROW+1 )
980 CALL CGEMV( 'c
', NUMROWS, BINDEX+1, Z_ONE,
981 $ WORK( INHTB+MYFIRSTROW-1 ), LDV,
982 $ WORK( INHTB+MYFIRSTROW-1+( BINDEX+1 )*LDV ),
983 $ 1, Z_ZERO, WORK( INTMP ), 1 )
985 CALL CGEMV( 'c
', NUMROWS, BINDEX+1, Z_ONE,
986 $ WORK( INVTB+MYFIRSTROW-1 ), LDV,
987 $ WORK( INHTB+MYFIRSTROW-1+( BINDEX+1 )*LDV ),
988 $ 1, Z_ZERO, WORK( INTMP+BINDEX+1 ), 1 )
991 CALL CGSUM2D( ICTXT, 'c
', ' ', 2*( BINDEX+1 ), 1,
992 $ WORK( INTMP ), 2*( BINDEX+1 ), -1, -1 )
996 CALL CGEMV( 'c
', NQB, BINDEX+1, Z_ONE, WORK( INHTB ),
997 $ LDV, WORK( INHTB+( BINDEX+1 )*LDV ), 1,
998 $ Z_ZERO, WORK( INTMP ), 1 )
1000 CALL CGEMV( 'c
', NQB, BINDEX+1, Z_ONE, WORK( INVTB ),
1001 $ LDV, WORK( INHTB+( BINDEX+1 )*LDV ), 1,
1002 $ Z_ZERO, WORK( INTMP+BINDEX+1 ), 1 )
1011 ROWSPERPROC = ICEIL( NPB, NPSET )
1012 MYFIRSTROW = MIN( NPB+1, 1+ROWSPERPROC*MYSETNUM )
1013 NUMROWS = MIN( ROWSPERPROC, NPB-MYFIRSTROW+1 )
1015 CALL CGSUM2D( ICTXT, 'r
', ' ', 2*( BINDEX+1 ), 1,
1016 $ WORK( INTMP ), 2*( BINDEX+1 ), -1, -1 )
1020.GT.
IF( INDEX1. ) THEN
1021 CALL CGEMV( 'n
', NUMROWS, BINDEX+1, Z_NEGONE,
1022 $ WORK( INVB+MYFIRSTROW-1 ), LDV,
1023 $ WORK( INTMP ), 1, Z_ONE,
1024 $ WORK( INVB+MYFIRSTROW-1+( BINDEX+1 )*
1028 CALL CGEMV( 'n
', NUMROWS, BINDEX+1, Z_NEGONE,
1029 $ WORK( INHB+MYFIRSTROW-1 ), LDV,
1030 $ WORK( INTMP+BINDEX+1 ), 1, Z_ONE,
1031 $ WORK( INVB+MYFIRSTROW-1+( BINDEX+1 )*
1037 CALL CGEMV( 'n
', NPB, BINDEX+1, Z_NEGONE, WORK( INVB ),
1038 $ LDV, WORK( INTMP ), 1, Z_ONE,
1039 $ WORK( INVB+( BINDEX+1 )*LDV ), 1 )
1043 CALL CGEMV( 'n
', NPB, BINDEX+1, Z_NEGONE, WORK( INHB ),
1044 $ LDV, WORK( INTMP+BINDEX+1 ), 1, Z_ONE,
1045 $ WORK( INVB+( BINDEX+1 )*LDV ), 1 )
1052.EQ.
IF( MYROWMYCOL ) THEN
1053 DO 120 I = 0, NQM1 - 1
1054 WORK( INTMP+I ) = WORK( INVT+LIJP1-1+( BINDEX+1 )*LDV+
1058 CALL CGESD2D( ICTXT, NQM1, 1,
1059 $ WORK( INVT+LIJP1-1+( BINDEX+1 )*LDV ),
1060 $ NQM1, MYCOL, MYROW )
1061 CALL CGERV2D( ICTXT, NPM1, 1, WORK( INTMP ), NPM1, MYCOL,
1065 DO 130 I = 0, NPM1 - 1
1066 WORK( INV+LIIP1-1+( BINDEX+1 )*LDV+I ) = WORK( INV+LIIP1-
1067 $ 1+( BINDEX+1 )*LDV+I ) + WORK( INTMP+I )
1072 CALL CGSUM2D( ICTXT, 'r
', ' ', NPM1, 1,
1073 $ WORK( INV+LIIP1-1+( BINDEX+1 )*LDV ), NPM1,
1081.EQ.
IF( MYCOLNXTCOL ) THEN
1083 DO 140 I = 0, NPM1 - 1
1084 CC( 1 ) = CC( 1 ) + CONJG( WORK( INV+LIIP1-1+( BINDEX+
1085 $ 1 )*LDV+I ) )*WORK( INH+LIIP1-1+
1086 $ ( BINDEX+1 )*LDV+I )
1088.EQ.
IF( MYROWNXTROW ) THEN
1089 CC( 2 ) = WORK( INV+LIIP1-1+( BINDEX+1 )*LDV )
1090 CC( 3 ) = WORK( INH+LIIP1-1+( BINDEX+1 )*LDV )
1095 CALL CGSUM2D( ICTXT, 'c
', ' ', 3, 1, CC, 3, -1, NXTCOL )
1101 TOPNV = TOPTAU*( TOPV-C*CONJG( TOPTAU ) / 2*TOPH )
1107 DO 150 I = 0, NPM1 - 1
1108 WORK( INV+LIIP1-1+( BINDEX+1 )*LDV+I ) = TOPTAU*
1109 $ ( WORK( INV+LIIP1-1+( BINDEX+1 )*LDV+I )-C*
1110 $ CONJG( TOPTAU ) / 2*WORK( INH+LIIP1-1+( BINDEX+1 )*
1122.LT.
IF( MAXINDEXN ) THEN
1124 DO 170 I = 0, NPM1 - 1
1125 WORK( INTMP+I ) = WORK( INH+LIIP1-1+ANB*LDV+I )
1130.NOT.
IF( TWOGEMMS ) THEN
1131 IF( INTERLEAVE ) THEN
1134 CALL CLAMOV( 'a
', LTNM1, ANB, WORK( INHT+LIJP1-1 ),
1135 $ LDV, WORK( INVT+LIJP1-1+ANB*LDV ), LDV )
1137 CALL CLAMOV( 'a
', LTNM1, ANB, WORK( INV+LTLIP1-1 ),
1138 $ LDV, WORK( INH+LTLIP1-1+ANB*LDV ), LDV )
1148 DO 180 PBMIN = 1, LTNM1, PNB
1150 PBSIZE = MIN( PNB, LTNM1-PBMIN+1 )
1151 PBMAX = MIN( LTNM1, PBMIN+PNB-1 )
1152 CALL CGEMM( 'n
', 'c
', PBSIZE, PBMAX, NBZG, Z_NEGONE,
1153 $ WORK( INH+LTLIP1-1+PBMIN-1 ), LDZG,
1154 $ WORK( INVT+LIJP1-1 ), LDZG, Z_ONE,
1155 $ A( LTLIP1+PBMIN-1+( LIJP1-1 )*LDA ), LDA )
1157 CALL CGEMM( 'n
', 'c
', PBSIZE, PBMAX, ANB, Z_NEGONE,
1158 $ WORK( INV+LTLIP1-1+PBMIN-1 ), LDZG,
1159 $ WORK( INHT+LIJP1-1 ), LDZG, Z_ONE,
1160 $ A( LTLIP1+PBMIN-1+( LIJP1-1 )*LDA ), LDA )
1166 DO 190 I = 0, NPM1 - 1
1167 WORK( INV+LIIP1-1+I ) = WORK( INV+LIIP1-1+ANB*LDV+I )
1168 WORK( INH+LIIP1-1+I ) = WORK( INTMP+I )
1170 DO 200 I = 0, NQM1 - 1
1171 WORK( INHT+LIJP1-1+I ) = WORK( INHT+LIJP1-1+ANB*LDV+I )
1181.EQ.
IF( MYCOLNXTCOL ) THEN
1182.EQ.
IF( MYROWNXTROW ) THEN
1184 D( NQ ) = REAL( A( NP+( NQ-1 )*LDA ) )
1185 A( NP+( NQ-1 )*LDA ) = D( NQ )
1187 CALL SGEBS2D( ICTXT, 'c
', ' ', 1, 1, D( NQ ), 1 )
1189 CALL SGEBR2D( ICTXT, 'c
', ' ', 1, 1, D( NQ ), 1, NXTROW,
1197 WORK( 1 ) = CMPLX( LWMIN )