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