4
    5
    6
    7
    8
    9
   10
   11      INTEGER            INFO, IZ, JZ, LIWORK, LWORK, M, N
   12      REAL               ORFAC
   13
   14
   15      INTEGER            DESCZ( * ), IBLOCK( * ), ICLUSTR( * ),
   16     $                   IFAIL( * ), ISPLIT( * ), IWORK( * )
   17      REAL               D( * ), E( * ), GAP( * ), W( * ), WORK( * )
   18      COMPLEX            Z( * )
   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      INTRINSIC          abs, 
max, 
min, mod, real
 
  265
  266
  267      INTEGER            ICEIL, NUMROC
  269
  270
  271      EXTERNAL           blacs_gridinfo, 
chk1mat, igamn2d, igebr2d,
 
  274
  275
  276      INTEGER            BLOCK_CYCLIC_2D, DLEN_, DTYPE_, CTXT_, M_, N_,
  277     $                   MB_, NB_, RSRC_, CSRC_, LLD_
  278      parameter( block_cyclic_2d = 1, dlen_ = 9, dtype_ = 1,
  279     $                   ctxt_ = 2, m_ = 3, n_ = 4, mb_ = 5, nb_ = 6,
  280     $                   rsrc_ = 7, csrc_ = 8, lld_ = 9 )
  281      REAL               ZERO, NEGONE, ODM1, FIVE, ODM3, ODM18
  282      parameter( zero = 0.0e+0, negone = -1.0e+0,
  283     $                   odm1 = 1.0e-1, five = 5.0e+0, odm3 = 1.0e-3,
  284     $                   odm18 = 1.0e-18 )
  285
  286
  287      LOGICAL            LQUERY, SORTED
  288      INTEGER            B1, BN, BNDRY, CLSIZ, COL, I, IFIRST, IINFO,
  289     $                   ILAST, IM, INDRW, ITMP, J, K, LGCLSIZ, LLWORK,
  290     $                   LOAD, LOCINFO, MAXVEC, MQ00, MYCOL, MYROW,
  291     $                   NBLK, NERR, NEXT, NP00, NPCOL, NPROW, NVS,
  292     $                   OLNBLK, P, ROW, SELF, TILL, TOTERR
  293      REAL               DIFF, MINGAP, ONENRM, ORGFAC, ORTOL, TMPFAC
  294
  295
  296      INTEGER            IDUM1( 1 ), IDUM2( 1 )
  297
  298
  299
  300      IF( block_cyclic_2d*csrc_*ctxt_*dlen_*dtype_*lld_*mb_*m_*nb_*n_*
  301     $    rsrc_.LT.0 )RETURN
  302
  303      CALL blacs_gridinfo( descz( ctxt_ ), nprow, npcol, myrow, mycol )
  304      self = myrow*npcol + mycol
  305
  306
  307
  308      info = 0
  309      IF( nprow.EQ.-1 ) THEN
  310         info = -( 1200+ctxt_ )
  311      ELSE
  312
  313
  314
  315         CALL chk1mat( n, 1, n, 1, iz, jz, descz, 12, info )
 
  316         IF( info.EQ.0 ) THEN
  317
  318
  319
  320
  321            np00 = 
numroc( n, descz( mb_ ), 0, 0, nprow )
 
  322            mq00 = 
numroc( m, descz( nb_ ), 0, 0, npcol )
 
  323            p = nprow*npcol
  324
  325
  326
  327            llwork = lwork
  328            CALL igamn2d( descz( ctxt_ ), 'A', ' ', 1, 1, llwork, 1, 1,
  329     $                    1, -1, -1, -1 )
  330            indrw = 
