26#include "vnl/vnl_matrix.h"
27#include "vnl/vnl_matrix_fixed.h"
28#include "vnl/vnl_vector.h"
29#include "vnl/vnl_vector_fixed.h"
32#include ITK_EIGEN(Dense)
49#define ITK_MATH_HAS_SOLVE_SYMMETRIC 1
61template <
typename TReal>
65 using ColMajor = Eigen::Matrix<TReal, Eigen::Dynamic, Eigen::Dynamic>;
66 using Vector = Eigen::Matrix<TReal, Eigen::Dynamic, 1>;
68 const Eigen::Map<const ColMajor> aMap(aData, n, n);
69 const Eigen::Map<const Vector> bMap(bData, n);
71 const Eigen::LDLT<ColMajor> ldlt(aMap);
72 if (ldlt.info() != Eigen::Success)
74 itkGenericExceptionMacro(
"itk::Math::SolveSymmetric failed; input is likely non-finite (NaN/Inf).");
76 Eigen::Map<Vector>(xData, n) = ldlt.solve(bMap);
83template <
typename TReal>
87 using ColMajor = Eigen::Matrix<TReal, Eigen::Dynamic, Eigen::Dynamic>;
88 using RowMajor = Eigen::Matrix<TReal, Eigen::Dynamic, Eigen::Dynamic, Eigen::RowMajor>;
90 const Eigen::Map<const ColMajor> aMap(aData, n, n);
91 const Eigen::Map<const RowMajor> bMap(bData, n, m);
93 const Eigen::LDLT<ColMajor> ldlt(aMap);
94 if (ldlt.info() != Eigen::Success)
96 itkGenericExceptionMacro(
"itk::Math::SolveSymmetric failed; input is likely non-finite (NaN/Inf).");
98 Eigen::Map<RowMajor>(xData, n, m) = ldlt.solve(bMap);
103template <
typename TReal>
107 using ColMajor = Eigen::Matrix<TReal, Eigen::Dynamic, Eigen::Dynamic>;
108 using RowMajor = Eigen::Matrix<TReal, Eigen::Dynamic, Eigen::Dynamic, Eigen::RowMajor>;
110 const Eigen::Map<const ColMajor> aMap(aData, n, n);
112 const Eigen::LDLT<ColMajor> ldlt(aMap);
113 if (ldlt.info() != Eigen::Success)
115 itkGenericExceptionMacro(
"itk::Math::InverseSymmetric failed; input is likely non-finite (NaN/Inf).");
117 const auto dAbs = ldlt.vectorD().cwiseAbs().eval();
118 const TReal dMax = dAbs.maxCoeff();
119 if (dMax == TReal{ 0 } || dAbs.minCoeff() <= dMax *
static_cast<TReal
>(n) * std::numeric_limits<TReal>::epsilon())
121 itkGenericExceptionMacro(
"itk::Math::InverseSymmetric failed; input matrix is singular.");
123 Eigen::Map<RowMajor>(invData, n, n) = ldlt.solve(ColMajor::Identity(n, n));
144template <
typename TReal>
148 const unsigned int n = A.rows();
149 if (n == 0 || A.cols() != n || b.size() != n)
151 itkGenericExceptionMacro(
"itk::Math::SolveSymmetric requires a non-empty square A and a matching b.");
159template <
typename TReal,
unsigned int VDim>
175template <
typename TReal>
179 const unsigned int n = A.rows();
180 if (n == 0 || A.cols() != n || b.size() != n)
182 itkGenericExceptionMacro(
"itk::Math::SolveSymmetric requires a non-empty square A and a matching b.");
184 vnl_vector<TReal> x(n);
190template <
typename TReal,
unsigned int VDim>
191vnl_vector_fixed<TReal, VDim>
192SolveSymmetric(
const vnl_matrix_fixed<TReal, VDim, VDim> & A,
const vnl_vector_fixed<TReal, VDim> & b)
194 vnl_vector_fixed<TReal, VDim> x;
204template <
typename TReal>
208 const unsigned int n = A.rows();
209 if (n == 0 || A.cols() != n || B.rows() != n)
211 itkGenericExceptionMacro(
"itk::Math::SolveSymmetric requires a non-empty square A and a matching B.");
227template <
typename TReal>
231 const unsigned int n = A.rows();
232 if (n == 0 || A.cols() != n)
234 itkGenericExceptionMacro(
"itk::Math::InverseSymmetric requires a non-empty square A.");
242template <
typename TReal>
246 const unsigned int n = A.rows();
247 if (n == 0 || A.cols() != n || B.rows() != n)
249 itkGenericExceptionMacro(
"itk::Math::SolveSymmetric requires a non-empty square A and a matching B.");
251 vnl_matrix<TReal> X(n, B.cols());
257template <
typename TReal>
261 const unsigned int n = A.rows();
262 if (n == 0 || A.cols() != n)
264 itkGenericExceptionMacro(
"itk::Math::InverseSymmetric requires a non-empty square A.");
266 vnl_matrix<TReal> inv(n, n);
Array2D class representing a 2D array.
Array class with size defined at construction time.
ValueType * GetDataPointer()
A templated class holding a M x N size Matrix.
InternalMatrixType & GetVnlMatrix()
A templated class holding a n-Dimensional vector.
Array2D< TReal > InverseSymmetric(const Array2D< TReal > &A)
Inverse of a symmetric matrix, backed by Eigen LDLT.
Array< TReal > SolveSymmetric(const Array2D< TReal > &A, const Array< TReal > &b)
Solve the symmetric linear system A x = b via LDLT, backed by Eigen.
void InverseSymmetricLDLTEigen(const TReal *aData, unsigned int n, TReal *invData)
void SolveSymmetricMatrixLDLTEigen(const TReal *aData, const TReal *bData, unsigned int n, unsigned int m, TReal *xData)
void SolveSymmetricLDLTEigen(const TReal *aData, const TReal *bData, unsigned int n, TReal *xData)
The "itk" namespace contains all Insight Segmentation and Registration Toolkit (ITK) classes....