84
   85
   86
   87
   88
   89
   90      INTEGER            INFO, N
   91
   92
   93      DOUBLE PRECISION   D( * ), E( * )
   94
   95
   96
   97
   98
   99      DOUBLE PRECISION   ZERO, ONE, TWO, THREE
  100      parameter( zero = 0.0d0, one = 1.0d0, two = 2.0d0,
  101     $                   three = 3.0d0 )
  102      INTEGER            MAXIT
  103      parameter( maxit = 30 )
  104
  105
  106      INTEGER            I, ISCALE, JTOT, L, L1, LEND, LENDSV, LSV, M,
  107     $                   NMAXIT
  108      DOUBLE PRECISION   ALPHA, ANORM, BB, C, EPS, EPS2, GAMMA, OLDC,
  109     $                   OLDGAM, P, R, RT1, RT2, RTE, S, SAFMAX, SAFMIN,
  110     $                   SIGMA, SSFMAX, SSFMIN, RMAX
  111
  112
  113      DOUBLE PRECISION   DLAMCH, DLANST, DLAPY2
  115
  116
  118
  119
  120      INTRINSIC          abs, sign, sqrt
  121
  122
  123
  124
  125
  126      info = 0
  127
  128
  129
  130      IF( n.LT.0 ) THEN
  131         info = -1
  132         CALL xerbla( 
'DSTERF', -info )
 
  133         RETURN
  134      END IF
  135      IF( n.LE.1 )
  136     $   RETURN
  137
  138
  139
  141      eps2 = eps**2
  143      safmax = one / safmin
  144      ssfmax = sqrt( safmax ) / three
  145      ssfmin = sqrt( safmin ) / eps2
  147
  148
  149
  150      nmaxit = n*maxit
  151      sigma = zero
  152      jtot = 0
  153
  154
  155
  156
  157
  158      l1 = 1
  159
  160   10 CONTINUE
  161      IF( l1.GT.n )
  162     $   GO TO 170
  163      IF( l1.GT.1 )
  164     $   e( l1-1 ) = zero
  165      DO 20 m = l1, n - 1
  166         IF( abs( e( m ) ).LE.( sqrt( abs( d( m ) ) )*sqrt( abs( d( m+
  167     $       1 ) ) ) )*eps ) THEN
  168            e( m ) = zero
  169            GO TO 30
  170         END IF
  171   20 CONTINUE
  172      m = n
  173
  174   30 CONTINUE
  175      l = l1
  176      lsv = l
  177      lend = m
  178      lendsv = lend
  179      l1 = m + 1
  180      IF( lend.EQ.l )
  181     $   GO TO 10
  182
  183
  184
  185      anorm = 
