Tests: Bound the conditioning of svd_min_norm's generated systems libeigen/eigen!3424 Co-authored-by: Rasmus Munk Larsen <rmlarsen@gmail.com>
diff --git a/test/svd_common.h b/test/svd_common.h index f1e6a6f..e737a01 100644 --- a/test/svd_common.h +++ b/test/svd_common.h
@@ -253,8 +253,10 @@ MatrixType2 m2(rank, cols); m2.setRandom(); if (SVD_FOR_MIN_NORM(MatrixType2)(m2).setThreshold(test_precision<Scalar>()).rank() != rank) { - // Ensure full row rank by making the leading square block diagonally dominant. - for (Index i = 0; i < rank; ++i) m2(i, i) += Scalar(1); + // With m2 = [B R] and s = 2 |m2|_F, sigma_min(m2 + s [I 0]) >= sigma_min(B + s I) >= s - |B|_2 >= |m2|_F (Weyl) + // and |m2 + s [I 0]|_2 <= 3 |m2|_F, so cond(m2) <= 3. + const Scalar shift = Scalar(2 * m2.norm()); + m2.diagonal().array() += shift; } RhsType2 rhs2 = RhsType2::Random(rank); @@ -277,7 +279,11 @@ typedef Matrix<Scalar, RowsAtCompileTime3, 1> RhsType3; Index rows3 = ColsAtCompileTime == Dynamic ? internal::random<Index>(rank + 1, 2 * cols) : Index(ColsAtCompileTime + 1); - Matrix<Scalar, RowsAtCompileTime3, Dynamic> C = Matrix<Scalar, RowsAtCompileTime3, Dynamic>::Random(rows3, rank); + // Orthonormal columns give m3 the nonzero singular values of m2, so sigma_0 / sigma_{rank-1} = cond(m2) stays far + // below 1/threshold() = 1/(diagSize * eps), and solve() keeps every direction of m2. + using MatrixTypeC = Matrix<Scalar, RowsAtCompileTime3, Dynamic>; + const MatrixTypeC C = + HouseholderQR<MatrixTypeC>(MatrixTypeC::Random(rows3, rank)).householderQ() * MatrixTypeC::Identity(rows3, rank); MatrixType3 m3 = C * m2; RhsType3 rhs3 = C * rhs2; SVD_STATIC_OPTIONS(MatrixType3, Options) svd3(m3);