1 /* slaed4.f -- translated by f2c (version 20061008).
2 You must link the resulting object file with libf2c:
3 on Microsoft Windows system, link with libf2c.lib;
4 on Linux or Unix systems, link with .../path/to/libf2c.a -lm
5 or, if you install libf2c.a in a standard place, with -lf2c -lm
6 -- in that order, at the end of the command line, as in
8 Source for libf2c is in /netlib/f2c/libf2c.zip, e.g.,
10 http://www.netlib.org/f2c/libf2c.zip
16 /* Subroutine */ int slaed4_(integer *n, integer *i__, real *d__, real *z__,
17 real *delta, real *rho, real *dlam, integer *info)
19 /* System generated locals */
23 /* Builtin functions */
24 double sqrt(doublereal);
33 real del, eta, phi, eps, tau, psi;
37 real temp, prew, temp1, dltlb, dltub, midpt;
40 extern /* Subroutine */ int slaed5_(integer *, real *, real *, real *,
41 real *, real *), slaed6_(integer *, logical *, real *, real *,
42 real *, real *, real *, integer *);
44 extern doublereal slamch_(char *);
49 /* -- LAPACK routine (version 3.2) -- */
50 /* Univ. of Tennessee, Univ. of California Berkeley and NAG Ltd.. */
53 /* .. Scalar Arguments .. */
55 /* .. Array Arguments .. */
61 /* This subroutine computes the I-th updated eigenvalue of a symmetric */
62 /* rank-one modification to a diagonal matrix whose elements are */
63 /* given in the array d, and that */
65 /* D(i) < D(j) for i < j */
67 /* and that RHO > 0. This is arranged by the calling routine, and is */
68 /* no loss in generality. The rank-one modified system is thus */
70 /* diag( D ) + RHO * Z * Z_transpose. */
72 /* where we assume the Euclidean norm of Z is 1. */
74 /* The method consists of approximating the rational functions in the */
75 /* secular equation by simpler interpolating rational functions. */
80 /* N (input) INTEGER */
81 /* The length of all arrays. */
83 /* I (input) INTEGER */
84 /* The index of the eigenvalue to be computed. 1 <= I <= N. */
86 /* D (input) REAL array, dimension (N) */
87 /* The original eigenvalues. It is assumed that they are in */
88 /* order, D(I) < D(J) for I < J. */
90 /* Z (input) REAL array, dimension (N) */
91 /* The components of the updating vector. */
93 /* DELTA (output) REAL array, dimension (N) */
94 /* If N .GT. 2, DELTA contains (D(j) - lambda_I) in its j-th */
95 /* component. If N = 1, then DELTA(1) = 1. If N = 2, see SLAED5 */
96 /* for detail. The vector DELTA contains the information necessary */
97 /* to construct the eigenvectors by SLAED3 and SLAED9. */
99 /* RHO (input) REAL */
100 /* The scalar in the symmetric updating formula. */
102 /* DLAM (output) REAL */
103 /* The computed lambda_I, the I-th updated eigenvalue. */
105 /* INFO (output) INTEGER */
106 /* = 0: successful exit */
107 /* > 0: if INFO = 1, the updating process failed. */
109 /* Internal Parameters */
110 /* =================== */
112 /* Logical variable ORGATI (origin-at-i?) is used for distinguishing */
113 /* whether D(i) or D(i+1) is treated as the origin. */
115 /* ORGATI = .true. origin at i */
116 /* ORGATI = .false. origin at i+1 */
118 /* Logical variable SWTCH3 (switch-for-3-poles?) is for noting */
119 /* if we are working with THREE poles! */
121 /* MAXIT is the maximum number of iterations allowed for each */
124 /* Further Details */
125 /* =============== */
127 /* Based on contributions by */
128 /* Ren-Cang Li, Computer Science Division, University of California */
129 /* at Berkeley, USA */
131 /* ===================================================================== */
133 /* .. Parameters .. */
135 /* .. Local Scalars .. */
137 /* .. Local Arrays .. */
139 /* .. External Functions .. */
141 /* .. External Subroutines .. */
143 /* .. Intrinsic Functions .. */
145 /* .. Executable Statements .. */
147 /* Since this routine is called in an inner loop, we do no argument */
150 /* Quick return for N=1 and 2. */
152 /* Parameter adjustments */
161 /* Presumably, I=1 upon entry */
163 *dlam = d__[1] + *rho * z__[1] * z__[1];
168 slaed5_(i__, &d__[1], &z__[1], &delta[1], rho, dlam);
172 /* Compute machine epsilon */
174 eps = slamch_("Epsilon");
181 /* Initialize some basic variables */
186 /* Calculate initial guess */
190 /* If ||Z||_2 is not one, then TEMP should be set to */
191 /* RHO * ||Z||_2^2 / TWO */
194 for (j = 1; j <= i__1; ++j) {
195 delta[j] = d__[j] - d__[*i__] - midpt;
201 for (j = 1; j <= i__1; ++j) {
202 psi += z__[j] * z__[j] / delta[j];
207 w = c__ + z__[ii] * z__[ii] / delta[ii] + z__[*n] * z__[*n] / delta[*
211 temp = z__[*n - 1] * z__[*n - 1] / (d__[*n] - d__[*n - 1] + *rho)
212 + z__[*n] * z__[*n] / *rho;
216 del = d__[*n] - d__[*n - 1];
217 a = -c__ * del + z__[*n - 1] * z__[*n - 1] + z__[*n] * z__[*n]
219 b = z__[*n] * z__[*n] * del;
221 tau = b * 2.f / (sqrt(a * a + b * 4.f * c__) - a);
223 tau = (a + sqrt(a * a + b * 4.f * c__)) / (c__ * 2.f);
227 /* It can be proved that */
228 /* D(N)+RHO/2 <= LAMBDA(N) < D(N)+TAU <= D(N)+RHO */
233 del = d__[*n] - d__[*n - 1];
234 a = -c__ * del + z__[*n - 1] * z__[*n - 1] + z__[*n] * z__[*n];
235 b = z__[*n] * z__[*n] * del;
237 tau = b * 2.f / (sqrt(a * a + b * 4.f * c__) - a);
239 tau = (a + sqrt(a * a + b * 4.f * c__)) / (c__ * 2.f);
242 /* It can be proved that */
243 /* D(N) < D(N)+TAU < LAMBDA(N) < D(N)+RHO/2 */
250 for (j = 1; j <= i__1; ++j) {
251 delta[j] = d__[j] - d__[*i__] - tau;
255 /* Evaluate PSI and the derivative DPSI */
261 for (j = 1; j <= i__1; ++j) {
262 temp = z__[j] / delta[j];
263 psi += z__[j] * temp;
268 erretm = dabs(erretm);
270 /* Evaluate PHI and the derivative DPHI */
272 temp = z__[*n] / delta[*n];
273 phi = z__[*n] * temp;
275 erretm = (-phi - psi) * 8.f + erretm - phi + rhoinv + dabs(tau) * (
278 w = rhoinv + phi + psi;
280 /* Test for convergence */
282 if (dabs(w) <= eps * erretm) {
283 *dlam = d__[*i__] + tau;
288 dltlb = dmax(dltlb,tau);
290 dltub = dmin(dltub,tau);
293 /* Calculate the new step */
296 c__ = w - delta[*n - 1] * dpsi - delta[*n] * dphi;
297 a = (delta[*n - 1] + delta[*n]) * w - delta[*n - 1] * delta[*n] * (
299 b = delta[*n - 1] * delta[*n] * w;
305 /* ETA = RHO - TAU */
307 } else if (a >= 0.f) {
308 eta = (a + sqrt((r__1 = a * a - b * 4.f * c__, dabs(r__1)))) / (
311 eta = b * 2.f / (a - sqrt((r__1 = a * a - b * 4.f * c__, dabs(
315 /* Note, eta should be positive if w is negative, and */
316 /* eta should be negative otherwise. However, */
317 /* if for some reason caused by roundoff, eta*w > 0, */
318 /* we simply use one Newton step instead. This way */
319 /* will guarantee eta*w < 0. */
322 eta = -w / (dpsi + dphi);
325 if (temp > dltub || temp < dltlb) {
327 eta = (dltub - tau) / 2.f;
329 eta = (dltlb - tau) / 2.f;
333 for (j = 1; j <= i__1; ++j) {
340 /* Evaluate PSI and the derivative DPSI */
346 for (j = 1; j <= i__1; ++j) {
347 temp = z__[j] / delta[j];
348 psi += z__[j] * temp;
353 erretm = dabs(erretm);
355 /* Evaluate PHI and the derivative DPHI */
357 temp = z__[*n] / delta[*n];
358 phi = z__[*n] * temp;
360 erretm = (-phi - psi) * 8.f + erretm - phi + rhoinv + dabs(tau) * (
363 w = rhoinv + phi + psi;
365 /* Main loop to update the values of the array DELTA */
369 for (niter = iter; niter <= 30; ++niter) {
371 /* Test for convergence */
373 if (dabs(w) <= eps * erretm) {
374 *dlam = d__[*i__] + tau;
379 dltlb = dmax(dltlb,tau);
381 dltub = dmin(dltub,tau);
384 /* Calculate the new step */
386 c__ = w - delta[*n - 1] * dpsi - delta[*n] * dphi;
387 a = (delta[*n - 1] + delta[*n]) * w - delta[*n - 1] * delta[*n] *
389 b = delta[*n - 1] * delta[*n] * w;
391 eta = (a + sqrt((r__1 = a * a - b * 4.f * c__, dabs(r__1)))) /
394 eta = b * 2.f / (a - sqrt((r__1 = a * a - b * 4.f * c__, dabs(
398 /* Note, eta should be positive if w is negative, and */
399 /* eta should be negative otherwise. However, */
400 /* if for some reason caused by roundoff, eta*w > 0, */
401 /* we simply use one Newton step instead. This way */
402 /* will guarantee eta*w < 0. */
405 eta = -w / (dpsi + dphi);
408 if (temp > dltub || temp < dltlb) {
410 eta = (dltub - tau) / 2.f;
412 eta = (dltlb - tau) / 2.f;
416 for (j = 1; j <= i__1; ++j) {
423 /* Evaluate PSI and the derivative DPSI */
429 for (j = 1; j <= i__1; ++j) {
430 temp = z__[j] / delta[j];
431 psi += z__[j] * temp;
436 erretm = dabs(erretm);
438 /* Evaluate PHI and the derivative DPHI */
440 temp = z__[*n] / delta[*n];
441 phi = z__[*n] * temp;
443 erretm = (-phi - psi) * 8.f + erretm - phi + rhoinv + dabs(tau) *
446 w = rhoinv + phi + psi;
450 /* Return with INFO = 1, NITER = MAXIT and not converged */
453 *dlam = d__[*i__] + tau;
456 /* End for the case I = N */
460 /* The case for I < N */
465 /* Calculate initial guess */
467 del = d__[ip1] - d__[*i__];
470 for (j = 1; j <= i__1; ++j) {
471 delta[j] = d__[j] - d__[*i__] - midpt;
477 for (j = 1; j <= i__1; ++j) {
478 psi += z__[j] * z__[j] / delta[j];
484 for (j = *n; j >= i__1; --j) {
485 phi += z__[j] * z__[j] / delta[j];
488 c__ = rhoinv + psi + phi;
489 w = c__ + z__[*i__] * z__[*i__] / delta[*i__] + z__[ip1] * z__[ip1] /
494 /* d(i)< the ith eigenvalue < (d(i)+d(i+1))/2 */
496 /* We choose d(i) as origin. */
499 a = c__ * del + z__[*i__] * z__[*i__] + z__[ip1] * z__[ip1];
500 b = z__[*i__] * z__[*i__] * del;
502 tau = b * 2.f / (a + sqrt((r__1 = a * a - b * 4.f * c__, dabs(
505 tau = (a - sqrt((r__1 = a * a - b * 4.f * c__, dabs(r__1)))) /
512 /* (d(i)+d(i+1))/2 <= the ith eigenvalue < d(i+1) */
514 /* We choose d(i+1) as origin. */
517 a = c__ * del - z__[*i__] * z__[*i__] - z__[ip1] * z__[ip1];
518 b = z__[ip1] * z__[ip1] * del;
520 tau = b * 2.f / (a - sqrt((r__1 = a * a + b * 4.f * c__, dabs(
523 tau = -(a + sqrt((r__1 = a * a + b * 4.f * c__, dabs(r__1))))
532 for (j = 1; j <= i__1; ++j) {
533 delta[j] = d__[j] - d__[*i__] - tau;
538 for (j = 1; j <= i__1; ++j) {
539 delta[j] = d__[j] - d__[ip1] - tau;
551 /* Evaluate PSI and the derivative DPSI */
557 for (j = 1; j <= i__1; ++j) {
558 temp = z__[j] / delta[j];
559 psi += z__[j] * temp;
564 erretm = dabs(erretm);
566 /* Evaluate PHI and the derivative DPHI */
571 for (j = *n; j >= i__1; --j) {
572 temp = z__[j] / delta[j];
573 phi += z__[j] * temp;
579 w = rhoinv + phi + psi;
581 /* W is the value of the secular function with */
582 /* its ii-th element removed. */
594 if (ii == 1 || ii == *n) {
598 temp = z__[ii] / delta[ii];
599 dw = dpsi + dphi + temp * temp;
600 temp = z__[ii] * temp;
602 erretm = (phi - psi) * 8.f + erretm + rhoinv * 2.f + dabs(temp) * 3.f
605 /* Test for convergence */
607 if (dabs(w) <= eps * erretm) {
609 *dlam = d__[*i__] + tau;
611 *dlam = d__[ip1] + tau;
617 dltlb = dmax(dltlb,tau);
619 dltub = dmin(dltub,tau);
622 /* Calculate the new step */
627 /* Computing 2nd power */
628 r__1 = z__[*i__] / delta[*i__];
629 c__ = w - delta[ip1] * dw - (d__[*i__] - d__[ip1]) * (r__1 *
632 /* Computing 2nd power */
633 r__1 = z__[ip1] / delta[ip1];
634 c__ = w - delta[*i__] * dw - (d__[ip1] - d__[*i__]) * (r__1 *
637 a = (delta[*i__] + delta[ip1]) * w - delta[*i__] * delta[ip1] *
639 b = delta[*i__] * delta[ip1] * w;
643 a = z__[*i__] * z__[*i__] + delta[ip1] * delta[ip1] *
646 a = z__[ip1] * z__[ip1] + delta[*i__] * delta[*i__] *
651 } else if (a <= 0.f) {
652 eta = (a - sqrt((r__1 = a * a - b * 4.f * c__, dabs(r__1)))) /
655 eta = b * 2.f / (a + sqrt((r__1 = a * a - b * 4.f * c__, dabs(
660 /* Interpolation using THREE most relevant poles */
662 temp = rhoinv + psi + phi;
664 temp1 = z__[iim1] / delta[iim1];
666 c__ = temp - delta[iip1] * (dpsi + dphi) - (d__[iim1] - d__[
668 zz[0] = z__[iim1] * z__[iim1];
669 zz[2] = delta[iip1] * delta[iip1] * (dpsi - temp1 + dphi);
671 temp1 = z__[iip1] / delta[iip1];
673 c__ = temp - delta[iim1] * (dpsi + dphi) - (d__[iip1] - d__[
675 zz[0] = delta[iim1] * delta[iim1] * (dpsi + (dphi - temp1));
676 zz[2] = z__[iip1] * z__[iip1];
678 zz[1] = z__[ii] * z__[ii];
679 slaed6_(&niter, &orgati, &c__, &delta[iim1], zz, &w, &eta, info);
685 /* Note, eta should be positive if w is negative, and */
686 /* eta should be negative otherwise. However, */
687 /* if for some reason caused by roundoff, eta*w > 0, */
688 /* we simply use one Newton step instead. This way */
689 /* will guarantee eta*w < 0. */
691 if (w * eta >= 0.f) {
695 if (temp > dltub || temp < dltlb) {
697 eta = (dltub - tau) / 2.f;
699 eta = (dltlb - tau) / 2.f;
706 for (j = 1; j <= i__1; ++j) {
711 /* Evaluate PSI and the derivative DPSI */
717 for (j = 1; j <= i__1; ++j) {
718 temp = z__[j] / delta[j];
719 psi += z__[j] * temp;
724 erretm = dabs(erretm);
726 /* Evaluate PHI and the derivative DPHI */
731 for (j = *n; j >= i__1; --j) {
732 temp = z__[j] / delta[j];
733 phi += z__[j] * temp;
739 temp = z__[ii] / delta[ii];
740 dw = dpsi + dphi + temp * temp;
741 temp = z__[ii] * temp;
742 w = rhoinv + phi + psi + temp;
743 erretm = (phi - psi) * 8.f + erretm + rhoinv * 2.f + dabs(temp) * 3.f
744 + (r__1 = tau + eta, dabs(r__1)) * dw;
748 if (-w > dabs(prew) / 10.f) {
752 if (w > dabs(prew) / 10.f) {
759 /* Main loop to update the values of the array DELTA */
763 for (niter = iter; niter <= 30; ++niter) {
765 /* Test for convergence */
767 if (dabs(w) <= eps * erretm) {
769 *dlam = d__[*i__] + tau;
771 *dlam = d__[ip1] + tau;
777 dltlb = dmax(dltlb,tau);
779 dltub = dmin(dltub,tau);
782 /* Calculate the new step */
787 /* Computing 2nd power */
788 r__1 = z__[*i__] / delta[*i__];
789 c__ = w - delta[ip1] * dw - (d__[*i__] - d__[ip1]) * (
792 /* Computing 2nd power */
793 r__1 = z__[ip1] / delta[ip1];
794 c__ = w - delta[*i__] * dw - (d__[ip1] - d__[*i__]) *
798 temp = z__[ii] / delta[ii];
804 c__ = w - delta[*i__] * dpsi - delta[ip1] * dphi;
806 a = (delta[*i__] + delta[ip1]) * w - delta[*i__] * delta[ip1]
808 b = delta[*i__] * delta[ip1] * w;
813 a = z__[*i__] * z__[*i__] + delta[ip1] *
814 delta[ip1] * (dpsi + dphi);
816 a = z__[ip1] * z__[ip1] + delta[*i__] * delta[
817 *i__] * (dpsi + dphi);
820 a = delta[*i__] * delta[*i__] * dpsi + delta[ip1]
825 } else if (a <= 0.f) {
826 eta = (a - sqrt((r__1 = a * a - b * 4.f * c__, dabs(r__1))
829 eta = b * 2.f / (a + sqrt((r__1 = a * a - b * 4.f * c__,
834 /* Interpolation using THREE most relevant poles */
836 temp = rhoinv + psi + phi;
838 c__ = temp - delta[iim1] * dpsi - delta[iip1] * dphi;
839 zz[0] = delta[iim1] * delta[iim1] * dpsi;
840 zz[2] = delta[iip1] * delta[iip1] * dphi;
843 temp1 = z__[iim1] / delta[iim1];
845 c__ = temp - delta[iip1] * (dpsi + dphi) - (d__[iim1]
846 - d__[iip1]) * temp1;
847 zz[0] = z__[iim1] * z__[iim1];
848 zz[2] = delta[iip1] * delta[iip1] * (dpsi - temp1 +
851 temp1 = z__[iip1] / delta[iip1];
853 c__ = temp - delta[iim1] * (dpsi + dphi) - (d__[iip1]
854 - d__[iim1]) * temp1;
855 zz[0] = delta[iim1] * delta[iim1] * (dpsi + (dphi -
857 zz[2] = z__[iip1] * z__[iip1];
860 slaed6_(&niter, &orgati, &c__, &delta[iim1], zz, &w, &eta,
867 /* Note, eta should be positive if w is negative, and */
868 /* eta should be negative otherwise. However, */
869 /* if for some reason caused by roundoff, eta*w > 0, */
870 /* we simply use one Newton step instead. This way */
871 /* will guarantee eta*w < 0. */
873 if (w * eta >= 0.f) {
877 if (temp > dltub || temp < dltlb) {
879 eta = (dltub - tau) / 2.f;
881 eta = (dltlb - tau) / 2.f;
886 for (j = 1; j <= i__1; ++j) {
894 /* Evaluate PSI and the derivative DPSI */
900 for (j = 1; j <= i__1; ++j) {
901 temp = z__[j] / delta[j];
902 psi += z__[j] * temp;
907 erretm = dabs(erretm);
909 /* Evaluate PHI and the derivative DPHI */
914 for (j = *n; j >= i__1; --j) {
915 temp = z__[j] / delta[j];
916 phi += z__[j] * temp;
922 temp = z__[ii] / delta[ii];
923 dw = dpsi + dphi + temp * temp;
924 temp = z__[ii] * temp;
925 w = rhoinv + phi + psi + temp;
926 erretm = (phi - psi) * 8.f + erretm + rhoinv * 2.f + dabs(temp) *
927 3.f + dabs(tau) * dw;
928 if (w * prew > 0.f && dabs(w) > dabs(prew) / 10.f) {
935 /* Return with INFO = 1, NITER = MAXIT and not converged */
939 *dlam = d__[*i__] + tau;
941 *dlam = d__[ip1] + tau;