1 SUBROUTINE pzpttrsv( UPLO, TRANS, N, NRHS, D, E, JA, DESCA, B, IB,
2 $ DESCB, AF, LAF, WORK, LWORK, INFO )
10 INTEGER IB, INFO, JA, LAF, LWORK, N, NRHS
13 INTEGER DESCA( * ), DESCB( * )
14 COMPLEX*16 AF( * ), B( * ), E( * ), WORK( * )
15 DOUBLE PRECISION D( * )
379 DOUBLE PRECISION ONE, ZERO
380 parameter( one = 1.0d+0 )
381 parameter( zero = 0.0d+0 )
382 COMPLEX*16 CONE, CZERO
383 parameter( cone = ( 1.0d+0, 0.0d+0 ) )
384 parameter( czero = ( 0.0d+0, 0.0d+0 ) )
386 parameter( int_one = 1 )
387 INTEGER DESCMULT, BIGNUM
388 parameter(descmult = 100, bignum = descmult * descmult)
389 INTEGER BLOCK_CYCLIC_2D, CSRC_, CTXT_, DLEN_, DTYPE_,
390 $ lld_, mb_, m_, nb_, n_, rsrc_
391 parameter( block_cyclic_2d = 1, dlen_ = 9, dtype_ = 1,
392 $ ctxt_ = 2, m_ = 3, n_ = 4, mb_ = 5, nb_ = 6,
393 $ rsrc_ = 7, csrc_ = 8, lld_ = 9 )
396 INTEGER CSRC, FIRST_PROC, ICTXT, ICTXT_NEW, ICTXT_SAVE,
397 $ idum1, idum2, idum3, ja_new, level_dist, llda,
398 $ lldb, mycol, myrow, my_num_cols, nb, np, npcol,
399 $ nprow, np_save, odd_size, part_offset,
400 $ part_size, return_code, store_m_b, store_n_a,
401 $ temp, work_size_min
404 INTEGER DESCA_1XP( 7 ), DESCB_PX1( 7 ),
405 $ param_check( 16, 3 )
408 EXTERNAL blacs_get, blacs_gridexit, blacs_gridinfo,
410 $ zgerv2d, zgesd2d, zlamov,
zmatadd, ztbtrs,
416 EXTERNAL lsame, numroc
419 INTRINSIC ichar,
min, mod
433 temp = desca( dtype_ )
434 IF( temp .EQ. 502 )
THEN
436 desca( dtype_ ) = 501
441 desca( dtype_ ) = temp
443 IF( return_code .NE. 0)
THEN
444 info = -( 8*100 + 2 )
449 IF( return_code .NE. 0)
THEN
450 info = -( 11*100 + 2 )
456 IF( desca_1xp( 2 ) .NE. descb_px1( 2 ) )
THEN
457 info = -( 11*100 + 2 )
464 IF( desca_1xp( 4 ) .NE. descb_px1( 4 ) )
THEN
465 info = -( 11*100 + 4 )
470 IF( desca_1xp( 5 ) .NE. descb_px1( 5 ) )
THEN
471 info = -( 11*100 + 5 )
476 ictxt = desca_1xp( 2 )
477 csrc = desca_1xp( 5 )
479 llda = desca_1xp( 6 )
480 store_n_a = desca_1xp( 3 )
481 lldb = descb_px1( 6 )
482 store_m_b = descb_px1( 3 )
487 CALL blacs_gridinfo( ictxt, nprow, npcol, myrow, mycol )
492 IF( lsame( uplo,
'U' ) )
THEN
494 ELSE IF ( lsame( uplo,
'L' ) )
THEN
500 IF( lsame( trans,
'N' ) )
THEN
502 ELSE IF ( lsame( trans,
'C' ) )
THEN
508 IF( lwork .LT. -1)
THEN
510 ELSE IF ( lwork .EQ. -1 )
THEN
520 IF( n+ja-1 .GT. store_n_a )
THEN
521 info = -( 8*100 + 6 )
524 IF( n+ib-1 .GT. store_m_b )
THEN
525 info = -( 11*100 + 3 )
528 IF( lldb .LT. nb )
THEN
529 info = -( 11*100 + 6 )
532 IF( nrhs .LT. 0 )
THEN
544 IF( nprow .NE. 1 )
THEN
548 IF( n .GT. np*nb-mod( ja-1, nb ))
THEN
551 $
'PZPTTRSV, D&C alg.: only 1 block per proc',
556 IF((ja+n-1.GT.nb) .AND. ( nb.LT.2*int_one ))
THEN
559 $
'PZPTTRSV, D&C alg.: NB too small',
568 work( 1 ) = work_size_min
570 IF( lwork .LT. work_size_min )
THEN
571 IF( lwork .NE. -1 )
THEN
574 $
'PZPTTRSV: worksize error',
582 param_check( 16, 1 ) = descb(5)
583 param_check( 15, 1 ) = descb(4)
584 param_check( 14, 1 ) = descb(3)
585 param_check( 13, 1 ) = descb(2)
586 param_check( 12, 1 ) = descb(1)
587 param_check( 11, 1 ) = ib
588 param_check( 10, 1 ) = desca(5)
589 param_check( 9, 1 ) = desca(4)
590 param_check( 8, 1 ) = desca(3)
591 param_check( 7, 1 ) = desca(1)
592 param_check( 6, 1 ) = ja
593 param_check( 5, 1 ) = nrhs
594 param_check( 4, 1 ) = n
595 param_check( 3, 1 ) = idum3
596 param_check( 2, 1 ) = idum2
597 param_check( 1, 1 ) = idum1
599 param_check( 16, 2 ) = 1105
600 param_check( 15, 2 ) = 1104
601 param_check( 14, 2 ) = 1103
602 param_check( 13, 2 ) = 1102
603 param_check( 12, 2 ) = 1101
604 param_check( 11, 2 ) = 10
605 param_check( 10, 2 ) = 805
606 param_check( 9, 2 ) = 804
607 param_check( 8, 2 ) = 803
608 param_check( 7, 2 ) = 801
609 param_check( 6, 2 ) = 7
610 param_check( 5, 2 ) = 4
611 param_check( 4, 2 ) = 3
612 param_check( 3, 2 ) = 14
613 param_check( 2, 2 ) = 2
614 param_check( 1, 2 ) = 1
622 ELSE IF( info.LT.-descmult )
THEN
625 info = -info * descmult
630 CALL globchk( ictxt, 16, param_check, 16,
631 $ param_check( 1, 3 ), info )
636 IF( info.EQ.bignum )
THEN
638 ELSE IF( mod( info, descmult ) .EQ. 0 )
THEN
639 info = -info / descmult
645 CALL pxerbla( ictxt,
'PZPTTRSV', -info )
661 part_offset = nb*( (ja-1)/(npcol*nb) )
663 IF ( (mycol-csrc) .LT. (ja-part_offset-1)/nb )
THEN
664 part_offset = part_offset + nb
667 IF ( mycol .LT. csrc )
THEN
668 part_offset = part_offset - nb
677 first_proc = mod( ( ja-1 )/nb+csrc, npcol )
681 ja_new = mod( ja-1, nb ) + 1
686 np = ( ja_new+n-2 )/nb + 1
690 CALL reshape( ictxt, int_one, ictxt_new, int_one,
691 $ first_proc, int_one, np )
697 desca_1xp( 2 ) = ictxt_new
698 descb_px1( 2 ) = ictxt_new
702 CALL blacs_gridinfo( ictxt, nprow, npcol, myrow, mycol )
706 IF( myrow .LT. 0 )
THEN
719 my_num_cols = numroc( n, part_size, mycol, 0, npcol )
723 IF ( mycol .EQ. 0 )
THEN
724 part_offset = part_offset+mod( ja_new-1, part_size )
725 my_num_cols = my_num_cols - mod(ja_new-1, part_size )
730 odd_size = my_num_cols
731 IF ( mycol .LT. np-1 )
THEN
732 odd_size = odd_size - int_one
739 IF ( lsame( uplo,
'L' ) )
THEN
741 IF ( lsame( trans,
'N' ) )
THEN
752 CALL zpttrsv( uplo,
'N', odd_size, nrhs, d( part_offset+1 ),
753 $ e( part_offset+1 ), b( part_offset+1 ), lldb,
757 IF ( mycol .LT. np-1 )
THEN
761 CALL zaxpy( nrhs, -e( part_offset+odd_size ),
762 $ b( part_offset+odd_size ), lldb,
763 $ b( part_offset+odd_size+1 ), lldb )
768 IF ( mycol .NE. 0 )
THEN
772 CALL zgemm(
'C',
'N', 1, nrhs, odd_size, -cone, af( 1 ),
773 $ odd_size, b( part_offset+1 ), lldb, czero,
774 $ work( 1+int_one-1 ), int_one )
785 IF( mycol .GT. 0)
THEN
787 CALL zgesd2d( ictxt, int_one, nrhs,
788 $ work( 1 ), int_one,
795 IF( mycol .LT. npcol-1)
THEN
797 CALL zgerv2d( ictxt, int_one, nrhs,
798 $ work( 1 ), int_one,
803 CALL zmatadd( int_one, nrhs, cone,
804 $ work( 1 ), int_one, cone,
805 $ b( part_offset+odd_size + 1 ), lldb )
812 IF( mycol .EQ. npcol-1 )
THEN
827 IF( mod( (mycol+1)/level_dist, 2) .NE. 0 )
GOTO 11
831 IF( mycol-level_dist .GE. 0 )
THEN
833 CALL zgerv2d( ictxt, int_one, nrhs,
835 $ int_one, 0, mycol-level_dist )
837 CALL zmatadd( int_one, nrhs, cone,
838 $ work( 1 ), int_one, cone,
839 $ b( part_offset+odd_size + 1 ), lldb )
845 IF( mycol+level_dist .LT. npcol-1 )
THEN
847 CALL zgerv2d( ictxt, int_one, nrhs,
849 $ int_one, 0, mycol+level_dist )
851 CALL zmatadd( int_one, nrhs, cone,
852 $ work( 1 ), int_one, cone,
853 $ b( part_offset+odd_size + 1 ), lldb )
857 level_dist = level_dist*2
870 CALL ztrtrs(
'L',
'N',
'U', int_one, nrhs, af( odd_size+2 ),
871 $ int_one, b( part_offset+odd_size+1 ), lldb, info )
880 IF( mycol/level_dist .LE. (npcol-1)/level_dist-2 )
THEN
884 CALL zgemm(
'C',
'N', int_one, nrhs, int_one, -cone,
885 $ af( (odd_size)*1+1 ),
887 $ b( part_offset+odd_size+1 ),
894 CALL zgesd2d( ictxt, int_one, nrhs,
896 $ int_one, 0, mycol+level_dist )
902 IF( (mycol/level_dist .GT. 0 ).AND.
903 $ ( mycol/level_dist .LE. (npcol-1)/level_dist-1 ) )
THEN
909 CALL zgemm(
'N',
'N', int_one, nrhs, int_one, -cone,
910 $ af( odd_size*1+2+1 ),
912 $ b( part_offset+odd_size+1 ),
919 CALL zgesd2d( ictxt, int_one, nrhs,
921 $ int_one, 0, mycol-level_dist )
940 IF( mycol .EQ. npcol-1 )
THEN
948 IF( mod( (mycol+1)/level_dist, 2) .NE. 0 )
GOTO 26
950 level_dist = level_dist*2
956 IF( (mycol/level_dist .GT. 0 ).AND.
957 $ ( mycol/level_dist .LE. (npcol-1)/level_dist-1 ) )
THEN
961 CALL zgerv2d( ictxt, int_one, nrhs,
963 $ int_one, 0, mycol-level_dist )
969 CALL zgemm(
'C',
'N', int_one, nrhs, int_one, -cone,
970 $ af( odd_size*1+2+1 ),
974 $ b( part_offset+odd_size+1 ),
980 IF( mycol/level_dist .LE. (npcol-1)/level_dist-2 )
THEN
984 CALL zgerv2d( ictxt, int_one, nrhs,
986 $ int_one, 0, mycol+level_dist )
990 CALL zgemm(
'N',
'N', int_one, nrhs, int_one, -cone,
991 $ af( (odd_size)*1+1 ),
995 $ b( part_offset+odd_size+1 ),
1004 CALL ztrtrs(
'L',
'C',
'U', int_one, nrhs, af( odd_size+2 ),
1005 $ int_one, b( part_offset+odd_size+1 ), lldb, info )
1007 IF( info.NE.0 )
THEN
1016 IF( level_dist .EQ. 1 )
GOTO 21
1018 level_dist = level_dist/2
1022 IF( mycol+level_dist .LT. npcol-1 )
THEN
1024 CALL zgesd2d( ictxt, int_one, nrhs,
1025 $ b( part_offset+odd_size+1 ),
1026 $ lldb, 0, mycol+level_dist )
1032 IF( mycol-level_dist .GE. 0 )
THEN
1034 CALL zgesd2d( ictxt, int_one, nrhs,
1035 $ b( part_offset+odd_size+1 ),
1036 $ lldb, 0, mycol-level_dist )
1054 IF( mycol .LT. npcol-1)
THEN
1056 CALL zgesd2d( ictxt, int_one, nrhs,
1057 $ b( part_offset+odd_size+1 ), lldb,
1064 IF( mycol .GT. 0)
THEN
1066 CALL zgerv2d( ictxt, int_one, nrhs,
1067 $ work( 1 ), int_one,
1078 IF ( mycol .NE. 0 )
THEN
1082 CALL zgemm(
'N',
'N', odd_size, nrhs, 1, -cone, af( 1 ),
1083 $ odd_size, work( 1+int_one-1 ), int_one, cone,
1084 $ b( part_offset+1 ), lldb )
1089 IF ( mycol .LT. np-1 )
THEN
1093 CALL zaxpy( nrhs, -dconjg( e( part_offset+odd_size ) ),
1094 $ b( part_offset+odd_size+1 ), lldb,
1095 $ b( part_offset+odd_size ), lldb )
1101 CALL zpttrsv( uplo,
'C', odd_size, nrhs, d( part_offset+1 ),
1102 $ e( part_offset+1 ), b( part_offset+1 ), lldb,
1113 IF ( lsame( trans,
'C' ) )
THEN
1124 CALL zpttrsv( uplo,
'C', odd_size, nrhs, d( part_offset+1 ),
1125 $ e( part_offset+1 ), b( part_offset+1 ), lldb,
1129 IF ( mycol .LT. np-1 )
THEN
1133 CALL zaxpy( nrhs, -dconjg( e( part_offset+odd_size ) ),
1134 $ b( part_offset+odd_size ), lldb,
1135 $ b( part_offset+odd_size+1 ), lldb )
1140 IF ( mycol .NE. 0 )
THEN
1144 CALL zgemm(
'T',
'N', 1, nrhs, odd_size, -cone, af( 1 ),
1145 $ odd_size, b( part_offset+1 ), lldb, czero,
1146 $ work( 1+int_one-1 ), int_one )
1157 IF( mycol .GT. 0)
THEN
1159 CALL zgesd2d( ictxt, int_one, nrhs,
1160 $ work( 1 ), int_one,
1167 IF( mycol .LT. npcol-1)
THEN
1169 CALL zgerv2d( ictxt, int_one, nrhs,
1170 $ work( 1 ), int_one,
1175 CALL zmatadd( int_one, nrhs, cone,
1176 $ work( 1 ), int_one, cone,
1177 $ b( part_offset+odd_size + 1 ), lldb )
1184 IF( mycol .EQ. npcol-1 )
THEN
1199 IF( mod( (mycol+1)/level_dist, 2) .NE. 0 )
GOTO 41
1203 IF( mycol-level_dist .GE. 0 )
THEN
1205 CALL zgerv2d( ictxt, int_one, nrhs,
1207 $ int_one, 0, mycol-level_dist )
1209 CALL zmatadd( int_one, nrhs, cone,
1210 $ work( 1 ), int_one, cone,
1211 $ b( part_offset+odd_size + 1 ), lldb )
1217 IF( mycol+level_dist .LT. npcol-1 )
THEN
1219 CALL zgerv2d( ictxt, int_one, nrhs,
1221 $ int_one, 0, mycol+level_dist )
1223 CALL zmatadd( int_one, nrhs, cone,
1224 $ work( 1 ), int_one, cone,
1225 $ b( part_offset+odd_size + 1 ), lldb )
1229 level_dist = level_dist*2
1242 CALL ztrtrs(
'L',
'N',
'U', int_one, nrhs, af( odd_size+2 ),
1243 $ int_one, b( part_offset+odd_size+1 ), lldb, info )
1245 IF( info.NE.0 )
THEN
1252 IF( mycol/level_dist .LE. (npcol-1)/level_dist-2 )
THEN
1256 CALL zgemm(
'T',
'N', int_one, nrhs, int_one, -cone,
1257 $ af( (odd_size)*1+1 ),
1259 $ b( part_offset+odd_size+1 ),
1266 CALL zgesd2d( ictxt, int_one, nrhs,
1268 $ int_one, 0, mycol+level_dist )
1274 IF( (mycol/level_dist .GT. 0 ).AND.
1275 $ ( mycol/level_dist .LE. (npcol-1)/level_dist-1 ) )
THEN
1281 CALL zgemm(
'C',
'N', int_one, nrhs, int_one, -cone,
1282 $ af( odd_size*1+2+1 ),
1284 $ b( part_offset+odd_size+1 ),
1291 CALL zgesd2d( ictxt, int_one, nrhs,
1293 $ int_one, 0, mycol-level_dist )
1312 IF( mycol .EQ. npcol-1 )
THEN
1320 IF( mod( (mycol+1)/level_dist, 2) .NE. 0 )
GOTO 56
1322 level_dist = level_dist*2
1328 IF( (mycol/level_dist .GT. 0 ).AND.
1329 $ ( mycol/level_dist .LE. (npcol-1)/level_dist-1 ) )
THEN
1333 CALL zgerv2d( ictxt, int_one, nrhs,
1335 $ int_one, 0, mycol-level_dist )
1341 CALL zgemm(
'T',
'N', int_one, nrhs, int_one, -cone,
1342 $ af( odd_size*1+2+1 ),
1346 $ b( part_offset+odd_size+1 ),
1352 IF( mycol/level_dist .LE. (npcol-1)/level_dist-2 )
THEN
1356 CALL zgerv2d( ictxt, int_one, nrhs,
1358 $ int_one, 0, mycol+level_dist )
1362 CALL zgemm(
'C',
'N', int_one, nrhs, int_one, -cone,
1363 $ af( (odd_size)*1+1 ),
1367 $ b( part_offset+odd_size+1 ),
1376 CALL ztrtrs(
'L',
'C',
'U', int_one, nrhs, af( odd_size+2 ),
1377 $ int_one, b( part_offset+odd_size+1 ), lldb, info )
1379 IF( info.NE.0 )
THEN
1388 IF( level_dist .EQ. 1 )
GOTO 51
1390 level_dist = level_dist/2
1394 IF( mycol+level_dist .LT. npcol-1 )
THEN
1396 CALL zgesd2d( ictxt, int_one, nrhs,
1397 $ b( part_offset+odd_size+1 ),
1398 $ lldb, 0, mycol+level_dist )
1404 IF( mycol-level_dist .GE. 0 )
THEN
1406 CALL zgesd2d( ictxt, int_one, nrhs,
1407 $ b( part_offset+odd_size+1 ),
1408 $ lldb, 0, mycol-level_dist )
1426 IF( mycol .LT. npcol-1)
THEN
1428 CALL zgesd2d( ictxt, int_one, nrhs,
1429 $ b( part_offset+odd_size+1 ), lldb,
1436 IF( mycol .GT. 0)
THEN
1438 CALL zgerv2d( ictxt, int_one, nrhs,
1439 $ work( 1 ), int_one,
1450 IF ( mycol .NE. 0 )
THEN
1454 CALL zgemm(
'C',
'N', odd_size, nrhs, 1, -cone, af( 1 ),
1455 $ int_one, work( 1 ), int_one, cone,
1456 $ b( part_offset+1 ), lldb )
1461 IF ( mycol .LT. np-1 )
THEN
1465 CALL zaxpy( nrhs, -e( part_offset+odd_size ),
1466 $ b( part_offset+odd_size+1 ), lldb,
1467 $ b( part_offset+odd_size ), lldb )
1473 CALL zpttrsv( uplo,
'N', odd_size, nrhs, d( part_offset+1 ),
1474 $ e( part_offset+1 ), b( part_offset+1 ), lldb,
1488 IF( ictxt_save .NE. ictxt_new )
THEN
1489 CALL blacs_gridexit( ictxt_new )
1501 work( 1 ) = work_size_min