3 /* Subroutine */ int dlaed4_(integer *n, integer *i__, doublereal *d__,
4 doublereal *z__, doublereal *delta, doublereal *rho, doublereal *dlam,
7 /* System generated locals */
11 /* Builtin functions */
12 double sqrt(doublereal);
21 doublereal del, eta, phi, eps, tau, psi;
23 doublereal dphi, dpsi;
25 doublereal temp, prew, temp1, dltlb, dltub, midpt;
28 extern /* Subroutine */ int dlaed5_(integer *, doublereal *, doublereal *,
29 doublereal *, doublereal *, doublereal *), dlaed6_(integer *,
30 logical *, doublereal *, doublereal *, doublereal *, doublereal *,
31 doublereal *, integer *);
33 extern doublereal dlamch_(char *);
35 doublereal erretm, rhoinv;
38 /* -- LAPACK routine (version 3.1) -- */
39 /* Univ. of Tennessee, Univ. of California Berkeley and NAG Ltd.. */
42 /* .. Scalar Arguments .. */
44 /* .. Array Arguments .. */
50 /* This subroutine computes the I-th updated eigenvalue of a symmetric */
51 /* rank-one modification to a diagonal matrix whose elements are */
52 /* given in the array d, and that */
54 /* D(i) < D(j) for i < j */
56 /* and that RHO > 0. This is arranged by the calling routine, and is */
57 /* no loss in generality. The rank-one modified system is thus */
59 /* diag( D ) + RHO * Z * Z_transpose. */
61 /* where we assume the Euclidean norm of Z is 1. */
63 /* The method consists of approximating the rational functions in the */
64 /* secular equation by simpler interpolating rational functions. */
69 /* N (input) INTEGER */
70 /* The length of all arrays. */
72 /* I (input) INTEGER */
73 /* The index of the eigenvalue to be computed. 1 <= I <= N. */
75 /* D (input) DOUBLE PRECISION array, dimension (N) */
76 /* The original eigenvalues. It is assumed that they are in */
77 /* order, D(I) < D(J) for I < J. */
79 /* Z (input) DOUBLE PRECISION array, dimension (N) */
80 /* The components of the updating vector. */
82 /* DELTA (output) DOUBLE PRECISION array, dimension (N) */
83 /* If N .GT. 2, DELTA contains (D(j) - lambda_I) in its j-th */
84 /* component. If N = 1, then DELTA(1) = 1. If N = 2, see DLAED5 */
85 /* for detail. The vector DELTA contains the information necessary */
86 /* to construct the eigenvectors by DLAED3 and DLAED9. */
88 /* RHO (input) DOUBLE PRECISION */
89 /* The scalar in the symmetric updating formula. */
91 /* DLAM (output) DOUBLE PRECISION */
92 /* The computed lambda_I, the I-th updated eigenvalue. */
94 /* INFO (output) INTEGER */
95 /* = 0: successful exit */
96 /* > 0: if INFO = 1, the updating process failed. */
98 /* Internal Parameters */
99 /* =================== */
101 /* Logical variable ORGATI (origin-at-i?) is used for distinguishing */
102 /* whether D(i) or D(i+1) is treated as the origin. */
104 /* ORGATI = .true. origin at i */
105 /* ORGATI = .false. origin at i+1 */
107 /* Logical variable SWTCH3 (switch-for-3-poles?) is for noting */
108 /* if we are working with THREE poles! */
110 /* MAXIT is the maximum number of iterations allowed for each */
113 /* Further Details */
114 /* =============== */
116 /* Based on contributions by */
117 /* Ren-Cang Li, Computer Science Division, University of California */
118 /* at Berkeley, USA */
120 /* ===================================================================== */
122 /* .. Parameters .. */
124 /* .. Local Scalars .. */
126 /* .. Local Arrays .. */
128 /* .. External Functions .. */
130 /* .. External Subroutines .. */
132 /* .. Intrinsic Functions .. */
134 /* .. Executable Statements .. */
136 /* Since this routine is called in an inner loop, we do no argument */
139 /* Quick return for N=1 and 2. */
141 /* Parameter adjustments */
150 /* Presumably, I=1 upon entry */
152 *dlam = d__[1] + *rho * z__[1] * z__[1];
157 dlaed5_(i__, &d__[1], &z__[1], &delta[1], rho, dlam);
161 /* Compute machine epsilon */
163 eps = dlamch_("Epsilon");
170 /* Initialize some basic variables */
175 /* Calculate initial guess */
179 /* If ||Z||_2 is not one, then TEMP should be set to */
180 /* RHO * ||Z||_2^2 / TWO */
183 for (j = 1; j <= i__1; ++j) {
184 delta[j] = d__[j] - d__[*i__] - midpt;
190 for (j = 1; j <= i__1; ++j) {
191 psi += z__[j] * z__[j] / delta[j];
196 w = c__ + z__[ii] * z__[ii] / delta[ii] + z__[*n] * z__[*n] / delta[*
200 temp = z__[*n - 1] * z__[*n - 1] / (d__[*n] - d__[*n - 1] + *rho)
201 + z__[*n] * z__[*n] / *rho;
205 del = d__[*n] - d__[*n - 1];
206 a = -c__ * del + z__[*n - 1] * z__[*n - 1] + z__[*n] * z__[*n]
208 b = z__[*n] * z__[*n] * del;
210 tau = b * 2. / (sqrt(a * a + b * 4. * c__) - a);
212 tau = (a + sqrt(a * a + b * 4. * c__)) / (c__ * 2.);
216 /* It can be proved that */
217 /* D(N)+RHO/2 <= LAMBDA(N) < D(N)+TAU <= D(N)+RHO */
222 del = d__[*n] - d__[*n - 1];
223 a = -c__ * del + z__[*n - 1] * z__[*n - 1] + z__[*n] * z__[*n];
224 b = z__[*n] * z__[*n] * del;
226 tau = b * 2. / (sqrt(a * a + b * 4. * c__) - a);
228 tau = (a + sqrt(a * a + b * 4. * c__)) / (c__ * 2.);
231 /* It can be proved that */
232 /* D(N) < D(N)+TAU < LAMBDA(N) < D(N)+RHO/2 */
239 for (j = 1; j <= i__1; ++j) {
240 delta[j] = d__[j] - d__[*i__] - tau;
244 /* Evaluate PSI and the derivative DPSI */
250 for (j = 1; j <= i__1; ++j) {
251 temp = z__[j] / delta[j];
252 psi += z__[j] * temp;
257 erretm = abs(erretm);
259 /* Evaluate PHI and the derivative DPHI */
261 temp = z__[*n] / delta[*n];
262 phi = z__[*n] * temp;
264 erretm = (-phi - psi) * 8. + erretm - phi + rhoinv + abs(tau) * (dpsi
267 w = rhoinv + phi + psi;
269 /* Test for convergence */
271 if (abs(w) <= eps * erretm) {
272 *dlam = d__[*i__] + tau;
277 dltlb = max(dltlb,tau);
279 dltub = min(dltub,tau);
282 /* Calculate the new step */
285 c__ = w - delta[*n - 1] * dpsi - delta[*n] * dphi;
286 a = (delta[*n - 1] + delta[*n]) * w - delta[*n - 1] * delta[*n] * (
288 b = delta[*n - 1] * delta[*n] * w;
294 /* ETA = RHO - TAU */
296 } else if (a >= 0.) {
297 eta = (a + sqrt((d__1 = a * a - b * 4. * c__, abs(d__1)))) / (c__
300 eta = b * 2. / (a - sqrt((d__1 = a * a - b * 4. * c__, abs(d__1)))
304 /* Note, eta should be positive if w is negative, and */
305 /* eta should be negative otherwise. However, */
306 /* if for some reason caused by roundoff, eta*w > 0, */
307 /* we simply use one Newton step instead. This way */
308 /* will guarantee eta*w < 0. */
311 eta = -w / (dpsi + dphi);
314 if (temp > dltub || temp < dltlb) {
316 eta = (dltub - tau) / 2.;
318 eta = (dltlb - tau) / 2.;
322 for (j = 1; j <= i__1; ++j) {
329 /* Evaluate PSI and the derivative DPSI */
335 for (j = 1; j <= i__1; ++j) {
336 temp = z__[j] / delta[j];
337 psi += z__[j] * temp;
342 erretm = abs(erretm);
344 /* Evaluate PHI and the derivative DPHI */
346 temp = z__[*n] / delta[*n];
347 phi = z__[*n] * temp;
349 erretm = (-phi - psi) * 8. + erretm - phi + rhoinv + abs(tau) * (dpsi
352 w = rhoinv + phi + psi;
354 /* Main loop to update the values of the array DELTA */
358 for (niter = iter; niter <= 30; ++niter) {
360 /* Test for convergence */
362 if (abs(w) <= eps * erretm) {
363 *dlam = d__[*i__] + tau;
368 dltlb = max(dltlb,tau);
370 dltub = min(dltub,tau);
373 /* Calculate the new step */
375 c__ = w - delta[*n - 1] * dpsi - delta[*n] * dphi;
376 a = (delta[*n - 1] + delta[*n]) * w - delta[*n - 1] * delta[*n] *
378 b = delta[*n - 1] * delta[*n] * w;
380 eta = (a + sqrt((d__1 = a * a - b * 4. * c__, abs(d__1)))) / (
383 eta = b * 2. / (a - sqrt((d__1 = a * a - b * 4. * c__, abs(
387 /* Note, eta should be positive if w is negative, and */
388 /* eta should be negative otherwise. However, */
389 /* if for some reason caused by roundoff, eta*w > 0, */
390 /* we simply use one Newton step instead. This way */
391 /* will guarantee eta*w < 0. */
394 eta = -w / (dpsi + dphi);
397 if (temp > dltub || temp < dltlb) {
399 eta = (dltub - tau) / 2.;
401 eta = (dltlb - tau) / 2.;
405 for (j = 1; j <= i__1; ++j) {
412 /* Evaluate PSI and the derivative DPSI */
418 for (j = 1; j <= i__1; ++j) {
419 temp = z__[j] / delta[j];
420 psi += z__[j] * temp;
425 erretm = abs(erretm);
427 /* Evaluate PHI and the derivative DPHI */
429 temp = z__[*n] / delta[*n];
430 phi = z__[*n] * temp;
432 erretm = (-phi - psi) * 8. + erretm - phi + rhoinv + abs(tau) * (
435 w = rhoinv + phi + psi;
439 /* Return with INFO = 1, NITER = MAXIT and not converged */
442 *dlam = d__[*i__] + tau;
445 /* End for the case I = N */
449 /* The case for I < N */
454 /* Calculate initial guess */
456 del = d__[ip1] - d__[*i__];
459 for (j = 1; j <= i__1; ++j) {
460 delta[j] = d__[j] - d__[*i__] - midpt;
466 for (j = 1; j <= i__1; ++j) {
467 psi += z__[j] * z__[j] / delta[j];
473 for (j = *n; j >= i__1; --j) {
474 phi += z__[j] * z__[j] / delta[j];
477 c__ = rhoinv + psi + phi;
478 w = c__ + z__[*i__] * z__[*i__] / delta[*i__] + z__[ip1] * z__[ip1] /
483 /* d(i)< the ith eigenvalue < (d(i)+d(i+1))/2 */
485 /* We choose d(i) as origin. */
488 a = c__ * del + z__[*i__] * z__[*i__] + z__[ip1] * z__[ip1];
489 b = z__[*i__] * z__[*i__] * del;
491 tau = b * 2. / (a + sqrt((d__1 = a * a - b * 4. * c__, abs(
494 tau = (a - sqrt((d__1 = a * a - b * 4. * c__, abs(d__1)))) / (
501 /* (d(i)+d(i+1))/2 <= the ith eigenvalue < d(i+1) */
503 /* We choose d(i+1) as origin. */
506 a = c__ * del - z__[*i__] * z__[*i__] - z__[ip1] * z__[ip1];
507 b = z__[ip1] * z__[ip1] * del;
509 tau = b * 2. / (a - sqrt((d__1 = a * a + b * 4. * c__, abs(
512 tau = -(a + sqrt((d__1 = a * a + b * 4. * c__, abs(d__1)))) /
521 for (j = 1; j <= i__1; ++j) {
522 delta[j] = d__[j] - d__[*i__] - tau;
527 for (j = 1; j <= i__1; ++j) {
528 delta[j] = d__[j] - d__[ip1] - tau;
540 /* Evaluate PSI and the derivative DPSI */
546 for (j = 1; j <= i__1; ++j) {
547 temp = z__[j] / delta[j];
548 psi += z__[j] * temp;
553 erretm = abs(erretm);
555 /* Evaluate PHI and the derivative DPHI */
560 for (j = *n; j >= i__1; --j) {
561 temp = z__[j] / delta[j];
562 phi += z__[j] * temp;
568 w = rhoinv + phi + psi;
570 /* W is the value of the secular function with */
571 /* its ii-th element removed. */
583 if (ii == 1 || ii == *n) {
587 temp = z__[ii] / delta[ii];
588 dw = dpsi + dphi + temp * temp;
589 temp = z__[ii] * temp;
591 erretm = (phi - psi) * 8. + erretm + rhoinv * 2. + abs(temp) * 3. +
594 /* Test for convergence */
596 if (abs(w) <= eps * erretm) {
598 *dlam = d__[*i__] + tau;
600 *dlam = d__[ip1] + tau;
606 dltlb = max(dltlb,tau);
608 dltub = min(dltub,tau);
611 /* Calculate the new step */
616 /* Computing 2nd power */
617 d__1 = z__[*i__] / delta[*i__];
618 c__ = w - delta[ip1] * dw - (d__[*i__] - d__[ip1]) * (d__1 *
621 /* Computing 2nd power */
622 d__1 = z__[ip1] / delta[ip1];
623 c__ = w - delta[*i__] * dw - (d__[ip1] - d__[*i__]) * (d__1 *
626 a = (delta[*i__] + delta[ip1]) * w - delta[*i__] * delta[ip1] *
628 b = delta[*i__] * delta[ip1] * w;
632 a = z__[*i__] * z__[*i__] + delta[ip1] * delta[ip1] *
635 a = z__[ip1] * z__[ip1] + delta[*i__] * delta[*i__] *
640 } else if (a <= 0.) {
641 eta = (a - sqrt((d__1 = a * a - b * 4. * c__, abs(d__1)))) / (
644 eta = b * 2. / (a + sqrt((d__1 = a * a - b * 4. * c__, abs(
649 /* Interpolation using THREE most relevant poles */
651 temp = rhoinv + psi + phi;
653 temp1 = z__[iim1] / delta[iim1];
655 c__ = temp - delta[iip1] * (dpsi + dphi) - (d__[iim1] - d__[
657 zz[0] = z__[iim1] * z__[iim1];
658 zz[2] = delta[iip1] * delta[iip1] * (dpsi - temp1 + dphi);
660 temp1 = z__[iip1] / delta[iip1];
662 c__ = temp - delta[iim1] * (dpsi + dphi) - (d__[iip1] - d__[
664 zz[0] = delta[iim1] * delta[iim1] * (dpsi + (dphi - temp1));
665 zz[2] = z__[iip1] * z__[iip1];
667 zz[1] = z__[ii] * z__[ii];
668 dlaed6_(&niter, &orgati, &c__, &delta[iim1], zz, &w, &eta, info);
674 /* Note, eta should be positive if w is negative, and */
675 /* eta should be negative otherwise. However, */
676 /* if for some reason caused by roundoff, eta*w > 0, */
677 /* we simply use one Newton step instead. This way */
678 /* will guarantee eta*w < 0. */
684 if (temp > dltub || temp < dltlb) {
686 eta = (dltub - tau) / 2.;
688 eta = (dltlb - tau) / 2.;
695 for (j = 1; j <= i__1; ++j) {
700 /* Evaluate PSI and the derivative DPSI */
706 for (j = 1; j <= i__1; ++j) {
707 temp = z__[j] / delta[j];
708 psi += z__[j] * temp;
713 erretm = abs(erretm);
715 /* Evaluate PHI and the derivative DPHI */
720 for (j = *n; j >= i__1; --j) {
721 temp = z__[j] / delta[j];
722 phi += z__[j] * temp;
728 temp = z__[ii] / delta[ii];
729 dw = dpsi + dphi + temp * temp;
730 temp = z__[ii] * temp;
731 w = rhoinv + phi + psi + temp;
732 erretm = (phi - psi) * 8. + erretm + rhoinv * 2. + abs(temp) * 3. + (
733 d__1 = tau + eta, abs(d__1)) * dw;
737 if (-w > abs(prew) / 10.) {
741 if (w > abs(prew) / 10.) {
748 /* Main loop to update the values of the array DELTA */
752 for (niter = iter; niter <= 30; ++niter) {
754 /* Test for convergence */
756 if (abs(w) <= eps * erretm) {
758 *dlam = d__[*i__] + tau;
760 *dlam = d__[ip1] + tau;
766 dltlb = max(dltlb,tau);
768 dltub = min(dltub,tau);
771 /* Calculate the new step */
776 /* Computing 2nd power */
777 d__1 = z__[*i__] / delta[*i__];
778 c__ = w - delta[ip1] * dw - (d__[*i__] - d__[ip1]) * (
781 /* Computing 2nd power */
782 d__1 = z__[ip1] / delta[ip1];
783 c__ = w - delta[*i__] * dw - (d__[ip1] - d__[*i__]) *
787 temp = z__[ii] / delta[ii];
793 c__ = w - delta[*i__] * dpsi - delta[ip1] * dphi;
795 a = (delta[*i__] + delta[ip1]) * w - delta[*i__] * delta[ip1]
797 b = delta[*i__] * delta[ip1] * w;
802 a = z__[*i__] * z__[*i__] + delta[ip1] *
803 delta[ip1] * (dpsi + dphi);
805 a = z__[ip1] * z__[ip1] + delta[*i__] * delta[
806 *i__] * (dpsi + dphi);
809 a = delta[*i__] * delta[*i__] * dpsi + delta[ip1]
814 } else if (a <= 0.) {
815 eta = (a - sqrt((d__1 = a * a - b * 4. * c__, abs(d__1))))
818 eta = b * 2. / (a + sqrt((d__1 = a * a - b * 4. * c__,
823 /* Interpolation using THREE most relevant poles */
825 temp = rhoinv + psi + phi;
827 c__ = temp - delta[iim1] * dpsi - delta[iip1] * dphi;
828 zz[0] = delta[iim1] * delta[iim1] * dpsi;
829 zz[2] = delta[iip1] * delta[iip1] * dphi;
832 temp1 = z__[iim1] / delta[iim1];
834 c__ = temp - delta[iip1] * (dpsi + dphi) - (d__[iim1]
835 - d__[iip1]) * temp1;
836 zz[0] = z__[iim1] * z__[iim1];
837 zz[2] = delta[iip1] * delta[iip1] * (dpsi - temp1 +
840 temp1 = z__[iip1] / delta[iip1];
842 c__ = temp - delta[iim1] * (dpsi + dphi) - (d__[iip1]
843 - d__[iim1]) * temp1;
844 zz[0] = delta[iim1] * delta[iim1] * (dpsi + (dphi -
846 zz[2] = z__[iip1] * z__[iip1];
849 dlaed6_(&niter, &orgati, &c__, &delta[iim1], zz, &w, &eta,
856 /* Note, eta should be positive if w is negative, and */
857 /* eta should be negative otherwise. However, */
858 /* if for some reason caused by roundoff, eta*w > 0, */
859 /* we simply use one Newton step instead. This way */
860 /* will guarantee eta*w < 0. */
866 if (temp > dltub || temp < dltlb) {
868 eta = (dltub - tau) / 2.;
870 eta = (dltlb - tau) / 2.;
875 for (j = 1; j <= i__1; ++j) {
883 /* Evaluate PSI and the derivative DPSI */
889 for (j = 1; j <= i__1; ++j) {
890 temp = z__[j] / delta[j];
891 psi += z__[j] * temp;
896 erretm = abs(erretm);
898 /* Evaluate PHI and the derivative DPHI */
903 for (j = *n; j >= i__1; --j) {
904 temp = z__[j] / delta[j];
905 phi += z__[j] * temp;
911 temp = z__[ii] / delta[ii];
912 dw = dpsi + dphi + temp * temp;
913 temp = z__[ii] * temp;
914 w = rhoinv + phi + psi + temp;
915 erretm = (phi - psi) * 8. + erretm + rhoinv * 2. + abs(temp) * 3.
917 if (w * prew > 0. && abs(w) > abs(prew) / 10.) {
924 /* Return with INFO = 1, NITER = MAXIT and not converged */
928 *dlam = d__[*i__] + tau;
930 *dlam = d__[ip1] + tau;