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