1 SUBROUTINE pcdttrsv( UPLO, TRANS, N, NRHS, DL, D, DU, JA, DESCA,
2 $ B, IB, DESCB, AF, LAF, WORK, LWORK, INFO )
10 INTEGER IB, INFO, JA, LAF, LWORK, N, NRHS
13 INTEGER DESCA( * ), DESCB( * )
14 COMPLEX AF( * ), B( * ), D( * ), DL( * ), DU( * ),
388 parameter( one = 1.0e+0 )
389 parameter( zero = 0.0e+0 )
391 PARAMETER ( cone = ( 1.0e+0, 0.0e+0 ) )
392 parameter( czero = ( 0.0e+0, 0.0e+0 ) )
394 parameter( int_one = 1 )
395 INTEGER DESCMULT, BIGNUM
396 parameter(descmult = 100, bignum = descmult * descmult)
397 INTEGER BLOCK_CYCLIC_2D, CSRC_, CTXT_, DLEN_, DTYPE_,
398 $ lld_, mb_, m_, nb_, n_, rsrc_
399 parameter( block_cyclic_2d = 1, dlen_ = 9, dtype_ = 1,
400 $ ctxt_ = 2, m_ = 3, n_ = 4, mb_ = 5, nb_ = 6,
401 $ rsrc_ = 7, csrc_ = 8, lld_ = 9 )
404 INTEGER CSRC, FIRST_PROC, ICTXT, ICTXT_NEW, ICTXT_SAVE,
405 $ idum1, idum2, idum3, ja_new, level_dist, llda,
406 $ lldb, mycol, myrow, my_num_cols, nb, np, npcol,
407 $ nprow, np_save, odd_size, part_offset,
408 $ part_size, return_code, store_m_b, store_n_a,
409 $ temp, work_size_min, work_u
412 INTEGER DESCA_1XP( 7 ), DESCB_PX1( 7 ),
413 $ param_check( 16, 3 )
425 EXTERNAL cdotc, lsame, numroc
428 INTRINSIC ichar,
min, mod
442 temp = desca( dtype_ )
443 IF( temp .EQ. 502 )
THEN
445 desca( dtype_ ) = 501
450 desca( dtype_ ) = temp
452 IF( return_code .NE. 0)
THEN
453 info = -( 9*100 + 2 )
458 IF( return_code .NE. 0)
THEN
459 info = -( 12*100 + 2 )
465 IF( desca_1xp( 2 ) .NE. descb_px1( 2 ) )
THEN
466 info = -( 12*100 + 2 )
473 IF( desca_1xp( 4 ) .NE. descb_px1( 4 ) )
THEN
474 info = -( 12*100 + 4 )
479 IF( desca_1xp( 5 ) .NE. descb_px1( 5 ) )
THEN
480 info = -( 12*100 + 5 )
485 ictxt = desca_1xp( 2 )
486 csrc = desca_1xp( 5 )
488 llda = desca_1xp( 6 )
489 store_n_a = desca_1xp( 3 )
490 lldb = descb_px1( 6 )
491 store_m_b = descb_px1( 3 )
501 IF( lsame( uplo,
'U' ) )
THEN
503 ELSE IF ( lsame( uplo,
'L' ) )
THEN
509 IF( lsame( trans,
'N' ) )
THEN
511 ELSE IF ( LSAME( TRANS, 'c
' ) ) THEN
517.LT.
IF( LWORK -1) THEN
519.EQ.
ELSE IF ( LWORK -1 ) THEN
529.GT.
IF( N+JA-1 STORE_N_A ) THEN
530 INFO = -( 9*100 + 6 )
533.GT.
IF( N+IB-1 STORE_M_B ) THEN
534 INFO = -( 12*100 + 3 )
537.LT.
IF( LLDB NB ) THEN
538 INFO = -( 12*100 + 6 )
541.LT.
IF( NRHS 0 ) THEN
553.NE.
IF( NPROW 1 ) THEN
557.GT.
IF( N NP*NB-MOD( JA-1, NB )) THEN
560 $ 'pcdttrsv, d&c alg.: only 1 block per proc
',
565.GT..AND..LT.
IF((JA+N-1NB) ( NB2*INT_ONE )) THEN
568 $ 'pcdttrsv, d&c alg.: nb too small
',
577 WORK( 1 ) = WORK_SIZE_MIN
579.LT.
IF( LWORK WORK_SIZE_MIN ) THEN
580.NE.
IF( LWORK -1 ) THEN
591 PARAM_CHECK( 16, 1 ) = DESCB(5)
592 PARAM_CHECK( 15, 1 ) = DESCB(4)
593 PARAM_CHECK( 14, 1 ) = DESCB(3)
594 PARAM_CHECK( 13, 1 ) = DESCB(2)
595 PARAM_CHECK( 12, 1 ) = DESCB(1)
596 PARAM_CHECK( 11, 1 ) = IB
597 PARAM_CHECK( 10, 1 ) = DESCA(5)
598 PARAM_CHECK( 9, 1 ) = DESCA(4)
599 PARAM_CHECK( 8, 1 ) = DESCA(3)
600 PARAM_CHECK( 7, 1 ) = DESCA(1)
601 PARAM_CHECK( 6, 1 ) = JA
602 PARAM_CHECK( 5, 1 ) = NRHS
603 PARAM_CHECK( 4, 1 ) = N
604 PARAM_CHECK( 3, 1 ) = IDUM3
605 PARAM_CHECK( 2, 1 ) = IDUM2
606 PARAM_CHECK( 1, 1 ) = IDUM1
608 PARAM_CHECK( 16, 2 ) = 1205
609 PARAM_CHECK( 15, 2 ) = 1204
610 PARAM_CHECK( 14, 2 ) = 1203
611 PARAM_CHECK( 13, 2 ) = 1202
612 PARAM_CHECK( 12, 2 ) = 1201
613 PARAM_CHECK( 11, 2 ) = 11
614 PARAM_CHECK( 10, 2 ) = 905
615 PARAM_CHECK( 9, 2 ) = 904
616 PARAM_CHECK( 8, 2 ) = 903
617 PARAM_CHECK( 7, 2 ) = 901
618 PARAM_CHECK( 6, 2 ) = 8
619 PARAM_CHECK( 5, 2 ) = 4
620 PARAM_CHECK( 4, 2 ) = 3
621 PARAM_CHECK( 3, 2 ) = 16
622 PARAM_CHECK( 2, 2 ) = 2
623 PARAM_CHECK( 1, 2 ) = 1
631.LT.
ELSE IF( INFO-DESCMULT ) THEN
634 INFO = -INFO * DESCMULT
639 CALL GLOBCHK( ICTXT, 16, PARAM_CHECK, 16,
640 $ PARAM_CHECK( 1, 3 ), INFO )
645.EQ.
IF( INFOBIGNUM ) THEN
647.EQ.
ELSE IF( MOD( INFO, DESCMULT ) 0 ) THEN
648 INFO = -INFO / DESCMULT
654 CALL PXERBLA( ICTXT, 'pcdttrsv', -INFO )
670 PART_OFFSET = NB*( (JA-1)/(NPCOL*NB) )
672.LT.
IF ( (MYCOL-CSRC) (JA-PART_OFFSET-1)/NB ) THEN
673 PART_OFFSET = PART_OFFSET + NB
676.LT.
IF ( MYCOL CSRC ) THEN
677 PART_OFFSET = PART_OFFSET - NB
686 FIRST_PROC = MOD( ( JA-1 )/NB+CSRC, NPCOL )
690 JA_NEW = MOD( JA-1, NB ) + 1
695 NP = ( JA_NEW+N-2 )/NB + 1
699 CALL RESHAPE( ICTXT, INT_ONE, ICTXT_NEW, INT_ONE,
700 $ FIRST_PROC, INT_ONE, NP )
706 DESCA_1XP( 2 ) = ICTXT_NEW
707 DESCB_PX1( 2 ) = ICTXT_NEW
711 CALL BLACS_GRIDINFO( ICTXT, NPROW, NPCOL, MYROW, MYCOL )
715.LT.
IF( MYROW 0 ) THEN
728 MY_NUM_COLS = NUMROC( N, PART_SIZE, MYCOL, 0, NPCOL )
732.EQ.
IF ( MYCOL 0 ) THEN
733 PART_OFFSET = PART_OFFSET+MOD( JA_NEW-1, PART_SIZE )
734 MY_NUM_COLS = MY_NUM_COLS - MOD(JA_NEW-1, PART_SIZE )
739 ODD_SIZE = MY_NUM_COLS
740.LT.
IF ( MYCOL NP-1 ) THEN
741 ODD_SIZE = ODD_SIZE - INT_ONE
746 WORK_U = INT_ONE*ODD_SIZE + 3
752 IF ( LSAME( UPLO, 'l
' ) ) THEN
754 IF ( LSAME( TRANS, 'n
' ) ) THEN
765 CALL CDTTRSV( UPLO, 'n
', ODD_SIZE, NRHS, DL( PART_OFFSET+2 ),
766 $ D( PART_OFFSET+1 ), DU( PART_OFFSET+1 ),
767 $ B( PART_OFFSET+1 ), LLDB, INFO )
770.LT.
IF ( MYCOL NP-1 ) THEN
774 CALL CAXPY( NRHS, -DL( PART_OFFSET+ODD_SIZE+1 ),
775 $ B( PART_OFFSET+ODD_SIZE ), LLDB,
776 $ B( PART_OFFSET+ODD_SIZE+1 ), LLDB )
781.NE.
IF ( MYCOL 0 ) THEN
785 CALL CGEMM( 'c
', 'n
', INT_ONE, NRHS, ODD_SIZE, -CONE,
786 $ AF( 1 ), ODD_SIZE, B( PART_OFFSET+1 ), LLDB,
787 $ CZERO, WORK( 1+INT_ONE-INT_ONE ), INT_ONE )
798.GT.
IF( MYCOL 0) THEN
800 CALL CGESD2D( ICTXT, INT_ONE, NRHS,
801 $ WORK( 1 ), INT_ONE,
808.LT.
IF( MYCOL NPCOL-1) THEN
810 CALL CGERV2D( ICTXT, INT_ONE, NRHS,
811 $ WORK( 1 ), INT_ONE,
816 CALL CMATADD( INT_ONE, NRHS, CONE,
817 $ WORK( 1 ), INT_ONE, CONE,
818 $ B( PART_OFFSET+ODD_SIZE + 1 ), LLDB )
825.EQ.
IF( MYCOL NPCOL-1 ) THEN
840.NE.
IF( MOD( (MYCOL+1)/LEVEL_DIST, 2) 0 ) GOTO 11
844.GE.
IF( MYCOL-LEVEL_DIST 0 ) THEN
846 CALL CGERV2D( ICTXT, INT_ONE, NRHS,
848 $ INT_ONE, 0, MYCOL-LEVEL_DIST )
850 CALL CMATADD( INT_ONE, NRHS, CONE,
851 $ WORK( 1 ), INT_ONE, CONE,
852 $ B( PART_OFFSET+ODD_SIZE + 1 ), LLDB )
858.LT.
IF( MYCOL+LEVEL_DIST NPCOL-1 ) THEN
860 CALL CGERV2D( ICTXT, INT_ONE, NRHS,
862 $ INT_ONE, 0, MYCOL+LEVEL_DIST )
864 CALL CMATADD( INT_ONE, NRHS, CONE,
865 $ WORK( 1 ), INT_ONE, CONE,
866 $ B( PART_OFFSET+ODD_SIZE + 1 ), LLDB )
870 LEVEL_DIST = LEVEL_DIST*2
883 CALL CTBTRS( 'l
', 'n
', 'u
', INT_ONE, MIN( INT_ONE, INT_ONE-1 ),
884 $ NRHS, AF( ODD_SIZE+2 ), INT_ONE+1,
885 $ B( PART_OFFSET+ODD_SIZE+1 ), LLDB, INFO )
894.LE.
IF( MYCOL/LEVEL_DIST (NPCOL-1)/LEVEL_DIST-2 )THEN
898 CALL CGEMM( 'c
', 'n
', INT_ONE, NRHS, INT_ONE, -CONE,
899 $ AF( (ODD_SIZE)*INT_ONE+1 ),
901 $ B( PART_OFFSET+ODD_SIZE+1 ),
908 CALL CGESD2D( ICTXT, INT_ONE, NRHS,
910 $ INT_ONE, 0, MYCOL+LEVEL_DIST )
916.GT..AND.
IF( (MYCOL/LEVEL_DIST 0 )
917.LE.
$ ( MYCOL/LEVEL_DIST (NPCOL-1)/LEVEL_DIST-1 ) ) THEN
923 CALL CGEMM( 'n
', 'n
', INT_ONE, NRHS, INT_ONE, -CONE,
924 $ AF( ODD_SIZE*INT_ONE+2+1 ),
926 $ B( PART_OFFSET+ODD_SIZE+1 ),
933 CALL CGESD2D( ICTXT, INT_ONE, NRHS,
935 $ INT_ONE, 0, MYCOL-LEVEL_DIST )
954.EQ.
IF( MYCOL NPCOL-1 ) THEN
962.NE.
IF( MOD( (MYCOL+1)/LEVEL_DIST, 2) 0 ) GOTO 26
964 LEVEL_DIST = LEVEL_DIST*2
970.GT..AND.
IF( (MYCOL/LEVEL_DIST 0 )
971.LE.
$ ( MYCOL/LEVEL_DIST (NPCOL-1)/LEVEL_DIST-1 ) ) THEN
975 CALL CGERV2D( ICTXT, INT_ONE, NRHS,
977 $ INT_ONE, 0, MYCOL-LEVEL_DIST )
983 CALL CGEMM( 'c
', 'n
', INT_ONE, NRHS, INT_ONE, -CONE,
984 $ AF( ODD_SIZE*INT_ONE+2+1 ),
988 $ B( PART_OFFSET+ODD_SIZE+1 ),
994.LE.
IF( MYCOL/LEVEL_DIST (NPCOL-1)/LEVEL_DIST-2 )THEN
998 CALL CGERV2D( ICTXT, INT_ONE, NRHS,
1000 $ INT_ONE, 0, MYCOL+LEVEL_DIST )
1004 CALL CGEMM( 'n
', 'n
', INT_ONE, NRHS, INT_ONE, -CONE,
1005 $ AF( (ODD_SIZE)*INT_ONE+1 ),
1009 $ B( PART_OFFSET+ODD_SIZE+1 ),
1018 CALL CTBTRS( 'l
', 'c
', 'u
', INT_ONE, MIN( INT_ONE, INT_ONE-1 ),
1019 $ NRHS, AF( ODD_SIZE+2 ), INT_ONE+1,
1020 $ B( PART_OFFSET+ODD_SIZE+1 ), LLDB, INFO )
1022.NE.
IF( INFO0 ) THEN
1031.EQ.
IF( LEVEL_DIST 1 ) GOTO 21
1033 LEVEL_DIST = LEVEL_DIST/2
1037.LT.
IF( MYCOL+LEVEL_DIST NPCOL-1 ) THEN
1039 CALL CGESD2D( ICTXT, INT_ONE, NRHS,
1040 $ B( PART_OFFSET+ODD_SIZE+1 ),
1041 $ LLDB, 0, MYCOL+LEVEL_DIST )
1047.GE.
IF( MYCOL-LEVEL_DIST 0 ) THEN
1049 CALL CGESD2D( ICTXT, INT_ONE, NRHS,
1050 $ B( PART_OFFSET+ODD_SIZE+1 ),
1051 $ LLDB, 0, MYCOL-LEVEL_DIST )
1069.LT.
IF( MYCOL NPCOL-1) THEN
1071 CALL CGESD2D( ICTXT, INT_ONE, NRHS,
1072 $ B( PART_OFFSET+ODD_SIZE+1 ), LLDB,
1079.GT.
IF( MYCOL 0) THEN
1081 CALL CGERV2D( ICTXT, INT_ONE, NRHS,
1082 $ WORK( 1 ), INT_ONE,
1093.NE.
IF ( MYCOL 0 ) THEN
1097 CALL CGEMM( 'n',
'N', odd_size, nrhs, int_one, -cone, af( 1 ),
1098 $ odd_size, work( 1+int_one-int_one ), int_one,
1099 $ cone, b( part_offset+1 ), lldb )
1104 IF ( mycol .LT. np-1 )
THEN
1108 CALL caxpy( nrhs, -conjg( dl( part_offset+odd_size+1 ) ),
1109 $ b( part_offset+odd_size+1 ), lldb,
1110 $ b( part_offset+odd_size ), lldb )
1116 CALL cdttrsv( uplo,
'C', odd_size, nrhs, dl( part_offset+2 ),
1117 $ d( part_offset+1 ), du( part_offset+1 ),
1118 $ b( part_offset+1 ), lldb, info )
1128 IF ( lsame( trans,
'C' ) )
THEN
1139 CALL cdttrsv( uplo,
'C', odd_size, nrhs, dl( part_offset+2 ),
1140 $ d( part_offset+1 ), du( part_offset+1 ),
1141 $ b( part_offset+1 ), lldb, info )
1144 IF ( mycol .LT. np-1 )
THEN
1148 CALL caxpy( nrhs, -conjg( du( part_offset+odd_size ) ),
1149 $ b( part_offset+odd_size ), lldb,
1150 $ b( part_offset+odd_size+1 ), lldb )
1155 IF ( mycol .NE. 0 )
THEN
1159 CALL cgemm(
'C',
'N', int_one, nrhs, odd_size, -cone,
1160 $ af( work_u+1 ), odd_size, b( part_offset
1161 $ lldb, czero, work( 1+int_one-int_one ),
1173 IF( mycol .GT. 0)
THEN
1175 CALL cgesd2d( ictxt, int_one, nrhs,
1176 $ work( 1 ), int_one,
1183 IF( mycol .LT. npcol-1)
THEN
1185 CALL cgerv2d( ictxt, int_one, nrhs,
1186 $ work( 1 ), int_one,
1191 CALL cmatadd( int_one, nrhs, cone,
1192 $ work( 1 ), int_one, cone,
1193 $ b( part_offset+odd_size + 1 ), lldb )
1200 IF( mycol .EQ. npcol-1 )
THEN
1215 IF( mod( (mycol+1)/level_dist, 2) .NE. 0 )
GOTO 41
1219 IF( mycol-level_dist .GE. 0 )
THEN
1221 CALL cgerv2d( ictxt, int_one, nrhs,
1223 $ int_one, 0, mycol-level_dist )
1225 CALL cmatadd( int_one, nrhs, cone,
1226 $ work( 1 ), int_one, cone,
1227 $ b( part_offset+odd_size + 1 ), lldb )
1233 IF( mycol+level_dist .LT. npcol-1 )
THEN
1235 CALL cgerv2d( ictxt, int_one, nrhs,
1237 $ int_one, 0, mycol+level_dist )
1239 CALL cmatadd( int_one, nrhs, cone,
1240 $ work( 1 ), int_one, cone,
1241 $ b( part_offset+odd_size + 1 ), lldb )
1245 level_dist = level_dist*2
1258 CALL ctbtrs(
'U',
'C',
'N', int_one,
min( int_one, int_one-1 ),
1259 $ nrhs, af( odd_size+2 ), int_one+1,
1260 $ b( part_offset+odd_size+1 ), lldb, info )
1262 IF( info.NE.0 )
THEN
1269 IF( mycol/level_dist .LE. (npcol-1)/level_dist-2 )
THEN
1273 CALL cgemm(
'C',
'N', int_one, nrhs, int_one, -cone,
1274 $ af( work_u+(odd_size)*int_one+1 ),
1276 $ b( part_offset+odd_size+1 ),
1283 CALL cgesd2d( ictxt, int_one, nrhs,
1285 $ int_one, 0, mycol+level_dist )
1291 IF( (mycol/level_dist .GT. 0 ).AND.
1292 $ ( mycol/level_dist .LE. (npcol-1)/level_dist-1 ) )
THEN
1298 CALL cgemm(
'N',
'N', int_one, nrhs, int_one, -cone,
1299 $ af( work_u+odd_size*int_one+2+1 ),
1301 $ b( part_offset+odd_size+1 ),
1308 CALL cgesd2d( ictxt, int_one, nrhs,
1310 $ int_one, 0, mycol-level_dist )
1329 IF( mycol .EQ. npcol-1 )
THEN
1337 IF( mod( (mycol+1)/level_dist, 2) .NE. 0 )
GOTO 56
1339 level_dist = level_dist*2
1345 IF( (mycol/level_dist .GT. 0 ).AND.
1346 $ ( mycol/level_dist .LE. (npcol-1)/level_dist-1 ) )
THEN
1350 CALL cgerv2d( ictxt, int_one, nrhs,
1352 $ int_one, 0, mycol-level_dist )
1358 CALL cgemm(
'C',
'N', int_one, nrhs, int_one, -cone,
1359 $ af( work_u+odd_size*int_one+2+1 ),
1363 $ b( part_offset+odd_size+1 ),
1369 IF( mycol/level_dist .LE. (npcol-1)/level_dist-2 )
THEN
1373 CALL cgerv2d( ictxt, int_one, nrhs,
1375 $ int_one, 0, mycol+level_dist )
1379 CALL cgemm(
'N',
'N', int_one, nrhs, int_one, -cone,
1380 $ af( work_u+(odd_size)*int_one+1 ),
1384 $ b( part_offset+odd_size+1 ),
1393 CALL ctbtrs(
'U',
'N',
'N', int_one,
min( int_one, int_one-1 ),
1394 $ nrhs, af( odd_size+2 ), int_one+1,
1395 $ b( part_offset+odd_size+1 ), lldb, info )
1397 IF( info.NE.0 )
THEN
1406 IF( level_dist .EQ. 1 )
GOTO 51
1408 level_dist = level_dist/2
1412 IF( mycol+level_dist .LT. npcol-1 )
THEN
1414 CALL cgesd2d( ictxt, int_one, nrhs,
1415 $ b( part_offset+odd_size+1 ),
1416 $ lldb, 0, mycol+level_dist )
1422 IF( mycol-level_dist .GE. 0 )
THEN
1424 CALL cgesd2d( ictxt, int_one, nrhs,
1425 $ b( part_offset+odd_size+1 ),
1426 $ lldb, 0, mycol-level_dist )
1444 IF( mycol .LT. npcol-1)
THEN
1446 CALL cgesd2d( ictxt, int_one, nrhs,
1447 $ b( part_offset+odd_size+1 ), lldb,
1454 IF( mycol .GT. 0)
THEN
1456 CALL cgerv2d( ictxt, int_one, nrhs,
1457 $ work( 1 ), int_one,
1468 IF ( mycol .NE. 0 )
THEN
1472 CALL cgemm(
'N',
'N', odd_size, nrhs, int_one, -cone,
1473 $ af( work_u+1 ), odd_size,
1474 $ work( 1+int_one-int_one ), int_one, cone,
1475 $ b( part_offset+1 ), lldb )
1480 IF ( mycol .LT. np-1 )
THEN
1484 CALL caxpy( nrhs, -( du( part_offset+odd_size ) ),
1485 $ b( part_offset+odd_size+1 ), lldb,
1486 $ b( part_offset+odd_size ), lldb )
1492 CALL cdttrsv( uplo,
'N', odd_size, nrhs, du( part_offset+2 ),
1493 $ d( part_offset+1 ), du( part_offset+1 ),
1494 $ b( part_offset+1 ), lldb, info )
1507 IF( ictxt_save .NE. ictxt_new )
THEN
1520 work( 1 ) = work_size_min