3
    4
    5
    6
    7
    8
    9
   10      CHARACTER          UPLO
   11      INTEGER            IB, INFO, JA, LAF, LWORK, N, NRHS
   12
   13
   14      INTEGER            DESCA( * ), DESCB( * )
   15      DOUBLE PRECISION   AF( * ), B( * ), D( * ), E( * ), WORK( * )
   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      DOUBLE PRECISION   ONE
  374      parameter( one = 1.0d+0 )
  375      DOUBLE PRECISION   ZERO
  376      parameter( zero = 0.0d+0 )
  377      INTEGER            INT_ONE
  378      parameter( int_one = 1 )
  379      INTEGER            DESCMULT, BIGNUM
  380      parameter( descmult = 100, bignum = descmult*descmult )
  381      INTEGER            BLOCK_CYCLIC_2D, CSRC_, CTXT_, DLEN_, DTYPE_,
  382     $                   LLD_, MB_, M_, NB_, N_, RSRC_
  383      parameter( block_cyclic_2d = 1, dlen_ = 9, dtype_ = 1,
  384     $                     ctxt_ = 2, m_ = 3, n_ = 4, mb_ = 5, nb_ = 6,
  385     $                     rsrc_ = 7, csrc_ = 8, lld_ = 9 )
  386
  387
  388      INTEGER            CSRC, FIRST_PROC, ICTXT, ICTXT_NEW, ICTXT_SAVE,
  389     $                   IDUM1, IDUM3, JA_NEW, LEVEL_DIST, LLDA, LLDB,
  390     $                   MYCOL, MYROW, MY_NUM_COLS, NB, NP, NPCOL,
  391     $                   NPROW, NP_SAVE, ODD_SIZE, PART_OFFSET,
  392     $                   PART_SIZE, RETURN_CODE, STORE_M_B, STORE_N_A,
  393     $                   TEMP, WORK_SIZE_MIN
  394
  395
  396      INTEGER            DESCA_1XP( 7 ), DESCB_PX1( 7 ),
  397     $                   PARAM_CHECK( 15, 3 )
  398
  399
  400      EXTERNAL           blacs_gridexit, blacs_gridinfo, daxpy,
  403
  404
  405      LOGICAL            LSAME
  406      INTEGER            NUMROC
  408
  409
  410      INTRINSIC          ichar, mod
  411
  412
  413
  414
  415
  416      info = 0
  417
  418
  419
  420
  421      desca_1xp( 1 ) = 501
  422      descb_px1( 1 ) = 502
  423
  424      temp = desca( dtype_ )
  425      IF( temp.EQ.502 ) THEN
  426
  427         desca( dtype_ ) = 501
  428      END IF
  429
  431
  432      desca( dtype_ ) = temp
  433
  434      IF( return_code.NE.0 ) THEN
  435         info = -( 7*100+2 )
  436      END IF
  437
  439
  440      IF( return_code.NE.0 ) THEN
  441         info = -( 10*100+2 )
  442      END IF
  443
  444
  445
  446
  447      IF( desca_1xp( 2 ).NE.descb_px1( 2 ) ) THEN
  448         info = -( 10*100+2 )
  449      END IF
  450
  451
  452
  453
  454
  455      IF( desca_1xp( 4 ).NE.descb_px1( 4 ) ) THEN
  456         info = -( 10*100+4 )
  457      END IF
  458
  459
  460
  461      IF( desca_1xp( 5 ).NE.descb_px1( 5 ) ) THEN
  462         info = -( 10*100+5 )
  463      END IF
  464
  465
  466
  467      ictxt = desca_1xp( 2 )
  468      csrc = desca_1xp( 5 )
  469      nb = desca_1xp( 4 )
  470      llda = desca_1xp( 6 )
  471      store_n_a = desca_1xp( 3 )
  472      lldb = descb_px1( 6 )
  473      store_m_b = descb_px1( 3 )
  474
  475
  476
  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( lwork.LT.-1 ) THEN
  492         info = -14
  493      ELSE IF( lwork.EQ.-1 ) THEN
  494         idum3 = -1
  495      ELSE
  496         idum3 = 1
  497      END IF
  498
  499      IF( n.LT.0 ) THEN
  500         info = -2
  501      END IF
  502
  503      IF( n+ja-1.GT.store_n_a ) THEN
  504         info = -( 7*100+6 )
  505      END IF
  506
  507      IF( n+ib-1.GT.store_m_b ) THEN
  508         info = -( 10*100+3 )
  509      END IF
  510
  511      IF( lldb.LT.nb ) THEN
  512         info = -( 10*100+6 )
  513      END IF
  514
  515      IF( nrhs.LT.0 ) THEN
  516         info = -3
  517      END IF
  518
  519
  520
  521      IF( ja.NE.ib ) THEN
  522         info = -6
  523      END IF
  524
  525
  526
  527      IF( nprow.NE.1 ) THEN
  528         info = -( 7*100+2 )
  529      END IF
  530
  531      IF( n.GT.np*nb-mod( ja-1, nb ) ) THEN
  532         info = -( 2 )
  534     $                 'PDPTTRSV, D&C alg.: only 1 block per proc',
  535     $                 -info )
  536         RETURN
  537      END IF
  538
  539      IF( ( ja+n-1.GT.nb ) .AND. ( nb.LT.2*int_one ) ) THEN
  540         info = -( 7*100+4 )
  541         CALL pxerbla( ictxt, 
'PDPTTRSV, D&C alg.: NB too small',
 
  542     $                 -info )
  543         RETURN
  544      END IF
  545
  546
  547      work_size_min = int_one*nrhs
  548
  549      work( 1 ) = work_size_min
  550
  551      IF( lwork.LT.work_size_min ) THEN
  552         IF( lwork.NE.-1 ) THEN
  553            info = -14
  554            CALL pxerbla( ictxt, 
'PDPTTRSV: worksize error', -info )
 
  555         END IF
  556         RETURN
  557      END IF
  558
  559
  560
  561      param_check( 15, 1 ) = descb( 5 )
  562      param_check( 14, 1 ) = descb( 4 )
  563      param_check( 13, 1 ) = descb( 3 )
  564      param_check( 12, 1 ) = descb( 2 )
  565      param_check( 11, 1 ) = descb( 1 )
  566      param_check( 10, 1 ) = ib
  567      param_check( 9, 1 ) = desca( 5 )
  568      param_check( 8, 1 ) = desca( 4 )
  569      param_check( 7, 1 ) = desca( 3 )
  570      param_check( 6, 1 ) = desca( 1 )
  571      param_check( 5, 1 ) = ja
  572      param_check( 4, 1 ) = nrhs
  573      param_check( 3, 1 ) = n
  574      param_check( 2, 1 ) = idum3
  575      param_check( 1, 1 ) = idum1
  576
  577      param_check( 15, 2 ) = 1005
  578      param_check( 14, 2 ) = 1004
  579      param_check( 13, 2 ) = 1003
  580      param_check( 12, 2 ) = 1002
  581      param_check( 11, 2 ) = 1001
  582      param_check( 10, 2 ) = 9
  583      param_check( 9, 2 ) = 705
  584      param_check( 8, 2 ) = 704
  585      param_check( 7, 2 ) = 703
  586      param_check( 6, 2 ) = 701
  587      param_check( 5, 2 ) = 6
  588      param_check( 4, 2 ) = 3
  589      param_check( 3, 2 ) = 2
  590      param_check( 2, 2 ) = 14
  591      param_check( 1, 2 ) = 1
  592
  593
  594
  595
  596
  597      IF( info.GE.0 ) THEN
  598         info = bignum
  599      ELSE IF( info.LT.-descmult ) THEN
  600         info = -info
  601      ELSE
  602         info = -info*descmult
  603      END IF
  604
  605
  606
  607      CALL globchk( ictxt, 15, param_check, 15, param_check( 1, 3 ),
 
  608     $              info )
  609
  610
  611
  612
  613      IF( info.EQ.bignum ) THEN
  614         info = 0
  615      ELSE IF( mod( info, descmult ).EQ.0 ) THEN
  616         info = -info / descmult
  617      ELSE
  618         info = -info
  619      END IF
  620
  621      IF( info.LT.0 ) THEN
  622         CALL pxerbla( ictxt, 
'PDPTTRSV', -info )
 
  623         RETURN
  624      END IF
  625
  626
  627
  628      IF( n.EQ.0 )
  629     $   RETURN
  630
  631      IF( nrhs.EQ.0 )
  632     $   RETURN
  633
  634
  635
  636
  637
  638      part_offset = nb*( ( ja-1 ) / ( npcol*nb ) )
  639
  640      IF( ( mycol-csrc ).LT.( ja-part_offset-1 ) / nb ) THEN
  641         part_offset = part_offset + nb
  642      END IF
  643
  644      IF( mycol.LT.csrc ) THEN
  645         part_offset = part_offset - nb
  646      END IF
  647
  648
  649
  650
  651
  652
  653
  654      first_proc = mod( ( ja-1 ) / nb+csrc, npcol )
  655
  656
  657
  658      ja_new = mod( ja-1, nb ) + 1
  659
  660
  661
  662      np_save = np
  663      np = ( ja_new+n-2 ) / nb + 1
  664
  665
  666
  667      CALL reshape( ictxt, int_one, ictxt_new, int_one, first_proc,
 
  668     $              int_one, np )
  669
  670
  671
  672      ictxt_save = ictxt
  673      ictxt = ictxt_new
  674      desca_1xp( 2 ) = ictxt_new
  675      descb_px1( 2 ) = ictxt_new
  676
  677
  678
  679      CALL blacs_gridinfo( ictxt, nprow, npcol, myrow, mycol )
  680
  681
  682
  683      IF( myrow.LT.0 ) THEN
  684         GO TO 100
  685      END IF
  686
  687
  688
  689
  690
  691
  692      part_size = nb
  693
  694
  695
  696      my_num_cols = 
