3
    4
    5
    6
    7
    8
    9
   10
   11
   12
   13      CHARACTER*1        ADIST, TRANS
   14      INTEGER            IACOL, IAROW, ICCOL, ICONTXT, ICROW, LDA, LDC,
   15     $                   M, N, NB
   16      COMPLEX*16         BETA
   17
   18
   19      COMPLEX*16         A( LDA, * ), C( LDC, * ), WORK( * )
   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      COMPLEX*16         ONE, ZERO
  180      parameter( one  = ( 1.0d+0, 0.0d+0 ),
  181     $                   zero = ( 0.0d+0, 0.0d+0 ) )
  182
  183
  184      LOGICAL            COLFORM, ROWFORM
  185      INTEGER            I, IDEX, IGD, INFO, JCCOL, JCROW, JDEX, LCM,
  186     $                   LCMP, LCMQ, MCCOL, MCROW, ML, MP, MQ, MQ0,
  187     $                   MRCOL, MRROW, MYCOL, MYROW, NP, NP0, NPCOL,
  188     $                   NPROW, NQ
  189      COMPLEX*16         TBETA
  190
  191
  192      LOGICAL            LSAME
  193      INTEGER            ILCM, ICEIL, NUMROC
  195
  196
  199     $                   zgebs2d, zgerv2d, zgesd2d
  200
  201
  203
  204
  205
  206
  207
  208      IF( m.EQ.0 .OR. n.EQ.0 ) RETURN
  209
  210      CALL blacs_gridinfo( icontxt, nprow, npcol, myrow, mycol )
  211
  212      colform = 
lsame( adist, 
'C' )
 
  213      rowform = 
lsame( adist, 
'R' )
 
  214
  215
  216
  217      info = 0
  218      IF( ( .NOT.colform ) .AND. ( .NOT.rowform ) ) THEN
  219         info = 2
  220      ELSE IF( m .LT.0                            ) THEN
  221         info = 4
  222      ELSE IF( n .LT.0                            ) THEN
  223         info = 5
  224      ELSE IF( nb.LT.1                            ) THEN
  225         info = 6
  226      ELSE IF( iarow.LT.-1 .OR. iarow.GE.nprow .OR.
  227     $       ( iarow.EQ.-1 .AND. colform )        ) THEN
  228         info = 12
  229      ELSE IF( iacol.LT.-1 .OR. iacol.GE.npcol .OR.
  230     $       ( iacol.EQ.-1 .AND. rowform )        ) THEN
  231         info = 13
  232      ELSE IF( icrow.LT.-1 .OR. icrow.GE.nprow .OR.
  233     $       ( icrow.EQ.-1 .AND. rowform )        ) THEN
  234         info = 14
  235      ELSE IF( iccol.LT.-1 .OR. iccol.GE.npcol .OR.
  236     $       ( iccol.EQ.-1 .AND. colform )        ) THEN
  237         info = 15
  238      END IF
  239
  240   10 CONTINUE
  241      IF( info .NE. 0 ) THEN
  242         CALL pxerbla( icontxt, 
'PBZTRAN ', info )
 
  243         RETURN
  244      END IF
  245
  246
  247
  248
  249
  250      lcm  = 
ilcm( nprow, npcol )
 
  251      lcmp = lcm   / nprow
  252      lcmq = lcm   / npcol
  253      igd  = npcol / lcmp
  254
  255
  256
  257      IF( colform ) THEN
  258
  259
  260
  261
  262
  263
  264
  265
  266
  267
  268
  269
  270
  271
  272        mrrow = mod( nprow+myrow-iarow, nprow )
  273        mrcol = mod( npcol+mycol-iccol, npcol )
  274        jcrow = icrow
  275        IF( icrow.EQ.-1 ) jcrow = iarow
  276
  277        mp  = 
numroc( m, nb, myrow, iarow, nprow )
 
  278        mq  = 
numroc( m, nb, mycol, iccol, npcol )
 
  279        mq0 = 
numroc( 
numroc(m, nb, 0, 0, npcol), nb, 0, 0, lcmq )
 
  280
  281        IF( lda.LT.mp .AND.
  282     $         ( iacol.EQ.mycol .OR. iacol.EQ.-1 ) ) THEN
  283           info = 8
  284        ELSE IF( ldc.LT.n .AND.
  285     $         ( icrow.EQ.myrow .OR. icrow.EQ.-1 ) ) THEN
  286           info = 11
  287        END IF
  288        IF( info.NE.0 ) GO TO 10
  289
  290
  291
  292        IF( iacol.GE.0 ) THEN
  293          tbeta = zero
  294          IF( myrow.EQ.jcrow ) tbeta = beta
  295
  296          DO 20 i = 0, 
