(no commit message)
authorjames <james@8a072113-8704-0410-8d35-dd094bca7971>
Thu, 6 Sep 2012 03:34:54 +0000 (03:34 +0000)
committerjames <james@8a072113-8704-0410-8d35-dd094bca7971>
Thu, 6 Sep 2012 03:34:54 +0000 (03:34 +0000)
SRC/dlasd4.f
SRC/slasd4.f
TESTING/svd.in

index 5dbda2dbfa5f56964cf3c38724a82d647fd385a5..0bd1b03875e0e257c1ec26be99f161f4b64f3ec4 100644 (file)
@@ -2,24 +2,24 @@
 *
 *  =========== DOCUMENTATION ===========
 *
-* Online html documentation available at 
-*            http://www.netlib.org/lapack/explore-html/ 
+* Online html documentation available at
+*            http://www.netlib.org/lapack/explore-html/
 *
 *> \htmlonly
-*> Download DLASD4 + dependencies 
-*> <a href="http://www.netlib.org/cgi-bin/netlibfiles.tgz?format=tgz&filename=/lapack/lapack_routine/dlasd4.f"> 
-*> [TGZ]</a> 
-*> <a href="http://www.netlib.org/cgi-bin/netlibfiles.zip?format=zip&filename=/lapack/lapack_routine/dlasd4.f"> 
-*> [ZIP]</a> 
-*> <a href="http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/dlasd4.f"> 
+*> Download DLASD4 + dependencies
+*> <a href="http://www.netlib.org/cgi-bin/netlibfiles.tgz?format=tgz&filename=/lapack/lapack_routine/dlasd4.f">
+*> [TGZ]</a>
+*> <a href="http://www.netlib.org/cgi-bin/netlibfiles.zip?format=zip&filename=/lapack/lapack_routine/dlasd4.f">
+*> [ZIP]</a>
+*> <a href="http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/dlasd4.f">
 *> [TXT]</a>
-*> \endhtmlonly 
+*> \endhtmlonly
 *
 *  Definition:
 *  ===========
 *
 *       SUBROUTINE DLASD4( N, I, D, Z, DELTA, RHO, SIGMA, WORK, INFO )
-* 
+*
 *       .. Scalar Arguments ..
 *       INTEGER            I, INFO, N
 *       DOUBLE PRECISION   RHO, SIGMA
@@ -27,7 +27,7 @@
 *       .. Array Arguments ..
 *       DOUBLE PRECISION   D( * ), DELTA( * ), WORK( * ), Z( * )
 *       ..
-*  
+*
 *
 *> \par Purpose:
 *  =============
 *  Authors:
 *  ========
 *
-*> \author Univ. of Tennessee 
-*> \author Univ. of California Berkeley 
-*> \author Univ. of Colorado Denver 
-*> \author NAG Ltd. 
+*> \author Univ. of Tennessee
+*> \author Univ. of California Berkeley
+*> \author Univ. of Colorado Denver
+*> \author NAG Ltd.
 *
 *> \date August 2012
 *
 *
 *     .. Parameters ..
       INTEGER            MAXIT
-*     set MAXIT to 40 from 64. RCL 8/26/2012
-      PARAMETER          ( MAXIT = 40 )
+      PARAMETER          ( MAXIT = 400 )
       DOUBLE PRECISION   ZERO, ONE, TWO, THREE, FOUR, EIGHT, TEN
       PARAMETER          ( ZERO = 0.0D+0, ONE = 1.0D+0, TWO = 2.0D+0,
      $                   THREE = 3.0D+0, FOUR = 4.0D+0, EIGHT = 8.0D+0,
      $                   TEN = 10.0D+0 )
 *     ..
 *     .. Local Scalars ..
-      LOGICAL            ORGATI, SWTCH, SWTCH3
+      LOGICAL            ORGATI, SWTCH, SWTCH3, GEOMAVG
       INTEGER            II, IIM1, IIP1, IP1, ITER, J, NITER
-      DOUBLE PRECISION   A, B, C, DELSQ, DELSQ2, DPHI, DPSI, DTIIM,
+      DOUBLE PRECISION   A, B, C, DELSQ, DELSQ2, SQ2, DPHI, DPSI, DTIIM,
      $                   DTIIP, DTIPSQ, DTISQ, DTNSQ, DTNSQ1, DW, EPS,
-     $                   ERRETM, ETA, PHI, PREW, PSI, RHOINV, SG2LB,
-     $                   SG2UB, TAU, TEMP, TEMP1, TEMP2, W
+     $                   ERRETM, ETA, PHI, PREW, PSI, RHOINV, SGLB,
+     $                   SGUB, TAU, TAU2, TEMP, TEMP1, TEMP2, W
 *     ..
 *     .. Local Arrays ..
       DOUBLE PRECISION   DD( 3 ), ZZ( 3 )
      $             ( D( N )-D( N-1 )+RHO / ( D( N )+TEMP1 ) ) ) +
      $             Z( N )*Z( N ) / RHO
 *
-*           The following TAU is to approximate
+*           The following TAU2 is to approximate
 *           SIGMA_n^2 - D( N )*D( N )
 *
             IF( C.LE.TEMP ) THEN
                A = -C*DELSQ + Z( N-1 )*Z( N-1 ) + Z( N )*Z( N )
                B = Z( N )*Z( N )*DELSQ
                IF( A.LT.ZERO ) THEN
-                  TAU = TWO*B / ( SQRT( A*A+FOUR*B*C )-A )
+                  TAU2 = TWO*B / ( SQRT( A*A+FOUR*B*C )-A )
                ELSE
-                  TAU = ( A+SQRT( A*A+FOUR*B*C ) ) / ( TWO*C )
+                  TAU2 = ( A+SQRT( A*A+FOUR*B*C ) ) / ( TWO*C )
                END IF
             END IF
 *
 *           It can be proved that
-*               D(N)^2+RHO/2 <= SIGMA_n^2 < D(N)^2+TAU <= D(N)^2+RHO
+*               D(N)^2+RHO/2 <= SIGMA_n^2 < D(N)^2+TAU2 <= D(N)^2+RHO
 *
          ELSE
             DELSQ = ( D( N )-D( N-1 ) )*( D( N )+D( N-1 ) )
             A = -C*DELSQ + Z( N-1 )*Z( N-1 ) + Z( N )*Z( N )
             B = Z( N )*Z( N )*DELSQ
 *
-*           The following TAU is to approximate
+*           The following TAU2 is to approximate
 *           SIGMA_n^2 - D( N )*D( N )
 *
             IF( A.LT.ZERO ) THEN
-               TAU = TWO*B / ( SQRT( A*A+FOUR*B*C )-A )
+               TAU2 = TWO*B / ( SQRT( A*A+FOUR*B*C )-A )
             ELSE
-               TAU = ( A+SQRT( A*A+FOUR*B*C ) ) / ( TWO*C )
+               TAU2 = ( A+SQRT( A*A+FOUR*B*C ) ) / ( TWO*C )
             END IF
 *
 *           It can be proved that
-*           D(N)^2 < D(N)^2+TAU < SIGMA(N)^2 < D(N)^2+RHO/2
+*           D(N)^2 < D(N)^2+TAU2 < SIGMA(N)^2 < D(N)^2+RHO/2
 *
          END IF
 *
