|  | // 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/. | 
|  |  | 
|  | #ifndef EIGEN_COMMAINITIALIZER_H | 
|  | #define EIGEN_COMMAINITIALIZER_H | 
|  |  | 
|  | #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 | 
|  | { | 
|  | typedef typename XprType::Scalar Scalar; | 
|  |  | 
|  | EIGEN_DEVICE_FUNC | 
|  | inline CommaInitializer(XprType& xpr, const Scalar& s) | 
|  | : m_xpr(xpr), m_row(0), m_col(1), m_currentBlockRows(1) | 
|  | { | 
|  | eigen_assert(m_xpr.rows() > 0 && m_xpr.cols() > 0 | 
|  | && "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.block(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. */ | 
|  | // FIXME in C++11 mode this could be replaced by a proper RValue constructor | 
|  | 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 | 
|  | EIGEN_EXCEPTION_SPEC(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 |