min( lcm, 
iceil(m,nb) ) - 1
 
  297            mcrow = mod( mod(i, nprow) + iarow, nprow )
  298            mccol = mod( mod(i, npcol) + iccol, npcol )
  299            IF( lcmq.EQ.1 )  mq0 = 
numroc( m, nb, i, 0, npcol )
 
  300            jdex = (i/npcol) * nb
  301
  302
  303
  304            IF( myrow.EQ.mcrow .AND. mycol.EQ.iacol ) THEN
  305
  306
  307
  308              idex = (i/nprow) * nb
  309              IF( myrow.EQ.jcrow .AND. mycol.EQ.mccol ) THEN
  310                CALL pbztr2at( icontxt, 
'Col', trans, mp-idex, n, nb,
 
  311     $                         a(idex+1,1), lda, tbeta, c(1,jdex+1),
  312     $                         ldc, lcmp, lcmq )
  313
  314
  315
  316              ELSE
  317                CALL pbztr2bt( icontxt, 
'Col', trans, mp-idex, n, nb,
 
  318     $                         a(idex+1,1), lda, zero, work, n,
  319     $                         lcmp*nb )
  320                CALL zgesd2d( icontxt, n, mq0, work, n, jcrow, mccol )
  321              END IF
  322
  323
  324
  325            ELSE IF( myrow.EQ.jcrow .AND. mycol.EQ.mccol ) THEN
  326              IF( lcmq.EQ.1 .AND. tbeta.EQ.zero ) THEN
  327                CALL zgerv2d( icontxt, n, mq0, c, ldc, mcrow, iacol )
  328              ELSE
  329                CALL zgerv2d( icontxt, n, mq0, work, n, mcrow, iacol )
  330                CALL pbztr2af( icontxt, 
'Row', n, mq-jdex, nb, work, n,
 
  331     $                         tbeta, c(1,jdex+1), ldc, lcmp, lcmq,
  332     $                         mq0 )
  333              END IF
  334            END IF
  335   20     CONTINUE
  336
  337
  338
  339          IF( icrow.EQ.-1 ) THEN
  340            IF( myrow.EQ.jcrow ) THEN
  341              CALL zgebs2d( icontxt, 'Col', '1-tree', n, mq, c, ldc )
  342            ELSE
  343              CALL zgebr2d( icontxt, 'Col', '1-tree', n, mq, c, ldc,
  344     $                      jcrow, mycol )
  345            END IF
  346          END IF
  347
  348
  349
  350        ELSE
  351          IF( lcmq.EQ.1 ) mq0 = mq
  352
  353
  354
  355
  356          DO 30 i = 0, lcmp-1
  357            IF( mrcol.EQ.mod( nprow*i+mrrow, npcol ) ) THEN
  358              IF( lcmq.EQ.1.AND.(icrow.EQ.-1.OR.icrow.EQ.myrow) ) THEN
  359                 CALL pbztr2bt( icontxt, 
'Col', trans, mp-i*nb, n, nb,
 
  360     $                          a(i*nb+1,1), lda, beta, c, ldc,
  361     $                          lcmp*nb )
  362              ELSE
  363                 CALL pbztr2bt( icontxt, 
'Col', trans, mp-i*nb, n, nb,
 
  364     $                          a(i*nb+1,1), lda, zero, work, n,
  365     $                          lcmp*nb )
  366              END IF
  367            END IF
  368   30     CONTINUE
  369
  370
  371
  372          mcrow = mod( mod(mrcol,nprow)+iarow, nprow )
  373          IF( lcmq.GT.1 ) THEN
  374            mccol = mod( npcol+mycol-iccol, npcol )
  376     $                     mcrow,  mccol, igd, myrow, mycol, nprow,
  377     $                     npcol )
  378          END IF
  379
  380
  381
  382          IF( icrow.EQ.-1 ) THEN
  383            IF( myrow.EQ.mcrow ) THEN
  384              IF( lcmq.GT.1 )
  385     $          
CALL pbztrsrt( icontxt, 
'Row', n, mq, nb, work, n, beta,
 
  386     $                         c, ldc, lcmp, lcmq, mq0 )
  387              CALL zgebs2d( icontxt, 'Col', '1-tree', n, mq, c, ldc )
  388            ELSE
  389              CALL zgebr2d( icontxt, 'Col', '1-tree', n, mq, c, ldc,
  390     $                      mcrow, mycol )
  391            END IF
  392
  393
  394
  395          ELSE
  396            IF( lcmq.EQ.1 ) THEN
  397              IF( myrow.EQ.mcrow ) THEN
  398                IF( myrow.NE.icrow )
  399     $            CALL zgesd2d( icontxt, n, mq, work, n, icrow, mycol )
  400              ELSE IF( myrow.EQ.icrow ) THEN
  401                IF( beta.EQ.zero ) THEN
  402                  CALL zgerv2d( icontxt, n, mq, c, ldc, mcrow, mycol )
  403                ELSE
  404                  CALL zgerv2d( icontxt, n, mq, work, n, mcrow, mycol )
  405                  CALL pbzmatadd( icontxt, 
'G', n, mq, one, work, n,
 
  406     $                            beta, c, ldc )
  407                END IF
  408              END IF
  409
  410            ELSE
  412              IF( myrow.EQ.mcrow ) THEN
  413                IF( myrow.NE.icrow )
  414     $            CALL zgesd2d( icontxt, n, ml, work, n, icrow, mycol )
  415              ELSE IF( myrow.EQ.icrow ) THEN
  416                CALL zgerv2d( icontxt, n, ml, work, n, mcrow, mycol )
  417              END IF
  418
  419              IF( myrow.EQ.icrow )
  420     $          
