Home | History | Annotate | Download | only in Core
      1 // This file is part of Eigen, a lightweight C++ template library
      2 // for linear algebra.
      3 //
      4 // Copyright (C) 2008 Gael Guennebaud <gael.guennebaud (at) inria.fr>
      5 // Copyright (C) 2006-2008 Benoit Jacob <jacob.benoit.1 (at) gmail.com>
      6 //
      7 // This Source Code Form is subject to the terms of the Mozilla
      8 // Public License v. 2.0. If a copy of the MPL was not distributed
      9 // with this file, You can obtain one at http://mozilla.org/MPL/2.0/.
     10 
     11 #ifndef EIGEN_COMMAINITIALIZER_H
     12 #define EIGEN_COMMAINITIALIZER_H
     13 
     14 namespace Eigen {
     15 
     16 /** \class CommaInitializer
     17   * \ingroup Core_Module
     18   *
     19   * \brief Helper class used by the comma initializer operator
     20   *
     21   * This class is internally used to implement the comma initializer feature. It is
     22   * the return type of MatrixBase::operator<<, and most of the time this is the only
     23   * way it is used.
     24   *
     25   * \sa \ref MatrixBaseCommaInitRef "MatrixBase::operator<<", CommaInitializer::finished()
     26   */
     27 template<typename XprType>
     28 struct CommaInitializer
     29 {
     30   typedef typename XprType::Scalar Scalar;
     31   typedef typename XprType::Index Index;
     32 
     33   inline CommaInitializer(XprType& xpr, const Scalar& s)
     34     : m_xpr(xpr), m_row(0), m_col(1), m_currentBlockRows(1)
     35   {
     36     m_xpr.coeffRef(0,0) = s;
     37   }
     38 
     39   template<typename OtherDerived>
     40   inline CommaInitializer(XprType& xpr, const DenseBase<OtherDerived>& other)
     41     : m_xpr(xpr), m_row(0), m_col(other.cols()), m_currentBlockRows(other.rows())
     42   {
     43     m_xpr.block(0, 0, other.rows(), other.cols()) = other;
     44   }
     45 
     46   /* inserts a scalar value in the target matrix */
     47   CommaInitializer& operator,(const Scalar& s)
     48   {
     49     if (m_col==m_xpr.cols())
     50     {
     51       m_row+=m_currentBlockRows;
     52       m_col = 0;
     53       m_currentBlockRows = 1;
     54       eigen_assert(m_row<m_xpr.rows()
     55         && "Too many rows passed to comma initializer (operator<<)");
     56     }
     57     eigen_assert(m_col<m_xpr.cols()
     58       && "Too many coefficients passed to comma initializer (operator<<)");
     59     eigen_assert(m_currentBlockRows==1);
     60     m_xpr.coeffRef(m_row, m_col++) = s;
     61     return *this;
     62   }
     63 
     64   /* inserts a matrix expression in the target matrix */
     65   template<typename OtherDerived>
     66   CommaInitializer& operator,(const DenseBase<OtherDerived>& other)
     67   {
     68     if (m_col==m_xpr.cols())
     69     {
     70       m_row+=m_currentBlockRows;
     71       m_col = 0;
     72       m_currentBlockRows = other.rows();
     73       eigen_assert(m_row+m_currentBlockRows<=m_xpr.rows()
     74         && "Too many rows passed to comma initializer (operator<<)");
     75     }
     76     eigen_assert(m_col<m_xpr.cols()
     77       && "Too many coefficients passed to comma initializer (operator<<)");
     78     eigen_assert(m_currentBlockRows==other.rows());
     79     if (OtherDerived::SizeAtCompileTime != Dynamic)
     80       m_xpr.template block<OtherDerived::RowsAtCompileTime != Dynamic ? OtherDerived::RowsAtCompileTime : 1,
     81                               OtherDerived::ColsAtCompileTime != Dynamic ? OtherDerived::ColsAtCompileTime : 1>
     82                     (m_row, m_col) = other;
     83     else
     84       m_xpr.block(m_row, m_col, other.rows(), other.cols()) = other;
     85     m_col += other.cols();
     86     return *this;
     87   }
     88 
     89   inline ~CommaInitializer()
     90   {
     91     eigen_assert((m_row+m_currentBlockRows) == m_xpr.rows()
     92          && m_col == m_xpr.cols()
     93          && "Too few coefficients passed to comma initializer (operator<<)");
     94   }
     95 
     96   /** \returns the built matrix once all its coefficients have been set.
     97     * Calling finished is 100% optional. Its purpose is to write expressions
     98     * like this:
     99     * \code
    100     * quaternion.fromRotationMatrix((Matrix3f() << axis0, axis1, axis2).finished());
    101     * \endcode
    102     */
    103   inline XprType& finished() { return m_xpr; }
    104 
    105   XprType& m_xpr;   // target expression
    106   Index m_row;              // current row id
    107   Index m_col;              // current col id
    108   Index m_currentBlockRows; // current block height
    109 };
    110 
    111 /** \anchor MatrixBaseCommaInitRef
    112   * Convenient operator to set the coefficients of a matrix.
    113   *
    114   * The coefficients must be provided in a row major order and exactly match
    115   * the size of the matrix. Otherwise an assertion is raised.
    116   *
    117   * Example: \include MatrixBase_set.cpp
    118   * Output: \verbinclude MatrixBase_set.out
    119   *
    120   * \sa CommaInitializer::finished(), class CommaInitializer
    121   */
    122 template<typename Derived>
    123 inline CommaInitializer<Derived> DenseBase<Derived>::operator<< (const Scalar& s)
    124 {
    125   return CommaInitializer<Derived>(*static_cast<Derived*>(this), s);
    126 }
    127 
    128 /** \sa operator<<(const Scalar&) */
    129 template<typename Derived>
    130 template<typename OtherDerived>
    131 inline CommaInitializer<Derived>
    132 DenseBase<Derived>::operator<<(const DenseBase<OtherDerived>& other)
    133 {
    134   return CommaInitializer<Derived>(*static_cast<Derived *>(this), other);
    135 }
    136 
    137 } // end namespace Eigen
    138 
    139 #endif // EIGEN_COMMAINITIALIZER_H
    140