Annotation of rpl/lapack/lapack/dstebz.f, revision 1.9

1.9     ! bertrand    1: *> \brief \b DSTEBZ
        !             2: *
        !             3: *  =========== DOCUMENTATION ===========
        !             4: *
        !             5: * Online html documentation available at 
        !             6: *            http://www.netlib.org/lapack/explore-html/ 
        !             7: *
        !             8: *> \htmlonly
        !             9: *> Download DSTEBZ + dependencies 
        !            10: *> <a href="http://www.netlib.org/cgi-bin/netlibfiles.tgz?format=tgz&filename=/lapack/lapack_routine/dstebz.f"> 
        !            11: *> [TGZ]</a> 
        !            12: *> <a href="http://www.netlib.org/cgi-bin/netlibfiles.zip?format=zip&filename=/lapack/lapack_routine/dstebz.f"> 
        !            13: *> [ZIP]</a> 
        !            14: *> <a href="http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/dstebz.f"> 
        !            15: *> [TXT]</a>
        !            16: *> \endhtmlonly 
        !            17: *
        !            18: *  Definition:
        !            19: *  ===========
        !            20: *
        !            21: *       SUBROUTINE DSTEBZ( RANGE, ORDER, N, VL, VU, IL, IU, ABSTOL, D, E,
        !            22: *                          M, NSPLIT, W, IBLOCK, ISPLIT, WORK, IWORK,
        !            23: *                          INFO )
        !            24: * 
        !            25: *       .. Scalar Arguments ..
        !            26: *       CHARACTER          ORDER, RANGE
        !            27: *       INTEGER            IL, INFO, IU, M, N, NSPLIT
        !            28: *       DOUBLE PRECISION   ABSTOL, VL, VU
        !            29: *       ..
        !            30: *       .. Array Arguments ..
        !            31: *       INTEGER            IBLOCK( * ), ISPLIT( * ), IWORK( * )
        !            32: *       DOUBLE PRECISION   D( * ), E( * ), W( * ), WORK( * )
        !            33: *       ..
        !            34: *  
        !            35: *
        !            36: *> \par Purpose:
        !            37: *  =============
        !            38: *>
        !            39: *> \verbatim
        !            40: *>
        !            41: *> DSTEBZ computes the eigenvalues of a symmetric tridiagonal
        !            42: *> matrix T.  The user may ask for all eigenvalues, all eigenvalues
        !            43: *> in the half-open interval (VL, VU], or the IL-th through IU-th
        !            44: *> eigenvalues.
        !            45: *>
        !            46: *> To avoid overflow, the matrix must be scaled so that its
        !            47: *> largest element is no greater than overflow**(1/2) * underflow**(1/4) in absolute value, and for greatest
        !            48: *> accuracy, it should not be much smaller than that.
        !            49: *>
        !            50: *> See W. Kahan "Accurate Eigenvalues of a Symmetric Tridiagonal
        !            51: *> Matrix", Report CS41, Computer Science Dept., Stanford
        !            52: *> University, July 21, 1966.
        !            53: *> \endverbatim
        !            54: *
        !            55: *  Arguments:
        !            56: *  ==========
        !            57: *
        !            58: *> \param[in] RANGE
        !            59: *> \verbatim
        !            60: *>          RANGE is CHARACTER*1
        !            61: *>          = 'A': ("All")   all eigenvalues will be found.
        !            62: *>          = 'V': ("Value") all eigenvalues in the half-open interval
        !            63: *>                           (VL, VU] will be found.
        !            64: *>          = 'I': ("Index") the IL-th through IU-th eigenvalues (of the
        !            65: *>                           entire matrix) will be found.
        !            66: *> \endverbatim
        !            67: *>
        !            68: *> \param[in] ORDER
        !            69: *> \verbatim
        !            70: *>          ORDER is CHARACTER*1
        !            71: *>          = 'B': ("By Block") the eigenvalues will be grouped by
        !            72: *>                              split-off block (see IBLOCK, ISPLIT) and
        !            73: *>                              ordered from smallest to largest within
        !            74: *>                              the block.
        !            75: *>          = 'E': ("Entire matrix")
        !            76: *>                              the eigenvalues for the entire matrix
        !            77: *>                              will be ordered from smallest to
        !            78: *>                              largest.
        !            79: *> \endverbatim
        !            80: *>
        !            81: *> \param[in] N
        !            82: *> \verbatim
        !            83: *>          N is INTEGER
        !            84: *>          The order of the tridiagonal matrix T.  N >= 0.
        !            85: *> \endverbatim
        !            86: *>
        !            87: *> \param[in] VL
        !            88: *> \verbatim
        !            89: *>          VL is DOUBLE PRECISION
        !            90: *> \endverbatim
        !            91: *>
        !            92: *> \param[in] VU
        !            93: *> \verbatim
        !            94: *>          VU is DOUBLE PRECISION
        !            95: *>
        !            96: *>          If RANGE='V', the lower and upper bounds of the interval to
        !            97: *>          be searched for eigenvalues.  Eigenvalues less than or equal
        !            98: *>          to VL, or greater than VU, will not be returned.  VL < VU.
        !            99: *>          Not referenced if RANGE = 'A' or 'I'.
        !           100: *> \endverbatim
        !           101: *>
        !           102: *> \param[in] IL
        !           103: *> \verbatim
        !           104: *>          IL is INTEGER
        !           105: *> \endverbatim
        !           106: *>
        !           107: *> \param[in] IU
        !           108: *> \verbatim
        !           109: *>          IU is INTEGER
        !           110: *>
        !           111: *>          If RANGE='I', the indices (in ascending order) of the
        !           112: *>          smallest and largest eigenvalues to be returned.
        !           113: *>          1 <= IL <= IU <= N, if N > 0; IL = 1 and IU = 0 if N = 0.
        !           114: *>          Not referenced if RANGE = 'A' or 'V'.
        !           115: *> \endverbatim
        !           116: *>
        !           117: *> \param[in] ABSTOL
        !           118: *> \verbatim
        !           119: *>          ABSTOL is DOUBLE PRECISION
        !           120: *>          The absolute tolerance for the eigenvalues.  An eigenvalue
        !           121: *>          (or cluster) is considered to be located if it has been
        !           122: *>          determined to lie in an interval whose width is ABSTOL or
        !           123: *>          less.  If ABSTOL is less than or equal to zero, then ULP*|T|
        !           124: *>          will be used, where |T| means the 1-norm of T.
        !           125: *>
        !           126: *>          Eigenvalues will be computed most accurately when ABSTOL is
        !           127: *>          set to twice the underflow threshold 2*DLAMCH('S'), not zero.
        !           128: *> \endverbatim
        !           129: *>
        !           130: *> \param[in] D
        !           131: *> \verbatim
        !           132: *>          D is DOUBLE PRECISION array, dimension (N)
        !           133: *>          The n diagonal elements of the tridiagonal matrix T.
        !           134: *> \endverbatim
        !           135: *>
        !           136: *> \param[in] E
        !           137: *> \verbatim
        !           138: *>          E is DOUBLE PRECISION array, dimension (N-1)
        !           139: *>          The (n-1) off-diagonal elements of the tridiagonal matrix T.
        !           140: *> \endverbatim
        !           141: *>
        !           142: *> \param[out] M
        !           143: *> \verbatim
        !           144: *>          M is INTEGER
        !           145: *>          The actual number of eigenvalues found. 0 <= M <= N.
        !           146: *>          (See also the description of INFO=2,3.)
        !           147: *> \endverbatim
        !           148: *>
        !           149: *> \param[out] NSPLIT
        !           150: *> \verbatim
        !           151: *>          NSPLIT is INTEGER
        !           152: *>          The number of diagonal blocks in the matrix T.
        !           153: *>          1 <= NSPLIT <= N.
        !           154: *> \endverbatim
        !           155: *>
        !           156: *> \param[out] W
        !           157: *> \verbatim
        !           158: *>          W is DOUBLE PRECISION array, dimension (N)
        !           159: *>          On exit, the first M elements of W will contain the
        !           160: *>          eigenvalues.  (DSTEBZ may use the remaining N-M elements as
        !           161: *>          workspace.)
        !           162: *> \endverbatim
        !           163: *>
        !           164: *> \param[out] IBLOCK
        !           165: *> \verbatim
        !           166: *>          IBLOCK is INTEGER array, dimension (N)
        !           167: *>          At each row/column j where E(j) is zero or small, the
        !           168: *>          matrix T is considered to split into a block diagonal
        !           169: *>          matrix.  On exit, if INFO = 0, IBLOCK(i) specifies to which
        !           170: *>          block (from 1 to the number of blocks) the eigenvalue W(i)
        !           171: *>          belongs.  (DSTEBZ may use the remaining N-M elements as
        !           172: *>          workspace.)
        !           173: *> \endverbatim
        !           174: *>
        !           175: *> \param[out] ISPLIT
        !           176: *> \verbatim
        !           177: *>          ISPLIT is INTEGER array, dimension (N)
        !           178: *>          The splitting points, at which T breaks up into submatrices.
        !           179: *>          The first submatrix consists of rows/columns 1 to ISPLIT(1),
        !           180: *>          the second of rows/columns ISPLIT(1)+1 through ISPLIT(2),
        !           181: *>          etc., and the NSPLIT-th consists of rows/columns
        !           182: *>          ISPLIT(NSPLIT-1)+1 through ISPLIT(NSPLIT)=N.
        !           183: *>          (Only the first NSPLIT elements will actually be used, but
        !           184: *>          since the user cannot know a priori what value NSPLIT will
        !           185: *>          have, N words must be reserved for ISPLIT.)
        !           186: *> \endverbatim
        !           187: *>
        !           188: *> \param[out] WORK
        !           189: *> \verbatim
        !           190: *>          WORK is DOUBLE PRECISION array, dimension (4*N)
        !           191: *> \endverbatim
        !           192: *>
        !           193: *> \param[out] IWORK
        !           194: *> \verbatim
        !           195: *>          IWORK is INTEGER array, dimension (3*N)
        !           196: *> \endverbatim
        !           197: *>
        !           198: *> \param[out] INFO
        !           199: *> \verbatim
        !           200: *>          INFO is INTEGER
        !           201: *>          = 0:  successful exit
        !           202: *>          < 0:  if INFO = -i, the i-th argument had an illegal value
        !           203: *>          > 0:  some or all of the eigenvalues failed to converge or
        !           204: *>                were not computed:
        !           205: *>                =1 or 3: Bisection failed to converge for some
        !           206: *>                        eigenvalues; these eigenvalues are flagged by a
        !           207: *>                        negative block number.  The effect is that the
        !           208: *>                        eigenvalues may not be as accurate as the
        !           209: *>                        absolute and relative tolerances.  This is
        !           210: *>                        generally caused by unexpectedly inaccurate
        !           211: *>                        arithmetic.
        !           212: *>                =2 or 3: RANGE='I' only: Not all of the eigenvalues
        !           213: *>                        IL:IU were found.
        !           214: *>                        Effect: M < IU+1-IL
        !           215: *>                        Cause:  non-monotonic arithmetic, causing the
        !           216: *>                                Sturm sequence to be non-monotonic.
        !           217: *>                        Cure:   recalculate, using RANGE='A', and pick
        !           218: *>                                out eigenvalues IL:IU.  In some cases,
        !           219: *>                                increasing the PARAMETER "FUDGE" may
        !           220: *>                                make things work.
        !           221: *>                = 4:    RANGE='I', and the Gershgorin interval
        !           222: *>                        initially used was too small.  No eigenvalues
        !           223: *>                        were computed.
        !           224: *>                        Probable cause: your machine has sloppy
        !           225: *>                                        floating-point arithmetic.
        !           226: *>                        Cure: Increase the PARAMETER "FUDGE",
        !           227: *>                              recompile, and try again.
        !           228: *> \endverbatim
        !           229: *
        !           230: *> \par Internal Parameters:
        !           231: *  =========================
        !           232: *>
        !           233: *> \verbatim
        !           234: *>  RELFAC  DOUBLE PRECISION, default = 2.0e0
        !           235: *>          The relative tolerance.  An interval (a,b] lies within
        !           236: *>          "relative tolerance" if  b-a < RELFAC*ulp*max(|a|,|b|),
        !           237: *>          where "ulp" is the machine precision (distance from 1 to
        !           238: *>          the next larger floating point number.)
        !           239: *>
        !           240: *>  FUDGE   DOUBLE PRECISION, default = 2
        !           241: *>          A "fudge factor" to widen the Gershgorin intervals.  Ideally,
        !           242: *>          a value of 1 should work, but on machines with sloppy
        !           243: *>          arithmetic, this needs to be larger.  The default for
        !           244: *>          publicly released versions should be large enough to handle
        !           245: *>          the worst machine around.  Note that this has no effect
        !           246: *>          on accuracy of the solution.
        !           247: *> \endverbatim
        !           248: *
        !           249: *  Authors:
        !           250: *  ========
        !           251: *
        !           252: *> \author Univ. of Tennessee 
        !           253: *> \author Univ. of California Berkeley 
        !           254: *> \author Univ. of Colorado Denver 
        !           255: *> \author NAG Ltd. 
        !           256: *
        !           257: *> \date November 2011
        !           258: *
        !           259: *> \ingroup auxOTHERcomputational
        !           260: *
        !           261: *  =====================================================================
