// This file is part of Eigen, a lightweight C++ template library
// for linear algebra.
//
// Copyright (C) 2011 Benoit Jacob <jacob.benoit.1@gmail.com>
//
// 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 "MovableScalar.h"

template <typename Scalar>
struct ReductionIdentity {
  ReductionIdentity(double initialValue, int& lvalueCount, int& rvalueCount)
      : value(initialValue), lvalueConversions(lvalueCount), rvalueConversions(rvalueCount) {}
  ReductionIdentity(const ReductionIdentity&) = delete;
  ReductionIdentity(ReductionIdentity&&) = delete;

  explicit operator Scalar() const& {
    ++lvalueConversions;
    return Scalar(value);
  }
  explicit operator Scalar() && {
    ++rvalueConversions;
    return Scalar(value);
  }

  double value;
  int& lvalueConversions;
  int& rvalueConversions;
};

template <typename Scalar>
void reductionIdentityArguments() {
  const internal::scalar_sum_op<Scalar, Scalar> sum;
  const Matrix<Scalar, 0, 1> fixedEmpty;
  const Matrix<Scalar, Dynamic, 1, 0, 0, 1> zeroCapacity(0);
  Matrix<Scalar, Dynamic, 1> dynamic(0);
  const double runtimeIdentity = 0.25;
  VERIFY_IS_EQUAL(double(internal::redux_with_identity(fixedEmpty, sum, runtimeIdentity)), runtimeIdentity);
  VERIFY_IS_EQUAL(double(internal::redux_with_identity(dynamic, sum, runtimeIdentity)), runtimeIdentity);

  int lvalueConversions = 0, rvalueConversions = 0;
  ReductionIdentity<Scalar> identity(runtimeIdentity, lvalueConversions, rvalueConversions);
  const auto& constIdentity = identity;
  VERIFY_IS_EQUAL(double(internal::redux_with_identity(fixedEmpty, sum, identity)), runtimeIdentity);
  VERIFY_IS_EQUAL(double(internal::redux_with_identity(zeroCapacity, sum, identity)), runtimeIdentity);
  VERIFY_IS_EQUAL(double(internal::redux_with_identity(dynamic, sum, constIdentity)), runtimeIdentity);
  VERIFY_IS_EQUAL(lvalueConversions, 3);
  VERIFY_IS_EQUAL(rvalueConversions, 0);

  Matrix<Scalar, 2, 1> fixed;
  fixed << Scalar(2), Scalar(3);
  dynamic = fixed;
  VERIFY_IS_EQUAL(double(internal::redux_with_identity(fixed, sum, identity)), 5.0);
  VERIFY_IS_EQUAL(double(internal::redux_with_identity(
                      dynamic, sum, ReductionIdentity<Scalar>(runtimeIdentity, lvalueConversions, rvalueConversions))),
                  5.0);
  VERIFY_IS_EQUAL(lvalueConversions, 3);
  VERIFY_IS_EQUAL(rvalueConversions, 0);

  dynamic.resize(0);
  VERIFY_IS_EQUAL(double(internal::redux_with_identity(dynamic, sum, std::move(identity))), runtimeIdentity);
  VERIFY_IS_EQUAL(
      double(internal::redux_with_identity(
          fixedEmpty, sum, ReductionIdentity<Scalar>(runtimeIdentity, lvalueConversions, rvalueConversions))),
      runtimeIdentity);
  VERIFY_IS_EQUAL(lvalueConversions, 3);
  VERIFY_IS_EQUAL(rvalueConversions, 2);
}

template <typename MatrixType>
void zeroReduction(const MatrixType& m) {
  // Reductions that must hold for zero sized objects
  VERIFY(m.all());
  VERIFY(!m.any());
  VERIFY(m.prod() == 1);
  VERIFY(m.sum() == 0);
  VERIFY(m.norm() == 0);
  VERIFY(m.squaredNorm() == 0);
  EIGEN_IF_CONSTEXPR (!NumTraits<typename MatrixType::Scalar>::IsInteger) {
    VERIFY(m.template lpNorm<Infinity>() == 0);
    VERIFY(m.hypotNorm() == 0);
    VERIFY(m.stableNorm() == 0);
  }
  VERIFY(m.count() == 0);
  VERIFY(m.allFinite());
  VERIFY(!m.hasNaN());
  VERIFY_RAISES_ASSERT(m.minCoeff());
  VERIFY_RAISES_ASSERT(m.maxCoeff());
  Index i, j;
  EIGEN_UNUSED_VARIABLE(i);  // Only used if exceptions are enabled.
  EIGEN_UNUSED_VARIABLE(j);
  VERIFY_RAISES_ASSERT(m.minCoeff(&i, &j));
  VERIFY_RAISES_ASSERT(m.maxCoeff(&i, &j));
  VERIFY_RAISES_ASSERT(m.reshaped().minCoeff(&i));
  VERIFY_RAISES_ASSERT(m.reshaped().maxCoeff(&i));
}

