CommaInitializer.h 5.6 KB

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