/* Max # of iterations */ /* R_zeroin2() is faster for "expensive" f(), in those typical cases where * f(ax) and f(bx) are available anyway : */ double R_zeroin2( /* An estimate of the root */ double ax, /* Left border | of the range */ double bx, /* Right border| the root is seeked*/ double fa, double fb, /* f(a), f(b) */ R_zeroin_fn f, /* Function under investigation */ dynamic info, /* Add'l info passed on to f */ ref double Tol, /* Acceptable tolerance */ ref int Maxit) { double a, b, c, fc; /* Abscissae, descr. see above, f(c) */ double tol; int maxit; a = ax; b = bx; c = a; fc = fa; maxit = Maxit + 1; tol = Tol; /* First test if we have found a root at an endpoint */ if (fa == 0.0) { Tol = 0.0; Maxit = 0; return a; } if (fb == 0.0) { Tol = 0.0; Maxit = 0; return b; } while (maxit-- != 0) /* Main iteration loop */ { double prev_step = b - a; /* Distance from the last but one to the last approximation */ double tol_act; /* Actual tolerance */ double p; /* Interpolation step is calcu- */ double q; /* lated in the form p/q; divi- * sion operations is delayed * until the last moment */ double new_step; /* Step at this iteration */ if (Math.Abs(fc) < Math.Abs(fb)) { /* Swap data for b to be the */ a = b; b = c; c = a; /* best approximation */ fa = fb; fb = fc; fc = fa; } tol_act = 2 * Double.Epsilon * Math.Abs(b) + tol / 2; new_step = (c - b) / 2; if (Math.Abs(new_step) <= tol_act || fb == (double)0) { Maxit -= maxit; Tol = Math.Abs(c - b); return b; /* Acceptable approx. is found */ } /* Decide if the interpolation can be tried */ if (Math.Abs(prev_step) >= tol_act /* If prev_step was large enough*/ && Math.Abs(fa) > Math.Abs(fb)) { /* and was in true direction, * Interpolation may be tried */ double t1, cb, t2; cb = c - b; if (a == c) { /* If we have only two distinct */ /* points linear interpolation */ t1 = fb / fa; /* can only be applied */ p = cb * t1; q = 1.0 - t1; } else { /* Quadric inverse interpolation*/ q = fa / fc; t1 = fb / fc; t2 = fb / fa; p = t2 * (cb * q * (q - t1) - (b - a) * (t1 - 1.0)); q = (q - 1.0) * (t1 - 1.0) * (t2 - 1.0); } if (p > (double)0) /* p was calculated with the */ q = -q; /* opposite sign; make p positive */ else /* and assign possible minus to */ p = -p; /* q */ if (p < (0.75 * cb * q - Math.Abs(tol_act * q) / 2) /* If b+p/q falls in [b,c]*/ && p < Math.Abs(prev_step * q / 2)) /* and isn't too large */ new_step = p / q; /* it is accepted * If p/q is too large then the * bisection procedure can * reduce [b,c] range to more * extent */ } if (Math.Abs(new_step) < tol_act) { /* Adjust the step to be not less*/ if (new_step > (double)0) /* than tolerance */ new_step = tol_act; else new_step = -tol_act; } a = b; fa = fb; /* Save the previous approx. */ b += new_step; fb = f(b, info); /* Do step to a new approxim. */ if ((fb > 0 && fc > 0) || (fb < 0 && fc < 0)) { /* Adjust c for it to have a sign opposite to that of b */ c = a; fc = fa; } } /* failed! */ Tol = Math.Abs(c - b); Maxit = -1; return b; }
/* * root finder routines are copied from stats/src/zeroin.c */ double R_zeroin( /* An estimate of the root */ double ax, /* Left border | of the range */ double bx, /* Right border| the root is seeked*/ R_zeroin_fn f, /* Function under investigation */ dynamic info, /* Add'l info passed on to f */ ref double Tol, /* Acceptable tolerance */ ref int Maxit) /* Max # of iterations */ { double fa = f(ax, info); double fb = f(bx, info); return(R_zeroin2(ax, bx, fa, fb, f, info, ref Tol, ref Maxit)); }
/* Max # of iterations */ /* * root finder routines are copied from stats/src/zeroin.c */ double R_zeroin( /* An estimate of the root */ double ax, /* Left border | of the range */ double bx, /* Right border| the root is seeked*/ R_zeroin_fn f, /* Function under investigation */ dynamic info, /* Add'l info passed on to f */ ref double Tol, /* Acceptable tolerance */ ref int Maxit) { double fa = f(ax, info); double fb = f(bx, info); return R_zeroin2(ax, bx, fa, fb, f, info, ref Tol, ref Maxit); }
/* R_zeroin2() is faster for "expensive" f(), in those typical cases where * f(ax) and f(bx) are available anyway : */ double R_zeroin2( /* An estimate of the root */ double ax, /* Left border | of the range */ double bx, /* Right border| the root is seeked*/ double fa, double fb, /* f(a), f(b) */ R_zeroin_fn f, /* Function under investigation */ dynamic info, /* Add'l info passed on to f */ ref double Tol, /* Acceptable tolerance */ ref int Maxit) /* Max # of iterations */ { double a, b, c, fc; /* Abscissae, descr. see above, f(c) */ double tol; int maxit; a = ax; b = bx; c = a; fc = fa; maxit = Maxit + 1; tol = Tol; /* First test if we have found a root at an endpoint */ if (fa == 0.0) { Tol = 0.0; Maxit = 0; return(a); } if (fb == 0.0) { Tol = 0.0; Maxit = 0; return(b); } while (maxit-- != 0) /* Main iteration loop */ { double prev_step = b - a; /* Distance from the last but one * to the last approximation */ double tol_act; /* Actual tolerance */ double p; /* Interpolation step is calcu- */ double q; /* lated in the form p/q; divi- * sion operations is delayed * until the last moment */ double new_step; /* Step at this iteration */ if (Math.Abs(fc) < Math.Abs(fb)) { /* Swap data for b to be the */ a = b; b = c; c = a; /* best approximation */ fa = fb; fb = fc; fc = fa; } tol_act = 2 * Double.Epsilon * Math.Abs(b) + tol / 2; new_step = (c - b) / 2; if (Math.Abs(new_step) <= tol_act || fb == (double)0) { Maxit -= maxit; Tol = Math.Abs(c - b); return(b); /* Acceptable approx. is found */ } /* Decide if the interpolation can be tried */ if (Math.Abs(prev_step) >= tol_act && /* If prev_step was large enough*/ Math.Abs(fa) > Math.Abs(fb)) { /* and was in true direction, * Interpolation may be tried */ double t1, cb, t2; cb = c - b; if (a == c) { /* If we have only two distinct */ /* points linear interpolation */ t1 = fb / fa; /* can only be applied */ p = cb * t1; q = 1.0 - t1; } else { /* Quadric inverse interpolation*/ q = fa / fc; t1 = fb / fc; t2 = fb / fa; p = t2 * (cb * q * (q - t1) - (b - a) * (t1 - 1.0)); q = (q - 1.0) * (t1 - 1.0) * (t2 - 1.0); } if (p > (double)0) /* p was calculated with the */ { q = -q; /* opposite sign; make p positive */ } else /* and assign possible minus to */ { p = -p; /* q */ } if (p < (0.75 * cb * q - Math.Abs(tol_act * q) / 2) && /* If b+p/q falls in [b,c]*/ p < Math.Abs(prev_step * q / 2)) /* and isn't too large */ { new_step = p / q; /* it is accepted * If p/q is too large then the * bisection procedure can * reduce [b,c] range to more * extent */ } } if (Math.Abs(new_step) < tol_act) { /* Adjust the step to be not less*/ if (new_step > (double)0) /* than tolerance */ { new_step = tol_act; } else { new_step = -tol_act; } } a = b; fa = fb; /* Save the previous approx. */ b += new_step; fb = f(b, info); /* Do step to a new approxim. */ if ((fb > 0 && fc > 0) || (fb < 0 && fc < 0)) { /* Adjust c for it to have a sign opposite to that of b */ c = a; fc = fa; } } /* failed! */ Tol = Math.Abs(c - b); Maxit = -1; return(b); }