1      SUBROUTINE pddttrf( N, DL, D, DU, JA, DESCA, AF, LAF, WORK, LWORK,
 
   10      INTEGER            INFO, JA, LAF, LWORK, N
 
   14      DOUBLE PRECISION   AF( * ), D( * ), DL( * ), DU( * ), WORK( * )
 
  356      parameter( one = 1.0d+0 )
 
  357      DOUBLE PRECISION   ZERO
 
  358      parameter( zero = 0.0d+0 )
 
  360      parameter( int_one = 1 )
 
  361      INTEGER            DESCMULT, BIGNUM
 
  362      parameter( descmult = 100, bignum = descmult*descmult )
 
  363      INTEGER            BLOCK_CYCLIC_2D, CSRC_, CTXT_, DLEN_, DTYPE_,
 
  364     $                   lld_, mb_, m_, nb_, n_, rsrc_
 
  365      parameter( block_cyclic_2d = 1, dlen_ = 9, dtype_ = 1,
 
  366     $                     ctxt_ = 2, m_ = 3, n_ = 4, mb_ = 5, nb_ = 6,
 
  367     $                     rsrc_ = 7, csrc_ = 8, lld_ = 9 )
 
  370      INTEGER            COMM_PROC, CSRC, FIRST_PROC, I, ICTXT,
 
  371     $                   ictxt_new, ictxt_save, idum3, ja_new, laf_min,
 
  372     $                   level_dist, llda, mycol, myrow, my_num_cols,
 
  373     $                   nb, np, npcol, nprow, np_save, odd_size,
 
  374     $                   part_offset, part_size, return_code, store_n_a,
 
  375     $                   temp, work_size_min, work_u
 
  378      INTEGER            DESCA_1XP( 7 ), PARAM_CHECK( 7, 3 )
 
  381      EXTERNAL           blacs_gridexit, blacs_gridinfo, 
ddttrf,
 
  383     $                   dtrrv2d, dtrsd2d, 
globchk, igamx2d, igebr2d,
 
  388      DOUBLE PRECISION   DDOT
 
  389      EXTERNAL           numroc, ddot
 
  405      temp = desca( dtype_ )
 
  406      IF( temp.EQ.502 ) 
THEN 
  408         desca( dtype_ ) = 501
 
  413      desca( dtype_ ) = temp
 
  415      IF( return_code.NE.0 ) 
THEN 
  421      ictxt = desca_1xp( 2 )
 
  422      csrc = desca_1xp( 5 )
 
  424      llda = desca_1xp( 6 )
 
  425      store_n_a = desca_1xp( 3 )
 
  430      CALL blacs_gridinfo( ictxt, nprow, npcol, myrow, mycol )
 
  435      IF( lwork.LT.-1 ) 
THEN 
  437      ELSE IF( lwork.EQ.-1 ) 
THEN 
  447      IF( n+ja-1.GT.store_n_a ) 
THEN 
  453      IF( nprow.NE.1 ) 
THEN 
  457      IF( n.GT.np*nb-mod( ja-1, nb ) ) 
THEN 
  459         CALL pxerbla( ictxt, 
'PDDTTRF, D&C alg.: only 1 block per proc' 
  464      IF( ( ja+n-1.GT.nb ) .AND. ( nb.LT.2*int_one ) ) 
THEN 
  466         CALL pxerbla( ictxt, 
'PDDTTRF, D&C alg.: NB too small', -info )
 
  473      laf_min = ( 12*npcol+3*nb )
 
  475      IF( laf.LT.laf_min ) 
THEN 
  479         CALL pxerbla( ictxt, 
'PDDTTRF: auxiliary storage error ',
 
  486      work_size_min = 8*npcol
 
  488      work( 1 ) = work_size_min
 
  490      IF( lwork.LT.work_size_min ) 
THEN 
  491         IF( lwork.NE.-1 ) 
THEN 
  493            CALL pxerbla( ictxt, 
'PDDTTRF: worksize error ', -info )
 
  500      param_check( 7, 1 ) = desca( 5 )
 
  501      param_check( 6, 1 ) = desca( 4 )
 
  502      param_check( 5, 1 ) = desca( 3 )
 
  503      param_check( 4, 1 ) = desca( 1 )
 
  504      param_check( 3, 1 ) = ja
 
  505      param_check( 2, 1 ) = n
 
  506      param_check( 1, 1 ) = idum3
 
  508      param_check( 7, 2 ) = 605
 
  509      param_check( 6, 2 ) = 604
 
  510      param_check( 5, 2 ) = 603
 
  511      param_check( 4, 2 ) = 601
 
  512      param_check( 3, 2 ) = 5
 
  513      param_check( 2, 2 ) = 1
 
  514      param_check( 1, 2 ) = 10
 
  522      ELSE IF( info.LT.-descmult ) 
THEN 
  525         info = -info*descmult
 
  530      CALL globchk( ictxt, 7, param_check, 7, param_check( 1, 3 ),
 
  536      IF( info.EQ.bignum ) 
THEN 
  538      ELSE IF( mod( info, descmult ).EQ.0 ) 
THEN 
  539         info = -info / descmult
 
  545         CALL pxerbla( ictxt, 
'PDDTTRF', -info )
 
  558      part_offset = nb*( ( ja-1 ) / ( npcol*nb ) )
 
  560      IF( ( mycol-csrc ).LT.( ja-part_offset-1 ) / nb ) 
THEN 
  561         part_offset = part_offset + nb
 
  564      IF( mycol.LT.csrc ) 
THEN 
  565         part_offset = part_offset - nb
 
  574      first_proc = mod( ( ja-1 ) / nb+csrc, npcol )
 
  578      ja_new = mod( ja-1, nb ) + 1
 
  583      np = ( ja_new+n-2 ) / nb + 1
 
  587      CALL reshape( ictxt, int_one, ictxt_new, int_one, first_proc,
 
  594      desca_1xp( 2 ) = ictxt_new
 
  598      CALL blacs_gridinfo( ictxt, nprow, npcol, myrow, mycol )
 
  602      IF( myrow.LT.0 ) 
THEN 
  615      my_num_cols = numroc( n, part_size, mycol, 0, npcol )
 
  619      IF( mycol.EQ.0 ) 
THEN 
  620         part_offset = part_offset + mod( ja_new-1, part_size )
 
  621         my_num_cols = my_num_cols - mod( ja_new-1, part_size )
 
  626      odd_size = my_num_cols
 
  627      IF( mycol.LT.np-1 ) 
THEN 
  628         odd_size = odd_size - int_one
 
  633      work_u = int_one*odd_size + 3
 
  650      IF( mycol.LT.np-1 ) 
THEN 
  656         CALL dtrsd2d( ictxt, 
'U', 
'N', 1, 1,
 
  657     $                 du( part_offset+odd_size+1 ), llda-1, 0,
 
  665      CALL ddttrf( odd_size, dl( part_offset+2 ), d( part_offset+1 ),
 
  666     $             du( part_offset+1 ), info )
 
  674      IF( mycol.LT.np-1 ) 
THEN 
  683         dl( part_offset+odd_size+1 ) = ( dl( part_offset+odd_size+1 ) )
 
  684     $                                   / ( d( part_offset+odd_size ) )
 
  691         d( part_offset+odd_size+1 ) = d( part_offset+odd_size+1 ) -
 
  692     $                                 dl( part_offset+odd_size+1 )*
 
  693     $                                 du( part_offset+odd_size )
 
  702      IF( mycol.NE.0 ) 
THEN 
  706         af( work_u+1 ) = ( dl( part_offset+1 ) )
 
  712            CALL ddttrsv( 
'L', 
'N', odd_size, int_one,
 
  713     $                    dl( part_offset+2 ), d( part_offset+1 ),
 
  714     $                    du( part_offset+1 ), af( work_u+1 ), odd_size,
 
  720            CALL dtrrv2d( ictxt, 
'U', 
'N', 1, 1, af( 1 ), odd_size, 0,
 
  723            CALL ddttrsv( 
'U', 
'T', odd_size, int_one,
 
  724     $                    dl( part_offset+2 ), d( part_offset+1 ),
 
  725     $                    du( part_offset+1 ), af( 1 ), odd_size, info )
 
  730            af( odd_size+3 ) = -one*ddot( odd_size, af( 1 ), 1,
 
  731     $                         af( work_u+1 ), 1 )
 
  737            CALL dgesd2d( ictxt, int_one, int_one, af( odd_size+3 ),
 
  738     $                    int_one, 0, mycol-1 )
 
  741            IF( mycol.LT.np-1 ) 
THEN 
  747               af( odd_size+1 ) = -one*( dl( part_offset+odd_size+1 )*
 
  748     $                            af( work_u+odd_size ) )
 
  751               af( work_u+( odd_size )+1 ) = -one*
 
  752     $            du( part_offset+odd_size )*( af( odd_size ) )
 
  765      CALL igamx2d( ictxt, 
'A', 
' ', 1, 1, info, 1, info, info, -1, 0,
 
  768      IF( mycol.EQ.0 ) 
THEN 
  769         CALL igebs2d( ictxt, 
'A', 
' ', 1, 1, info, 1 )
 
  771         CALL igebr2d( ictxt, 
'A', 
' ', 1, 1, info, 1, 0, 0 )
 
  789      IF( mycol.EQ.npcol-1 ) 
THEN 
  797      IF( ( mod( mycol+1, 2 ).EQ.0 ) .AND. ( mycol.GT.0 ) ) 
THEN 
  799         CALL dgesd2d( ictxt, int_one, int_one, af( odd_size+1 ),
 
  800     $                 int_one, 0, mycol-1 )
 
  802         CALL dgesd2d( ictxt, int_one, int_one, af( work_u+odd_size+1 ),
 
  803     $                 int_one, 0, mycol-1 )
 
  810      af( odd_size+2 ) = dble( d( part_offset+odd_size+1 ) )
 
  814      IF( mycol.LT.npcol-1 ) 
THEN 
  816         CALL dgerv2d( ictxt, int_one, int_one, af( odd_size+2+1 ),
 
  817     $                 int_one, 0, mycol+1 )
 
  821         af( odd_size+2 ) = af( odd_size+2 ) + af( odd_size+3 )
 
  836      IF( mod( ( mycol+1 ) / level_dist, 2 ).NE.0 )
 
  841      IF( mycol-level_dist.GE.0 ) 
THEN 
  842         CALL dgerv2d( ictxt, int_one, int_one, work( 1 ), int_one, 0,
 
  845         af( odd_size+2 ) = af( odd_size+2 ) + work( 1 )
 
  851      IF( mycol+level_dist.LT.npcol-1 ) 
THEN 
  852         CALL dgerv2d( ictxt, int_one, int_one, work( 1 ), int_one, 0,
 
  855         af( odd_size+2 ) = af( odd_size+2 ) + work( 1 )
 
  859      level_dist = level_dist*2
 
  868      IF( af( odd_size+2 ).EQ.zero ) 
THEN 
  877      IF( level_dist.EQ.1 ) 
THEN 
  878         comm_proc = mycol + 1
 
  883         af( work_u+odd_size+3 ) = af( odd_size+1 )
 
  885         af( odd_size+3 ) = af( work_u+odd_size+1 )
 
  888         comm_proc = mycol + level_dist / 2
 
  891      IF( mycol / level_dist.LE.( npcol-1 ) / level_dist-2 ) 
THEN 
  893         CALL dgerv2d( ictxt, int_one, int_one, af( odd_size+1 ),
 
  894     $                 int_one, 0, comm_proc )
 
  896         CALL dgerv2d( ictxt, int_one, int_one, af( work_u+odd_size+1 ),
 
  897     $                 int_one, 0, comm_proc )
 
  905            af( odd_size+1 ) = af( odd_size+1 ) / ( af( odd_size+2 ) )
 
  912         work( 1 ) = -one*( af( odd_size+1 ) )*
 
  913     $               af( work_u+( odd_size )+1 )
 
  917         CALL dgesd2d( ictxt, int_one, int_one, work( 1 ), int_one, 0,
 
  928      IF( ( mycol / level_dist.GT.0 ) .AND.
 
  929     $    ( mycol / level_dist.LE.( npcol-1 ) / level_dist-1 ) ) 
THEN 
  931         IF( level_dist.GT.1 ) 
THEN 
  936            CALL dgerv2d( ictxt, int_one, int_one,
 
  937     $                    af( work_u+odd_size+2+1 ), int_one, 0,
 
  938     $                    mycol-level_dist / 2 )
 
  943            CALL dgerv2d( ictxt, int_one, int_one, af( odd_size+2+1 ),
 
  944     $                    int_one, 0, mycol-level_dist / 2 )
 
  953            af( odd_size+3 ) = af( odd_size+3 ) / ( af( odd_size+2 ) )
 
  962         work( 1 ) = -one*af( odd_size+3 )*( af( work_u+odd_size+3 ) )
 
  966         CALL dgesd2d( ictxt, int_one, int_one, work( 1 ), int_one, 0,
 
  971         IF( mycol / level_dist.LE.( npcol-1 ) / level_dist-2 ) 
THEN 
  975            IF( ( mod( mycol / ( 2*level_dist ), 2 ) ).EQ.0 ) 
THEN 
  976               comm_proc = mycol + level_dist
 
  978               comm_proc = mycol - level_dist
 
  985            work( 1 ) = -one*af( work_u+odd_size+3 )*af( odd_size+1 )
 
  989            CALL dgesd2d( ictxt, int_one, int_one, work( 1 ), int_one,
 
  992            work( 1 ) = -one*af( odd_size+3 )*af( work_u+odd_size+1 )
 
  996            CALL dgesd2d( ictxt, int_one, int_one, work( 1 ), int_one,
 
 1012      IF( ictxt_save.NE.ictxt_new ) 
THEN 
 1013         CALL blacs_gridexit( ictxt_new )
 
 1025      work( 1 ) = work_size_min
 
 1029      CALL igamx2d( ictxt, 
'A', 
' ', 1, 1, info, 1, info, info, -1, 0,
 
 1032      IF( mycol.EQ.0 ) 
THEN 
 1033         CALL igebs2d( ictxt, 
'A', 
' ', 1, 1, info, 1 )
 
 1035         CALL igebr2d( ictxt, 
'A', 
' ', 1, 1, info, 1, 0, 0 )