numerical-collection-cpp 0.10.0
A collection of algorithms in numerical analysis implemented in C++
Loading...
Searching...
No Matches
tanh_finite_integrator.h
Go to the documentation of this file.
1/*
2 * Copyright 2024 MusicScience37 (Kenta Kabashima)
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
20#pragma once
21
22#include <cmath> // IWYU pragma: keep
23#include <cstddef>
24#include <type_traits>
25#include <vector>
26
39
41
44 logging::log_tag_view("num_collect::integration::tanh_finite_integrator");
45
46namespace impl {
47
53template <typename Variable>
55
59template <>
61public:
63 static constexpr double default_max_point = 10.0F;
64};
65
69template <>
71public:
73 static constexpr double default_max_point = 20.0;
74};
75
76} // namespace impl
77
84template <typename Signature>
86
94template <typename Result, base::concepts::real_scalar Variable>
95class tanh_finite_integrator<Result(Variable)> : public logging::logging_mixin {
96public:
98 using variable_type = std::decay_t<Variable>;
99
101 using result_type = std::decay_t<Result>;
102
107 : logging::logging_mixin(tanh_finite_integrator_tag) {
108 calculate_coefficients();
109 }
110
120 template <base::concepts::invocable_as<result_type(variable_type)> Function>
121 [[nodiscard]] auto integrate(const Function& function, variable_type left,
122 variable_type right) const -> result_type {
123 const variable_type center =
124 constants::half<variable_type> * (left + right);
125 const variable_type width = right - left;
126
127 constexpr auto center_weight_rate = static_cast<variable_type>(0.5);
128 const variable_type center_weight = width * center_weight_rate;
130 sum += function(center) * center_weight;
131
132 for (index_type i = 0; i < points_; ++i) {
133 const variable_type variable_distance =
134 width * variable_rate_list_[static_cast<std::size_t>(i)];
135 const variable_type weight =
136 width * weight_rate_list_[static_cast<std::size_t>(i)];
137
138 const variable_type var_plus = right - variable_distance;
139 const variable_type var_minus = left + variable_distance;
140 const result_type function_values =
141 function(var_plus) + function(var_minus);
142 if (!base::isfinite(function_values)) [[unlikely]] {
143 NUM_COLLECT_LOG_WARNING(this->logger(),
144 "A function value was not a finite value. "
145 "Stopped numerical integration.");
146 break;
147 }
148 sum += function_values * weight;
149 }
150
151 return sum.sum() * interval_;
152 }
153
168 template <base::concepts::invocable_as<result_type(variable_type)>
169 LeftBoundaryFunction,
170 base::concepts::invocable_as<result_type(variable_type)>
171 RightBoundaryFunction>
172 [[nodiscard]] auto integrate(
173 const LeftBoundaryFunction& left_boundary_function,
174 const RightBoundaryFunction& right_boundary_function,
175 variable_type left, variable_type right) const -> result_type {
176 using constants::half;
177
178 const variable_type width = right - left;
179 const variable_type half_width = half<variable_type> * width;
180
181 constexpr auto center_weight_rate = static_cast<variable_type>(0.5);
182 const variable_type center_weight = width * center_weight_rate;
184 sum += left_boundary_function(half_width) * center_weight;
185
186 for (index_type i = 0; i < points_; ++i) {
187 const variable_type variable_distance =
188 width * variable_rate_list_[static_cast<std::size_t>(i)];
189 const variable_type weight =
190 width * weight_rate_list_[static_cast<std::size_t>(i)];
191
192 const result_type function_values =
193 left_boundary_function(variable_distance) +
194 right_boundary_function(-variable_distance);
195 if (!base::isfinite(function_values)) [[unlikely]] {
196 NUM_COLLECT_LOG_WARNING(this->logger(),
197 "A function value was not a finite value. "
198 "Stopped numerical integration.");
199 break;
200 }
201 sum += function_values * weight;
202 }
203
204 return sum.sum() * interval_;
205 }
206
216 template <base::concepts::invocable_as<result_type(variable_type)> Function>
217 [[nodiscard]] auto operator()(const Function& function, variable_type left,
218 variable_type right) const -> result_type {
219 return integrate(function, left, right);
220 }
221
236 template <base::concepts::invocable_as<result_type(variable_type)>
237 LeftBoundaryFunction,
238 base::concepts::invocable_as<result_type(variable_type)>
239 RightBoundaryFunction>
240 [[nodiscard]] auto operator()(
241 const LeftBoundaryFunction& left_boundary_function,
242 const RightBoundaryFunction& right_boundary_function,
243 variable_type left, variable_type right) const -> result_type {
244 return integrate(
245 left_boundary_function, right_boundary_function, left, right);
246 }
247
255 NUM_COLLECT_PRECONDITION(val > static_cast<variable_type>(0),
256 this->logger(), "Maximum point must be a positive value.");
257 max_point_ = val;
258 calculate_coefficients();
259 return *this;
260 }
261
269 NUM_COLLECT_PRECONDITION(val > 0, this->logger(),
270 "Number of points must a positive integer.");
271 points_ = val;
272 calculate_coefficients();
273 return *this;
274 }
275
276private:
283 using constants::one;
284
285 variable_rate_list_.clear();
286 variable_rate_list_.reserve(static_cast<std::size_t>(points_));
287 weight_rate_list_.clear();
288 weight_rate_list_.reserve(static_cast<std::size_t>(points_));
289
290 interval_ = max_point_ / static_cast<variable_type>(points_);
291 for (index_type i = 1; i <= points_; ++i) {
292 const variable_type changed_variable =
293 interval_ * static_cast<variable_type>(i);
294 const variable_type exp_value =
295 std::exp(static_cast<variable_type>(-2) * changed_variable);
296 const variable_type denominator = one<variable_type> + exp_value;
297 variable_rate_list_.push_back(exp_value / denominator);
298 weight_rate_list_.push_back(static_cast<variable_type>(2) *
299 exp_value / (denominator * denominator));
300 }
301 }
302
304 static constexpr auto default_max_point =
306
308 variable_type max_point_{default_max_point};
309
311 static constexpr index_type default_points = 50;
312
314 index_type points_{default_points};
315
317 variable_type interval_{};
318
320 std::vector<variable_type> variable_rate_list_{};
321
323 std::vector<variable_type> weight_rate_list_{};
324};
325
326} // namespace num_collect::integration
auto operator()(const LeftBoundaryFunction &left_boundary_function, const RightBoundaryFunction &right_boundary_function, variable_type left, variable_type right) const -> result_type
Integrate a function.
auto integrate(const LeftBoundaryFunction &left_boundary_function, const RightBoundaryFunction &right_boundary_function, variable_type left, variable_type right) const -> result_type
Integrate a function.
auto integrate(const Function &function, variable_type left, variable_type right) const -> result_type
Integrate a function.
auto max_point(variable_type val) -> tanh_finite_integrator &
Set maximum point in changed variable.
auto operator()(const Function &function, variable_type left, variable_type right) const -> result_type
Integrate a function.
auto points(index_type val) -> tanh_finite_integrator &
Set number of points.
Class to perform numerical integration on finite range using TANH rule.
Class of tags of logs without memory management.
Class to incorporate logging in algorithms.
Class to add numbers using Kahan summation kahan1965.
Definition kahan_adder.h:32
auto sum() const noexcept -> const T &
Get sum.
Definition of exceptions.
Definition of half.
Definition of index_type type.
Definition of invocable_as concept.
Definition of isfinite function.
Definition of kahan_adder class.
Definition of log_tag_view class.
Definition of macros for logging.
#define NUM_COLLECT_LOG_WARNING(LOGGER,...)
Write a warning log.
Definition of logging_mixin class.
std::ptrdiff_t index_type
Type of indices in this library.
Definition index_type.h:33
auto isfinite(const T &val) -> bool
Check whether a number is finite.
Definition isfinite.h:39
constexpr T half
Value 0.5.
Definition half.h:30
constexpr T one
Value 1.
Definition one.h:30
Namespace of numerical integration.
constexpr auto tanh_finite_integrator_tag
Tag of de_finite_integrator.
Definition of one.
Definition of NUM_COLLECT_PRECONDITION macro.
#define NUM_COLLECT_PRECONDITION(CONDITION,...)
Check whether a precondition is satisfied and throw an exception if not.
Definition of real_scalar concept.
Helper class of constants for use in tanh_finite_integrator class.