-*        The following ETA is to approximate SIGMA_n - D( N )
+*        The following TAU is to approximate SIGMA_n - D( N )
 *
-         ETA = TAU / ( D( N )+SQRT( D( N )*D( N )+TAU ) )
+         TAU = TAU2 / ( D( N )+SQRT( D( N )*D( N )+TAU2 ) )
 *
-         SIGMA = D( N ) + ETA
+         SIGMA = D( N ) + TAU
          DO 30 J = 1, N
-            DELTA( J ) = ( D( J )-D( I ) ) - ETA
-            WORK( J ) = D( J ) + D( I ) + ETA
+            DELTA( J ) = ( D( J )-D( I ) ) - TAU
+            WORK( J ) = D( J ) + D( I ) + TAU
    30    CONTINUE
 *
 *        Evaluate PSI and the derivative DPSI
          PHI = Z( N )*TEMP
          DPHI = TEMP*TEMP
          ERRETM = EIGHT*( -PHI-PSI ) + ERRETM - PHI + RHOINV +
-     $            ABS( TAU )*( DPSI+DPHI )
+     $            ABS( TAU2 )*( DPSI+DPHI )
 *
          W = RHOINV + PHI + PSI
 *
          IF( TEMP.GT.RHO )
      $      ETA = RHO + DTNSQ
 *
-         TAU = TAU + ETA
          ETA = ETA / ( SIGMA+SQRT( ETA+SIGMA*SIGMA ) )
+         TAU = TAU + ETA
+         SIGMA = SIGMA + ETA
+*
          DO 50 J = 1, N
             DELTA( J ) = DELTA( J ) - ETA
             WORK( J ) = WORK( J ) + ETA
    50    CONTINUE
-*
-         SIGMA = SIGMA + ETA
 *
 *        Evaluate PSI and the derivative DPSI
 *
 *
 *        Evaluate PHI and the derivative DPHI
 *
-         TEMP = Z( N ) / ( WORK( N )*DELTA( N ) )
+         TAU2 = WORK( N )*DELTA( N )
+         TEMP = Z( N ) / TAU2
          PHI = Z( N )*TEMP
          DPHI = TEMP*TEMP
          ERRETM = EIGHT*( -PHI-PSI ) + ERRETM - PHI + RHOINV +
-     $            ABS( TAU )*( DPSI+DPHI )
+     $            ABS( TAU2 )*( DPSI+DPHI )
 *
          W = RHOINV + PHI + PSI
 *
             IF( TEMP.LE.ZERO )
      $         ETA = ETA / TWO
 *
-            TAU = TAU + ETA
             ETA = ETA / ( SIGMA+SQRT( ETA+SIGMA*SIGMA ) )
+            TAU = TAU + ETA
+            SIGMA = SIGMA + ETA
+*
             DO 70 J = 1, N
                DELTA( J ) = DELTA( J ) - ETA
                WORK( J ) = WORK( J ) + ETA
    70       CONTINUE
-*
-            SIGMA = SIGMA + ETA
 *
 *           Evaluate PSI and the derivative DPSI
 *
 *
 *           Evaluate PHI and the derivative DPHI
 *
-            TEMP = Z( N ) / ( WORK( N )*DELTA( N ) )
+            TAU2 = WORK( N )*DELTA( N )
+            TEMP = Z( N ) / TAU2
             PHI = Z( N )*TEMP
             DPHI = TEMP*TEMP
             ERRETM = EIGHT*( -PHI-PSI ) + ERRETM - PHI + RHOINV +
-     $               ABS( TAU )*( DPSI+DPHI )
+     $               ABS( TAU2 )*( DPSI+DPHI )
 *
             W = RHOINV + PHI + PSI
    90    CONTINUE
 *
          DELSQ = ( D( IP1 )-D( I ) )*( D( IP1 )+D( I ) )
          DELSQ2 = DELSQ / TWO
-         TEMP = DELSQ2 / ( D( I )+SQRT( D( I )*D( I )+DELSQ2 ) )
+         SQ2=SQRT( ( D( I )*D( I )+D( IP1 )*D( IP1 ) ) / TWO )
+         TEMP = DELSQ2 / ( D( I )+SQ2 )
          DO 100 J = 1, N
             WORK( J ) = D( J ) + D( I ) + TEMP
             DELTA( J ) = ( D( J )-D( I ) ) - TEMP
          W = C + Z( I )*Z( I ) / ( WORK( I )*DELTA( I ) ) +
      $       Z( IP1 )*Z( IP1 ) / ( WORK( IP1 )*DELTA( IP1 ) )
 *
+         GEOMAVG = .FALSE.
          IF( W.GT.ZERO ) THEN
 *
 *           d(i)^2 < the ith sigma^2 < (d(i)^2+d(i+1)^2)/2
 *           We choose d(i) as origin.
 *
             ORGATI = .TRUE.
-            SG2LB = ZERO
-            SG2UB = DELSQ2
+            II = I
+            SGLB = ZERO
+            SGUB = DELSQ2  / ( D( I )+SQ2 )
             A = C*DELSQ + Z( I )*Z( I ) + Z( IP1 )*Z( IP1 )
             B = Z( I )*Z( I )*DELSQ
             IF( A.GT.ZERO ) THEN
-               TAU = TWO*B / ( A+SQRT( ABS( A*A-FOUR*B*C ) ) )
+               TAU2 = TWO*B / ( A+SQRT( ABS( A*A-FOUR*B*C ) ) )
             ELSE
-               TAU = ( A-SQRT( ABS( A*A-FOUR*B*C ) ) ) / ( TWO*C )
+               TAU2 = ( A-SQRT( ABS( A*A-FOUR*B*C ) ) ) / ( TWO*C )
             END IF
 *
-*           TAU now is an estimation of SIGMA^2 - D( I )^2. The
+*           TAU2 now is an estimation of SIGMA^2 - D( I )^2. The
 *           following, however, is the corresponding estimation of
 *           SIGMA - D( I ).
 *
-            ETA = TAU / ( D( I )+SQRT( D( I )*D( I )+TAU ) )
+            TAU = TAU2 / ( D( I )+SQRT( D( I )*D( I )+TAU2 ) )
+            TEMP = SQRT(EPS)
+            IF( (D(I).LE.TEMP*D(IP1)).AND.(ABS(Z(I)).LE.TEMP)
+     $                               .AND.(D(I).GT.ZERO) ) THEN
+               TAU = MIN( TEN*D(I), SGUB )
+               GEOMAVG = .TRUE.
+            END IF
          ELSE
 *
 *           (d(i)^2+d(i+1)^2)/2 <= the ith sigma^2 < d(i+1)^2/2
 *           We choose d(i+1) as origin.
 *
             ORGATI = .FALSE.
-            SG2LB = -DELSQ2
-            SG2UB = ZERO
+            II = IP1
+            SGLB = -DELSQ2  / ( D( II )+SQ2 )
+            SGUB = ZERO
             A = C*DELSQ - Z( I )*Z( I ) - Z( IP1 )*Z( IP1 )
             B = Z( IP1 )*Z( IP1 )*DELSQ
             IF( A.LT.ZERO ) THEN
