3
    4
    5
    6
    7
    8
    9      CHARACTER          TRANS, UPLO
   10      INTEGER            BWL, BWU, IB, INFO, JA, LAF, LWORK, N, NRHS
   11
   12
   13      INTEGER            DESCA( * ), DESCB( * )
   14      COMPLEX            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
  369
  370
  371
  372
  373      REAL               ONE, ZERO
  374      parameter( one = 1.0e+0 )
  375      parameter( zero = 0.0e+0 )
  376      COMPLEX            CONE, CZERO
  377      parameter( cone = ( 1.0e+0, 0.0e+0 ) )
  378      parameter( czero = ( 0.0e+0, 0.0e+0 ) )
  379      INTEGER            INT_ONE
  380      parameter( int_one = 1 )
  381      INTEGER            DESCMULT, BIGNUM
  382      parameter(descmult = 100, bignum = descmult * descmult)
  383      INTEGER            BLOCK_CYCLIC_2D, CSRC_, CTXT_, DLEN_, DTYPE_,
  384     $                   LLD_, MB_, M_, NB_, N_, RSRC_
  385      parameter( block_cyclic_2d = 1, dlen_ = 9, dtype_ = 1,
  386     $                     ctxt_ = 2, m_ = 3, n_ = 4, mb_ = 5, nb_ = 6,
  387     $                     rsrc_ = 7, csrc_ = 8, lld_ = 9 )
  388
  389
  390      INTEGER            CSRC, FIRST_PROC, ICTXT, ICTXT_NEW, ICTXT_SAVE,
  391     $                   IDUM1, IDUM2, IDUM3, JA_NEW, LEVEL_DIST, LLDA,
  392     $                   LLDB, MAX_BW, MBW2, MYCOL, MYROW, MY_NUM_COLS,
  393     $                   NB, NP, NPCOL, NPROW, NP_SAVE, ODD_SIZE, OFST,
  394     $                   PART_OFFSET, PART_SIZE, RETURN_CODE, STORE_M_B,
  395     $                   STORE_N_A, WORK_SIZE_MIN, WORK_U
  396
  397
  398      INTEGER            DESCA_1XP( 7 ), DESCB_PX1( 7 ),
  399     $                   PARAM_CHECK( 18, 3 )
  400
  401
  402      EXTERNAL           blacs_get, blacs_gridexit, blacs_gridinfo,
  403     $                   cgemm, cgerv2d, cgesd2d, clamov, 
cmatadd,
 
  406
  407
  408      LOGICAL            LSAME
  409      INTEGER            NUMROC
  411
  412
  413      INTRINSIC          ichar, 
min, mod
 
  414
  415
  416
  417
  418
  419      info = 0
  420
  421
  422
  423
  424      desca_1xp( 1 ) = 501
  425      descb_px1( 1 ) = 502
  426
  428
  429      IF( return_code .NE. 0) THEN
  430         info = -( 9*100 + 2 )
  431      ENDIF
  432
  434
  435      IF( return_code .NE. 0) THEN
  436         info = -( 12*100 + 2 )
  437      ENDIF
  438
  439
  440
  441
  442      IF( desca_1xp( 2 ) .NE. descb_px1( 2 ) ) THEN
  443         info = -( 12*100 + 2 )
  444      ENDIF
  445
  446
  447
  448
  449
  450      IF( desca_1xp( 4 ) .NE. descb_px1( 4 ) ) THEN
  451         info = -( 12*100 + 4 )
  452      ENDIF
  453
  454
  455
  456      IF( desca_1xp( 5 ) .NE. descb_px1( 5 ) ) THEN
  457         info = -( 12*100 + 5 )
  458      ENDIF
  459
  460
  461
  462      ictxt = desca_1xp( 2 )
  463      csrc = desca_1xp( 5 )
  464      nb = desca_1xp( 4 )
  465      llda = desca_1xp( 6 )
  466      store_n_a = desca_1xp( 3 )
  467      lldb = descb_px1( 6 )
  468      store_m_b = descb_px1( 3 )
  469
  470
  471
  472
  473
  474
  475      max_bw = 
