GteIntegration.h
Go to the documentation of this file.
1 // David Eberly, Geometric Tools, Redmond WA 98052
2 // Copyright (c) 1998-2017
3 // Distributed under the Boost Software License, Version 1.0.
4 // http://www.boost.org/LICENSE_1_0.txt
5 // http://www.geometrictools.com/License/Boost/LICENSE_1_0.txt
6 // File Version: 3.0.0 (2016/06/19)
7 
8 #pragma once
9 
11 #include <array>
12 #include <functional>
13 #include <vector>
14 
15 namespace gte
16 {
17 
18 template <typename Real>
20 {
21 public:
22  // A simple algorithm, but slow to converge as the number of samples is
23  // increased. The 'numSamples' needs to be two or larger.
24  static Real TrapezoidRule(int numSamples, Real a, Real b,
25  std::function<Real(Real)> const& integrand);
26 
27  // The trapezoid rule is used to generate initial estimates, but then
28  // Richardson extrapolation is used to improve the estimates. This is
29  // preferred over TrapezoidRule. The 'order' must be positive.
30  static Real Romberg(int order, Real a, Real b,
31  std::function<Real(Real)> const& integrand);
32 
33  // Gaussian quadrature estimates the integral of a function f(x) defined
34  // on [-1,1] using
35  // integral_{-1}^{1} f(t) dt = sum_{i=0}^{n-1} c[i]*f(r[i])
36  // where r[i] are the roots to the Legendre polynomial p(t) of degree n
37  // and c[i] = integral_{-1}^{1} prod_{j=0,j!=i} (t-r[j]/(r[i]-r[j]) dt.
38  // To integrate over [a,b], a transformation to [-1,1] is applied
39  // internally: x - ((b-a)*t + (b+a))/2. The Legendre polynomials are
40  // generated by
41  // P[0](x) = 1, P[1](x) = x,
42  // P[k](x) = ((2*k-1)*x*P[k-1](x) - (k-1)*P[k-2](x))/k, k >= 2
43  // Implementing the polynomial generation is simple, and computing the
44  // roots requires a numerical method for finding polynomial roots. The
45  // challenging task is to develop an efficient algorithm for computing
46  // the coefficients c[i] for a specified degree. The 'degree' must be
47  // two or larger.
48 
49  static void ComputeQuadratureInfo(int degree, std::vector<Real>& roots,
50  std::vector<Real>& coefficients);
51 
52  static Real GaussianQuadrature(std::vector<Real> const& roots,
53  std::vector<Real>const & coefficients, Real a, Real b,
54  std::function<Real(Real)> const& integrand);
55 };
56 
57 
58 template <typename Real>
59 Real Integration<Real>::TrapezoidRule(int numSamples, Real a, Real b,
60  std::function<Real(Real)> const& integrand)
61 {
62  Real h = (b - a) / (Real)(numSamples - 1);
63  Real result = ((Real)0.5) * (integrand(a) + integrand(b));
64  for (int i = 1; i <= numSamples - 2; ++i)
65  {
66  result += integrand(a + i*h);
67  }
68  result *= h;
69  return result;
70 }
71 
72 template <typename Real>
73 Real Integration<Real>::Romberg(int order, Real a, Real b,
74  std::function<Real(Real)> const& integrand)
75 {
76  Real const half = (Real)0.5;
77  std::vector<std::array<Real, 2>> rom(order);
78  Real h = b - a;
79  rom[0][0] = half * h * (integrand(a) + integrand(b));
80  for (int i0 = 2, p0 = 1; i0 <= order; ++i0, p0 *= 2, h *= half)
81  {
82  // Approximations via the trapezoid rule.
83  Real sum = (Real)0;
84  int i1;
85  for (i1 = 1; i1 <= p0; ++i1)
86  {
87  sum += integrand(a + h * (i1 - half));
88  }
89 
90  // Richardson extrapolation.
91  rom[0][1] = half * (rom[0][0] + h * sum);
92  for (int i2 = 1, p2 = 4; i2 < i0; ++i2, p2 *= 4)
93  {
94  rom[i2][1] = (p2*rom[i2 - 1][1] - rom[i2 - 1][0]) / (p2 - 1);
95  }
96 
97  for (i1 = 0; i1 < i0; ++i1)
98  {
99  rom[i1][0] = rom[i1][1];
100  }
101  }
102 
103  Real result = rom[order - 1][0];
104  return result;
105 }
106 
107 template <typename Real>
109  std::vector<Real>& roots, std::vector<Real>& coefficients)
110 {
111  Real const zero = (Real)0;
112  Real const one = (Real)1;
113  Real const half = (Real)0.5;
114 
115  std::vector<std::vector<Real>> poly(degree + 1);
116 
117  poly[0].resize(1);
118  poly[0][0] = one;
119 
120  poly[1].resize(2);
121  poly[1][0] = zero;
122  poly[1][1] = one;
123 
124  for (int n = 2; n <= degree; ++n)
125  {
126  Real mult0 = (Real)(n - 1) / (Real)n;
127  Real mult1 = (Real)(2 * n - 1) / (Real)n;
128 
129  poly[n].resize(n + 1);
130  poly[n][0] = -mult0 * poly[n - 2][0];
131  for (int i = 1; i <= n - 2; ++i)
132  {
133  poly[n][i] = mult1 * poly[n - 1][i - 1] - mult0 * poly[n - 2][i];
134  }
135  poly[n][n - 1] = mult1 * poly[n - 1][n - 2];
136  poly[n][n] = mult1 * poly[n - 1][n - 1];
137  }
138 
139  roots.resize(degree);
140  RootsPolynomial<Real>::Find(degree, &poly[degree][0], 2048, &roots[0]);
141 
142  coefficients.resize(roots.size());
143  size_t n = roots.size() - 1;
144  std::vector<Real> subroots(n);
145  for (size_t i = 0; i < roots.size(); ++i)
146  {
147  Real denominator = (Real)1;
148  for (size_t j = 0, k = 0; j < roots.size(); ++j)
149  {
150  if (j != i)
151  {
152  subroots[k++] = roots[j];
153  denominator *= roots[i] - roots[j];
154  }
155  }
156 
157  std::array<Real, 2> delta =
158  {
159  -one - subroots.back(),
160  +one - subroots.back()
161  };
162 
163  std::vector<std::array<Real, 2>> weights(n);
164  weights[0][0] = half * delta[0] * delta[0];
165  weights[0][1] = half * delta[1] * delta[1];
166  for (size_t k = 1; k < n; ++k)
167  {
168  Real dk = (Real)k;
169  Real mult = -dk / (dk + (Real)2);
170  weights[k][0] = mult * delta[0] * weights[k - 1][0];
171  weights[k][1] = mult * delta[1] * weights[k - 1][1];
172  }
173 
174  struct Info
175  {
176  int numBits;
177  std::array<Real, 2> product;
178  };
179 
180  int numElements = (1 << static_cast<unsigned int>(n - 1));
181  std::vector<Info> info(numElements);
182  info[0].numBits = 0;
183  info[0].product[0] = one;
184  info[0].product[1] = one;
185  for (int ipow = 1, r = 0; ipow < numElements; ipow <<= 1, ++r)
186  {
187  info[ipow].numBits = 1;
188  info[ipow].product[0] = -one - subroots[r];
189  info[ipow].product[1] = +one - subroots[r];
190  for (int m = 1, j = ipow + 1; m < ipow; ++m, ++j)
191  {
192  info[j].numBits = info[m].numBits + 1;
193  info[j].product[0] =
194  info[ipow].product[0] * info[m].product[0];
195  info[j].product[1] =
196  info[ipow].product[1] * info[m].product[1];
197  }
198  }
199 
200  std::vector<std::array<Real, 2>> sum(n);
201  std::array<Real, 2> zero2 = { zero, zero };
202  std::fill(sum.begin(), sum.end(), zero2);
203  for (size_t k = 0; k < info.size(); ++k)
204  {
205  sum[info[k].numBits][0] += info[k].product[0];
206  sum[info[k].numBits][1] += info[k].product[1];
207  }
208 
209  std::array<Real, 2> total = zero2;
210  for (size_t k = 0; k < n; ++k)
211  {
212  total[0] += weights[n - 1 - k][0] * sum[k][0];
213  total[1] += weights[n - 1 - k][1] * sum[k][1];
214  }
215 
216  coefficients[i] = (total[1] - total[0]) / denominator;
217  }
218 }
219 
220 template <typename Real>
221 Real Integration<Real>::GaussianQuadrature(std::vector<Real> const& roots,
222  std::vector<Real>const & coefficients, Real a, Real b,
223  std::function<Real(Real)> const& integrand)
224 {
225  Real const half = (Real)0.5;
226  Real radius = half * (b - a);
227  Real center = half * (b + a);
228  Real result = (Real)0;
229  for (size_t i = 0; i < roots.size(); ++i)
230  {
231  result += coefficients[i] * integrand(radius*roots[i] + center);
232  }
233  result *= radius;
234  return result;
235 }
236 
237 
238 }
GLdouble n
Definition: glcorearb.h:2003
GLfixed GLfixed GLint GLint order
Definition: glext.h:4927
const GLbyte * weights
Definition: glext.h:4455
static Real GaussianQuadrature(std::vector< Real > const &roots, std::vector< Real >const &coefficients, Real a, Real b, std::function< Real(Real)> const &integrand)
const GLfloat * m
Definition: glext.h:6461
GLboolean GLboolean GLboolean GLboolean a
Definition: glcorearb.h:1217
static Real TrapezoidRule(int numSamples, Real a, Real b, std::function< Real(Real)> const &integrand)
static void ComputeQuadratureInfo(int degree, std::vector< Real > &roots, std::vector< Real > &coefficients)
GLboolean GLboolean GLboolean b
Definition: glcorearb.h:1217
INT32 INT32 * denominator
Definition: wglext.h:821
GLfloat GLfloat GLfloat GLfloat h
Definition: glcorearb.h:1997
GLboolean r
Definition: glcorearb.h:1217
static Real Romberg(int order, Real a, Real b, std::function< Real(Real)> const &integrand)
GLuint64EXT * result
Definition: glext.h:10003
static int Find(int degree, Real const *c, unsigned int maxIterations, Real *roots)


geometric_tools_engine
Author(s): Yijiang Huang
autogenerated on Thu Jul 18 2019 04:00:00