-               TAU = TWO*B / ( A-SQRT( ABS( A*A+FOUR*B*C ) ) )
+               TAU2 = TWO*B / ( A-SQRT( ABS( A*A+FOUR*B*C ) ) )
             ELSE
-               TAU = -( A+SQRT( ABS( A*A+FOUR*B*C ) ) ) / ( TWO*C )
+               TAU2 = -( A+SQRT( ABS( A*A+FOUR*B*C ) ) ) / ( TWO*C )
             END IF
 *
-*           TAU now is an estimation of SIGMA^2 - D( IP1 )^2. The
+*           TAU2 now is an estimation of SIGMA^2 - D( IP1 )^2. The
 *           following, however, is the corresponding estimation of
 *           SIGMA - D( IP1 ).
 *
-            ETA = TAU / ( D( IP1 )+SQRT( ABS( D( IP1 )*D( IP1 )+
-     $            TAU ) ) )
+            TAU = TAU2 / ( D( IP1 )+SQRT( ABS( D( IP1 )*D( IP1 )+
+     $            TAU2 ) ) )
          END IF
 *
-         IF( ORGATI ) THEN
-            II = I
-            SIGMA = D( I ) + ETA
-            DO 130 J = 1, N
-               WORK( J ) = D( J ) + D( I ) + ETA
-               DELTA( J ) = ( D( J )-D( I ) ) - ETA
-  130       CONTINUE
-         ELSE
-            II = I + 1
-            SIGMA = D( IP1 ) + ETA
-            DO 140 J = 1, N
-               WORK( J ) = D( J ) + D( IP1 ) + ETA
-               DELTA( J ) = ( D( J )-D( IP1 ) ) - ETA
-  140       CONTINUE
-         END IF
+         SIGMA = D( II ) + TAU
+         DO 130 J = 1, N
+            WORK( J ) = D( J ) + D( II ) + TAU
+            DELTA( J ) = ( D( J )-D( II ) ) - TAU
+  130    CONTINUE
          IIM1 = II - 1
          IIP1 = II + 1
 *
          TEMP = Z( II )*TEMP
          W = W + TEMP
          ERRETM = EIGHT*( PHI-PSI ) + ERRETM + TWO*RHOINV +
-     $            THREE*ABS( TEMP ) + ABS( TAU )*DW
+     $            THREE*ABS( TEMP ) + ABS( TAU2 )*DW
 *
 *        Test for convergence
 *
          END IF
 *
          IF( W.LE.ZERO ) THEN
-            SG2LB = MAX( SG2LB, TAU )
+            SGLB = MAX( SGLB, TAU )
          ELSE
-            SG2UB = MIN( SG2UB, TAU )
+            SGUB = MIN( SGUB, TAU )
          END IF
 *
 *        Calculate the new step
             DD( 2 ) = DELTA( II )*WORK( II )
             DD( 3 ) = DTIIP
             CALL DLAED6( NITER, ORGATI, C, DD, ZZ, W, ETA, INFO )
-            IF( INFO.NE.0 )
-     $         GO TO 240
+*
+            IF( INFO.NE.0 ) THEN
+*
+*              If INFO is not 0, i.e., DLAED6 failed, switch back to 2 pole interpolation.
+*
+               SWTCH3 = .FALSE.
+               INFO = 0
+               DTIPSQ = WORK( IP1 )*DELTA( IP1 )
+               DTISQ = WORK( I )*DELTA( I )
+               IF( ORGATI ) THEN
+                  C = W - DTIPSQ*DW + DELSQ*( Z( I ) / DTISQ )**2
+               ELSE
+                  C = W - DTISQ*DW - DELSQ*( Z( IP1 ) / DTIPSQ )**2
+               END IF
+               A = ( DTIPSQ+DTISQ )*W - DTIPSQ*DTISQ*DW
+               B = DTIPSQ*DTISQ*W
+               IF( C.EQ.ZERO ) THEN
+                  IF( A.EQ.ZERO ) THEN
+                     IF( ORGATI ) THEN
+                        A = Z( I )*Z( I ) + DTIPSQ*DTIPSQ*( DPSI+DPHI )
+                     ELSE
+                        A = Z( IP1 )*Z( IP1 ) + DTISQ*DTISQ*( DPSI+DPHI)
+                     END IF
+                  END IF
+                  ETA = B / A
+               ELSE IF( A.LE.ZERO ) THEN
+                  ETA = ( A-SQRT( ABS( A*A-FOUR*B*C ) ) ) / ( TWO*C )
+               ELSE
+                  ETA = TWO*B / ( A+SQRT( ABS( A*A-FOUR*B*C ) ) )
+               END IF
+            END IF
          END IF
 *
 *        Note, eta should be positive if w is negative, and
 *
          IF( W*ETA.GE.ZERO )
      $      ETA = -W / DW
-         IF( ORGATI ) THEN
-            TEMP1 = WORK( I )*DELTA( I )
-            TEMP = ETA - TEMP1
-         ELSE
-            TEMP1 = WORK( IP1 )*DELTA( IP1 )
-            TEMP = ETA - TEMP1
-         END IF
-         IF( TEMP.GT.SG2UB .OR. TEMP.LT.SG2LB ) THEN
+*
+         ETA = ETA / ( SIGMA+SQRT( SIGMA*SIGMA+ETA ) )
+         TEMP = TAU + ETA
+         IF( TEMP.GT.SGUB .OR. TEMP.LT.SGLB ) THEN
             IF( W.LT.ZERO ) THEN
-               ETA = ( SG2UB-TAU ) / TWO
+               ETA = ( SGUB-TAU ) / TWO
             ELSE
-               ETA = ( SG2LB-TAU ) / TWO
+               ETA = ( SGLB-TAU ) / TWO
+            END IF
+            IF( GEOMAVG ) THEN
+               IF( W .LT. ZERO ) THEN
+                  IF( TAU .GT. ZERO ) THEN
+                     ETA = SQRT(SGUB*TAU)-TAU
+                  END IF
+               ELSE
+                  IF( SGLB .GT. ZERO ) THEN
+                     ETA = SQRT(SGLB*TAU)-TAU
+                  END IF
+               END IF
             END IF
          END IF
-*
-         TAU = TAU + ETA
-         ETA = ETA / ( SIGMA+SQRT( SIGMA*SIGMA+ETA ) )
 *
          PREW = W
 *
+         TAU = TAU + ETA
          SIGMA = SIGMA + ETA
+*
          DO 170 J = 1, N
             WORK( J ) = WORK( J ) + ETA
             DELTA( J ) = DELTA( J ) - ETA
             ERRETM = ERRETM + PHI
   190    CONTINUE
 *
-         TEMP = Z( II ) / ( WORK( II )*DELTA( II ) )
+         TAU2 = WORK( II )*DELTA( II )
+         TEMP = Z( II ) / TAU2
          DW = DPSI + DPHI + TEMP*TEMP
          TEMP = Z( II )*TEMP
          W = RHOINV + PHI + PSI + TEMP
          ERRETM = EIGHT*( PHI-PSI ) + ERRETM + TWO*RHOINV +
