FERS 1.0.0
The Flexible Extensible Radar Simulator
Loading...
Searching...
No Matches
interpolation_set.cpp
Go to the documentation of this file.
1// SPDX-License-Identifier: GPL-2.0-only
2//
3// Copyright (c) 2007-2008 Marc Brooker and Michael Inggs
4// Copyright (c) 2008-present FERS Contributors (see AUTHORS.md).
5//
6// See the GNU GPLv2 LICENSE file in the FERS project root for more information.
7
8/**
9 * @file interpolation_set.cpp
10 * @brief Implementation file for interpolation of sets of data.
11 */
12
13#include "interpolation_set.h"
14
15#include <algorithm>
16#include <cmath>
17#include <cstddef>
18#include <iterator>
19#include <ranges>
20#include <stdexcept>
21
22namespace interp
23{
24 template <RealConcept T>
25 std::optional<T> InterpSetData::value(T x) const noexcept
26 {
27 if (_data.empty())
28 {
29 return std::nullopt;
30 }
31
32 // TODO: RealConcept is broader than the implementation really supports?
33 // std::is_arithmetic_v<T> admits integral types
34 // That may be intended, but for value(T x) it means interpolation with
35 // integer queries returns std::optional<int>, and the final interpolated
36 // double gets truncated by:
37 // return static_cast<T>(...)
38 // If the class is conceptually for real-valued interpolation,
39 // std::floating_point<T> would be a better constraint
40 const RealType x_value = static_cast<RealType>(x);
41 const auto iter = _data.lower_bound(x_value);
42
43 if (iter == _data.begin())
44 {
45 return static_cast<T>(iter->second);
46 }
47 if (iter == _data.end())
48 {
49 const auto prev = std::prev(iter);
50 return static_cast<T>(prev->second);
51 }
52 if (iter->first == x_value)
53 {
54 return static_cast<T>(iter->second);
55 }
56
57 auto prev = std::prev(iter);
58 const auto [x1, y1] = *prev;
59 const auto [x2, y2] = *iter;
60
61 return static_cast<T>(y2 * (x_value - x1) / (x2 - x1) + y1 * (x2 - x_value) / (x2 - x1));
62 }
63
64 double InterpSetData::max() const noexcept
65 {
66 auto values = _data | std::views::values;
67
68 const auto max_element =
69 std::ranges::max_element(values, [](const double a, const double b) { return std::abs(a) < std::abs(b); });
70
71 return max_element != values.end() ? std::abs(*max_element) : 0.0;
72 }
73
74 template <RealConcept T>
76 {
77 if (a == 0)
78 {
79 throw std::invalid_argument("Division by zero is not allowed.");
80 }
81
82 std::ranges::for_each(_data | std::views::values, [a](auto& value) { value /= static_cast<double>(a); });
83 }
84
85 // Explicit instantiations for double and float
86 template std::optional<double> InterpSetData::value<double>(double) const noexcept;
87
88 template void InterpSetData::divide<double>(double);
89
90 template std::optional<float> InterpSetData::value<float>(float) const noexcept;
91
92 template void InterpSetData::divide<float>(float);
93}
double max() const noexcept
Retrieves the maximum absolute value in the interpolation set.
void divide(T a)
Divides all y-values in the dataset by a given number.
std::optional< T > value(T x) const noexcept
Retrieves the interpolated value at a given point.
double RealType
Type for real numbers.
Definition config.h:27
Header file for the interpolation of sets of data.