Routine: PDSTEBZ()  File: SRC\pdstebz.f

 
 
# lines: 882
  # code: 882
  # comment: 0
  # blank:0
# Variables:116
# Callers:2
# Callings:4
# Words:663
# Keywords:417
 

 

..
     .. Array Arguments ..
     ..
  Purpose
  =======
  PDSTEBZ computes the eigenvalues of a symmetric tridiagonal matrix in
  parallel. The user may ask for all eigenvalues, all eigenvalues in
  the interval [VL, VU], or the eigenvalues indexed IL through IU. A
  static partitioning of work is done at the beginning of PDSTEBZ which
  results in all processes finding an (almost) equal number of
  eigenvalues.
  NOTE : It is assumed that the user is on an IEEE machine. If the user
         is not on an IEEE mchine, set the compile time flag NO_IEEE
         to 1 (in SLmake.inc). The features of IEEE arithmetic that
         are needed for the "fast" Sturm Count are : (a) infinity
         arithmetic (b) the sign bit of a single precision floating
         point number is assumed be in the 32nd bit position
         (c) the sign of negative zero.
  See W. Kahan "Accurate Eigenvalues of a Symmetric Tridiagonal
  Matrix", Report CS41, Computer Science Dept., Stanford
  University, July 21, 1966.
  Arguments
  =========
  ICTXT   (global input) INTEGER
          The BLACS context handle.
  RANGE   (global input) CHARACTER
          Specifies which eigenvalues are to be found.
          = 'A': ("All")   all eigenvalues will be found.
          = 'V': ("Value") all eigenvalues in the interval
                           [VL, VU] will be found.
          = 'I': ("Index") the IL-th through IU-th eigenvalues (of the
                           entire matrix) will be found.
  ORDER   (global input) CHARACTER
          Specifies the order in which the eigenvalues and their block
          numbers are stored in W and IBLOCK.
          = 'B': ("By Block") the eigenvalues will be grouped by
                              split-off block (see IBLOCK, ISPLIT) and
                              ordered from smallest to largest within
                              the block.
          = 'E': ("Entire matrix")
                              the eigenvalues for the entire matrix
                              will be ordered from smallest to largest.
  N       (global input) INTEGER
          The order of the tridiagonal matrix T.  N >= 0.
  VL      (global input) DOUBLE PRECISION
          If RANGE='V', the lower bound of the interval to be searched
          for eigenvalues.  Eigenvalues less than VL will not be
          returned.  Not referenced if RANGE='A' or 'I'.
  VU      (global input) DOUBLE PRECISION
          If RANGE='V', the upper bound of the interval to be searched
          for eigenvalues.  Eigenvalues greater than VU will not be
          returned.  VU must be greater than VL.  Not referenced if
          RANGE='A' or 'I'.
  IL      (global input) INTEGER
          If RANGE='I', the index (from smallest to largest) of the
          smallest eigenvalue to be returned.  IL must be at least 1.
          Not referenced if RANGE='A' or 'V'.
  IU      (global input) INTEGER
          If RANGE='I', the index (from smallest to largest) of the
          largest eigenvalue to be returned.  IU must be at least IL
          and no greater than N.  Not referenced if RANGE='A' or 'V'.
  ABSTOL  (global input) DOUBLE PRECISION
          The absolute tolerance for the eigenvalues.  An eigenvalue
          (or cluster) is considered to be located if it has been
          determined to lie in an interval whose width is ABSTOL or
          less.  If ABSTOL is less than or equal to zero, then ULP*|T|
          will be used, where |T| means the 1-norm of T.
          Eigenvalues will be computed most accurately when ABSTOL is
          set to the underflow threshold DLAMCH('U'), not zero.
          Note : If eigenvectors are desired later by inverse iteration
          ( PDSTEIN ), ABSTOL should be set to 2*PDLAMCH('S').
  D       (global input) DOUBLE PRECISION array, dimension (N)
          The n diagonal elements of the tridiagonal matrix T.  To
          avoid overflow, the matrix must be scaled so that its largest
          entry is no greater than overflow**(1/2) * underflow**(1/4)
          in absolute value, and for greatest accuracy, it should not
          be much smaller than that.
  E       (global input) DOUBLE PRECISION array, dimension (N-1)
          The (n-1) off-diagonal elements of the tridiagonal matrix T.
          To avoid overflow, the matrix must be scaled so that its
          largest entry is no greater than overflow**(1/2) *
          underflow**(1/4) in absolute value, and for greatest
          accuracy, it should not be much smaller than that.
  M       (global output) INTEGER
          The actual number of eigenvalues found. 0 <= M <= N.
          (See also the description of INFO=2)
  NSPLIT  (global output) INTEGER
          The number of diagonal blocks in the matrix T.
          1 <= NSPLIT <= N.
  W       (global output) DOUBLE PRECISION array, dimension (N)
          On exit, the first M elements of W contain the eigenvalues
          on all processes.
  IBLOCK  (global output) INTEGER array, dimension (N)
          At each row/column j where E(j) is zero or small, the
          matrix T is considered to split into a block diagonal
          matrix.  On exit IBLOCK(i) specifies which block (from 1
          to the number of blocks) the eigenvalue W(i) belongs to.
          NOTE:  in the (theoretically impossible) event that bisection
          does not converge for some or all eigenvalues, INFO is set
          to 1 and the ones for which it did not are identified by a
          negative block number.
  ISPLIT  (global output) INTEGER array, dimension (N)
          The splitting points, at which T breaks up into submatrices.
          The first submatrix consists of rows/columns 1 to ISPLIT(1),
          the second of rows/columns ISPLIT(1)+1 through ISPLIT(2),
          etc., and the NSPLIT-th consists of rows/columns
          ISPLIT(NSPLIT-1)+1 through ISPLIT(NSPLIT)=N.
          (Only the first NSPLIT elements will actually be used, but
          since the user cannot know a priori what value NSPLIT will
          have, N words must be reserved for ISPLIT.)
  WORK    (local workspace) DOUBLE PRECISION array,
          dimension ( MAX( 5*N, 7 ) )
  LWORK   (local input) INTEGER
          size of array WORK must be >= MAX( 5*N, 7 )
          If LWORK = -1, then LWORK is global input and a workspace
          query is assumed; the routine only calculates the minimum
          and optimal size for all work arrays. Each of these
          values is returned in the first entry of the corresponding
          work array, and no error message is issued by PXERBLA.
  IWORK   (local workspace) INTEGER array, dimension ( MAX( 4*N, 14 ) )
  LIWORK  (local input) INTEGER
          size of array IWORK must be >= MAX( 4*N, 14, NPROCS )
          If LIWORK = -1, then LIWORK is global input and a workspace
          query is assumed; the routine only calculates the minimum
          and optimal size for all work arrays. Each of these
          values is returned in the first entry of the corresponding
          work array, and no error message is issued by PXERBLA.
  INFO    (global output) INTEGER
          = 0 :  successful exit
          < 0 :  if INFO = -i, the i-th argument had an illegal value
          > 0 :  some or all of the eigenvalues failed to converge or
                 were not computed:
              = 1 : Bisection failed to converge for some eigenvalues;
                    these eigenvalues are flagged by a negative block
                    number.  The effect is that the eigenvalues may not
                    be as accurate as the absolute and relative
                    tolerances. This is generally caused by arithmetic
                    which is less accurate than PDLAMCH says.
              = 2 : There is a mismatch between the number of
                    eigenvalues output and the number desired.
              = 3 : RANGE='i', and the Gershgorin interval initially
                    used was incorrect. No eigenvalues were computed.
                    Probable cause: your machine has sloppy floating
                    point arithmetic.
                    Cure: Increase the PARAMETER "FUDGE", recompile,
                    and try again.
  Internal Parameters
  ===================
  RELFAC  DOUBLE PRECISION, default = 2.0
          The relative tolerance.  An interval [a,b] lies within
          "relative tolerance" if  b-a < RELFAC*ulp*max(|a|,|b|),
          where "ulp" is the machine precision (distance from 1 to
          the next larger floating point number.)
  FUDGE   DOUBLE PRECISION, default = 2.0
          A "fudge factor" to widen the Gershgorin intervals.  Ideally,
          a value of 1 should work, but on machines with sloppy
          arithmetic, this needs to be larger.  The default for
          publicly released versions should be large enough to handle
          the worst machine around.  Note that this has no effect
          on the accuracy of the solution.
  =====================================================================
     .. Intrinsic Functions ..

 
