// This file is part of Eigen, a lightweight C++ template library
// for linear algebra.
//
// Copyright (C) 2008 Benoit Jacob <jacob.benoit.1@gmail.com>
// Copyright (C) 2008 Gael Guennebaud <gael.guennebaud@inria.fr>
//
// 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/.
// SPDX-License-Identifier: MPL-2.0

#include "main.h"
#include <Eigen/LU>
#include <algorithm>
#include <limits>
#include <vector>

template <typename Scalar>
struct determinant_reference_scalar {
  typedef long double type;
};

template <typename RealScalar>
struct determinant_reference_scalar<std::complex<RealScalar> > {
  typedef std::complex<long double> type;
};

template <typename MatrixType>
typename determinant_reference_scalar<typename MatrixType::Scalar>::type brute_force_determinant(const MatrixType& m) {
  typedef typename MatrixType::Scalar Scalar;
  typedef typename determinant_reference_scalar<Scalar>::type ReferenceScalar;
  const Index size = m.rows();
  std::vector<Index> permutation(size);
  for (Index i = 0; i < size; ++i) permutation[i] = i;

  ReferenceScalar result(0);
  do {
    int inversions = 0;
    for (Index i = 0; i < size; ++i)
      for (Index j = i + 1; j < size; ++j)
        if (permutation[i] > permutation[j]) ++inversions;

    ReferenceScalar term(1);
    for (Index i = 0; i < size; ++i) term *= ReferenceScalar(m(i, permutation[i]));
    result += inversions % 2 ? -term : term;
  } while (std::next_permutation(permutation.begin(), permutation.end()));

  return result;
}

template <typename MatrixType>
void verify_determinant_against_reference(const MatrixType& m) {
  typedef typename MatrixType::Scalar Scalar;
  typedef typename NumTraits<Scalar>::Real RealScalar;

  Scalar expected = Scalar(brute_force_determinant(m));
  Scalar actual = m.determinant();
  const RealScalar max_abs = (std::max)(RealScalar(1), m.cwiseAbs().maxCoeff());
  RealScalar scale = max_abs;
  for (Index i = 1; i < m.rows(); ++i) scale *= max_abs;
  RealScalar tolerance = RealScalar(100000) * NumTraits<RealScalar>::epsilon() * scale;
  RealScalar error = numext::abs(actual - expected);
  if (error > tolerance) std::cerr << "determinant error " << error << " exceeds tolerance " << tolerance << std::endl;
  VERIFY(error <= tolerance);
}

template <typename MatrixType>
void determinant_lu_fallback_reference(const MatrixType& m) {
  typedef typename MatrixType::Scalar Scalar;
  typedef typename NumTraits<Scalar>::Real RealScalar;
  const Index size = m.rows();

  MatrixType random(size, size);
  random.setRandom();
  verify_determinant_against_reference(random);

  MatrixType ill_conditioned = random;
  ill_conditioned.col(0) = ill_conditioned.col(1) + RealScalar(1e-8) * ill_conditioned.col(0);
  verify_determinant_against_reference(ill_conditioned);

  MatrixType scaled = RealScalar(1e6) * random;
  verify_determinant_against_reference(scaled);

  MatrixType tiny = MatrixType::Identity(size, size);
  tiny(0, 0) = Scalar((std::numeric_limits<RealScalar>::min)());
  verify_determinant_against_reference(tiny);

#if !EIGEN_ARCH_ARM
  MatrixType subnormal = MatrixType::Identity(size, size);
  subnormal(0, 0) = Scalar(std::numeric_limits<RealScalar>::denorm_min() * RealScalar(16));
  verify_determinant_against_reference(subnormal);
#endif
}

void determinant_non_finite_lu_fallback() {
  Matrix<double, 5, 5> m = Matrix<double, 5, 5>::Identity();
  m(0, 0) = std::numeric_limits<double>::quiet_NaN();
  VERIFY((numext::isnan)(m.determinant()));

  m = Matrix<double, 5, 5>::Identity();
  m(0, 0) = std::numeric_limits<double>::infinity();
  VERIFY((numext::isinf)(m.determinant()));
}

template <typename MatrixType>
void determinant(const MatrixType& m) {
  /* this test covers the following files:
     Determinant.h
  */
  Index size = m.rows();

  MatrixType m1(size, size), m2(size, size);
  m1.setRandom();
  m2.setRandom();
  typedef typename MatrixType::Scalar Scalar;
  Scalar x = internal::random<Scalar>();
  VERIFY_IS_APPROX(MatrixType::Identity(size, size).determinant(), Scalar(1));
  VERIFY_IS_APPROX((m1 * m2).eval().determinant(), m1.determinant() * m2.determinant());
  if (size == 1) return;
  Index i = internal::random<Index>(0, size - 1);
  Index j;
  do {
    j = internal::random<Index>(0, size - 1);
  } while (j == i);
  m2 = m1;
  m2.row(i).swap(m2.row(j));
  VERIFY_IS_APPROX(m2.determinant(), -m1.determinant());
  m2 = m1;
  m2.col(i).swap(m2.col(j));
  VERIFY_IS_APPROX(m2.determinant(), -m1.determinant());
  VERIFY_IS_APPROX(m2.determinant(), m2.transpose().determinant());
  VERIFY_IS_APPROX(numext::conj(m2.determinant()), m2.adjoint().determinant());
  m2 = m1;
  m2.row(i) += x * m2.row(j);
  VERIFY_IS_APPROX(m2.determinant(), m1.determinant());
  m2 = m1;
  m2.row(i) *= x;
  VERIFY_IS_APPROX(m2.determinant(), m1.determinant() * x);

  // check empty matrix
  VERIFY_IS_APPROX(m2.block(0, 0, 0, 0).determinant(), Scalar(1));
}

EIGEN_DECLARE_TEST(determinant) {
  for (int i = 0; i < g_repeat; i++) {
    int s = 0;
    CALL_SUBTEST_1(determinant(Matrix<float, 1, 1>()));
    CALL_SUBTEST_2(determinant(Matrix<double, 2, 2>()));
    CALL_SUBTEST_3(determinant(Matrix<double, 3, 3>()));
    CALL_SUBTEST_4(determinant(Matrix<double, 4, 4>()));
    CALL_SUBTEST_5(determinant(Matrix<double, 5, 5>()));
    CALL_SUBTEST_6(determinant(Matrix<std::complex<double>, 10, 10>()));
    CALL_SUBTEST_7(determinant_lu_fallback_reference(Matrix<double, 5, 5>()));
    CALL_SUBTEST_8(determinant_lu_fallback_reference(MatrixXcd(5, 5)));
    CALL_SUBTEST_9(determinant_non_finite_lu_fallback());
    s = internal::random<int>(1, EIGEN_TEST_MAX_SIZE / 4);
    CALL_SUBTEST_10(determinant(MatrixXd(s, s)));
    TEST_SET_BUT_UNUSED_VARIABLE(s);
  }
}
