9#include <Eigen/SparseCholesky>
10#include <tinyopt/types.h>
14template <
typename Derived>
15std::optional<Matrix<
typename Derived::Scalar, Derived::RowsAtCompileTime,
16 Derived::ColsAtCompileTime>>
17DenseInvCov(
const MatrixBase<Derived> &m) {
19 Matrix<typename Derived::Scalar, Derived::RowsAtCompileTime, Derived::ColsAtCompileTime>;
20 if constexpr (Derived::ColsAtCompileTime == 1) {
21 return MatType(m.cwiseInverse().asDiagonal());
22 }
else if (m.cols() == 1) {
23 return MatType(m.inverse());
24 }
else if (m.cols() > 0) {
25 const auto &chol = m.template selfadjointView<Upper>().ldlt();
26 if (chol.info() == Eigen::Success && chol.isPositive())
27 return chol.solve(MatType::Identity(m.rows(), m.cols()));
32template <
typename Derived>
33auto InvCov(
const MatrixBase<Derived> &m) {
34 return DenseInvCov(m);
38std::optional<SparseMatrix<typename T::Scalar>> SparseInvCov(
39 const T &m,
typename T::Scalar retry_with_shift_offset =
typename T::Scalar(0.0)) {
40 using Scalar =
typename T::Scalar;
41 if (m.size() == 0)
return std::nullopt;
42 Eigen::SimplicialLDLT<SparseMatrix<Scalar>, Eigen::Upper> solver;
44 if (solver.info() != Eigen::Success) {
45 if (retry_with_shift_offset > 0 && solver.info() == Eigen::NumericalIssue) {
46 solver.setShift(retry_with_shift_offset);
49 if (solver.info() != Eigen::Success)
return std::nullopt;
51 SparseMatrix<Scalar> identity(m.rows(), m.cols());
52 identity.setIdentity();
53 auto inverse = solver.solve(identity);
54 if (solver.info() != Eigen::Success)
return std::nullopt;
58template <
typename Scalar>
59std::optional<SparseMatrix<Scalar>> InvCov(
60 const SparseMatrix<Scalar> &m, Scalar retry_with_shift_offset = Scalar(0.0)) {
61 return SparseInvCov(m, retry_with_shift_offset);
64template <
typename XprType,
int BlockRows,
int BlockCols,
bool InnerPanel>
65auto InvCov(
const Block<XprType, BlockRows, BlockCols, InnerPanel> &m) {
66 using Scalar =
typename XprType::Scalar;
67 if constexpr (std::is_same_v<std::decay_t<XprType>, SparseMatrix<Scalar>>)
68 return SparseInvCov(m);
70 return DenseInvCov(m);