18#ifndef itkSymmetricEigenAnalysis_h
19#define itkSymmetricEigenAnalysis_h
23#include ITK_EIGEN(Eigenvalues)
27#include "vnl/vnl_matrix.h"
28#include "vnl/vnl_matrix_fixed.h"
36template <
typename TValueType,
unsigned int VRows,
unsigned int VColumns>
40 return inputMatrix.data_block();
42template <
typename TValueType>
46 return inputMatrix.data_block();
49template <
typename TValueType,
unsigned int VRows,
unsigned int VColumns>
71template <
typename TArray>
75 std::vector<int> indicesSortPermutations(numberOfElements, 0);
76 std::iota(std::begin(indicesSortPermutations), std::end(indicesSortPermutations), 0);
78 std::sort(std::begin(indicesSortPermutations),
79 std::end(indicesSortPermutations),
80 [&eigenValues](
unsigned int a,
unsigned int b) {
83 auto tmpCopy = eigenValues;
84 for (
unsigned int i = 0; i < numberOfElements; ++i)
86 eigenValues[i] = tmpCopy[indicesSortPermutations[i]];
88 return indicesSortPermutations;
99template <
typename QMatrix>
103 using EigenLibPermutationMatrix = Eigen::PermutationMatrix<Eigen::Dynamic, Eigen::Dynamic>;
104 auto numberOfElements = indicesSortPermutations.size();
107 EigenLibPermutationMatrix perm(numberOfElements);
109 std::copy(indicesSortPermutations.begin(), indicesSortPermutations.end(), perm.indices().data());
111 eigenVectors = (eigenVectors * perm).eval();
138extern ITKCommon_EXPORT std::ostream &
149 return EigenValueOrderEnum::OrderByValue;
151 return EigenValueOrderEnum::OrderByMagnitude;
153 return EigenValueOrderEnum::DoNotOrder;
157 itkGenericExceptionMacro(
"Error: Invalid value for conversion.");
160#if !defined(ITK_LEGACY_REMOVE)
163inline constexpr EigenValueOrderEnum OrderByMagnitude = EigenValueOrderEnum::OrderByMagnitude;
206template <
typename TMatrix,
typename TVector,
typename TEigenMatrix = TMatrix>
211#if !defined(ITK_LEGACY_REMOVE)
279 [[nodiscard]]
unsigned int
347 [[nodiscard]]
unsigned int
517 template <
typename QMatrix = TMatrix>
521 return QMatrix::element_type();
523 template <
typename QMatrix = TMatrix>
527 return QMatrix::ValueType();
533 TVector & EigenValues,
534 TEigenMatrix & EigenVectors)
const
545 template <
typename QMatrix>
548 TVector & EigenValues,
549 TEigenMatrix & EigenVectors,
550 long)
const ->
decltype(1U)
553 using EigenLibMatrixType = Eigen::Matrix<ValueType, Eigen::Dynamic, Eigen::Dynamic, Eigen::RowMajor>;
555 for (
unsigned int row = 0; row <
m_Dimension; ++row)
557 for (
unsigned int col = 0; col <
m_Dimension; ++col)
559 inputMatrix(row, col) = A(row, col);
562 using EigenSolverType = Eigen::SelfAdjointEigenSolver<EigenLibMatrixType>;
563 const EigenSolverType solver(inputMatrix);
564 const auto & eigenValues = solver.eigenvalues();
568 const auto & eigenVectors = solver.eigenvectors();
572 auto copyEigenValues = eigenValues;
573 auto copyEigenVectors = eigenVectors;
577 for (
unsigned int row = 0; row <
m_Dimension; ++row)
579 EigenValues[row] = copyEigenValues[row];
580 for (
unsigned int col = 0; col <
m_Dimension; ++col)
582 EigenVectors[row][col] = copyEigenVectors(col, row);
588 for (
unsigned int row = 0; row <
m_Dimension; ++row)
590 EigenValues[row] = eigenValues[row];
591 for (
unsigned int col = 0; col <
m_Dimension; ++col)
593 EigenVectors[row][col] = eigenVectors(col, row);
611 template <
typename QMatrix>
614 TVector & EigenValues,
615 TEigenMatrix & EigenVectors,
616 bool)
const ->
decltype(GetPointerToMatrixData(A), 1U)
618 auto pointerToData = GetPointerToMatrixData(A);
619 using PointerType =
decltype(pointerToData);
620 using ValueTypeCV = std::remove_pointer_t<PointerType>;
621 using ValueType = std::remove_cv_t<ValueTypeCV>;
622 using EigenLibMatrixType = Eigen::Matrix<ValueType, Eigen::Dynamic, Eigen::Dynamic, Eigen::RowMajor>;
623 using EigenConstMatrixMap = Eigen::Map<const EigenLibMatrixType>;
625 using EigenSolverType = Eigen::SelfAdjointEigenSolver<EigenLibMatrixType>;
626 EigenSolverType solver(inputMatrix);
627 const auto & eigenValues = solver.eigenvalues();
631 const auto & eigenVectors = solver.eigenvectors();
634 auto copyEigenValues = eigenValues;
635 auto copyEigenVectors = eigenVectors;
638 for (
unsigned int row = 0; row <
m_Dimension; ++row)
640 EigenValues[row] = copyEigenValues[row];
641 for (
unsigned int col = 0; col <
m_Dimension; ++col)
643 EigenVectors[row][col] = copyEigenVectors(col, row);
649 for (
unsigned int row = 0; row <
m_Dimension; ++row)
651 EigenValues[row] = eigenValues[row];
652 for (
unsigned int col = 0; col <
m_Dimension; ++col)
654 EigenVectors[row][col] = eigenVectors(col, row);
675 template <
typename QMatrix>
680 using EigenLibMatrixType = Eigen::Matrix<ValueType, Eigen::Dynamic, Eigen::Dynamic, Eigen::RowMajor>;
682 for (
unsigned int row = 0; row <
m_Dimension; ++row)
684 for (
unsigned int col = 0; col <
m_Dimension; ++col)
686 inputMatrix(row, col) = A(row, col);
689 using EigenSolverType = Eigen::SelfAdjointEigenSolver<EigenLibMatrixType>;
690 const EigenSolverType solver(inputMatrix, Eigen::EigenvaluesOnly);
691 auto eigenValues = solver.eigenvalues();
698 EigenValues[i] = eigenValues[i];
714 template <
typename QMatrix>
717 ->
decltype(GetPointerToMatrixData(A), 1U)
719 auto pointerToData = GetPointerToMatrixData(A);
720 using PointerType =
decltype(pointerToData);
721 using ValueTypeCV = std::remove_pointer_t<PointerType>;
722 using ValueType = std::remove_cv_t<ValueTypeCV>;
723 using EigenLibMatrixType = Eigen::Matrix<ValueType, Eigen::Dynamic, Eigen::Dynamic, Eigen::RowMajor>;
724 using EigenConstMatrixMap = Eigen::Map<const EigenLibMatrixType>;
726 using EigenSolverType = Eigen::SelfAdjointEigenSolver<EigenLibMatrixType>;
727 EigenSolverType solver(inputMatrix, Eigen::EigenvaluesOnly);
728 auto eigenValues = solver.eigenvalues();
735 EigenValues[i] = eigenValues[i];
742template <
typename TMatrix,
typename TVector,
typename TEigenMatrix>
746 os <<
"[ClassType: SymmetricEigenAnalysis]" << std::endl;
748 os <<
" Order : " << s.
GetOrder() << std::endl;
755template <
unsigned int VDimension,
typename TMatrix,
typename TVector,
typename TEigenMatrix = TMatrix>
759#if !defined(ITK_LEGACY_REMOVE)
763#if !defined(ITK_LEGACY_REMOVE)
767 static constexpr EigenValueOrderEnum OrderByMagnitude = EigenValueOrderEnum::OrderByMagnitude;
854 [[nodiscard]]
constexpr unsigned int
859 [[nodiscard]]
constexpr unsigned int
864 [[nodiscard]]
constexpr bool
881 template <
typename QMatrix = TMatrix>
885 return QMatrix::element_type();
887 template <
typename QMatrix = TMatrix>
891 return QMatrix::ValueType();
903 template <
typename QMatrix>
906 TVector & EigenValues,
907 TEigenMatrix & EigenVectors,
908 bool)
const ->
decltype(GetPointerToMatrixData(A), 1U)
910 auto pointerToData = GetPointerToMatrixData(A);
911 using PointerType =
decltype(pointerToData);
912 using ValueTypeCV = std::remove_pointer_t<PointerType>;
913 using ValueType = std::remove_cv_t<ValueTypeCV>;
914 using EigenLibMatrixType = Eigen::Matrix<ValueType, VDimension, VDimension, Eigen::RowMajor>;
915 using EigenConstMatrixMap = Eigen::Map<const EigenLibMatrixType>;
916 EigenConstMatrixMap inputMatrix(pointerToData);
917 using EigenSolverType = Eigen::SelfAdjointEigenSolver<EigenLibMatrixType>;
918 EigenSolverType solver(inputMatrix);
919 const auto & eigenValues = solver.eigenvalues();
923 const auto & eigenVectors = solver.eigenvectors();
926 auto copyEigenValues = eigenValues;
927 auto copyEigenVectors = eigenVectors;
930 for (
unsigned int row = 0; row < VDimension; ++row)
932 EigenValues[row] = copyEigenValues[row];
933 for (
unsigned int col = 0; col < VDimension; ++col)
935 EigenVectors[row][col] = copyEigenVectors(col, row);
941 for (
unsigned int row = 0; row < VDimension; ++row)
943 EigenValues[row] = eigenValues[row];
944 for (
unsigned int col = 0; col < VDimension; ++col)
946 EigenVectors[row][col] = eigenVectors(col, row);
960 template <
typename QMatrix>
963 TVector & EigenValues,
964 TEigenMatrix & EigenVectors,
965 long)
const ->
decltype(1U)
968 using EigenLibMatrixType = Eigen::Matrix<ValueType, VDimension, VDimension, Eigen::RowMajor>;
969 EigenLibMatrixType inputMatrix;
970 for (
unsigned int row = 0; row < VDimension; ++row)
972 for (
unsigned int col = 0; col < VDimension; ++col)
974 inputMatrix(row, col) = A(row, col);
977 using EigenSolverType = Eigen::SelfAdjointEigenSolver<EigenLibMatrixType>;
978 const EigenSolverType solver(inputMatrix);
979 const auto & eigenValues = solver.eigenvalues();
983 const auto & eigenVectors = solver.eigenvectors();
987 auto copyEigenValues = eigenValues;
988 auto copyEigenVectors = eigenVectors;
992 for (
unsigned int row = 0; row < VDimension; ++row)
994 EigenValues[row] = copyEigenValues[row];
995 for (
unsigned int col = 0; col < VDimension; ++col)
997 EigenVectors[row][col] = copyEigenVectors(col, row);
1003 for (
unsigned int row = 0; row < VDimension; ++row)
1005 EigenValues[row] = eigenValues[row];
1006 for (
unsigned int col = 0; col < VDimension; ++col)
1008 EigenVectors[row][col] = eigenVectors(col, row);
1022 template <
typename QMatrix>
1027 using EigenLibMatrixType = Eigen::Matrix<ValueType, VDimension, VDimension, Eigen::RowMajor>;
1028 EigenLibMatrixType inputMatrix;
1029 for (
unsigned int row = 0; row < VDimension; ++row)
1031 for (
unsigned int col = 0; col < VDimension; ++col)
1033 inputMatrix(row, col) = A(row, col);
1036 using EigenSolverType = Eigen::SelfAdjointEigenSolver<EigenLibMatrixType>;
1042 ITK_GCC_SUPPRESS_Wmaybe_uninitialized
1043 const EigenSolverType solver(inputMatrix, Eigen::EigenvaluesOnly);
1044 auto eigenValues = solver.eigenvalues();
1051 for (
unsigned int i = 0; i < VDimension; ++i)
1053 EigenValues[i] = eigenValues[i];
1069 template <
typename QMatrix>
1072 ->
decltype(GetPointerToMatrixData(A), 1U)
1074 auto pointerToData = GetPointerToMatrixData(A);
1075 using PointerType =
decltype(pointerToData);
1076 using ValueTypeCV = std::remove_pointer_t<PointerType>;
1077 using ValueType = std::remove_cv_t<ValueTypeCV>;
1078 using EigenLibMatrixType = Eigen::Matrix<ValueType, VDimension, VDimension, Eigen::RowMajor>;
1079 using EigenConstMatrixMap = Eigen::Map<const EigenLibMatrixType>;
1080 EigenConstMatrixMap inputMatrix(pointerToData);
1081 using EigenSolverType = Eigen::SelfAdjointEigenSolver<EigenLibMatrixType>;
1082 EigenSolverType solver(inputMatrix, Eigen::EigenvaluesOnly);
1083 auto eigenValues = solver.eigenvalues();
1088 for (
unsigned int i = 0; i < VDimension; ++i)
1090 EigenValues[i] = eigenValues[i];
1097template <
unsigned int VDimension,
typename TMatrix,
typename TVector,
typename TEigenMatrix>
1102 os <<
"[ClassType: SymmetricEigenAnalysisFixedDimension]" << std::endl;
1103 os <<
" Dimension : " << s.
GetDimension() << std::endl;
1104 os <<
" Order : " << s.
GetOrder() << std::endl;
1112#ifndef ITK_MANUAL_INSTANTIATION
1113# include "itkSymmetricEigenAnalysis.hxx"
A templated class holding a M x N size Matrix.
InternalMatrixType & GetVnlMatrix()
This class contains all enum classes used by SymmetricEigenAnalysis class.
auto GetMatrixValueType(bool) const -> typename QMatrix::element_type
bool GetOrderEigenMagnitudes() const
auto ComputeEigenValuesWithEigenLibraryImpl(const QMatrix &A, EigenValuesArrayType &EigenValues, long) const -> decltype(1U)
unsigned int ComputeEigenValuesAndVectors(const TMatrix &A, TVector &EigenValues, TEigenMatrix &EigenVectors) const
EigenValueOrderEnum m_OrderEigenValues
constexpr bool GetUseEigenLibrary() const
auto ComputeEigenValuesWithEigenLibraryImpl(const QMatrix &A, TVector &EigenValues, bool) const -> decltype(GetPointerToMatrixData(A), 1U)
constexpr unsigned int GetOrder() const
void SetOrderEigenValues(const bool b)
auto ComputeEigenValuesAndVectorsWithEigenLibraryImpl(const QMatrix &A, EigenValuesArrayType &EigenValues, EigenVectorsMatrixType &EigenVectors, bool) const -> decltype(GetPointerToMatrixData(A), 1U)
unsigned int ComputeEigenValues(const TMatrix &A, TVector &EigenValues) const
bool GetOrderEigenValues() const
constexpr unsigned int GetDimension() const
void SetOrderEigenMagnitudes(const bool b)
TEigenMatrix EigenMatrixType
auto GetMatrixValueType(bool) const -> typename QMatrix::ValueType
auto ComputeEigenValuesAndVectorsWithEigenLibraryImpl(const QMatrix &A, TVector &EigenValues, TEigenMatrix &EigenVectors, long) const -> decltype(1U)
Find Eigen values of a real 2D symmetric matrix. It serves as a thread-safe alternative to the class:...
void SetOrderEigenMagnitudes(const bool b)
bool GetOrderEigenValues() const
void SetUseEigenLibraryOn()
void SetDimension(const unsigned int n)
unsigned int ComputeEigenValuesAndVectors(const TMatrix &A, TVector &EigenValues, TEigenMatrix &EigenVectors) const
itk::EigenValueOrderEnum EigenValueOrderEnum
unsigned int GetDimension() const
unsigned int ComputeEigenValuesLegacy(const TMatrix &A, TVector &D) const
unsigned int ComputeEigenValuesAndVectorsWithEigenLibrary(const TMatrix &A, TVector &EigenValues, TEigenMatrix &EigenVectors) const
unsigned int ComputeEigenValuesWithEigenLibrary(const TMatrix &A, TVector &EigenValues) const
unsigned int GetOrder() const
bool GetUseEigenLibrary() const
unsigned int ComputeEigenValuesAndVectorsUsingQL(double *d, double *e, double *z) const
auto ComputeEigenValuesWithEigenLibraryImpl(const QMatrix &A, TVector &EigenValues, bool) const -> decltype(GetPointerToMatrixData(A), 1U)
EigenValueOrderEnum m_OrderEigenValues
unsigned int ComputeEigenValuesAndVectorsLegacy(const TMatrix &A, TVector &EigenValues, TEigenMatrix &EigenVectors) const
auto GetMatrixValueType(...) const -> typename QMatrix::ValueType
SymmetricEigenAnalysis(const unsigned int dimension)
bool GetOrderEigenMagnitudes() const
void SetOrder(const unsigned int n)
void SetOrderEigenValues(const bool b)
auto ComputeEigenValuesAndVectorsWithEigenLibraryImpl(const QMatrix &A, TVector &EigenValues, TEigenMatrix &EigenVectors, bool) const -> decltype(GetPointerToMatrixData(A), 1U)
void SetUseEigenLibrary(const bool input)
unsigned int ComputeEigenValuesUsingQL(double *d, double *e) const
SymmetricEigenAnalysis()=default
void ReduceToTridiagonalMatrixAndGetTransformation(const double *a, double *d, double *e, double *z) const
unsigned int ComputeEigenValues(const TMatrix &A, TVector &D) const
auto ComputeEigenValuesAndVectorsWithEigenLibraryImpl(const QMatrix &A, TOutput &EigenValues, TInput &EigenVectors, long) const -> decltype(1U)
auto ComputeEigenValuesWithEigenLibraryImpl(const QMatrix &A, TOutput &EigenValues, long) const -> decltype(1U)
void ReduceToTridiagonalMatrix(double *a, double *d, double *e, double *e2) const
~SymmetricEigenAnalysis()=default
TEigenMatrix EigenMatrixType
auto GetMatrixValueType(bool) const -> typename QMatrix::element_type
void SetUseEigenLibraryOff()
constexpr auto Absolute(T x) noexcept
Returns the absolute value of a number.
const TValueType * GetPointerToMatrixData(const vnl_matrix_fixed< TValueType, VRows, VColumns > &inputMatrix)
void permuteColumnsWithSortIndices(QMatrix &eigenVectors, const std::vector< int > &indicesSortPermutations)
std::vector< int > sortEigenValuesByMagnitude(TArray &eigenValues, const unsigned int numberOfElements)
The "itk" namespace contains all Insight Segmentation and Registration Toolkit (ITK) classes....
ITKCommon_EXPORT std::ostream & operator<<(std::ostream &out, AnatomicalOrientation::CoordinateEnum value)
SymmetricEigenAnalysisEnums::EigenValueOrder EigenValueOrderEnum
EigenValueOrderEnum Int2EigenValueOrderEnum(const uint8_t value)