-     $            THREE*ABS( TEMP ) + ABS( TAU )*DW
-*
-         IF( W.LE.ZERO ) THEN
-            SG2LB = MAX( SG2LB, TAU )
-         ELSE
-            SG2UB = MIN( SG2UB, TAU )
-         END IF
+     $            THREE*ABS( TEMP ) + ABS( TAU2 )*DW
 *
          SWTCH = .FALSE.
          IF( ORGATI ) THEN
 *           Test for convergence
 *
             IF( ABS( W ).LE.EPS*ERRETM ) THEN
+*     $          .OR. (SGUB-SGLB).LE.EIGHT*ABS(SGUB+SGLB) ) THEN
                GO TO 240
             END IF
+*
+            IF( W.LE.ZERO ) THEN
+               SGLB = MAX( SGLB, TAU )
+            ELSE
+               SGUB = MIN( SGUB, TAU )
+            END IF
 *
 *           Calculate the new step
 *
                DD( 2 ) = DELTA( II )*WORK( II )
                DD( 3 ) = DTIIP
                CALL DLAED6( NITER, ORGATI, C, DD, ZZ, W, ETA, INFO )
-               IF( INFO.NE.0 )
-     $            GO TO 240
+*
+               IF( INFO.NE.0 ) THEN
+*
+*                 If INFO is not 0, i.e., DLAED6 failed, switch back to two pole interpolation
+*
+                  SWTCH3 = .FALSE.
+                  INFO = 0
+                  DTIPSQ = WORK( IP1 )*DELTA( IP1 )
+                  DTISQ = WORK( I )*DELTA( I )
+                  IF( .NOT.SWTCH ) THEN
+                     IF( ORGATI ) THEN
+                        C = W - DTIPSQ*DW + DELSQ*( Z( I )/DTISQ )**2
+                     ELSE
+                        C = W - DTISQ*DW - DELSQ*( Z( IP1 )/DTIPSQ )**2
+                     END IF
+                  ELSE
+                     TEMP = Z( II ) / ( WORK( II )*DELTA( II ) )
+                     IF( ORGATI ) THEN
+                        DPSI = DPSI + TEMP*TEMP
+                     ELSE
+                        DPHI = DPHI + TEMP*TEMP
+                     END IF
+                     C = W - DTISQ*DPSI - DTIPSQ*DPHI
+                  END IF
+                  A = ( DTIPSQ+DTISQ )*W - DTIPSQ*DTISQ*DW
+                  B = DTIPSQ*DTISQ*W
+                  IF( C.EQ.ZERO ) THEN
+                     IF( A.EQ.ZERO ) THEN
+                        IF( .NOT.SWTCH ) THEN
+                           IF( ORGATI ) THEN
+                              A = Z( I )*Z( I ) + DTIPSQ*DTIPSQ*
+     $                            ( DPSI+DPHI )
+                           ELSE
+                              A = Z( IP1 )*Z( IP1 ) +
+     $                            DTISQ*DTISQ*( DPSI+DPHI )
+                           END IF
+                        ELSE
+                           A = DTISQ*DTISQ*DPSI + DTIPSQ*DTIPSQ*DPHI
+                        END IF
+                     END IF
+                     ETA = B / A
+                  ELSE IF( A.LE.ZERO ) THEN
+                     ETA = ( A-SQRT( ABS( A*A-FOUR*B*C ) ) ) / ( TWO*C )
+                  ELSE
+                     ETA = TWO*B / ( A+SQRT( ABS( A*A-FOUR*B*C ) ) )
+                  END IF
+               END IF
             END IF
 *
 *           Note, eta should be positive if w is negative, and
 *
             IF( W*ETA.GE.ZERO )
      $         ETA = -W / DW
-            IF( ORGATI ) THEN
-               TEMP1 = WORK( I )*DELTA( I )
-               TEMP = ETA - TEMP1
-            ELSE
-               TEMP1 = WORK( IP1 )*DELTA( IP1 )
-               TEMP = ETA - TEMP1
-            END IF
-            IF( TEMP.GT.SG2UB .OR. TEMP.LT.SG2LB ) THEN
+*
+            ETA = ETA / ( SIGMA+SQRT( SIGMA*SIGMA+ETA ) )
+            TEMP=TAU+ETA
+            IF( TEMP.GT.SGUB .OR. TEMP.LT.SGLB ) THEN
                IF( W.LT.ZERO ) THEN
-                  ETA = ( SG2UB-TAU ) / TWO
+                  ETA = ( SGUB-TAU ) / TWO
                ELSE
-                  ETA = ( SG2LB-TAU ) / TWO
+                  ETA = ( SGLB-TAU ) / TWO
+               END IF
+               IF( GEOMAVG ) THEN
+                  IF( W .LT. ZERO ) THEN
+                     IF( TAU .GT. ZERO ) THEN
+                        ETA = SQRT(SGUB*TAU)-TAU
+                     END IF
+                  ELSE
+                     IF( SGLB .GT. ZERO ) THEN
+                        ETA = SQRT(SGLB*TAU)-TAU
+                     END IF
+                  END IF
                END IF
             END IF
 *
-            TAU = TAU + ETA
-            ETA = ETA / ( SIGMA+SQRT( SIGMA*SIGMA+ETA ) )
+            PREW = W
 *
+            TAU = TAU + ETA
             SIGMA = SIGMA + ETA
+*
             DO 200 J = 1, N
                WORK( J ) = WORK( J ) + ETA
                DELTA( J ) = DELTA( J ) - ETA
   200       CONTINUE
-*
-            PREW = W
 *
 *           Evaluate PSI and the derivative DPSI
 *
                ERRETM = ERRETM + PHI
   220       CONTINUE
 *
-            TEMP = Z( II ) / ( WORK( II )*DELTA( II ) )
+            TAU2 = WORK( II )*DELTA( II )
+            TEMP = Z( II ) / TAU2
             DW = DPSI + DPHI + TEMP*TEMP
             TEMP = Z( II )*TEMP
             W = RHOINV + PHI + PSI + TEMP
             ERRETM = EIGHT*( PHI-PSI ) + ERRETM + TWO*RHOINV +
-     $               THREE*ABS( TEMP ) + ABS( TAU )*DW
+     $               THREE*ABS( TEMP ) + ABS( TAU2 )*DW
+*
             IF( W*PREW.GT.ZERO .AND. ABS( W ).GT.ABS( PREW ) / TEN )
      $         SWTCH = .NOT.SWTCH
-*           I don't understand the following 5 lines in the first place. RCL 8/26/2012
-*           IF( W.LE.ZERO ) THEN
-*               SG2LB = MAX( SG2LB, TAU )
-*            ELSE
-*               SG2UB = MIN( SG2UB, TAU )
-*           END IF
 *
   230    CONTINUE
 *
index 51b35385111917e7802e9d8db34aebd1b69c669f..0455af46a0b7310ed9031eda22fa9b94a99faf6d 100644 (file)
@@ -2,24 +2,24 @@
 *
 *  =========== DOCUMENTATION ===========
 *
-* Online html documentation available at 
-*            http://www.netlib.org/lapack/explore-html/ 
+* Online html documentation available at
+*            http://www.netlib.org/lapack/explore-html/
 *
 *> \htmlonly
