3
    4
    5
    6
    7
    8
    9      CHARACTER          TRANS, UPLO
   10      INTEGER            BW, IB, INFO, JA, LAF, LWORK, N, NRHS
   11
   12
   13      INTEGER            DESCA( * ), DESCB( * )
   14      DOUBLE PRECISION   A( * ), AF( * ), B( * ), WORK( * )
   15
   16
   17
   18
   19
   20
   21
   22
   23
   24
   25
   26
   27
   28
   29
   30
   31
   32
   33
   34
   35
   36
   37
   38
   39
   40
   41
   42
   43
   44
   45
   46
   47
   48
   49
   50
   51
   52
   53
   54
   55
   56
   57
   58
   59
   60
   61
   62
   63
   64
   65
   66
   67
   68
   69
   70
   71
   72
   73
   74
   75
   76
   77
   78
   79
   80
   81
   82
   83
   84
   85
   86
   87
   88
   89
   90
   91
   92
   93
   94
   95
   96
   97
   98
   99
  100
  101
  102
  103
  104
  105
  106
  107
  108
  109
  110
  111
  112
  113
  114
  115
  116
  117
  118
  119
  120
  121
  122
  123
  124
  125
  126
  127
  128
  129
  130
  131
  132
  133
  134
  135
  136
  137
  138
  139
  140
  141
  142
  143
  144
  145
  146
  147
  148
  149
  150
  151
  152
  153
  154
  155
  156
  157
  158
  159
  160
  161
  162
  163
  164
  165
  166
  167
  168
  169
  170
  171
  172
  173
  174
  175
  176
  177
  178
  179
  180
  181
  182
  183
  184
  185
  186
  187
  188
  189
  190
  191
  192
  193
  194
  195
  196
  197
  198
  199
  200
  201
  202
  203
  204
  205
  206
  207
  208
  209
  210
  211
  212
  213
  214
  215
  216
  217
  218
  219
  220
  221
  222
  223
  224
  225
  226
  227
  228
  229
  230
  231
  232
  233
  234
  235
  236
  237
  238
  239
  240
  241
  242
  243
  244
  245
  246
  247
  248
  249
  250
  251
  252
  253
  254
  255
  256
  257
  258
  259
  260
  261
  262
  263
  264
  265
  266
  267
  268
  269
  270
  271
  272
  273
  274
  275
  276
  277
  278
  279
  280
  281
  282
  283
  284
  285
  286
  287
  288
  289
  290
  291
  292
  293
  294
  295
  296
  297
  298
  299
  300
  301
  302
  303
  304
  305
  306
  307
  308
  309
  310
  311
  312
  313
  314
  315
  316
  317
  318
  319
  320
  321
  322
  323
  324
  325
  326
  327
  328
  329
  330
  331
  332
  333
  334
  335
  336
  337
  338
  339
  340
  341
  342
  343
  344
  345
  346
  347
  348
  349
  350
  351
  352
  353
  354
  355
  356
  357
  358
  359
  360
  361
  362
  363
  364
  365
  366
  367
  368      DOUBLE PRECISION   ONE
  369      parameter( one = 1.0d+0 )
  370      DOUBLE PRECISION   ZERO
  371      parameter( zero = 0.0d+0 )
  372      INTEGER            INT_ONE
  373      parameter( int_one = 1 )
  374      INTEGER            DESCMULT, BIGNUM
  375      parameter( descmult = 100, bignum = descmult*descmult )
  376      INTEGER            BLOCK_CYCLIC_2D, CSRC_, CTXT_, DLEN_, DTYPE_,
  377     $                   LLD_, MB_, M_, NB_, N_, RSRC_
  378      parameter( block_cyclic_2d = 1, dlen_ = 9, dtype_ = 1,
  379     $                     ctxt_ = 2, m_ = 3, n_ = 4, mb_ = 5, nb_ = 6,
  380     $                     rsrc_ = 7, csrc_ = 8, lld_ = 9 )
  381
  382
  383      INTEGER            CSRC, FIRST_PROC, ICTXT, ICTXT_NEW, ICTXT_SAVE,
  384     $                   IDUM1, IDUM2, IDUM3, JA_NEW, LEVEL_DIST, LLDA,
  385     $                   LLDB, MBW2, MYCOL, MYROW, MY_NUM_COLS, NB, NP,
  386     $                   NPCOL, NPROW, NP_SAVE, ODD_SIZE, OFST,
  387     $                   PART_OFFSET, PART_SIZE, RETURN_CODE, STORE_M_B,
  388     $                   STORE_N_A, WORK_SIZE_MIN
  389
  390
  391      INTEGER            DESCA_1XP( 7 ), DESCB_PX1( 7 ),
  392     $                   PARAM_CHECK( 17, 3 )
  393
  394
  396     $                   dgemm, dgerv2d, dgesd2d, dlamov, 
