• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // This file is part of Eigen, a lightweight C++ template library
2 // for linear algebra.
3 //
4 // Copyright (C) 2008-2014 Gael Guennebaud <gael.guennebaud@inria.fr>
5 // Copyright (C) 2006-2008 Benoit Jacob <jacob.benoit.1@gmail.com>
6 // Copyright (C) 2016 Eugene Brevdo <ebrevdo@gmail.com>
7 //
8 // This Source Code Form is subject to the terms of the Mozilla
9 // Public License v. 2.0. If a copy of the MPL was not distributed
10 // with this file, You can obtain one at http://mozilla.org/MPL/2.0/.
11 
12 #ifndef EIGEN_CWISE_TERNARY_OP_H
13 #define EIGEN_CWISE_TERNARY_OP_H
14 
15 namespace Eigen {
16 
17 namespace internal {
18 template <typename TernaryOp, typename Arg1, typename Arg2, typename Arg3>
19 struct traits<CwiseTernaryOp<TernaryOp, Arg1, Arg2, Arg3> > {
20   // we must not inherit from traits<Arg1> since it has
21   // the potential to cause problems with MSVC
22   typedef typename remove_all<Arg1>::type Ancestor;
23   typedef typename traits<Ancestor>::XprKind XprKind;
24   enum {
25     RowsAtCompileTime = traits<Ancestor>::RowsAtCompileTime,
26     ColsAtCompileTime = traits<Ancestor>::ColsAtCompileTime,
27     MaxRowsAtCompileTime = traits<Ancestor>::MaxRowsAtCompileTime,
28     MaxColsAtCompileTime = traits<Ancestor>::MaxColsAtCompileTime
29   };
30 
31   // even though we require Arg1, Arg2, and Arg3 to have the same scalar type
32   // (see CwiseTernaryOp constructor),
33   // we still want to handle the case when the result type is different.
34   typedef typename result_of<TernaryOp(
35       const typename Arg1::Scalar&, const typename Arg2::Scalar&,
36       const typename Arg3::Scalar&)>::type Scalar;
37 
38   typedef typename internal::traits<Arg1>::StorageKind StorageKind;
39   typedef typename internal::traits<Arg1>::StorageIndex StorageIndex;
40 
41   typedef typename Arg1::Nested Arg1Nested;
42   typedef typename Arg2::Nested Arg2Nested;
43   typedef typename Arg3::Nested Arg3Nested;
44   typedef typename remove_reference<Arg1Nested>::type _Arg1Nested;
45   typedef typename remove_reference<Arg2Nested>::type _Arg2Nested;
46   typedef typename remove_reference<Arg3Nested>::type _Arg3Nested;
47   enum { Flags = _Arg1Nested::Flags & RowMajorBit };
48 };
49 }  // end namespace internal
50 
51 template <typename TernaryOp, typename Arg1, typename Arg2, typename Arg3,
52           typename StorageKind>
53 class CwiseTernaryOpImpl;
54 
55 /** \class CwiseTernaryOp
56   * \ingroup Core_Module
57   *
58   * \brief Generic expression where a coefficient-wise ternary operator is
59  * applied to two expressions
60   *
61   * \tparam TernaryOp template functor implementing the operator
62   * \tparam Arg1Type the type of the first argument
63   * \tparam Arg2Type the type of the second argument
64   * \tparam Arg3Type the type of the third argument
65   *
66   * This class represents an expression where a coefficient-wise ternary
67  * operator is applied to three expressions.
68   * It is the return type of ternary operators, by which we mean only those
69  * ternary operators where
70   * all three arguments are Eigen expressions.
71   * For example, the return type of betainc(matrix1, matrix2, matrix3) is a
72  * CwiseTernaryOp.
73   *
74   * Most of the time, this is the only way that it is used, so you typically
75  * don't have to name
76   * CwiseTernaryOp types explicitly.
77   *
78   * \sa MatrixBase::ternaryExpr(const MatrixBase<Argument2> &, const
79  * MatrixBase<Argument3> &, const CustomTernaryOp &) const, class CwiseBinaryOp,
80  * class CwiseUnaryOp, class CwiseNullaryOp
81   */
82 template <typename TernaryOp, typename Arg1Type, typename Arg2Type,
83           typename Arg3Type>
84 class CwiseTernaryOp : public CwiseTernaryOpImpl<
85                            TernaryOp, Arg1Type, Arg2Type, Arg3Type,
86                            typename internal::traits<Arg1Type>::StorageKind>,
87                        internal::no_assignment_operator
88 {
89  public:
90   typedef typename internal::remove_all<Arg1Type>::type Arg1;
91   typedef typename internal::remove_all<Arg2Type>::type Arg2;
92   typedef typename internal::remove_all<Arg3Type>::type Arg3;
93 
94   typedef typename CwiseTernaryOpImpl<
95       TernaryOp, Arg1Type, Arg2Type, Arg3Type,
96       typename internal::traits<Arg1Type>::StorageKind>::Base Base;
97   EIGEN_GENERIC_PUBLIC_INTERFACE(CwiseTernaryOp)
98 
99   typedef typename internal::ref_selector<Arg1Type>::type Arg1Nested;
100   typedef typename internal::ref_selector<Arg2Type>::type Arg2Nested;
101   typedef typename internal::ref_selector<Arg3Type>::type Arg3Nested;
102   typedef typename internal::remove_reference<Arg1Nested>::type _Arg1Nested;
103   typedef typename internal::remove_reference<Arg2Nested>::type _Arg2Nested;
104   typedef typename internal::remove_reference<Arg3Nested>::type _Arg3Nested;
105 
106   EIGEN_DEVICE_FUNC
107   EIGEN_STRONG_INLINE CwiseTernaryOp(const Arg1& a1, const Arg2& a2,
108                                      const Arg3& a3,
109                                      const TernaryOp& func = TernaryOp())
110       : m_arg1(a1), m_arg2(a2), m_arg3(a3), m_functor(func) {
111     // require the sizes to match
112     EIGEN_STATIC_ASSERT_SAME_MATRIX_SIZE(Arg1, Arg2)
113     EIGEN_STATIC_ASSERT_SAME_MATRIX_SIZE(Arg1, Arg3)
114 
115     // The index types should match
116     EIGEN_STATIC_ASSERT((internal::is_same<
117                          typename internal::traits<Arg1Type>::StorageKind,
118                          typename internal::traits<Arg2Type>::StorageKind>::value),
119                         STORAGE_KIND_MUST_MATCH)
120     EIGEN_STATIC_ASSERT((internal::is_same<
121                          typename internal::traits<Arg1Type>::StorageKind,
122                          typename internal::traits<Arg3Type>::StorageKind>::value),
123                         STORAGE_KIND_MUST_MATCH)
124 
125     eigen_assert(a1.rows() == a2.rows() && a1.cols() == a2.cols() &&
126                  a1.rows() == a3.rows() && a1.cols() == a3.cols());
127   }
128 
129   EIGEN_DEVICE_FUNC
130   EIGEN_STRONG_INLINE Index rows() const {
131     // return the fixed size type if available to enable compile time
132     // optimizations
133     if (internal::traits<typename internal::remove_all<Arg1Nested>::type>::
134                 RowsAtCompileTime == Dynamic &&
135         internal::traits<typename internal::remove_all<Arg2Nested>::type>::
136                 RowsAtCompileTime == Dynamic)
137       return m_arg3.rows();
138     else if (internal::traits<typename internal::remove_all<Arg1Nested>::type>::
139                      RowsAtCompileTime == Dynamic &&
140              internal::traits<typename internal::remove_all<Arg3Nested>::type>::
141                      RowsAtCompileTime == Dynamic)
142       return m_arg2.rows();
143     else
144       return m_arg1.rows();
145   }
146   EIGEN_DEVICE_FUNC
147   EIGEN_STRONG_INLINE Index cols() const {
148     // return the fixed size type if available to enable compile time
149     // optimizations
150     if (internal::traits<typename internal::remove_all<Arg1Nested>::type>::
151                 ColsAtCompileTime == Dynamic &&
152         internal::traits<typename internal::remove_all<Arg2Nested>::type>::
153                 ColsAtCompileTime == Dynamic)
154       return m_arg3.cols();
155     else if (internal::traits<typename internal::remove_all<Arg1Nested>::type>::
156                      ColsAtCompileTime == Dynamic &&
157              internal::traits<typename internal::remove_all<Arg3Nested>::type>::
158                      ColsAtCompileTime == Dynamic)
159       return m_arg2.cols();
160     else
161       return m_arg1.cols();
162   }
163 
164   /** \returns the first argument nested expression */
165   EIGEN_DEVICE_FUNC
166   const _Arg1Nested& arg1() const { return m_arg1; }
167   /** \returns the first argument nested expression */
168   EIGEN_DEVICE_FUNC
169   const _Arg2Nested& arg2() const { return m_arg2; }
170   /** \returns the third argument nested expression */
171   EIGEN_DEVICE_FUNC
172   const _Arg3Nested& arg3() const { return m_arg3; }
173   /** \returns the functor representing the ternary operation */
174   EIGEN_DEVICE_FUNC
175   const TernaryOp& functor() const { return m_functor; }
176 
177  protected:
178   Arg1Nested m_arg1;
179   Arg2Nested m_arg2;
180   Arg3Nested m_arg3;
181   const TernaryOp m_functor;
182 };
183 
184 // Generic API dispatcher
185 template <typename TernaryOp, typename Arg1, typename Arg2, typename Arg3,
186           typename StorageKind>
187 class CwiseTernaryOpImpl
188     : public internal::generic_xpr_base<
189           CwiseTernaryOp<TernaryOp, Arg1, Arg2, Arg3> >::type {
190  public:
191   typedef typename internal::generic_xpr_base<
192       CwiseTernaryOp<TernaryOp, Arg1, Arg2, Arg3> >::type Base;
193 };
194 
195 }  // end namespace Eigen
196 
197 #endif  // EIGEN_CWISE_TERNARY_OP_H
198