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