|
1 | 1 | #ifndef MATH_SEGMENTEDFUNC_TPP |
2 | 2 | #define MATH_SEGMENTEDFUNC_TPP |
3 | 3 |
|
| 4 | +#include <ranges> |
| 5 | + |
4 | 6 | #include "base/math/interpolation.h" |
5 | 7 | #include "base/math/range.h" |
6 | 8 |
|
7 | 9 | #include "segmentedfunc.h" |
8 | 10 |
|
9 | 11 | template <typename T> |
10 | | -T Math::SegmentedFunction<T>::at(double pos) const |
| 12 | +T Math::SegmentedFunction<T>::operator()(double pos) const |
11 | 13 | { |
12 | 14 | if (stops.empty()) return T(); |
13 | | - if (stops.size() == 1) return stops.at(0).value; |
14 | | - |
15 | | - if (pos < stops.front().pos) return stops.front().value; |
16 | | - if (pos > stops.back().pos) return stops.back().value; |
| 15 | + if (stops.size() == 1 || pos < stops.front().pos) |
| 16 | + return stops.front().value; |
17 | 17 |
|
18 | | - for (auto i = 1U; i < stops.size(); ++i) { |
19 | | - auto &[ppos, pval] = stops[i - 1]; |
20 | | - auto &[cpos, cval] = stops[i]; |
21 | | - if (ppos <= pos && pos <= cpos) |
22 | | - return interpolate(pval, |
23 | | - cval, |
24 | | - Range{ppos, cpos}.rescale(pos)); |
25 | | - } |
| 18 | + if (auto it = std::ranges::adjacent_find(stops, |
| 19 | + [pos](auto &&cur, auto &&next) |
| 20 | + { |
| 21 | + return cur.pos <= pos && pos <= next.pos; |
| 22 | + }); |
| 23 | + it != stops.end()) |
| 24 | + return interpolate(it->value, |
| 25 | + std::next(it)->value, |
| 26 | + Range{it->pos, std::next(it)->pos}.rescale(pos)); |
26 | 27 |
|
27 | 28 | return stops.back().value; |
28 | 29 | } |
29 | 30 |
|
30 | 31 | template <typename T> |
31 | | -bool Math::SegmentedFunction<T>::operator==( |
32 | | - const SegmentedFunction &other) const |
33 | | -{ |
34 | | - return stops == other.stops; |
35 | | -} |
36 | | - |
37 | | -template <typename T> |
38 | | -Math::SegmentedFunction<T> Math::SegmentedFunction<T>::operator*( |
39 | | - double value) const |
| 32 | +template <class Self> |
| 33 | +Self Math::SegmentedFunction<T>::operator*(this const Self &self, |
| 34 | + double value) |
40 | 35 | { |
41 | | - auto res = *this; |
| 36 | + auto res = self; |
42 | 37 | for (auto &stop : res.stops) stop.value = stop.value * value; |
43 | 38 | return res; |
44 | 39 | } |
45 | 40 |
|
46 | 41 | template <typename T> |
47 | | -Math::SegmentedFunction<T> Math::SegmentedFunction<T>::operator+( |
48 | | - const SegmentedFunction &other) const |
| 42 | +template <class Self> |
| 43 | +Self Math::SegmentedFunction<T>::operator+(this const Self &self, |
| 44 | + const Self &other) |
49 | 45 | { |
50 | | - SegmentedFunction<T> res; |
| 46 | + Self res; |
| 47 | + auto &stops = self.stops; |
51 | 48 |
|
52 | 49 | for (auto it0 = stops.begin(), it1 = other.stops.begin(); |
53 | 50 | it0 != stops.end() || it1 != other.stops.end();) { |
54 | 51 | if (it1 == other.stops.end() || it0->pos < it1->pos) { |
55 | 52 | res.stops.emplace_back(it0->pos, |
56 | | - it0->value + other.at(it0->pos)); |
| 53 | + it0->value + other(it0->pos)); |
57 | 54 | ++it0; |
58 | 55 | } |
59 | 56 | else if (it0 == stops.end() || it1->pos < it0->pos) { |
60 | 57 | res.stops.emplace_back(it1->pos, |
61 | | - it1->value + at(it1->pos)); |
| 58 | + it1->value + self(it1->pos)); |
62 | 59 | ++it1; |
63 | 60 | } |
64 | 61 | else { |
|
0 commit comments