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_ROMBERG_H_
00037 #define _NUMERICS4CPP_INTEGRATION_ROMBERG_H_
00038
00039 #include <vector>
00040 #include "trapezoid.h"
00041
00042 NUM_NAMESPACE_BEGIN
00043
00083 template<class Function>
00084 class romberg_integrator : public iterative_method {
00085
00086 public:
00093 romberg_integrator(Function& f, unsigned int iterations = 100,
00094 double relative_error = 1.0e-15)
00095 : iterative_method(iterations, relative_error), _function(f)
00096 {
00097 }
00098
00102 ~romberg_integrator() {
00103 }
00104
00111 double integrate(double a, double b) {
00112 trapezoidal_integrator_state<Function> state(_function, a, b);
00113
00114 std::vector<double> r0, r1;
00115 double error = std::numeric_limits<double>::max();
00116 unsigned int n;
00117
00118 r0.push_back(state.result());
00119 do {
00120 state.iterate();
00121 n = state.iterations();
00122
00123 r1.resize(0);
00124 r1.push_back(state.result());
00125 double d = 4.0;
00126 for (unsigned int i = 0; i < n; ++i) {
00127 r1.push_back(r1[i] + (r1[i] - r0[i]) / (d - 1.0));
00128 d *= 4.0;
00129 }
00130 error = std::fabs(r1[n] / r0[n - 1] - 1.0);
00131 r0 = r1;
00132 r1.resize(0);
00133 } while (n < maximum_iterations() && error > maximum_relative_error());
00134
00135 if (n >= maximum_iterations()) {
00136 throw new convergence_exception(
00137 "Romberg integration failed to converge.");
00138 }
00139
00140 return r0[r0.size() - 1];
00141 }
00142
00143 private:
00145 Function& _function;
00146 };
00147
00148 NUM_NAMESPACE_END
00149
00150 #endif