1 SUBROUTINE pzpbtrsv( UPLO, TRANS, N, BW, NRHS, A, JA, DESCA, B,
2 $ IB, DESCB, AF, LAF, WORK, LWORK, INFO )
10 INTEGER BW, , INFO, JA, LAF, LWORK, N, NRHS
13 INTEGER DESCA( * ), DESCB( * )
14 COMPLEX*16 A( * ), AF( * ), B(
370 DOUBLE PRECISION ONE, ZERO
371 parameter( one = 1.0d+0 )
372 parameter( zero = 0.0d+0 )
373 COMPLEX*16 CONE, CZERO
374 parameter( cone = ( 1.0d+0, 0.0d+0 ) )
375 parameter( czero = ( 0.0d+0, 0.0d+0 ) )
377 parameter( int_one = 1 )
378 INTEGER DESCMULT, BIGNUM
379 parameter(descmult = 100, bignum = descmult * descmult)
380 INTEGER BLOCK_CYCLIC_2D, CSRC_, CTXT_, DLEN_, DTYPE_,
381 $ lld_, mb_, m_, nb_, n_, rsrc_
382 parameter( block_cyclic_2d = 1, dlen_ = 9, dtype_ = 1,
383 $ ctxt_ = 2, m_ = 3, n_ = 4, mb_ = 5, nb_ = 6,
384 $ rsrc_ = 7, csrc_ = 8, lld_ = 9 )
387 INTEGER CSRC, FIRST_PROC, ICTXT, ICTXT_NEW, ICTXT_SAVE,
388 $ idum1, idum2, idum3, ja_new, level_dist, llda,
389 $ lldb, mbw2, mycol, myrow, my_num_cols, nb, np,
390 $ npcol, nprow, np_save, odd_size, ofst,
391 $ part_offset, part_size, return_code, store_m_b,
392 $ store_n_a, work_size_min
395 INTEGER DESCA_1XP( 7 ), DESCB_PX1( 7 ),
396 $ param_check( 17, 3 )
410 INTRINSIC ichar,
min, mod
426 IF( return_code .NE. 0)
THEN
427 info = -( 8*100 + 2 )
432 IF( return_code .NE. 0)
THEN
433 info = -( 11*100 + 2 )
439 IF( desca_1xp( 2 ) .NE. descb_px1( 2 ) )
THEN
440 info = -( 11*100 + 2 )
447 IF( desca_1xp( 4 ) .NE. descb_px1( 4 ) )
THEN
448 info = -( 11*100 + 4 )
453 IF( desca_1xp( 5 ) .NE. descb_px1( 5 ) )
THEN
454 info = -( 11*100 + 5 )
459 ictxt = desca_1xp( 2 )
460 csrc = desca_1xp( 5 )
462 llda = desca_1xp( 6 )
463 store_n_a = desca_1xp( 3 )
464 lldb = descb_px1( 6 )
465 store_m_b = descb_px1( 3 )
479 IF( lsame( uplo, 'u
' ) ) THEN
481 ELSE IF ( LSAME( UPLO, 'l
' ) ) THEN
487 IF( LSAME( TRANS, 'n
' ) ) THEN
489 ELSE IF ( LSAME( TRANS, 'c
' ) ) THEN
495.LT.
IF( LWORK -1) THEN
497.EQ.
ELSE IF ( LWORK -1 ) THEN
507.GT.
IF( N+JA-1 STORE_N_A ) THEN
508 INFO = -( 8*100 + 6 )
511.GT..OR.
IF(( BW N-1 )
512.LT.
$ ( BW 0 ) ) THEN
516.LT.
IF( LLDA (BW+1) ) THEN
517 INFO = -( 8*100 + 6 )
521 INFO = -( 8*100 + 4 )
524.GT.
IF( N+IB-1 STORE_M_B ) THEN
525 INFO = -( 11*100 + 3 )
528.LT.
IF( LLDB NB ) THEN
529 INFO = -( 11*100 + 6 )
532.LT.
IF( NRHS 0 ) THEN
544.NE.
IF( NPROW 1 ) THEN
548.GT.
IF( N NP*NB-MOD( JA-1, NB )) THEN
556.GT..AND..LT.
IF((JA+N-1NB) ( NB2*BW )) THEN
568 WORK( 1 ) = WORK_SIZE_MIN
570.LT.
IF( LWORK WORK_SIZE_MIN ) THEN
571.NE.
IF( LWORK -1 ) THEN
582 PARAM_CHECK( 17, 1 ) = DESCB(5)
583 PARAM_CHECK( 16, 1 ) = DESCB(4)
584 PARAM_CHECK( 15, 1 ) = DESCB(3)
585 PARAM_CHECK( 14, 1 ) = DESCB(2)
586 PARAM_CHECK( 13, 1 ) = DESCB(1)
587 PARAM_CHECK( 12, 1 ) = IB
588 PARAM_CHECK( 11, 1 ) = DESCA(5)
589 PARAM_CHECK( 10, 1 ) = DESCA(4)
590 PARAM_CHECK( 9, 1 ) = DESCA(3)
591 PARAM_CHECK( 8, 1 ) = DESCA(1)
592 PARAM_CHECK( 7, 1 ) = JA
593 PARAM_CHECK( 6, 1 ) = NRHS
594 PARAM_CHECK( 5, 1 ) = BW
595 PARAM_CHECK( 4, 1 ) = N
596 PARAM_CHECK( 3, 1 ) = IDUM3
597 PARAM_CHECK( 2, 1 ) = IDUM2
598 PARAM_CHECK( 1, 1 ) = IDUM1
600 PARAM_CHECK( 17, 2 ) = 1105
601 PARAM_CHECK( 16, 2 ) = 1104
602 PARAM_CHECK( 15, 2 ) = 1103
603 PARAM_CHECK( 14, 2 ) = 1102
604 PARAM_CHECK( 13, 2 ) = 1101
605 PARAM_CHECK( 12, 2 ) = 10
606 PARAM_CHECK( 11, 2 ) = 805
607 PARAM_CHECK( 10, 2 ) = 804
608 PARAM_CHECK( 9, 2 ) = 803
609 PARAM_CHECK( 8, 2 ) = 801
610 PARAM_CHECK( 7, 2 ) = 7
611 PARAM_CHECK( 6, 2 ) = 5
612 PARAM_CHECK( 5, 2 ) = 4
613 PARAM_CHECK( 4, 2 ) = 3
614 PARAM_CHECK( 3, 2 ) = 14
615 PARAM_CHECK( 2, 2 ) = 2
616 PARAM_CHECK( 1, 2 ) = 1
624.LT.
ELSE IF( INFO-DESCMULT ) THEN
627 INFO = -INFO * DESCMULT
632 CALL GLOBCHK( ICTXT, 17, PARAM_CHECK, 17,
633 $ PARAM_CHECK( 1, 3 ), INFO )
638.EQ.
IF( INFOBIGNUM ) THEN
640.EQ.
ELSE IF( MOD( INFO, DESCMULT ) 0 ) THEN
641 INFO = -INFO / DESCMULT
647 CALL PXERBLA( ICTXT, 'pzpbtrsv', -INFO )
663 PART_OFFSET = NB*( (JA-1)/(NPCOL*NB) )
665.LT.
IF ( (MYCOL-CSRC) (JA-PART_OFFSET-1)/NB ) THEN
666 PART_OFFSET = PART_OFFSET + NB
669.LT.
IF ( MYCOL CSRC ) THEN
670 PART_OFFSET = PART_OFFSET - NB
679 FIRST_PROC = MOD( ( JA-1 )/NB+CSRC, NPCOL )
683 JA_NEW = MOD( JA-1, NB ) + 1
688 NP = ( JA_NEW+N-2 )/NB + 1
692 CALL RESHAPE( ICTXT, INT_ONE, ICTXT_NEW, INT_ONE,
693 $ FIRST_PROC, INT_ONE, NP )
699 DESCA_1XP( 2 ) = ICTXT_NEW
700 DESCB_PX1( 2 ) = ICTXT_NEW
704 CALL BLACS_GRIDINFO( ICTXT, NPROW, NPCOL, MYROW, MYCOL )
708.LT.
IF( MYROW 0 ) THEN
721 MY_NUM_COLS = NUMROC( N, PART_SIZE, MYCOL, 0, NPCOL )
725.EQ.
IF ( MYCOL 0 ) THEN
726 PART_OFFSET = PART_OFFSET+MOD( JA_NEW-1, PART_SIZE )
727 MY_NUM_COLS = MY_NUM_COLS - MOD(JA_NEW-1, PART_SIZE )
732 OFST = PART_OFFSET*LLDA
736 ODD_SIZE = MY_NUM_COLS
737.LT.
IF ( MYCOL NP-1 ) THEN
738 ODD_SIZE = ODD_SIZE - BW
745 IF ( LSAME( UPLO, 'l
' ) ) THEN
747 IF ( LSAME( TRANS, 'n
' ) ) THEN
758 CALL ZTBTRS( UPLO, 'n',
'N', odd_size,
761 $ b( part_offset+1 ), lldb, info )
764 IF ( mycol .LT. np-1 )
THEN
772 CALL zlamov(
'N', bw, nrhs,
773 $ b( part_offset+odd_size-bw+1), lldb,
776 CALL ztrmm(
'L',
'U',
'N',
'N', bw, nrhs, -cone,
777 $ a(( ofst+(bw+1)+(odd_size-bw)*llda )), llda-1,
780 CALL zmatadd( bw, nrhs, cone, work( 1 ), bw,
781 $ cone, b( part_offset+odd_size+1 ), lldb )
786 IF ( mycol .NE. 0 )
THEN
790 CALL zgemm(
'C',
'N', bw, nrhs, odd_size, -cone, af( 1 ),
791 $ odd_size, b( part_offset+1 ), lldb, czero,
792 $ work( 1+bw-bw ), bw )
803 IF( mycol .GT. 0)
THEN
805 CALL zgesd2d( ictxt, bw, nrhs,
813 IF( mycol .LT. npcol-1)
THEN
815 CALL zgerv2d( ictxt, bw, nrhs,
822 $ work( 1 ), bw, cone,
823 $ b( part_offset+odd_size + 1 ), lldb )
830 IF( mycol .EQ. npcol-1 )
THEN
845 IF( mod( (mycol+1)/level_dist, 2) .NE. 0 )
GOTO 11
849 IF( mycol-level_dist .GE. 0 )
THEN
851 CALL zgerv2d( ictxt, bw, nrhs,
853 $ bw, 0, mycol-level_dist )
856 $ work( 1 ), bw, cone,
857 $ b( part_offset+odd_size + 1 ), lldb )
863 IF( mycol+level_dist .LT. npcol-1 )
THEN
865 CALL zgerv2d( ictxt, bw, nrhs,
867 $ bw, 0, mycol+level_dist )
870 $ work( 1 ), bw, cone,
871 $ b( part_offset+odd_size + 1 ), lldb )
875 level_dist = level_dist*2
888 CALL ztrtrs(
'L',
'N',
'N', bw, nrhs, af( odd_size*bw+mbw2+1 ),
889 $ bw, b( part_offset+odd_size+1 ), lldb, info )
898 IF( mycol/level_dist .LE. (npcol-1)/level_dist-2 )
THEN
902 CALL zgemm(
'C',
'N', bw, nrhs, bw, -cone,
903 $ af( (odd_size)*bw+1 ),
905 $ b( part_offset+odd_size+1 ),
912 CALL zgesd2d( ictxt, bw, nrhs,
914 $ bw, 0, mycol+level_dist )
920 IF( (mycol/level_dist .GT. 0 ).AND.
921 $ ( mycol/level_dist .LE. (npcol-1)/level_dist-1 ) )
THEN
927 CALL zgemm(
'N',
'N', bw, nrhs, bw, -cone,
928 $ af( odd_size*bw+2*mbw2+1 ),
930 $ b( part_offset+odd_size+1 ),
937 CALL zgesd2d( ictxt, bw, nrhs,
939 $ bw, 0, mycol-level_dist )
958 IF( mycol .EQ. npcol-1 )
THEN
966 IF( mod( (mycol+1)/level_dist, 2) .NE. 0 )
GOTO 26
968 level_dist = level_dist*2
974 IF( (mycol/level_dist .GT. 0 ).AND.
975 $ ( mycol/level_dist .LE. (npcol-1)/level_dist-1 ) )
THEN
979 CALL zgerv2d( ictxt, bw, nrhs,
981 $ bw, 0, mycol-level_dist )
987 CALL zgemm(
'C',
'N', bw, nrhs, bw, -cone,
988 $ af( odd_size*bw+2*mbw2+1 ),
992 $ b( part_offset+odd_size+1 ),
998 IF( mycol/level_dist .LE. (npcol-1)/level_dist-2 )
THEN
1002 CALL zgerv2d( ictxt, bw, nrhs,
1004 $ bw, 0, mycol+level_dist )
1008 CALL zgemm(
'N',
'N', bw, nrhs, bw, -cone,
1009 $ af( (odd_size)*bw+1 ),
1013 $ b( part_offset+odd_size+1 ),
1022 CALL ztrtrs(
'L',
'C',
'N', bw, nrhs, af( odd_size*bw+mbw2+1 ),
1023 $ bw, b( part_offset+odd_size+1 ), lldb, info )
1025 IF( info.NE.0 )
THEN
1034 IF( level_dist .EQ. 1 )
GOTO 21
1036 level_dist = level_dist/2
1040 IF( mycol+level_dist .LT. npcol-1 )
THEN
1042 CALL zgesd2d( ictxt, bw, nrhs,
1043 $ b( part_offset+odd_size+1 ),
1044 $ lldb, 0, mycol+level_dist )
1050 IF( mycol-level_dist .GE. 0 )
THEN
1052 CALL zgesd2d( ictxt, bw, nrhs,
1053 $ b( part_offset+odd_size+1 ),
1054 $ lldb, 0, mycol-level_dist )
1072 IF( mycol .LT. npcol-1)
THEN
1074 CALL zgesd2d( ictxt, bw, nrhs,
1075 $ b( part_offset+odd_size+1 ), lldb,
1082 IF( mycol .GT. 0)
THEN
1084 CALL zgerv2d( ictxt, bw, nrhs,
1096 IF ( mycol .NE. 0 )
THEN
1100 CALL zgemm(
'N',
'N', odd_size, nrhs, bw, -cone, af( 1 ),
1101 $ odd_size, work( 1+bw-bw ), bw, cone,
1102 $ b( part_offset+1 ), lldb )
1107 IF ( mycol .LT. np-1 )
THEN
1115 CALL zlamov(
'N', bw, nrhs, b( part_offset+odd_size+1), lldb,
1116 $ work( 1+bw-bw ), bw )
1118 CALL ztrmm(
'L',
'U',
'C',
'N', bw, nrhs, -cone,
1119 $ a(( ofst+(bw+1)+(odd_size-bw)*llda )), llda-1,
1120 $ work( 1+bw-bw ), bw )
1122 CALL zmatadd( bw, nrhs, cone, work( 1+bw-bw ), bw, cone,
1123 $ b( part_offset+odd_size-bw+1 ), lldb )
1129 CALL ztbtrs( uplo,
'C',
'N', odd_size,
1132 $ llda, b( part_offset+1 ),
1143 IF ( lsame( trans,
'C' ) )
THEN
1154 CALL ztbtrs( uplo,
'C',
'N', odd_size,
1156 $ a( ofst+1 ), llda,
1157 $ b( part_offset+1 ), lldb, info )
1160 IF ( mycol .LT. np-1 )
THEN
1168 CALL zlamov(
'N', bw, nrhs,
1169 $ b( part_offset+odd_size-bw+1), lldb,
1172 CALL ztrmm(
'L',
'L',
'C',
'N', bw, nrhs, -cone,
1173 $ a(( ofst+1+odd_size*llda )), llda-1, work( 1 ),
1176 CALL zmatadd( bw, nrhs, cone, work( 1 ), bw
1177 $ cone, b( part_offset+odd_size+1 ), lldb )
1182 IF ( mycol .NE. 0 )
THEN
1186 CALL zgemm(
'C',
'N', bw, nrhs, odd_size, -cone, af( 1 ),
1187 $ odd_size, b( part_offset+1 ), lldb, czero,
1188 $ work( 1+bw-bw ), bw )
1199 IF( mycol .GT. 0)
THEN
1201 CALL zgesd2d( ictxt, bw, nrhs,
1209 IF( mycol .LT. npcol-1)
THEN
1211 CALL zgerv2d( ictxt, bw, nrhs,
1218 $ work( 1 ), bw, cone,
1219 $ b( part_offset+odd_size + 1 ), lldb )
1226 IF( mycol .EQ. npcol-1 )
THEN
1241 IF( mod( (mycol+1)/level_dist, 2) .NE. 0 )
GOTO 41
1245 IF( mycol-level_dist .GE. 0 )
THEN
1247 CALL zgerv2d( ictxt, bw, nrhs,
1249 $ bw, 0, mycol-level_dist )
1253 $ b( part_offset+odd_size + 1 ), lldb )
1259 IF( mycol+level_dist .LT. npcol-1 )
THEN
1261 CALL zgerv2d( ictxt, bw, nrhs,
1263 $ bw, 0, mycol+level_dist )
1266 $ work( 1 ), bw, cone,
1267 $ b( part_offset+odd_size + 1 ), lldb )
1271 level_dist = level_dist*2
1284 CALL ztrtrs(
'L',
'N',
'N', bw, nrhs, af( odd_size*bw+mbw2+1 ),
1285 $ bw, b( part_offset+odd_size+1 ), lldb, info )
1287 IF( info.NE.0 )
THEN
1294 IF( mycol/level_dist .LE. (npcol-1)/level_dist-2 )
THEN
1298 CALL zgemm(
'C',
'N', bw, nrhs, bw, -cone,
1299 $ af( (odd_size)*bw+1 ),
1301 $ b( part_offset+odd_size+1 ),
1308 CALL zgesd2d( ictxt, bw, nrhs,
1310 $ bw, 0, mycol+level_dist )
1316 IF( (mycol/level_dist .GT. 0 ).AND.
1317 $ ( mycol/level_dist .LE. (npcol-1)/level_dist-1 ) )
THEN
1323 CALL zgemm(
'N',
'N', bw, nrhs, bw, -cone,
1324 $ af( odd_size*bw+2*mbw2+1 ),
1326 $ b( part_offset+odd_size+1 ),
1333 CALL zgesd2d( ictxt, bw, nrhs,
1335 $ bw, 0, mycol-level_dist )
1354 IF( mycol .EQ. npcol-1 )
THEN
1362 IF( mod( (mycol+1)/level_dist, 2) .NE. 0 )
GOTO 56
1364 level_dist = level_dist*2
1370 IF( (mycol/level_dist .GT. 0 ).AND.
1371 $ ( mycol/level_dist .LE. (npcol-1)/level_dist-1 ) )
THEN
1375 CALL zgerv2d( ictxt, bw, nrhs,
1377 $ bw, 0, mycol-level_dist )
1383 CALL zgemm(
'C',
'N', bw, nrhs, bw, -cone,
1384 $ af( odd_size*bw+2*mbw2+1 ),
1388 $ b( part_offset+odd_size+1 ),
1394 IF( mycol/level_dist .LE. (npcol-1)/level_dist-2 )
THEN
1398 CALL zgerv2d( ictxt, bw, nrhs,
1400 $ bw, 0, mycol+level_dist )
1404 CALL zgemm(
'N', 'n
', BW, NRHS, BW, -CONE,
1405 $ AF( (ODD_SIZE)*BW+1 ),
1409 $ B( PART_OFFSET+ODD_SIZE+1 ),
1418 CALL ZTRTRS( 'l
', 'c
', 'n
', BW, NRHS, AF( ODD_SIZE*BW+MBW2+1 ),
1419 $ BW, B( PART_OFFSET+ODD_SIZE+1 ), LLDB, INFO )
1421.NE.
IF( INFO0 ) THEN
1430.EQ.
IF( LEVEL_DIST 1 ) GOTO 51
1432 LEVEL_DIST = LEVEL_DIST/2
1436.LT.
IF( MYCOL+LEVEL_DIST NPCOL-1 ) THEN
1438 CALL ZGESD2D( ICTXT, BW, NRHS,
1439 $ B( PART_OFFSET+ODD_SIZE+1 ),
1440 $ LLDB, 0, MYCOL+LEVEL_DIST )
1446.GE.
IF( MYCOL-LEVEL_DIST 0 ) THEN
1448 CALL ZGESD2D( ICTXT, BW, NRHS,
1449 $ B( PART_OFFSET+ODD_SIZE+1 ),
1450 $ LLDB, 0, MYCOL-LEVEL_DIST )
1468.LT.
IF( MYCOL NPCOL-1) THEN
1470 CALL ZGESD2D( ICTXT, BW, NRHS,
1471 $ B( PART_OFFSET+ODD_SIZE+1 ), LLDB,
1478.GT.
IF( MYCOL 0) THEN
1480 CALL ZGERV2D( ICTXT, BW, NRHS,
1492.NE.
IF ( MYCOL 0 ) THEN
1496 CALL ZGEMM( 'n
', 'n
', ODD_SIZE, NRHS, BW, -CONE, AF( 1 ),
1497 $ ODD_SIZE, WORK( 1+BW-BW ), BW, CONE,
1498 $ B( PART_OFFSET+1 ), LLDB )
1503.LT.
IF ( MYCOL NP-1 ) THEN
1511 CALL ZLAMOV( 'n
', BW, NRHS, B( PART_OFFSET+ODD_SIZE+1), LLDB,
1512 $ WORK( 1+BW-BW ), BW )
1514 CALL ZTRMM( 'l
', 'l
', 'n
', 'n
', BW, NRHS, -CONE,
1515 $ A(( OFST+1+ODD_SIZE*LLDA )), LLDA-1,
1516 $ WORK( 1+BW-BW ), BW )
1518 CALL ZMATADD( BW, NRHS, CONE, WORK( 1+BW-BW ), BW, CONE,
1519 $ B( PART_OFFSET+ODD_SIZE-BW+1 ), LLDB )
1525 CALL ZTBTRS( UPLO, 'n
', 'n
', ODD_SIZE,
1528 $ LLDA, B( PART_OFFSET+1 ),
1542.NE.
IF( ICTXT_SAVE ICTXT_NEW ) THEN
1543 CALL BLACS_GRIDEXIT( ICTXT_NEW )
1555 WORK( 1 ) = WORK_SIZE_MIN