CALL pbztrsrt( icontxt, 
'Row', n, mq, nb, work, n, beta,
 
  421     $                         c, ldc, lcmp, lcmq, mq0 )
  422            END IF
  423          END IF
  424
  425        END IF
  426
  427
  428
  429      ELSE
  430
  431
  432
  433
  434
  435
  436
  437
  438
  439
  440
  441
  442
  443
  444         mrrow = mod( nprow+myrow-icrow, nprow )
  445         mrcol = mod( npcol+mycol-iacol, npcol )
  446         jccol = iccol
  447         IF( iccol.EQ.-1 ) jccol = iacol
  448
  449         np  = 
numroc( n, nb, myrow, icrow, nprow )
 
  450         nq  = 
numroc( n, nb, mycol, iacol, npcol )
 
  451         np0 = 
numroc( 
numroc(n, nb, 0, 0, nprow), nb, 0, 0, lcmp )
 
  452
  453         IF( lda.LT.m .AND.
  454     $          ( iarow.EQ.myrow .OR. iarow.EQ.-1 ) ) THEN
  455            info = 8
  456         ELSE IF( ldc.LT.np .AND.
  457     $          ( iccol.EQ.mycol .OR. iccol.EQ.-1 ) ) THEN
  458            info = 11
  459         END IF
  460         IF( info.NE.0 ) GO TO 10
  461
  462
  463
  464         IF( iarow.GE.0 ) THEN
  465           tbeta = zero
  466           IF( mycol.EQ.jccol ) tbeta = beta
  467
  468           DO 40 i = 0, 
min( lcm, 
iceil(n,nb) ) - 1
 
  469             mcrow = mod( mod(i, nprow) + icrow, nprow )
  470             mccol = mod( mod(i, npcol) + iacol, npcol )
  471             IF( lcmp.EQ.1 )  np0 = 
numroc( n, nb, i, 0, nprow )
 
  472             idex = (i/nprow) * nb
  473
  474
  475
  476             IF( myrow.EQ.iarow .AND. mycol.EQ.mccol ) THEN
  477
  478
  479
  480               jdex = (i/npcol) * nb
  481               IF( myrow.EQ.mcrow .AND. mycol.EQ.jccol ) THEN
  482                 CALL pbztr2at( icontxt, 
'Row', trans, m, nq-jdex, nb,
 
  483     $                          a(1,jdex+1), lda, tbeta, c(idex+1,1),
  484     $                          ldc, lcmp, lcmq )
  485
  486
  487
  488               ELSE
  489                 CALL pbztr2bt( icontxt, 
'Row', trans, m, nq-jdex, nb,
 
  490     $                          a(1,jdex+1), lda, zero, work, np0,
  491     $                          lcmq*nb )
  492                 CALL zgesd2d( icontxt, np0, m, work, np0,
  493     $                         mcrow, jccol )
  494               END IF
  495
  496
  497
  498            ELSE IF( myrow.EQ.mcrow .AND. mycol.EQ.jccol ) THEN
  499              IF( lcmp.EQ.1 .AND. tbeta.EQ.zero ) THEN
  500                CALL zgerv2d( icontxt, np0, m, c, ldc, iarow, mccol )
  501              ELSE
  502                CALL zgerv2d( icontxt, np0, m, work, np0, iarow, mccol )
  503                CALL pbztr2af( icontxt, 
'Col', np-idex, m, nb, work,
 
  504     $                         np0, tbeta, c(idex+1,1), ldc, lcmp, lcmq,
  505     $                         np0 )
  506              END IF
  507            END IF
  508   40     CONTINUE
  509
  510
  511
  512          IF( iccol.EQ.-1 ) THEN
  513            IF( mycol.EQ.jccol ) THEN
  514              CALL zgebs2d( icontxt, 'Row', '1-tree', np, m, c, ldc )
  515            ELSE
  516              CALL zgebr2d( icontxt, 'Row', '1-tree', np, m, c, ldc,
  517     $                       myrow, jccol )
  518            END IF
  519          END IF
  520
  521
  522
  523        ELSE
  524          IF( lcmp.EQ.1 ) np0 = np
  525
  526
  527
  528
  529          DO 50 i = 0, lcmq-1
  530            IF( mrrow.EQ.mod(npcol*i+mrcol, nprow) ) THEN
  531              IF( lcmp.EQ.1.AND.(iccol.EQ.-1.OR.iccol.EQ.mycol) ) THEN
  532                CALL pbztr2bt( icontxt, 
'Row', trans, m, nq-i*nb, nb,
 
  533     $                         a(1,i*nb+1), lda, beta, c, ldc,
  534     $                         lcmq*nb )
  535              ELSE
  536                CALL pbztr2bt( icontxt, 
'Row', trans, m, nq-i*nb, nb,
 
  537     $                         a(1,i*nb+1), lda, zero, work, np0,
  538     $                         lcmq*nb )
  539              END IF
  540            END IF
  541   50     CONTINUE
  542
  543
  544
  545          mccol = mod( mod(mrrow, npcol)+iacol, npcol )
  546          IF( lcmp.GT.1 ) THEN
  547            mcrow = mod( nprow+myrow-icrow, nprow )
  549     $                     np0, mcrow, mccol, igd, myrow, mycol, nprow,
  550     $                     npcol )
  551          END IF
  552
  553
  554
  555          IF( iccol.EQ.-1 ) THEN
  556            IF( mycol.EQ.mccol ) THEN
  557              IF( lcmp.GT.1 )
  558     $          
