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_TRAPEZOID_H_
00037 #define _NUMERICS4CPP_INTEGRATION_TRAPEZOID_H_
00038
00039 #include <limits>
00040 #include "../iterativemethod.h"
00041 #include "../exception/exception.h"
00042
00043 NUM_NAMESPACE_BEGIN
00044
00053 template<class Function>
00054 class trapezoidal_integrator_state {
00055 public:
00056 trapezoidal_integrator_state(Function &f, double a, double b) :
00057 _function(f), _a(a), _b(b), _n(0), _k(2)
00058 {
00059 double fa = f(a);
00060 double fb = f(b);
00061 _s = (b - a) * (fa / 2.0 + fb / 2.0);
00062 }
00063
00068 unsigned int iterations() const {
00069 return _n;
00070 }
00071
00076 void iterate() {
00077 ++_n;
00078
00079
00080 double sn = 0.0;
00081 double h = (_b - _a) / _k;
00082 for (int i = _k - 1; i >= 1; i -= 2) {
00083 double x = _a + (i * h);
00084 sn += _function(x);
00085 }
00086 sn = (0.5 * _s) + (h * sn);
00087
00088 _k *= 2;
00089 _s = sn;
00090 }
00091
00096 double result() const {
00097 return _s;
00098 }
00099
00100 private:
00102 Function& _function;
00103
00105 double _a;
00106
00108 double _b;
00109
00111 unsigned int _n;
00112
00114 double _s;
00115
00117 unsigned int _k;
00118 };
00119
00120
00162 template<class Function>
00163 class trapezoidal_integrator : public iterative_method {
00164
00165 public:
00172 trapezoidal_integrator(Function& f, unsigned int iterations = 100,
00173 double relative_error = 1.0e-13)
00174 : iterative_method(iterations, relative_error), _function(f)
00175 {
00176 }
00177
00181 ~trapezoidal_integrator() {
00182 }
00183
00190 double integrate(double a, double b) {
00191 trapezoidal_integrator_state<Function> state(_function, a, b);
00192
00193 double s = state.result();
00194 double sn = s;
00195 double error = std::numeric_limits<double>::max();
00196 do {
00197 state.iterate();
00198 sn = state.result();
00199 error = std::fabs(sn / s - 1.0);
00200 s = sn;
00201 } while (state.iterations() < maximum_iterations() &&
00202 error > maximum_relative_error());
00203
00204 if (state.iterations() >= maximum_iterations()) {
00205 throw convergence_exception("Trapezoidal integration failed to converge.");
00206 }
00207
00208 return s;
00209 }
00210
00211 private:
00213 Function& _function;
00214 };
00215
00216 NUM_NAMESPACE_END
00217
00218 #endif