numroc( n, part_size, mycol, 0, npcol )
 
  697
  698
  699
  700      IF( mycol.EQ.0 ) THEN
  701         part_offset = part_offset + mod( ja_new-1, part_size )
  702         my_num_cols = my_num_cols - mod( ja_new-1, part_size )
  703      END IF
  704
  705
  706
  707      odd_size = my_num_cols
  708      IF( mycol.LT.np-1 ) THEN
  709         odd_size = odd_size - int_one
  710      END IF
  711
  712
  713
  714
  715
  716      IF( 
lsame( uplo, 
'L' ) ) 
THEN 
  717
  718
  719
  720
  721
  722
  723
  724
  725
  726
  727
  728         CALL dpttrsv( 
'N', odd_size, nrhs, d( part_offset+1 ),
 
  729     $                 e( part_offset+1 ), b( part_offset+1 ), lldb,
  730     $                 info )
  731
  732
  733         IF( mycol.LT.np-1 ) THEN
  734
  735
  736
  737            CALL daxpy( nrhs, -e( part_offset+odd_size ),
  738     $                  b( part_offset+odd_size ), lldb,
  739     $                  b( part_offset+odd_size+1 ), lldb )
  740
  741         END IF
  742
  743
  744         IF( mycol.NE.0 ) THEN
  745
  746
  747
  748            CALL dgemm( 'T', 'N', 1, nrhs, odd_size, -one, af( 1 ),
  749     $                  odd_size, b( part_offset+1 ), lldb, zero,
  750     $                  work( 1+int_one-1 ), int_one )
  751         END IF
  752
  753
  754
  755
  756
  757
  758
  759
  760
  761         IF( mycol.GT.0 ) THEN
  762
  763            CALL dgesd2d( ictxt, int_one, nrhs, work( 1 ), int_one, 0,
  764     $                    mycol-1 )
  765
  766         END IF
  767
  768
  769
  770         IF( mycol.LT.npcol-1 ) THEN
  771
  772            CALL dgerv2d( ictxt, int_one, nrhs, work( 1 ), int_one, 0,
  773     $                    mycol+1 )
  774
  775
  776
  777            CALL dmatadd( int_one, nrhs, one, work( 1 ), int_one, one,
 
  778     $                    b( part_offset+odd_size+1 ), lldb )
  779
  780         END IF
  781
  782
  783
  784
  785         IF( mycol.EQ.npcol-1 ) THEN
  786            GO TO 30
  787         END IF
  788
  789
  790
  791
  792
  793
  794
  795         level_dist = 1
  796
  797
  798
  799   10    CONTINUE
  800         IF( mod( ( mycol+1 ) / level_dist, 2 ).NE.0 )
  801     $      GO TO 20
  802
  803
  804
  805         IF( mycol-level_dist.GE.0 ) THEN
  806
  807            CALL dgerv2d( ictxt, int_one, nrhs, work( 1 ), int_one, 0,
  808     $                    mycol-level_dist )
  809
  810            CALL dmatadd( int_one, nrhs, one, work( 1 ), int_one, one,
 
  811     $                    b( part_offset+odd_size+1 ), lldb )
  812
  813         END IF
  814
  815
  816
  817         IF( mycol+level_dist.LT.npcol-1 ) THEN
  818
  819            CALL dgerv2d( ictxt, int_one, nrhs, work( 1 ), int_one, 0,
  820     $                    mycol+level_dist )
  821
  822            CALL dmatadd( int_one, nrhs, one, work( 1 ), int_one, one,
 
  823     $                    b( part_offset+odd_size+1 ), lldb )
  824
  825         END IF
  826
  827         level_dist = level_dist*2
  828
  829         GO TO 10
  830   20    CONTINUE
  831
  832
  833
  834
  835
  836
  837
  838
  839
  840         CALL dtrtrs( 'L', 'N', 'U', int_one, nrhs, af( odd_size+2 ),
  841     $                int_one, b( part_offset+odd_size+1 ), lldb, info )
  842
  843         IF( info.NE.0 ) THEN
  844            GO TO 90
  845         END IF
  846
  847
  848
  849
  850         IF( mycol / level_dist.LE.( npcol-1 ) / level_dist-2 ) THEN
  851
  852
  853
  854            CALL dgemm( 'T', 'N', int_one, nrhs, int_one, -one,
  855     $                  af( ( odd_size )*1+1 ), int_one,
  856     $                  b( part_offset+odd_size+1 ), lldb, zero,
  857     $                  work( 1 ), int_one )
  858
  859
  860
  861            CALL dgesd2d( ictxt, int_one, nrhs, work( 1 ), int_one, 0,
  862     $                    mycol+level_dist )
  863
  864         END IF
  865
  866
  867
  868         IF( ( mycol / level_dist.GT.0 ) .AND.
  869     $       ( mycol / level_dist.LE.( npcol-1 ) / level_dist-1 ) ) THEN
  870
  871
  872
  873
  874
  875            CALL dgemm( 'N', 'N', int_one, nrhs, int_one, -one,
  876     $                  af( odd_size*1+2+1 ), int_one,
  877     $                  b( part_offset+odd_size+1 ), lldb, zero,
  878     $                  work( 1 ), int_one )
  879
  880
  881
  882            CALL dgesd2d( ictxt, int_one, nrhs, work( 1 ), int_one, 0,
  883     $                    mycol-level_dist )
  884
  885         END IF
  886
  887
  888   30    CONTINUE
  889
  890      ELSE
  891
  892
  893
  894
  895
  896
  897
  898
  899
  900
  901
  902         IF( mycol.EQ.npcol-1 ) THEN
  903            GO TO 80
  904         END IF
  905
  906
  907
  908         level_dist = 1
  909   40    CONTINUE
  910         IF( mod( ( mycol+1 ) / level_dist, 2 ).NE.0 )
  911     $      GO TO 50
  912
  913         level_dist = level_dist*2
  914
  915         GO TO 40
  916   50    CONTINUE
  917
  918
  919         IF( ( mycol / level_dist.GT.0 ) .AND.
  920     $       ( mycol / level_dist.LE.( npcol-1 ) / level_dist-1 ) ) THEN
  921
  922
  923
  924            CALL dgerv2d( ictxt, int_one, nrhs, work( 1 ), int_one, 0,
  925     $                    mycol-level_dist )
  926
  927
  928
  929
  930
  931            CALL dgemm( 'T', 'N', int_one, nrhs, int_one, -one,
  932     $                  af( odd_size*1+2+1 ), int_one, work( 1 ),
  933     $                  int_one, one, b( part_offset+odd_size+1 ),
  934     $                  lldb )
  935         END IF
  936
  937
  938
  939         IF( mycol / level_dist.LE.( npcol-1 ) / level_dist-2 ) THEN
  940
  941
  942
  943            CALL dgerv2d( ictxt, int_one, nrhs, work( 1 ), int_one, 0,
  944     $                    mycol+level_dist )
  945
  946
  947
  948            CALL dgemm( 'N', 'N', int_one, nrhs, int_one, -one,
  949     $                  af( ( odd_size )*1+1 ), int_one, work( 1 ),
  950     $                  int_one, one, b( part_offset+odd_size+1 ),
  951     $                  lldb )
  952
  953         END IF
  954
  955
  956
  957
  958
  959         CALL dtrtrs( 'L', 'T', 'U', int_one, nrhs, af( odd_size+2 ),
  960     $                int_one, b( part_offset+odd_size+1 ), lldb, info )
  961
  962         IF( info.NE.0 ) THEN
  963            GO TO 90
  964         END IF
  965
  966
  967
  968
  969
  970   60    CONTINUE
  971         IF( level_dist.EQ.1 )
  972     $      GO TO 70
  973
  974         level_dist = level_dist / 2
  975
  976
  977
  978         IF( mycol+level_dist.LT.npcol-1 ) THEN
  979
  980            CALL dgesd2d( ictxt, int_one, nrhs,
  981     $                    b( part_offset+odd_size+1 ), lldb, 0,
  982     $                    mycol+level_dist )
  983
  984         END IF
  985
  986
  987
  988         IF( mycol-level_dist.GE.0 ) THEN
  989
  990            CALL dgesd2d( ictxt, int_one, nrhs,
  991     $                    b( part_offset+odd_size+1 ), lldb, 0,
  992     $                    mycol-level_dist )
  993
  994         END IF
  995
  996         GO TO 60
  997   70    CONTINUE
  998
  999
 1000   80    CONTINUE
 1001
 1002
 1003
 1004
 1005
 1006
 1007
 1008
 1009
 1010         IF( mycol.LT.npcol-1 ) THEN
 1011
 1012            CALL dgesd2d( ictxt, int_one, nrhs,
 1013     $                    b( part_offset+odd_size+1 ), lldb, 0,
 1014     $                    mycol+1 )
 1015
 1016         END IF
 1017
 1018
 1019
 1020         IF( mycol.GT.0 ) THEN
 1021
 1022            CALL dgerv2d( ictxt, int_one, nrhs, work( 1 ), int_one, 0,
 1023     $                    mycol-1 )
 1024
 1025         END IF
 1026
 1027
 1028
 1029
 1030
 1031
 1032
 1033         IF( mycol.NE.0 ) THEN
 1034
 1035
 1036
 1037            CALL dgemm( 'N', 'N', odd_size, nrhs, 1, -one, af( 1 ),
 1038     $                  odd_size, work( 1+int_one-1 ), int_one, one,
 1039     $                  b( part_offset+1 ), lldb )
 1040
 1041         END IF
 1042
 1043
 1044         IF( mycol.LT.np-1 ) THEN
 1045
 1046
 1047
 1048            CALL daxpy( nrhs, -( e( part_offset+odd_size ) ),
 1049     $                  b( part_offset+odd_size+1 ), lldb,
 1050     $                  b( part_offset+odd_size ), lldb )
 1051
 1052         END IF
 1053
 1054
 1055
 1056         CALL dpttrsv( 
'T', odd_size, nrhs, d( part_offset+1 ),
 
 1057     $                 e( part_offset+1 ), b( part_offset+1 ), lldb,
 1058     $                 info )
 1059
 1060
 1061      END IF
 1062
 1063   90 CONTINUE
 1064
 1065
 1066
 1067
 1068      IF( ictxt_save.NE.ictxt_new ) THEN
 1069         CALL blacs_gridexit( ictxt_new )
 1070      END IF
 1071
 1072  100 CONTINUE
 1073
 1074
 1075
 1076      ictxt = ictxt_save
 1077      np = np_save
 1078
 1079
 1080
 1081      work( 1 ) = work_size_min
 1082
 1083
 1084      RETURN
 1085
 1086
 1087
subroutine desc_convert(desc_in, desc_out, info)
 
subroutine dmatadd(m, n, alpha, a, lda, beta, c, ldc)
 
subroutine dpttrsv(trans, n, nrhs, d, e, b, ldb, 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)