max( 5*n, np00*mq00 )
 
  331            IF( n.NE.0 )
  332     $         maxvec = ( llwork-indrw ) / n
  334            IF( myrow.EQ.0 .AND. mycol.EQ.0 ) THEN
  335               tmpfac = orfac
  336               CALL sgebs2d( descz( ctxt_ ), 'ALL', ' ', 1, 1, tmpfac,
  337     $                       1 )
  338            ELSE
  339               CALL sgebr2d( descz( ctxt_ ), 'ALL', ' ', 1, 1, tmpfac,
  340     $                       1, 0, 0 )
  341            END IF
  342
  343            lquery = ( lwork.EQ.-1 .OR. liwork.EQ.-1 )
  344            IF( m.LT.0 .OR. m.GT.n ) THEN
  345               info = -4
  346            ELSE IF( maxvec.LT.load .AND. .NOT.lquery ) THEN
  347               info = -14
  348            ELSE IF( liwork.LT.3*n+p+1 .AND. .NOT.lquery ) THEN
  349               info = -16
  350            ELSE
  351               DO 10 i = 2, m
  352                  IF( iblock( i ).LT.iblock( i-1 ) ) THEN
  353                     info = -6
  354                     GO TO 20
  355                  END IF
  356                  IF( iblock( i ).EQ.iblock( i-1 ) .AND. w( i ).LT.
  357     $                w( i-1 ) ) THEN
  358                     info = -5
  359                     GO TO 20
  360                  END IF
  361   10          CONTINUE
  362   20          CONTINUE
  363               IF( info.EQ.0 ) THEN
  364                  IF( abs( tmpfac-orfac ).GT.five*abs( tmpfac ) )
  365     $               info = -8
  366               END IF
  367            END IF
  368
  369         END IF
  370         idum1( 1 ) = m
  371         idum2( 1 ) = 4
  372         CALL pchk1mat( n, 1, n, 1, iz, jz, descz, 12, 1, idum1, idum2,
 
  373     $                  info )
  374         work( 1 ) = real( 
max( 5*n, np00*mq00 )+
iceil( m, p )*n )
 
  375         iwork( 1 ) = 3*n + p + 1
  376      END IF
  377      IF( info.NE.0 ) THEN
  378         CALL pxerbla( descz( ctxt_ ), 
'PCSTEIN', -info )
 
  379         RETURN
  380      ELSE IF( lwork.EQ.-1 .OR. liwork.EQ.-1 ) THEN
  381         RETURN
  382      END IF
  383
  384      DO 30 i = 1, m
  385         ifail( i ) = 0
  386   30 CONTINUE
  387      DO 40 i = 1, p + 1
  388         iwork( i ) = 0
  389   40 CONTINUE
  390      DO 50 i = 1, p
  391         gap( i ) = negone
  392         iclustr( 2*i-1 ) = 0
  393         iclustr( 2*i ) = 0
  394   50 CONTINUE
  395
  396
  397
  398
  399      IF( n.EQ.0 .OR. m.EQ.0 )
  400     $   RETURN
  401
  402      IF( orfac.GE.zero ) THEN
  403         tmpfac = orfac
  404      ELSE
  405         tmpfac = odm3
  406      END IF
  407      orgfac = tmpfac
  408
  409
  410
  411      ilast = m / load
  412      IF( mod( m, load ).EQ.0 )
  413     $   ilast = ilast - 1
  414      olnblk = -1
  415      nvs = 0
  416      next = 1
  417      im = 0
  418      onenrm = zero
  419      DO 100 i = 0, ilast - 1
  420         next = next + load
  421         j = next - 1
  422         IF( j.GT.nvs ) THEN
  423            nblk = iblock( next )
  424            IF( nblk.EQ.iblock( next-1 ) .AND. nblk.NE.olnblk ) THEN
  425
  426
  427
  428               IF( nblk.EQ.1 ) THEN
  429                  b1 = 1
  430               ELSE
  431                  b1 = isplit( nblk-1 ) + 1
  432               END IF
  433               bn = isplit( nblk )
  434
  435               onenrm = abs( d( b1 ) ) + abs( e( b1 ) )
  436               onenrm = 
max( onenrm, abs( d( bn ) )+abs( e( bn-1 ) ) )
 
  437               DO 60 j = b1 + 1, bn - 1
  438                  onenrm = 
max( onenrm, abs( d( j ) )+abs( e( j-1 ) )+
 
  439     $                     abs( e( j ) ) )
  440   60          CONTINUE
  441               olnblk = nblk
  442            END IF
  443            till = nvs + maxvec
  444   70       CONTINUE
  445            j = next - 1
  446            IF( tmpfac.GT.odm18 ) THEN
  447               ortol = tmpfac*onenrm
  448               DO 80 j = next - 1, 
