qxLib
integration.inl
Go to the documentation of this file.
1 /**
2 
3  @file integration.inl
4  @author Khrapov
5  @date 29.04.2023
6  @copyright © Nick Khrapov, 2023. All right reserved.
7 
8 **/
9 
10 namespace qx
11 {
12 
13 template<class function_2d_t>
14 inline double integrate_rectangle_rule(const function_2d_t& func, double x0, double x1, size_t nIntervalsPer1)
15 {
16  const size_t nIntervals = static_cast<size_t>(std::ceil((x1 - x0) * static_cast<double>(nIntervalsPer1)));
17 
18  const double dx = (x1 - x0) / static_cast<double>(nIntervals);
19  double fTotalArea = 0.0;
20  double x = x0;
21 
22  for (size_t i = 0; i < nIntervals; ++i)
23  {
24  fTotalArea += dx * func(x);
25  x += dx;
26  }
27 
28  return fTotalArea;
29 }
30 
31 template<class function_2d_t>
32 double integrate_trapezoid_rule(const function_2d_t& func, double x0, double x1, size_t nIntervalsPer1)
33 {
34  const size_t nIntervals = static_cast<size_t>(std::ceil(static_cast<double>(nIntervalsPer1) * (x1 - x0)));
35 
36  const double dx = (x1 - x0) / static_cast<double>(nIntervals);
37  double fTotalArea = 0.0;
38  double x = x0;
39 
40  for (size_t i = 0; i < nIntervals; ++i)
41  {
42  fTotalArea += dx * (func(x) + func(x + dx)) / 2;
43  x += dx;
44  }
45 
46  return fTotalArea;
47 }
48 
49 template<class function_2d_t>
51  const function_2d_t& func,
52  double x0,
53  double x1,
54  double fMaxSliceError,
55  size_t nIntervalsPer1,
56  size_t nMaxRecursion)
57 {
58  const size_t nIntervals = static_cast<size_t>(std::ceil(static_cast<double>(nIntervalsPer1) * (x1 - x0)));
59 
60  const double dx = (x1 - x0) / static_cast<double>(nIntervals);
61  double fTotalArea = 0.0;
62  double x = x0;
63 
64  auto slice_area = make_recursive_lambda(
65  [nMaxRecursion](
66  const auto& slice_area,
67  const function_2d_t& func,
68  double x0,
69  double x1,
70  double max_slice_error,
71  size_t recursionLevel)
72  {
73  const double y0 = func(x0);
74  const double y1 = func(x1);
75  const double xm = (x0 + x1) / 2;
76  const double ym = func(xm);
77 
78  const double fArea12 = (x1 - x0) * (y0 + y1) / 2.0;
79  const double fArea1m = (xm - x0) * (y0 + ym) / 2.0;
80  const double fAream2 = (x1 - xm) * (ym + y1) / 2.0;
81  const double fArea1m2 = fArea1m + fAream2;
82 
83  const double fError = (fArea1m2 - fArea12) / fArea12;
84 
85  ++recursionLevel;
86  if (recursionLevel > nMaxRecursion || std::abs(fError) < max_slice_error)
87  {
88  return fArea1m2;
89  }
90  else
91  {
92  return slice_area(func, x0, xm, max_slice_error, recursionLevel)
93  + slice_area(func, xm, x1, max_slice_error, recursionLevel);
94  }
95  });
96 
97  for (size_t i = 0; i < nIntervals; ++i)
98  {
99  fTotalArea += slice_area(func, x, x + dx, fMaxSliceError, 0);
100  x += dx;
101  }
102 
103  return fTotalArea;
104 }
105 
106 template<class function_2d_t>
108  const function_2d_t& funcIsInside,
109  glm::dvec2 pos0,
110  glm::dvec2 pos1,
111  size_t nPointsPerOneSquare)
112 {
113  const double fArea = std::abs(pos1.x - pos0.x) * std::abs(pos1.y - pos0.y);
114  const int nTotalPoints = static_cast<int>(std::ceil(fArea * static_cast<double>(nPointsPerOneSquare)));
115 
116  int points_inside = 0;
117 
118  std::default_random_engine generator(static_cast<unsigned>(std::time(nullptr)));
119 
120  std::uniform_real_distribution<double> x_dist(pos0.x, pos1.x);
121  std::uniform_real_distribution<double> y_dist(pos0.y, pos1.y);
122 
123  for (int i = 0; i < nTotalPoints; ++i)
124  {
125  int f = funcIsInside(x_dist(generator), y_dist(generator));
126  if (f > 0)
127  points_inside++;
128  else if (f < 0)
129  points_inside--;
130  }
131 
132  return (static_cast<double>(points_inside) / nTotalPoints) * fArea;
133 }
134 } // namespace qx
double integrate_trapezoid_rule(const function_2d_t &func, double x0, double x1, size_t nIntervalsPer1=10)
Integrate using trapezoid rule.
Definition: integration.inl:32
double integrate_rectangle_rule(const function_2d_t &func, double x0, double x1, size_t nIntervalsPer1=10)
Integrate using rectangle rule.
Definition: integration.inl:14
double integrate_adaptive_midpoint(const function_2d_t &func, double x0, double x1, double fMaxSliceError, size_t nIntervalsPer1=10, size_t nMaxRecursion=300)
Integrate using adaptive midpoint.
Definition: integration.inl:50
double integrate_monte_carlo(const function_2d_t &funcIsInside, glm::dvec2 pos0, glm::dvec2 pos1, size_t nPointsPerOneSquare=1000)
Integrate using probabilistic algorithm Monte Carlo.
recursive_lambda< std::decay_t< lambda_t > > make_recursive_lambda(lambda_t &&lambda)
Create lambda that can be called recursively.