max(bwl,bwu)
 
  476      mbw2 = max_bw * max_bw
  477
  478      CALL blacs_gridinfo( ictxt, nprow, npcol, myrow, mycol )
  479      np = nprow * npcol
  480
  481
  482
  483      IF( 
lsame( uplo, 
'U' ) ) 
THEN 
  484         idum1 = ichar( 'U' )
  485      ELSE IF ( 
lsame( uplo, 
'L' ) ) 
THEN 
  486         idum1 = ichar( 'L' )
  487      ELSE
  488         info = -1
  489      END IF
  490
  491      IF( 
lsame( trans, 
'N' ) ) 
THEN 
  492         idum2 = ichar( 'N' )
  493      ELSE IF ( 
lsame( trans, 
'C' ) ) 
THEN 
  494         idum2 = ichar( 'C' )
  495      ELSE
  496         info = -2
  497      END IF
  498
  499      IF( lwork .LT. -1) THEN
  500         info = -16
  501      ELSE IF ( lwork .EQ. -1 ) THEN
  502         idum3 = -1
  503      ELSE
  504         idum3 = 1
  505      ENDIF
  506
  507      IF( n .LT. 0 ) THEN
  508         info = -3
  509      ENDIF
  510
  511      IF( n+ja-1 .GT. store_n_a ) THEN
  512         info = -( 9*100 + 6 )
  513      ENDIF
  514
  515      IF(( bwl .GT. n-1 ) .OR.
  516     $   ( bwl .LT. 0 ) ) THEN
  517         info = -4
  518      ENDIF
  519
  520      IF(( bwu .GT. n-1 ) .OR.
  521     $   ( bwu .LT. 0 ) ) THEN
  522         info = -5
  523      ENDIF
  524
  525      IF( llda .LT. (bwl+bwu+1) ) THEN
  526         info = -( 9*100 + 6 )
  527      ENDIF
  528
  529      IF( nb .LE. 0 ) THEN
  530         info = -( 9*100 + 4 )
  531      ENDIF
  532
  533      IF( n+ib-1 .GT. store_m_b ) THEN
  534         info = -( 12*100 + 3 )
  535      ENDIF
  536
  537      IF( lldb .LT. nb ) THEN
  538         info = -( 12*100 + 6 )
  539      ENDIF
  540
  541      IF( nrhs .LT. 0 ) THEN
  542         info = -6
  543      ENDIF
  544
  545
  546
  547      IF( ja .NE. ib) THEN
  548         info = -8
  549      ENDIF
  550
  551
  552
  553      IF( nprow .NE. 1 ) THEN
  554         info = -( 9*100+2 )
  555      ENDIF
  556
  557      IF( n .GT. np*nb-mod( ja-1, nb )) THEN
  558         info = -( 3 )
  560     $      'PCDBTRSV, D&C alg.: only 1 block per proc',
  561     $      -info )
  562         RETURN
  563      ENDIF
  564
  565      IF((ja+n-1.GT.nb) .AND. ( nb.LT.2*
max(bwl,bwu) )) 
THEN 
  566         info = -( 9*100+4 )
  568     $      'PCDBTRSV, D&C alg.: NB too small',
  569     $      -info )
  570         RETURN
  571      ENDIF
  572
  573
  574      work_size_min =
  576
  577      work( 1 ) = work_size_min
  578
  579      IF( lwork .LT. work_size_min ) THEN
  580         IF( lwork .NE. -1 ) THEN
  581         info = -16
  583     $      'PCDBTRSV: worksize error',
  584     $      -info )
  585         ENDIF
  586         RETURN
  587      ENDIF
  588
  589
  590
  591      param_check( 18, 1 ) = descb(5)
  592      param_check( 17, 1 ) = descb(4)
  593      param_check( 16, 1 ) = descb(3)
  594      param_check( 15, 1 ) = descb(2)
  595      param_check( 14, 1 ) = descb(1)
  596      param_check( 13, 1 ) = ib
  597      param_check( 12, 1 ) = desca(5)
  598      param_check( 11, 1 ) = desca(4)
  599      param_check( 10, 1 ) = desca(3)
  600      param_check(  9, 1 ) = desca(1)
  601      param_check(  8, 1 ) = ja
  602      param_check(  7, 1 ) = nrhs
  603      param_check(  6, 1 ) = bwu
  604      param_check(  5, 1 ) = bwl
  605      param_check(  4, 1 ) = n
  606      param_check(  3, 1 ) = idum3
  607      param_check(  2, 1 ) = idum2
  608      param_check(  1, 1 ) = idum1
  609
  610      param_check( 18, 2 ) = 1205
  611      param_check( 17, 2 ) = 1204
  612      param_check( 16, 2 ) = 1203
  613      param_check( 15, 2 ) = 1202
  614      param_check( 14, 2 ) = 1201
  615      param_check( 13, 2 ) = 11
  616      param_check( 12, 2 ) = 905
  617      param_check( 11, 2 ) = 904
  618      param_check( 10, 2 ) = 903
  619      param_check(  9, 2 ) = 901
  620      param_check(  8, 2 ) = 8
  621      param_check(  7, 2 ) = 6
  622      param_check(  6, 2 ) = 5
  623      param_check(  5, 2 ) = 4
  624      param_check(  4, 2 ) = 3
  625      param_check(  3, 2 ) = 16
  626      param_check(  2, 2 ) = 2
  627      param_check(  1, 2 ) = 1
  628
  629
  630
  631
  632
  633      IF( info.GE.0 ) THEN
  634         info = bignum
  635      ELSE IF( info.LT.-descmult ) THEN
  636         info = -info
  637      ELSE
  638         info = -info * descmult
  639      END IF
  640
  641
  642
  643      CALL globchk( ictxt, 18, param_check, 18,
 
  644     $              param_check( 1, 3 ), info )
  645
  646
  647
  648
  649      IF( info.EQ.bignum ) THEN
  650         info = 0
  651      ELSE IF( mod( info, descmult ) .EQ. 0 ) THEN
  652         info = -info / descmult
  653      ELSE
  654         info = -info
  655      END IF
  656
  657      IF( info.LT.0 ) THEN
  658         CALL pxerbla( ictxt, 
'PCDBTRSV', -info )
 
  659         RETURN
  660      END IF
  661
  662
  663
  664      IF( n.EQ.0 )
  665     $   RETURN
  666
  667      IF( nrhs.EQ.0 )
  668     $   RETURN
  669
  670
  671
  672
  673
  674      part_offset = nb*( (ja-1)/(npcol*nb) )
  675
  676      IF ( (mycol-csrc) .LT. (ja-part_offset-1)/nb ) THEN
  677         part_offset = part_offset + nb
  678      ENDIF
  679
  680      IF ( mycol .LT. csrc ) THEN
  681         part_offset = part_offset - nb
  682      ENDIF
  683
  684
  685
  686
  687
  688
  689
  690      first_proc = mod( ( ja-1 )/nb+csrc, npcol )
  691
  692
  693
  694      ja_new = mod( ja-1, nb ) + 1
  695
  696
  697
  698      np_save = np
  699      np = ( ja_new+n-2 )/nb + 1
  700
  701
  702
  703      CALL reshape( ictxt, int_one, ictxt_new, int_one,
 
  704     $              first_proc, int_one, np )
  705
  706
  707
  708      ictxt_save = ictxt
  709      ictxt = ictxt_new
  710      desca_1xp( 2 ) = ictxt_new
  711      descb_px1( 2 ) = ictxt_new
  712
  713
  714
  715      CALL blacs_gridinfo( ictxt, nprow, npcol, myrow, mycol )
  716
  717
  718
  719      IF( myrow .LT. 0 ) THEN
  720         GOTO 1234
  721      ENDIF
  722
  723
  724
  725
  726
  727
  728      part_size = nb
  729
  730
  731
  732      my_num_cols = 
