tinyopt 700
Tinyopt, a lightweight, header only optimization library
Loading...
Searching...
No Matches
distances.h
1// Copyright 2026 Julien Michot.
2// SPDX-License-Identifier: Apache-2.0
3
4#pragma once
5
6#include <tinyopt/math.h>
7#include <tinyopt/traits.h>
8
9#include <tinyopt/losses/mahalanobis.h>
10#include <tinyopt/losses/norms.h>
11#include <type_traits>
12
13namespace tinyopt::distances {
14
16template <typename TA, typename TB, typename ExportJ = std::nullptr_t>
17auto Euclidean(const TA &a, const TB &b, const ExportJ &export_jac = nullptr) {
18 if constexpr (traits::is_nullptr_v<ExportJ>) {
19 return losses::L2(a - b);
20 } else if constexpr (traits::is_scalar_v<TA>) {
21 const auto &[d, J] = losses::L2(a - b, export_jac);
22 return std::make_tuple(d, J, -J);
23 } else {
24 const auto &[d, J] = losses::L2(a - b, export_jac);
25 return std::make_tuple(d, J, (-J).eval());
26 }
27}
28
29template <typename TA, typename TB, typename ExportJ = std::nullptr_t>
30auto L2(const TA &a, const TB &b, const ExportJ &export_jac = nullptr) {
31 return Euclidean(a, b, export_jac);
32}
33
35template <typename TA, typename TB, typename ExportJ = std::nullptr_t>
36auto Manhattan(const TA &a, const TB &b, const ExportJ &export_jac = nullptr) {
37 if constexpr (traits::is_nullptr_v<ExportJ>) {
38 return losses::L1(a - b);
39 } else if constexpr (traits::is_scalar_v<TA>) {
40 const auto &[d, J] = losses::L1(a - b, export_jac);
41 return std::make_tuple(d, J, -J);
42 } else {
43 const auto &[d, J] = losses::L1(a - b, export_jac);
44 return std::make_tuple(d, J, (-J).eval());
45 }
46}
47
48template <typename TA, typename TB, typename ExportJ = std::nullptr_t>
49auto L1(const TA &a, const TB &b, const ExportJ &export_jac = nullptr) {
50 return Manhattan(a, b, export_jac);
51}
52
54template <typename TA, typename TB, typename ExportJ = std::nullptr_t>
55auto Linf(const TA &a, const TB &b, const ExportJ &export_jac = nullptr) {
56 if constexpr (traits::is_nullptr_v<ExportJ>) {
57 return losses::Linf(a - b);
58 } else if constexpr (traits::is_scalar_v<TA>) {
59 const auto &[d, J] = losses::Linf(a - b, export_jac);
60 return std::make_tuple(d, J, -J);
61 } else {
62 const auto &[d, J] = losses::Linf(a - b, export_jac);
63 return std::make_tuple(d, J, (-J).eval());
64 }
65}
66
68template <typename TA, typename TB, typename ExportJ = std::nullptr_t>
69auto Cosine(const TA &a, const TB &b, const ExportJ & = nullptr) {
70 if constexpr (traits::is_nullptr_v<ExportJ>) {
71 return TA(0);
72 } else if constexpr (traits::is_scalar_v<TA>) {
73 return std::make_tuple(TA(0), TA(0), TA(0));
74 } else { // Vectors
75 using Scalar = std::decay_t<typename TA::Scalar>;
76 constexpr double eps2 = FloatEpsilon2<Scalar>();
77 constexpr Index Dims = traits::params_trait<TA>::Dims;
78 using Vec = RowVector<Scalar, Dims>;
79 const auto a_norm = a.norm();
80 const auto b_norm = b.norm();
81 if (a_norm * b_norm < eps2) {
82 return std::make_tuple(Scalar(0), Vec::Zero(a.size()), Vec::Zero(a.size()));
83 } else {
84 const auto ab = a.dot(b);
85 const auto d = (ab / (a_norm * b_norm));
86 Vec Ja = (b / (a_norm * b_norm)) - (ab * a / (a_norm * a_norm * a_norm * b_norm));
87 Vec Jb = (a / (a_norm * b_norm)) - (ab * b / (a_norm * b_norm * b_norm));
88 return std::make_tuple(d, Ja, Jb);
89 }
90 }
91}
92
94template <typename TA, typename TB, typename Cov_t, typename ExportJ = std::nullptr_t>
95auto MahaNorm(const TA &a, const TB &b, const Cov_t &cov_or_var,
96 const ExportJ &export_jac = nullptr) {
97 if constexpr (traits::is_nullptr_v<ExportJ>) {
98 return losses::MahaNorm(a - b, cov_or_var);
99 } else if constexpr (traits::is_scalar_v<TA>) {
100 const auto &[d, J] = losses::MahaNorm(a - b, cov_or_var, export_jac);
101 return std::make_tuple(d, J, -J);
102 } else {
103 const auto &[d, J] = losses::MahaNorm(a - b, cov_or_var, export_jac);
104 return std::make_tuple(d, J, (-J).eval());
105 }
106}
107
108} // namespace tinyopt::distances
auto Linf(const T &x)
Return L infinity norm of a vector or scalar.
Definition norms.h:117
auto MahaNorm(const T &x, const Cov_t &cov_or_var, const ExportJ &Jx_or_bool=nullptr)
Compute the Mahalanobis distance of ´x´ with a covariance cov: n(x) = ||x||Σ
Definition mahalanobis.h:87
auto L2(const T &x)
Return L2 norm of a vector or scalar.
Definition norms.h:52
auto L1(const T &x)
Return L1 norm of a vector or scalar.
Definition norms.h:84