#include "blaswrap.h" /* -- translated by f2c (version 19990503). You must link the resulting object file with the libraries: -lf2c -lm (in that order) */ #include "f2c.h" /* Common Block Declarations */ struct { real ops, itcnt; } latime_; #define latime_1 latime_ /* Subroutine */ int slasq4_(integer *i0, integer *n0, real *z__, integer *pp, integer *n0in, real *dmin__, real *dmin1, real *dmin2, real *dn, real *dn1, real *dn2, real *tau, integer *ttype) { /* Initialized data */ static real g = 0.f; /* System generated locals */ integer i__1; real r__1, r__2; /* Builtin functions */ double sqrt(doublereal); /* Local variables */ static real s, a2, b1, b2; static integer i4, nn, np; static real gam, gap1, gap2; /* -- LAPACK auxiliary routine (instrumented to count ops, version 3.0) -- Univ. of Tennessee, Univ. of California Berkeley, NAG Ltd., Courant Institute, Argonne National Lab, and Rice University May 17, 2000 Purpose ======= SLASQ4 computes an approximation TAU to the smallest eigenvalue using values of d from the previous transform. I0 (input) INTEGER First index. N0 (input) INTEGER Last index. Z (input) REAL array, dimension ( 4*N ) Z holds the qd array. PP (input) INTEGER PP=0 for ping, PP=1 for pong. NOIN (input) INTEGER The value of N0 at start of EIGTEST. DMIN (input) REAL Minimum value of d. DMIN1 (input) REAL Minimum value of d, excluding D( N0 ). DMIN2 (input) REAL Minimum value of d, excluding D( N0 ) and D( N0-1 ). DN (input) REAL d(N) DN1 (input) REAL d(N-1) DN2 (input) REAL d(N-2) TAU (output) REAL This is the shift. TTYPE (output) INTEGER Shift type. Further Details =============== CNST1 = 9/16 ===================================================================== Parameter adjustments */ --z__; /* Function Body A negative DMIN forces the shift to take that absolute value TTYPE records the type of shift. */ if (*dmin__ <= 0.f) { *tau = -(*dmin__); *ttype = -1; return 0; } nn = (*n0 << 2) + *pp; if (*n0in == *n0) { /* No eigenvalues deflated. */ if (*dmin__ == *dn || *dmin__ == *dn1) { latime_1.ops += 7.f; b1 = sqrt(z__[nn - 3]) * sqrt(z__[nn - 5]); b2 = sqrt(z__[nn - 7]) * sqrt(z__[nn - 9]); a2 = z__[nn - 7] + z__[nn - 5]; /* Cases 2 and 3. */ if (*dmin__ == *dn && *dmin1 == *dn1) { latime_1.ops += 3.f; gap2 = *dmin2 - a2 - *dmin2 * .25f; if (gap2 > 0.f && gap2 > b2) { latime_1.ops += 4.f; gap1 = a2 - *dn - b2 / gap2 * b2; } else { latime_1.ops += 3.f; gap1 = a2 - *dn - (b1 + b2); } if (gap1 > 0.f && gap1 > b1) { latime_1.ops += 4.f; /* Computing MAX */ r__1 = *dn - b1 / gap1 * b1, r__2 = *dmin__ * .5f; s = dmax(r__1,r__2); *ttype = -2; } else { latime_1.ops += 2.f; s = 0.f; if (*dn > b1) { s = *dn - b1; } if (a2 > b1 + b2) { /* Computing MIN */ r__1 = s, r__2 = a2 - (b1 + b2); s = dmin(r__1,r__2); } /* Computing MAX */ r__1 = s, r__2 = *dmin__ * .333f; s = dmax(r__1,r__2); *ttype = -3; } } else { /* Case 4. */ *ttype = -4; latime_1.ops += 1.f; s = *dmin__ * .25f; if (*dmin__ == *dn) { latime_1.ops += 1.f; gam = *dn; a2 = 0.f; if (z__[nn - 5] > z__[nn - 7]) { return 0; } b2 = z__[nn - 5] / z__[nn - 7]; np = nn - 9; } else { latime_1.ops += 2.f; np = nn - (*pp << 1); b2 = z__[np - 2]; gam = *dn1; if (z__[np - 4] > z__[np - 2]) { return 0; } a2 = z__[np - 4] / z__[np - 2]; if (z__[nn - 9] > z__[nn - 11]) { return 0; } b2 = z__[nn - 9] / z__[nn - 11]; np = nn - 13; } /* Approximate contribution to norm squared from I < NN-1. */ a2 += b2; i__1 = (*i0 << 2) - 1 + *pp; for (i4 = np; i4 >= i__1; i4 += -4) { latime_1.ops += 5.f; if (b2 == 0.f) { goto L20; } b1 = b2; if (z__[i4] > z__[i4 - 2]) { return 0; } b2 *= z__[i4] / z__[i4 - 2]; a2 += b2; if (dmax(b2,b1) * 100.f < a2 || .563f < a2) { goto L20; } /* L10: */ } L20: latime_1.ops += 1.f; a2 *= 1.05f; /* Rayleigh quotient residual bound. */ latime_1.ops += 5.f; if (a2 < .563f) { s = gam * (1.f - sqrt(a2)) / (a2 + 1.f); } } } else if (*dmin__ == *dn2) { /* Case 5. */ *ttype = -5; latime_1.ops += 1.f; s = *dmin__ * .25f; /* Compute contribution to norm squared from I > NN-2. */ latime_1.ops += 4.f; np = nn - (*pp << 1); b1 = z__[np - 2]; b2 = z__[np - 6]; gam = *dn2; if (z__[np - 8] > b2 || z__[np - 4] > b1) { return 0; } a2 = z__[np - 8] / b2 * (z__[np - 4] / b1 + 1.f); /* Approximate contribution to norm squared from I < NN-2. */ if (*n0 - *i0 > 2) { latime_1.ops += 3.f; b2 = z__[nn - 13] / z__[nn - 15]; a2 += b2; i__1 = (*i0 << 2) - 1 + *pp; for (i4 = nn - 17; i4 >= i__1; i4 += -4) { latime_1.ops += 5.f; if (b2 == 0.f) { goto L40; } b1 = b2; if (z__[i4] > z__[i4 - 2]) { return 0; } b2 *= z__[i4] / z__[i4 - 2]; a2 += b2; if (dmax(b2,b1) * 100.f < a2 || .563f < a2) { goto L40; } /* L30: */ } L40: a2 *= 1.05f; } latime_1.ops += 5.f; if (a2 < .563f) { s = gam * (1.f - sqrt(a2)) / (a2 + 1.f); } } else { /* Case 6, no information to guide us. */ if (*ttype == -6) { latime_1.ops += 3.f; g += (1.f - g) * .333f; } else if (*ttype == -18) { latime_1.ops += 1.f; g = .083250000000000005f; } else { g = .25f; } latime_1.ops += 1.f; s = g * *dmin__; *ttype = -6; } } else if (*n0in == *n0 + 1) { /* One eigenvalue just deflated. Use DMIN1, DN1 for DMIN and DN. */ if (*dmin1 == *dn1 && *dmin2 == *dn2) { /* Cases 7 and 8. */ *ttype = -7; latime_1.ops += 2.f; s = *dmin1 * .333f; if (z__[nn - 5] > z__[nn - 7]) { return 0; } b1 = z__[nn - 5] / z__[nn - 7]; b2 = b1; if (b2 == 0.f) { goto L60; } i__1 = (*i0 << 2) - 1 + *pp; for (i4 = (*n0 << 2) - 9 + *pp; i4 >= i__1; i4 += -4) { latime_1.ops += 4.f; a2 = b1; if (z__[i4] > z__[i4 - 2]) { return 0; } b1 *= z__[i4] / z__[i4 - 2]; b2 += b1; if (dmax(b1,a2) * 100.f < b2) { goto L60; } /* L50: */ } L60: latime_1.ops += 8.f; b2 = sqrt(b2 * 1.05f); /* Computing 2nd power */ r__1 = b2; a2 = *dmin1 / (r__1 * r__1 + 1.f); gap2 = *dmin2 * .5f - a2; if (gap2 > 0.f && gap2 > b2 * a2) { latime_1.ops += 7.f; /* Computing MAX */ r__1 = s, r__2 = a2 * (1.f - a2 * 1.01f * (b2 / gap2) * b2); s = dmax(r__1,r__2); } else { latime_1.ops += 4.f; /* Computing MAX */ r__1 = s, r__2 = a2 * (1.f - b2 * 1.01f); s = dmax(r__1,r__2); *ttype = -8; } } else { /* Case 9. */ latime_1.ops += 2.f; s = *dmin1 * .25f; if (*dmin1 == *dn1) { s = *dmin1 * .5f; } *ttype = -9; } } else if (*n0in == *n0 + 2) { /* Two eigenvalues deflated. Use DMIN2, DN2 for DMIN and DN. Cases 10 and 11. */ latime_1.ops += 1.f; if (*dmin2 == *dn2 && z__[nn - 5] * 2.f < z__[nn - 7]) { *ttype = -10; latime_1.ops += 1.f; s = *dmin2 * .333f; if (z__[nn - 5] > z__[nn - 7]) { return 0; } b1 = z__[nn - 5] / z__[nn - 7]; b2 = b1; if (b2 == 0.f) { goto L80; } i__1 = (*i0 << 2) - 1 + *pp; for (i4 = (*n0 << 2) - 9 + *pp; i4 >= i__1; i4 += -4) { latime_1.ops += 4.f; if (z__[i4] > z__[i4 - 2]) { return 0; } b1 *= z__[i4] / z__[i4 - 2]; b2 += b1; if (b1 * 100.f < b2) { goto L80; } /* L70: */ } L80: latime_1.ops += 12.f; b2 = sqrt(b2 * 1.05f); /* Computing 2nd power */ r__1 = b2; a2 = *dmin2 / (r__1 * r__1 + 1.f); gap2 = z__[nn - 7] + z__[nn - 9] - sqrt(z__[nn - 11]) * sqrt(z__[ nn - 9]) - a2; if (gap2 > 0.f && gap2 > b2 * a2) { latime_1.ops += 7.f; /* Computing MAX */ r__1 = s, r__2 = a2 * (1.f - a2 * 1.01f * (b2 / gap2) * b2); s = dmax(r__1,r__2); } else { latime_1.ops += 4.f; /* Computing MAX */ r__1 = s, r__2 = a2 * (1.f - b2 * 1.01f); s = dmax(r__1,r__2); } } else { latime_1.ops += 1.f; s = *dmin2 * .25f; *ttype = -11; } } else if (*n0in > *n0 + 2) { /* Case 12, more than two eigenvalues deflated. No information. */ s = 0.f; *ttype = -12; } *tau = s; return 0; /* End of SLASQ4 */ } /* slasq4_ */