|  | // This file is part of Eigen, a lightweight C++ template library | 
|  | // for linear algebra. | 
|  | // | 
|  | // Copyright (C) 2021 Kolja Brix <kolja.brix@rwth-aachen.de> | 
|  | // | 
|  | // This Source Code Form is subject to the terms of the Mozilla | 
|  | // Public License v. 2.0. If a copy of the MPL was not distributed | 
|  | // with this file, You can obtain one at http://mozilla.org/MPL/2.0/. | 
|  |  | 
|  | #include "main.h" | 
|  | #include <Eigen/SVD> | 
|  |  | 
|  |  | 
|  | template<typename MatrixType> | 
|  | void check_generateRandomUnitaryMatrix(const Index dim) | 
|  | { | 
|  | const MatrixType Q = generateRandomUnitaryMatrix<MatrixType>(dim); | 
|  |  | 
|  | // validate dimensions | 
|  | VERIFY_IS_EQUAL(Q.rows(), dim); | 
|  | VERIFY_IS_EQUAL(Q.cols(), dim); | 
|  |  | 
|  | VERIFY_IS_UNITARY(Q); | 
|  | } | 
|  |  | 
|  | template<typename VectorType, typename RealScalarType> | 
|  | void check_setupRandomSvs(const Index dim, const RealScalarType max) | 
|  | { | 
|  | const VectorType v = setupRandomSvs<VectorType, RealScalarType>(dim, max); | 
|  |  | 
|  | // validate dimensions | 
|  | VERIFY_IS_EQUAL(v.size(), dim); | 
|  |  | 
|  | // check entries | 
|  | for(Index i = 0; i < v.size(); ++i) | 
|  | VERIFY_GE(v(i), 0); | 
|  | for(Index i = 0; i < v.size()-1; ++i) | 
|  | VERIFY_GE(v(i), v(i+1)); | 
|  | } | 
|  |  | 
|  | template<typename VectorType, typename RealScalarType> | 
|  | void check_setupRangeSvs(const Index dim, const RealScalarType min, const RealScalarType max) | 
|  | { | 
|  | const VectorType v = setupRangeSvs<VectorType, RealScalarType>(dim, min, max); | 
|  |  | 
|  | // validate dimensions | 
|  | VERIFY_IS_EQUAL(v.size(), dim); | 
|  |  | 
|  | // check entries | 
|  | if(dim == 1) { | 
|  | VERIFY_IS_APPROX(v(0), min); | 
|  | } else { | 
|  | VERIFY_IS_APPROX(v(0), max); | 
|  | VERIFY_IS_APPROX(v(dim-1), min); | 
|  | } | 
|  | for(Index i = 0; i < v.size()-1; ++i) | 
|  | VERIFY_GE(v(i), v(i+1)); | 
|  | } | 
|  |  | 
|  | template<typename MatrixType, typename RealScalar, typename RealVectorType> | 
|  | void check_generateRandomMatrixSvs(const Index rows, const Index cols, const Index diag_size, | 
|  | const RealScalar min_svs, const RealScalar max_svs) | 
|  | { | 
|  | RealVectorType svs = setupRangeSvs<RealVectorType, RealScalar>(diag_size, min_svs, max_svs); | 
|  |  | 
|  | MatrixType M; | 
|  | generateRandomMatrixSvs(svs, rows, cols, M); | 
|  |  | 
|  | // validate dimensions | 
|  | VERIFY_IS_EQUAL(M.rows(), rows); | 
|  | VERIFY_IS_EQUAL(M.cols(), cols); | 
|  | VERIFY_IS_EQUAL(svs.size(), diag_size); | 
|  |  | 
|  | // validate singular values | 
|  | Eigen::JacobiSVD<MatrixType> SVD(M); | 
|  | VERIFY_IS_APPROX(svs, SVD.singularValues()); | 
|  | } | 
|  |  | 
|  | template<typename MatrixType> | 
|  | void check_random_matrix(const MatrixType &m) | 
|  | { | 
|  | enum { | 
|  | Rows = MatrixType::RowsAtCompileTime, | 
|  | Cols = MatrixType::ColsAtCompileTime, | 
|  | DiagSize = EIGEN_SIZE_MIN_PREFER_DYNAMIC(Rows, Cols) | 
|  | }; | 
|  | typedef typename MatrixType::Scalar Scalar; | 
|  | typedef typename NumTraits<Scalar>::Real RealScalar; | 
|  | typedef Matrix<RealScalar, DiagSize, 1> RealVectorType; | 
|  |  | 
|  | const Index rows = m.rows(), cols = m.cols(); | 
|  | const Index diag_size = (std::min)(rows, cols); | 
|  | const RealScalar min_svs = 1.0, max_svs = 1000.0; | 
|  |  | 
|  | // check generation of unitary random matrices | 
|  | typedef Matrix<Scalar, Rows, Rows> MatrixAType; | 
|  | typedef Matrix<Scalar, Cols, Cols> MatrixBType; | 
|  | check_generateRandomUnitaryMatrix<MatrixAType>(rows); | 
|  | check_generateRandomUnitaryMatrix<MatrixBType>(cols); | 
|  |  | 
|  | // test generators for singular values | 
|  | check_setupRandomSvs<RealVectorType, RealScalar>(diag_size, max_svs); | 
|  | check_setupRangeSvs<RealVectorType, RealScalar>(diag_size, min_svs, max_svs); | 
|  |  | 
|  | // check generation of random matrices | 
|  | check_generateRandomMatrixSvs<MatrixType, RealScalar, RealVectorType>(rows, cols, diag_size, min_svs, max_svs); | 
|  | } | 
|  |  | 
|  | EIGEN_DECLARE_TEST(random_matrix) | 
|  | { | 
|  | for(int i = 0; i < g_repeat; i++) { | 
|  | CALL_SUBTEST_1(check_random_matrix(Matrix<float, 1, 1>())); | 
|  | CALL_SUBTEST_2(check_random_matrix(Matrix<float, 4, 4>())); | 
|  | CALL_SUBTEST_3(check_random_matrix(Matrix<float, 2, 3>())); | 
|  | CALL_SUBTEST_4(check_random_matrix(Matrix<float, 7, 4>())); | 
|  |  | 
|  | CALL_SUBTEST_5(check_random_matrix(Matrix<double, 1, 1>())); | 
|  | CALL_SUBTEST_6(check_random_matrix(Matrix<double, 6, 6>())); | 
|  | CALL_SUBTEST_7(check_random_matrix(Matrix<double, 5, 3>())); | 
|  | CALL_SUBTEST_8(check_random_matrix(Matrix<double, 4, 9>())); | 
|  |  | 
|  | CALL_SUBTEST_9(check_random_matrix(Matrix<std::complex<float>, 12, 12>())); | 
|  | CALL_SUBTEST_10(check_random_matrix(Matrix<std::complex<float>, 7, 14>())); | 
|  | CALL_SUBTEST_11(check_random_matrix(Matrix<std::complex<double>, 15, 11>())); | 
|  | CALL_SUBTEST_12(check_random_matrix(Matrix<std::complex<double>, 6, 9>())); | 
|  |  | 
|  | CALL_SUBTEST_13(check_random_matrix( | 
|  | MatrixXf(internal::random<int>(1, EIGEN_TEST_MAX_SIZE), internal::random<int>(1, EIGEN_TEST_MAX_SIZE)))); | 
|  | CALL_SUBTEST_14(check_random_matrix( | 
|  | MatrixXd(internal::random<int>(1, EIGEN_TEST_MAX_SIZE), internal::random<int>(1, EIGEN_TEST_MAX_SIZE)))); | 
|  | CALL_SUBTEST_15(check_random_matrix( | 
|  | MatrixXcf(internal::random<int>(1, EIGEN_TEST_MAX_SIZE), internal::random<int>(1, EIGEN_TEST_MAX_SIZE)))); | 
|  | CALL_SUBTEST_16(check_random_matrix( | 
|  | MatrixXcd(internal::random<int>(1, EIGEN_TEST_MAX_SIZE), internal::random<int>(1, EIGEN_TEST_MAX_SIZE)))); | 
|  | } | 
|  | } |