cpp-toolbox  0.0.1
A toolbox library for C++
Loading...
Searching...
No Matches
vector_metrics.hpp
Go to the documentation of this file.
1#pragma once
2
3#include <algorithm>
4#include <cmath>
5#include <cstddef>
6#include <cstdlib>
7#include <limits>
8#include <stdexcept>
9
12
13namespace toolbox::metrics
14{
15
16template<typename T>
17class L2Metric : public base_metric_t<L2Metric<T>, T>
18{
19public:
20 using element_type = T;
21
22 constexpr T distance_impl(const T* a, const T* b, std::size_t size) const
23 {
24 return std::sqrt(squared_distance_impl(a, b, size));
25 }
26
27 constexpr T squared_distance_impl(const T* a,
28 const T* b,
29 std::size_t size) const
30 {
31 T sum {};
32 for (std::size_t i = 0; i < size; ++i) {
33 T diff = a[i] - b[i];
34 sum += diff * diff;
35 }
36 return sum;
37 }
38
39 // Overload for point_t types
40 template<typename U>
41 constexpr auto operator()(const toolbox::types::point_t<U>& a,
42 const toolbox::types::point_t<U>& b) const
43 {
44 T dx = a.x - b.x;
45 T dy = a.y - b.y;
46 T dz = a.z - b.z;
47 return std::sqrt(dx * dx + dy * dy + dz * dz);
48 }
49};
50
51template<typename T>
52class L1Metric : public base_metric_t<L1Metric<T>, T>
53{
54public:
55 using element_type = T;
56
57 constexpr T distance_impl(const T* a, const T* b, std::size_t size) const
58 {
59 T sum {};
60 for (std::size_t i = 0; i < size; ++i) {
61 sum += std::abs(a[i] - b[i]);
62 }
63 return sum;
64 }
65
66 constexpr T squared_distance_impl(const T* a,
67 const T* b,
68 std::size_t size) const
69 {
70 T dist = distance_impl(a, b, size);
71 return dist * dist;
72 }
73
74 // Overload for point_t types
75 template<typename U>
76 constexpr auto operator()(const toolbox::types::point_t<U>& a,
77 const toolbox::types::point_t<U>& b) const
78 {
79 return std::abs(static_cast<T>(a.x - b.x)) +
80 std::abs(static_cast<T>(a.y - b.y)) +
81 std::abs(static_cast<T>(a.z - b.z));
82 }
83};
84
85template<typename T>
86class LinfMetric : public base_metric_t<LinfMetric<T>, T>
87{
88public:
89 using element_type = T;
90
91 constexpr T distance_impl(const T* a, const T* b, std::size_t size) const
92 {
93 T max_diff {};
94 for (std::size_t i = 0; i < size; ++i) {
95 T diff = std::abs(a[i] - b[i]);
96 if (diff > max_diff) {
97 max_diff = diff;
98 }
99 }
100 return max_diff;
101 }
102
103 constexpr T squared_distance_impl(const T* a,
104 const T* b,
105 std::size_t size) const
106 {
107 T dist = distance_impl(a, b, size);
108 return dist * dist;
109 }
110
111 // Overload for point_t types
112 template<typename U>
113 constexpr auto operator()(const toolbox::types::point_t<U>& a,
114 const toolbox::types::point_t<U>& b) const
115 {
116 return std::max({std::abs(static_cast<T>(a.x - b.x)),
117 std::abs(static_cast<T>(a.y - b.y)),
118 std::abs(static_cast<T>(a.z - b.z))});
119 }
120};
121
122template<typename T, int P = 2>
123class LpMetric : public base_metric_t<LpMetric<T, P>, T>
124{
125public:
126 using element_type = T;
127 static constexpr int p_value = P;
128
129 constexpr T distance_impl(const T* a, const T* b, std::size_t size) const
130 {
131 static_assert(P > 0, "P must be positive");
132
133 if constexpr (P == 1) {
134 // Special case for L1
135 T sum {};
136 for (std::size_t i = 0; i < size; ++i) {
137 sum += std::abs(a[i] - b[i]);
138 }
139 return sum;
140 }
141 else if constexpr (P == 2) {
142 // Special case for L2
143 return std::sqrt(squared_distance_impl(a, b, size));
144 }
145 else {
146 T sum {};
147 for (std::size_t i = 0; i < size; ++i) {
148 T diff = std::abs(a[i] - b[i]);
149 sum += std::pow(diff, P);
150 }
151 return std::pow(sum, T(1) / P);
152 }
153 }
154
155 constexpr T squared_distance_impl(const T* a,
156 const T* b,
157 std::size_t size) const
158 {
159 if constexpr (P == 2) {
160 T sum {};
161 for (std::size_t i = 0; i < size; ++i) {
162 T diff = a[i] - b[i];
163 sum += diff * diff;
164 }
165 return sum;
166 }
167 else {
168 T dist = distance_impl(a, b, size);
169 return dist * dist;
170 }
171 }
172};
173
174// Specialization for dynamic p-value
175template<typename T>
176class GeneralizedLpMetric : public base_metric_t<GeneralizedLpMetric<T>, T>
177{
178public:
179 using element_type = T;
180
181 explicit GeneralizedLpMetric(T p) : p_(p)
182 {
183 if (p <= 0) {
184 throw std::invalid_argument("P must be positive");
185 }
186 }
187
188 constexpr T distance_impl(const T* a, const T* b, std::size_t size) const
189 {
190 if (std::abs(p_ - T(1)) < std::numeric_limits<T>::epsilon()) {
191 // L1 norm
192 T sum {};
193 for (std::size_t i = 0; i < size; ++i) {
194 sum += std::abs(a[i] - b[i]);
195 }
196 return sum;
197 }
198 else if (std::abs(p_ - T(2)) < std::numeric_limits<T>::epsilon()) {
199 // L2 norm
200 return std::sqrt(squared_distance_impl(a, b, size));
201 }
202 else if (std::isinf(p_)) {
203 // L-infinity norm
204 T max_diff {};
205 for (std::size_t i = 0; i < size; ++i) {
206 T diff = std::abs(a[i] - b[i]);
207 if (diff > max_diff) {
208 max_diff = diff;
209 }
210 }
211 return max_diff;
212 }
213 else {
214 // General Lp norm
215 T sum {};
216 for (std::size_t i = 0; i < size; ++i) {
217 T diff = std::abs(a[i] - b[i]);
218 sum += std::pow(diff, p_);
219 }
220 return std::pow(sum, T(1) / p_);
221 }
222 }
223
224 constexpr T squared_distance_impl(const T* a,
225 const T* b,
226 std::size_t size) const
227 {
228 if (std::abs(p_ - T(2)) < std::numeric_limits<T>::epsilon()) {
229 T sum {};
230 for (std::size_t i = 0; i < size; ++i) {
231 T diff = a[i] - b[i];
232 sum += diff * diff;
233 }
234 return sum;
235 }
236 else {
237 T dist = distance_impl(a, b, size);
238 return dist * dist;
239 }
240 }
241
242 // Overload for point_t types
243 template<typename U>
244 constexpr auto operator()(const toolbox::types::point_t<U>& a,
245 const toolbox::types::point_t<U>& b) const
246 {
247 if (std::abs(p_ - T(1)) < std::numeric_limits<T>::epsilon()) {
248 return std::abs(static_cast<T>(a.x - b.x)) +
249 std::abs(static_cast<T>(a.y - b.y)) +
250 std::abs(static_cast<T>(a.z - b.z));
251 }
252 else if (std::abs(p_ - T(2)) < std::numeric_limits<T>::epsilon()) {
253 T dx = a.x - b.x;
254 T dy = a.y - b.y;
255 T dz = a.z - b.z;
256 return std::sqrt(dx * dx + dy * dy + dz * dz);
257 }
258 else if (std::isinf(p_)) {
259 return std::max({std::abs(static_cast<T>(a.x - b.x)),
260 std::abs(static_cast<T>(a.y - b.y)),
261 std::abs(static_cast<T>(a.z - b.z))});
262 }
263 else {
264 T sum = std::pow(std::abs(static_cast<T>(a.x - b.x)), p_) +
265 std::pow(std::abs(static_cast<T>(a.y - b.y)), p_) +
266 std::pow(std::abs(static_cast<T>(a.z - b.z)), p_);
267 return std::pow(sum, T(1) / p_);
268 }
269 }
270
271 T get_p() const { return p_; }
272
273private:
274 T p_;
275};
276
277} // namespace toolbox::metrics
Definition vector_metrics.hpp:177
GeneralizedLpMetric(T p)
Definition vector_metrics.hpp:181
constexpr auto operator()(const toolbox::types::point_t< U > &a, const toolbox::types::point_t< U > &b) const
Definition vector_metrics.hpp:244
T element_type
Definition vector_metrics.hpp:179
T get_p() const
Definition vector_metrics.hpp:271
constexpr T squared_distance_impl(const T *a, const T *b, std::size_t size) const
Definition vector_metrics.hpp:224
constexpr T distance_impl(const T *a, const T *b, std::size_t size) const
Definition vector_metrics.hpp:188
Definition vector_metrics.hpp:53
T element_type
Definition vector_metrics.hpp:55
constexpr auto operator()(const toolbox::types::point_t< U > &a, const toolbox::types::point_t< U > &b) const
Definition vector_metrics.hpp:76
constexpr T squared_distance_impl(const T *a, const T *b, std::size_t size) const
Definition vector_metrics.hpp:66
constexpr T distance_impl(const T *a, const T *b, std::size_t size) const
Definition vector_metrics.hpp:57
Definition vector_metrics.hpp:18
constexpr T distance_impl(const T *a, const T *b, std::size_t size) const
Definition vector_metrics.hpp:22
constexpr auto operator()(const toolbox::types::point_t< U > &a, const toolbox::types::point_t< U > &b) const
Definition vector_metrics.hpp:41
constexpr T squared_distance_impl(const T *a, const T *b, std::size_t size) const
Definition vector_metrics.hpp:27
T element_type
Definition vector_metrics.hpp:20
Definition vector_metrics.hpp:87
constexpr T squared_distance_impl(const T *a, const T *b, std::size_t size) const
Definition vector_metrics.hpp:103
T element_type
Definition vector_metrics.hpp:89
constexpr auto operator()(const toolbox::types::point_t< U > &a, const toolbox::types::point_t< U > &b) const
Definition vector_metrics.hpp:113
constexpr T distance_impl(const T *a, const T *b, std::size_t size) const
Definition vector_metrics.hpp:91
Definition vector_metrics.hpp:124
T element_type
Definition vector_metrics.hpp:126
constexpr T squared_distance_impl(const T *a, const T *b, std::size_t size) const
Definition vector_metrics.hpp:155
constexpr T distance_impl(const T *a, const T *b, std::size_t size) const
Definition vector_metrics.hpp:129
static constexpr int p_value
Definition vector_metrics.hpp:127
Definition base_metric.hpp:13
Definition angular_metrics.hpp:11
3D点/向量模板类 / A 3D point/vector template class
Definition point.hpp:48
T x
X坐标 / X coordinate.
Definition point.hpp:51
T z
Z坐标 / Z coordinate.
Definition point.hpp:53
T y
Y坐标 / Y coordinate.
Definition point.hpp:52