File indexing completed on 2025-01-18 09:56:11
0001
0002
0003
0004
0005
0006
0007
0008
0009
0010 #ifndef EIGEN_CONDITIONESTIMATOR_H
0011 #define EIGEN_CONDITIONESTIMATOR_H
0012
0013 namespace Eigen {
0014
0015 namespace internal {
0016
0017 template <typename Vector, typename RealVector, bool IsComplex>
0018 struct rcond_compute_sign {
0019 static inline Vector run(const Vector& v) {
0020 const RealVector v_abs = v.cwiseAbs();
0021 return (v_abs.array() == static_cast<typename Vector::RealScalar>(0))
0022 .select(Vector::Ones(v.size()), v.cwiseQuotient(v_abs));
0023 }
0024 };
0025
0026
0027 template <typename Vector>
0028 struct rcond_compute_sign<Vector, Vector, false> {
0029 static inline Vector run(const Vector& v) {
0030 return (v.array() < static_cast<typename Vector::RealScalar>(0))
0031 .select(-Vector::Ones(v.size()), Vector::Ones(v.size()));
0032 }
0033 };
0034
0035
0036
0037
0038
0039
0040
0041
0042
0043
0044
0045
0046
0047
0048
0049
0050
0051
0052
0053
0054
0055 template <typename Decomposition>
0056 typename Decomposition::RealScalar rcond_invmatrix_L1_norm_estimate(const Decomposition& dec)
0057 {
0058 typedef typename Decomposition::MatrixType MatrixType;
0059 typedef typename Decomposition::Scalar Scalar;
0060 typedef typename Decomposition::RealScalar RealScalar;
0061 typedef typename internal::plain_col_type<MatrixType>::type Vector;
0062 typedef typename internal::plain_col_type<MatrixType, RealScalar>::type RealVector;
0063 const bool is_complex = (NumTraits<Scalar>::IsComplex != 0);
0064
0065 eigen_assert(dec.rows() == dec.cols());
0066 const Index n = dec.rows();
0067 if (n == 0)
0068 return 0;
0069
0070
0071 #ifdef __INTEL_COMPILER
0072 #pragma warning push
0073 #pragma warning ( disable : 2259 )
0074 #endif
0075 Vector v = dec.solve(Vector::Ones(n) / Scalar(n));
0076 #ifdef __INTEL_COMPILER
0077 #pragma warning pop
0078 #endif
0079
0080
0081
0082
0083
0084 RealScalar lower_bound = v.template lpNorm<1>();
0085 if (n == 1)
0086 return lower_bound;
0087
0088
0089
0090
0091 RealScalar old_lower_bound = lower_bound;
0092 Vector sign_vector(n);
0093 Vector old_sign_vector;
0094 Index v_max_abs_index = -1;
0095 Index old_v_max_abs_index = v_max_abs_index;
0096 for (int k = 0; k < 4; ++k)
0097 {
0098 sign_vector = internal::rcond_compute_sign<Vector, RealVector, is_complex>::run(v);
0099 if (k > 0 && !is_complex && sign_vector == old_sign_vector) {
0100
0101 break;
0102 }
0103
0104 v = dec.adjoint().solve(sign_vector);
0105 v.real().cwiseAbs().maxCoeff(&v_max_abs_index);
0106 if (v_max_abs_index == old_v_max_abs_index) {
0107
0108 break;
0109 }
0110
0111 v = dec.solve(Vector::Unit(n, v_max_abs_index));
0112 lower_bound = v.template lpNorm<1>();
0113 if (lower_bound <= old_lower_bound) {
0114
0115 break;
0116 }
0117 if (!is_complex) {
0118 old_sign_vector = sign_vector;
0119 }
0120 old_v_max_abs_index = v_max_abs_index;
0121 old_lower_bound = lower_bound;
0122 }
0123
0124
0125
0126
0127
0128
0129
0130
0131
0132
0133 Scalar alternating_sign(RealScalar(1));
0134 for (Index i = 0; i < n; ++i) {
0135
0136 v[i] = alternating_sign * static_cast<RealScalar>(RealScalar(1) + (RealScalar(i) / (RealScalar(n - 1))));
0137 alternating_sign = -alternating_sign;
0138 }
0139 v = dec.solve(v);
0140 const RealScalar alternate_lower_bound = (2 * v.template lpNorm<1>()) / (3 * RealScalar(n));
0141 return numext::maxi(lower_bound, alternate_lower_bound);
0142 }
0143
0144
0145
0146
0147
0148
0149
0150
0151
0152
0153
0154
0155
0156
0157 template <typename Decomposition>
0158 typename Decomposition::RealScalar
0159 rcond_estimate_helper(typename Decomposition::RealScalar matrix_norm, const Decomposition& dec)
0160 {
0161 typedef typename Decomposition::RealScalar RealScalar;
0162 eigen_assert(dec.rows() == dec.cols());
0163 if (dec.rows() == 0) return NumTraits<RealScalar>::infinity();
0164 if (matrix_norm == RealScalar(0)) return RealScalar(0);
0165 if (dec.rows() == 1) return RealScalar(1);
0166 const RealScalar inverse_matrix_norm = rcond_invmatrix_L1_norm_estimate(dec);
0167 return (inverse_matrix_norm == RealScalar(0) ? RealScalar(0)
0168 : (RealScalar(1) / inverse_matrix_norm) / matrix_norm);
0169 }
0170
0171 }
0172
0173 }
0174
0175 #endif