min( till, m-1 )
 
  449                  IF( iblock( j+1 ).NE.iblock( j ) .OR. w( j+1 )-
  450     $                w( j ).GE.ortol ) THEN
  451                     GO TO 90
  452                  END IF
  453   80          CONTINUE
  454               IF( j.EQ.m .AND. till.GE.m )
  455     $            GO TO 90
  456               tmpfac = tmpfac*odm1
  457               GO TO 70
  458            END IF
  459   90       CONTINUE
  461         END IF
  462         IF( self.EQ.i )
  463     $      im = 
max( 0, j-nvs )
 
  464
  465         iwork( i+1 ) = nvs
  467  100 CONTINUE
  468      IF( self.EQ.ilast )
  469     $   im = m - nvs
  470      iwork( ilast+1 ) = nvs
  471      DO 110 i = ilast + 2, p + 1
  472         iwork( i ) = m
  473  110 CONTINUE
  474
  475      clsiz = 1
  476      lgclsiz = 1
  477      ilast = 0
  478      nblk = 0
  479      bndry = 2
  480      k = 1
  481      DO 140 i = 1, m
  482         IF( iblock( i ).NE.nblk ) THEN
  483            nblk = iblock( i )
  484            IF( nblk.EQ.1 ) THEN
  485               b1 = 1
  486            ELSE
  487               b1 = isplit( nblk-1 ) + 1
  488            END IF
  489            bn = isplit( nblk )
  490
  491            onenrm = abs( d( b1 ) ) + abs( e( b1 ) )
  492            onenrm = 
max( onenrm, abs( d( bn ) )+abs( e( bn-1 ) ) )
 
  493            DO 120 j = b1 + 1, bn - 1
  494               onenrm = 
max( onenrm, abs( d( j ) )+abs( e( j-1 ) )+
 
  495     $                  abs( e( j ) ) )
  496  120       CONTINUE
  497
  498         END IF
  499         IF( i.GT.1 ) THEN
  500            diff = w( i ) - w( i-1 )
  501            IF( iblock( i ).NE.iblock( i-1 ) .OR. i.EQ.m .OR. diff.GT.
  502     $          orgfac*onenrm ) THEN
  503               ifirst = ilast
  504               IF( i.EQ.m ) THEN
  505                  IF( iblock( m ).NE.iblock( m-1 ) .OR. diff.GT.orgfac*
  506     $                onenrm ) THEN
  507                     ilast = m - 1
  508                  ELSE
  509                     ilast = m
  510                  END IF
  511               ELSE
  512                  ilast = i - 1
  513               END IF
  514               clsiz = ilast - ifirst
  515               IF( clsiz.GT.1 ) THEN
  516                  IF( lgclsiz.LT.clsiz )
  517     $               lgclsiz = clsiz
  518                  mingap = onenrm
  519  130             CONTINUE
  520                  IF( bndry.GT.p+1 )
  521     $               GO TO 150
  522                  IF( iwork( bndry ).GT.ifirst .AND. iwork( bndry ).LT.
  523     $                ilast ) THEN
  524                     mingap = 
