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
13namespace 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
30namespace internal {
31template<typename ConditionMatrixType, typename ThenMatrixType, typename ElseMatrixType>
32struct 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
51template<typename ConditionMatrixType, typename ThenMatrixType, typename ElseMatrixType>
52class 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 */
121template<typename Derived>
122template<typename ThenDerived,typename ElseDerived>
123inline const Select<Derived,ThenDerived,ElseDerived>
124DenseBase<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 */
135template<typename Derived>
136template<typename ThenDerived>
137inline const Select<Derived,ThenDerived, typename ThenDerived::ConstantReturnType>
138DenseBase<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 */
150template<typename Derived>
151template<typename ElseDerived>
152inline const Select<Derived, typename ElseDerived::ConstantReturnType, ElseDerived >
153DenseBase<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