6#include <tinyopt/math.h>
7#include <tinyopt/traits.h>
9#include <tinyopt/losses/mahalanobis.h>
10#include <tinyopt/losses/norms.h>
13namespace tinyopt::distances {
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>) {
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);
24 const auto &[d, J] =
losses::L2(a - b, export_jac);
25 return std::make_tuple(d, J, (-J).eval());
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);
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>) {
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);
43 const auto &[d, J] =
losses::L1(a - b, export_jac);
44 return std::make_tuple(d, J, (-J).eval());
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);
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>) {
58 }
else if constexpr (traits::is_scalar_v<TA>) {
60 return std::make_tuple(d, J, -J);
63 return std::make_tuple(d, J, (-J).eval());
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>) {
72 }
else if constexpr (traits::is_scalar_v<TA>) {
73 return std::make_tuple(TA(0), TA(0), TA(0));
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()));
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);
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>) {
99 }
else if constexpr (traits::is_scalar_v<TA>) {
101 return std::make_tuple(d, J, -J);
104 return std::make_tuple(d, J, (-J).eval());
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