-*> Download SLASD4 + dependencies 
-*> <a href="http://www.netlib.org/cgi-bin/netlibfiles.tgz?format=tgz&filename=/lapack/lapack_routine/slasd4.f"> 
-*> [TGZ]</a> 
-*> <a href="http://www.netlib.org/cgi-bin/netlibfiles.zip?format=zip&filename=/lapack/lapack_routine/slasd4.f"> 
-*> [ZIP]</a> 
-*> <a href="http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/slasd4.f"> 
+*> Download SLASD4 + dependencies
+*> <a href="http://www.netlib.org/cgi-bin/netlibfiles.tgz?format=tgz&filename=/lapack/lapack_routine/dlasd4.f">
+*> [TGZ]</a>
+*> <a href="http://www.netlib.org/cgi-bin/netlibfiles.zip?format=zip&filename=/lapack/lapack_routine/dlasd4.f">
+*> [ZIP]</a>
+*> <a href="http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/dlasd4.f">
 *> [TXT]</a>
-*> \endhtmlonly 
+*> \endhtmlonly
 *
 *  Definition:
 *  ===========
 *
 *       SUBROUTINE SLASD4( N, I, D, Z, DELTA, RHO, SIGMA, WORK, INFO )
-* 
+*
 *       .. Scalar Arguments ..
 *       INTEGER            I, INFO, N
 *       REAL               RHO, SIGMA
@@ -27,7 +27,7 @@
 *       .. Array Arguments ..
 *       REAL               D( * ), DELTA( * ), WORK( * ), Z( * )
 *       ..
-*  
+*
 *
 *> \par Purpose:
 *  =============
 *>
 *> \param[in] Z
 *> \verbatim
-*>          Z is REAL array, dimension (N)
+*>          Z is REAL array, dimension ( N )
 *>         The components of the updating vector.
 *> \endverbatim
 *>
 *> \param[out] DELTA
 *> \verbatim
-*>          DELTA is REAL array, dimension (N)
+*>          DELTA is REAL array, dimension ( N )
 *>         If N .ne. 1, DELTA contains (D(j) - sigma_I) in its  j-th
 *>         component.  If N = 1, then DELTA(1) = 1.  The vector DELTA
 *>         contains the information necessary to construct the
 *>
 *> \param[out] WORK
 *> \verbatim
-*>          WORK is REAL array, dimension (N)
+*>          WORK is REAL array, dimension ( N )
 *>         If N .ne. 1, WORK contains (D(j) + sigma_I) in its  j-th
 *>         component.  If N = 1, then WORK( 1 ) = 1.
 *> \endverbatim
 *  Authors:
 *  ========
 *
-*> \author Univ. of Tennessee 
-*> \author Univ. of California Berkeley 
-*> \author Univ. of Colorado Denver 
-*> \author NAG Ltd. 
+*> \author Univ. of Tennessee
+*> \author Univ. of California Berkeley
+*> \author Univ. of Colorado Denver
+*> \author NAG Ltd.
 *
 *> \date August 2012
 *
 *
 *     .. Parameters ..
       INTEGER            MAXIT
-*     set MAXIT to 40 from 64. RCL 8/26/2012
-      PARAMETER          ( MAXIT = 40 )
+      PARAMETER          ( MAXIT = 400 )
       REAL               ZERO, ONE, TWO, THREE, FOUR, EIGHT, TEN
       PARAMETER          ( ZERO = 0.0E+0, ONE = 1.0E+0, TWO = 2.0E+0,
      $                   THREE = 3.0E+0, FOUR = 4.0E+0, EIGHT = 8.0E+0,
      $                   TEN = 10.0E+0 )
 *     ..
 *     .. Local Scalars ..
-      LOGICAL            ORGATI, SWTCH, SWTCH3
+      LOGICAL            ORGATI, SWTCH, SWTCH3, GEOMAVG
       INTEGER            II, IIM1, IIP1, IP1, ITER, J, NITER
-      REAL               A, B, C, DELSQ, DELSQ2, DPHI, DPSI, DTIIM,
+      REAL               A, B, C, DELSQ, DELSQ2, SQ2, DPHI, DPSI, DTIIM,
      $                   DTIIP, DTIPSQ, DTISQ, DTNSQ, DTNSQ1, DW, EPS,
-     $                   ERRETM, ETA, PHI, PREW, PSI, RHOINV, SG2LB,
-     $                   SG2UB, TAU, TEMP, TEMP1, TEMP2, W
+     $                   ERRETM, ETA, PHI, PREW, PSI, RHOINV, SGLB,
+     $                   SGUB, TAU, TAU2, TEMP, TEMP1, TEMP2, W
 *     ..
 *     .. Local Arrays ..
       REAL               DD( 3 ), ZZ( 3 )
      $             ( D( N )-D( N-1 )+RHO / ( D( N )+TEMP1 ) ) ) +
      $             Z( N )*Z( N ) / RHO
 *
-*           The following TAU is to approximate
+*           The following TAU2 is to approximate
 *           SIGMA_n^2 - D( N )*D( N )
 *
             IF( C.LE.TEMP ) THEN
                A = -C*DELSQ + Z( N-1 )*Z( N-1 ) + Z( N )*Z( N )
                B = Z( N )*Z( N )*DELSQ
                IF( A.LT.ZERO ) THEN
-                  TAU = TWO*B / ( SQRT( A*A+FOUR*B*C )-A )
+                  TAU2 = TWO*B / ( SQRT( A*A+FOUR*B*C )-A )
                ELSE
-                  TAU = ( A+SQRT( A*A+FOUR*B*C ) ) / ( TWO*C )
+                  TAU2 = ( A+SQRT( A*A+FOUR*B*C ) ) / ( TWO*C )
                END IF
             END IF
 *
 *           It can be proved that
-*               D(N)^2+RHO/2 <= SIGMA_n^2 < D(N)^2+TAU <= D(N)^2+RHO
+*               D(N)^2+RHO/2 <= SIGMA_n^2 < D(N)^2+TAU2 <= D(N)^2+RHO
 *
          ELSE
             DELSQ = ( D( N )-D( N-1 ) )*( D( N )+D( N-1 ) )
             A = -C*DELSQ + Z( N-1 )*Z( N-1 ) + Z( N )*Z( N )
             B = Z( N )*Z( N )*DELSQ
 *
-*           The following TAU is to approximate
+*           The following TAU2 is to approximate
 *           SIGMA_n^2 - D( N )*D( N )
 *
             IF( A.LT.ZERO ) THEN
-               TAU = TWO*B / ( SQRT( A*A+FOUR*B*C )-A )
+               TAU2 = TWO*B / ( SQRT( A*A+FOUR*B*C )-A )
             ELSE
-               TAU = ( A+SQRT( A*A+FOUR*B*C ) ) / ( TWO*C )
+               TAU2 = ( A+SQRT( A*A+FOUR*B*C ) ) / ( TWO*C )
             END IF
 *
 *           It can be proved that
-*           D(N)^2 < D(N)^2+TAU < SIGMA(N)^2 < D(N)^2+RHO/2
+*           D(N)^2 < D(N)^2+TAU2 < SIGMA(N)^2 < D(N)^2+RHO/2
 *
          END IF
 *
-*        The following ETA is to approximate SIGMA_n - D( N )
+*        The following TAU is to approximate SIGMA_n - D( N )
 *