dmatadd,
 
  399
  400
  401      LOGICAL            LSAME
  402      INTEGER            NUMROC
  404
  405
  406      INTRINSIC          ichar, mod
  407
  408
  409
  410
  411
  412      info = 0
  413
  414
  415
  416
  417      desca_1xp( 1 ) = 501
  418      descb_px1( 1 ) = 502
  419
  421
  422      IF( return_code.NE.0 ) THEN
  423         info = -( 8*100+2 )
  424      END IF
  425
  427
  428      IF( return_code.NE.0 ) THEN
  429         info = -( 11*100+2 )
  430      END IF
  431
  432
  433
  434
  435      IF( desca_1xp( 2 ).NE.descb_px1( 2 ) ) THEN
  436         info = -( 11*100+2 )
  437      END IF
  438
  439
  440
  441
  442
  443      IF( desca_1xp( 4 ).NE.descb_px1( 4 ) ) THEN
  444         info = -( 11*100+4 )
  445      END IF
  446
  447
  448
  449      IF( desca_1xp( 5 ).NE.descb_px1( 5 ) ) THEN
  450         info = -( 11*100+5 )
  451      END IF
  452
  453
  454
  455      ictxt = desca_1xp( 2 )
  456      csrc = desca_1xp( 5 )
  457      nb = desca_1xp( 4 )
  458      llda = desca_1xp( 6 )
  459      store_n_a = desca_1xp( 3 )
  460      lldb = descb_px1( 6 )
  461      store_m_b = descb_px1( 3 )
  462
  463
  464
  465
  466
  467
  468      mbw2 = bw*bw
  469
  470      CALL blacs_gridinfo( ictxt, nprow, npcol, myrow, mycol )
  471      np = nprow*npcol
  472
  473
  474
  475      IF( 
lsame( uplo, 
'U' ) ) 
THEN 
  476         idum1 = ichar( 'U' )
  477      ELSE IF( 
lsame( uplo, 
'L' ) ) 
THEN 
  478         idum1 = ichar( 'L' )
  479      ELSE
  480         info = -1
  481      END IF
  482
  483      IF( 
lsame( trans, 
'N' ) ) 
THEN 
  484         idum2 = ichar( 'N' )
  485      ELSE IF( 
lsame( trans, 
'T' ) ) 
THEN 
  486         idum2 = ichar( 'T' )
  487      ELSE IF( 
lsame( trans, 
'C' ) ) 
THEN 
  488         idum2 = ichar( 'T' )
  489      ELSE
  490         info = -2
  491      END IF
  492
  493      IF( lwork.LT.-1 ) THEN
  494         info = -14
  495      ELSE IF( lwork.EQ.-1 ) THEN
  496         idum3 = -1
  497      ELSE
  498         idum3 = 1
  499      END IF
  500
  501      IF( n.LT.0 ) THEN
  502         info = -3
  503      END IF
  504
  505      IF( n+ja-1.GT.store_n_a ) THEN
  506         info = -( 8*100+6 )
  507      END IF
  508
  509      IF( ( bw.GT.n-1 ) .OR. ( bw.LT.0 ) ) THEN
  510         info = -4
  511      END IF
  512
  513      IF( llda.LT.( bw+1 ) ) THEN
  514         info = -( 8*100+6 )
  515      END IF
  516
  517      IF( nb.LE.0 ) THEN
  518         info = -( 8*100+4 )
  519      END IF
  520
  521      IF( n+ib-1.GT.store_m_b ) THEN
  522         info = -( 11*100+3 )
  523      END IF
  524
  525      IF( lldb.LT.nb ) THEN
  526         info = -( 11*100+6 )
  527      END IF
  528
  529      IF( nrhs.LT.0 ) THEN
  530         info = -5
  531      END IF
  532
  533
  534
  535      IF( ja.NE.ib ) THEN
  536         info = -7
  537      END IF
  538
  539
  540
  541      IF( nprow.NE.1 ) THEN
  542         info = -( 8*100+2 )
  543      END IF
  544
  545      IF( n.GT.np*nb-mod( ja-1, nb ) ) THEN
  546         info = -( 3 )
  548     $                 'PDPBTRSV, D&C alg.: only 1 block per proc',
  549     $                 -info )
  550         RETURN
  551      END IF
  552
  553      IF( ( ja+n-1.GT.nb ) .AND. ( nb.LT.2*bw ) ) THEN
  554         info = -( 8*100+4 )
  555         CALL pxerbla( ictxt, 
'PDPBTRSV, D&C alg.: NB too small',
 
  556     $                 -info )
  557         RETURN
  558      END IF
  559
  560
  561      work_size_min = bw*nrhs
  562
  563      work( 1 ) = work_size_min
  564
  565      IF( lwork.LT.work_size_min ) THEN
  566         IF( lwork.NE.-1 ) THEN
  567            info = -14
  568            CALL pxerbla( ictxt, 
'PDPBTRSV: worksize error', -info )
 
  569         END IF
  570         RETURN
  571      END IF
  572
  573
  574
  575      param_check( 17, 1 ) = descb( 5 )
  576      param_check( 16, 1 ) = descb( 4 )
  577      param_check( 15, 1 ) = descb( 3 )
  578      param_check( 14, 1 ) = descb( 2 )
  579      param_check( 13, 1 ) = descb( 1 )
  580      param_check( 12, 1 ) = ib
  581      param_check( 11, 1 ) = desca( 5 )
  582      param_check( 10, 1 ) = desca( 4 )
  583      param_check( 9, 1 ) = desca( 3 )
  584      param_check( 8, 1 ) = desca( 1 )
  585      param_check( 7, 1 ) = ja
  586      param_check( 6, 1 ) = nrhs
  587      param_check( 5, 1 ) = bw
  588      param_check( 4, 1 ) = n
  589      param_check( 3, 1 ) = idum3
  590      param_check( 2, 1 ) = idum2
  591      param_check( 1, 1 ) = idum1
  592
  593      param_check( 17, 2 ) = 1105
  594      param_check( 16, 2 ) = 1104
  595      param_check( 15, 2 ) = 1103
  596      param_check( 14, 2 ) = 1102
  597      param_check( 13, 2 ) = 1101
  598      param_check( 12, 2 ) = 10
  599      param_check( 11, 2 ) = 805
  600      param_check( 10, 2 ) = 804
  601      param_check( 9, 2 ) = 803
  602      param_check( 8, 2 ) = 801
  603      param_check( 7, 2 ) = 7
  604      param_check( 6, 2 ) = 5
  605      param_check( 5, 2 ) = 4
  606      param_check( 4, 2 ) = 3
  607      param_check( 3, 2 ) = 14
  608      param_check( 2, 2 ) = 2
  609      param_check( 1, 2 ) = 1
  610
  611
  612
  613
  614
  615      IF( info.GE.0 ) THEN
  616         info = bignum
  617      ELSE IF( info.LT.-descmult ) THEN
  618         info = -info
  619      ELSE
  620         info = -info*descmult
  621      END IF
  622
  623
  624
  625      CALL globchk( ictxt, 17, param_check, 17, param_check( 1, 3 ),
 
  626     $              info )
  627
  628
  629
  630
  631      IF( info.EQ.bignum ) THEN
  632         info = 0
  633      ELSE IF( mod( info, descmult ).EQ.0 ) THEN
  634         info = -info / descmult
  635      ELSE
  636         info = -info
  637      END IF
  638
  639      IF( info.LT.0 ) THEN
  640         CALL pxerbla( ictxt, 
'PDPBTRSV', -info )
 
  641         RETURN
  642      END IF
  643
  644
  645
  646      IF( n.EQ.0 )
  647     $   RETURN
  648
  649      IF( nrhs.EQ.0 )
  650     $   RETURN
  651
  652
  653
  654
  655
  656      part_offset = nb*( ( ja-1 ) / ( npcol*nb ) )
  657
  658      IF( ( mycol-csrc ).LT.( ja-part_offset-1 ) / nb ) THEN
  659         part_offset = part_offset + nb
  660      END IF
  661
  662      IF( mycol.LT.csrc ) THEN
  663         part_offset = part_offset - nb
  664      END IF
  665
  666
  667
  668
  669
  670
  671
  672      first_proc = mod( ( ja-1 ) / nb+csrc, npcol )
  673
  674
  675
  676      ja_new = mod( ja-1, nb ) + 1
  677
  678
  679
  680      np_save = np
  681      np = ( ja_new+n-2 ) / nb + 1
  682
  683
  684
  685      CALL reshape( ictxt, int_one, ictxt_new, int_one, first_proc,
 
  686     $              int_one, np )
  687
  688
  689
  690      ictxt_save = ictxt
  691      ictxt = ictxt_new
  692      desca_1xp( 2 ) = ictxt_new
  693      descb_px1( 2 ) = ictxt_new
  694
  695
  696
  697      CALL blacs_gridinfo( ictxt, nprow, npcol, myrow, mycol )
  698
  699
  700
  701      IF( myrow.LT.0 ) THEN
  702         GO TO 180
  703      END IF
  704
  705
  706
  707
  708
  709
  710      part_size = nb
  711
  712
  713
  714      my_num_cols = 