numroc( n, part_size, mycol, 0, npcol )
 
  733
  734
  735
  736      IF ( mycol .EQ. 0 ) THEN
  737        part_offset = part_offset+mod( ja_new-1, part_size )
  738        my_num_cols = my_num_cols - mod(ja_new-1, part_size )
  739      ENDIF
  740
  741
  742
  743      ofst = part_offset*llda
  744
  745
  746
  747      odd_size = my_num_cols
  748      IF ( mycol .LT. np-1 ) THEN
  749         odd_size = odd_size - max_bw
  750      ENDIF
  751
  752
  753
  754      work_u = bwu*odd_size + 3*mbw2
  755
  756
  757
  758
  759
  760      IF ( 
lsame( uplo, 
'L' ) ) 
THEN 
  761
  762      IF ( 
lsame( trans, 
'N' ) ) 
THEN 
  763
  764
  765
  766
  767
  768
  769
  770
  771
  772
  773        CALL ctbtrs( uplo, 'N', 'U', odd_size,
  774     $                    bwl, nrhs,
  775     $                    a( ofst+1+bwu ), llda,
  776     $                    b( part_offset+1 ), lldb, info )
  777
  778
  779        IF ( mycol .LT. np-1 ) THEN
  780
  781
  782
  783
  784
  785
  786
  787            CALL clamov( 'N', bwl, nrhs,
  788     $                b( part_offset+odd_size-bwl+1), lldb,
  789     $                work( 1 ), max_bw )
  790
  791            CALL ctrmm( 'L', 'U', 'N', 'N', bwl, nrhs, -cone,
  792     $                  a(( ofst+(bwl+bwu+1)+(odd_size-bwl)*llda )),
  793     $                  llda-1, work( 1 ), max_bw )
  794
  795            CALL cmatadd( bwl, nrhs, cone, work( 1 ), max_bw,
 
  796     $                cone, b( part_offset+odd_size+1 ), lldb )
  797
  798        ENDIF
  799
  800
  801
  802        DO 10               idum1=1, work_size_min
  803          work( idum1 )=0.0
  804   10   CONTINUE
  805
  806
  807        IF ( mycol .NE. 0 ) THEN
  808
  809
  810
  811            CALL cgemm( 'C', 'N', bwu, nrhs, odd_size, -cone, af( 1 ),
  812     $                  odd_size, b( part_offset+1 ), lldb, czero,
  813     $                  work( 1+max_bw-bwu ), max_bw )
  814        ENDIF
  815
  816
  817
  818
  819
  820
  821
  822
  823
  824        IF( mycol .GT. 0) THEN
  825
  826          CALL cgesd2d( ictxt, max_bw, nrhs,
  827     $                     work( 1 ), max_bw,
  828     $                     0, mycol - 1 )
  829
  830        ENDIF
  831
  832
  833
  834        IF( mycol .LT. npcol-1) THEN
  835
  836          CALL cgerv2d( ictxt, max_bw, nrhs,
  837     $                     work( 1 ), max_bw,
  838     $                     0, mycol + 1 )
  839
  840
  841
  842          CALL cmatadd( max_bw, nrhs, cone,
 
  843     $                work( 1 ), max_bw, cone,
  844     $                b( part_offset+odd_size + 1 ), lldb )
  845
  846        ENDIF
  847
  848
  849
  850
  851        IF( mycol .EQ. npcol-1 ) THEN
  852          GOTO 14
  853        ENDIF
  854
  855
  856
  857
  858
  859
  860
  861        level_dist = 1
  862
  863
  864
  865   12   CONTINUE
  866        IF( mod( (mycol+1)/level_dist, 2) .NE. 0 ) GOTO 11
  867
  868
  869
  870          IF( mycol-level_dist .GE. 0 ) THEN
  871
  872            CALL cgerv2d( ictxt, max_bw, nrhs,
  873     $                     work( 1 ),
  874     $                     max_bw, 0, mycol-level_dist )
  875
  876            CALL cmatadd( max_bw, nrhs, cone,
 
  877     $                work( 1 ), max_bw, cone,
  878     $                b( part_offset+odd_size + 1 ), lldb )
  879
  880          ENDIF
  881
  882
  883
  884          IF( mycol+level_dist .LT. npcol-1 ) THEN
  885
  886            CALL cgerv2d( ictxt, max_bw, nrhs,
  887     $                     work( 1 ),
  888     $                     max_bw, 0, mycol+level_dist )
  889
  890            CALL cmatadd( max_bw, nrhs, cone,
 
  891     $                work( 1 ), max_bw, cone,
  892     $                b( part_offset+odd_size + 1 ), lldb )
  893
  894          ENDIF
  895
  896          level_dist = level_dist*2
  897
  898        GOTO 12
  899   11   CONTINUE
  900
  901
  902
  903
  904
  905
  906
  907
  908
  909        CALL ctbtrs( 
'L', 
'N', 
'U', max_bw, 
min( bwl, max_bw-1 ), nrhs,
 
  910     $               af( odd_size*bwu+mbw2+1 ), max_bw+1,
  911     $               b( part_offset+odd_size+1 ), lldb, info )
  912
  913        IF( info.NE.0 ) THEN
  914          GO TO 1000
  915        ENDIF
  916
  917
  918
  919
  920        IF( mycol/level_dist .LE. (npcol-1)/level_dist-2 )THEN
  921
  922
  923
  924          CALL cgemm( 'C', 'N', max_bw, nrhs, max_bw, -cone,
  925     $                     af( (odd_size)*bwu+1 ),
  926     $                     max_bw,
  927     $                     b( part_offset+odd_size+1 ),
  928     $                     lldb, czero,
  929     $                     work( 1 ),
  930     $                     max_bw )
  931
  932
  933
  934          CALL cgesd2d( ictxt, max_bw, nrhs,
  935     $                     work( 1 ),
  936     $                     max_bw, 0, mycol+level_dist )
  937
  938        ENDIF
  939
  940
  941
  942        IF( (mycol/level_dist .GT. 0 ).AND.
  943     $      ( mycol/level_dist .LE. (npcol-1)/level_dist-1 ) ) THEN
  944
  945
  946
  947
  948
  949          CALL cgemm( 'N', 'N', max_bw, nrhs, max_bw, -cone,
  950     $                     af( odd_size*bwu+2*mbw2+1 ),
  951     $                     max_bw,
  952     $                     b( part_offset+odd_size+1 ),
  953     $                     lldb, czero,
  954     $                     work( 1 ),
  955     $                     max_bw )
  956
  957
  958
  959          CALL cgesd2d( ictxt, max_bw, nrhs,
  960     $                     work( 1 ),
  961     $                     max_bw, 0, mycol-level_dist )
  962
  963        ENDIF
  964
  965
  966   14  CONTINUE
  967
  968      ELSE
  969
  970
  971
  972
  973
  974
  975
  976
  977
  978
  979
  980        IF( mycol .EQ. npcol-1 ) THEN
  981          GOTO 24
  982        ENDIF
  983
  984
  985
  986        level_dist = 1
  987   27   CONTINUE
  988        IF( mod( (mycol+1)/level_dist, 2) .NE. 0 ) GOTO 26
  989
  990          level_dist = level_dist*2
  991
  992        GOTO 27
  993   26   CONTINUE
  994
  995
  996        IF( (mycol/level_dist .GT. 0 ).AND.
  997     $      ( mycol/level_dist .LE. (npcol-1)/level_dist-1 ) ) THEN
  998
  999
 1000
 1001          CALL cgerv2d( ictxt, max_bw, nrhs,
 1002     $                     work( 1 ),
 1003     $                     max_bw, 0, mycol-level_dist )
 1004
 1005
 1006
 1007
 1008
 1009          CALL cgemm( 'C', 'N', max_bw, nrhs, max_bw, -cone,
 1010     $                     af( odd_size*bwu+2*mbw2+1 ),
 1011     $                     max_bw,
 1012     $                     work( 1 ),
 1013     $                     max_bw, cone,
 1014     $                     b( part_offset+odd_size+1 ),
 1015     $                     lldb )
 1016        ENDIF
 1017
 1018
 1019
 1020        IF( mycol/level_dist .LE. (npcol-1)/level_dist-2 )THEN
 1021
 1022
 1023
 1024          CALL cgerv2d( ictxt, max_bw, nrhs,
 1025     $                     work( 1 ),
 1026     $                     max_bw, 0, mycol+level_dist )
 1027
 1028
 1029
 1030          CALL cgemm( 'N', 'N', max_bw, nrhs, max_bw, -cone,
 1031     $                     af( (odd_size)*bwu+1 ),
 1032     $                     max_bw,
 1033     $                     work( 1 ),
 1034     $                     max_bw, cone,
 1035     $                     b( part_offset+odd_size+1 ),
 1036     $                     lldb )
 1037
 1038        ENDIF
 1039
 1040
 1041
 1042
 1043
 1044        CALL ctbtrs( 
'L', 
'C', 
'U', max_bw, 
min( bwl, max_bw-1 ), nrhs,
 
 1045     $               af( odd_size*bwu+mbw2+1 ), max_bw+1,
 1046     $               b( part_offset+odd_size+1 ), lldb, info )
 1047
 1048        IF( info.NE.0 ) THEN
 1049          GO TO 1000
 1050        ENDIF
 1051
 1052
 1053
 1054
 1055
 1056   22   CONTINUE
 1057        IF( level_dist .EQ. 1 ) GOTO 21
 1058
 1059          level_dist = level_dist/2
 1060
 1061
 1062
 1063          IF( mycol+level_dist .LT. npcol-1 ) THEN
 1064
 1065          CALL cgesd2d( ictxt, max_bw, nrhs,
 1066     $                     b( part_offset+odd_size+1 ),
 1067     $                     lldb, 0, mycol+level_dist )
 1068
 1069          ENDIF
 1070
 1071
 1072
 1073          IF( mycol-level_dist .GE. 0 ) THEN
 1074
 1075          CALL cgesd2d( ictxt, max_bw, nrhs,
 1076     $                     b( part_offset+odd_size+1 ),
 1077     $                     lldb, 0, mycol-level_dist )
 1078
 1079          ENDIF
 1080
 1081        GOTO 22
 1082   21   CONTINUE
 1083
 1084
 1085   24   CONTINUE
 1086
 1087
 1088
 1089
 1090
 1091
 1092
 1093
 1094
 1095        IF( mycol .LT. npcol-1) THEN
 1096
 1097          CALL cgesd2d( ictxt, max_bw, nrhs,
 1098     $                     b( part_offset+odd_size+1 ), lldb,
 1099     $                     0, mycol +1 )
 1100
 1101        ENDIF
 1102
 1103
 1104
 1105        IF( mycol .GT. 0) THEN
 1106
 1107          CALL cgerv2d( ictxt, max_bw, nrhs,
 1108     $                     work( 1 ), max_bw,
 1109     $                     0, mycol - 1 )
 1110
 1111        ENDIF
 1112
 1113
 1114
 1115
 1116
 1117
 1118
 1119        IF ( mycol .NE. 0 ) THEN
 1120
 1121
 1122
 1123          CALL cgemm( 'N', 'N', odd_size, nrhs, bwu, -cone, af( 1 ),
 1124     $                odd_size, work( 1+max_bw-bwu ), max_bw, cone,
 1125     $                b( part_offset+1 ), lldb )
 1126
 1127        ENDIF
 1128
 1129
 1130        IF ( mycol .LT. np-1 ) THEN
 1131
 1132
 1133
 1134
 1135
 1136
 1137
 1138          CALL clamov( 'N', bwl, nrhs, b( part_offset+odd_size+1), lldb,
 1139     $                 work( 1+max_bw-bwl ), max_bw )
 1140
 1141          CALL ctrmm( 'L', 'U', 'C', 'N', bwl, nrhs, -cone,
 1142     $                a(( ofst+(bwl+bwu+1)+(odd_size-bwl)*llda )),
 1143     $                llda-1, work( 1+max_bw-bwl ), max_bw )
 1144
 1145          CALL cmatadd( bwl, nrhs, cone, work( 1+max_bw-bwl ), max_bw,
 
 1146     $                  cone, b( part_offset+odd_size-bwl+1 ), lldb )
 1147
 1148        ENDIF
 1149
 1150
 1151
 1152        CALL ctbtrs( uplo, 'C', 'U', odd_size,
 1153     $                    bwl, nrhs,
 1154     $                    a( ofst+1+bwu ),
 1155     $                    llda,  b( part_offset+1 ),
 1156     $                    lldb, info )
 1157
 1158      ENDIF
 1159
 1160
 1161
 1162      ELSE
 1163
 1164
 1165
 1166      IF ( 
lsame( trans, 
'C' ) ) 
THEN 
 1167
 1168
 1169
 1170
 1171
 1172
 1173
 1174
 1175
 1176
 1177        CALL ctbtrs( uplo, 'C', 'N', odd_size,
 1178     $                    bwu, nrhs,
 1179     $                    a( ofst+1 ), llda,
 1180     $                    b( part_offset+1 ), lldb, info )
 1181
 1182
 1183        IF ( mycol .LT. np-1 ) THEN
 1184
 1185
 1186
 1187
 1188
 1189
 1190
 1191            CALL clamov( 'N', bwu, nrhs,
 1192     $                b( part_offset+odd_size-bwu+1), lldb,
 1193     $                work( 1 ), max_bw )
 1194
 1195            CALL ctrmm( 'L', 'L', 'C', 'N', bwu, nrhs, -cone,
 1196     $                  a(( ofst+1+odd_size*llda )), llda-1, work( 1 ),
 1197     $                  max_bw )
 1198
 1199            CALL cmatadd( bwu, nrhs, cone, work( 1 ), max_bw,
 
 1200     $                cone, b( part_offset+odd_size+1 ), lldb )
 1201
 1202        ENDIF
 1203
 1204
 1205
 1206        DO 20               idum1=1, work_size_min
 1207          work( idum1 )=0.0
 1208   20   CONTINUE
 1209
 1210
 1211        IF ( mycol .NE. 0 ) THEN
 1212
 1213
 1214
 1215            CALL cgemm( 'C', 'N', bwl, nrhs, odd_size, -cone,
 1216     $                  af( work_u+1 ), odd_size, b( part_offset+1 ),
 1217     $                  lldb, czero, work( 1+max_bw-bwl ), max_bw )
 1218        ENDIF
 1219
 1220
 1221
 1222
 1223
 1224
 1225
 1226
 1227
 1228        IF( mycol .GT. 0) THEN
 1229
 1230          CALL cgesd2d( ictxt, max_bw, nrhs,
 1231     $                     work( 1 ), max_bw,
 1232     $                     0, mycol - 1 )
 1233
 1234        ENDIF
 1235
 1236
 1237
 1238        IF( mycol .LT. npcol-1) THEN
 1239
 1240          CALL cgerv2d( ictxt, max_bw, nrhs,
 1241     $                     work( 1 ), max_bw,
 1242     $                     0, mycol + 1 )
 1243
 1244
 1245
 1246          CALL cmatadd( max_bw, nrhs, cone,
 
 1247     $                work( 1 ), max_bw, cone,
 1248     $                b( part_offset+odd_size + 1 ), lldb )
 1249
 1250        ENDIF
 1251
 1252
 1253
 1254
 1255        IF( mycol .EQ. npcol-1 ) THEN
 1256          GOTO 44
 1257        ENDIF
 1258
 1259
 1260
 1261
 1262
 1263
 1264
 1265        level_dist = 1
 1266
 1267
 1268
 1269   42   CONTINUE
 1270        IF( mod( (mycol+1)/level_dist, 2) .NE. 0 ) GOTO 41
 1271
 1272
 1273
 1274          IF( mycol-level_dist .GE. 0 ) THEN
 1275
 1276            CALL cgerv2d( ictxt, max_bw, nrhs,
 1277     $                     work( 1 ),
 1278     $                     max_bw, 0, mycol-level_dist )
 1279
 1280            CALL cmatadd( max_bw, nrhs, cone,
 
 1281     $                work( 1 ), max_bw, cone,
 1282     $                b( part_offset+odd_size + 1 ), lldb )
 1283
 1284          ENDIF
 1285
 1286
 1287
 1288          IF( mycol+level_dist .LT. npcol-1 ) THEN
 1289
 1290            CALL cgerv2d( ictxt, max_bw, nrhs,
 1291     $                     work( 1 ),
 1292     $                     max_bw, 0, mycol+level_dist )
 1293
 1294            CALL cmatadd( max_bw, nrhs, cone,
 
 1295     $                work( 1 ), max_bw, cone,
 1296     $                b( part_offset+odd_size + 1 ), lldb )
 1297
 1298          ENDIF
 1299
 1300          level_dist = level_dist*2
 1301
 1302        GOTO 42
 1303   41   CONTINUE
 1304
 1305
 1306
 1307
 1308
 1309
 1310
 1311
 1312
 1313        CALL ctbtrs( 
'U', 
'C', 
'N', max_bw, 
min( bwu, max_bw-1 ), nrhs,
 
 1314     $               af( odd_size*bwu+mbw2+1-
min( bwu, max_bw-1 ) ),
 
 1315     $               max_bw+1, b( part_offset+odd_size+1 ), lldb,
 1316     $               info )
 1317
 1318        IF( info.NE.0 ) THEN
 1319          GO TO 1000
 1320        ENDIF
 1321
 1322
 1323
 1324
 1325        IF( mycol/level_dist .LE. (npcol-1)/level_dist-2 )THEN
 1326
 1327
 1328
 1329          CALL cgemm( 'C', 'N', max_bw, nrhs, max_bw, -cone,
 1330     $                     af( work_u+(odd_size)*bwl+1 ),
 1331     $                     max_bw,
 1332     $                     b( part_offset+odd_size+1 ),
 1333     $                     lldb, czero,
 1334     $                     work( 1 ),
 1335     $                     max_bw )
 1336
 1337
 1338
 1339          CALL cgesd2d( ictxt, max_bw, nrhs,
 1340     $                     work( 1 ),
 1341     $                     max_bw, 0, mycol+level_dist )
 1342
 1343        ENDIF
 1344
 1345
 1346
 1347        IF( (mycol/level_dist .GT. 0 ).AND.
 1348     $      ( mycol/level_dist .LE. (npcol-1)/level_dist-1 ) ) THEN
 1349
 1350
 1351
 1352
 1353
 1354          CALL cgemm( 'N', 'N', max_bw, nrhs, max_bw, -cone,
 1355     $                     af( work_u+odd_size*bwl+2*mbw2+1 ),
 1356     $                     max_bw,
 1357     $                     b( part_offset+odd_size+1 ),
 1358     $                     lldb, czero,
 1359     $                     work( 1 ),
 1360     $                     max_bw )
 1361
 1362
 1363
 1364          CALL cgesd2d( ictxt, max_bw, nrhs,
 1365     $                     work( 1 ),
 1366     $                     max_bw, 0, mycol-level_dist )
 1367
 1368        ENDIF
 1369
 1370
 1371   44  CONTINUE
 1372
 1373      ELSE
 1374
 1375
 1376
 1377
 1378
 1379
 1380
 1381
 1382
 1383
 1384
 1385        IF( mycol .EQ. npcol-1 ) THEN
 1386          GOTO 54
 1387        ENDIF
 1388
 1389
 1390
 1391        level_dist = 1
 1392   57   CONTINUE
 1393        IF( mod( (mycol+1)/level_dist, 2) .NE. 0 ) GOTO 56
 1394
 1395          level_dist = level_dist*2
 1396
 1397        GOTO 57
 1398   56   CONTINUE
 1399
 1400
 1401        IF( (mycol/level_dist .GT. 0 ).AND.
 1402     $      ( mycol/level_dist .LE. (npcol-1)/level_dist-1 ) ) THEN
 1403
 1404
 1405
 1406          CALL cgerv2d( ictxt, max_bw, nrhs,
 1407     $                     work( 1 ),
 1408     $                     max_bw, 0, mycol-level_dist )
 1409
 1410
 1411
 1412
 1413
 1414          CALL cgemm( 'C', 'N', max_bw, nrhs, max_bw, -cone,
 1415     $                     af( work_u+odd_size*bwl+2*mbw2+1 ),
 1416     $                     max_bw,
 1417     $                     work( 1 ),
 1418     $                     max_bw, cone,
 1419     $                     b( part_offset+odd_size+1 ),
 1420     $                     lldb )
 1421        ENDIF
 1422
 1423
 1424
 1425        IF( mycol/level_dist .LE. (npcol-1)/level_dist-2 )THEN
 1426
 1427
 1428
 1429          CALL cgerv2d( ictxt, max_bw, nrhs,
 1430     $                     work( 1 ),
 1431     $                     max_bw, 0, mycol+level_dist )
 1432
 1433
 1434
 1435          CALL cgemm( 'N', 'N', max_bw, nrhs, max_bw, -cone,
 1436     $                     af( work_u+(odd_size)*bwl+1 ),
 1437     $                     max_bw,
 1438     $                     work( 1 ),
 1439     $                     max_bw, cone,
 1440     $                     b( part_offset+odd_size+1 ),
 1441     $                     lldb )
 1442
 1443        ENDIF
 1444
 1445
 1446
 1447
 1448
 1449        CALL ctbtrs( 
'U', 
'N', 
'N', max_bw, 
min( bwu, max_bw-1 ), nrhs,
 
 1450     $               af( odd_size*bwu+mbw2+1-
min( bwu, max_bw-1 ) ),
 
 1451     $               max_bw+1, b( part_offset+odd_size+1 ), lldb,
 1452     $               info )
 1453
 1454        IF( info.NE.0 ) THEN
 1455          GO TO 1000
 1456        ENDIF
 1457
 1458
 1459
 1460
 1461
 1462   52   CONTINUE
 1463        IF( level_dist .EQ. 1 ) GOTO 51
 1464
 1465          level_dist = level_dist/2
 1466
 1467
 1468
 1469          IF( mycol+level_dist .LT. npcol-1 ) THEN
 1470
 1471          CALL cgesd2d( ictxt, max_bw, nrhs,
 1472     $                     b( part_offset+odd_size+1 ),
 1473     $                     lldb, 0, mycol+level_dist )
 1474
 1475          ENDIF
 1476
 1477
 1478
 1479          IF( mycol-level_dist .GE. 0 ) THEN
 1480
 1481          CALL cgesd2d( ictxt, max_bw, nrhs,
 1482     $                     b( part_offset+odd_size+1 ),
 1483     $                     lldb, 0, mycol-level_dist )
 1484
 1485          ENDIF
 1486
 1487        GOTO 52
 1488   51   CONTINUE
 1489
 1490
 1491   54   CONTINUE
 1492
 1493
 1494
 1495
 1496
 1497
 1498
 1499
 1500
 1501        IF( mycol .LT. npcol-1) THEN
 1502
 1503          CALL cgesd2d( ictxt, max_bw, nrhs,
 1504     $                     b( part_offset+odd_size+1 ), lldb,
 1505     $                     0, mycol +1 )
 1506
 1507        ENDIF
 1508
 1509
 1510
 1511        IF( mycol .GT. 0) THEN
 1512
 1513          CALL cgerv2d( ictxt, max_bw, nrhs,
 1514     $                     work( 1 ), max_bw,
 1515     $                     0, mycol - 1 )
 1516
 1517        ENDIF
 1518
 1519
 1520
 1521
 1522
 1523
 1524
 1525        IF ( mycol .NE. 0 ) THEN
 1526
 1527
 1528
 1529          CALL cgemm( 'N', 'N', odd_size, nrhs, bwl, -cone,
 1530     $                af( work_u+1 ), odd_size, work( 1+max_bw-bwl ),
 1531     $                max_bw, cone, b( part_offset+1 ), lldb )
 1532
 1533        ENDIF
 1534
 1535
 1536        IF ( mycol .LT. np-1 ) THEN
 1537
 1538
 1539
 1540
 1541
 1542
 1543
 1544          CALL clamov( 'N', bwu, nrhs, b( part_offset+odd_size+1), lldb,
 1545     $                 work( 1+max_bw-bwu ), max_bw+bwl )
 1546
 1547          CALL ctrmm( 'L', 'L', 'N', 'N', bwu, nrhs, -cone,
 1548     $                a(( ofst+1+odd_size*llda )), llda-1,
 1549     $                work( 1+max_bw-bwu ), max_bw+bwl )
 1550
 1551          CALL cmatadd( bwu, nrhs, cone, work( 1+max_bw-bwu ),
 
 1552     $                  max_bw+bwl, cone,
 1553     $                  b( part_offset+odd_size-bwu+1 ), lldb )
 1554
 1555        ENDIF
 1556
 1557
 1558
 1559        CALL ctbtrs( uplo, 'N', 'N', odd_size,
 1560     $                    bwu, nrhs,
 1561     $                    a( ofst+1 ),
 1562     $                    llda,  b( part_offset+1 ),
 1563     $                    lldb, info )
 1564
 1565      ENDIF
 1566
 1567
 1568
 1569      ENDIF
 1570
 1571 1000 CONTINUE
 1572
 1573
 1574
 1575
 1576      IF( ictxt_save .NE. ictxt_new ) THEN
 1577         CALL blacs_gridexit( ictxt_new )
 1578      ENDIF
 1579
 1580 1234 CONTINUE
 1581
 1582
 1583
 1584      ictxt = ictxt_save
 1585      np = np_save
 1586
 1587
 1588
 1589      work( 1 ) = work_size_min
 1590
 1591
 1592      RETURN
 1593
 1594
 1595
subroutine cmatadd(m, n, alpha, a, lda, beta, c, ldc)
 
subroutine desc_convert(desc_in, desc_out, info)
 
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)