1 SUBROUTINE pzdttrsv( 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*16 AF( * ), B( * ), D( * ), DL( * ), DU( * ),
387 DOUBLE PRECISION ONE, ZERO
388 parameter( one = 1.0d+0 )
389 parameter( zero = 0.0d+0 )
390 COMPLEX*16 CONE, CZERO
391 parameter( cone = ( 1.0d+0, 0.0d+0 ) )
392 parameter( czero = ( 0.0d+0, 0.0d+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 )
416 EXTERNAL blacs_get, blacs_gridexit, blacs_gridinfo,
418 $ zgerv2d, zgesd2d, zlamov,
zmatadd, ztbtrs,
425 EXTERNAL lsame, numroc, zdotc
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 )
496 CALL blacs_gridinfo( ictxt, nprow, npcol, myrow, mycol )
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 IF( lwork .LT. -1)
THEN
519 ELSE IF ( lwork .EQ. -1 )
THEN
529 IF( n+ja-1 .GT. store_n_a )
THEN
530 info = -( 9*100 + 6 )
533 IF( n+ib-1 .GT. store_m_b )
THEN
534 info = -( 12*100 + 3 )
537 IF( lldb .LT. nb )
THEN
538 info = -( 12*100 + 6 )
541 IF( nrhs .LT. 0 )
THEN
553 IF( nprow .NE. 1 )
THEN
557 IF( n .GT. np*nb-mod( ja-1, nb ))
THEN
560 $
'PZDTTRSV, D&C alg.: only 1 block per proc',
565 IF((ja+n-1.GT.nb) .AND. ( nb.LT.2*int_one ))
THEN
568 $
'PZDTTRSV, D&C alg.: NB too small',
577 work( 1 ) = work_size_min
579 IF( lwork .LT. work_size_min )
THEN
580 IF( lwork .NE. -1 )
THEN
583 $
'PZDTTRSV: worksize error',
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 ELSE IF( info.LT.-descmult )
THEN
634 info = -info * descmult
639 CALL globchk( ictxt, 16, param_check, 16,
640 $ param_check( 1, 3 ), info )
645 IF( info.EQ.bignum )
THEN
647 ELSE IF( mod( info, descmult ) .EQ. 0 )
THEN
648 info = -info / descmult
654 CALL pxerbla( ictxt,
'PZDTTRSV', -info )
670 part_offset = nb*( (ja-1)/(npcol*nb) )
672 IF ( (mycol-csrc) .LT. (ja-part_offset-1)/nb )
THEN
673 part_offset = part_offset + nb
676 IF ( mycol .LT. 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 IF( myrow .LT. 0 )
THEN
728 my_num_cols = numroc( n, part_size, mycol, 0, npcol )
732 IF ( mycol .EQ. 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 IF ( mycol .LT. 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 zdttrsv( 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 IF ( mycol .LT. np-1 )
THEN
774 CALL zaxpy( nrhs, -dl( part_offset+odd_size+1 ),
775 $ b( part_offset+odd_size ), lldb,
776 $ b( part_offset+odd_size+1 ), lldb )
781 IF ( mycol .NE. 0 )
THEN
785 CALL zgemm(
'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 IF( mycol .GT. 0)
THEN
800 CALL zgesd2d( ictxt, int_one, nrhs,
801 $ work( 1 ), int_one,
808 IF( mycol .LT. npcol-1)
THEN
810 CALL zgerv2d( ictxt, int_one, nrhs,
811 $ work( 1 ), int_one,
816 CALL zmatadd( int_one, nrhs, cone,
817 $ work( 1 ), int_one, cone,
818 $ b( part_offset+odd_size + 1 ), lldb )
825 IF( mycol .EQ. npcol-1 )
THEN
840 IF( mod( (mycol+1)/level_dist, 2) .NE. 0 )
GOTO 11
844 IF( mycol-level_dist .GE. 0 )
THEN
846 CALL zgerv2d( ictxt, int_one, nrhs,
848 $ int_one, 0, mycol-level_dist )
850 CALL zmatadd( int_one, nrhs, cone,
851 $ work( 1 ), int_one, cone,
852 $ b( part_offset+odd_size + 1 ), lldb )
858 IF( mycol+level_dist .LT. npcol-1 )
THEN
860 CALL zgerv2d( ictxt, int_one, nrhs,
862 $ int_one, 0, mycol+level_dist )
864 CALL zmatadd( 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 ztbtrs(
'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 IF( mycol/level_dist .LE. (npcol-1)/level_dist-2 )
THEN
898 CALL zgemm(
'C',
'N', int_one, nrhs, int_one, -cone,
899 $ af( (odd_size)*int_one+1 ),
901 $ b( part_offset+odd_size+1 ),
908 CALL zgesd2d( ictxt, int_one, nrhs,
910 $ int_one, 0, mycol+level_dist )
916 IF( (mycol/level_dist .GT. 0 ).AND.
917 $ ( mycol/level_dist .LE. (npcol-1)/level_dist-1 ) )
THEN
923 CALL zgemm(
'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 zgesd2d( ictxt, int_one, nrhs,
935 $ int_one, 0, mycol-level_dist )
954 IF( mycol .EQ. npcol-1 )
THEN
962 IF( mod( (mycol+1)/level_dist, 2) .NE. 0 )
GOTO 26
964 level_dist = level_dist*2
970 IF( (mycol/level_dist .GT. 0 ).AND.
971 $ ( mycol/level_dist .LE. (npcol-1)/level_dist-1 ) )
THEN
975 CALL zgerv2d( ictxt, int_one, nrhs,
977 $ int_one, 0, mycol-level_dist )
983 CALL zgemm(
'C',
'N', int_one, nrhs, int_one, -cone,
984 $ af( odd_size*int_one+2+1 ),
988 $ b( part_offset+odd_size+1 ),
994 IF( mycol/level_dist .LE. (npcol-1)/level_dist-2 )
THEN
998 CALL zgerv2d( ictxt, int_one, nrhs,
1000 $ int_one, 0, mycol+level_dist )
1004 CALL zgemm(
'N',
'N', int_one, nrhs, int_one, -cone,
1005 $ af( (odd_size)*int_one+1 ),
1009 $ b( part_offset+odd_size+1 ),
1018 CALL ztbtrs(
'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 IF( info.NE.0 )
THEN
1031 IF( level_dist .EQ. 1 )
GOTO 21
1033 level_dist = level_dist/2
1037 IF( mycol+level_dist .LT. npcol-1 )
THEN
1039 CALL zgesd2d( ictxt, int_one, nrhs,
1040 $ b( part_offset+odd_size+1 ),
1041 $ lldb, 0, mycol+level_dist )
1047 IF( mycol-level_dist .GE. 0 )
THEN
1049 CALL zgesd2d( ictxt, int_one, nrhs,
1050 $ b( part_offset+odd_size+1 ),
1051 $ lldb, 0, mycol-level_dist )
1069 IF( mycol .LT. npcol-1)
THEN
1071 CALL zgesd2d( ictxt, int_one, nrhs,
1072 $ b( part_offset+odd_size+1 ), lldb,
1079 IF( mycol .GT. 0)
THEN
1081 CALL zgerv2d( ictxt, int_one, nrhs,
1082 $ work( 1 ), int_one,
1093 IF ( mycol .NE. 0 )
THEN
1097 CALL zgemm(
'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 zaxpy( nrhs, -dconjg( dl( part_offset+odd_size+1 ) ),
1109 $ b( part_offset+odd_size+1 ), lldb,
1110 $ b( part_offset+odd_size ), lldb )
1116 CALL zdttrsv( 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 zdttrsv( 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 zaxpy( nrhs, -dconjg( 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 zgemm(
'C',
'N', int_one, nrhs, odd_size, -cone,
1160 $ af( work_u+1 ), odd_size, b( part_offset+1 ),
1161 $ lldb, czero, work( 1+int_one-int_one ),
1173 IF( mycol .GT. 0)
THEN
1175 CALL zgesd2d( ictxt, int_one, nrhs,
1176 $ work( 1 ), int_one,
1183 IF( mycol .LT. npcol-1)
THEN
1185 CALL zgerv2d( ictxt, int_one, nrhs,
1186 $ work( 1 ), int_one,
1191 CALL zmatadd( 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 zgerv2d( ictxt, int_one, nrhs,
1223 $ int_one, 0, mycol-level_dist )
1225 CALL zmatadd( 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 zgerv2d( ictxt, int_one, nrhs,
1237 $ int_one, 0, mycol+level_dist )
1239 CALL zmatadd( 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 ztbtrs(
'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 zgemm(
'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 zgesd2d( 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 zgemm(
'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 zgesd2d( 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 zgerv2d( ictxt, int_one, nrhs,
1352 $ int_one, 0, mycol-level_dist )
1358 CALL zgemm(
'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 zgerv2d( ictxt, int_one, nrhs,
1375 $ int_one, 0, mycol+level_dist )
1379 CALL zgemm(
'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 ztbtrs(
'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 zgesd2d( 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 zgesd2d( 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 zgesd2d( ictxt, int_one, nrhs,
1447 $ b( part_offset+odd_size+1 ), lldb,
1454 IF( mycol .GT. 0)
THEN
1456 CALL zgerv2d( ictxt, int_one, nrhs,
1457 $ work( 1 ), int_one,
1468 IF ( mycol .NE. 0 )
THEN
1472 CALL zgemm(
'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 zaxpy( nrhs, -( du( part_offset+odd_size ) ),
1485 $ b( part_offset+odd_size+1 ), lldb,
1486 $ b( part_offset+odd_size ), lldb )
1492 CALL zdttrsv( 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
1508 CALL blacs_gridexit( ictxt_new )
1520 work( 1 ) = work_size_min