dlanst( 
'M', lend-l+1, d( l ), e( l ) )
 
  186      iscale = 0
  187      IF( anorm.EQ.zero )
  188     $   GO TO 10
  189      IF( (anorm.GT.ssfmax) ) THEN
  190         iscale = 1
  191         CALL dlascl( 
'G', 0, 0, anorm, ssfmax, lend-l+1, 1, d( l ),
 
  192     $                n,
  193     $                info )
  194         CALL dlascl( 
'G', 0, 0, anorm, ssfmax, lend-l, 1, e( l ), n,
 
  195     $                info )
  196      ELSE IF( anorm.LT.ssfmin ) THEN
  197         iscale = 2
  198         CALL dlascl( 
'G', 0, 0, anorm, ssfmin, lend-l+1, 1, d( l ),
 
  199     $                n,
  200     $                info )
  201         CALL dlascl( 
'G', 0, 0, anorm, ssfmin, lend-l, 1, e( l ), n,
 
  202     $                info )
  203      END IF
  204
  205      DO 40 i = l, lend - 1
  206         e( i ) = e( i )**2
  207   40 CONTINUE
  208
  209
  210
  211      IF( abs( d( lend ) ).LT.abs( d( l ) ) ) THEN
  212         lend = lsv
  213         l = lendsv
  214      END IF
  215
  216      IF( lend.GE.l ) THEN
  217
  218
  219
  220
  221
  222   50    CONTINUE
  223         IF( l.NE.lend ) THEN
  224            DO 60 m = l, lend - 1
  225               IF( abs( e( m ) ).LE.eps2*abs( d( m )*d( m+1 ) ) )
  226     $            GO TO 70
  227   60       CONTINUE
  228         END IF
  229         m = lend
  230
  231   70    CONTINUE
  232         IF( m.LT.lend )
  233     $      e( m ) = zero
  234         p = d( l )
  235         IF( m.EQ.l )
  236     $      GO TO 90
  237
  238
  239
  240
  241         IF( m.EQ.l+1 ) THEN
  242            rte = sqrt( e( l ) )
  243            CALL dlae2( d( l ), rte, d( l+1 ), rt1, rt2 )
 
  244            d( l ) = rt1
  245            d( l+1 ) = rt2
  246            e( l ) = zero
  247            l = l + 2
  248            IF( l.LE.lend )
  249     $         GO TO 50
  250            GO TO 150
  251         END IF
  252
  253         IF( jtot.EQ.nmaxit )
  254     $      GO TO 150
  255         jtot = jtot + 1
  256
  257
  258
  259         rte = sqrt( e( l ) )
  260         sigma = ( d( l+1 )-p ) / ( two*rte )
  262         sigma = p - ( rte / ( sigma+sign( r, sigma ) ) )
  263
  264         c = one
  265         s = zero
  266         gamma = d( m ) - sigma
  267         p = gamma*gamma
  268
  269
  270
  271         DO 80 i = m - 1, l, -1
  272            bb = e( i )
  273            r = p + bb
  274            IF( i.NE.m-1 )
  275     $         e( i+1 ) = s*r
  276            oldc = c
  277            c = p / r
  278            s = bb / r
  279            oldgam = gamma
  280            alpha = d( i )
  281            gamma = c*( alpha-sigma ) - s*oldgam
  282            d( i+1 ) = oldgam + ( alpha-gamma )
  283            IF( c.NE.zero ) THEN
  284               p = ( gamma*gamma ) / c
  285            ELSE
  286               p = oldc*bb
  287            END IF
  288   80    CONTINUE
  289
  290         e( l ) = s*p
  291         d( l ) = sigma + gamma
  292         GO TO 50
  293
  294
  295
  296   90    CONTINUE
  297         d( l ) = p
  298
  299         l = l + 1
  300         IF( l.LE.lend )
  301     $      GO TO 50
  302         GO TO 150
  303
  304      ELSE
  305
  306
  307
  308
  309
  310  100    CONTINUE
  311         DO 110 m = l, lend + 1, -1
  312            IF( abs( e( m-1 ) ).LE.eps2*abs( d( m )*d( m-1 ) ) )
  313     $         GO TO 120
  314  110    CONTINUE
  315         m = lend
  316
  317  120    CONTINUE
  318         IF( m.GT.lend )
  319     $      e( m-1 ) = zero
  320         p = d( l )
  321         IF( m.EQ.l )
  322     $      GO TO 140
  323
  324
  325
  326
  327         IF( m.EQ.l-1 ) THEN
  328            rte = sqrt( e( l-1 ) )
  329            CALL dlae2( d( l ), rte, d( l-1 ), rt1, rt2 )
 
  330            d( l ) = rt1
  331            d( l-1 ) = rt2
  332            e( l-1 ) = zero
  333            l = l - 2
  334            IF( l.GE.lend )
  335     $         GO TO 100
  336            GO TO 150
  337         END IF
  338
  339         IF( jtot.EQ.nmaxit )
  340     $      GO TO 150
  341         jtot = jtot + 1
  342
  343
  344
  345         rte = sqrt( e( l-1 ) )
  346         sigma = ( d( l-1 )-p ) / ( two*rte )
  348         sigma = p - ( rte / ( sigma+sign( r, sigma ) ) )
  349
  350         c = one
  351         s = zero
  352         gamma = d( m ) - sigma
  353         p = gamma*gamma
  354
  355
  356
  357         DO 130 i = m, l - 1
  358            bb = e( i )
  359            r = p + bb
  360            IF( i.NE.m )
  361     $         e( i-1 ) = s*r
  362            oldc = c
  363            c = p / r
  364            s = bb / r
  365            oldgam = gamma
  366            alpha = d( i+1 )
  367            gamma = c*( alpha-sigma ) - s*oldgam
  368            d( i ) = oldgam + ( alpha-gamma )
  369            IF( c.NE.zero ) THEN
  370               p = ( gamma*gamma ) / c
  371            ELSE
  372               p = oldc*bb
  373            END IF
  374  130    CONTINUE
  375
  376         e( l-1 ) = s*p
  377         d( l ) = sigma + gamma
  378         GO TO 100
  379
  380
  381
  382  140    CONTINUE
  383         d( l ) = p
  384
  385         l = l - 1
  386         IF( l.GE.lend )
  387     $      GO TO 100
  388         GO TO 150
  389
  390      END IF
  391
  392
  393
  394  150 CONTINUE
  395      IF( iscale.EQ.1 )
  396     $   
CALL dlascl( 
'G', 0, 0, ssfmax, anorm, lendsv-lsv+1, 1,
 
  397     $                d( lsv ), n, info )
  398      IF( iscale.EQ.2 )
  399     $   
CALL dlascl( 
'G', 0, 0, ssfmin, anorm, lendsv-lsv+1, 1,
 
  400     $                d( lsv ), n, info )
  401
  402
  403
  404
  405      IF( jtot.LT.nmaxit )
  406     $   GO TO 10
  407      DO 160 i = 1, n - 1
  408         IF( e( i ).NE.zero )
  409     $      info = info + 1
  410  160 CONTINUE
  411      GO TO 180
  412
  413
  414
  415  170 CONTINUE
  416      CALL dlasrt( 
'I', n, d, info )
 
  417
  418  180 CONTINUE
  419      RETURN
  420
  421
  422
subroutine xerbla(srname, info)
 
subroutine dlae2(a, b, c, rt1, rt2)
DLAE2 computes the eigenvalues of a 2-by-2 symmetric matrix.
 
double precision function dlamch(cmach)
DLAMCH
 
double precision function dlanst(norm, n, d, e)
DLANST returns the value of the 1-norm, or the Frobenius norm, or the infinity norm,...
 
double precision function dlapy2(x, y)
DLAPY2 returns sqrt(x2+y2).
 
subroutine dlascl(type, kl, ku, cfrom, cto, m, n, a, lda, info)
DLASCL multiplies a general rectangular matrix by a real scalar defined as cto/cfrom.
 
subroutine dlasrt(id, n, d, info)
DLASRT sorts numbers in increasing or decreasing order.