// 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))));
  }
}
