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_INTEGRATION_ADAPTIVE_H_
00037 #define _NUMERICS4CPP_INTEGRATION_ADAPTIVE_H_
00038
00039 #include <limits>
00040 #include "../iterativemethod.h"
00041 #include "../exception/exception.h"
00042
00043 NUM_NAMESPACE_BEGIN
00044
00084 template<class Function>
00085 class adaptive_integrator : public iterative_method {
00086
00087 public:
00094 adaptive_integrator(Function& f, unsigned int iterations = 100,
00095 double relative_error = 1.0e-15)
00096 : iterative_method(iterations, relative_error), _function(f)
00097 {
00098 }
00099
00103 ~adaptive_integrator() {
00104 }
00105
00112 double integrate(double a, double b) {
00113 double ret;
00114
00115 if (is_nan(a) || is_nan(b)) {
00116 ret = std::numeric_limits<double>::quiet_NaN();
00117 } else {
00118 unsigned int level = 1;
00119 double tolerance = 10.0 * maximum_relative_error();
00120 double h = (b - a) / 2.0;
00121 double fa = _function(a);
00122 double fc = _function(a + h);
00123 double fb = _function(b);
00124 double s = h * (fa + 4.0 * fc + fb) / 3.0;
00125 ret = integrate(a, b, fa, fb, fc, h, tolerance, s, level);
00126 }
00127
00128 return ret;
00129 }
00130
00131 private:
00147 double integrate(double a, double b, double fa, double fb, double fc,
00148 double h, double tolerance, double s, unsigned int level)
00149 {
00150 double ret = s;
00151
00152 if (level < maximum_iterations()) {
00153 double fd = _function(a + h / 2.0);
00154 double fe = _function(a + 3.0 * h / 2.0);
00155 double s1 = h * (fa + (4.0 * fd) + fc) / 6.0;
00156 double s2 = h * (fc + (4.0 * fe) + fb) / 6.0;
00157 double sn = s1 + s2;
00158 if (std::fabs(sn - s) <= tolerance) {
00159 ret = sn;
00160 } else {
00161 double pivot = a + h;
00162 h /= 2.0;
00163 tolerance /= 2;
00164 ++level;
00165 ret = integrate(a, pivot, fa, fc, fd, h, tolerance, s1, level) +
00166 integrate(pivot, b, fc, fb, fe, h, tolerance, s2, level);
00167 }
00168 } else {
00169 throw convergence_exception(
00170 "Adaptive quadrature failed to converge.");
00171 }
00172
00173 return ret;
00174 }
00175
00177 Function& _function;
00178 };
00179
00180 NUM_NAMESPACE_END
00181
00182 #endif