min( w( iwork( bndry )+1 )-
 
  525     $                        w( iwork( bndry ) ), mingap )
  526                  ELSE IF( iwork( bndry ).GE.ilast ) THEN
  527                     IF( mingap.LT.onenrm ) THEN
  528                        iclustr( 2*k-1 ) = ifirst + 1
  529                        iclustr( 2*k ) = ilast
  530                        gap( k ) = mingap / onenrm
  531                        k = k + 1
  532                     END IF
  533                     GO TO 140
  534                  END IF
  535                  bndry = bndry + 1
  536                  GO TO 130
  537               END IF
  538            END IF
  539         END IF
  540  140 CONTINUE
  541  150 CONTINUE
  542      info = ( k-1 )*( m+1 )
  543
  544
  545
  546      CALL sstein2( n, d, e, im, w( iwork( self+1 )+1 ),
 
  547     $              iblock( iwork( self+1 )+1 ), isplit, orgfac,
  548     $              work( indrw+1 ), n, work, iwork( p+2 ),
  549     $              ifail( iwork( self+1 )+1 ), locinfo )
  550
  551
  552
  553
  554
  555      DO 160 i = 1, m
  556         iwork( p+1+i ) = i
  557  160 CONTINUE
  558
  559      CALL slasrt2( 
'I', m, w, iwork( p+2 ), iinfo )
 
  560
  561      DO 170 i = 1, m
  562         iwork( m+p+1+iwork( p+1+i ) ) = i
  563  170 CONTINUE
  564
  565
  566      DO 180 i = 1, locinfo
  567         itmp = iwork( self+1 ) + i
  568         ifail( itmp ) = ifail( itmp ) + itmp - i
  569         ifail( itmp ) = iwork( m+p+1+ifail( itmp ) )
  570  180 CONTINUE
  571
  572      DO 190 i = 1, k - 1
  573         iclustr( 2*i-1 ) = iwork( m+p+1+iclustr( 2*i-1 ) )
  574         iclustr( 2*i ) = iwork( m+p+1+iclustr( 2*i ) )
  575  190 CONTINUE
  576
  577
  578
  579
  580
  581      toterr = 0
  582      DO 210 i = 1, p
  583         IF( self.EQ.i-1 ) THEN
  584            CALL igebs2d( descz( ctxt_ ), 'ALL', ' ', 1, 1, locinfo, 1 )
  585            IF( locinfo.NE.0 ) THEN
  586               CALL igebs2d( descz( ctxt_ ), 'ALL', ' ', locinfo, 1,
  587     $                       ifail( iwork( i )+1 ), locinfo )
  588               DO 200 j = 1, locinfo
  589                  ifail( toterr+j ) = ifail( iwork( i )+j )
  590  200          CONTINUE
  591               toterr = toterr + locinfo
  592            END IF
  593         ELSE
  594
  595            row = ( i-1 ) / npcol
  596            col = mod( i-1, npcol )
  597
  598            CALL igebr2d( descz( ctxt_ ), 'ALL', ' ', 1, 1, nerr, 1,
  599     $                    row, col )
  600            IF( nerr.NE.0 ) THEN
  601               CALL igebr2d( descz( ctxt_ ), 'ALL', ' ', nerr, 1,
  602     $                       ifail( toterr+1 ), nerr, row, col )
  603               toterr = toterr + nerr
  604            END IF
  605         END IF
  606  210 CONTINUE
  607      info = info + toterr
  608
  609
  610      CALL pclaevswp( n, work( indrw+1 ), n, z, iz, jz, descz, iwork,
 
  611     $                iwork( m+p+2 ), work, indrw )
  612
  613      DO 220 i = 2, p
  614         iwork( i ) = iwork( m+p+1+iwork( i ) )
  615  220 CONTINUE
  616
  617
  618
  619
  620
  621  230 CONTINUE
  622      sorted = .true.
  623      DO 240 i = 2, p - 1
  624         IF( iwork( i ).GT.iwork( i+1 ) ) THEN
  625            itmp = iwork( i+1 )
  626            iwork( i+1 ) = iwork( i )
  627            iwork( i ) = itmp
  628            sorted = .false.
  629         END IF
  630  240 CONTINUE
  631      IF( .NOT.sorted )
  632     $   GO TO 230
  633
  634      DO 250 i = p + 1, 1, -1
  635         iwork( i+1 ) = iwork( i )
  636  250 CONTINUE
  637
  638      work( 1 ) = ( lgclsiz+load-1 )*n + indrw
  639      iwork( 1 ) = 3*n + p + 1
  640
  641
  642
subroutine chk1mat(ma, mapos0, na, napos0, ia, ja, desca, descapos0, info)
 
integer function iceil(inum, idenom)
 
integer function numroc(n, nb, iproc, isrcproc, nprocs)
 
subroutine pchk1mat(ma, mapos0, na, napos0, ia, ja, desca, descapos0, nextra, ex, expos, info)
 
subroutine pclaevswp(n, zin, ldzi, z, iz, jz, descz, nvs, key, rwork, lrwork)
 
subroutine pxerbla(ictxt, srname, info)
 
subroutine slasrt2(id, n, d, key, info)
 
subroutine sstein2(n, d, e, m, w, iblock, isplit, orfac, z, ldz, work, iwork, ifail, info)