Display dynamic version Find AutoScroll Reload FontSize: - + Hide Comments Hide Blanks Frame FullScreen MailPrint

 
001        SUBROUTINE PDSTEBZ( ICTXT , RANGE , ORDER , N , VL , VU , IL , IU ,
002       $ABSTOL , D , E , M , NSPLIT , W , IBLOCK , ISPLIT ,
003       $WORK , LWORK , IWORK , LIWORK , INFO )
004  
005  *     -- ScaLAPACK routine(version 1.7) --
006  *     University of Tennessee , Knoxville , Oak Ridge National Laboratory ,
007  *     and University of California , Berkeley.
008  *     November 15 , 1997
009  
010  *     .. Scalar Arguments ..
011        CHARACTER ORDER , RANGE
012        INTEGER ICTXT , IL , INFO , IU , LIWORK , LWORK , M , N ,
013       $NSPLIT
014        DOUBLE PRECISION ABSTOL , VL , VU
015        INTRINSIC ABS , DBLE , ICHAR , MAX , MIN , MOD
016  *     ..
017  *     .. External Functions ..
018        LOGICAL LSAME
019        INTEGER BLACS_PNUM
020        DOUBLE PRECISION PDLAMCH
021        EXTERNAL LSAME , BLACS_PNUM , PDLAMCH
022  *     ..
023  *     .. External Subroutines ..
024        EXTERNAL BLACS_FREEBUFF , BLACS_GET , BLACS_GRIDEXIT ,
025       $BLACS_GRIDINFO , BLACS_GRIDMAP , DGEBR2D ,
026       $DGEBS2D , DGERV2D , DGESD2D , DLASRT2 , GLOBCHK ,
027       $IGEBR2D , IGEBS2D , IGERV2D , IGESD2D , IGSUM2D ,
028       $PDLAEBZ , PDLAIECTB , PDLAIECTL , PDLAPDCT ,
029       $PDLASNBT , PXERBLA
030  *     ..
031  *     .. Parameters ..
032        INTEGER BLOCK_CYCLIC_2D , DLEN_ , DTYPE_ , CTXT_ , M_ , N_ ,
033       $MB_ , NB_ , RSRC_ , CSRC_ , LLD_
034        PARAMETER( BLOCK_CYCLIC_2D = 1 , DLEN_ = 9 , DTYPE_ = 1 ,
035       $CTXT_ = 2 , M_ = 3 , N_ = 4 , MB_ = 5 , NB_ = 6 ,
036       $RSRC_ = 7 , CSRC_ = 8 , LLD_ = 9 )
037        INTEGER BIGNUM , DESCMULT
038        PARAMETER( BIGNUM = 10000 , DESCMULT = 100 )
039        DOUBLE PRECISION ZERO , ONE , TWO , FIVE , HALF
040        PARAMETER( ZERO = 0.0D + 0 , ONE = 1.0D + 0 , TWO = 2.0D + 0 ,
041       $FIVE = 5.0D + 0 , HALF = 1.0D + 0 / TWO )
042        DOUBLE PRECISION FUDGE , RELFAC
043        PARAMETER( FUDGE = 2.0D + 0 , RELFAC = 2.0D + 0 )
044  *     ..
045  *     .. Local Scalars ..
046        LOGICAL LQUERY
047        INTEGER BLKNO , FOUND , I , IBEGIN , IEFLAG , IEND , IFRST ,
048       $IINFO , ILAST , ILOAD , IM , IMYLOAD , IN , INDRIW1 ,
049       $INDRIW2 , INDRW1 , INDRW2 , INXTLOAD , IOFF ,
050       $IORDER , IOUT , IRANGE , IRECV , IREM , ITMP1 ,
051       $ITMP2 , J , JB , K , LAST , LEXTRA , LREQ , MYCOL ,
052       $MYROW , NALPHA , NBETA , NCMP , NEIGINT , NEXT , NGL ,
053       $NGLOB , NGU , NINT , NPCOL , NPROW , OFFSET ,
054       $ONEDCONTEXT , P , PREV , REXTRA , RREQ , SELF ,
055       $TORECV
056        DOUBLE PRECISION ALPHA , ATOLI , BETA , BNORM , DRECV , DSEND , GL ,
057       $GU , INITVL , INITVU , LSAVE , MID , PIVMIN , RELTOL ,
058       $SAFEMN , TMP1 , TMP2 , TNORM , ULP
059  *     ..
060  *     .. Local Arrays ..
061        INTEGER IDUM( 5 , 2 )
062  *     ..
063  *     .. Executable Statements ..
064  *     This is just to keep ftnchek happy
065        IF( BLOCK_CYCLIC_2D*CSRC_*CTXT_*DLEN_*DTYPE_*LLD_*MB_*M_*NB_*N_*
066       $    RSRC_.LT.0 )RETURN
067  
068  *         Set up process grid
069  
070            CALL BLACS_GRIDINFO( ICTXT , NPROW , NPCOL , MYROW , MYCOL )
071  
072            INFO = 0
073            M = 0
074  
075  *         Decode RANGE
076  
077            IF( LSAME( RANGE , 'A' ) ) THEN
078                IRANGE = 1
079            ELSE IF( LSAME( RANGE , 'V' ) ) THEN
080                IRANGE = 2
081            ELSE IF( LSAME( RANGE , 'I' ) ) THEN
082                IRANGE = 3
083            ELSE
084                IRANGE = 0
085            END IF
086  
087  *         Decode ORDER
088  
089            IF( LSAME( ORDER , 'B' ) ) THEN
090                IORDER = 2
091            ELSE IF( LSAME( ORDER , 'E' ) .OR. LSAME( ORDER , 'A' ) ) THEN
092                IORDER = 1
093            ELSE
094                IORDER = 0
095            END IF
096  
097  *         Check for Errors
098  
099            IF( NPROW.EQ. - 1 ) THEN
100                INFO = - 1
101            ELSE
102  
103  *             Get machine constants
104  
105                SAFEMN = PDLAMCH( ICTXT , 'S' )
106                ULP = PDLAMCH( ICTXT , 'P' )
107                RELTOL = ULP*RELFAC
108                IDUM( 1 , 1 ) = ICHAR( RANGE )
109                IDUM( 1 , 2 ) = 2
110                IDUM( 2 , 1 ) = ICHAR( ORDER )
111                IDUM( 2 , 2 ) = 3
112                IDUM( 3 , 1 ) = N
113                IDUM( 3 , 2 ) = 4
114                NGLOB = 5
115                IF( IRANGE.EQ.3 ) THEN
116                    IDUM( 4 , 1 ) = IL
117                    IDUM( 4 , 2 ) = 7
118                    IDUM( 5 , 1 ) = IU
119                    IDUM( 5 , 2 ) = 8
120                ELSE
121                    IDUM( 4 , 1 ) = 0
122                    IDUM( 4 , 2 ) = 0
123                    IDUM( 5 , 1 ) = 0
124                    IDUM( 5 , 2 ) = 0
125                END IF
126                IF( MYROW.EQ.0 .AND. MYCOL.EQ.0 ) THEN
127                    WORK( 1 ) = ABSTOL
128                    IF( IRANGE.EQ.2 ) THEN
129                        WORK( 2 ) = VL
130                        WORK( 3 ) = VU
131                    ELSE
132                        WORK( 2 ) = ZERO
133                        WORK( 3 ) = ZERO
134                    END IF
135                    CALL DGEBS2D( ICTXT , 'ALL' , ' ' , 3 , 1 , WORK , 3 )
136                ELSE
137                    CALL DGEBR2D( ICTXT , 'ALL' , ' ' , 3 , 1 , WORK , 3 , 0 , 0 )
138                END IF
139                LQUERY =( LWORK.EQ. - 1 .OR. LIWORK.EQ. - 1 )
140                IF( INFO.EQ.0 ) THEN
141                    IF( IRANGE.EQ.0 ) THEN
142                        INFO = - 2
143                    ELSE IF( IORDER.EQ.0 ) THEN
144                        INFO = - 3
145                    ELSE IF( IRANGE.EQ.2 .AND. VL.GE.VU ) THEN
146                        INFO = - 5
147                    ELSE IF( IRANGE.EQ.3 .AND.( IL.LT.1 .OR. IL.GT.MAX( 1 ,
148       $                N ) ) ) THEN
149                        INFO = - 6
150                    ELSE IF( IRANGE.EQ.3 .AND.( IU.LT.MIN( N ,
151       $                IL ) .OR. IU.GT.N ) ) THEN
152                        INFO = - 7
153                    ELSE IF( LWORK.LT.MAX( 5*N , 7 ) .AND. .NOT.LQUERY ) THEN
154                        INFO = - 18
155                    ELSE IF( LIWORK.LT.MAX( 4*N , 14 , NPROW*NPCOL ) .AND. .NOT.
156       $                LQUERY ) THEN
157                        INFO = - 20
158                    ELSE IF( IRANGE.EQ.2 .AND.( ABS( WORK( 2 ) - VL ).GT.FIVE*
159       $                ULP*ABS( VL ) ) ) THEN
160                        INFO = - 5
161                    ELSE IF( IRANGE.EQ.2 .AND.( ABS( WORK( 3 ) - VU ).GT.FIVE*
162       $                ULP*ABS( VU ) ) ) THEN
163                        INFO = - 6
164                    ELSE IF( ABS( WORK( 1 ) - ABSTOL ).GT.FIVE*ULP*ABS( ABSTOL ) )
165       $                THEN
166                        INFO = - 9
167                    END IF
168                END IF
169                IF( INFO.EQ.0 )
170       $            INFO = BIGNUM
171                    CALL GLOBCHK( ICTXT , NGLOB , IDUM , 5 , IWORK , INFO )
172                    IF( INFO.EQ.BIGNUM ) THEN
173                        INFO = 0
174                    ELSE IF( MOD( INFO , DESCMULT ).EQ.0 ) THEN
175                        INFO = - INFO / DESCMULT
176                    ELSE
177                        INFO = - INFO
178                    END IF
179                END IF
180                WORK( 1 ) = DBLE( MAX( 5*N , 7 ) )
181                IWORK( 1 ) = MAX( 4*N , 14 , NPROW*NPCOL )
182  
183                IF( INFO.NE.0 ) THEN
184                    CALL PXERBLA( ICTXT , 'PDSTEBZ' , - INFO )
185                    RETURN
186                ELSE IF( LWORK.EQ. - 1 .AND. LIWORK.EQ. - 1 ) THEN
187                    RETURN
188                END IF
189  
190  *             Quick return if possible
191  
192                IF( N.EQ.0 )
193       $            RETURN
194  
195                    K = 1
196                    DO 20 I = 0 , NPROW - 1
197                        DO 10 J = 0 , NPCOL - 1
198                            IWORK( K ) = BLACS_PNUM( ICTXT , I , J )
199                            K = K + 1
200     10                 CONTINUE
201     20             CONTINUE
202  
203                    P = NPROW*NPCOL
204                    NPROW = 1
205                    NPCOL = P
206  
207                    CALL BLACS_GET( ICTXT , 10 , ONEDCONTEXT )
208                    CALL BLACS_GRIDMAP( ONEDCONTEXT , IWORK , NPROW , NPROW , NPCOL )
209                    CALL BLACS_GRIDINFO( ONEDCONTEXT , I , J , K , SELF )
210  
211  *                 Simplifications :
212  
213                    IF( IRANGE.EQ.3 .AND. IL.EQ.1 .AND. IU.EQ.N )
214       $                IRANGE = 1
215  
216                    NEXT = MOD( SELF + 1 , P )
217                    PREV = MOD( P + SELF - 1 , P )
218  
219  *                 Compute squares of off - diagonals , splitting points and pivmin.
220  *                 Interleave diagonals and off - diagonals.
221  
222                    INDRW1 = MAX( 2*N , 4 )
223                    INDRW2 = INDRW1 + 2*N
224                    INDRIW1 = MAX( 2*N , 8 )
225                    NSPLIT = 1
226                    WORK( INDRW1 + 2*N ) = ZERO
227                    PIVMIN = ONE
228  
229                    DO 30 I = 1 , N - 1
230                        TMP1 = E( I )**2
231                        J = 2*I
232                        WORK( INDRW1 + J - 1 ) = D( I )
233                        IF( ABS( D( I + 1 )*D( I ) )*ULP**2 + SAFEMN.GT.TMP1 ) THEN
234                            ISPLIT( NSPLIT ) = I
235                            NSPLIT = NSPLIT + 1
236                            WORK( INDRW1 + J ) = ZERO
237                        ELSE
238                            WORK( INDRW1 + J ) = TMP1
239                            PIVMIN = MAX( PIVMIN , TMP1 )
240                        END IF
241     30             CONTINUE
242                    WORK( INDRW1 + 2*N - 1 ) = D( N )
243                    ISPLIT( NSPLIT ) = N
244                    PIVMIN = PIVMIN*SAFEMN
245  
246  *                 Compute Gershgorin interval[gl , gu] for entire matrix
247  
248                    GU = D( 1 )
249                    GL = D( 1 )
250                    TMP1 = ZERO
251  
252                    DO 40 I = 1 , N - 1
253                        TMP2 = ABS( E( I ) )
254                        GU = MAX( GU , D( I ) + TMP1 + TMP2 )
255                        GL = MIN( GL , D( I ) - TMP1 - TMP2 )
256                        TMP1 = TMP2
257     40             CONTINUE
258                    GU = MAX( GU , D( N ) + TMP1 )
259                    GL = MIN( GL , D( N ) - TMP1 )
260                    TNORM = MAX( ABS( GL ) , ABS( GU ) )
261                    GL = GL - FUDGE*TNORM*ULP*N - FUDGE*TWO*PIVMIN
262                    GU = GU + FUDGE*TNORM*ULP*N + FUDGE*PIVMIN
263  
264                    IF( ABSTOL.LE.ZERO ) THEN
265                        ATOLI = ULP*TNORM
266                    ELSE
267                        ATOLI = ABSTOL
268                    END IF
269  
270  *                 Find out if on an IEEE machine , the sign bit is the
271  *                 32nd bit(Big Endian) or the 64th bit(Little Endian)
272  
273                    IF( IRANGE.EQ.1 .OR. NSPLIT.EQ.1 ) THEN
274                        CALL PDLASNBT( IEFLAG )
275                    ELSE
276                        IEFLAG = 0
277                    END IF
278                    LEXTRA = 0
279                    REXTRA = 0
280  
281  *                 Form Initial Interval containing desired eigenvalues
282  
283                    IF( IRANGE.EQ.1 ) THEN
284                        INITVL = GL
285                        INITVU = GU
286                        WORK( 1 ) = GL
287                        WORK( 2 ) = GU
288                        IWORK( 1 ) = 0
289                        IWORK( 2 ) = N
290                        IFRST = 1
291                        ILAST = N
292                    ELSE IF( IRANGE.EQ.2 ) THEN
293                        IF( VL.GT.GL ) THEN
294                            IF( IEFLAG.EQ.0 ) THEN
295                                CALL PDLAPDCT ( VL , N , WORK( INDRW1 + 1 ) , PIVMIN , IFRST )
296                            ELSE IF( IEFLAG.EQ.1 ) THEN
297                                CALL PDLAIECTB( VL , N , WORK( INDRW1 + 1 ) , IFRST )
298                            ELSE
299                                CALL PDLAIECTL( VL , N , WORK( INDRW1 + 1 ) , IFRST )
300                            END IF
301                            IFRST = IFRST + 1
302                            INITVL = VL
303                        ELSE
304                            INITVL = GL
305                            IFRST = 1
306                        END IF
307                        IF( VU.LT.GU ) THEN
308                            IF( IEFLAG.EQ.0 ) THEN
309                                CALL PDLAPDCT ( VU , N , WORK( INDRW1 + 1 ) , PIVMIN , ILAST )
310                            ELSE IF( IEFLAG.EQ.1 ) THEN
311                                CALL PDLAIECTB( VU , N , WORK( INDRW1 + 1 ) , ILAST )
312                            ELSE
313                                CALL PDLAIECTL( VU , N , WORK( INDRW1 + 1 ) , ILAST )
314                            END IF
315                            INITVU = VU
316                        ELSE
317                            INITVU = GU
318                            ILAST = N
319                        END IF
320                        WORK( 1 ) = INITVL
321                        WORK( 2 ) = INITVU
322                        IWORK( 1 ) = IFRST - 1
323                        IWORK( 2 ) = ILAST
324                    ELSE IF( IRANGE.EQ.3 ) THEN
325                        WORK( 1 ) = GL
326                        WORK( 2 ) = GU
327                        IWORK( 1 ) = 0
328                        IWORK( 2 ) = N
329                        IWORK( 5 ) = IL - 1
330                        IWORK( 6 ) = IU
331                        CALL PDLAEBZ ( 0 , N , 2 , 1 , ATOLI , RELTOL , PIVMIN ,
332       $                WORK( INDRW1 + 1 ) , IWORK( 5 ) , WORK , IWORK , NINT ,
333       $                LSAVE , IEFLAG , IINFO )
334                        IF( IINFO.NE.0 ) THEN
335                            INFO = 3
336                            GO TO 230
337                        END IF
338                        IF( NINT.GT.1 ) THEN
339                            IF( IWORK( 5 ).EQ.IL - 1 ) THEN
340                                WORK( 2 ) = WORK( 4 )
341                                IWORK( 2 ) = IWORK( 4 )
342                            ELSE
343                                WORK( 1 ) = WORK( 3 )
344                                IWORK( 1 ) = IWORK( 3 )
345                            END IF
346                            IF( IWORK( 1 ).LT.0 .OR. IWORK( 1 ).GT.IL - 1 .OR.
347       $                    IWORK( 2 ).LE.MIN( IU - 1 , IWORK( 1 ) ) .OR.
348       $                    IWORK( 2 ).GT.N ) THEN
349                            INFO = 3
350                            GO TO 230
351                        END IF
352                    END IF
353                    LEXTRA = IL - 1 - IWORK( 1 )
354                    REXTRA = IWORK( 2 ) - IU
355                    INITVL = WORK( 1 )
356                    INITVU = WORK( 2 )
357                    IFRST = IL
358                    ILAST = IU
359                END IF
360  *             NVL = IFRST - 1
361  *             NVU = ILAST
362                GL = INITVL
363                GU = INITVU
364                NGL = IWORK( 1 )
365                NGU = IWORK( 2 )
366                IM = 0
367                FOUND = 0
368                INDRIW2 = INDRIW1 + NGU - NGL
369                IEND = 0
370                IF( IFRST.GT.ILAST )
371       $            GO TO 100
372                    IF( IFRST.EQ.1 .AND. ILAST.EQ.N )
373       $                IRANGE = 1
374  
375  *                     Find Eigenvalues -- Loop Over Blocks
376  
377                        DO 90 JB = 1 , NSPLIT
378                            IOFF = IEND
379                            IBEGIN = IOFF + 1
380                            IEND = ISPLIT( JB )
381                            IN = IEND - IOFF
382                            IF( JB.NE.1 ) THEN
383                                IF( IRANGE.NE.1 ) THEN
384                                    FOUND = IM
385  
386  *                                 Find total number of eigenvalues found thus far
387  
388                                    CALL IGSUM2D( ONEDCONTEXT , 'All' , ' ' , 1 , 1 , FOUND , 1 ,
389       $                            - 1 , - 1 )
390                                ELSE
391                                    FOUND = IOFF
392                                END IF
393                            END IF
394  *                         IF( SELF.GE.P )
395  *                         $ GO TO 30
396                            IF( IN.NE.N ) THEN
397  
398  *                             Compute Gershgorin interval[gl , gu] for split matrix
399  
400                                GU = D( IBEGIN )
401                                GL = D( IBEGIN )
402                                TMP1 = ZERO
403  
404                                DO 50 J = IBEGIN , IEND - 1
405                                    TMP2 = ABS( E( J ) )
406                                    GU = MAX( GU , D( J ) + TMP1 + TMP2 )
407                                    GL = MIN( GL , D( J ) - TMP1 - TMP2 )
408                                    TMP1 = TMP2
409     50                         CONTINUE
410  
411                                GU = MAX( GU , D( IEND ) + TMP1 )
412                                GL = MIN( GL , D( IEND ) - TMP1 )
413                                BNORM = MAX( ABS( GL ) , ABS( GU ) )
414                                GL = GL - FUDGE*BNORM*ULP*IN - FUDGE*PIVMIN
415                                GU = GU + FUDGE*BNORM*ULP*IN + FUDGE*PIVMIN
416  
417  *                             Compute ATOLI for the current submatrix
418  
419                                IF( ABSTOL.LE.ZERO ) THEN
420                                    ATOLI = ULP*BNORM
421                                ELSE
422                                    ATOLI = ABSTOL
423                                END IF
424  
425                                IF( GL.LT.INITVL ) THEN
426                                    GL = INITVL
427                                    IF( IEFLAG.EQ.0 ) THEN
428                                        CALL PDLAPDCT ( GL , IN , WORK( INDRW1 + 2*IOFF + 1 ) ,
429       $                                PIVMIN , NGL )
430                                    ELSE IF( IEFLAG.EQ.1 ) THEN
431                                        CALL PDLAIECTB( GL , IN , WORK( INDRW1 + 2*IOFF + 1 ) , NGL )
432                                    ELSE
433                                        CALL PDLAIECTL( GL , IN , WORK( INDRW1 + 2*IOFF + 1 ) , NGL )
434                                    END IF
435                                ELSE
436                                    NGL = 0
437                                END IF
438                                IF( GU.GT.INITVU ) THEN
439                                    GU = INITVU
440                                    IF( IEFLAG.EQ.0 ) THEN
441                                        CALL PDLAPDCT ( GU , IN , WORK( INDRW1 + 2*IOFF + 1 ) ,
442       $                                PIVMIN , NGU )
443                                    ELSE IF( IEFLAG.EQ.1 ) THEN
444                                        CALL PDLAIECTB( GU , IN , WORK( INDRW1 + 2*IOFF + 1 ) , NGU )
445                                    ELSE
446                                        CALL PDLAIECTL( GU , IN , WORK( INDRW1 + 2*IOFF + 1 ) , NGU )
447                                    END IF
448                                ELSE
449                                    NGU = IN
450                                END IF
451                                IF( NGL.GE.NGU )
452       $                            GO TO 90
453                                    WORK( 1 ) = GL
454                                    WORK( 2 ) = GU
455                                    IWORK( 1 ) = NGL
456                                    IWORK( 2 ) = NGU
457                                END IF
458                                OFFSET = FOUND - NGL
459                                BLKNO = JB
460  
461  *                             Do a static partitioning of work so that each process
462  *                             has to find an(almost) equal number of eigenvalues
463  
464                                NCMP = NGU - NGL
465                                ILOAD = NCMP / P
466                                IREM = NCMP - ILOAD*P
467                                ITMP1 = MOD( SELF - FOUND , P )
468                                IF( ITMP1.LT.0 )
469       $                            ITMP1 = ITMP1 + P
470                                    IF( ITMP1.LT.IREM ) THEN
471                                        IMYLOAD = ILOAD + 1
472                                    ELSE
473                                        IMYLOAD = ILOAD
474                                    END IF
475                                    IF( IMYLOAD.EQ.0 ) THEN
476                                        GO TO 90
477                                    ELSE IF( IN.EQ.1 ) THEN
478                                        WORK( INDRW2 + IM + 1 ) = WORK( INDRW1 + 2*IOFF + 1 )
479                                        IWORK( INDRIW1 + IM + 1 ) = BLKNO
480                                        IWORK( INDRIW2 + IM + 1 ) = OFFSET + 1
481                                        IM = IM + 1
482                                        GO TO 90
483                                    ELSE
484                                        INXTLOAD = ILOAD
485                                        ITMP2 = MOD( SELF + 1 - FOUND , P )
486                                        IF( ITMP2.LT.0 )
487       $                                    ITMP2 = ITMP2 + P
488                                            IF( ITMP2.LT.IREM )
489       $                                        INXTLOAD = INXTLOAD + 1
490                                                LREQ = NGL + ITMP1*ILOAD + MIN( IREM , ITMP1 )
491                                                RREQ = LREQ + IMYLOAD
492                                                IWORK( 5 ) = LREQ
493                                                IWORK( 6 ) = RREQ
494                                                TMP1 = WORK( 1 )
495                                                ITMP1 = IWORK( 1 )
496                                                CALL PDLAEBZ ( 1 , IN , 1 , 1 , ATOLI , RELTOL , PIVMIN ,
497       $                                        WORK( INDRW1 + 2*IOFF + 1 ) , IWORK( 5 ) , WORK ,
498       $                                        IWORK , NINT , LSAVE , IEFLAG , IINFO )
499                                                ALPHA = WORK( 1 )
500                                                BETA = WORK( 2 )
501                                                NALPHA = IWORK( 1 )
502                                                NBETA = IWORK( 2 )
503                                                DSEND = BETA
504                                                IF( NBETA.GT.RREQ + INXTLOAD ) THEN
505                                                    NBETA = RREQ
506                                                    DSEND = ALPHA
507                                                END IF
508                                                LAST = MOD( FOUND + MIN( NGU - NGL , P ) - 1 , P )
509                                                IF( LAST.LT.0 )
510       $                                            LAST = LAST + P
511                                                    IF( SELF.NE.LAST ) THEN
512                                                        CALL DGESD2D( ONEDCONTEXT , 1 , 1 , DSEND , 1 , 0 , NEXT )
513                                                        CALL IGESD2D( ONEDCONTEXT , 1 , 1 , NBETA , 1 , 0 , NEXT )
514                                                    END IF
515                                                    IF( SELF.NE.MOD( FOUND , P ) ) THEN
516                                                        CALL DGERV2D( ONEDCONTEXT , 1 , 1 , DRECV , 1 , 0 , PREV )
517                                                        CALL IGERV2D( ONEDCONTEXT , 1 , 1 , IRECV , 1 , 0 , PREV )
518                                                    ELSE
519                                                        DRECV = TMP1
520                                                        IRECV = ITMP1
521                                                    END IF
522                                                    WORK( 1 ) = MAX( LSAVE , DRECV )
523                                                    IWORK( 1 ) = IRECV
524                                                    ALPHA = MAX( ALPHA , WORK( 1 ) )
525                                                    NALPHA = MAX( NALPHA , IRECV )
526                                                    IF( BETA - ALPHA.LE.MAX( ATOLI , RELTOL*MAX( ABS( ALPHA ) ,
527       $                                            ABS( BETA ) ) ) ) THEN
528                                                    MID = HALF*( ALPHA + BETA )
529                                                    DO 60 J = OFFSET + NALPHA + 1 , OFFSET + NBETA
530                                                    WORK( INDRW2 + IM + 1 ) = MID
531                                                    IWORK( INDRIW1 + IM + 1 ) = BLKNO
532                                                    IWORK( INDRIW2 + IM + 1 ) = J
533                                                    IM = IM + 1
534     60                                             CONTINUE
535                                                    WORK( 2 ) = ALPHA
536                                                    IWORK( 2 ) = NALPHA
537                                                END IF
538                                            END IF
539                                            NEIGINT = IWORK( 2 ) - IWORK( 1 )
540                                            IF( NEIGINT.LE.0 )
541       $                                        GO TO 90
542  
543  *                                             Call the main computational routine
544  
545                                                CALL PDLAEBZ ( 2 , IN , NEIGINT , 1 , ATOLI , RELTOL , PIVMIN ,
546       $                                        WORK( INDRW1 + 2*IOFF + 1 ) , IWORK , WORK , IWORK ,
547       $                                        IOUT , LSAVE , IEFLAG , IINFO )
548                                                IF( IINFO.NE.0 ) THEN
549                                                    INFO = 1
550                                                END IF
551                                                DO 80 I = 1 , IOUT
552                                                    MID = HALF*( WORK( 2*I - 1 ) + WORK( 2*I ) )
553                                                    IF( I.GT.IOUT - IINFO )
554       $                                                BLKNO = - BLKNO
555                                                        DO 70 J = OFFSET + IWORK( 2*I - 1 ) + 1 ,
556       $                                                OFFSET + IWORK( 2*I )
557                                                        WORK( INDRW2 + IM + 1 ) = MID
558                                                        IWORK( INDRIW1 + IM + 1 ) = BLKNO
559                                                        IWORK( INDRIW2 + IM + 1 ) = J
560                                                        IM = IM + 1
561     70                                                 CONTINUE
562     80                                         CONTINUE
563     90                 CONTINUE
564  
565  *                     Find out total number of eigenvalues computed
566  
567    100 CONTINUE
568        M = IM
569        CALL IGSUM2D( ONEDCONTEXT , 'ALL' , ' ' , 1 , 1 , M , 1 , - 1 , - 1 )
570  
571  *     Move the eigenvalues found to their final destinations
572  
573        DO 130 I = 1 , P
574            IF( SELF.EQ.I - 1 ) THEN
575                CALL IGEBS2D( ONEDCONTEXT , 'ALL' , ' ' , 1 , 1 , IM , 1 )
576                IF( IM.NE.0 ) THEN
577                    CALL IGEBS2D( ONEDCONTEXT , 'ALL' , ' ' , IM , 1 ,
578       $            IWORK( INDRIW2 + 1 ) , IM )
579                    CALL DGEBS2D( ONEDCONTEXT , 'ALL' , ' ' , IM , 1 ,
580       $            WORK( INDRW2 + 1 ) , IM )
581                    CALL IGEBS2D( ONEDCONTEXT , 'ALL' , ' ' , IM , 1 ,
582       $            IWORK( INDRIW1 + 1 ) , IM )
583                    DO 110 J = 1 , IM
584                        W( IWORK( INDRIW2 + J ) ) = WORK( INDRW2 + J )
585                        IBLOCK( IWORK( INDRIW2 + J ) ) = IWORK( INDRIW1 + J )
586    110             CONTINUE
587                END IF
588            ELSE
589                CALL IGEBR2D( ONEDCONTEXT , 'ALL' , ' ' , 1 , 1 , TORECV , 1 , 0 ,
590       $        I - 1 )
591                IF( TORECV.NE.0 ) THEN
592                    CALL IGEBR2D( ONEDCONTEXT , 'ALL' , ' ' , TORECV , 1 , IWORK ,
593       $            TORECV , 0 , I - 1 )
594                    CALL DGEBR2D( ONEDCONTEXT , 'ALL' , ' ' , TORECV , 1 , WORK ,
595       $            TORECV , 0 , I - 1 )
596                    CALL IGEBR2D( ONEDCONTEXT , 'ALL' , ' ' , TORECV , 1 ,
597       $            IWORK( N + 1 ) , TORECV , 0 , I - 1 )
598                    DO 120 J = 1 , TORECV
599                        W( IWORK( J ) ) = WORK( J )
600                        IBLOCK( IWORK( J ) ) = IWORK( N + J )
601    120             CONTINUE
602                END IF
603            END IF
604    130 CONTINUE
605        IF( NSPLIT.GT.1 .AND. IORDER.EQ.1 ) THEN
606  
607  *         Sort the eigenvalues
608  
609            DO 140 I = 1 , M
610                IWORK( M + I ) = I
611    140     CONTINUE
612            CALL DLASRT2 ( 'I' , M , W , IWORK( M + 1 ) , IINFO )
613            DO 150 I = 1 , M
614                IWORK( I ) = IBLOCK( I )
615    150     CONTINUE
616            DO 160 I = 1 , M
617                IBLOCK( I ) = IWORK( IWORK( M + I ) )
618    160     CONTINUE
619        END IF
620        IF( IRANGE.EQ.3 .AND.( LEXTRA.GT.0 .OR. REXTRA.GT.0 ) ) THEN
621  
622  *         Discard unwanted eigenvalues(occurs only when RANGE = 'I' ,
623  *         and eigenvalues IL , and / or IU are in a cluster)
624  
625            DO 170 I = 1 , M
626                WORK( I ) = W( I )
627                IWORK( I ) = I
628                IWORK( M + I ) = I
629    170     CONTINUE
630            DO 190 I = 1 , LEXTRA
631                ITMP1 = I
632                DO 180 J = I + 1 , M
633                    IF( WORK( J ).LT.WORK( ITMP1 ) ) THEN
634                        ITMP1 = J
635                    END IF
636    180         CONTINUE
637                TMP1 = WORK( I )
638                WORK( I ) = WORK( ITMP1 )
639                WORK( ITMP1 ) = TMP1
640                IWORK( IWORK( M + ITMP1 ) ) = I
641                IWORK( IWORK( M + I ) ) = ITMP1
642                ITMP2 = IWORK( M + I )
643                IWORK( M + I ) = IWORK( M + ITMP1 )
644                IWORK( M + ITMP1 ) = ITMP2
645    190     CONTINUE
646            DO 210 I = 1 , REXTRA
647                ITMP1 = M - I + 1
648                DO 200 J = M - I , LEXTRA + 1 , - 1
649                    IF( WORK( J ).GT.WORK( ITMP1 ) ) THEN
650                        ITMP1 = J
651                    END IF
652    200         CONTINUE
653                TMP1 = WORK( M - I + 1 )
654                WORK( M - I + 1 ) = WORK( ITMP1 )
655                WORK( ITMP1 ) = TMP1
656                IWORK( IWORK( M + ITMP1 ) ) = M - I + 1
657                IWORK( IWORK( 2*M - I + 1 ) ) = ITMP1
658                ITMP2 = IWORK( 2*M - I + 1 )
659                IWORK( 2*M - I + 1 ) = IWORK( M + ITMP1 )
660                IWORK( M + ITMP1 ) = ITMP2
661  *             IWORK( ITMP1 ) = 1
662    210     CONTINUE
663            J = 0
664            DO 220 I = 1 , M
665                IF( IWORK( I ).GT.LEXTRA .AND. IWORK( I ).LE.M - REXTRA ) THEN
666                    J = J + 1
667                    W( J ) = WORK( IWORK( I ) )
668                    IBLOCK( J ) = IBLOCK( I )
669                END IF
670    220     CONTINUE
671            M = M - LEXTRA - REXTRA
672        END IF
673        IF( M.NE.ILAST - IFRST + 1 ) THEN
674            INFO = 2
675        END IF
676  
677    230 CONTINUE
678        CALL BLACS_FREEBUFF( ONEDCONTEXT , 1 )
679        CALL BLACS_GRIDEXIT( ONEDCONTEXT )
680        RETURN
681  
682  *     End of PDSTEBZ
683  
684        END
685