00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036 #ifndef _NUMERICS4CPP_ROOT_NEWTON_H_
00037 #define _NUMERICS4CPP_ROOT_NEWTON_H_
00038
00039 #include <cmath>
00040 #include <limits>
00041 #include "../iterativemethod.h"
00042 #include "../math.h"
00043
00044 NUM_NAMESPACE_BEGIN
00045
00072 template<class Function>
00073 class newton_root_finder : public iterative_method {
00074
00075 public:
00083 newton_root_finder(Function& f, Function& d, unsigned int iterations = 100,
00084 double relative_error = 1.0e-15)
00085 : iterative_method(iterations, relative_error), _function(f),
00086 _derivative(d)
00087 {
00088 }
00089
00096 double find_root(double x0) {
00097 double ret;
00098
00099 if (is_nan(x0)) {
00100 ret = std::numeric_limits<double>::quiet_NaN();
00101 } else {
00102 unsigned int n = 0;
00103 double x = x0;
00104 double error;
00105 double delta;
00106 double fx;
00107 double dx;
00108 do {
00109 ++n;
00110 fx = _function(x);
00111 dx = _derivative(x);
00112 delta = fx / dx;
00113
00114 error = std::max(std::fabs(fx), std::fabs(delta / x));
00115 x = x - delta;
00116 } while (n < maximum_iterations() &&
00117 error > maximum_relative_error());
00118
00119 if (n >= maximum_iterations()) {
00120 throw convergence_exception(
00121 "Newton's method failed to converge.");
00122 }
00123
00124 ret = x;
00125 }
00126
00127 return ret;
00128 }
00129
00130 private:
00132 Function& _function;
00133
00135 Function& _derivative;
00136 };
00137
00138 NUM_NAMESPACE_END
00139
00140 #endif