cpp-toolbox  0.0.1
A toolbox library for C++
Loading...
Searching...
No Matches
angular_metrics.hpp
Go to the documentation of this file.
1#pragma once
2
3#include <algorithm>
4#include <cmath>
5#include <numeric>
6
9
11{
12
13template<typename T>
14class CosineMetric : public base_metric_t<CosineMetric<T>, T>
15{
16public:
17 using element_type = T;
18
19 constexpr T distance_impl(const T* a, const T* b, std::size_t size) const
20 {
21 T dot_product {};
22 T norm_a {};
23 T norm_b {};
24
25 for (std::size_t i = 0; i < size; ++i) {
26 dot_product += a[i] * b[i];
27 norm_a += a[i] * a[i];
28 norm_b += b[i] * b[i];
29 }
30
31 norm_a = std::sqrt(norm_a);
32 norm_b = std::sqrt(norm_b);
33
34 if (norm_a < std::numeric_limits<T>::epsilon() ||
35 norm_b < std::numeric_limits<T>::epsilon()) {
36 return T(1); // Maximum distance for zero vectors
37 }
38
39 // Cosine similarity is in [-1, 1], convert to distance in [0, 2]
40 T cosine_similarity = dot_product / (norm_a * norm_b);
41
42 // Clamp to handle numerical errors
43 cosine_similarity = std::max(T(-1), std::min(T(1), cosine_similarity));
44
45 // Convert to distance: 1 - cosine_similarity gives [0, 2]
46 return T(1) - cosine_similarity;
47 }
48
49 constexpr T squared_distance_impl(const T* a, const T* b, std::size_t size) const
50 {
51 T dist = distance_impl(a, b, size);
52 return dist * dist;
53 }
54
55 // Overload for point_t types
56 template<typename U>
57 constexpr auto operator()(const toolbox::types::point_t<U>& a,
58 const toolbox::types::point_t<U>& b) const
59 {
60 T arr_a[3] = {static_cast<T>(a.x), static_cast<T>(a.y), static_cast<T>(a.z)};
61 T arr_b[3] = {static_cast<T>(b.x), static_cast<T>(b.y), static_cast<T>(b.z)};
62 return distance_impl(arr_a, arr_b, 3);
63 }
64};
65
66template<typename T>
67class AngularMetric : public base_metric_t<AngularMetric<T>, T>
68{
69public:
70 using element_type = T;
71
72 constexpr T distance_impl(const T* a, const T* b, std::size_t size) const
73 {
74 T dot_product {};
75 T norm_a {};
76 T norm_b {};
77
78 for (std::size_t i = 0; i < size; ++i) {
79 dot_product += a[i] * b[i];
80 norm_a += a[i] * a[i];
81 norm_b += b[i] * b[i];
82 }
83
84 norm_a = std::sqrt(norm_a);
85 norm_b = std::sqrt(norm_b);
86
87 if (norm_a < std::numeric_limits<T>::epsilon() ||
88 norm_b < std::numeric_limits<T>::epsilon()) {
89 return T(M_PI); // Maximum angular distance
90 }
91
92 // Compute cosine of angle
93 T cosine = dot_product / (norm_a * norm_b);
94
95 // Clamp to handle numerical errors
96 cosine = std::max(T(-1), std::min(T(1), cosine));
97
98 // Return angle in radians [0, pi]
99 return std::acos(cosine);
100 }
101
102 constexpr T squared_distance_impl(const T* a, const T* b, std::size_t size) const
103 {
104 T dist = distance_impl(a, b, size);
105 return dist * dist;
106 }
107
108 // Overload for point_t types
109 template<typename U>
110 constexpr auto operator()(const toolbox::types::point_t<U>& a,
111 const toolbox::types::point_t<U>& b) const
112 {
113 T arr_a[3] = {static_cast<T>(a.x), static_cast<T>(a.y), static_cast<T>(a.z)};
114 T arr_b[3] = {static_cast<T>(b.x), static_cast<T>(b.y), static_cast<T>(b.z)};
115 return distance_impl(arr_a, arr_b, 3);
116 }
117};
118
119// Normalized angular distance (scaled to [0, 1])
120template<typename T>
121class NormalizedAngularMetric : public base_metric_t<NormalizedAngularMetric<T>, T>
122{
123public:
124 using element_type = T;
125
126 constexpr T distance_impl(const T* a, const T* b, std::size_t size) const
127 {
128 T dot_product {};
129 T norm_a {};
130 T norm_b {};
131
132 for (std::size_t i = 0; i < size; ++i) {
133 dot_product += a[i] * b[i];
134 norm_a += a[i] * a[i];
135 norm_b += b[i] * b[i];
136 }
137
138 norm_a = std::sqrt(norm_a);
139 norm_b = std::sqrt(norm_b);
140
141 if (norm_a < std::numeric_limits<T>::epsilon() ||
142 norm_b < std::numeric_limits<T>::epsilon()) {
143 return T(1); // Maximum normalized distance
144 }
145
146 // Compute cosine of angle
147 T cosine = dot_product / (norm_a * norm_b);
148
149 // Clamp to handle numerical errors
150 cosine = std::max(T(-1), std::min(T(1), cosine));
151
152 // Return normalized angle [0, 1]
153 return std::acos(cosine) / T(M_PI);
154 }
155
156 constexpr T squared_distance_impl(const T* a, const T* b, std::size_t size) const
157 {
158 T dist = distance_impl(a, b, size);
159 return dist * dist;
160 }
161};
162
163// Correlation distance (based on Pearson correlation)
164template<typename T>
165class CorrelationMetric : public base_metric_t<CorrelationMetric<T>, T>
166{
167public:
168 using element_type = T;
169
170 constexpr T distance_impl(const T* a, const T* b, std::size_t size) const
171 {
172 if (size == 0) {
173 return T(0);
174 }
175
176 // Compute means
177 T mean_a = std::accumulate(a, a + size, T(0)) / size;
178 T mean_b = std::accumulate(b, b + size, T(0)) / size;
179
180 // Compute correlation
181 T cov {};
182 T var_a {};
183 T var_b {};
184
185 for (std::size_t i = 0; i < size; ++i) {
186 T diff_a = a[i] - mean_a;
187 T diff_b = b[i] - mean_b;
188 cov += diff_a * diff_b;
189 var_a += diff_a * diff_a;
190 var_b += diff_b * diff_b;
191 }
192
193 if (var_a < std::numeric_limits<T>::epsilon() ||
194 var_b < std::numeric_limits<T>::epsilon()) {
195 return T(1); // Maximum distance for constant vectors
196 }
197
198 T correlation = cov / std::sqrt(var_a * var_b);
199
200 // Clamp to handle numerical errors
201 correlation = std::max(T(-1), std::min(T(1), correlation));
202
203 // Convert correlation to distance: (1 - correlation) / 2 gives [0, 1]
204 return (T(1) - correlation) / T(2);
205 }
206
207 constexpr T squared_distance_impl(const T* a, const T* b, std::size_t size) const
208 {
209 T dist = distance_impl(a, b, size);
210 return dist * dist;
211 }
212};
213
214// Inner product distance (for normalized vectors)
215template<typename T>
216class InnerProductMetric : public base_metric_t<InnerProductMetric<T>, T>
217{
218public:
219 using element_type = T;
220
221 constexpr T distance_impl(const T* a, const T* b, std::size_t size) const
222 {
223 T inner_product {};
224
225 for (std::size_t i = 0; i < size; ++i) {
226 inner_product += a[i] * b[i];
227 }
228
229 // For normalized vectors, inner product is in [-1, 1]
230 // Convert to distance
231 return T(1) - inner_product;
232 }
233
234 constexpr T squared_distance_impl(const T* a, const T* b, std::size_t size) const
235 {
236 T dist = distance_impl(a, b, size);
237 return dist * dist;
238 }
239};
240
241} // namespace toolbox::metrics
Definition angular_metrics.hpp:68
constexpr T distance_impl(const T *a, const T *b, std::size_t size) const
Definition angular_metrics.hpp:72
T element_type
Definition angular_metrics.hpp:70
constexpr auto operator()(const toolbox::types::point_t< U > &a, const toolbox::types::point_t< U > &b) const
Definition angular_metrics.hpp:110
constexpr T squared_distance_impl(const T *a, const T *b, std::size_t size) const
Definition angular_metrics.hpp:102
Definition angular_metrics.hpp:166
constexpr T distance_impl(const T *a, const T *b, std::size_t size) const
Definition angular_metrics.hpp:170
T element_type
Definition angular_metrics.hpp:168
constexpr T squared_distance_impl(const T *a, const T *b, std::size_t size) const
Definition angular_metrics.hpp:207
Definition angular_metrics.hpp:15
constexpr auto operator()(const toolbox::types::point_t< U > &a, const toolbox::types::point_t< U > &b) const
Definition angular_metrics.hpp:57
T element_type
Definition angular_metrics.hpp:17
constexpr T squared_distance_impl(const T *a, const T *b, std::size_t size) const
Definition angular_metrics.hpp:49
constexpr T distance_impl(const T *a, const T *b, std::size_t size) const
Definition angular_metrics.hpp:19
Definition angular_metrics.hpp:217
T element_type
Definition angular_metrics.hpp:219
constexpr T distance_impl(const T *a, const T *b, std::size_t size) const
Definition angular_metrics.hpp:221
constexpr T squared_distance_impl(const T *a, const T *b, std::size_t size) const
Definition angular_metrics.hpp:234
Definition angular_metrics.hpp:122
constexpr T distance_impl(const T *a, const T *b, std::size_t size) const
Definition angular_metrics.hpp:126
constexpr T squared_distance_impl(const T *a, const T *b, std::size_t size) const
Definition angular_metrics.hpp:156
T element_type
Definition angular_metrics.hpp:124
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