-         ETA = TAU / ( D( N )+SQRT( D( N )*D( N )+TAU ) )
+         TAU = TAU2 / ( D( N )+SQRT( D( N )*D( N )+TAU2 ) )
 *
-         SIGMA = D( N ) + ETA
+         SIGMA = D( N ) + TAU
          DO 30 J = 1, N
-            DELTA( J ) = ( D( J )-D( I ) ) - ETA
-            WORK( J ) = D( J ) + D( I ) + ETA
+            DELTA( J ) = ( D( J )-D( I ) ) - TAU
+            WORK( J ) = D( J ) + D( I ) + TAU
    30    CONTINUE
 *
 *        Evaluate PSI and the derivative DPSI
          PHI = Z( N )*TEMP
          DPHI = TEMP*TEMP
          ERRETM = EIGHT*( -PHI-PSI ) + ERRETM - PHI + RHOINV +
-     $            ABS( TAU )*( DPSI+DPHI )
+     $            ABS( TAU2 )*( DPSI+DPHI )
 *
          W = RHOINV + PHI + PSI
 *
          IF( TEMP.GT.RHO )
      $      ETA = RHO + DTNSQ
 *
-         TAU = TAU + ETA
          ETA = ETA / ( SIGMA+SQRT( ETA+SIGMA*SIGMA ) )
+         TAU = TAU + ETA
+         SIGMA = SIGMA + ETA
+*
          DO 50 J = 1, N
             DELTA( J ) = DELTA( J ) - ETA
             WORK( J ) = WORK( J ) + ETA
    50    CONTINUE
-*
-         SIGMA = SIGMA + ETA
 *
 *        Evaluate PSI and the derivative DPSI
 *
 *
 *        Evaluate PHI and the derivative DPHI
 *
-         TEMP = Z( N ) / ( WORK( N )*DELTA( N ) )
+         TAU2 = WORK( N )*DELTA( N )
+         TEMP = Z( N ) / TAU2
          PHI = Z( N )*TEMP
          DPHI = TEMP*TEMP
          ERRETM = EIGHT*( -PHI-PSI ) + ERRETM - PHI + RHOINV +
-     $            ABS( TAU )*( DPSI+DPHI )
+     $            ABS( TAU2 )*( DPSI+DPHI )
 *
          W = RHOINV + PHI + PSI
 *
             IF( TEMP.LE.ZERO )
      $         ETA = ETA / TWO
 *
-            TAU = TAU + ETA
             ETA = ETA / ( SIGMA+SQRT( ETA+SIGMA*SIGMA ) )
+            TAU = TAU + ETA
+            SIGMA = SIGMA + ETA
+*
             DO 70 J = 1, N
                DELTA( J ) = DELTA( J ) - ETA
                WORK( J ) = WORK( J ) + ETA
    70       CONTINUE
-*
-            SIGMA = SIGMA + ETA
 *
 *           Evaluate PSI and the derivative DPSI
 *
 *
 *           Evaluate PHI and the derivative DPHI
 *
-            TEMP = Z( N ) / ( WORK( N )*DELTA( N ) )
+            TAU2 = WORK( N )*DELTA( N )
+            TEMP = Z( N ) / TAU2
             PHI = Z( N )*TEMP
             DPHI = TEMP*TEMP
             ERRETM = EIGHT*( -PHI-PSI ) + ERRETM - PHI + RHOINV +
-     $               ABS( TAU )*( DPSI+DPHI )
+     $               ABS( TAU2 )*( DPSI+DPHI )
 *
             W = RHOINV + PHI + PSI
    90    CONTINUE
 *
          DELSQ = ( D( IP1 )-D( I ) )*( D( IP1 )+D( I ) )
          DELSQ2 = DELSQ / TWO
-         TEMP = DELSQ2 / ( D( I )+SQRT( D( I )*D( I )+DELSQ2 ) )
+         SQ2=SQRT( ( D( I )*D( I )+D( IP1 )*D( IP1 ) ) / TWO )
+         TEMP = DELSQ2 / ( D( I )+SQ2 )
          DO 100 J = 1, N
             WORK( J ) = D( J ) + D( I ) + TEMP
             DELTA( J ) = ( D( J )-D( I ) ) - TEMP
          W = C + Z( I )*Z( I ) / ( WORK( I )*DELTA( I ) ) +
      $       Z( IP1 )*Z( IP1 ) / ( WORK( IP1 )*DELTA( IP1 ) )
 *
+         GEOMAVG = .FALSE.
          IF( W.GT.ZERO ) THEN
 *
 *           d(i)^2 < the ith sigma^2 < (d(i)^2+d(i+1)^2)/2
 *           We choose d(i) as origin.
 *
             ORGATI = .TRUE.
-            SG2LB = ZERO
-            SG2UB = DELSQ2
+            II = I
+            SGLB = ZERO
+            SGUB = DELSQ2  / ( D( I )+SQ2 )
             A = C*DELSQ + Z( I )*Z( I ) + Z( IP1 )*Z( IP1 )
             B = Z( I )*Z( I )*DELSQ
             IF( A.GT.ZERO ) THEN
-               TAU = TWO*B / ( A+SQRT( ABS( A*A-FOUR*B*C ) ) )
+               TAU2 = TWO*B / ( A+SQRT( ABS( A*A-FOUR*B*C ) ) )
             ELSE
-               TAU = ( A-SQRT( ABS( A*A-FOUR*B*C ) ) ) / ( TWO*C )
+               TAU2 = ( A-SQRT( ABS( A*A-FOUR*B*C ) ) ) / ( TWO*C )
             END IF
 *
-*           TAU now is an estimation of SIGMA^2 - D( I )^2. The
+*           TAU2 now is an estimation of SIGMA^2 - D( I )^2. The
 *           following, however, is the corresponding estimation of
 *           SIGMA - D( I ).
 *
-            ETA = TAU / ( D( I )+SQRT( D( I )*D( I )+TAU ) )
+            TAU = TAU2 / ( D( I )+SQRT( D( I )*D( I )+TAU2 ) )
+            TEMP = SQRT(EPS)
+            IF( (D(I).LE.TEMP*D(IP1)).AND.(ABS(Z(I)).LE.TEMP)
+     $                               .AND.(D(I).GT.ZERO) ) THEN
+               TAU = MIN( TEN*D(I), SGUB )
+               GEOMAVG = .TRUE.
+            END IF
          ELSE
 *
 *           (d(i)^2+d(i+1)^2)/2 <= the ith sigma^2 < d(i+1)^2/2
 *           We choose d(i+1) as origin.
 *
             ORGATI = .FALSE.
-            SG2LB = -DELSQ2
-            SG2UB = ZERO
+            II = IP1
+            SGLB = -DELSQ2  / ( D( II )+SQ2 )
+            SGUB = ZERO
             A = C*DELSQ - Z( I )*Z( I ) - Z( IP1 )*Z( IP1 )
             B = Z( IP1 )*Z( IP1 )*DELSQ
             IF( A.LT.ZERO ) THEN
-               TAU = TWO*B / ( A-SQRT( ABS( A*A+FOUR*B*C ) ) )
+               TAU2 = TWO*B / ( A-SQRT( ABS( A*A+FOUR*B*C ) ) )
             ELSE
