00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023 #include "findroot.h"
00024
00025 #include <cassert>
00026 #include <cmath>
00027
00028 using namespace sheep;
00029
00030 Real sheep::FindRoot(const Function1 &f, Real left, Real right, Real tolerance) {
00031 assert(tolerance >= 0);
00032
00033 if(left > right) {
00034 Real dummy = left;
00035 left = right;
00036 right = dummy;
00037 }
00038
00039 Real fl = f.EvaluateAt(left);
00040 Real fr = f.EvaluateAt(right);
00041
00042 if(fabs(fl) < tolerance)
00043 return fl;
00044 else if(fabs(fr) < tolerance)
00045 return fr;
00046
00047 assert(fl * fr < 0);
00048
00049 int sign = fr > 0 ? 1 : -1;
00050
00051 while(right - left > tolerance) {
00052 Real mid = (left + right) / 2;
00053 Real fm = f.EvaluateAt(mid);
00054
00055 if(sign * fm > 0)
00056 right = mid;
00057 else left = mid;
00058 }
00059
00060 return (left + right) / 2;
00061 }
00062
00063
00064
00065
00066
00067
00068
00069
00070
00071
00072
00073
00074
00075
00076
00077
00078
00079
00080
00081
00082
00083
00084
00085
00086
00087
00088
00089
00090
00091
00092
00093
00094
00095 Real eps = 1;
00096 Real tol1;
00097
00098 do {
00099 eps /= 2;
00100 tol1 = 1 + eps;
00101 } while(tol1 > 1);
00102
00103 // Initialization.
00104
00105 Real a = left;
00106 Real b = right;
00107 Real fa = f.EvaluateAt(a);
00108 Real fb = f.EvaluateAt(b);
00109
00110
00111 assert(fa * fb < 0);
00112
00113 // Begin step.
00114
00115 Real c = a;
00116 Real fc = fa;
00117 Real d = b - a;
00118 Real e = d;
00119
00120 while(1) {
00121 if(fabs(fc) < fabs(fb)) {
00122 a = b;
00123 b = c;
00124 c = a;
00125
00126 fa = fb;
00127 fb = fc;
00128 fc = fa;
00129 }
00130
00131 // Convergence test.
00132
00133 Real mid = 0.5 * (c - b);
00134 Real tol = 2 * eps * fabs(b) + 0.5 * tolerance;
00135
00136 if(fabs(mid) <= tol)
00137 break;
00138
00139 if(fb == 0)
00140 break;
00141
00142 if(fabs(e) < tol || fabs(fa) <= fabs(fb)) { // is bisection necessary?
00143 // Bisection.
00144 e = d = mid;
00145 } else {
00146 Real p, q, r, s;
00147
00148 if(a != c) { // is quadratic interpolation possible?
00149 // Inverse quadratic interpolation.
00150 q = fa / fc;
00151 r = fb / fc;
00152 s = fb / fa;
00153 p = s * (2 * mid * q * (q - r) - (b - a) * (r - 1));
00154 q = (q - 1) * (r - 1) * (s - 1);
00155 } else {
00156 // Linear interpolation.
00157 s = fb / fa;
00158 p = 2 * mid * s;
00159 q = 1 - s;
00160 }
00161
00162 // Adjust signs.
00163
00164 if(p > 0)
00165 q = -q;
00166
00167 p = fabs(p);
00168
00169 // Is interpolation acceptable?
00170
00171 if(2 * p >= 3 * mid * q - fabs(tol * q) || p >= fabs(0.5 * e * q)) {
00172 // Bisection.
00173 e = d = mid;
00174 } else {
00175 e = d;
00176 d = p / q;
00177 }
00178 }
00179
00180 // Complete step.
00181
00182 a = b;
00183 fa = fb;
00184
00185 if(fabs(d) > tol)
00186 b += d;
00187 else b += fabs(tol) * (mid >= 0 ? 1 : -1);
00188
00189 fb = f.EvaluateAt(b);
00190
00191 if(fb * (fc / fabs(fc)) > 0) {
00192 c = a;
00193 fc = fa;
00194 e = d = b - a;
00195 }
00196 }
00197
00198 return b;
00199 }
00200 */