template <typename MatrixType>
void zeroSizedMatrix() {
  MatrixType t1;
  typedef typename MatrixType::Scalar Scalar;

  if (MatrixType::SizeAtCompileTime == Dynamic || MatrixType::SizeAtCompileTime == 0) {
    zeroReduction(t1);
    if (MatrixType::RowsAtCompileTime == Dynamic) VERIFY(t1.rows() == 0);
    if (MatrixType::ColsAtCompileTime == Dynamic) VERIFY(t1.cols() == 0);

    MatrixType reversed = t1;
    reversed.reverseInPlace();
    VERIFY(reversed == t1.reverse());
    if (t1.rows() == t1.cols()) {
      MatrixType transposed = t1;
      transposed.transposeInPlace();
      VERIFY(transposed == t1.transpose());
    }

    if (MatrixType::RowsAtCompileTime == Dynamic && MatrixType::ColsAtCompileTime == Dynamic) {
      MatrixType t2(0, 0);
      VERIFY(t2.rows() == 0);
      VERIFY(t2.cols() == 0);

      zeroReduction(t2);
      VERIFY(t1 == t2);
    }
  }

  if (MatrixType::MaxColsAtCompileTime != 0 && MatrixType::MaxRowsAtCompileTime != 0) {
    Index rows = MatrixType::RowsAtCompileTime == Dynamic ? internal::random<Index>(1, 10)
                                                          : Index(MatrixType::RowsAtCompileTime);
    Index cols = MatrixType::ColsAtCompileTime == Dynamic ? internal::random<Index>(1, 10)
                                                          : Index(MatrixType::ColsAtCompileTime);
    MatrixType m(rows, cols);
    zeroReduction(m.template block<0, MatrixType::ColsAtCompileTime>(0, 0, 0, cols));
    zeroReduction(m.template block<MatrixType::RowsAtCompileTime, 0>(0, 0, rows, 0));
    zeroReduction(m.template block<0, 1>(0, 0));
    zeroReduction(m.template block<1, 0>(0, 0));
    Matrix<Scalar, Dynamic, Dynamic> prod = m.template block<MatrixType::RowsAtCompileTime, 0>(0, 0, rows, 0) *
                                            m.template block<0, MatrixType::ColsAtCompileTime>(0, 0, 0, cols);
    VERIFY(prod.rows() == rows && prod.cols() == cols);
    VERIFY(prod.isZero());
    prod = m.template block<1, 0>(0, 0) * m.template block<0, 1>(0, 0);
    VERIFY(prod.size() == 1);
    VERIFY(prod.isZero());
  }
}

// Complex extrema are unordered; check only reductions with defined empty identities.
template <typename MatrixType>
void zeroComplexReduction(const MatrixType& m) {
  using Scalar = typename MatrixType::Scalar;
  VERIFY_IS_EQUAL(m.sum(), Scalar(0));
  VERIFY_IS_EQUAL(m.prod(), Scalar(1));
  VERIFY_IS_EQUAL(m.template lpNorm<Infinity>(), 0.0);
  VERIFY_IS_EQUAL(m.hypotNorm(), 0.0);
  VERIFY_IS_EQUAL(m.stableNorm(), 0.0);
}

template <typename VectorType>
void zeroSizedVector() {
  VectorType t1;

  if (VectorType::SizeAtCompileTime == Dynamic || VectorType::SizeAtCompileTime == 0) {
    zeroReduction(t1);
    VERIFY(t1.size() == 0);
    VectorType t2(DenseIndex(0));  // Select the size constructor.
    VERIFY(t2.size() == 0);
    zeroReduction(t2);

    VERIFY(t1 == t2);
  }
}

EIGEN_DECLARE_TEST(zerosized) {
  reductionIdentityArguments<double>();
  reductionIdentityArguments<MovableScalar<double>>();
  zeroSizedMatrix<Matrix2d>();
  zeroSizedMatrix<Matrix3i>();
  zeroSizedMatrix<Matrix<float, 2, Dynamic> >();
  zeroSizedMatrix<MatrixXf>();
  zeroSizedMatrix<Matrix<float, 0, 0> >();
  zeroSizedMatrix<Matrix<float, Dynamic, 0, 0, 0, 0> >();
  zeroSizedMatrix<Matrix<float, 0, Dynamic, 0, 0, 0> >();
  zeroSizedMatrix<Matrix<float, Dynamic, Dynamic, 0, 0, 0> >();
  zeroSizedMatrix<Matrix<float, 0, 4> >();
  zeroSizedMatrix<Matrix<float, 4, 0> >();

  zeroSizedVector<Vector2d>();
  zeroSizedVector<Vector3i>();
  zeroSizedVector<VectorXf>();
  zeroSizedVector<Matrix<float, 0, 1> >();
  zeroSizedVector<Matrix<float, 1, 0> >();
  zeroComplexReduction(MatrixXcd(0, 3));
  zeroComplexReduction(MatrixXcd(3, 0));
  zeroComplexReduction(Matrix<std::complex<double>, 0, 0>());
  zeroComplexReduction(Matrix<std::complex<double>, 0, 3>());
  zeroComplexReduction(Matrix<std::complex<double>, 3, 0>());
}