-               TAU = -( A+SQRT( ABS( A*A+FOUR*B*C ) ) ) / ( TWO*C )
+               TAU2 = -( A+SQRT( ABS( A*A+FOUR*B*C ) ) ) / ( TWO*C )
             END IF
 *
-*           TAU now is an estimation of SIGMA^2 - D( IP1 )^2. The
+*           TAU2 now is an estimation of SIGMA^2 - D( IP1 )^2. The
 *           following, however, is the corresponding estimation of
 *           SIGMA - D( IP1 ).
 *
-            ETA = TAU / ( D( IP1 )+SQRT( ABS( D( IP1 )*D( IP1 )+
-     $            TAU ) ) )
+            TAU = TAU2 / ( D( IP1 )+SQRT( ABS( D( IP1 )*D( IP1 )+
+     $            TAU2 ) ) )
          END IF
 *
-         IF( ORGATI ) THEN
-            II = I
-            SIGMA = D( I ) + ETA
-            DO 130 J = 1, N
-               WORK( J ) = D( J ) + D( I ) + ETA
-               DELTA( J ) = ( D( J )-D( I ) ) - ETA
-  130       CONTINUE
-         ELSE
-            II = I + 1
-            SIGMA = D( IP1 ) + ETA
-            DO 140 J = 1, N
-               WORK( J ) = D( J ) + D( IP1 ) + ETA
-               DELTA( J ) = ( D( J )-D( IP1 ) ) - ETA
-  140       CONTINUE
-         END IF
+         SIGMA = D( II ) + TAU
+         DO 130 J = 1, N
+            WORK( J ) = D( J ) + D( II ) + TAU
+            DELTA( J ) = ( D( J )-D( II ) ) - TAU
+  130    CONTINUE
          IIM1 = II - 1
          IIP1 = II + 1
 *
          TEMP = Z( II )*TEMP
          W = W + TEMP
          ERRETM = EIGHT*( PHI-PSI ) + ERRETM + TWO*RHOINV +
-     $            THREE*ABS( TEMP ) + ABS( TAU )*DW
+     $            THREE*ABS( TEMP ) + ABS( TAU2 )*DW
 *
 *        Test for convergence
 *
          END IF
 *
          IF( W.LE.ZERO ) THEN
-            SG2LB = MAX( SG2LB, TAU )
+            SGLB = MAX( SGLB, TAU )
          ELSE
-            SG2UB = MIN( SG2UB, TAU )
+            SGUB = MIN( SGUB, TAU )
          END IF
 *
 *        Calculate the new step
             DD( 2 ) = DELTA( II )*WORK( II )
             DD( 3 ) = DTIIP
             CALL SLAED6( NITER, ORGATI, C, DD, ZZ, W, ETA, INFO )
-            IF( INFO.NE.0 )
-     $         GO TO 240
+*
+            IF( INFO.NE.0 ) THEN
+*
+*              If INFO is not 0, i.e., SLAED6 failed, switch back to 2 pole interpolation.
+*
+               SWTCH3 = .FALSE.
+               INFO = 0
+               DTIPSQ = WORK( IP1 )*DELTA( IP1 )
+               DTISQ = WORK( I )*DELTA( I )
+               IF( ORGATI ) THEN
+                  C = W - DTIPSQ*DW + DELSQ*( Z( I ) / DTISQ )**2
+               ELSE
+                  C = W - DTISQ*DW - DELSQ*( Z( IP1 ) / DTIPSQ )**2
+               END IF
+               A = ( DTIPSQ+DTISQ )*W - DTIPSQ*DTISQ*DW
+               B = DTIPSQ*DTISQ*W
+               IF( C.EQ.ZERO ) THEN
+                  IF( A.EQ.ZERO ) THEN
+                     IF( ORGATI ) THEN
+                        A = Z( I )*Z( I ) + DTIPSQ*DTIPSQ*( DPSI+DPHI )
+                     ELSE
+                        A = Z( IP1 )*Z( IP1 ) + DTISQ*DTISQ*( DPSI+DPHI)
+                     END IF
+                  END IF
+                  ETA = B / A
+               ELSE IF( A.LE.ZERO ) THEN
+                  ETA = ( A-SQRT( ABS( A*A-FOUR*B*C ) ) ) / ( TWO*C )
+               ELSE
+                  ETA = TWO*B / ( A+SQRT( ABS( A*A-FOUR*B*C ) ) )
+               END IF
+            END IF
          END IF
 *
 *        Note, eta should be positive if w is negative, and
 *
          IF( W*ETA.GE.ZERO )
      $      ETA = -W / DW
-         IF( ORGATI ) THEN
-            TEMP1 = WORK( I )*DELTA( I )
-            TEMP = ETA - TEMP1
-         ELSE
-            TEMP1 = WORK( IP1 )*DELTA( IP1 )
-            TEMP = ETA - TEMP1
-         END IF
-         IF( TEMP.GT.SG2UB .OR. TEMP.LT.SG2LB ) THEN
+*
+         ETA = ETA / ( SIGMA+SQRT( SIGMA*SIGMA+ETA ) )
+         TEMP = TAU + ETA
+         IF( TEMP.GT.SGUB .OR. TEMP.LT.SGLB ) THEN
             IF( W.LT.ZERO ) THEN
-               ETA = ( SG2UB-TAU ) / TWO
+               ETA = ( SGUB-TAU ) / TWO
             ELSE
-               ETA = ( SG2LB-TAU ) / TWO
+               ETA = ( SGLB-TAU ) / TWO
+            END IF
+            IF( GEOMAVG ) THEN
+               IF( W .LT. ZERO ) THEN
+                  IF( TAU .GT. ZERO ) THEN
+                     ETA = SQRT(SGUB*TAU)-TAU
+                  END IF
+               ELSE
+                  IF( SGLB .GT. ZERO ) THEN
+                     ETA = SQRT(SGLB*TAU)-TAU
+                  END IF
+               END IF
             END IF
          END IF
-*
-         TAU = TAU + ETA
-         ETA = ETA / ( SIGMA+SQRT( SIGMA*SIGMA+ETA ) )
 *
          PREW = W
 *
+         TAU = TAU + ETA
          SIGMA = SIGMA + ETA
+*
          DO 170 J = 1, N
             WORK( J ) = WORK( J ) + ETA
             DELTA( J ) = DELTA( J ) - ETA
             ERRETM = ERRETM + PHI
   190    CONTINUE
 *
-         TEMP = Z( II ) / ( WORK( II )*DELTA( II ) )
+         TAU2 = WORK( II )*DELTA( II )
+         TEMP = Z( II ) / TAU2
          DW = DPSI + DPHI + TEMP*TEMP
          TEMP = Z( II )*TEMP
          W = RHOINV + PHI + PSI + TEMP
          ERRETM = EIGHT*( PHI-PSI ) + ERRETM + TWO*RHOINV +
-     $            THREE*ABS( TEMP ) + ABS( TAU )*DW
-*
-         IF( W.LE.ZERO ) THEN
-            SG2LB = MAX( SG2LB, TAU )
-         ELSE
-            SG2UB = MIN( SG2UB, TAU )
-         END IF
+     $            THREE*ABS( TEMP ) + ABS( TAU2 )*DW
 *
          SWTCH = .FALSE.
          IF( ORGATI ) THEN
 *           Test for convergence
 *
             IF( ABS( W ).LE.EPS*ERRETM ) THEN
