Branch data Line data Source code
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@inria.fr> 5 : : // Copyright (C) 2006-2008 Benoit Jacob <jacob.benoit.1@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 \blank \ref MatrixBaseCommaInitRef "MatrixBase::operator<<", CommaInitializer::finished() 26 : : */ 27 : : template<typename XprType> 28 : : struct CommaInitializer 29 : : { 30 : : typedef typename XprType::Scalar Scalar; 31 : : 32 : : EIGEN_DEVICE_FUNC 33 : 32088 : inline CommaInitializer(XprType& xpr, const Scalar& s) 34 : 32088 : : m_xpr(xpr), m_row(0), m_col(1), m_currentBlockRows(1) 35 : : { 36 : 32088 : eigen_assert(m_xpr.rows() > 0 && m_xpr.cols() > 0 37 : : && "Cannot comma-initialize a 0x0 matrix (operator<<)"); 38 : 32088 : m_xpr.coeffRef(0,0) = s; 39 : 32088 : } 40 : : 41 : : template<typename OtherDerived> 42 : : EIGEN_DEVICE_FUNC 43 : 306 : inline CommaInitializer(XprType& xpr, const DenseBase<OtherDerived>& other) 44 : 306 : : m_xpr(xpr), m_row(0), m_col(other.cols()), m_currentBlockRows(other.rows()) 45 : : { 46 : 306 : eigen_assert(m_xpr.rows() >= other.rows() && m_xpr.cols() >= other.cols() 47 : : && "Cannot comma-initialize a 0x0 matrix (operator<<)"); 48 : 306 : m_xpr.block(0, 0, other.rows(), other.cols()) = other; 49 : 306 : } 50 : : 51 : : /* Copy/Move constructor which transfers ownership. This is crucial in 52 : : * absence of return value optimization to avoid assertions during destruction. */ 53 : : // FIXME in C++11 mode this could be replaced by a proper RValue constructor 54 : : EIGEN_DEVICE_FUNC 55 : : inline CommaInitializer(const CommaInitializer& o) 56 : : : m_xpr(o.m_xpr), m_row(o.m_row), m_col(o.m_col), m_currentBlockRows(o.m_currentBlockRows) { 57 : : // Mark original object as finished. In absence of R-value references we need to const_cast: 58 : : const_cast<CommaInitializer&>(o).m_row = m_xpr.rows(); 59 : : const_cast<CommaInitializer&>(o).m_col = m_xpr.cols(); 60 : : const_cast<CommaInitializer&>(o).m_currentBlockRows = 0; 61 : : } 62 : : 63 : : /* inserts a scalar value in the target matrix */ 64 : : EIGEN_DEVICE_FUNC 65 : 80661 : CommaInitializer& operator,(const Scalar& s) 66 : : { 67 : 80661 : if (m_col==m_xpr.cols()) 68 : : { 69 : 72217 : m_row+=m_currentBlockRows; 70 : 72217 : m_col = 0; 71 : 72217 : m_currentBlockRows = 1; 72 : 72217 : eigen_assert(m_row<m_xpr.rows() 73 : : && "Too many rows passed to comma initializer (operator<<)"); 74 : : } 75 : 80661 : eigen_assert(m_col<m_xpr.cols() 76 : : && "Too many coefficients passed to comma initializer (operator<<)"); 77 : 80661 : eigen_assert(m_currentBlockRows==1); 78 : 80661 : m_xpr.coeffRef(m_row, m_col++) = s; 79 : 80661 : return *this; 80 : : } 81 : : 82 : : /* inserts a matrix expression in the target matrix */ 83 : : template<typename OtherDerived> 84 : : EIGEN_DEVICE_FUNC 85 : 306 : CommaInitializer& operator,(const DenseBase<OtherDerived>& other) 86 : : { 87 : 306 : if (m_col==m_xpr.cols() && (other.cols()!=0 || other.rows()!=m_currentBlockRows)) 88 : : { 89 : 306 : m_row+=m_currentBlockRows; 90 : 306 : m_col = 0; 91 : 306 : m_currentBlockRows = other.rows(); 92 : 306 : eigen_assert(m_row+m_currentBlockRows<=m_xpr.rows() 93 : : && "Too many rows passed to comma initializer (operator<<)"); 94 : : } 95 : 306 : eigen_assert((m_col + other.cols() <= m_xpr.cols()) 96 : : && "Too many coefficients passed to comma initializer (operator<<)"); 97 : 306 : eigen_assert(m_currentBlockRows==other.rows()); 98 : 306 : m_xpr.template block<OtherDerived::RowsAtCompileTime, OtherDerived::ColsAtCompileTime> 99 : 306 : (m_row, m_col, other.rows(), other.cols()) = other; 100 : 306 : m_col += other.cols(); 101 : 306 : return *this; 102 : : } 103 : : 104 : : EIGEN_DEVICE_FUNC 105 : 32394 : inline ~CommaInitializer() 106 : : #if defined VERIFY_RAISES_ASSERT && (!defined EIGEN_NO_ASSERTION_CHECKING) && defined EIGEN_EXCEPTIONS 107 : : EIGEN_EXCEPTION_SPEC(Eigen::eigen_assert_exception) 108 : : #endif 109 : : { 110 : 32394 : finished(); 111 : 32394 : } 112 : : 113 : : /** \returns the built matrix once all its coefficients have been set. 114 : : * Calling finished is 100% optional. Its purpose is to write expressions 115 : : * like this: 116 : : * \code 117 : : * quaternion.fromRotationMatrix((Matrix3f() << axis0, axis1, axis2).finished()); 118 : : * \endcode 119 : : */ 120 : : EIGEN_DEVICE_FUNC 121 : 35694 : inline XprType& finished() { 122 : 35694 : eigen_assert(((m_row+m_currentBlockRows) == m_xpr.rows() || m_xpr.cols() == 0) 123 : : && m_col == m_xpr.cols() 124 : : && "Too few coefficients passed to comma initializer (operator<<)"); 125 : 35694 : return m_xpr; 126 : : } 127 : : 128 : : XprType& m_xpr; // target expression 129 : : Index m_row; // current row id 130 : : Index m_col; // current col id 131 : : Index m_currentBlockRows; // current block height 132 : : }; 133 : : 134 : : /** \anchor MatrixBaseCommaInitRef 135 : : * Convenient operator to set the coefficients of a matrix. 136 : : * 137 : : * The coefficients must be provided in a row major order and exactly match 138 : : * the size of the matrix. Otherwise an assertion is raised. 139 : : * 140 : : * Example: \include MatrixBase_set.cpp 141 : : * Output: \verbinclude MatrixBase_set.out 142 : : * 143 : : * \note According the c++ standard, the argument expressions of this comma initializer are evaluated in arbitrary order. 144 : : * 145 : : * \sa CommaInitializer::finished(), class CommaInitializer 146 : : */ 147 : : template<typename Derived> 148 : 32088 : EIGEN_DEVICE_FUNC inline CommaInitializer<Derived> DenseBase<Derived>::operator<< (const Scalar& s) 149 : : { 150 : 32088 : return CommaInitializer<Derived>(*static_cast<Derived*>(this), s); 151 : : } 152 : : 153 : : /** \sa operator<<(const Scalar&) */ 154 : : template<typename Derived> 155 : : template<typename OtherDerived> 156 : : EIGEN_DEVICE_FUNC inline CommaInitializer<Derived> 157 : 306 : DenseBase<Derived>::operator<<(const DenseBase<OtherDerived>& other) 158 : : { 159 : 306 : return CommaInitializer<Derived>(*static_cast<Derived *>(this), other); 160 : : } 161 : : 162 : : } // end namespace Eigen 163 : : 164 : : #endif // EIGEN_COMMAINITIALIZER_H