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

1.9     ! bertrand    1: *> \brief \b DLASQ3
        !             2: *
        !             3: *  =========== DOCUMENTATION ===========
        !             4: *
        !             5: * Online html documentation available at 
        !             6: *            http://www.netlib.org/lapack/explore-html/ 
        !             7: *
        !             8: *> \htmlonly
        !             9: *> Download DLASQ3 + dependencies 
        !            10: *> <a href="http://www.netlib.org/cgi-bin/netlibfiles.tgz?format=tgz&filename=/lapack/lapack_routine/dlasq3.f"> 
        !            11: *> [TGZ]</a> 
        !            12: *> <a href="http://www.netlib.org/cgi-bin/netlibfiles.zip?format=zip&filename=/lapack/lapack_routine/dlasq3.f"> 
        !            13: *> [ZIP]</a> 
        !            14: *> <a href="http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/dlasq3.f"> 
        !            15: *> [TXT]</a>
        !            16: *> \endhtmlonly 
        !            17: *
        !            18: *  Definition:
        !            19: *  ===========
        !            20: *
        !            21: *       SUBROUTINE DLASQ3( I0, N0, Z, PP, DMIN, SIGMA, DESIG, QMAX, NFAIL,
        !            22: *                          ITER, NDIV, IEEE, TTYPE, DMIN1, DMIN2, DN, DN1,
        !            23: *                          DN2, G, TAU )
        !            24: * 
        !            25: *       .. Scalar Arguments ..
        !            26: *       LOGICAL            IEEE
        !            27: *       INTEGER            I0, ITER, N0, NDIV, NFAIL, PP
        !            28: *       DOUBLE PRECISION   DESIG, DMIN, DMIN1, DMIN2, DN, DN1, DN2, G,
        !            29: *      $                   QMAX, SIGMA, TAU
        !            30: *       ..
        !            31: *       .. Array Arguments ..
        !            32: *       DOUBLE PRECISION   Z( * )
        !            33: *       ..
        !            34: *  
        !            35: *
        !            36: *> \par Purpose:
        !            37: *  =============
        !            38: *>
        !            39: *> \verbatim
        !            40: *>
        !            41: *> DLASQ3 checks for deflation, computes a shift (TAU) and calls dqds.
        !            42: *> In case of failure it changes shifts, and tries again until output
        !            43: *> is positive.
        !            44: *> \endverbatim
        !            45: *
        !            46: *  Arguments:
        !            47: *  ==========
        !            48: *
        !            49: *> \param[in] I0
        !            50: *> \verbatim
        !            51: *>          I0 is INTEGER
        !            52: *>         First index.
        !            53: *> \endverbatim
        !            54: *>
        !            55: *> \param[in,out] N0
        !            56: *> \verbatim
        !            57: *>          N0 is INTEGER
        !            58: *>         Last index.
        !            59: *> \endverbatim
        !            60: *>
        !            61: *> \param[in] Z
        !            62: *> \verbatim
        !            63: *>          Z is DOUBLE PRECISION array, dimension ( 4*N )
        !            64: *>         Z holds the qd array.
        !            65: *> \endverbatim
        !            66: *>
        !            67: *> \param[in,out] PP
        !            68: *> \verbatim
        !            69: *>          PP is INTEGER
        !            70: *>         PP=0 for ping, PP=1 for pong.
        !            71: *>         PP=2 indicates that flipping was applied to the Z array   
        !            72: *>         and that the initial tests for deflation should not be 
        !            73: *>         performed.
        !            74: *> \endverbatim
        !            75: *>
        !            76: *> \param[out] DMIN
        !            77: *> \verbatim
        !            78: *>          DMIN is DOUBLE PRECISION
        !            79: *>         Minimum value of d.
        !            80: *> \endverbatim
        !            81: *>
        !            82: *> \param[out] SIGMA
        !            83: *> \verbatim
        !            84: *>          SIGMA is DOUBLE PRECISION
        !            85: *>         Sum of shifts used in current segment.
        !            86: *> \endverbatim
        !            87: *>
        !            88: *> \param[in,out] DESIG
        !            89: *> \verbatim
        !            90: *>          DESIG is DOUBLE PRECISION
        !            91: *>         Lower order part of SIGMA
        !            92: *> \endverbatim
        !            93: *>
        !            94: *> \param[in] QMAX
        !            95: *> \verbatim
        !            96: *>          QMAX is DOUBLE PRECISION
        !            97: *>         Maximum value of q.
        !            98: *> \endverbatim
        !            99: *>
        !           100: *> \param[out] NFAIL
        !           101: *> \verbatim
        !           102: *>          NFAIL is INTEGER
        !           103: *>         Number of times shift was too big.
        !           104: *> \endverbatim
        !           105: *>
        !           106: *> \param[out] ITER
        !           107: *> \verbatim
        !           108: *>          ITER is INTEGER
        !           109: *>         Number of iterations.
        !           110: *> \endverbatim
        !           111: *>
        !           112: *> \param[out] NDIV
        !           113: *> \verbatim
        !           114: *>          NDIV is INTEGER
        !           115: *>         Number of divisions.
        !           116: *> \endverbatim
        !           117: *>
        !           118: *> \param[in] IEEE
        !           119: *> \verbatim
        !           120: *>          IEEE is LOGICAL
        !           121: *>         Flag for IEEE or non IEEE arithmetic (passed to DLASQ5).
        !           122: *> \endverbatim
        !           123: *>
        !           124: *> \param[in,out] TTYPE
        !           125: *> \verbatim
        !           126: *>          TTYPE is INTEGER
        !           127: *>         Shift type.
        !           128: *> \endverbatim
        !           129: *>
        !           130: *> \param[in,out] DMIN1
        !           131: *> \verbatim
        !           132: *>          DMIN1 is DOUBLE PRECISION
        !           133: *> \endverbatim
        !           134: *>
        !           135: *> \param[in,out] DMIN2
        !           136: *> \verbatim
        !           137: *>          DMIN2 is DOUBLE PRECISION
        !           138: *> \endverbatim
        !           139: *>
        !           140: *> \param[in,out] DN
        !           141: *> \verbatim
        !           142: *>          DN is DOUBLE PRECISION
        !           143: *> \endverbatim
        !           144: *>
        !           145: *> \param[in,out] DN1
        !           146: *> \verbatim
        !           147: *>          DN1 is DOUBLE PRECISION
        !           148: *> \endverbatim
        !           149: *>
        !           150: *> \param[in,out] DN2
        !           151: *> \verbatim
        !           152: *>          DN2 is DOUBLE PRECISION
        !           153: *> \endverbatim
        !           154: *>
        !           155: *> \param[in,out] G
        !           156: *> \verbatim
        !           157: *>          G is DOUBLE PRECISION
        !           158: *> \endverbatim
        !           159: *>
        !           160: *> \param[in,out] TAU
        !           161: *> \verbatim
        !           162: *>          TAU is DOUBLE PRECISION
        !           163: *>
        !           164: *>         These are passed as arguments in order to save their values
        !           165: *>         between calls to DLASQ3.
        !           166: *> \endverbatim
        !           167: *
        !           168: *  Authors:
        !           169: *  ========
        !           170: *
        !           171: *> \author Univ. of Tennessee 
        !           172: *> \author Univ. of California Berkeley 
        !           173: *> \author Univ. of Colorado Denver 
        !           174: *> \author NAG Ltd. 
        !           175: *
        !           176: *> \date November 2011
        !           177: *
        !           178: *> \ingroup auxOTHERcomputational
        !           179: *
        !           180: *  =====================================================================
