18auto MahaSquaredNorm(
const T &x,
const Cov_t &cov_or_var,
const ExportJ &Jx_or_bool =
nullptr,
19 bool add_scale =
true) {
20 using Scalar =
typename traits::params_trait<T>::Scalar;
21 constexpr Index Dims = traits::params_trait<T>::Dims;
22 if constexpr (traits::is_scalar_v<T>) {
23 const T s = cov_or_var < FloatEpsilon<T>() ? T(1.0) : T(T(1.0) / cov_or_var);
24 const T n2 = x * x * s;
25 if constexpr (traits::is_bool_v<ExportJ>) {
26 const T J = add_scale ? Scalar(2) * s * x : s * x;
27 return std::make_pair(n2, J);
28 }
else if constexpr (!traits::is_nullptr_v<ExportJ>) {
29 const T J = add_scale ? Scalar(2) * s * x : s * x;
30 return std::make_pair(n2, T(J * Jx_or_bool));
34 }
else if constexpr (traits::is_nullptr_v<ExportJ>) {
35 const auto cov_vars = cov_or_var.template cast<Scalar>().eval();
36 if (x.cols() != 1)
throw std::invalid_argument(
"'x' must be a vector");
37 Scalar n2 = Scalar(0.0);
39 assert(x.size() == cov_vars.size());
40 n2 = x.dot(cov_vars.cwiseInverse().asDiagonal() * x);
42 if (cov_vars.cols() > 1) {
43 const auto I = InvCov(cov_vars);
45 throw std::invalid_argument(
"Covariance is not invertible, make sure it is");
46 n2 = x.dot(I.value() * x);
49 assert(x.size() == cov_vars.size());
50 n2 = x.dot(cov_vars.cwiseInverse().asDiagonal() * x);
55 if (x.cols() != 1)
throw std::invalid_argument(
"'x' must be a vector");
56 const auto cov_vars = cov_or_var.template cast<Scalar>().eval();
57 Scalar n2 = Scalar(0.0);
58 Vector<Scalar, Dims> Jt(x.size());
61 assert(x.size() == cov_vars.size());
62 Jt = cov_vars.cwiseInverse().asDiagonal() * x;
65 if (cov_vars.cols() > 1) {
66 const auto I = InvCov(cov_vars);
68 throw std::invalid_argument(
"Covariance is not invertible, make sure it is");
73 Jt = cov_vars.cwiseInverse().asDiagonal() * x;
77 if (add_scale) Jt *= Scalar(2);
78 if constexpr (traits::is_bool_v<ExportJ>)
79 return std::make_pair(n2, Jt.transpose().eval());
81 return std::make_pair(n2, (Jt.transpose() * Jx_or_bool).eval());
87auto MahaNorm(
const T &x,
const Cov_t &cov_or_var,
const ExportJ &Jx_or_bool =
nullptr) {
88 using Scalar =
typename traits::params_trait<T>::Scalar;
90 constexpr bool add_scale =
false;
91 if constexpr (traits::is_nullptr_v<ExportJ>) {
94 }
else if constexpr (traits::is_scalar_v<T>) {
96 const auto &[n2, J] =
MahaSquaredNorm(x, cov_or_var, Jx_or_bool, add_scale);
97 const auto n = sqrt(n2);
98 const auto s = n > FloatEpsilon<Scalar>() ? n : Scalar(1);
99 return std::make_pair(n, J / s);
101 const auto &[n2, J] =
MahaSquaredNorm(x, cov_or_var, Jx_or_bool, add_scale);
102 const auto n = sqrt(n2);
103 const auto s = n > FloatEpsilon<Scalar>() ? n : Scalar(1);
104 return std::make_pair(n, (J / s).eval());
111auto MahaWhitened(
const MatrixBase<Derived> &res,
const Cov_t &cov_stevs,
112 const ExportJ &Jx_or_bool =
nullptr) {
113 using Scalar =
typename Derived::Scalar;
114 if constexpr (traits::is_scalar_v<Cov_t>) {
115 const auto res2 = (res / cov_stevs).eval();
117 if constexpr (traits::is_nullptr_v<ExportJ>)
119 else if constexpr (traits::is_bool_v<ExportJ>)
120 return std::make_pair(res2, 1.0 / cov_stevs);
122 return std::make_pair(res2, (Jx_or_bool / cov_stevs).eval());
126 assert(res.size() == cov_stevs.size());
127 const auto res2 = (res.array() / cov_stevs.array()).matrix().eval();
128 using Mat = Matrix<Scalar, Derived::RowsAtCompileTime, Derived::RowsAtCompileTime>;
131 if constexpr (traits::is_nullptr_v<ExportJ>)
133 else if constexpr (traits::is_bool_v<ExportJ>)
134 return std::make_pair(res2, Mat(cov_stevs.cwiseInverse().asDiagonal()));
136 return std::make_pair(res2, (cov_stevs.cwiseInverse().asDiagonal() * Jx_or_bool).eval());
139 const auto cov = cov_stevs.template cast<Scalar>().eval();
141 static constexpr Index Dims = Derived::RowsAtCompileTime;
142 using Mat = Matrix<Scalar, Dims, Dims>;
143 const auto chol = Eigen::SelfAdjointView<const Mat, Upper>(cov).llt();
144 const auto res2 = chol.matrixL().solve(res).eval();
147 if constexpr (traits::is_nullptr_v<ExportJ>)
149 else if constexpr (traits::is_bool_v<ExportJ>)
150 return std::make_pair(res2, (chol.matrixL().solve(Mat::Identity())).eval());
152 return std::make_pair(res2, (chol.matrixL().solve(Jx_or_bool)).eval());
162 const ExportJ &Jx_or_bool =
nullptr) {
163 auto UU = U.template triangularView<Upper>();
164 const auto res2 = (UU * res).eval();
166 if constexpr (traits::is_nullptr_v<ExportJ>)
168 else if constexpr (traits::is_bool_v<ExportJ>)
169 return std::make_pair(res2, U.eval());
171 return std::make_pair(res2, (UU * Jx_or_bool).eval());
auto MahaWhitened(const MatrixBase< Derived > &res, const Cov_t &cov_stevs, const ExportJ &Jx_or_bool=nullptr)
Definition mahalanobis.h:111
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 MahaWhitenedInfoU(const MatrixBase< Derived > &res, const MatrixBase< DerivedC > &U, const ExportJ &Jx_or_bool=nullptr)
Definition mahalanobis.h:161
auto MahaSquaredNorm(const T &x, const Cov_t &cov_or_var, const ExportJ &Jx_or_bool=nullptr, bool add_scale=true)
Compute the Squared Mahalanobis distance of ´x´ with a covariance cov: n(x) = ||x||Σ²
Definition mahalanobis.h:18