12#ifndef EIGEN_SELFADJOINTEIGENSOLVER_H
13#define EIGEN_SELFADJOINTEIGENSOLVER_H
15#include "./Tridiagonalization.h"
18#include "./InternalHeaderCheck.h"
22template <
typename MatrixType_>
26template <
typename SolverType,
int Size,
bool IsComplex,
bool IsDirect = !IsComplex && (Size == 2 || Size == 3)>
27struct direct_selfadjoint_eigenvalues;
29template <
bool PerBlockScaling,
typename MatrixType,
typename DiagType,
typename SubDiagType>
30EIGEN_DEVICE_FUNC
ComputationInfo computeFromTridiagonal_impl(DiagType& diag, SubDiagType& subdiag,
31 const Index maxIterations,
bool computeEigenvectors,
82template <
typename MatrixType_>
85 using MatrixType = MatrixType_;
87 Size = MatrixType::RowsAtCompileTime,
88 ColsAtCompileTime = MatrixType::ColsAtCompileTime,
89 Options = internal::plain_object_options<MatrixType>::value,
90 MaxColsAtCompileTime = MatrixType::MaxColsAtCompileTime
94 using Scalar =
typename MatrixType::Scalar;
107 std::conditional_t<internal::is_ref<MatrixType>::value, MatrixType,
125 using
VectorType = typename internal::plain_col_type<MatrixType, Scalar>::type;
126 using RealVectorType = typename internal::plain_col_type<MatrixType, RealScalar>::type;
128 using SubDiagonalType = typename TridiagonalizationType::SubDiagonalType;
146 m_info(InvalidInput),
147 m_isInitialized(false),
148 m_eigenvectorsOk(false) {}
163 : m_eivec(size, size),
166 m_subdiag(size > 1 ? size - 1 : 1),
167 m_hcoeffs(size > 1 ? size - 1 : 1),
168 m_isInitialized(false),
169 m_eigenvectorsOk(false) {}
186 template <
typename InputType>
189 : m_eivec(matrix.rows(), matrix.cols()),
190 m_workspace(matrix.cols()),
191 m_eivalues(matrix.cols()),
192 m_subdiag(matrix.rows() > 1 ? matrix.rows() - 1 : 1),
193 m_hcoeffs(matrix.cols() > 1 ? matrix.cols() - 1 : 1),
194 m_isInitialized(false),
195 m_eigenvectorsOk(false) {
210 template <typename InputType, bool IsRef = internal::is_ref<MatrixType>::value, std::enable_if_t<IsRef, int> = 0>
213 m_eivec.template triangularView<StrictlyUpper>().setZero();
214 computeInPlace(options);
247 template <
typename InputType>
318 eigen_assert(m_isInitialized &&
"SelfAdjointEigenSolver is not initialized.");
319 eigen_assert(m_eigenvectorsOk &&
"The eigenvectors have not been computed together with the eigenvalues.");
339 eigen_assert(m_isInitialized &&
"SelfAdjointEigenSolver is not initialized.");
361 eigen_assert(m_isInitialized &&
"SelfAdjointEigenSolver is not initialized.");
362 eigen_assert(m_eigenvectorsOk &&
"The eigenvectors have not been computed together with the eigenvalues.");
363 return m_eivec * m_eivalues.cwiseSqrt().asDiagonal() * m_eivec.adjoint();
377 eigen_assert(m_isInitialized &&
"SelfAdjointEigenSolver is not initialized.");
378 eigen_assert(m_eigenvectorsOk &&
"The eigenvectors have not been computed together with the eigenvalues.");
379 return m_eivec * m_eivalues.array().exp().matrix().asDiagonal() * m_eivec.adjoint();
401 eigen_assert(m_isInitialized &&
"SelfAdjointEigenSolver is not initialized.");
402 eigen_assert(m_eigenvectorsOk &&
"The eigenvectors have not been computed together with the eigenvalues.");
403 return m_eivec * m_eivalues.cwiseInverse().cwiseSqrt().asDiagonal() * m_eivec.adjoint();
411 eigen_assert(m_isInitialized &&
"SelfAdjointEigenSolver is not initialized.");
423 EIGEN_STATIC_ASSERT_NON_INTEGER(
Scalar)
426 struct BindStorageTag {};
430 template <
typename InputType>
432 : m_eivec(matrix.derived()),
433 m_workspace(matrix.cols()),
434 m_eivalues(matrix.cols()),
435 m_subdiag(matrix.rows() > 1 ? matrix.rows() - 1 : 1),
436 m_hcoeffs(matrix.cols() > 1 ? matrix.cols() - 1 : 1),
437 m_isInitialized(false),
438 m_eigenvectorsOk(false) {}
446 RealVectorType m_eivalues;
447 typename TridiagonalizationType::SubDiagonalType m_subdiag;
448 typename TridiagonalizationType::CoeffVectorType m_hcoeffs;
449 ComputationInfo m_info;
450 bool m_isInitialized;
451 bool m_eigenvectorsOk;
473template <
typename RealScalar,
typename Index,
typename MatrixQType>
474EIGEN_DEVICE_FUNC
static void tridiagonal_qr_step(RealScalar* diag, RealScalar* subdiag, Index start, Index end,
475 MatrixQType* matrixQ);
478template <
typename MatrixType>
479template <
typename InputType>
482 const InputType& matrix(a_matrix.derived());
483 eigen_assert(matrix.cols() == matrix.rows());
484 m_eivec = matrix.template triangularView<Lower>();
485 return computeInPlace(options);
488template <
typename MatrixType>
490 eigen_assert(m_eivec.cols() == m_eivec.rows());
491 eigen_assert((options & ~(EigVecMask | GenEigMask)) == 0 && (options & EigVecMask) != EigVecMask &&
492 "invalid option parameter");
494 Index n = m_eivec.cols();
495 m_eivalues.resize(n, 1);
498 if (n == 1) m_eivalues.coeffRef(0, 0) = numext::real(m_eivec.coeff(0, 0));
499 if (computeEigenvectors) m_eivec.setOnes();
501 m_isInitialized =
true;
502 m_eigenvectorsOk = computeEigenvectors;
507 RealVectorType& diag = m_eivalues;
508 EigenvectorsType& mat = m_eivec;
515 const RealScalar maxCoeff = internal::safe_scaling<RealScalar>::recover_flushed_max_coeff(
516 mat, mat.cwiseAbs().template maxCoeff<PropagateNaN>());
517 if (!(numext::isfinite)(maxCoeff)) {
520 m_isInitialized =
true;
521 m_eigenvectorsOk =
false;
524 const auto factors = internal::safe_scaling<RealScalar>::with_scaled(mat, maxCoeff, [&](
const auto& scaled) {
525 mat.template triangularView<Lower>() = scaled.template triangularView<Lower>();
527 m_subdiag.resize(n - 1);
528 m_hcoeffs.resize(n - 1);
529 internal::tridiagonalization_inplace(mat, diag, m_subdiag, m_hcoeffs, m_workspace, computeEigenvectors);
531 m_info = internal::computeFromTridiagonal_impl<false>(diag, m_subdiag, m_maxIterations, computeEigenvectors, m_eivec);
534 internal::safe_scaling<RealScalar>::unscale_in_place(m_eivalues, maxCoeff, factors);
536 m_isInitialized =
true;
537 m_eigenvectorsOk = computeEigenvectors;
541template <
typename MatrixType>
543 const RealVectorType& diag,
const SubDiagonalType& subdiag,
int options) {
552 if (m_eivalues.size() > 0) scale = m_eivalues.cwiseAbs().maxCoeff();
553 if (m_subdiag.size() > 0) scale = numext::maxi(scale, m_subdiag.cwiseAbs().maxCoeff());
554 if (!(numext::isfinite)(scale)) {
556 m_isInitialized =
true;
557 m_eigenvectorsOk =
false;
562 if (computeEigenvectors) {
563 m_eivec.setIdentity(diag.size(), diag.size());
568 internal::computeFromTridiagonal_impl<true>(m_eivalues, m_subdiag,
m_maxIterations, computeEigenvectors, m_eivec);
570 m_isInitialized =
true;
571 m_eigenvectorsOk = computeEigenvectors;
591template <
bool PerBlockScaling,
typename MatrixType,
typename DiagType,
typename SubDiagType>
592EIGEN_DEVICE_FUNC
ComputationInfo computeFromTridiagonal_impl(DiagType& diag, SubDiagType& subdiag,
593 const Index maxIterations,
bool computeEigenvectors,
597 Index n = diag.size();
602 using RealScalar =
typename DiagType::RealScalar;
603 const RealScalar considerAsZero = (std::numeric_limits<RealScalar>::min)();
604 const RealScalar precision = NumTraits<RealScalar>::epsilon();
605 const RealScalar precision_inv = RealScalar(1) / precision;
608 auto deflate = [&](Index lo, Index hi) {
609 for (Index i = lo; i < hi; ++i) {
610 const RealScalar absSubdiag = numext::abs(subdiag[i]);
611 if (absSubdiag < considerAsZero) {
612 subdiag[i] = RealScalar(0);
613 }
else if (!PerBlockScaling) {
616 if (absSubdiag <= precision * numext::maxi(numext::abs(diag[i]), numext::abs(diag[i + 1]))) {
617 subdiag[i] = RealScalar(0);
620 const RealScalar scaled_subdiag = precision_inv * subdiag[i];
621 if (scaled_subdiag * scaled_subdiag <= (numext::abs(diag[i]) + numext::abs(diag[i + 1]))) {
622 subdiag[i] = RealScalar(0);
632 Index scaled_start = -1, scaled_end = -1;
633 RealScalar block_norm = RealScalar(0);
634 safe_scaling_factors<RealScalar> blockFactors;
635 const auto restore_block = [&]() {
636 if (scaled_start < 0)
return;
637 auto diagonal = diag.segment(scaled_start, scaled_end - scaled_start + 1);
638 auto offDiagonal = subdiag.segment(scaled_start, scaled_end - scaled_start);
639 safe_scaling<RealScalar>::unscale_in_place(diagonal, block_norm, blockFactors);
640 safe_scaling<RealScalar>::unscale_in_place(offDiagonal, block_norm, blockFactors);
647 while (end > 0 && numext::is_exactly_zero(subdiag[end - 1])) {
654 if (iter > maxIterations * n)
break;
657 while (start > 0 && !numext::is_exactly_zero(subdiag[start - 1])) start--;
659 if (PerBlockScaling) {
661 if (start != scaled_start || end != scaled_end) {
664 block_norm = RealScalar(0);
665 for (Index i = start; i <= end; ++i) block_norm = numext::maxi(block_norm, numext::abs(diag[i]));
666 for (Index i = start; i < end; ++i) block_norm = numext::maxi(block_norm, numext::abs(subdiag[i]));
667 auto diagonal = diag.segment(start, end - start + 1);
668 auto offDiagonal = subdiag.segment(start, end - start);
669 blockFactors = safe_scaling<RealScalar>::scale_to(diagonal, diagonal, block_norm);
670 safe_scaling<RealScalar>::scale_to(offDiagonal, offDiagonal, block_norm, blockFactors);
671 scaled_start = start;
676 internal::tridiagonal_qr_step(diag.data(), subdiag.data(), start, end,
677 computeEigenvectors ? &eivec :
static_cast<MatrixType*
>(
nullptr));
681 if (PerBlockScaling) restore_block();
682 if (iter <= maxIterations * n)
690 for (Index i = 0; i < n - 1; ++i) {
696 RealScalar min_val = diag[i];
697 for (Index j = i + 1; j < n; ++j) {
698 if (diag[j] < min_val) {
704 numext::swap(diag[i], diag[k]);
705 if (computeEigenvectors) eivec.col(i).swap(eivec.col(k));
712template <
typename SolverType,
int Size,
bool IsComplex,
bool IsDirect>
713struct direct_selfadjoint_eigenvalues {
714 EIGEN_DEVICE_FUNC
static inline void run(SolverType& eig,
const typename SolverType::MatrixType& A,
int options) {
715 eig.compute(A, options);
719template <
typename SolverType,
int Size>
720struct direct_selfadjoint_eigensolver_kernel;
722template <
typename SolverType>
723struct direct_selfadjoint_eigensolver_kernel<SolverType, 3> {
724 using MatrixType =
typename SolverType::MatrixType;
725 using VectorType =
typename SolverType::RealVectorType;
726 using Scalar =
typename SolverType::Scalar;
727 using EigenvectorsType =
typename SolverType::EigenvectorsType;
728 using PlainMatrixType =
typename SolverType::PlainMatrixType;
734 EIGEN_DEVICE_FUNC
static inline void computeRoots(
const MatrixType& m, VectorType& roots) {
735 EIGEN_USING_STD(sqrt)
736 EIGEN_USING_STD(atan2)
739 const Scalar s_inv3 = Scalar(1) / Scalar(3);
740 const Scalar s_sqrt3 = sqrt(Scalar(3));
745 Scalar c0 = m(0, 0) * m(1, 1) * m(2, 2) + Scalar(2) * m(1, 0) * m(2, 0) * m(2, 1) - m(0, 0) * m(2, 1) * m(2, 1) -
746 m(1, 1) * m(2, 0) * m(2, 0) - m(2, 2) * m(1, 0) * m(1, 0);
747 Scalar c1 = m(0, 0) * m(1, 1) - m(1, 0) * m(1, 0) + m(0, 0) * m(2, 2) - m(2, 0) * m(2, 0) + m(1, 1) * m(2, 2) -
749 Scalar c2 = m(0, 0) + m(1, 1) + m(2, 2);
753 Scalar c2_over_3 = c2 * s_inv3;
754 Scalar a_over_3 = (c2 * c2_over_3 - c1) * s_inv3;
755 a_over_3 = numext::maxi(a_over_3, Scalar(0));
757 Scalar half_b = Scalar(0.5) * (c0 + c2_over_3 * (Scalar(2) * c2_over_3 * c2_over_3 - c1));
759 Scalar q = a_over_3 * a_over_3 * a_over_3 - half_b * half_b;
760 q = numext::maxi(q, Scalar(0));
763 Scalar rho = sqrt(a_over_3);
764 Scalar theta = atan2(sqrt(q), half_b) * s_inv3;
765 Scalar cos_theta = cos(theta);
766 Scalar sin_theta = sin(theta);
768 roots(0) = c2_over_3 - rho * (cos_theta + s_sqrt3 * sin_theta);
769 roots(1) = c2_over_3 - rho * (cos_theta - s_sqrt3 * sin_theta);
770 roots(2) = c2_over_3 + Scalar(2) * rho * cos_theta;
773 EIGEN_DEVICE_FUNC
static inline bool extract_kernel(PlainMatrixType& mat, Ref<VectorType> res,
774 Ref<VectorType> representative) {
775 EIGEN_USING_STD(abs);
776 EIGEN_USING_STD(sqrt);
779 mat.diagonal().cwiseAbs().maxCoeff(&i0);
782 representative = mat.col(i0);
785 n0 = (c0 = representative.cross(mat.col((i0 + 1) % 3))).squaredNorm();
786 n1 = (c1 = representative.cross(mat.col((i0 + 2) % 3))).squaredNorm();
795 EIGEN_DEVICE_FUNC
static void run(PlainMatrixType& scaledMat, VectorType& eivals, EigenvectorsType& eivecs,
796 bool computeEigenvectors,
const Scalar& maxCoeff) {
798 computeRoots(scaledMat, eivals);
803 if (eivals(0) > eivals(1)) numext::swap(eivals(0), eivals(1));
804 if (eivals(1) > eivals(2)) numext::swap(eivals(1), eivals(2));
805 if (eivals(0) > eivals(1)) numext::swap(eivals(0), eivals(1));
808 if (computeEigenvectors) {
809 if ((eivals(2) - eivals(0)) <= Eigen::NumTraits<Scalar>::epsilon() * maxCoeff) {
811 eivecs.setIdentity();
817 Scalar d0 = eivals(2) - eivals(1);
818 Scalar d1 = eivals(1) - eivals(0);
827 tmp.diagonal().array() -= eivals(k);
829 extract_kernel(tmp, eivecs.col(k), eivecs.col(l));
833 if (d0 <= 2 * Eigen::NumTraits<Scalar>::epsilon() * d1) {
836 eivecs.col(l) -= eivecs.col(k).dot(eivecs.col(l)) * eivecs.col(k);
837 eivecs.col(l).normalize();
840 tmp.diagonal().array() -= eivals(l);
843 extract_kernel(tmp, eivecs.col(l), dummy);
847 eivecs.col(1) = eivecs.col(2).cross(eivecs.col(0)).normalized();
854template <
typename SolverType>
855struct direct_selfadjoint_eigensolver_kernel<SolverType, 2> {
856 using MatrixType =
typename SolverType::MatrixType;
857 using VectorType =
typename SolverType::RealVectorType;
858 using Scalar =
typename SolverType::Scalar;
859 using EigenvectorsType =
typename SolverType::EigenvectorsType;
860 using PlainMatrixType =
typename SolverType::PlainMatrixType;
862 EIGEN_DEVICE_FUNC
static inline void computeRoots(
const MatrixType& m, VectorType& roots) {
863 EIGEN_USING_STD(sqrt);
864 const Scalar t0 = Scalar(0.5) * sqrt(numext::abs2(m(0, 0) - m(1, 1)) + Scalar(4) * numext::abs2(m(1, 0)));
865 const Scalar t1 = Scalar(0.5) * (m(0, 0) + m(1, 1));
870 EIGEN_DEVICE_FUNC EIGEN_ALWAYS_INLINE
static void run(PlainMatrixType& scaledMat, VectorType& eivals,
871 EigenvectorsType& eivecs,
bool computeEigenvectors,
873 EIGEN_USING_STD(sqrt);
874 EIGEN_USING_STD(abs);
877 computeRoots(scaledMat, eivals);
880 if (computeEigenvectors) {
881 if ((eivals(1) - eivals(0)) <= abs(eivals(1)) * Eigen::NumTraits<Scalar>::epsilon()) {
882 eivecs.setIdentity();
884 scaledMat.diagonal().array() -= eivals(1);
885 Scalar a2 = numext::abs2(scaledMat(0, 0));
886 Scalar c2 = numext::abs2(scaledMat(1, 1));
887 Scalar b2 = numext::abs2(scaledMat(1, 0));
889 eivecs.col(1) << -scaledMat(1, 0), scaledMat(0, 0);
890 eivecs.col(1) /= sqrt(a2 + b2);
892 eivecs.col(1) << -scaledMat(1, 1), scaledMat(1, 0);
893 eivecs.col(1) /= sqrt(c2 + b2);
897 eivecs.col(0) << -eivecs(1, 1), eivecs(0, 1);
903template <
typename SolverType,
int Size>
904struct direct_selfadjoint_eigenvalues<SolverType, Size, false, true> {
905 using MatrixType =
typename SolverType::MatrixType;
906 using PlainMatrixType =
typename SolverType::PlainMatrixType;
907 using Scalar =
typename SolverType::Scalar;
910 using Limit = std::conditional_t<std::is_same<Scalar, long double>::value,
long double,
double>;
912 EIGEN_DEVICE_FUNC
static constexpr Limit power_of_two(
int exponent) {
914 for (; exponent > 0; --exponent) result *= 2;
915 for (; exponent < 0; ++exponent) result /= 2;
919 EIGEN_DEVICE_FUNC
static bool safe_without_scaling(
const Scalar& magnitude, true_type) {
922 constexpr int degree = Size == 3 ? 6 : 2;
923 constexpr int lower = std::numeric_limits<Scalar>::min_exponent - 1 + std::numeric_limits<Scalar>::digits - 1 + 12;
924 constexpr int upper = std::numeric_limits<Scalar>::max_exponent - 1 - 12;
925 constexpr int minExponent = lower >= 0 ? (lower + degree - 1) / degree : lower / degree;
926 constexpr int maxExponent = upper >= 0 ? upper / degree : (upper - degree + 1) / degree;
927 constexpr Limit minimum = power_of_two(minExponent);
928 constexpr Limit maximum = power_of_two(maxExponent);
929 return magnitude >= Scalar(minimum) && magnitude <= Scalar(maximum);
932 EIGEN_DEVICE_FUNC
static bool safe_without_scaling(
const Scalar& magnitude, false_type) {
933 return magnitude >= Scalar(0.25) && magnitude <= Scalar(2) &&
934 NumTraits<Scalar>::epsilon() / Scalar(4096) >= (std::numeric_limits<Scalar>::min)();
937 EIGEN_DEVICE_FUNC EIGEN_DONT_INLINE
static void run_scaled(SolverType& solver,
const MatrixType& mat,
938 const Scalar& shift, Scalar centeredMax,
int options) {
939 PlainMatrixType scaledMat = mat.template selfadjointView<Lower>();
940 scaledMat.diagonal().array() -= shift;
941 centeredMax = safe_scaling<Scalar>::recover_flushed_max_coeff(scaledMat, centeredMax);
942 const auto factors = safe_scaling<Scalar>::scale_to(scaledMat, scaledMat, centeredMax);
943 direct_selfadjoint_eigensolver_kernel<SolverType, Size>::run(scaledMat, solver.m_eivalues, solver.m_eivec,
945 scaledMat.cwiseAbs().maxCoeff());
946 safe_scaling<Scalar>::unscale_in_place(solver.m_eivalues, centeredMax, factors);
949 EIGEN_DEVICE_FUNC EIGEN_ALWAYS_INLINE
static void run_centered(SolverType& solver,
const MatrixType& mat,
952 PlainMatrixType scaledMat = mat.template selfadjointView<Lower>();
953 const Scalar first = scaledMat(0, 0);
954 Scalar shift = first;
955 for (Index i = 1; i < Size; ++i) shift += (scaledMat(i, i) - first) / Scalar(Size);
956 scaledMat.diagonal().array() -= shift;
958 const Scalar centeredMax = scaledMat.cwiseAbs().maxCoeff();
959 if (safe_without_scaling(centeredMax, supports_power_of_two_scaling<Scalar>())) {
960 direct_selfadjoint_eigensolver_kernel<SolverType, Size>::run(scaledMat, solver.m_eivalues, solver.m_eivec,
961 computeEigenvectors, centeredMax);
963 run_scaled(solver, mat, shift, centeredMax, options);
965 solver.m_eivalues.array() += shift;
967 solver.m_isInitialized =
true;
968 solver.m_eigenvectorsOk = computeEigenvectors;
971 EIGEN_DEVICE_FUNC
static void run_large(SolverType& solver, PlainMatrixType& scaledMat,
int options, false_type) {
972 run_centered(solver, scaledMat, options);
975 EIGEN_DEVICE_FUNC
static void run_large(SolverType& solver, PlainMatrixType& scaledMat,
int options, true_type) {
977 solver.compute(scaledMat, options);
980 EIGEN_DEVICE_FUNC EIGEN_DONT_INLINE
static void run_prescaled(SolverType& solver,
const MatrixType& mat,
981 const Scalar& maxCoeff,
int options) {
982 PlainMatrixType scaledMat = mat.template selfadjointView<Lower>();
983 const Scalar recoveredMax = safe_scaling<Scalar>::recover_flushed_max_coeff(scaledMat, maxCoeff);
984 const auto inputFactors = safe_scaling<Scalar>::scale_to(scaledMat, scaledMat, recoveredMax);
985 if (maxCoeff > (NumTraits<Scalar>::highest() * Scalar(0.5)) / Scalar(Size)) {
986 run_large(solver, scaledMat, options,
987 bool_constant<(Size == 3 && supports_power_of_two_scaling<Scalar>::value)>());
989 run_centered(solver, scaledMat, options);
991 safe_scaling<Scalar>::unscale_in_place(solver.m_eivalues, recoveredMax, inputFactors);
994 EIGEN_DEVICE_FUNC EIGEN_ALWAYS_INLINE
static void run(SolverType& solver,
const MatrixType& mat,
int options) {
995 eigen_assert(mat.rows() == Size && mat.cols() == Size);
996 eigen_assert((options & ~(EigVecMask | GenEigMask)) == 0 && (options & EigVecMask) != EigVecMask &&
997 "invalid option parameter");
998 PlainMatrixType scaledMat = mat.template selfadjointView<Lower>();
999 const Scalar maxCoeff = scaledMat.cwiseAbs().maxCoeff();
1003 if (EIGEN_PREDICT_FALSE(maxCoeff < (std::numeric_limits<Scalar>::min)() / NumTraits<Scalar>::epsilon() ||
1004 maxCoeff > (NumTraits<Scalar>::highest() * Scalar(0.5)) / Scalar(Size))) {
1005 run_prescaled(solver, mat, maxCoeff, options);
1007 run_centered(solver, mat, options);
1014template <
typename MatrixType>
1016 const MatrixType& matrix,
int options) {
1017 internal::direct_selfadjoint_eigenvalues<SelfAdjointEigenSolver, Size, NumTraits<Scalar>::IsComplex>::run(
1018 *
this, matrix, options);
1025template <
typename RealScalar,
typename Index,
typename MatrixQType>
1026EIGEN_DEVICE_FUNC
static void tridiagonal_qr_step(RealScalar* diag, RealScalar* subdiag, Index start, Index end,
1027 MatrixQType* matrixQ) {
1029 RealScalar td = (diag[end - 1] - diag[end]) * RealScalar(0.5);
1030 RealScalar e = subdiag[end - 1];
1031 RealScalar mu = diag[end];
1032 if (numext::is_exactly_zero(td)) {
1033 mu -= numext::abs(e);
1034 }
else if (!numext::is_exactly_zero(e)) {
1035 const RealScalar e2 = numext::abs2(e);
1036 if (numext::is_exactly_zero(e2)) {
1041 const RealScalar ratio = td / e;
1042 const RealScalar h = numext::hypot(ratio, RealScalar(1));
1043 mu -= e / (ratio + (ratio > RealScalar(0) ? h : -h));
1045 const RealScalar h = numext::hypot(td, e);
1046 mu -= e2 / (td + (td > RealScalar(0) ? h : -h));
1050 RealScalar x = diag[start] - mu;
1051 RealScalar z = subdiag[start];
1054 for (Index k = start; k < end && !numext::is_exactly_zero(z); ++k) {
1055 JacobiRotation<RealScalar> rot;
1056 rot.makeGivens(x, z);
1061 const RealScalar diff = diag[k] - diag[k + 1];
1070 const RealScalar delta = rot.s() * (rot.s() * diff + RealScalar(2) * rot.c() * subdiag[k]);
1073 subdiag[k] = rot.c() * rot.s() * diff + (rot.c() * rot.c() - rot.s() * rot.s()) * subdiag[k];
1075 diag[k + 1] += delta;
1077 if (k > start) subdiag[k - 1] = rot.c() * subdiag[k - 1] - rot.s() * z;
1082 z = -rot.s() * subdiag[k + 1];
1083 subdiag[k + 1] = rot.c() * subdiag[k + 1];
1091 EIGEN_IF_CONSTEXPR (!MatrixQType::IsRowMajor &&
int(MatrixQType::InnerStrideAtCompileTime) == 1) {
1092 using Scalar =
typename MatrixQType::Scalar;
1093 Map<Matrix<Scalar, Dynamic, Dynamic, ColMajor>,
Unaligned, OuterStride<>> q(
1094 matrixQ->data(), matrixQ->rows(), matrixQ->cols(), OuterStride<>(matrixQ->outerStride()));
1095 q.applyOnTheRight(k, k + 1, rot);
1097 matrixQ->applyOnTheRight(k, k + 1, rot);
Computes eigenvalues and eigenvectors of the generalized selfadjoint eigen problem.
Definition GeneralizedSelfAdjointEigenSolver.h:52
The matrix class, also used for vectors and row-vectors.
Definition Matrix.h:188
Computes eigenvalues and eigenvectors of selfadjoint matrices.
Definition SelfAdjointEigenSolver.h:83
PlainMatrixType operatorExp() const
Computes the matrix exponential of the matrix.
Definition SelfAdjointEigenSolver.h:376
SelfAdjointEigenSolver & compute(const EigenBase< InputType > &matrix, int options=ComputeEigenvectors)
Computes eigendecomposition of given matrix.
SelfAdjointEigenSolver & computeFromTridiagonal(const RealVectorType &diag, const SubDiagonalType &subdiag, int options=ComputeEigenvectors)
Computes the eigen decomposition from a tridiagonal symmetric matrix.
Definition SelfAdjointEigenSolver.h:542
SelfAdjointEigenSolver(EigenBase< InputType > &matrix, int options=ComputeEigenvectors)
Constructor for inplace decomposition .
Definition SelfAdjointEigenSolver.h:211
typename MatrixType::Scalar Scalar
Scalar type for matrices of type MatrixType_.
Definition SelfAdjointEigenSolver.h:94
typename internal::plain_col_type< MatrixType, Scalar >::type VectorType
Type for vector of eigenvalues as returned by eigenvalues().
Definition SelfAdjointEigenSolver.h:125
SelfAdjointEigenSolver()
Default constructor for fixed-size matrices.
Definition SelfAdjointEigenSolver.h:140
ComputationInfo info() const
Reports whether previous computation was successful.
Definition SelfAdjointEigenSolver.h:410
Matrix< Scalar, Size, ColsAtCompileTime, Options, MatrixType::MaxRowsAtCompileTime, MaxColsAtCompileTime > PlainMatrixType
Plain matrix type with the shape and storage options of MatrixType_; MatrixType_ itself unless that i...
Definition SelfAdjointEigenSolver.h:99
PlainMatrixType operatorInverseSqrt() const
Computes the inverse square root of the matrix.
Definition SelfAdjointEigenSolver.h:400
std::conditional_t< internal::is_ref< MatrixType >::value, MatrixType, Matrix< Scalar, Size, Size, ColMajor, MaxColsAtCompileTime, MaxColsAtCompileTime > > EigenvectorsType
Type of the matrix returned by eigenvectors().
Definition SelfAdjointEigenSolver.h:106
typename NumTraits< Scalar >::Real RealScalar
Real scalar type for MatrixType_.
Definition SelfAdjointEigenSolver.h:116
PlainMatrixType operatorSqrt() const
Computes the positive-definite square root of the matrix.
Definition SelfAdjointEigenSolver.h:360
Eigen::Index Index
Definition SelfAdjointEigenSolver.h:95
SelfAdjointEigenSolver(Index size)
Constructor, pre-allocates memory for dynamic-size matrices.
Definition SelfAdjointEigenSolver.h:162
const RealVectorType & eigenvalues() const
Returns the eigenvalues of given matrix.
Definition SelfAdjointEigenSolver.h:338
static const int m_maxIterations
Maximum number of iterations.
Definition SelfAdjointEigenSolver.h:420
const EigenvectorsType & eigenvectors() const
Returns the eigenvectors of given matrix.
Definition SelfAdjointEigenSolver.h:317
SelfAdjointEigenSolver(const EigenBase< InputType > &matrix, int options=ComputeEigenvectors)
Constructor; computes eigendecomposition of given matrix.
Definition SelfAdjointEigenSolver.h:187
SelfAdjointEigenSolver & computeDirect(const MatrixType &matrix, int options=ComputeEigenvectors)
Computes eigendecomposition of given matrix primarily using a closed-form algorithm.
Definition SelfAdjointEigenSolver.h:1015
Tridiagonal decomposition of a selfadjoint matrix.
Definition Tridiagonalization.h:71
ComputationInfo
Definition Constants.h:455
@ Unaligned
Definition Constants.h:236
@ Success
Definition Constants.h:457
@ NoConvergence
Definition Constants.h:461
@ ComputeEigenvectors
Definition Constants.h:406
Definition EigenBase.h:34
constexpr Derived & derived()
Definition EigenBase.h:50
Holds information about the various numeric (i.e. scalar) types allowed by Eigen.
Definition NumTraits.h:233