00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013 #include <limits>
00014
00015 #ifndef adaptsim_H
00016 #define adaptsim_H
00017
00018 namespace NR {
00019
00047 template <typename FunctionType, typename ScalarType>
00048 ScalarType adaptsim(FunctionType& func, ScalarType a, ScalarType b, ScalarType tol, int& info) {
00049 const ScalarType mach_eps = std::numeric_limits<ScalarType>::epsilon();
00050
00051 info = 0;
00052 if (tol < mach_eps)
00053 tol = mach_eps;
00054
00055 double sign = 1.0;
00056 if (a > b) {
00057 sign = -1.0;
00058 double t = a;
00059 a = b;
00060 b = t;
00061 }
00062
00063 ScalarType fa = func(a);
00064 ScalarType fm = func(0.5*(a+b));
00065 ScalarType fb = func(b);
00066
00067
00068 ScalarType mc_pos[] = { 0.9501, 0.2311, 0.6068, 0.4860, 0.8913 };
00069 ScalarType sum_y = fa + fm + fb;
00070 for (int i = 0; i < 5; ++ i)
00071 sum_y += func(a + mc_pos[i] * (b-a));
00072 ScalarType is = (b - a)/8.0 * sum_y;
00073 if (is == 0.0)
00074 is = b-a;
00075
00076
00077 is *= tol/mach_eps;
00078 return sign*adaptsimstp(func, a, b, fa, fm, fb, is, info);
00079 }
00080
00093 template <typename FunctionType, typename ScalarType>
00094 ScalarType adaptsimstp(FunctionType& func,
00095 ScalarType a, ScalarType b,
00096 ScalarType fa, ScalarType fm, ScalarType fb,
00097 ScalarType is,
00098 int& info) {
00099 const ScalarType eps = std::numeric_limits<ScalarType>::epsilon() * fabs(is);
00100 ScalarType Q;
00101 ScalarType m = (a + b)/2;
00102 ScalarType h = (b - a)/4;
00103 ScalarType fml = func(a + h);
00104 ScalarType fmr = func(b - h);
00105
00106
00107 ScalarType i1 = h/1.5 * (fa + 4*fm + fb);
00108
00109 ScalarType i2 = h/3 * (fa + 4*(fml + fmr) + 2*fm + fb);
00110
00111 i1 = (16*i2 - i1)/15;
00112
00113 if ((fabs(i1-i2) < eps) || (m <= a) || (b <= m)) {
00114 if (((m <= a) || (b <= m)) && (info == 0)) {
00115 rWarning("Interval contains no more machine number. Required tolerance may not be met.");
00116 info = 1;
00117 }
00118 Q = i1;
00119
00120 } else {
00121 Q = adaptsimstp(func, a, m, fa, fml, fm, is, info) +
00122 adaptsimstp(func, m, b, fm, fmr, fb, is, info);
00123 }
00124 return Q;
00125 }
00126
00127 }
00128
00129 #endif