30template <
typename Iterator1,
typename Iterator2>
32 Iterator2 first2, Iterator2 last2)
34 auto n1 = std::distance(first1, last1);
35 auto n2 = std::distance(first2, last2);
38 throw std::invalid_argument(
"statcpp::euclidean_distance: sequences must have the same length");
41 throw std::invalid_argument(
"statcpp::euclidean_distance: empty sequences");
48 while (it1 != last1) {
49 double diff =
static_cast<double>(*it1) -
static_cast<double>(*it2);
55 return std::sqrt(sum_sq);
61template <
typename Iterator1,
typename Iterator2,
typename Proj1,
typename Proj2>
63 Iterator2 first2, Iterator2 last2,
64 Proj1 proj1, Proj2 proj2)
66 auto n1 = std::distance(first1, last1);
67 auto n2 = std::distance(first2, last2);
70 throw std::invalid_argument(
"statcpp::euclidean_distance: sequences must have the same length");
73 throw std::invalid_argument(
"statcpp::euclidean_distance: empty sequences");
80 while (it1 != last1) {
81 double v1 =
static_cast<double>(proj1(*it1));
82 double v2 =
static_cast<double>(proj2(*it2));
83 double diff = v1 - v2;
89 return std::sqrt(sum_sq);
107template <
typename Iterator1,
typename Iterator2>
109 Iterator2 first2, Iterator2 last2)
111 auto n1 = std::distance(first1, last1);
112 auto n2 = std::distance(first2, last2);
115 throw std::invalid_argument(
"statcpp::manhattan_distance: sequences must have the same length");
118 throw std::invalid_argument(
"statcpp::manhattan_distance: empty sequences");
121 double sum_abs = 0.0;
125 while (it1 != last1) {
126 double diff =
static_cast<double>(*it1) -
static_cast<double>(*it2);
127 sum_abs += std::abs(
diff);
138template <
typename Iterator1,
typename Iterator2,
typename Proj1,
typename Proj2>
140 Iterator2 first2, Iterator2 last2,
141 Proj1 proj1, Proj2 proj2)
143 auto n1 = std::distance(first1, last1);
144 auto n2 = std::distance(first2, last2);
147 throw std::invalid_argument(
"statcpp::manhattan_distance: sequences must have the same length");
150 throw std::invalid_argument(
"statcpp::manhattan_distance: empty sequences");
153 double sum_abs = 0.0;
157 while (it1 != last1) {
158 double v1 =
static_cast<double>(proj1(*it1));
159 double v2 =
static_cast<double>(proj2(*it2));
160 double diff = v1 - v2;
161 sum_abs += std::abs(
diff);
189template <
typename Iterator1,
typename Iterator2>
191 Iterator2 first2, Iterator2 last2)
193 auto n1 = std::distance(first1, last1);
194 auto n2 = std::distance(first2, last2);
197 throw std::invalid_argument(
"statcpp::cosine_similarity: sequences must have the same length");
200 throw std::invalid_argument(
"statcpp::cosine_similarity: empty sequences");
203 double dot_product = 0.0;
204 double norm1_sq = 0.0;
205 double norm2_sq = 0.0;
210 while (it1 != last1) {
211 double v1 =
static_cast<double>(*it1);
212 double v2 =
static_cast<double>(*it2);
214 dot_product += v1 * v2;
222 if (norm1_sq == 0.0 || norm2_sq == 0.0) {
223 throw std::invalid_argument(
"statcpp::cosine_similarity: zero vector encountered");
226 return dot_product / (std::sqrt(norm1_sq) * std::sqrt(norm2_sq));
232template <
typename Iterator1,
typename Iterator2,
typename Proj1,
typename Proj2>
234 Iterator2 first2, Iterator2 last2,
235 Proj1 proj1, Proj2 proj2)
237 auto n1 = std::distance(first1, last1);
238 auto n2 = std::distance(first2, last2);
241 throw std::invalid_argument(
"statcpp::cosine_similarity: sequences must have the same length");
244 throw std::invalid_argument(
"statcpp::cosine_similarity: empty sequences");
247 double dot_product = 0.0;
248 double norm1_sq = 0.0;
249 double norm2_sq = 0.0;
254 while (it1 != last1) {
255 double v1 =
static_cast<double>(proj1(*it1));
256 double v2 =
static_cast<double>(proj2(*it2));
258 dot_product += v1 * v2;
266 if (norm1_sq == 0.0 || norm2_sq == 0.0) {
267 throw std::invalid_argument(
"statcpp::cosine_similarity: zero vector encountered");
270 return dot_product / (std::sqrt(norm1_sq) * std::sqrt(norm2_sq));
287template <
typename Iterator1,
typename Iterator2>
289 Iterator2 first2, Iterator2 last2)
297template <
typename Iterator1,
typename Iterator2,
typename Proj1,
typename Proj2>
299 Iterator2 first2, Iterator2 last2,
300 Proj1 proj1, Proj2 proj2)
323 const std::vector<double>&
mean,
324 const std::vector<std::vector<double>>& cov_matrix)
326 if (x.size() !=
mean.size()) {
327 throw std::invalid_argument(
"statcpp::mahalanobis_distance: x and mean must have same dimension");
330 throw std::invalid_argument(
"statcpp::mahalanobis_distance: only 2D is currently supported");
332 if (cov_matrix.size() != 2 || cov_matrix[0].size() != 2 || cov_matrix[1].size() != 2) {
333 throw std::invalid_argument(
"statcpp::mahalanobis_distance: covariance matrix must be 2x2");
337 double d0 = x[0] -
mean[0];
338 double d1 = x[1] -
mean[1];
346 double a = cov_matrix[0][0];
347 double b = cov_matrix[0][1];
348 double c = cov_matrix[1][0];
349 double d = cov_matrix[1][1];
351 double det = a * d - b * c;
353 if (std::abs(det) < 1e-10) {
354 throw std::invalid_argument(
"statcpp::mahalanobis_distance: covariance matrix is singular");
358 double inv_a = d / det;
359 double inv_b = -b / det;
360 double inv_c = -c / det;
361 double inv_d = a / det;
365 double temp0 = inv_a * d0 + inv_b * d1;
366 double temp1 = inv_c * d0 + inv_d * d1;
369 double mahalanobis_sq = d0 * temp0 + d1 * temp1;
371 if (mahalanobis_sq < 0.0) {
373 mahalanobis_sq = 0.0;
376 return std::sqrt(mahalanobis_sq);
400template <
typename Iterator1,
typename Iterator2>
402 Iterator2 first2, Iterator2 last2,
406 throw std::invalid_argument(
"statcpp::minkowski_distance: p must be >= 1");
409 auto n1 = std::distance(first1, last1);
410 auto n2 = std::distance(first2, last2);
413 throw std::invalid_argument(
"statcpp::minkowski_distance: sequences must have the same length");
416 throw std::invalid_argument(
"statcpp::minkowski_distance: empty sequences");
423 while (it1 != last1) {
424 double diff = std::abs(
static_cast<double>(*it1) -
static_cast<double>(*it2));
430 return std::pow(
sum, 1.0 / p);
436template <
typename Iterator1,
typename Iterator2,
typename Proj1,
typename Proj2>
438 Iterator2 first2, Iterator2 last2,
439 double p, Proj1 proj1, Proj2 proj2)
442 throw std::invalid_argument(
"statcpp::minkowski_distance: p must be >= 1");
445 auto n1 = std::distance(first1, last1);
446 auto n2 = std::distance(first2, last2);
449 throw std::invalid_argument(
"statcpp::minkowski_distance: sequences must have the same length");
452 throw std::invalid_argument(
"statcpp::minkowski_distance: empty sequences");
459 while (it1 != last1) {
460 double v1 =
static_cast<double>(proj1(*it1));
461 double v2 =
static_cast<double>(proj2(*it2));
462 double diff = std::abs(v1 - v2);
468 return std::pow(
sum, 1.0 / p);
486template <
typename Iterator1,
typename Iterator2>
488 Iterator2 first2, Iterator2 last2)
490 auto n1 = std::distance(first1, last1);
491 auto n2 = std::distance(first2, last2);
494 throw std::invalid_argument(
"statcpp::chebyshev_distance: sequences must have the same length");
497 throw std::invalid_argument(
"statcpp::chebyshev_distance: empty sequences");
500 double max_diff = 0.0;
504 while (it1 != last1) {
505 double diff = std::abs(
static_cast<double>(*it1) -
static_cast<double>(*it2));
506 if (
diff > max_diff) {
519template <
typename Iterator1,
typename Iterator2,
typename Proj1,
typename Proj2>
521 Iterator2 first2, Iterator2 last2,
522 Proj1 proj1, Proj2 proj2)
524 auto n1 = std::distance(first1, last1);
525 auto n2 = std::distance(first2, last2);
528 throw std::invalid_argument(
"statcpp::chebyshev_distance: sequences must have the same length");
531 throw std::invalid_argument(
"statcpp::chebyshev_distance: empty sequences");
534 double max_diff = 0.0;
538 while (it1 != last1) {
539 double v1 =
static_cast<double>(proj1(*it1));
540 double v2 =
static_cast<double>(proj2(*it2));
541 double diff = std::abs(v1 - v2);
542 if (
diff > max_diff) {
double cosine_distance(Iterator1 first1, Iterator1 last1, Iterator2 first2, Iterator2 last2)
Cosine distance.
double minkowski_distance(Iterator1 first1, Iterator1 last1, Iterator2 first2, Iterator2 last2, double p)
Minkowski distance (generalized Lp distance)
auto sum(Iterator first, Iterator last)
Sum.
double cosine_similarity(Iterator1 first1, Iterator1 last1, Iterator2 first2, Iterator2 last2)
Cosine similarity.
double chebyshev_distance(Iterator1 first1, Iterator1 last1, Iterator2 first2, Iterator2 last2)
Chebyshev distance (L∞ norm, maximum metric)
double mean(Iterator first, Iterator last)
Arithmetic mean.
std::vector< double > diff(Iterator first, Iterator last, std::size_t order=1)
Difference series (first-order or d-th order differencing)
double mahalanobis_distance(const std::vector< double > &x, const std::vector< double > &mean, const std::vector< std::vector< double > > &cov_matrix)
Mahalanobis distance.
double euclidean_distance(const std::vector< double > &a, const std::vector< double > &b)
Euclidean distance.
double manhattan_distance(const std::vector< double > &a, const std::vector< double > &b)
Manhattan distance.