Antkeeper  0.0.1
quadrature.hpp
Go to the documentation of this file.
1 /*
2  * Copyright (C) 2023 Christopher J. Howard
3  *
4  * This file is part of Antkeeper source code.
5  *
6  * Antkeeper source code is free software: you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License as published by
8  * the Free Software Foundation, either version 3 of the License, or
9  * (at your option) any later version.
10  *
11  * Antkeeper source code is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14  * GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with Antkeeper source code. If not, see <http://www.gnu.org/licenses/>.
18  */
19 
20 #ifndef ANTKEEPER_MATH_QUADRATURE_HPP
21 #define ANTKEEPER_MATH_QUADRATURE_HPP
22 
23 #include <iterator>
24 #include <type_traits>
25 
26 namespace math {
27 
29 namespace quadrature {
30 
41 template<class UnaryOp, class InputIt>
42 [[nodiscard]] typename std::invoke_result<UnaryOp, typename std::iterator_traits<InputIt>::value_type>::type
43  simpson(UnaryOp f, InputIt first, InputIt last)
44 {
45  typedef typename std::iterator_traits<InputIt>::value_type input_type;
46  typedef typename std::invoke_result<UnaryOp, input_type>::type output_type;
47  typedef decltype(*last - *first) difference_type;
48 
49  if (first == last)
50  return output_type{0};
51 
52  output_type f_a = f(*first);
53 
54  InputIt second = first;
55  ++second;
56 
57  if (second == last)
58  return f_a;
59 
60  difference_type h = *second - *first;
61  output_type f_b = f(*first + h / difference_type(2));
62  output_type f_c = f(*second);
63 
64  output_type sum = (f_a + f_b * difference_type(4) + f_c) * h;
65 
66  for (first = second++; second != last; first = second++)
67  {
68  h = *second - *first;
69 
70  f_a = f_c;
71  f_c = f(*second);
72  f_b = f(*first + h / difference_type(2));
73 
74  sum += (f_a + f_b * difference_type(4) + f_c) * h;
75  }
76 
77  return sum / difference_type(6);
78 }
79 
90 template<class UnaryOp, class InputIt>
91 [[nodiscard]] typename std::invoke_result<UnaryOp, typename std::iterator_traits<InputIt>::value_type>::type
92  trapezoid(UnaryOp f, InputIt first, InputIt last)
93 {
94  typedef typename std::iterator_traits<InputIt>::value_type input_type;
95  typedef typename std::invoke_result<UnaryOp, input_type>::type output_type;
96  typedef decltype(*last - *first) difference_type;
97 
98  if (first == last)
99  return output_type{0};
100 
101  output_type f_a = f(*first);
102 
103  InputIt second = first;
104  ++second;
105 
106  if (second == last)
107  return f_a;
108 
109  output_type f_b = f(*second);
110  output_type sum = (f_a + f_b) * (*second - *first);
111 
112  for (first = second++; second != last; first = second++)
113  {
114  f_a = f_b;
115  f_b = f(*second);
116  sum += (f_a + f_b) * (*second - *first);
117  }
118 
119  return sum / difference_type(2);
120 }
121 
122 } // namespace quadrature
123 
124 } // namespace math
125 
126 #endif // ANTKEEPER_MATH_QUADRATURE_HPP
std::invoke_result< UnaryOp, typename std::iterator_traits< InputIt >::value_type >::type simpson(UnaryOp f, InputIt first, InputIt last)
Approximates the definite integral of a function using Simpson's 1/3 rule.
Definition: quadrature.hpp:43
std::invoke_result< UnaryOp, typename std::iterator_traits< InputIt >::value_type >::type trapezoid(UnaryOp f, InputIt first, InputIt last)
Approximates the definite integral of a function using the trapezoidal rule.
Definition: quadrature.hpp:92
Mathematical functions and data types.
Definition: angles.hpp:26
constexpr T sum(const vector< T, N > &x) noexcept
Calculates the sum of all elements in a vector.
Definition: vector.hpp:1585