1.1       bertrand  181:       SUBROUTINE DLASQ3( I0, N0, Z, PP, DMIN, SIGMA, DESIG, QMAX, NFAIL,
                    182:      $                   ITER, NDIV, IEEE, TTYPE, DMIN1, DMIN2, DN, DN1,
                    183:      $                   DN2, G, TAU )
                    184: *
1.9     ! bertrand  185: *  -- LAPACK computational routine (version 3.4.0) --
1.1       bertrand  186: *  -- LAPACK is a software package provided by Univ. of Tennessee,    --
                    187: *  -- Univ. of California Berkeley, Univ. of Colorado Denver and NAG Ltd..--
1.9     ! bertrand  188: *     November 2011
1.1       bertrand  189: *
                    190: *     .. Scalar Arguments ..
                    191:       LOGICAL            IEEE
                    192:       INTEGER            I0, ITER, N0, NDIV, NFAIL, PP
                    193:       DOUBLE PRECISION   DESIG, DMIN, DMIN1, DMIN2, DN, DN1, DN2, G,
                    194:      $                   QMAX, SIGMA, TAU
                    195: *     ..
                    196: *     .. Array Arguments ..
                    197:       DOUBLE PRECISION   Z( * )
                    198: *     ..
                    199: *
                    200: *  =====================================================================
                    201: *
                    202: *     .. Parameters ..
                    203:       DOUBLE PRECISION   CBIAS
                    204:       PARAMETER          ( CBIAS = 1.50D0 )
                    205:       DOUBLE PRECISION   ZERO, QURTR, HALF, ONE, TWO, HUNDRD
                    206:       PARAMETER          ( ZERO = 0.0D0, QURTR = 0.250D0, HALF = 0.5D0,
                    207:      $                     ONE = 1.0D0, TWO = 2.0D0, HUNDRD = 100.0D0 )
                    208: *     ..
                    209: *     .. Local Scalars ..
                    210:       INTEGER            IPN4, J4, N0IN, NN, TTYPE
                    211:       DOUBLE PRECISION   EPS, S, T, TEMP, TOL, TOL2
                    212: *     ..
                    213: *     .. External Subroutines ..
                    214:       EXTERNAL           DLASQ4, DLASQ5, DLASQ6
                    215: *     ..
                    216: *     .. External Function ..
                    217:       DOUBLE PRECISION   DLAMCH
                    218:       LOGICAL            DISNAN
                    219:       EXTERNAL           DISNAN, DLAMCH
                    220: *     ..
                    221: *     .. Intrinsic Functions ..
                    222:       INTRINSIC          ABS, MAX, MIN, SQRT
                    223: *     ..
                    224: *     .. Executable Statements ..
                    225: *
                    226:       N0IN = N0
                    227:       EPS = DLAMCH( 'Precision' )
                    228:       TOL = EPS*HUNDRD
                    229:       TOL2 = TOL**2
                    230: *
                    231: *     Check for deflation.
                    232: *
                    233:    10 CONTINUE
                    234: *
                    235:       IF( N0.LT.I0 )
                    236:      $   RETURN
                    237:       IF( N0.EQ.I0 )
                    238:      $   GO TO 20
                    239:       NN = 4*N0 + PP
                    240:       IF( N0.EQ.( I0+1 ) )
                    241:      $   GO TO 40
                    242: *
                    243: *     Check whether E(N0-1) is negligible, 1 eigenvalue.
                    244: *
                    245:       IF( Z( NN-5 ).GT.TOL2*( SIGMA+Z( NN-3 ) ) .AND.
                    246:      $    Z( NN-2*PP-4 ).GT.TOL2*Z( NN-7 ) )
                    247:      $   GO TO 30
                    248: *
                    249:    20 CONTINUE
                    250: *
                    251:       Z( 4*N0-3 ) = Z( 4*N0+PP-3 ) + SIGMA
                    252:       N0 = N0 - 1
                    253:       GO TO 10
                    254: *
                    255: *     Check  whether E(N0-2) is negligible, 2 eigenvalues.
                    256: *
                    257:    30 CONTINUE
                    258: *
                    259:       IF( Z( NN-9 ).GT.TOL2*SIGMA .AND.
                    260:      $    Z( NN-2*PP-8 ).GT.TOL2*Z( NN-11 ) )
                    261:      $   GO TO 50
                    262: *
                    263:    40 CONTINUE
                    264: *
                    265:       IF( Z( NN-3 ).GT.Z( NN-7 ) ) THEN
                    266:          S = Z( NN-3 )
                    267:          Z( NN-3 ) = Z( NN-7 )
                    268:          Z( NN-7 ) = S
                    269:       END IF
                    270:       IF( Z( NN-5 ).GT.Z( NN-3 )*TOL2 ) THEN
                    271:          T = HALF*( ( Z( NN-7 )-Z( NN-3 ) )+Z( NN-5 ) )
                    272:          S = Z( NN-3 )*( Z( NN-5 ) / T )
                    273:          IF( S.LE.T ) THEN
                    274:             S = Z( NN-3 )*( Z( NN-5 ) /
                    275:      $          ( T*( ONE+SQRT( ONE+S / T ) ) ) )
                    276:          ELSE
                    277:             S = Z( NN-3 )*( Z( NN-5 ) / ( T+SQRT( T )*SQRT( T+S ) ) )
                    278:          END IF
                    279:          T = Z( NN-7 ) + ( S+Z( NN-5 ) )
                    280:          Z( NN-3 ) = Z( NN-3 )*( Z( NN-7 ) / T )
                    281:          Z( NN-7 ) = T
                    282:       END IF
                    283:       Z( 4*N0-7 ) = Z( NN-7 ) + SIGMA
                    284:       Z( 4*N0-3 ) = Z( NN-3 ) + SIGMA
                    285:       N0 = N0 - 2
                    286:       GO TO 10
                    287: *
                    288:    50 CONTINUE
                    289:       IF( PP.EQ.2 ) 
                    290:      $   PP = 0
                    291: *
                    292: *     Reverse the qd-array, if warranted.
                    293: *
                    294:       IF( DMIN.LE.ZERO .OR. N0.LT.N0IN ) THEN
                    295:          IF( CBIAS*Z( 4*I0+PP-3 ).LT.Z( 4*N0+PP-3 ) ) THEN
                    296:             IPN4 = 4*( I0+N0 )
                    297:             DO 60 J4 = 4*I0, 2*( I0+N0-1 ), 4
                    298:                TEMP = Z( J4-3 )
                    299:                Z( J4-3 ) = Z( IPN4-J4-3 )
                    300:                Z( IPN4-J4-3 ) = TEMP
                    301:                TEMP = Z( J4-2 )
                    302:                Z( J4-2 ) = Z( IPN4-J4-2 )
                    303:                Z( IPN4-J4-2 ) = TEMP
                    304:                TEMP = Z( J4-1 )
                    305:                Z( J4-1 ) = Z( IPN4-J4-5 )
                    306:                Z( IPN4-J4-5 ) = TEMP
                    307:                TEMP = Z( J4 )
                    308:                Z( J4 ) = Z( IPN4-J4-4 )
                    309:                Z( IPN4-J4-4 ) = TEMP
                    310:    60       CONTINUE
                    311:             IF( N0-I0.LE.4 ) THEN
                    312:                Z( 4*N0+PP-1 ) = Z( 4*I0+PP-1 )
                    313:                Z( 4*N0-PP ) = Z( 4*I0-PP )
                    314:             END IF
                    315:             DMIN2 = MIN( DMIN2, Z( 4*N0+PP-1 ) )
                    316:             Z( 4*N0+PP-1 ) = MIN( Z( 4*N0+PP-1 ), Z( 4*I0+PP-1 ),
                    317:      $                            Z( 4*I0+PP+3 ) )
                    318:             Z( 4*N0-PP ) = MIN( Z( 4*N0-PP ), Z( 4*I0-PP ),
                    319:      $                          Z( 4*I0-PP+4 ) )
                    320:             QMAX = MAX( QMAX, Z( 4*I0+PP-3 ), Z( 4*I0+PP+1 ) )
                    321:             DMIN = -ZERO
                    322:          END IF
                    323:       END IF
                    324: *
                    325: *     Choose a shift.
                    326: *
                    327:       CALL DLASQ4( I0, N0, Z, PP, N0IN, DMIN, DMIN1, DMIN2, DN, DN1,
                    328:      $             DN2, TAU, TTYPE, G )
                    329: *
                    330: *     Call dqds until DMIN > 0.
                    331: *
                    332:    70 CONTINUE
                    333: *
                    334:       CALL DLASQ5( I0, N0, Z, PP, TAU, DMIN, DMIN1, DMIN2, DN,
                    335:      $             DN1, DN2, IEEE )
                    336: *
                    337:       NDIV = NDIV + ( N0-I0+2 )
                    338:       ITER = ITER + 1
                    339: *
                    340: *     Check status.
                    341: *
                    342:       IF( DMIN.GE.ZERO .AND. DMIN1.GT.ZERO ) THEN
                    343: *
                    344: *        Success.
                    345: *
                    346:          GO TO 90
                    347: *
                    348:       ELSE IF( DMIN.LT.ZERO .AND. DMIN1.GT.ZERO .AND. 
                    349:      $         Z( 4*( N0-1 )-PP ).LT.TOL*( SIGMA+DN1 ) .AND.
                    350:      $         ABS( DN ).LT.TOL*SIGMA ) THEN
                    351: *
                    352: *        Convergence hidden by negative DN.
                    353: *
                    354:          Z( 4*( N0-1 )-PP+2 ) = ZERO
                    355:          DMIN = ZERO
                    356:          GO TO 90
                    357:       ELSE IF( DMIN.LT.ZERO ) THEN
                    358: *
                    359: *        TAU too big. Select new TAU and try again.
                    360: *
                    361:          NFAIL = NFAIL + 1
                    362:          IF( TTYPE.LT.-22 ) THEN
                    363: *
                    364: *           Failed twice. Play it safe.
                    365: *
                    366:             TAU = ZERO
                    367:          ELSE IF( DMIN1.GT.ZERO ) THEN
                    368: *
                    369: *           Late failure. Gives excellent shift.
                    370: *
                    371:             TAU = ( TAU+DMIN )*( ONE-TWO*EPS )
                    372:             TTYPE = TTYPE - 11
                    373:          ELSE
                    374: *
                    375: *           Early failure. Divide by 4.
                    376: *
                    377:             TAU = QURTR*TAU
                    378:             TTYPE = TTYPE - 12
                    379:          END IF
                    380:          GO TO 70
                    381:       ELSE IF( DISNAN( DMIN ) ) THEN
                    382: *
                    383: *        NaN.
                    384: *
                    385:          IF( TAU.EQ.ZERO ) THEN
                    386:             GO TO 80
                    387:          ELSE
                    388:             TAU = ZERO
                    389:             GO TO 70
                    390:          END IF
                    391:       ELSE
                    392: *            
                    393: *        Possible underflow. Play it safe.
                    394: *
                    395:          GO TO 80
                    396:       END IF
                    397: *
                    398: *     Risk of underflow.
                    399: *
                    400:    80 CONTINUE
                    401:       CALL DLASQ6( I0, N0, Z, PP, DMIN, DMIN1, DMIN2, DN, DN1, DN2 )
                    402:       NDIV = NDIV + ( N0-I0+2 )
                    403:       ITER = ITER + 1
                    404:       TAU = ZERO
                    405: *
                    406:    90 CONTINUE
                    407:       IF( TAU.LT.SIGMA ) THEN
                    408:          DESIG = DESIG + TAU
                    409:          T = SIGMA + DESIG
                    410:          DESIG = DESIG - ( T-SIGMA )
                    411:       ELSE
                    412:          T = SIGMA + TAU
                    413:          DESIG = SIGMA - ( T-TAU ) + DESIG
                    414:       END IF
                    415:       SIGMA = T
                    416: *
                    417:       RETURN
                    418: *
                    419: *     End of DLASQ3
                    420: *
                    421:       END

CVSweb interface <joel.bertrand@systella.fr>