+*     $          .OR. (SGUB-SGLB).LE.EIGHT*ABS(SGUB+SGLB) ) THEN
                GO TO 240
             END IF
+*
+            IF( W.LE.ZERO ) THEN
+               SGLB = MAX( SGLB, TAU )
+            ELSE
+               SGUB = MIN( SGUB, TAU )
+            END IF
 *
 *           Calculate the new step
 *
                DD( 2 ) = DELTA( II )*WORK( II )
                DD( 3 ) = DTIIP
                CALL SLAED6( NITER, ORGATI, C, DD, ZZ, W, ETA, INFO )
-               IF( INFO.NE.0 )
-     $            GO TO 240
+*
+               IF( INFO.NE.0 ) THEN
+*
+*                 If INFO is not 0, i.e., SLAED6 failed, switch back to two pole interpolation
+*
+                  SWTCH3 = .FALSE.
+                  INFO = 0
+                  DTIPSQ = WORK( IP1 )*DELTA( IP1 )
+                  DTISQ = WORK( I )*DELTA( I )
+                  IF( .NOT.SWTCH ) THEN
+                     IF( ORGATI ) THEN
+                        C = W - DTIPSQ*DW + DELSQ*( Z( I )/DTISQ )**2
+                     ELSE
+                        C = W - DTISQ*DW - DELSQ*( Z( IP1 )/DTIPSQ )**2
+                     END IF
+                  ELSE
+                     TEMP = Z( II ) / ( WORK( II )*DELTA( II ) )
+                     IF( ORGATI ) THEN
+                        DPSI = DPSI + TEMP*TEMP
+                     ELSE
+                        DPHI = DPHI + TEMP*TEMP
+                     END IF
+                     C = W - DTISQ*DPSI - DTIPSQ*DPHI
+                  END IF
+                  A = ( DTIPSQ+DTISQ )*W - DTIPSQ*DTISQ*DW
+                  B = DTIPSQ*DTISQ*W
+                  IF( C.EQ.ZERO ) THEN
+                     IF( A.EQ.ZERO ) THEN
+                        IF( .NOT.SWTCH ) THEN
+                           IF( ORGATI ) THEN
+                              A = Z( I )*Z( I ) + DTIPSQ*DTIPSQ*
+     $                            ( DPSI+DPHI )
+                           ELSE
+                              A = Z( IP1 )*Z( IP1 ) +
+     $                            DTISQ*DTISQ*( DPSI+DPHI )
+                           END IF
+                        ELSE
+                           A = DTISQ*DTISQ*DPSI + DTIPSQ*DTIPSQ*DPHI
+                        END IF
+                     END IF
+                     ETA = B / A
+                  ELSE IF( A.LE.ZERO ) THEN
+                     ETA = ( A-SQRT( ABS( A*A-FOUR*B*C ) ) ) / ( TWO*C )
+                  ELSE
+                     ETA = TWO*B / ( A+SQRT( ABS( A*A-FOUR*B*C ) ) )
+                  END IF
+               END IF
             END IF
 *
 *           Note, eta should be positive if w is negative, and
 *
             IF( W*ETA.GE.ZERO )
      $         ETA = -W / DW
-            IF( ORGATI ) THEN
-               TEMP1 = WORK( I )*DELTA( I )
-               TEMP = ETA - TEMP1
-            ELSE
-               TEMP1 = WORK( IP1 )*DELTA( IP1 )
-               TEMP = ETA - TEMP1
-            END IF
-            IF( TEMP.GT.SG2UB .OR. TEMP.LT.SG2LB ) THEN
+*
+            ETA = ETA / ( SIGMA+SQRT( SIGMA*SIGMA+ETA ) )
+            TEMP=TAU+ETA
+            IF( TEMP.GT.SGUB .OR. TEMP.LT.SGLB ) THEN
                IF( W.LT.ZERO ) THEN
-                  ETA = ( SG2UB-TAU ) / TWO
+                  ETA = ( SGUB-TAU ) / TWO
                ELSE
-                  ETA = ( SG2LB-TAU ) / TWO
+                  ETA = ( SGLB-TAU ) / TWO
+               END IF
+               IF( GEOMAVG ) THEN
+                  IF( W .LT. ZERO ) THEN
+                     IF( TAU .GT. ZERO ) THEN
+                        ETA = SQRT(SGUB*TAU)-TAU
+                     END IF
+                  ELSE
+                     IF( SGLB .GT. ZERO ) THEN
+                        ETA = SQRT(SGLB*TAU)-TAU
+                     END IF
+                  END IF
                END IF
             END IF
 *
-            TAU = TAU + ETA
-            ETA = ETA / ( SIGMA+SQRT( SIGMA*SIGMA+ETA ) )
+            PREW = W
 *
+            TAU = TAU + ETA
             SIGMA = SIGMA + ETA
+*
             DO 200 J = 1, N
                WORK( J ) = WORK( J ) + ETA
                DELTA( J ) = DELTA( J ) - ETA
   200       CONTINUE
-*
-            PREW = W
 *
 *           Evaluate PSI and the derivative DPSI
 *
                ERRETM = ERRETM + PHI
   220       CONTINUE
 *
-            TEMP = Z( II ) / ( WORK( II )*DELTA( II ) )
+            TAU2 = WORK( II )*DELTA( II )
+            TEMP = Z( II ) / TAU2
             DW = DPSI + DPHI + TEMP*TEMP
             TEMP = Z( II )*TEMP
             W = RHOINV + PHI + PSI + TEMP
             ERRETM = EIGHT*( PHI-PSI ) + ERRETM + TWO*RHOINV +
-     $               THREE*ABS( TEMP ) + ABS( TAU )*DW
+     $               THREE*ABS( TEMP ) + ABS( TAU2 )*DW
+*
             IF( W*PREW.GT.ZERO .AND. ABS( W ).GT.ABS( PREW ) / TEN )
      $         SWTCH = .NOT.SWTCH
-*           I don't understand the following 5 lines in the first place. RCL 8/26/2012
-*            IF( W.LE.ZERO ) THEN
-*               SG2LB = MAX( SG2LB, TAU )
-*            ELSE
-*               SG2UB = MIN( SG2UB, TAU )
-*            END IF
 *
   230    CONTINUE
 *
index bc0ae2d2ece694536bdb01ebb49d59b4774049ac..0dc39b788519fb5a150659cd97974c5808c79b08 100644 (file)
@@ -1,7 +1,7 @@
 SVD:  Data file for testing Singular Value Decomposition routines
-19                                            Number of values of M
-0 0 0 1 1 1 2 2 3 3 3 10 10 16 16 30 30 40 40 Values of M
-0 1 3 0 1 2 0 1 0 1 3 10 16 10 16 30 40 30 40 Values of N
+18                                            Number of values of M
+0 0 0 1 1 2 2 3 3 3 10 10 16 16 30 30 40 40   Values of M
+0 1 3 1 2 0 1 0 1 3 10 16 10 16 30 40 30 40   Values of N
 5                                             Number of parameter values
 1 3  3  3 20                                  Values of NB (blocksize)
 2 2  2  2  2                                  Values of NBMIN (minimum blocksize)