4
    5
    6
    7
    8
    9      IMPLICIT NONE
   10
   11
   12      INTEGER            IFIRST, ILAST, INFO, N, OFFSET, TWIST
   13      DOUBLE PRECISION   LGPVMN, LGSPDM, PIVMIN, 
   14     $                   RTOL1, RTOL2
   15
   16
   17      INTEGER            IWORK( * )
   18      DOUBLE PRECISION   D( * ), LLD( * ), W( * ),
   19     $                   WERR( * ), WGAP( * ), WORK( * )
   20
   21
   22
   23
   24
   25
   26
   27
   28
   29
   30
   31
   32
   33
   34
   35
   36
   37
   38
   39
   40
   41
   42
   43
   44
   45
   46
   47
   48
   49
   50
   51
   52
   53
   54
   55
   56
   57
   58
   59
   60
   61
   62
   63
   64
   65
   66
   67
   68
   69
   70
   71
   72
   73
   74
   75
   76
   77
   78
   79
   80
   81
   82
   83
   84
   85
   86
   87
   88
   89
   90
   91
   92
   93
   94
   95
   96
   97
   98
   99
  100
  101
  102
  103
  104
  105
  106
  107
  108
  109
  110
  111
  112
  113
  114
  115
  116
  117
  118      DOUBLE PRECISION   ZERO, TWO, HALF
  119      parameter( zero = 0.0d0, two = 2.0d0,
  120     $                   half = 0.5d0 )
  121      INTEGER   MAXITR
  122
  123
  124      INTEGER            I, I1, II, INDLLD, IP, ITER, J, K, NEGCNT,
  125     $                   NEXT, NINT, OLNINT, PREV, R
  126      DOUBLE PRECISION   BACK, CVRGD, GAP, LEFT, LGAP, MID, MNWDTH,
  127     $                   RGAP, RIGHT, SAVGAP, TMP, WIDTH
  128      LOGICAL   PARANOID
  129
  130
  131      LOGICAL            DISNAN
  132      DOUBLE PRECISION   DLAMCH
  133      INTEGER            DLANEG2A
  136
  137
  138
  140
  141
  142
  143      info = 0
  144
  145
  146
  147
  148      paranoid = .true.
  149
  150      maxitr = int( ( lgspdm - lgpvmn ) / log( two ) ) + 2
  151      mnwdth = two * pivmin
  152
  153      r = twist
  154
  155      indlld = 2*n     
  156      DO 5 j = 1, n-1 
  157         i=2*j
  158         work(indlld+i-1) = d(j)
  159         work(indlld+i) = lld(j)
  160  5   CONTINUE
  161      work(indlld+2*n-1) = d(n)
  162
  163      IF((r.LT.1).OR.(r.GT.n)) r = n
  164
  165
  166
  167
  168
  169
  170
  171
  172      i1 = ifirst
  173
  174      nint = 0
  175
  176      prev = 0
  177     
  178      rgap = wgap( i1-offset )
  179      DO 75 i = i1, ilast
  180         k = 2*i
  181         ii = i - offset
  182         left = w( ii ) - werr( ii )
  183         right = w( ii ) + werr( ii )
  184         lgap = rgap
  185         rgap = wgap( ii )
  186         gap = 
min( lgap, rgap )
 
  187 
  188         IF((abs(left).LE.16*pivmin).OR.(abs(right).LE.16*pivmin))
  189     $      THEN
  190            info = -1
  191            RETURN
  192         ENDIF
  193 
  194         IF( paranoid ) THEN
  195
  196
  197
  198
  199
  200         back = werr( ii )
  201 20      CONTINUE
  202         negcnt = 
dlaneg2a( n, work(indlld+1), left, pivmin, r )
 
  203         IF( negcnt.GT.i-1 ) THEN
  204            left = left - back
  205            back = two*back
  206            GO TO 20
  207         END IF
  208
  209
  210
  211
  212         back = werr( ii )
  213 50      CONTINUE
  214         negcnt = 
dlaneg2a( n, work(indlld+1),right, pivmin, r )
 
  215 
  216         IF( negcnt.LT.i ) THEN
  217             right = right + back
  218             back = two*back
  219             GO TO 50
  220         END IF
  221         ENDIF
  222 
  223         width = half*abs( left - right )
  224         tmp = 
max( abs( left ), abs( right ) )
 
  225         cvrgd = 
max(rtol1*gap,rtol2*tmp)
 
  226         IF( width.LE.cvrgd .OR. width.LE.mnwdth ) THEN
  227
  228
  229
  230
  231            iwork( k-1 ) = -1
  232
  233            IF((i.EQ.i1).AND.(i.LT.ilast)) i1 = i + 1
  234            IF((prev.GE.i1).AND.(i.LE.ilast)) iwork( 2*prev-1 ) = i + 1
  235         ELSE
  236
  237            prev = i
  238            nint = nint + 1
  239            iwork( k-1 ) = i + 1
  240            iwork( k ) = negcnt
  241         END IF
  242         work( k-1 ) = left
  243         work( k ) = right
  244 75   CONTINUE
  245 
  246
  247
  248
  249
  250      iter = 0 
  251 80   CONTINUE
  252      prev = i1 - 1
  253      i = i1
  254      olnint = nint
  255 
  256      DO 100 ip = 1, olnint
  257         k = 2*i
  258         ii = i - offset
  259         rgap = wgap( ii )
  260         lgap = rgap
  261         IF(ii.GT.1) lgap = wgap( ii-1 ) 
  262         gap = 
min( lgap, rgap )
 
  263         next = iwork( k-1 )
  264         left = work( k-1 )
  265         right = work( k )
  266         mid = half*( left + right ) 
  267
  268         width = right - mid
  269         tmp = 
max( abs( left ), abs( right ) )
 
  270         cvrgd = 
max(rtol1*gap,rtol2*tmp)
 
  271         IF( ( width.LE.cvrgd ) .OR. ( width.LE.mnwdth ).OR.
  272     $       ( iter.EQ.maxitr ) )THEN
  273
  274            nint = nint - 1
  275
  276            iwork( k-1 ) = 0
  277            IF( i1.EQ.i ) THEN
  278               i1 = next
  279            ELSE
  280
  281               IF(prev.GE.i1) iwork( 2*prev-1 ) = next
  282            END IF
  283            i = next
  284            GO TO 100
  285         END IF
  286         prev = i
  287
  288
  289
  290         negcnt = 
dlaneg2a( n, work(indlld+1), mid, pivmin, r )
 
  291         IF( negcnt.LE.i-1 ) THEN
  292            work( k-1 ) = mid
  293         ELSE
  294            work( k ) = mid
  295         END IF
  296         i = next
  297 100  CONTINUE
  298      iter = iter + 1
  299
  300
  301
  302      IF( ( nint.GT.0 ).AND.(iter.LE.maxitr) ) GO TO 80
  303
  304
  305
  306
  307
  308      savgap = wgap( ilast-offset )
  309
  310      left = work( 2*ifirst-1 )
  311      DO 110 i = ifirst, ilast
  312         k = 2*i
  313         ii = i - offset
  314
  315         right = work( k ) 
  316
  317         IF( iwork( k-1 ).EQ.0 ) THEN
  318            w( ii ) = half*( left+right )
  319            werr( ii ) = right - w( ii )
  320         END IF
  321
  322         left = work( k +1 ) 
  323         wgap( ii ) = 
max( zero, left - right )
 
  324 110  CONTINUE
  325
  326      wgap( ilast-offset ) = savgap
  327 
  328      RETURN
  329
  330
  331
integer function dlaneg2a(n, dlld, sigma, pivmin, r)