CALL pbztrsrt( icontxt, 
'Col', np, m, nb, work, np0,
 
  559     $                         beta, c, ldc, lcmp, lcmq, np0 )
  560              CALL zgebs2d( icontxt, 'Row', '1-tree', np, m, c, ldc )
  561            ELSE
  562              CALL zgebr2d( icontxt, 'Row', '1-tree', np, m, c, ldc,
  563     $                       myrow, mccol )
  564            END IF
  565
  566
  567
  568          ELSE
  569            IF( lcmp.EQ.1 ) THEN
  570              IF( mycol.EQ.mccol ) THEN
  571                IF( mycol.NE.iccol )
  572     $            CALL zgesd2d( icontxt, np, m, work, np, myrow, iccol )
  573              ELSE IF( mycol.EQ.iccol ) THEN
  574                IF( beta.EQ.zero ) THEN
  575                  CALL zgerv2d( icontxt, np, m, c, ldc, myrow, mccol )
  576                ELSE
  577                  CALL zgerv2d( icontxt, np, m, work, np, myrow, mccol )
  578                  CALL pbzmatadd( icontxt, 
'G', np, m, one, work, np,
 
  579     $                            beta, c, ldc )
  580                END IF
  581              END IF
  582
  583            ELSE
  584              ml = m * 
min( lcmp, 
max( 0, 
iceil(n,nb) - mcrow ) )
 
  585              IF( mycol.EQ.mccol ) THEN
  586                IF( mycol.NE.iccol )
  587     $            CALL zgesd2d( icontxt, np0, ml, work, np0,
  588     $                          myrow, iccol )
  589              ELSE IF( mycol.EQ.iccol ) THEN
  590                CALL zgerv2d( icontxt, np0, ml, work, np0,
  591     $                        myrow, mccol )
  592              END IF
  593
  594              IF( mycol.EQ.iccol )
  595     $          
CALL pbztrsrt( icontxt, 
'Col', np, m, nb, work, np0,
 
  596     $                         beta, c, ldc, lcmp, lcmq, np0 )
  597            END IF
  598          END IF
  599
  600        END IF
  601      END IF
  602
  603      RETURN
  604
  605
  606
integer function iceil(inum, idenom)
 
integer function ilcm(m, n)
 
integer function numroc(n, nb, iproc, isrcproc, nprocs)
 
subroutine pbzmatadd(icontxt, mode, m, n, alpha, a, lda, beta, b, ldb)
 
subroutine pbztr2af(icontxt, adist, m, n, nb, a, lda, beta, b, ldb, lcmp, lcmq, nint)
 
subroutine pbztr2bt(icontxt, adist, trans, m, n, nb, a, lda, beta, b, ldb, intv)
 
subroutine pbztr2at(icontxt, adist, trans, m, n, nb, a, lda, beta, b, ldb, lcmp, lcmq)
 
subroutine pbztrget(icontxt, adist, m, n, mnb, a, lda, mcrow, mccol, igd, myrow, mycol, nprow, npcol)
 
subroutine pbztrsrt(icontxt, adist, m, n, nb, a, lda, beta, b, ldb, lcmp, lcmq, nint)
 
subroutine pxerbla(ictxt, srname, info)