vSMC
vSMC: Scalable Monte Carlo
nintegrate_newton_cotes.hpp
Go to the documentation of this file.
1 //============================================================================
2 // vSMC/include/vsmc/integrate/nintegrate_newton_cotes.hpp
3 //----------------------------------------------------------------------------
4 // vSMC: Scalable Monte Carlo
5 //----------------------------------------------------------------------------
6 // Copyright (c) 2013,2014, Yan Zhou
7 // All rights reserved.
8 //
9 // Redistribution and use in source and binary forms, with or without
10 // modification, are permitted provided that the following conditions are met:
11 //
12 // Redistributions of source code must retain the above copyright notice,
13 // this list of conditions and the following disclaimer.
14 //
15 // Redistributions in binary form must reproduce the above copyright notice,
16 // this list of conditions and the following disclaimer in the documentation
17 // and/or other materials provided with the distribution.
18 //
19 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS AS IS
20 // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21 // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22 // ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
23 // LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
24 // CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
25 // SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
26 // INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
27 // CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
28 // ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
29 // POSSIBILITY OF SUCH DAMAGE.
30 //============================================================================
31 
32 #ifndef VSMC_INTEGRATE_NINTEGRATE_NEWTON_COTES_HPP
33 #define VSMC_INTEGRATE_NINTEGRATE_NEWTON_COTES_HPP
34 
36 
37 #define VSMC_STATIC_ASSERT_INTEGRATE_NINTEGRATE_NEWTON_COTES_DEGREE(degree) \
38  VSMC_STATIC_ASSERT((degree >= 1 && degree <= max_degree_), \
39  USE_NIntegrateNewtonCotes_WITH_A_DEGREE_LARGER_THAN_max_degree)
40 
41 namespace vsmc {
42 
43 namespace internal {
44 
45 template <unsigned Index, typename EvalType>
47 {
48  static double result (const double *coeff, double a, double h,
49  const EvalType &eval)
50  {
51  return coeff[Index] * eval(a + (Index - 1) * h) +
53  result(coeff, a, h, eval);
54  }
55 }; // struct NIntegrateNewtonCotesEval
56 
57 template <typename EvalType>
58 struct NIntegrateNewtonCotesEval<1, EvalType>
59 {
60  static double result (const double *coeff, double a, double,
61  const EvalType &eval) {return coeff[1] * eval(a);}
62 }; // struct NIntegrateNewtonCotesEval
63 
64 template <unsigned Degree>
66 {
67  public :
68 
70  {
72 
73  return coeff;
74  }
75 
76  const double *coeff() const {return coeff_;}
77 
78  private :
79 
80  double coeff_[Degree + 2];
81 
84 
85  NIntegrateNewtonCotesCoeff (
86  const NIntegrateNewtonCotesCoeff<Degree> &);
87 
88  NIntegrateNewtonCotesCoeff<Degree> &operator= (
89  const NIntegrateNewtonCotesCoeff<Degree> &);
90 
92  {
93  coeff_[0] = 0.5;
94  coeff_[1] = 1;
95  coeff_[2] = 1;
96  }
97 
98  void coeff_init (cxx11::integral_constant<unsigned, 2>)
99  {
100  coeff_[0] = 1.0 / 6.0;
101  coeff_[1] = 1;
102  coeff_[2] = 4;
103  coeff_[3] = 1;
104  }
105 
106  void coeff_init (cxx11::integral_constant<unsigned, 3>)
107  {
108  coeff_[0] = 0.125;
109  coeff_[1] = 1;
110  coeff_[2] = 3;
111  coeff_[3] = 3;
112  coeff_[4] = 1;
113  }
114 
115  void coeff_init (cxx11::integral_constant<unsigned, 4>)
116  {
117  coeff_[0] = 1.0 / 90.0;
118  coeff_[1] = 7;
119  coeff_[2] = 32;
120  coeff_[3] = 12;
121  coeff_[4] = 32;
122  coeff_[5] = 7;
123  }
124 
125  void coeff_init (cxx11::integral_constant<unsigned, 5>)
126  {
127  coeff_[0] = 1.0 / 288.0;
128  coeff_[1] = 19;
129  coeff_[2] = 75;
130  coeff_[3] = 50;
131  coeff_[4] = 50;
132  coeff_[5] = 75;
133  coeff_[6] = 19;
134  }
135 
136  void coeff_init (cxx11::integral_constant<unsigned, 6>)
137  {
138  coeff_[0] = 1.0 / 840.0;
139  coeff_[1] = 41;
140  coeff_[2] = 216;
141  coeff_[3] = 27;
142  coeff_[4] = 272;
143  coeff_[5] = 27;
144  coeff_[6] = 216;
145  coeff_[7] = 41;
146  }
147 
148  void coeff_init (cxx11::integral_constant<unsigned, 7>)
149  {
150  coeff_[0] = 1.0 / 17280.0;
151  coeff_[1] = 751;
152  coeff_[2] = 3577;
153  coeff_[3] = 1323;
154  coeff_[4] = 2989;
155  coeff_[5] = 2989;
156  coeff_[6] = 1323;
157  coeff_[7] = 3577;
158  coeff_[8] = 751;
159  }
160 
161  void coeff_init (cxx11::integral_constant<unsigned, 8>)
162  {
163  coeff_[0] = 1.0 / 28350.0;
164  coeff_[1] = 989;
165  coeff_[2] = 5888;
166  coeff_[3] = -928;
167  coeff_[4] = 10496;
168  coeff_[5] = -4540;
169  coeff_[6] = 10496;
170  coeff_[7] = -928;
171  coeff_[8] = 5888;
172  coeff_[9] = 989;
173  }
174 
175  void coeff_init (cxx11::integral_constant<unsigned, 9>)
176  {
177  coeff_[0] = 1.0 / 89600.0;
178  coeff_[1] = 2857;
179  coeff_[2] = 15741;
180  coeff_[3] = 1080;
181  coeff_[4] = 19344;
182  coeff_[5] = 5778;
183  coeff_[6] = 5778;
184  coeff_[7] = 19344;
185  coeff_[8] = 1080;
186  coeff_[9] = 15741;
187  coeff_[10] = 2857;
188  }
189 
190  void coeff_init (cxx11::integral_constant<unsigned, 10>)
191  {
192  coeff_[0] = 1.0 / 598752.0;
193  coeff_[1] = 16067;
194  coeff_[2] = 106300;
195  coeff_[3] = -48525;
196  coeff_[4] = 272400;
197  coeff_[5] = -260550;
198  coeff_[6] = 427368;
199  coeff_[7] = -260550;
200  coeff_[8] = 272400;
201  coeff_[9] = -48525;
202  coeff_[10] = 106300;
203  coeff_[11] = 16067;
204  }
205 }; // NIntegrateNewtonCotesCoeff
206 
207 } // namespace vsmc::internal
208 
211 template <unsigned Degree>
213  public NIntegrateBase<NIntegrateNewtonCotes<Degree> >
214 {
215  public :
216 
221 
222  static double integrate_segment (double a, double b, const eval_type &eval)
223  {
225 
226  const double *const coeff =
228 
229  double h = (b - a) / Degree;
230 
231  return coeff[0] * (b - a) * (
233  result(coeff, a, h, eval) + coeff[Degree + 1] * eval(b));
234  }
235 
236  static VSMC_CONSTEXPR unsigned max_degree () {return max_degree_;}
237 
238  private :
239 
240  static VSMC_CONSTEXPR const unsigned max_degree_ = 10;
241 }; // class NIntegrateNewtonCotes
242 
243 } // namespace vsmc
244 
245 #endif // VSMC_INTEGRATE_NINTEGRATE_NEWTON_COTES_HPP
Definition: adapter.hpp:37
static double result(const double *coeff, double a, double h, const EvalType &eval)
#define VSMC_CONSTEXPR
constexpr
Definition: defines.hpp:55
Numerical integration with the (closed) Newton-Cotes formulae.
static double integrate_segment(double a, double b, const eval_type &eval)
static constexpr unsigned max_degree()
NIntegrateBase< NIntegrateNewtonCotes< Degree > >::eval_type eval_type
static double result(const double *coeff, double a, double, const EvalType &eval)
NIntegrateBase< NIntegrateNewtonCotes< Degree > >::size_type size_type
#define VSMC_STATIC_ASSERT_INTEGRATE_NINTEGRATE_NEWTON_COTES_DEGREE(degree)
static NIntegrateNewtonCotesCoeff< Degree > & instance()
Numerical integration base dispatch class.