1 SUBROUTINE pcpttrsv( UPLO, TRANS, N, NRHS, D, E, JA, DESCA, B, IB,
2 $ DESCB, AF, LAF, WORK, LWORK, INFO )
13 INTEGER IB, INFO, JA, LAF, LWORK, N, NRHS
16 INTEGER DESCA( * ), DESCB( * )
17 COMPLEX AF( * ), B( * ), E( * ), WORK( * )
383 parameter( one = 1.0e+0 )
384 parameter( zero = 0.0e+0 )
386 parameter( cone = ( 1.0e+0, 0.0e+0 ) )
387 parameter( czero = ( 0.0e+0, 0.0e+0 ) )
389 parameter( int_one = 1 )
390 INTEGER DESCMULT, BIGNUM
391 parameter(descmult = 100, bignum = descmult * descmult)
392 INTEGER BLOCK_CYCLIC_2D, CSRC_, CTXT_, DLEN_, DTYPE_,
393 $ lld_, mb_, m_, nb_, n_, rsrc_
394 parameter( block_cyclic_2d = 1, dlen_ = 9, dtype_ = 1,
395 $ ctxt_ = 2, m_ = 3, n_ = 4, mb_ = 5, nb_ = 6,
396 $ rsrc_ = 7, csrc_ = 8, lld_ = 9 )
399 INTEGER CSRC, FIRST_PROC, ICTXT, ICTXT_NEW, ICTXT_SAVE,
400 $ idum1, idum2, idum3, ja_new, level_dist, llda,
401 $ lldb, mycol, myrow, my_num_cols, nb, np, npcol,
402 $ nprow, np_save, odd_size, part_offset,
403 $ part_size, return_code, store_m_b, store_n_a,
404 $ temp, work_size_min
407 INTEGER DESCA_1XP( 7 ), DESCB_PX1( 7 ),
408 $ param_check( 16, 3 )
411 EXTERNAL blacs_get, blacs_gridexit, blacs_gridinfo,
412 $ cgemm, cgerv2d, cgesd2d, clamov,
cmatadd,
419 EXTERNAL lsame, numroc
422 INTRINSIC ichar,
min, mod
436 temp = desca( dtype_ )
437 IF( temp .EQ. 502 )
THEN
439 desca( dtype_ ) = 501
444 desca( dtype_ ) = temp
446 IF( return_code .NE. 0)
THEN
447 info = -( 8*100 + 2 )
452 IF( return_code .NE. 0)
THEN
453 info = -( 11*100 + 2 )
459 IF( desca_1xp( 2 ) .NE. descb_px1( 2 ) )
THEN
460 info = -( 11*100 + 2 )
467 IF( desca_1xp( 4 ) .NE. descb_px1( 4 ) )
THEN
468 info = -( 11*100 + 4 )
473 IF( desca_1xp( 5 ) .NE. descb_px1( 5 ) )
THEN
474 info = -( 11*100 + 5 )
479 ictxt = desca_1xp( 2 )
480 csrc = desca_1xp( 5 )
482 llda = desca_1xp( 6 )
483 store_n_a = desca_1xp( 3 )
484 lldb = descb_px1( 6 )
485 store_m_b = descb_px1( 3 )
490 CALL blacs_gridinfo( ictxt, nprow, npcol, myrow, mycol )
495 IF( lsame( uplo,
'U' ) )
THEN
497 ELSE IF ( lsame( uplo,
'L' ) )
THEN
503 IF( lsame( trans,
'N' ) )
THEN
505 ELSE IF ( lsame( trans,
'C' ) )
THEN
511 IF( lwork .LT. -1)
THEN
513 ELSE IF ( lwork .EQ. -1 )
THEN
523 IF( n+ja-1 .GT. store_n_a )
THEN
524 info = -( 8*100 + 6 )
527 IF( n+ib-1 .GT. store_m_b )
THEN
528 info = -( 11*100 + 3 )
531 IF( lldb .LT. nb )
THEN
532 info = -( 11*100 + 6 )
535 IF( nrhs .LT. 0 )
THEN
547 IF( nprow .NE. 1 )
THEN
551 IF( n .GT. np*nb-mod( ja-1, nb ))
THEN
554 $
'PCPTTRSV, D&C alg.: only 1 block per proc',
559 IF((ja+n-1.GT.nb) .AND. ( nb.LT.2*int_one ))
THEN
562 $
'PCPTTRSV, D&C alg.: NB too small',
571 work( 1 ) = work_size_min
573 IF( lwork .LT. work_size_min )
THEN
574 IF( lwork .NE. -1 )
THEN
577 $
'PCPTTRSV: worksize error',
585 param_check( 16, 1 ) = descb(5)
586 param_check( 15, 1 ) = descb(4)
587 param_check( 14, 1 ) = descb(3)
588 param_check( 13, 1 ) = descb(2)
589 param_check( 12, 1 ) = descb(1)
590 param_check( 11, 1 ) = ib
591 param_check( 10, 1 ) = desca(5)
592 param_check( 9, 1 ) = desca(4)
593 param_check( 8, 1 ) = desca(3)
594 param_check( 7, 1 ) = desca(1)
595 param_check( 6, 1 ) = ja
596 param_check( 5, 1 ) = nrhs
597 param_check( 4, 1 ) = n
598 param_check( 3, 1 ) = idum3
599 param_check( 2, 1 ) = idum2
600 param_check( 1, 1 ) = idum1
602 param_check( 16, 2 ) = 1105
603 param_check( 15, 2 ) = 1104
604 param_check( 14, 2 ) = 1103
605 param_check( 13, 2 ) = 1102
606 param_check( 12, 2 ) = 1101
607 param_check( 11, 2 ) = 10
608 param_check( 10, 2 ) = 805
609 param_check( 9, 2 ) = 804
610 param_check( 8, 2 ) = 803
611 param_check( 7, 2 ) = 801
612 param_check( 6, 2 ) = 7
613 param_check( 5, 2 ) = 4
614 param_check( 4, 2 ) = 3
615 param_check( 3, 2 ) = 14
616 param_check( 2, 2 ) = 2
617 param_check( 1, 2 ) = 1
625 ELSE IF( info.LT.-descmult )
THEN
628 info = -info * descmult
633 CALL globchk( ictxt, 16, param_check, 16,
634 $ param_check( 1, 3 ), info )
639 IF( info.EQ.bignum )
THEN
641 ELSE IF( mod( info, descmult ) .EQ. 0 )
THEN
642 info = -info / descmult
648 CALL pxerbla( ictxt,
'PCPTTRSV', -info )
664 part_offset = nb*( (ja-1)/(npcol*nb) )
666 IF ( (mycol-csrc) .LT. (ja-part_offset-1)/nb )
THEN
667 part_offset = part_offset + nb
670 IF ( mycol .LT. csrc )
THEN
671 part_offset = part_offset - nb
680 first_proc = mod( ( ja-1 )/nb+csrc, npcol )
684 ja_new = mod( ja-1, nb ) + 1
689 np = ( ja_new+n-2 )/nb + 1
693 CALL reshape( ictxt, int_one, ictxt_new, int_one,
694 $ first_proc, int_one, np )
700 desca_1xp( 2 ) = ictxt_new
701 descb_px1( 2 ) = ictxt_new
705 CALL blacs_gridinfo( ictxt, nprow, npcol, myrow, mycol )
709 IF( myrow .LT. 0 )
THEN
722 my_num_cols = numroc( n, part_size, mycol, 0, npcol )
726 IF ( mycol .EQ. 0 )
THEN
727 part_offset = part_offset+mod( ja_new-1, part_size )
728 my_num_cols = my_num_cols - mod(ja_new-1, part_size )
733 odd_size = my_num_cols
734 IF ( mycol .LT. np-1 )
THEN
735 odd_size = odd_size - int_one
742 IF ( lsame( uplo,
'L' ) )
THEN
744 IF ( lsame( trans,
'N' ) )
THEN
755 CALL cpttrsv( uplo,
'N', odd_size, nrhs, d( part_offset+1 ),
756 $ e( part_offset+1 ), b( part_offset+1 ), lldb,
760 IF ( mycol .LT. np-1 )
THEN
764 CALL caxpy( nrhs, -e( part_offset+odd_size ),
765 $ b( part_offset+odd_size ), lldb,
766 $ b( part_offset+odd_size+1 ), lldb )
771 IF ( mycol .NE. 0 )
THEN
775 CALL cgemm(
'C',
'N', 1, nrhs, odd_size, -cone, af( 1 ),
776 $ odd_size, b( part_offset+1 ), lldb, czero,
777 $ work( 1+int_one-1 ), int_one )
788 IF( mycol .GT. 0)
THEN
790 CALL cgesd2d( ictxt, int_one, nrhs,
791 $ work( 1 ), int_one,
798 IF( mycol .LT. npcol-1)
THEN
800 CALL cgerv2d( ictxt, int_one, nrhs,
801 $ work( 1 ), int_one,
806 CALL cmatadd( int_one, nrhs, cone,
807 $ work( 1 ), int_one, cone,
808 $ b( part_offset+odd_size + 1 ), lldb )
815 IF( mycol .EQ. npcol-1 )
THEN
830 IF( mod( (mycol+1)/level_dist, 2) .NE. 0 )
GOTO 11
834 IF( mycol-level_dist .GE. 0 )
THEN
836 CALL cgerv2d( ictxt, int_one, nrhs,
838 $ int_one, 0, mycol-level_dist )
840 CALL cmatadd( int_one, nrhs, cone,
841 $ work( 1 ), int_one, cone,
842 $ b( part_offset+odd_size + 1 ), lldb )
848 IF( mycol+level_dist .LT. npcol-1 )
THEN
850 CALL cgerv2d( ictxt, int_one, nrhs,
852 $ int_one, 0, mycol+level_dist )
854 CALL cmatadd( int_one, nrhs, cone,
855 $ work( 1 ), int_one, cone,
856 $ b( part_offset+odd_size + 1 ), lldb )
860 level_dist = level_dist*2
873 CALL ctrtrs(
'L',
'N',
'U', int_one, nrhs, af( odd_size+2 ),
874 $ int_one, b( part_offset+odd_size+1 ), lldb, info )
883 IF( mycol/level_dist .LE. (npcol-1)/level_dist-2 )
THEN
887 CALL cgemm(
'C',
'N', int_one, nrhs, int_one, -cone,
888 $ af( (odd_size)*1+1 ),
890 $ b( part_offset+odd_size+1 ),
897 CALL cgesd2d( ictxt, int_one, nrhs,
899 $ int_one, 0, mycol+level_dist )
905 IF( (mycol/level_dist .GT. 0 ).AND.
906 $ ( mycol/level_dist .LE. (npcol-1)/level_dist-1 ) )
THEN
912 CALL cgemm(
'N',
'N', int_one, nrhs, int_one, -cone,
913 $ af( odd_size*1+2+1 ),
915 $ b( part_offset+odd_size+1 ),
922 CALL cgesd2d( ictxt, int_one, nrhs,
924 $ int_one, 0, mycol-level_dist )
943 IF( mycol .EQ. npcol-1 )
THEN
951 IF( mod( (mycol+1)/level_dist, 2) .NE. 0 )
GOTO 26
953 level_dist = level_dist*2
959 IF( (mycol/level_dist .GT. 0 ).AND.
960 $ ( mycol/level_dist .LE. (npcol-1)/level_dist-1 ) )
THEN
964 CALL cgerv2d( ictxt, int_one, nrhs,
966 $ int_one, 0, mycol-level_dist )
972 CALL cgemm(
'C',
'N', int_one, nrhs, int_one, -cone,
973 $ af( odd_size*1+2+1 ),
977 $ b( part_offset+odd_size+1 ),
983 IF( mycol/level_dist .LE. (npcol-1)/level_dist-2 )
THEN
987 CALL cgerv2d( ictxt, int_one, nrhs,
989 $ int_one, 0, mycol+level_dist )
993 CALL cgemm(
'N',
'N', int_one, nrhs, int_one, -cone,
994 $ af( (odd_size)*1+1 ),
998 $ b( part_offset+odd_size+1 ),
1007 CALL ctrtrs(
'L',
'C',
'U', int_one, nrhs, af( odd_size+2 ),
1008 $ int_one, b( part_offset+odd_size+1 ), lldb, info )
1010 IF( info.NE.0 )
THEN
1019 IF( level_dist .EQ. 1 )
GOTO 21
1021 level_dist = level_dist/2
1025 IF( mycol+level_dist .LT. npcol-1 )
THEN
1027 CALL cgesd2d( ictxt, int_one, nrhs,
1028 $ b( part_offset+odd_size+1 ),
1029 $ lldb, 0, mycol+level_dist )
1035 IF( mycol-level_dist .GE. 0 )
THEN
1037 CALL cgesd2d( ictxt, int_one, nrhs,
1038 $ b( part_offset+odd_size+1 ),
1039 $ lldb, 0, mycol-level_dist )
1057 IF( mycol .LT. npcol-1)
THEN
1059 CALL cgesd2d( ictxt, int_one, nrhs,
1060 $ b( part_offset+odd_size+1 ), lldb,
1067 IF( mycol .GT. 0)
THEN
1069 CALL cgerv2d( ictxt, int_one, nrhs,
1070 $ work( 1 ), int_one,
1081 IF ( mycol .NE. 0 )
THEN
1085 CALL cgemm(
'N',
'N', odd_size, nrhs, 1, -cone, af( 1 ),
1086 $ odd_size, work( 1+int_one-1 ), int_one, cone,
1087 $ b( part_offset+1 ), lldb )
1092 IF ( mycol .LT. np-1 )
THEN
1096 CALL caxpy( nrhs, -conjg( e( part_offset+odd_size ) ),
1097 $ b( part_offset+odd_size+1 ), lldb,
1098 $ b( part_offset+odd_size ), lldb )
1104 CALL cpttrsv( uplo,
'C', odd_size, nrhs, d( part_offset+1 ),
1105 $ e( part_offset+1 ), b( part_offset+1 ), lldb,
1116 IF ( lsame( trans,
'C' ) )
THEN
1127 CALL cpttrsv( uplo,
'C', odd_size, nrhs, d( part_offset+1 ),
1128 $ e( part_offset+1 ), b( part_offset+1 ), lldb,
1132 IF ( mycol .LT. np-1 )
THEN
1136 CALL caxpy( nrhs, -conjg( e( part_offset+odd_size ) ),
1137 $ b( part_offset+odd_size ), lldb,
1138 $ b( part_offset+odd_size+1 ), lldb )
1143 IF ( mycol .NE. 0 )
THEN
1147 CALL cgemm(
'T',
'N', 1, nrhs, odd_size, -cone, af( 1 ),
1148 $ odd_size, b( part_offset+1 ), lldb, czero,
1149 $ work( 1+int_one-1 ), int_one )
1160 IF( mycol .GT. 0)
THEN
1162 CALL cgesd2d( ictxt, int_one, nrhs,
1163 $ work( 1 ), int_one,
1170 IF( mycol .LT. npcol-1)
THEN
1172 CALL cgerv2d( ictxt, int_one, nrhs,
1173 $ work( 1 ), int_one,
1178 CALL cmatadd( int_one, nrhs, cone,
1179 $ work( 1 ), int_one, cone,
1180 $ b( part_offset+odd_size + 1 ), lldb )
1187 IF( mycol .EQ. npcol-1 )
THEN
1202 IF( mod( (mycol+1)/level_dist, 2) .NE. 0 )
GOTO 41
1206 IF( mycol-level_dist .GE. 0 )
THEN
1208 CALL cgerv2d( ictxt, int_one, nrhs,
1210 $ int_one, 0, mycol-level_dist )
1212 CALL cmatadd( int_one, nrhs, cone,
1213 $ work( 1 ), int_one, cone,
1214 $ b( part_offset+odd_size + 1 ), lldb )
1220 IF( mycol+level_dist .LT. npcol-1 )
THEN
1222 CALL cgerv2d( ictxt, int_one, nrhs,
1224 $ int_one, 0, mycol+level_dist )
1226 CALL cmatadd( int_one, nrhs, cone,
1227 $ work( 1 ), int_one, cone,
1228 $ b( part_offset+odd_size + 1 ), lldb )
1232 level_dist = level_dist*2
1245 CALL ctrtrs(
'L',
'N',
'U', int_one, nrhs, af( odd_size+2 ),
1246 $ int_one, b( part_offset+odd_size+1 ), lldb, info )
1248 IF( info.NE.0 )
THEN
1255 IF( mycol/level_dist .LE. (npcol-1)/level_dist-2 )
THEN
1259 CALL cgemm(
'T',
'N', int_one, nrhs, int_one, -cone,
1260 $ af( (odd_size)*1+1 ),
1262 $ b( part_offset+odd_size+1 ),
1269 CALL cgesd2d( ictxt, int_one, nrhs,
1271 $ int_one, 0, mycol+level_dist )
1277 IF( (mycol/level_dist .GT. 0 ).AND.
1278 $ ( mycol/level_dist .LE. (npcol-1)/level_dist-1 ) )
THEN
1284 CALL cgemm(
'C',
'N', int_one, nrhs, int_one, -cone,
1285 $ af( odd_size*1+2+1 ),
1287 $ b( part_offset+odd_size+1 ),
1294 CALL cgesd2d( ictxt, int_one, nrhs,
1296 $ int_one, 0, mycol-level_dist )
1315 IF( mycol .EQ. npcol-1 )
THEN
1323 IF( mod( (mycol+1)/level_dist, 2) .NE. 0 )
GOTO 56
1325 level_dist = level_dist*2
1331 IF( (mycol/level_dist .GT. 0 ).AND.
1332 $ ( mycol/level_dist .LE. (npcol-1)/level_dist-1 ) )
THEN
1336 CALL cgerv2d( ictxt, int_one, nrhs,
1338 $ int_one, 0, mycol-level_dist )
1344 CALL cgemm(
'T',
'N', int_one, nrhs, int_one, -cone,
1345 $ af( odd_size*1+2+1 ),
1349 $ b( part_offset+odd_size+1 ),
1355 IF( mycol/level_dist .LE. (npcol-1)/level_dist-2 )
THEN
1359 CALL cgerv2d( ictxt, int_one, nrhs,
1361 $ int_one, 0, mycol+level_dist )
1365 CALL cgemm(
'C',
'N', int_one, nrhs, int_one, -cone,
1366 $ af( (odd_size)*1+1 ),
1370 $ b( part_offset+odd_size+1 ),
1379 CALL ctrtrs(
'L',
'C',
'U', int_one, nrhs, af( odd_size+2 ),
1380 $ int_one, b( part_offset+odd_size+1 ), lldb, info )
1382 IF( info.NE.0 )
THEN
1391 IF( level_dist .EQ. 1 )
GOTO 51
1393 level_dist = level_dist/2
1397 IF( mycol+level_dist .LT. npcol-1 )
THEN
1399 CALL cgesd2d( ictxt, int_one, nrhs,
1400 $ b( part_offset+odd_size+1 ),
1401 $ lldb, 0, mycol+level_dist )
1407 IF( mycol-level_dist .GE. 0 )
THEN
1409 CALL cgesd2d( ictxt, int_one, nrhs,
1410 $ b( part_offset+odd_size+1 ),
1411 $ lldb, 0, mycol-level_dist )
1429 IF( mycol .LT. npcol-1)
THEN
1431 CALL cgesd2d( ictxt, int_one, nrhs,
1432 $ b( part_offset+odd_size+1 ), lldb,
1439 IF( mycol .GT. 0)
THEN
1441 CALL cgerv2d( ictxt, int_one, nrhs,
1442 $ work( 1 ), int_one,
1453 IF ( mycol .NE. 0 )
THEN
1457 CALL cgemm(
'C',
'N', odd_size, nrhs, 1, -cone, af( 1 ),
1458 $ int_one, work( 1 ), int_one, cone,
1459 $ b( part_offset+1 ), lldb )
1464 IF ( mycol .LT. np-1 )
THEN
1468 CALL caxpy( nrhs, -e( part_offset+odd_size ),
1469 $ b( part_offset+odd_size+1 ), lldb,
1470 $ b( part_offset+odd_size ), lldb )
1476 CALL cpttrsv( uplo,
'N', odd_size, nrhs, d( part_offset+1 ),
1477 $ e( part_offset+1 ), b( part_offset+1 ), lldb,
1491 IF( ictxt_save .NE. ictxt_new )
THEN
1492 CALL blacs_gridexit( ictxt_new )
1504 work( 1 ) = work_size_min