numroc( n, part_size, mycol, 0, npcol )
 
  715
  716
  717
  718      IF( mycol.EQ.0 ) THEN
  719         part_offset = part_offset + mod( ja_new-1, part_size )
  720         my_num_cols = my_num_cols - mod( ja_new-1, part_size )
  721      END IF
  722
  723
  724
  725      ofst = part_offset*llda
  726
  727
  728
  729      odd_size = my_num_cols
  730      IF( mycol.LT.np-1 ) THEN
  731         odd_size = odd_size - bw
  732      END IF
  733
  734
  735
  736
  737
  738      IF( 
lsame( uplo, 
'L' ) ) 
THEN 
  739
  740         IF( 
lsame( trans, 
'N' ) ) 
THEN 
  741
  742
  743
  744
  745
  746
  747
  748
  749
  750
  751            CALL dtbtrs( uplo, 'N', 'N', odd_size, bw, nrhs,
  752     $                   a( ofst+1 ), llda, b( part_offset+1 ), lldb,
  753     $                   info )
  754
  755
  756            IF( mycol.LT.np-1 ) THEN
  757
  758
  759
  760
  761
  762
  763
  764               CALL dlamov( 'N', bw, nrhs,
  765     $                      b( part_offset+odd_size-bw+1 ), lldb,
  766     $                      work( 1 ), bw )
  767
  768               CALL dtrmm( 'L', 'U', 'N', 'N', bw, nrhs, -one,
  769     $                     a( ( ofst+( bw+1 )+( odd_size-bw )*llda ) ),
  770     $                     llda-1, work( 1 ), bw )
  771
  772               CALL dmatadd( bw, nrhs, one, work( 1 ), bw, one,
 
  773     $                       b( part_offset+odd_size+1 ), lldb )
  774
  775            END IF
  776
  777
  778            IF( mycol.NE.0 ) THEN
  779
  780
  781
  782               CALL dgemm( 'T', 'N', bw, nrhs, odd_size, -one, af( 1 ),
  783     $                     odd_size, b( part_offset+1 ), lldb, zero,
  784     $                     work( 1+bw-bw ), bw )
  785            END IF
  786
  787
  788
  789
  790
  791
  792
  793
  794
  795            IF( mycol.GT.0 ) THEN
  796
  797               CALL dgesd2d( ictxt, bw, nrhs, work( 1 ), bw, 0,
  798     $                       mycol-1 )
  799
  800            END IF
  801
  802
  803
  804            IF( mycol.LT.npcol-1 ) THEN
  805
  806               CALL dgerv2d( ictxt, bw, nrhs, work( 1 ), bw, 0,
  807     $                       mycol+1 )
  808
  809
  810
  811               CALL dmatadd( bw, nrhs, one, work( 1 ), bw, one,
 
  812     $                       b( part_offset+odd_size+1 ), lldb )
  813
  814            END IF
  815
  816
  817
  818
  819            IF( mycol.EQ.npcol-1 ) THEN
  820               GO TO 30
  821            END IF
  822
  823
  824
  825
  826
  827
  828
  829            level_dist = 1
  830
  831
  832
  833   10       CONTINUE
  834            IF( mod( ( mycol+1 ) / level_dist, 2 ).NE.0 )
  835     $         GO TO 20
  836
  837
  838
  839            IF( mycol-level_dist.GE.0 ) THEN
  840
  841               CALL dgerv2d( ictxt, bw, nrhs, work( 1 ), bw, 0,
  842     $                       mycol-level_dist )
  843
  844               CALL dmatadd( bw, nrhs, one, work( 1 ), bw, one,
 
  845     $                       b( part_offset+odd_size+1 ), lldb )
  846
  847            END IF
  848
  849
  850
  851            IF( mycol+level_dist.LT.npcol-1 ) THEN
  852
  853               CALL dgerv2d( ictxt, bw, nrhs, work( 1 ), bw, 0,
  854     $                       mycol+level_dist )
  855
  856               CALL dmatadd( bw, nrhs, one, work( 1 ), bw, one,
 
  857     $                       b( part_offset+odd_size+1 ), lldb )
  858
  859            END IF
  860
  861            level_dist = level_dist*2
  862
  863            GO TO 10
  864   20       CONTINUE
  865
  866
  867
  868
  869
  870
  871
  872
  873
  874            CALL dtrtrs( 'L', 'N', 'N', bw, nrhs,
  875     $                   af( odd_size*bw+mbw2+1 ), bw,
  876     $                   b( part_offset+odd_size+1 ), lldb, info )
  877
  878            IF( info.NE.0 ) THEN
  879               GO TO 170
  880            END IF
  881
  882
  883
  884
  885            IF( mycol / level_dist.LE.( npcol-1 ) / level_dist-2 ) THEN
  886
  887
  888
  889               CALL dgemm( 'T', 'N', bw, nrhs, bw, -one,
  890     $                     af( ( odd_size )*bw+1 ), bw,
  891     $                     b( part_offset+odd_size+1 ), lldb, zero,
  892     $                     work( 1 ), bw )
  893
  894
  895
  896               CALL dgesd2d( ictxt, bw, nrhs, work( 1 ), bw, 0,
  897     $                       mycol+level_dist )
  898
  899            END IF
  900
  901
  902
  903            IF( ( mycol / level_dist.GT.0 ) .AND.
  904     $          ( mycol / level_dist.LE.( npcol-1 ) / level_dist-1 ) )
  905     $           THEN
  906
  907
  908
  909
  910
  911               CALL dgemm( 'N', 'N', bw, nrhs, bw, -one,
  912     $                     af( odd_size*bw+2*mbw2+1 ), bw,
  913     $                     b( part_offset+odd_size+1 ), lldb, zero,
  914     $                     work( 1 ), bw )
  915
  916
  917
  918               CALL dgesd2d( ictxt, bw, nrhs, work( 1 ), bw, 0,
  919     $                       mycol-level_dist )
  920
  921            END IF
  922
  923
  924   30       CONTINUE
  925
  926         ELSE
  927
  928
  929
  930
  931
  932
  933
  934
  935
  936
  937
  938            IF( mycol.EQ.npcol-1 ) THEN
  939               GO TO 80
  940            END IF
  941
  942
  943
  944            level_dist = 1
  945   40       CONTINUE
  946            IF( mod( ( mycol+1 ) / level_dist, 2 ).NE.0 )
  947     $         GO TO 50
  948
  949            level_dist = level_dist*2
  950
  951            GO TO 40
  952   50       CONTINUE
  953
  954
  955            IF( ( mycol / level_dist.GT.0 ) .AND.
  956     $          ( mycol / level_dist.LE.( npcol-1 ) / level_dist-1 ) )
  957     $           THEN
  958
  959
  960
  961               CALL dgerv2d( ictxt, bw, nrhs, work( 1 ), bw, 0,
  962     $                       mycol-level_dist )
  963
  964
  965
  966
  967
  968               CALL dgemm( 'T', 'N', bw, nrhs, bw, -one,
  969     $                     af( odd_size*bw+2*mbw2+1 ), bw, work( 1 ),
  970     $                     bw, one, b( part_offset+odd_size+1 ), lldb )
  971            END IF
  972
  973
  974
  975            IF( mycol / level_dist.LE.( npcol-1 ) / level_dist-2 ) THEN
  976
  977
  978
  979               CALL dgerv2d( ictxt, bw, nrhs, work( 1 ), bw, 0,
  980     $                       mycol+level_dist )
  981
  982
  983
  984               CALL dgemm( 'N', 'N', bw, nrhs, bw, -one,
  985     $                     af( ( odd_size )*bw+1 ), bw, work( 1 ), bw,
  986     $                     one, b( part_offset+odd_size+1 ), lldb )
  987
  988            END IF
  989
  990
  991
  992
  993
  994            CALL dtrtrs( 'L', 'T', 'N', bw, nrhs,
  995     $                   af( odd_size*bw+mbw2+1 ), bw,
  996     $                   b( part_offset+odd_size+1 ), lldb, info )
  997
  998            IF( info.NE.0 ) THEN
  999               GO TO 170
 1000            END IF
 1001
 1002
 1003
 1004
 1005
 1006   60       CONTINUE
 1007            IF( level_dist.EQ.1 )
 1008     $         GO TO 70
 1009
 1010            level_dist = level_dist / 2
 1011
 1012
 1013
 1014            IF( mycol+level_dist.LT.npcol-1 ) THEN
 1015
 1016               CALL dgesd2d( ictxt, bw, nrhs,
 1017     $                       b( part_offset+odd_size+1 ), lldb, 0,
 1018     $                       mycol+level_dist )
 1019
 1020            END IF
 1021
 1022
 1023
 1024            IF( mycol-level_dist.GE.0 ) THEN
 1025
 1026               CALL dgesd2d( ictxt, bw, nrhs,
 1027     $                       b( part_offset+odd_size+1 ), lldb, 0,
 1028     $                       mycol-level_dist )
 1029
 1030            END IF
 1031
 1032            GO TO 60
 1033   70       CONTINUE
 1034
 1035
 1036   80       CONTINUE
 1037
 1038
 1039
 1040
 1041
 1042
 1043
 1044
 1045
 1046            IF( mycol.LT.npcol-1 ) THEN
 1047
 1048               CALL dgesd2d( ictxt, bw, nrhs,
 1049     $                       b( part_offset+odd_size+1 ), lldb, 0,
 1050     $                       mycol+1 )
 1051
 1052            END IF
 1053
 1054
 1055
 1056            IF( mycol.GT.0 ) THEN
 1057
 1058               CALL dgerv2d( ictxt, bw, nrhs, work( 1 ), bw, 0,
 1059     $                       mycol-1 )
 1060
 1061            END IF
 1062
 1063
 1064
 1065
 1066
 1067
 1068
 1069            IF( mycol.NE.0 ) THEN
 1070
 1071
 1072
 1073               CALL dgemm( 'N', 'N', odd_size, nrhs, bw, -one, af( 1 ),
 1074     $                     odd_size, work( 1+bw-bw ), bw, one,
 1075     $                     b( part_offset+1 ), lldb )
 1076
 1077            END IF
 1078
 1079
 1080            IF( mycol.LT.np-1 ) THEN
 1081
 1082
 1083
 1084
 1085
 1086
 1087
 1088               CALL dlamov( 'N', bw, nrhs, b( part_offset+odd_size+1 ),
 1089     $                      lldb, work( 1+bw-bw ), bw )
 1090
 1091               CALL dtrmm( 'L', 'U', 'T', 'N', bw, nrhs, -one,
 1092     $                     a( ( ofst+( bw+1 )+( odd_size-bw )*llda ) ),
 1093     $                     llda-1, work( 1+bw-bw ), bw )
 1094
 1095               CALL dmatadd( bw, nrhs, one, work( 1+bw-bw ), bw, one,
 
 1096     $                       b( part_offset+odd_size-bw+1 ), lldb )
 1097
 1098            END IF
 1099
 1100
 1101
 1102            CALL dtbtrs( uplo, 'T', 'N', odd_size, bw, nrhs,
 1103     $                   a( ofst+1 ), llda, b( part_offset+1 ), lldb,
 1104     $                   info )
 1105
 1106         END IF
 1107
 1108
 1109
 1110      ELSE
 1111
 1112
 1113
 1114         IF( 
lsame( trans, 
'T' ) ) 
THEN 
 1115
 1116
 1117
 1118
 1119
 1120
 1121
 1122
 1123
 1124
 1125            CALL dtbtrs( uplo, 'T', 'N', odd_size, bw, nrhs,
 1126     $                   a( ofst+1 ), llda, b( part_offset+1 ), lldb,
 1127     $                   info )
 1128
 1129
 1130            IF( mycol.LT.np-1 ) THEN
 1131
 1132
 1133
 1134
 1135
 1136
 1137
 1138               CALL dlamov( 'N', bw, nrhs,
 1139     $                      b( part_offset+odd_size-bw+1 ), lldb,
 1140     $                      work( 1 ), bw )
 1141
 1142               CALL dtrmm( 'L', 'L', 'T', 'N', bw, nrhs, -one,
 1143     $                     a( ( ofst+1+odd_size*llda ) ), llda-1,
 1144     $                     work( 1 ), bw )
 1145
 1146               CALL dmatadd( bw, nrhs, one, work( 1 ), bw, one,
 
 1147     $                       b( part_offset+odd_size+1 ), lldb )
 1148
 1149            END IF
 1150
 1151
 1152            IF( mycol.NE.0 ) THEN
 1153
 1154
 1155
 1156               CALL dgemm( 'T', 'N', bw, nrhs, odd_size, -one, af( 1 ),
 1157     $                     odd_size, b( part_offset+1 ), lldb, zero,
 1158     $                     work( 1+bw-bw ), bw )
 1159            END IF
 1160
 1161
 1162
 1163
 1164
 1165
 1166
 1167
 1168
 1169            IF( mycol.GT.0 ) THEN
 1170
 1171               CALL dgesd2d( ictxt, bw, nrhs, work( 1 ), bw, 0,
 1172     $                       mycol-1 )
 1173
 1174            END IF
 1175
 1176
 1177
 1178            IF( mycol.LT.npcol-1 ) THEN
 1179
 1180               CALL dgerv2d( ictxt, bw, nrhs, work( 1 ), bw, 0,
 1181     $                       mycol+1 )
 1182
 1183
 1184
 1185               CALL dmatadd( bw, nrhs, one, work( 1 ), bw, one,
 
 1186     $                       b( part_offset+odd_size+1 ), lldb )
 1187
 1188            END IF
 1189
 1190
 1191
 1192
 1193            IF( mycol.EQ.npcol-1 ) THEN
 1194               GO TO 110
 1195            END IF
 1196
 1197
 1198
 1199
 1200
 1201
 1202
 1203            level_dist = 1
 1204
 1205
 1206
 1207   90       CONTINUE
 1208            IF( mod( ( mycol+1 ) / level_dist, 2 ).NE.0 )
 1209     $         GO TO 100
 1210
 1211
 1212
 1213            IF( mycol-level_dist.GE.0 ) THEN
 1214
 1215               CALL dgerv2d( ictxt, bw, nrhs, work( 1 ), bw, 0,
 1216     $                       mycol-level_dist )
 1217
 1218               CALL dmatadd( bw, nrhs, one, work( 1 ), bw, one,
 
 1219     $                       b( part_offset+odd_size+1 ), lldb )
 1220
 1221            END IF
 1222
 1223
 1224
 1225            IF( mycol+level_dist.LT.npcol-1 ) THEN
 1226
 1227               CALL dgerv2d( ictxt, bw, nrhs, work( 1 ), bw, 0,
 1228     $                       mycol+level_dist )
 1229
 1230               CALL dmatadd( bw, nrhs, one, work( 1 ), bw, one,
 
 1231     $                       b( part_offset+odd_size+1 ), lldb )
 1232
 1233            END IF
 1234
 1235            level_dist = level_dist*2
 1236
 1237            GO TO 90
 1238  100       CONTINUE
 1239
 1240
 1241
 1242
 1243
 1244
 1245
 1246
 1247
 1248            CALL dtrtrs( 'L', 'N', 'N', bw, nrhs,
 1249     $                   af( odd_size*bw+mbw2+1 ), bw,
 1250     $                   b( part_offset+odd_size+1 ), lldb, info )
 1251
 1252            IF( info.NE.0 ) THEN
 1253               GO TO 170
 1254            END IF
 1255
 1256
 1257
 1258
 1259            IF( mycol / level_dist.LE.( npcol-1 ) / level_dist-2 ) THEN
 1260
 1261
 1262
 1263               CALL dgemm( 'T', 'N', bw, nrhs, bw, -one,
 1264     $                     af( ( odd_size )*bw+1 ), bw,
 1265     $                     b( part_offset+odd_size+1 ), lldb, zero,
 1266     $                     work( 1 ), bw )
 1267
 1268
 1269
 1270               CALL dgesd2d( ictxt, bw, nrhs, work( 1 ), bw, 0,
 1271     $                       mycol+level_dist )
 1272
 1273            END IF
 1274
 1275
 1276
 1277            IF( ( mycol / level_dist.GT.0 ) .AND.
 1278     $          ( mycol / level_dist.LE.( npcol-1 ) / level_dist-1 ) )
 1279     $           THEN
 1280
 1281
 1282
 1283
 1284
 1285               CALL dgemm( 'N', 'N', bw, nrhs, bw, -one,
 1286     $                     af( odd_size*bw+2*mbw2+1 ), bw,
 1287     $                     b( part_offset+odd_size+1 ), lldb, zero,
 1288     $                     work( 1 ), bw )
 1289
 1290
 1291
 1292               CALL dgesd2d( ictxt, bw, nrhs, work( 1 ), bw, 0,
 1293     $                       mycol-level_dist )
 1294
 1295            END IF
 1296
 1297
 1298  110       CONTINUE
 1299
 1300         ELSE
 1301
 1302
 1303
 1304
 1305
 1306
 1307
 1308
 1309
 1310
 1311
 1312            IF( mycol.EQ.npcol-1 ) THEN
 1313               GO TO 160
 1314            END IF
 1315
 1316
 1317
 1318            level_dist = 1
 1319  120       CONTINUE
 1320            IF( mod( ( mycol+1 ) / level_dist, 2 ).NE.0 )
 1321     $         GO TO 130
 1322
 1323            level_dist = level_dist*2
 1324
 1325            GO TO 120
 1326  130       CONTINUE
 1327
 1328
 1329            IF( ( mycol / level_dist.GT.0 ) .AND.
 1330     $          ( mycol / level_dist.LE.( npcol-1 ) / level_dist-1 ) )
 1331     $           THEN
 1332
 1333
 1334
 1335               CALL dgerv2d( ictxt, bw, nrhs, work( 1 ), bw, 0,
 1336     $                       mycol-level_dist )
 1337
 1338
 1339
 1340
 1341
 1342               CALL dgemm( 'T', 'N', bw, nrhs, bw, -one,
 1343     $                     af( odd_size*bw+2*mbw2+1 ), bw, work( 1 ),
 1344     $                     bw, one, b( part_offset+odd_size+1 ), lldb )
 1345            END IF
 1346
 1347
 1348
 1349            IF( mycol / level_dist.LE.( npcol-1 ) / level_dist-2 ) THEN
 1350
 1351
 1352
 1353               CALL dgerv2d( ictxt, bw, nrhs, work( 1 ), bw, 0,
 1354     $                       mycol+level_dist )
 1355
 1356
 1357
 1358               CALL dgemm( 'N', 'N', bw, nrhs, bw, -one,
 1359     $                     af( ( odd_size )*bw+1 ), bw, work( 1 ), bw,
 1360     $                     one, b( part_offset+odd_size+1 ), lldb )
 1361
 1362            END IF
 1363
 1364
 1365
 1366
 1367
 1368            CALL dtrtrs( 'L', 'T', 'N', bw, nrhs,
 1369     $                   af( odd_size*bw+mbw2+1 ), bw,
 1370     $                   b( part_offset+odd_size+1 ), lldb, info )
 1371
 1372            IF( info.NE.0 ) THEN
 1373               GO TO 170
 1374            END IF
 1375
 1376
 1377
 1378
 1379
 1380  140       CONTINUE
 1381            IF( level_dist.EQ.1 )
 1382     $         GO TO 150
 1383
 1384            level_dist = level_dist / 2
 1385
 1386
 1387
 1388            IF( mycol+level_dist.LT.npcol-1 ) THEN
 1389
 1390               CALL dgesd2d( ictxt, bw, nrhs,
 1391     $                       b( part_offset+odd_size+1 ), lldb, 0,
 1392     $                       mycol+level_dist )
 1393
 1394            END IF
 1395
 1396
 1397
 1398            IF( mycol-level_dist.GE.0 ) THEN
 1399
 1400               CALL dgesd2d( ictxt, bw, nrhs,
 1401     $                       b( part_offset+odd_size+1 ), lldb, 0,
 1402     $                       mycol-level_dist )
 1403
 1404            END IF
 1405
 1406            GO TO 140
 1407  150       CONTINUE
 1408
 1409
 1410  160       CONTINUE
 1411
 1412
 1413
 1414
 1415
 1416
 1417
 1418
 1419
 1420            IF( mycol.LT.npcol-1 ) THEN
 1421
 1422               CALL dgesd2d( ictxt, bw, nrhs,
 1423     $                       b( part_offset+odd_size+1 ), lldb, 0,
 1424     $                       mycol+1 )
 1425
 1426            END IF
 1427
 1428
 1429
 1430            IF( mycol.GT.0 ) THEN
 1431
 1432               CALL dgerv2d( ictxt, bw, nrhs, work( 1 ), bw, 0,
 1433     $                       mycol-1 )
 1434
 1435            END IF
 1436
 1437
 1438
 1439
 1440
 1441
 1442
 1443            IF( mycol.NE.0 ) THEN
 1444
 1445
 1446
 1447               CALL dgemm( 'N', 'N', odd_size, nrhs, bw, -one, af( 1 ),
 1448     $                     odd_size, work( 1+bw-bw ), bw, one,
 1449     $                     b( part_offset+1 ), lldb )
 1450
 1451            END IF
 1452
 1453
 1454            IF( mycol.LT.np-1 ) THEN
 1455
 1456
 1457
 1458
 1459
 1460
 1461
 1462               CALL dlamov( 'N', bw, nrhs, b( part_offset+odd_size+1 ),
 1463     $                      lldb, work( 1+bw-bw ), bw )
 1464
 1465               CALL dtrmm( 'L', 'L', 'N', 'N', bw, nrhs, -one,
 1466     $                     a( ( ofst+1+odd_size*llda ) ), llda-1,
 1467     $                     work( 1+bw-bw ), bw )
 1468
 1469               CALL dmatadd( bw, nrhs, one, work( 1+bw-bw ), bw, one,
 
 1470     $                       b( part_offset+odd_size-bw+1 ), lldb )
 1471
 1472            END IF
 1473
 1474
 1475
 1476            CALL dtbtrs( uplo, 'N', 'N', odd_size, bw, nrhs,
 1477     $                   a( ofst+1 ), llda, b( part_offset+1 ), lldb,
 1478     $                   info )
 1479
 1480         END IF
 1481
 1482
 1483
 1484      END IF
 1485
 1486  170 CONTINUE
 1487
 1488
 1489
 1490
 1491      IF( ictxt_save.NE.ictxt_new ) THEN
 1492         CALL blacs_gridexit( ictxt_new )
 1493      END IF
 1494
 1495  180 CONTINUE
 1496
 1497
 1498
 1499      ictxt = ictxt_save
 1500      np = np_save
 1501
 1502
 1503
 1504      work( 1 ) = work_size_min
 1505
 1506
 1507      RETURN
 1508
 1509
 1510
subroutine desc_convert(desc_in, desc_out, info)
 
subroutine dmatadd(m, n, alpha, a, lda, beta, c, ldc)
 
integer function numroc(n, nb, iproc, isrcproc, nprocs)
 
subroutine globchk(ictxt, n, x, ldx, iwork, info)
 
subroutine pxerbla(ictxt, srname, info)
 
void reshape(Int *context_in, Int *major_in, Int *context_out, Int *major_out, Int *first_proc, Int *nprow_new, Int *npcol_new)