// This file is part of Eigen, a lightweight C++ template library
// for linear algebra.
//
// Copyright (C) 2008 Gael Guennebaud <gael.guennebaud@inria.fr>
// Copyright (C) 2006-2008 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

#ifndef EIGEN_COMMAINITIALIZER_H
#define EIGEN_COMMAINITIALIZER_H

// IWYU pragma: private
#include "./InternalHeaderCheck.h"

namespace Eigen {

/** \class CommaInitializer
 * \ingroup Core_Module
 *
 * \brief Helper class used by the comma initializer operator
 *
 * This class is internally used to implement the comma initializer feature. It is
 * the return type of MatrixBase::operator<<, and most of the time this is the only
 * way it is used.
 *
 * \sa \blank \ref MatrixBaseCommaInitRef "MatrixBase::operator<<", CommaInitializer::finished()
 */
template <typename XprType>
struct CommaInitializer {
  using Scalar = typename XprType::Scalar;

  EIGEN_DEVICE_FUNC constexpr CommaInitializer(XprType& xpr, const Scalar& s)
      : m_xpr(xpr), m_row(0), m_col(1), m_currentBlockRows(1) {
    EIGEN_INTERNAL_ASSERT_NONEMPTY_MSG(m_xpr, "Cannot comma-initialize a 0x0 matrix (operator<<)");
    m_xpr.coeffRef(0, 0) = s;
  }

  template <typename OtherDerived>
  EIGEN_DEVICE_FUNC inline CommaInitializer(XprType& xpr, const DenseBase<OtherDerived>& other)
      : m_xpr(xpr), m_row(0), m_col(other.cols()), m_currentBlockRows(other.rows()) {
    eigen_assert(m_xpr.rows() >= other.rows() && m_xpr.cols() >= other.cols() &&
                 "Cannot comma-initialize a 0x0 matrix (operator<<)");
    m_xpr.template block<OtherDerived::RowsAtCompileTime, OtherDerived::ColsAtCompileTime>(0, 0, other.rows(),
                                                                                           other.cols()) = other;
  }

  /* Copy/Move constructor which transfers ownership. This is crucial in
   * absence of return value optimization to avoid assertions during destruction. */
  EIGEN_DEVICE_FUNC inline CommaInitializer(const CommaInitializer& o)
      : m_xpr(o.m_xpr), m_row(o.m_row), m_col(o.m_col), m_currentBlockRows(o.m_currentBlockRows) {
    // Mark original object as finished. In absence of R-value references we need to const_cast:
    const_cast<CommaInitializer&>(o).m_row = m_xpr.rows();
    const_cast<CommaInitializer&>(o).m_col = m_xpr.cols();
    const_cast<CommaInitializer&>(o).m_currentBlockRows = 0;
  }

  /* inserts a scalar value in the target matrix */
  EIGEN_DEVICE_FUNC CommaInitializer &operator,(const Scalar& s) {
    if (m_col == m_xpr.cols()) {
      m_row += m_currentBlockRows;
      m_col = 0;
      m_currentBlockRows = 1;
      eigen_assert(m_row < m_xpr.rows() && "Too many rows passed to comma initializer (operator<<)");
    }
    eigen_assert(m_col < m_xpr.cols() && "Too many coefficients passed to comma initializer (operator<<)");
    eigen_assert(m_currentBlockRows == 1);
    m_xpr.coeffRef(m_row, m_col++) = s;
    return *this;
  }

  /* inserts a matrix expression in the target matrix */
  template <typename OtherDerived>
  EIGEN_DEVICE_FUNC CommaInitializer &operator,(const DenseBase<OtherDerived>& other) {
    if (m_col == m_xpr.cols() && (other.cols() != 0 || other.rows() != m_currentBlockRows)) {
      m_row += m_currentBlockRows;
      m_col = 0;
      m_currentBlockRows = other.rows();
      eigen_assert(m_row + m_currentBlockRows <= m_xpr.rows() &&
                   "Too many rows passed to comma initializer (operator<<)");
    }
    eigen_assert((m_col + other.cols() <= m_xpr.cols()) &&
                 "Too many coefficients passed to comma initializer (operator<<)");
    eigen_assert(m_currentBlockRows == other.rows());
    m_xpr.template block<OtherDerived::RowsAtCompileTime, OtherDerived::ColsAtCompileTime>(m_row, m_col, other.rows(),
                                                                                           other.cols()) = other;
    m_col += other.cols();
    return *this;
  }

  EIGEN_DEVICE_FUNC inline ~CommaInitializer()
#if defined VERIFY_RAISES_ASSERT && (!defined EIGEN_NO_ASSERTION_CHECKING) && defined EIGEN_EXCEPTIONS
      noexcept(false)  // Eigen::eigen_assert_exception
#endif
  {
    finished();
  }

  /** \returns the built matrix once all its coefficients have been set.
   * Calling finished is 100% optional. Its purpose is to write expressions
   * like this:
   * \code
   * quaternion.fromRotationMatrix((Matrix3f() << axis0, axis1, axis2).finished());
   * \endcode
   */
  EIGEN_DEVICE_FUNC inline XprType& finished() {
    eigen_assert(((m_row + m_currentBlockRows) == m_xpr.rows() || m_xpr.cols() == 0) && m_col == m_xpr.cols() &&
                 "Too few coefficients passed to comma initializer (operator<<)");
    return m_xpr;
  }

  XprType& m_xpr;            // target expression
  Index m_row;               // current row id
  Index m_col;               // current col id
  Index m_currentBlockRows;  // current block height
};

/** \anchor MatrixBaseCommaInitRef
 * Convenient operator to set the coefficients of a matrix.
 *
 * The coefficients must be provided in a row major order and exactly match
 * the size of the matrix. Otherwise an assertion is raised.
 *
 * Example: \include MatrixBase_set.cpp
 * Output: \verbinclude MatrixBase_set.out
 *
 * \note According the c++ standard, the argument expressions of this comma initializer are evaluated in arbitrary
 * order.
 *
 * \sa CommaInitializer::finished(), class CommaInitializer
 */
template <typename Derived>
EIGEN_DEVICE_FUNC inline CommaInitializer<Derived> DenseBase<Derived>::operator<<(const Scalar& s) {
  return CommaInitializer<Derived>(*static_cast<Derived*>(this), s);
}

/** \sa operator<<(const Scalar&) */
template <typename Derived>
template <typename OtherDerived>
EIGEN_DEVICE_FUNC inline CommaInitializer<Derived> DenseBase<Derived>::operator<<(
    const DenseBase<OtherDerived>& other) {
  return CommaInitializer<Derived>(*static_cast<Derived*>(this), other);
}

}  // end namespace Eigen

#endif  // EIGEN_COMMAINITIALIZER_H
