| // SPDX-FileCopyrightText: The Eigen Authors |
| // SPDX-License-Identifier: MPL-2.0 |
| |
| #define EIGEN_JACOBI_SVD_BLOCKING_THRESHOLD 16 |
| #include "main.h" |
| #include <Eigen/SVD> |
| |
| template <typename MatrixType> |
| void jacobisvd_blocked(const MatrixType& input) { |
| using Scalar = typename MatrixType::Scalar; |
| using RealScalar = typename MatrixType::RealScalar; |
| const Index n = input.rows(); |
| MatrixType matrix = input; |
| JacobiSVD<MatrixType, ComputeFullU | ComputeFullV> svd(n, n); |
| JacobiSVD<MatrixType> valuesOnly(n, n); |
| // O(n*eps) backward error and orthogonality bounds for accumulated rotations. |
| const RealScalar tolerance = RealScalar(64 * n) * NumTraits<RealScalar>::epsilon(); |
| for (int pattern = 0; pattern < 4; ++pattern) { |
| if (pattern == 1) matrix.col(n - 1) = matrix.col(0); |
| if (pattern == 2) matrix.setIdentity(); |
| if (pattern == 3) matrix.setZero(); |
| svd.compute(matrix); |
| valuesOnly.compute(matrix); |
| VERIFY_IS_EQUAL(svd.info(), Success); |
| VERIFY_IS_EQUAL(valuesOnly.info(), Success); |
| const MatrixType reconstructed = |
| svd.matrixU() * svd.singularValues().template cast<Scalar>().asDiagonal() * svd.matrixV().adjoint(); |
| VERIFY_LE((matrix - reconstructed).norm(), tolerance * matrix.norm()); |
| VERIFY_LE((svd.matrixU().adjoint() * svd.matrixU() - MatrixType::Identity(n, n)).norm(), tolerance); |
| VERIFY_LE((svd.matrixV().adjoint() * svd.matrixV() - MatrixType::Identity(n, n)).norm(), tolerance); |
| VERIFY_LE((valuesOnly.singularValues() - svd.singularValues()).norm(), tolerance * matrix.norm()); |
| } |
| } |
| |
| EIGEN_DECLARE_TEST(jacobisvd_blocked) { |
| for (int repeat = 0; repeat < g_repeat; ++repeat) { |
| // Default block size is 32: cover scalar tails, contiguous blocks, and distant rows. |
| for (Index n : {31, 32, 33, 34, 65}) { |
| TEST_SET_BUT_UNUSED_VARIABLE(n); |
| CALL_SUBTEST_1(jacobisvd_blocked(MatrixXf(MatrixXf::Random(n, n)))); |
| CALL_SUBTEST_2((jacobisvd_blocked(Matrix<double, Dynamic, Dynamic, RowMajor>::Random(n, n).eval()))); |
| CALL_SUBTEST_3((jacobisvd_blocked(Matrix<std::complex<float>, Dynamic, Dynamic, RowMajor>::Random(n, n).eval()))); |
| CALL_SUBTEST_4(jacobisvd_blocked(MatrixXcd(MatrixXcd::Random(n, n)))); |
| CALL_SUBTEST_5((jacobisvd_blocked(Matrix<double, Dynamic, Dynamic, RowMajor, 65, 65>::Random(n, n).eval()))); |
| } |
| CALL_SUBTEST_6((jacobisvd_blocked(Matrix<double, 34, 34>::Random().eval()))); |
| } |
| } |