00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022 #ifndef ZEROINVISITOR_H
00023 #define ZEROINVISITOR_H
00024
00025 #include "designbycontract.h"
00026
00027 #include <iostream>
00028 #include <cmath>
00029
00030 #ifndef DBL_EPSILON
00031 #define DBL_EPSILON 2e-16
00032 #endif
00033
00035
00076 template < class Subject, class Ordinate = double, class Abscissa = double >
00077 class ZeroIn : public DesignByContract {
00078
00079 private:
00080 Abscissa ax;
00081 Abscissa bx;
00082 Ordinate(Subject::*method) (const Abscissa&);
00083 Abscissa tol;
00084 Abscissa x;
00085 bool issolved;
00086
00087 Abscissa a, b, c;
00088 Ordinate fa;
00089 Ordinate fb;
00090 Ordinate fc;
00091
00092 Subject *subject;
00093
00094 public:
00095
00096 ZeroIn() {
00097 this->tol = 0.0 * Abscissa();
00098 }
00099
00101 void setLowerBound(const Abscissa& ax) {
00102 this->ax = ax;
00103 }
00104
00106 Abscissa getLowerBound() const {
00107 return ax;
00108 }
00109
00111 void setUpperBound(const Abscissa& bx) {
00112 this->bx = bx;
00113 }
00114
00116 Abscissa getUpperBound() const{
00117 return bx;
00118 }
00119
00121 void setTolerance(const Abscissa& tol) {
00122 this->tol = tol;
00123 }
00124
00126
00134 void setMethod(Ordinate(Subject::*method) (const Abscissa&)) {
00135 this->method = method;
00136 }
00137
00139
00182 void visit(Subject *subject) {
00183
00184
00185
00186 this->subject = subject;
00187 this->issolved = false;
00188
00189 a = ax;
00190 b = bx;
00191 fa = ((*subject).*method) (a);
00192 fb = ((*subject).*method) (b);
00193 c = a;
00194 fc = fa;
00195
00196 if(fa == 0.0 * Ordinate()){
00197 fb=0.0 * Ordinate();
00198 this->issolved = true;
00199 return;
00200 }
00201
00202
00203
00204 for (;;) {
00205 Abscissa prev_step = b - a;
00206 Abscissa tol_act;
00207 Abscissa p;
00208 double q;
00209 Abscissa new_step;
00210
00211 if (fabs(fc) < fabs(fb)) {
00212 a = b;
00213 b = c;
00214 c = a;
00215 fa = fb;
00216 fb = fc;
00217 fc = fa;
00218 }
00219
00220
00221 tol_act = 2.0* DBL_EPSILON * fabs(b) + tol / 2.0;
00222
00223 new_step = (c - b) / 2.0;
00224
00225 if (fabs(new_step) <= tol_act || fb == 0.0 * Ordinate()) {
00226 this->issolved = true;
00227
00228 return;
00229 }
00230
00231
00232 if (fabs(prev_step) >= tol_act
00233 && fabs(fa) > fabs(fb))
00234 {
00235 register double t1, t2;
00236 Abscissa cb;
00237
00238 cb = c - b;
00239 if (a == c) {
00240
00241
00242 t1 = fb / fa;
00243 p = cb * t1;
00244 q = 1.0 - t1;
00245 } else {
00246
00247
00248 q = fa / fc;
00249 t1 = fb / fc;
00250 t2 = fb / fa;
00251 p = t2 * (cb * q * (q - t1) - (b - a) * (t1 - 1.0));
00252 q = (q - 1.0) * (t1 - 1.0) * (t2 - 1.0);
00253 }
00254 if (p > 0.0 * Abscissa()) {
00255
00256 q = -q;
00257 } else {
00258 p = -p;
00259 }
00260
00261 if (p < (0.75 * cb * q - fabs(tol_act * q) / 2.0)
00262 && p < fabs(prev_step * q / 2.0)
00263 ) {
00264
00265
00266 new_step = p / q;
00267 }
00268
00269
00270 }
00271
00272 if (fabs(new_step) < tol_act) {
00273 if (new_step > 0.0 * Abscissa())
00274 new_step = tol_act;
00275 else
00276 new_step = -tol_act;
00277 }
00278
00279 a = b;
00280 fa = fb;
00281 b += new_step;
00282 fb = ((*subject).*method) (b);
00283
00284 if ((fb > 0.0 * Ordinate() && fc > 0.0 * Ordinate())
00285 || (fb < 0.0 * Ordinate() && fc < 0.0 * Ordinate())) {
00286 c = a;
00287 fc = fa;
00288 }
00289 }
00290
00291 }
00292
00293 bool isSolved(void) const{
00294 return issolved;
00295 }
00296
00297 bool isSolved(const Ordinate &error) {
00298 if (fabs(fb) > error) {
00299 return false;
00300 }
00301 return true;
00302 }
00303
00304 Abscissa getSolution(void) const {
00305 return a;
00306 }
00307
00308 Ordinate getError(void) const{
00309 return fb;
00310 }
00311 };
00312
00313 #endif