1.1       bertrand  262:       SUBROUTINE DSTEBZ( RANGE, ORDER, N, VL, VU, IL, IU, ABSTOL, D, E,
                    263:      $                   M, NSPLIT, W, IBLOCK, ISPLIT, WORK, IWORK,
                    264:      $                   INFO )
                    265: *
1.9     ! bertrand  266: *  -- LAPACK computational routine (version 3.4.0) --
1.1       bertrand  267: *  -- LAPACK is a software package provided by Univ. of Tennessee,    --
                    268: *  -- Univ. of California Berkeley, Univ. of Colorado Denver and NAG Ltd..--
1.9     ! bertrand  269: *     November 2011
1.1       bertrand  270: *
                    271: *     .. Scalar Arguments ..
                    272:       CHARACTER          ORDER, RANGE
                    273:       INTEGER            IL, INFO, IU, M, N, NSPLIT
                    274:       DOUBLE PRECISION   ABSTOL, VL, VU
                    275: *     ..
                    276: *     .. Array Arguments ..
                    277:       INTEGER            IBLOCK( * ), ISPLIT( * ), IWORK( * )
                    278:       DOUBLE PRECISION   D( * ), E( * ), W( * ), WORK( * )
                    279: *     ..
                    280: *
                    281: *  =====================================================================
                    282: *
                    283: *     .. Parameters ..
                    284:       DOUBLE PRECISION   ZERO, ONE, TWO, HALF
                    285:       PARAMETER          ( ZERO = 0.0D0, ONE = 1.0D0, TWO = 2.0D0,
                    286:      $                   HALF = 1.0D0 / TWO )
                    287:       DOUBLE PRECISION   FUDGE, RELFAC
                    288:       PARAMETER          ( FUDGE = 2.1D0, RELFAC = 2.0D0 )
                    289: *     ..
                    290: *     .. Local Scalars ..
                    291:       LOGICAL            NCNVRG, TOOFEW
                    292:       INTEGER            IB, IBEGIN, IDISCL, IDISCU, IE, IEND, IINFO,
                    293:      $                   IM, IN, IOFF, IORDER, IOUT, IRANGE, ITMAX,
                    294:      $                   ITMP1, IW, IWOFF, J, JB, JDISC, JE, NB, NWL,
                    295:      $                   NWU
                    296:       DOUBLE PRECISION   ATOLI, BNORM, GL, GU, PIVMIN, RTOLI, SAFEMN,
                    297:      $                   TMP1, TMP2, TNORM, ULP, WKILL, WL, WLU, WU, WUL
                    298: *     ..
                    299: *     .. Local Arrays ..
                    300:       INTEGER            IDUMMA( 1 )
                    301: *     ..
                    302: *     .. External Functions ..
                    303:       LOGICAL            LSAME
                    304:       INTEGER            ILAENV
                    305:       DOUBLE PRECISION   DLAMCH
                    306:       EXTERNAL           LSAME, ILAENV, DLAMCH
                    307: *     ..
                    308: *     .. External Subroutines ..
                    309:       EXTERNAL           DLAEBZ, XERBLA
                    310: *     ..
                    311: *     .. Intrinsic Functions ..
                    312:       INTRINSIC          ABS, INT, LOG, MAX, MIN, SQRT
                    313: *     ..
                    314: *     .. Executable Statements ..
                    315: *
                    316:       INFO = 0
                    317: *
                    318: *     Decode RANGE
                    319: *
                    320:       IF( LSAME( RANGE, 'A' ) ) THEN
                    321:          IRANGE = 1
                    322:       ELSE IF( LSAME( RANGE, 'V' ) ) THEN
                    323:          IRANGE = 2
                    324:       ELSE IF( LSAME( RANGE, 'I' ) ) THEN
                    325:          IRANGE = 3
                    326:       ELSE
                    327:          IRANGE = 0
                    328:       END IF
                    329: *
                    330: *     Decode ORDER
                    331: *
                    332:       IF( LSAME( ORDER, 'B' ) ) THEN
                    333:          IORDER = 2
                    334:       ELSE IF( LSAME( ORDER, 'E' ) ) THEN
                    335:          IORDER = 1
                    336:       ELSE
                    337:          IORDER = 0
                    338:       END IF
                    339: *
                    340: *     Check for Errors
                    341: *
                    342:       IF( IRANGE.LE.0 ) THEN
                    343:          INFO = -1
                    344:       ELSE IF( IORDER.LE.0 ) THEN
                    345:          INFO = -2
                    346:       ELSE IF( N.LT.0 ) THEN
                    347:          INFO = -3
                    348:       ELSE IF( IRANGE.EQ.2 ) THEN
                    349:          IF( VL.GE.VU )
                    350:      $      INFO = -5
                    351:       ELSE IF( IRANGE.EQ.3 .AND. ( IL.LT.1 .OR. IL.GT.MAX( 1, N ) ) )
                    352:      $          THEN
                    353:          INFO = -6
                    354:       ELSE IF( IRANGE.EQ.3 .AND. ( IU.LT.MIN( N, IL ) .OR. IU.GT.N ) )
                    355:      $          THEN
                    356:          INFO = -7
                    357:       END IF
                    358: *
                    359:       IF( INFO.NE.0 ) THEN
                    360:          CALL XERBLA( 'DSTEBZ', -INFO )
                    361:          RETURN
                    362:       END IF
                    363: *
                    364: *     Initialize error flags
                    365: *
                    366:       INFO = 0
                    367:       NCNVRG = .FALSE.
                    368:       TOOFEW = .FALSE.
                    369: *
                    370: *     Quick return if possible
                    371: *
                    372:       M = 0
                    373:       IF( N.EQ.0 )
                    374:      $   RETURN
                    375: *
                    376: *     Simplifications:
                    377: *
                    378:       IF( IRANGE.EQ.3 .AND. IL.EQ.1 .AND. IU.EQ.N )
                    379:      $   IRANGE = 1
                    380: *
                    381: *     Get machine constants
                    382: *     NB is the minimum vector length for vector bisection, or 0
                    383: *     if only scalar is to be done.
                    384: *
                    385:       SAFEMN = DLAMCH( 'S' )
                    386:       ULP = DLAMCH( 'P' )
                    387:       RTOLI = ULP*RELFAC
                    388:       NB = ILAENV( 1, 'DSTEBZ', ' ', N, -1, -1, -1 )
                    389:       IF( NB.LE.1 )
                    390:      $   NB = 0
                    391: *
                    392: *     Special Case when N=1
                    393: *
                    394:       IF( N.EQ.1 ) THEN
                    395:          NSPLIT = 1
                    396:          ISPLIT( 1 ) = 1
                    397:          IF( IRANGE.EQ.2 .AND. ( VL.GE.D( 1 ) .OR. VU.LT.D( 1 ) ) ) THEN
                    398:             M = 0
                    399:          ELSE
                    400:             W( 1 ) = D( 1 )
                    401:             IBLOCK( 1 ) = 1
                    402:             M = 1
                    403:          END IF
                    404:          RETURN
                    405:       END IF
                    406: *
                    407: *     Compute Splitting Points
                    408: *
                    409:       NSPLIT = 1
                    410:       WORK( N ) = ZERO
                    411:       PIVMIN = ONE
                    412: *
                    413:       DO 10 J = 2, N
                    414:          TMP1 = E( J-1 )**2
                    415:          IF( ABS( D( J )*D( J-1 ) )*ULP**2+SAFEMN.GT.TMP1 ) THEN
                    416:             ISPLIT( NSPLIT ) = J - 1
                    417:             NSPLIT = NSPLIT + 1
                    418:             WORK( J-1 ) = ZERO
                    419:          ELSE
                    420:             WORK( J-1 ) = TMP1
                    421:             PIVMIN = MAX( PIVMIN, TMP1 )
                    422:          END IF
                    423:    10 CONTINUE
                    424:       ISPLIT( NSPLIT ) = N
                    425:       PIVMIN = PIVMIN*SAFEMN
                    426: *
                    427: *     Compute Interval and ATOLI
                    428: *
                    429:       IF( IRANGE.EQ.3 ) THEN
                    430: *
                    431: *        RANGE='I': Compute the interval containing eigenvalues
                    432: *                   IL through IU.
                    433: *
                    434: *        Compute Gershgorin interval for entire (split) matrix
                    435: *        and use it as the initial interval
                    436: *
                    437:          GU = D( 1 )
                    438:          GL = D( 1 )
                    439:          TMP1 = ZERO
                    440: *
                    441:          DO 20 J = 1, N - 1
                    442:             TMP2 = SQRT( WORK( J ) )
                    443:             GU = MAX( GU, D( J )+TMP1+TMP2 )
                    444:             GL = MIN( GL, D( J )-TMP1-TMP2 )
                    445:             TMP1 = TMP2
                    446:    20    CONTINUE
                    447: *
                    448:          GU = MAX( GU, D( N )+TMP1 )
                    449:          GL = MIN( GL, D( N )-TMP1 )
                    450:          TNORM = MAX( ABS( GL ), ABS( GU ) )
                    451:          GL = GL - FUDGE*TNORM*ULP*N - FUDGE*TWO*PIVMIN
                    452:          GU = GU + FUDGE*TNORM*ULP*N + FUDGE*PIVMIN
                    453: *
                    454: *        Compute Iteration parameters
                    455: *
                    456:          ITMAX = INT( ( LOG( TNORM+PIVMIN )-LOG( PIVMIN ) ) /
                    457:      $           LOG( TWO ) ) + 2
                    458:          IF( ABSTOL.LE.ZERO ) THEN
                    459:             ATOLI = ULP*TNORM
                    460:          ELSE
                    461:             ATOLI = ABSTOL
                    462:          END IF
                    463: *
                    464:          WORK( N+1 ) = GL
                    465:          WORK( N+2 ) = GL
                    466:          WORK( N+3 ) = GU
                    467:          WORK( N+4 ) = GU
                    468:          WORK( N+5 ) = GL
                    469:          WORK( N+6 ) = GU
                    470:          IWORK( 1 ) = -1
                    471:          IWORK( 2 ) = -1
                    472:          IWORK( 3 ) = N + 1
                    473:          IWORK( 4 ) = N + 1
                    474:          IWORK( 5 ) = IL - 1
                    475:          IWORK( 6 ) = IU
                    476: *
                    477:          CALL DLAEBZ( 3, ITMAX, N, 2, 2, NB, ATOLI, RTOLI, PIVMIN, D, E,
                    478:      $                WORK, IWORK( 5 ), WORK( N+1 ), WORK( N+5 ), IOUT,
                    479:      $                IWORK, W, IBLOCK, IINFO )
                    480: *
                    481:          IF( IWORK( 6 ).EQ.IU ) THEN
                    482:             WL = WORK( N+1 )
                    483:             WLU = WORK( N+3 )
                    484:             NWL = IWORK( 1 )
                    485:             WU = WORK( N+4 )
                    486:             WUL = WORK( N+2 )
                    487:             NWU = IWORK( 4 )
                    488:          ELSE
                    489:             WL = WORK( N+2 )
                    490:             WLU = WORK( N+4 )
                    491:             NWL = IWORK( 2 )
                    492:             WU = WORK( N+3 )
                    493:             WUL = WORK( N+1 )
                    494:             NWU = IWORK( 3 )
                    495:          END IF
                    496: *
                    497:          IF( NWL.LT.0 .OR. NWL.GE.N .OR. NWU.LT.1 .OR. NWU.GT.N ) THEN
                    498:             INFO = 4
                    499:             RETURN
                    500:          END IF
                    501:       ELSE
                    502: *
                    503: *        RANGE='A' or 'V' -- Set ATOLI
                    504: *
                    505:          TNORM = MAX( ABS( D( 1 ) )+ABS( E( 1 ) ),
                    506:      $           ABS( D( N ) )+ABS( E( N-1 ) ) )
                    507: *
                    508:          DO 30 J = 2, N - 1
                    509:             TNORM = MAX( TNORM, ABS( D( J ) )+ABS( E( J-1 ) )+
                    510:      $              ABS( E( J ) ) )
                    511:    30    CONTINUE
                    512: *
                    513:          IF( ABSTOL.LE.ZERO ) THEN
                    514:             ATOLI = ULP*TNORM
                    515:          ELSE
                    516:             ATOLI = ABSTOL
                    517:          END IF
                    518: *
                    519:          IF( IRANGE.EQ.2 ) THEN
                    520:             WL = VL
                    521:             WU = VU
                    522:          ELSE
                    523:             WL = ZERO
                    524:             WU = ZERO
                    525:          END IF
                    526:       END IF
                    527: *
                    528: *     Find Eigenvalues -- Loop Over Blocks and recompute NWL and NWU.
                    529: *     NWL accumulates the number of eigenvalues .le. WL,
                    530: *     NWU accumulates the number of eigenvalues .le. WU
                    531: *
                    532:       M = 0
                    533:       IEND = 0
                    534:       INFO = 0
                    535:       NWL = 0
                    536:       NWU = 0
                    537: *
                    538:       DO 70 JB = 1, NSPLIT
                    539:          IOFF = IEND
                    540:          IBEGIN = IOFF + 1
                    541:          IEND = ISPLIT( JB )
                    542:          IN = IEND - IOFF
                    543: *
                    544:          IF( IN.EQ.1 ) THEN
                    545: *
                    546: *           Special Case -- IN=1
                    547: *
                    548:             IF( IRANGE.EQ.1 .OR. WL.GE.D( IBEGIN )-PIVMIN )
                    549:      $         NWL = NWL + 1
                    550:             IF( IRANGE.EQ.1 .OR. WU.GE.D( IBEGIN )-PIVMIN )
                    551:      $         NWU = NWU + 1
                    552:             IF( IRANGE.EQ.1 .OR. ( WL.LT.D( IBEGIN )-PIVMIN .AND. WU.GE.
                    553:      $          D( IBEGIN )-PIVMIN ) ) THEN
                    554:                M = M + 1
                    555:                W( M ) = D( IBEGIN )
                    556:                IBLOCK( M ) = JB
                    557:             END IF
                    558:          ELSE
                    559: *
                    560: *           General Case -- IN > 1
                    561: *
                    562: *           Compute Gershgorin Interval
                    563: *           and use it as the initial interval
                    564: *
                    565:             GU = D( IBEGIN )
                    566:             GL = D( IBEGIN )
                    567:             TMP1 = ZERO
                    568: *
                    569:             DO 40 J = IBEGIN, IEND - 1
                    570:                TMP2 = ABS( E( J ) )
                    571:                GU = MAX( GU, D( J )+TMP1+TMP2 )
                    572:                GL = MIN( GL, D( J )-TMP1-TMP2 )
                    573:                TMP1 = TMP2
                    574:    40       CONTINUE
                    575: *
                    576:             GU = MAX( GU, D( IEND )+TMP1 )
                    577:             GL = MIN( GL, D( IEND )-TMP1 )
                    578:             BNORM = MAX( ABS( GL ), ABS( GU ) )
                    579:             GL = GL - FUDGE*BNORM*ULP*IN - FUDGE*PIVMIN
                    580:             GU = GU + FUDGE*BNORM*ULP*IN + FUDGE*PIVMIN
                    581: *
                    582: *           Compute ATOLI for the current submatrix
                    583: *
                    584:             IF( ABSTOL.LE.ZERO ) THEN
                    585:                ATOLI = ULP*MAX( ABS( GL ), ABS( GU ) )
                    586:             ELSE
                    587:                ATOLI = ABSTOL
                    588:             END IF
                    589: *
                    590:             IF( IRANGE.GT.1 ) THEN
                    591:                IF( GU.LT.WL ) THEN
                    592:                   NWL = NWL + IN
                    593:                   NWU = NWU + IN
                    594:                   GO TO 70
                    595:                END IF
                    596:                GL = MAX( GL, WL )
                    597:                GU = MIN( GU, WU )
                    598:                IF( GL.GE.GU )
                    599:      $            GO TO 70
                    600:             END IF
                    601: *
                    602: *           Set Up Initial Interval
                    603: *
                    604:             WORK( N+1 ) = GL
                    605:             WORK( N+IN+1 ) = GU
                    606:             CALL DLAEBZ( 1, 0, IN, IN, 1, NB, ATOLI, RTOLI, PIVMIN,
                    607:      $                   D( IBEGIN ), E( IBEGIN ), WORK( IBEGIN ),
                    608:      $                   IDUMMA, WORK( N+1 ), WORK( N+2*IN+1 ), IM,
                    609:      $                   IWORK, W( M+1 ), IBLOCK( M+1 ), IINFO )
                    610: *
                    611:             NWL = NWL + IWORK( 1 )
                    612:             NWU = NWU + IWORK( IN+1 )
                    613:             IWOFF = M - IWORK( 1 )
                    614: *
                    615: *           Compute Eigenvalues
                    616: *
                    617:             ITMAX = INT( ( LOG( GU-GL+PIVMIN )-LOG( PIVMIN ) ) /
                    618:      $              LOG( TWO ) ) + 2
                    619:             CALL DLAEBZ( 2, ITMAX, IN, IN, 1, NB, ATOLI, RTOLI, PIVMIN,
                    620:      $                   D( IBEGIN ), E( IBEGIN ), WORK( IBEGIN ),
                    621:      $                   IDUMMA, WORK( N+1 ), WORK( N+2*IN+1 ), IOUT,
                    622:      $                   IWORK, W( M+1 ), IBLOCK( M+1 ), IINFO )
                    623: *
                    624: *           Copy Eigenvalues Into W and IBLOCK
                    625: *           Use -JB for block number for unconverged eigenvalues.
                    626: *
                    627:             DO 60 J = 1, IOUT
                    628:                TMP1 = HALF*( WORK( J+N )+WORK( J+IN+N ) )
                    629: *
                    630: *              Flag non-convergence.
                    631: *
                    632:                IF( J.GT.IOUT-IINFO ) THEN
                    633:                   NCNVRG = .TRUE.
                    634:                   IB = -JB
                    635:                ELSE
                    636:                   IB = JB
                    637:                END IF
                    638:                DO 50 JE = IWORK( J ) + 1 + IWOFF,
                    639:      $                 IWORK( J+IN ) + IWOFF
                    640:                   W( JE ) = TMP1
                    641:                   IBLOCK( JE ) = IB
                    642:    50          CONTINUE
                    643:    60       CONTINUE
                    644: *
                    645:             M = M + IM
                    646:          END IF
                    647:    70 CONTINUE
                    648: *
                    649: *     If RANGE='I', then (WL,WU) contains eigenvalues NWL+1,...,NWU
                    650: *     If NWL+1 < IL or NWU > IU, discard extra eigenvalues.
                    651: *
                    652:       IF( IRANGE.EQ.3 ) THEN
                    653:          IM = 0
                    654:          IDISCL = IL - 1 - NWL
                    655:          IDISCU = NWU - IU
                    656: *
                    657:          IF( IDISCL.GT.0 .OR. IDISCU.GT.0 ) THEN
                    658:             DO 80 JE = 1, M
                    659:                IF( W( JE ).LE.WLU .AND. IDISCL.GT.0 ) THEN
                    660:                   IDISCL = IDISCL - 1
                    661:                ELSE IF( W( JE ).GE.WUL .AND. IDISCU.GT.0 ) THEN
                    662:                   IDISCU = IDISCU - 1
                    663:                ELSE
                    664:                   IM = IM + 1
                    665:                   W( IM ) = W( JE )
                    666:                   IBLOCK( IM ) = IBLOCK( JE )
                    667:                END IF
                    668:    80       CONTINUE
                    669:             M = IM
                    670:          END IF
                    671:          IF( IDISCL.GT.0 .OR. IDISCU.GT.0 ) THEN
                    672: *
                    673: *           Code to deal with effects of bad arithmetic:
                    674: *           Some low eigenvalues to be discarded are not in (WL,WLU],
                    675: *           or high eigenvalues to be discarded are not in (WUL,WU]
                    676: *           so just kill off the smallest IDISCL/largest IDISCU
                    677: *           eigenvalues, by simply finding the smallest/largest
                    678: *           eigenvalue(s).
                    679: *
                    680: *           (If N(w) is monotone non-decreasing, this should never
                    681: *               happen.)
                    682: *
                    683:             IF( IDISCL.GT.0 ) THEN
                    684:                WKILL = WU
                    685:                DO 100 JDISC = 1, IDISCL
                    686:                   IW = 0
                    687:                   DO 90 JE = 1, M
                    688:                      IF( IBLOCK( JE ).NE.0 .AND.
                    689:      $                   ( W( JE ).LT.WKILL .OR. IW.EQ.0 ) ) THEN
                    690:                         IW = JE
                    691:                         WKILL = W( JE )
                    692:                      END IF
                    693:    90             CONTINUE
                    694:                   IBLOCK( IW ) = 0
                    695:   100          CONTINUE
                    696:             END IF
                    697:             IF( IDISCU.GT.0 ) THEN
                    698: *
                    699:                WKILL = WL
                    700:                DO 120 JDISC = 1, IDISCU
                    701:                   IW = 0
                    702:                   DO 110 JE = 1, M
                    703:                      IF( IBLOCK( JE ).NE.0 .AND.
                    704:      $                   ( W( JE ).GT.WKILL .OR. IW.EQ.0 ) ) THEN
                    705:                         IW = JE
                    706:                         WKILL = W( JE )
                    707:                      END IF
                    708:   110             CONTINUE
                    709:                   IBLOCK( IW ) = 0
                    710:   120          CONTINUE
                    711:             END IF
                    712:             IM = 0
                    713:             DO 130 JE = 1, M
                    714:                IF( IBLOCK( JE ).NE.0 ) THEN
                    715:                   IM = IM + 1
                    716:                   W( IM ) = W( JE )
                    717:                   IBLOCK( IM ) = IBLOCK( JE )
                    718:                END IF
                    719:   130       CONTINUE
                    720:             M = IM
                    721:          END IF
                    722:          IF( IDISCL.LT.0 .OR. IDISCU.LT.0 ) THEN
                    723:             TOOFEW = .TRUE.
                    724:          END IF
                    725:       END IF
                    726: *
                    727: *     If ORDER='B', do nothing -- the eigenvalues are already sorted
                    728: *        by block.
                    729: *     If ORDER='E', sort the eigenvalues from smallest to largest
                    730: *
                    731:       IF( IORDER.EQ.1 .AND. NSPLIT.GT.1 ) THEN
                    732:          DO 150 JE = 1, M - 1
                    733:             IE = 0
                    734:             TMP1 = W( JE )
                    735:             DO 140 J = JE + 1, M
                    736:                IF( W( J ).LT.TMP1 ) THEN
                    737:                   IE = J
                    738:                   TMP1 = W( J )
                    739:                END IF
                    740:   140       CONTINUE
                    741: *
                    742:             IF( IE.NE.0 ) THEN
                    743:                ITMP1 = IBLOCK( IE )
                    744:                W( IE ) = W( JE )
                    745:                IBLOCK( IE ) = IBLOCK( JE )
                    746:                W( JE ) = TMP1
                    747:                IBLOCK( JE ) = ITMP1
                    748:             END IF
                    749:   150    CONTINUE
                    750:       END IF
                    751: *
                    752:       INFO = 0
                    753:       IF( NCNVRG )
                    754:      $   INFO = INFO + 1
                    755:       IF( TOOFEW )
                    756:      $   INFO = INFO + 2
                    757:       RETURN
                    758: *
                    759: *     End of DSTEBZ
                    760: *
                    761:       END

CVSweb interface <joel.bertrand@systella.fr>