| 1 | // This file is part of Eigen, a lightweight C++ template library |
| 2 | // for linear algebra. |
| 3 | // |
| 4 | // Copyright (C) 2008-2010 Gael Guennebaud <gael.guennebaud@inria.fr> |
| 5 | // |
| 6 | // This Source Code Form is subject to the terms of the Mozilla |
| 7 | // Public License v. 2.0. If a copy of the MPL was not distributed |
| 8 | // with this file, You can obtain one at http://mozilla.org/MPL/2.0/. |
| 9 | |
| 10 | #ifndef EIGEN_SELECT_H |
| 11 | #define EIGEN_SELECT_H |
| 12 | |
| 13 | namespace Eigen { |
| 14 | |
| 15 | /** \class Select |
| 16 | * \ingroup Core_Module |
| 17 | * |
| 18 | * \brief Expression of a coefficient wise version of the C++ ternary operator ?: |
| 19 | * |
| 20 | * \param ConditionMatrixType the type of the \em condition expression which must be a boolean matrix |
| 21 | * \param ThenMatrixType the type of the \em then expression |
| 22 | * \param ElseMatrixType the type of the \em else expression |
| 23 | * |
| 24 | * This class represents an expression of a coefficient wise version of the C++ ternary operator ?:. |
| 25 | * It is the return type of DenseBase::select() and most of the time this is the only way it is used. |
| 26 | * |
| 27 | * \sa DenseBase::select(const DenseBase<ThenDerived>&, const DenseBase<ElseDerived>&) const |
| 28 | */ |
| 29 | |
| 30 | namespace internal { |
| 31 | template<typename ConditionMatrixType, typename ThenMatrixType, typename ElseMatrixType> |
| 32 | struct traits<Select<ConditionMatrixType, ThenMatrixType, ElseMatrixType> > |
| 33 | : traits<ThenMatrixType> |
| 34 | { |
| 35 | typedef typename traits<ThenMatrixType>::Scalar Scalar; |
| 36 | typedef Dense StorageKind; |
| 37 | typedef typename traits<ThenMatrixType>::XprKind XprKind; |
| 38 | typedef typename ConditionMatrixType::Nested ConditionMatrixNested; |
| 39 | typedef typename ThenMatrixType::Nested ThenMatrixNested; |
| 40 | typedef typename ElseMatrixType::Nested ElseMatrixNested; |
| 41 | enum { |
| 42 | RowsAtCompileTime = ConditionMatrixType::RowsAtCompileTime, |
| 43 | ColsAtCompileTime = ConditionMatrixType::ColsAtCompileTime, |
| 44 | MaxRowsAtCompileTime = ConditionMatrixType::MaxRowsAtCompileTime, |
| 45 | MaxColsAtCompileTime = ConditionMatrixType::MaxColsAtCompileTime, |
| 46 | Flags = (unsigned int)ThenMatrixType::Flags & ElseMatrixType::Flags & RowMajorBit |
| 47 | }; |
| 48 | }; |
| 49 | } |
| 50 | |
| 51 | template<typename ConditionMatrixType, typename ThenMatrixType, typename ElseMatrixType> |
| 52 | class Select : public internal::dense_xpr_base< Select<ConditionMatrixType, ThenMatrixType, ElseMatrixType> >::type, |
| 53 | internal::no_assignment_operator |
| 54 | { |
| 55 | public: |
| 56 | |
| 57 | typedef typename internal::dense_xpr_base<Select>::type Base; |
| 58 | EIGEN_DENSE_PUBLIC_INTERFACE(Select) |
| 59 | |
| 60 | inline EIGEN_DEVICE_FUNC |
| 61 | Select(const ConditionMatrixType& a_conditionMatrix, |
| 62 | const ThenMatrixType& a_thenMatrix, |
| 63 | const ElseMatrixType& a_elseMatrix) |
| 64 | : m_condition(a_conditionMatrix), m_then(a_thenMatrix), m_else(a_elseMatrix) |
| 65 | { |
| 66 | eigen_assert(m_condition.rows() == m_then.rows() && m_condition.rows() == m_else.rows()); |
| 67 | eigen_assert(m_condition.cols() == m_then.cols() && m_condition.cols() == m_else.cols()); |
| 68 | } |
| 69 | |
| 70 | inline EIGEN_DEVICE_FUNC Index rows() const { return m_condition.rows(); } |
| 71 | inline EIGEN_DEVICE_FUNC Index cols() const { return m_condition.cols(); } |
| 72 | |
| 73 | inline EIGEN_DEVICE_FUNC |
| 74 | const Scalar coeff(Index i, Index j) const |
| 75 | { |
| 76 | if (m_condition.coeff(i,j)) |
| 77 | return m_then.coeff(i,j); |
| 78 | else |
| 79 | return m_else.coeff(i,j); |
| 80 | } |
| 81 | |
| 82 | inline EIGEN_DEVICE_FUNC |
| 83 | const Scalar coeff(Index i) const |
| 84 | { |
| 85 | if (m_condition.coeff(i)) |
| 86 | return m_then.coeff(i); |
| 87 | else |
| 88 | return m_else.coeff(i); |
| 89 | } |
| 90 | |
| 91 | inline EIGEN_DEVICE_FUNC const ConditionMatrixType& conditionMatrix() const |
| 92 | { |
| 93 | return m_condition; |
| 94 | } |
| 95 | |
| 96 | inline EIGEN_DEVICE_FUNC const ThenMatrixType& thenMatrix() const |
| 97 | { |
| 98 | return m_then; |
| 99 | } |
| 100 | |
| 101 | inline EIGEN_DEVICE_FUNC const ElseMatrixType& elseMatrix() const |
| 102 | { |
| 103 | return m_else; |
| 104 | } |
| 105 | |
| 106 | protected: |
| 107 | typename ConditionMatrixType::Nested m_condition; |
| 108 | typename ThenMatrixType::Nested m_then; |
| 109 | typename ElseMatrixType::Nested m_else; |
| 110 | }; |
| 111 | |
| 112 | |
| 113 | /** \returns a matrix where each coefficient (i,j) is equal to \a thenMatrix(i,j) |
| 114 | * if \c *this(i,j), and \a elseMatrix(i,j) otherwise. |
| 115 | * |
| 116 | * Example: \include MatrixBase_select.cpp |
| 117 | * Output: \verbinclude MatrixBase_select.out |
| 118 | * |
| 119 | * \sa class Select |
| 120 | */ |
| 121 | template<typename Derived> |
| 122 | template<typename ThenDerived,typename ElseDerived> |
| 123 | inline const Select<Derived,ThenDerived,ElseDerived> |
| 124 | DenseBase<Derived>::select(const DenseBase<ThenDerived>& thenMatrix, |
| 125 | const DenseBase<ElseDerived>& elseMatrix) const |
| 126 | { |
| 127 | return Select<Derived,ThenDerived,ElseDerived>(derived(), thenMatrix.derived(), elseMatrix.derived()); |
| 128 | } |
| 129 | |
| 130 | /** Version of DenseBase::select(const DenseBase&, const DenseBase&) with |
| 131 | * the \em else expression being a scalar value. |
| 132 | * |
| 133 | * \sa DenseBase::select(const DenseBase<ThenDerived>&, const DenseBase<ElseDerived>&) const, class Select |
| 134 | */ |
| 135 | template<typename Derived> |
| 136 | template<typename ThenDerived> |
| 137 | inline const Select<Derived,ThenDerived, typename ThenDerived::ConstantReturnType> |
| 138 | DenseBase<Derived>::select(const DenseBase<ThenDerived>& thenMatrix, |
| 139 | const typename ThenDerived::Scalar& elseScalar) const |
| 140 | { |
| 141 | return Select<Derived,ThenDerived,typename ThenDerived::ConstantReturnType>( |
| 142 | derived(), thenMatrix.derived(), ThenDerived::Constant(rows(),cols(),elseScalar)); |
| 143 | } |
| 144 | |
| 145 | /** Version of DenseBase::select(const DenseBase&, const DenseBase&) with |
| 146 | * the \em then expression being a scalar value. |
| 147 | * |
| 148 | * \sa DenseBase::select(const DenseBase<ThenDerived>&, const DenseBase<ElseDerived>&) const, class Select |
| 149 | */ |
| 150 | template<typename Derived> |
| 151 | template<typename ElseDerived> |
| 152 | inline const Select<Derived, typename ElseDerived::ConstantReturnType, ElseDerived > |
| 153 | DenseBase<Derived>::select(const typename ElseDerived::Scalar& thenScalar, |
| 154 | const DenseBase<ElseDerived>& elseMatrix) const |
| 155 | { |
| 156 | return Select<Derived,typename ElseDerived::ConstantReturnType,ElseDerived>( |
| 157 | derived(), ElseDerived::Constant(rows(),cols(),thenScalar), elseMatrix.derived()); |
| 158 | } |
| 159 | |
| 160 | } // end namespace Eigen |
| 161 | |
| 162 | #endif // EIGEN_SELECT_H |
| 163 | |