EigenRand  0.5.0
 
Loading...
Searching...
No Matches
CwiseHeteroBinaryOp.h
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//
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_CWISE_HETERO_BINARY_OP_H
12#define EIGEN_CWISE_HETERO_BINARY_OP_H
13
14namespace Eigen {
15
16 template<typename BinaryOp, typename LhsType, typename RhsType>
17 class CwiseHeteroBinaryOp;
18
19 namespace internal {
20 template<typename BinaryOp, typename Lhs, typename Rhs>
21 struct traits<CwiseHeteroBinaryOp<BinaryOp, Lhs, Rhs> >
22 {
23 // we must not inherit from traits<Lhs> since it has
24 // the potential to cause problems with MSVC
25 typedef typename remove_all<Lhs>::type Ancestor;
26 typedef typename traits<Ancestor>::XprKind XprKind;
27 enum {
28 RowsAtCompileTime = traits<Ancestor>::RowsAtCompileTime,
29 ColsAtCompileTime = traits<Ancestor>::ColsAtCompileTime,
30 MaxRowsAtCompileTime = traits<Ancestor>::MaxRowsAtCompileTime,
31 MaxColsAtCompileTime = traits<Ancestor>::MaxColsAtCompileTime
32 };
33
34 // even though we require Lhs and Rhs to have the same scalar type (see CwiseHeteroBinaryOp constructor),
35 // we still want to handle the case when the result type is different.
36 typedef typename result_of<
37 BinaryOp(
38 const typename Lhs::Scalar&,
39 const typename Rhs::Scalar&
40 )
41 >::type Scalar;
42 typedef typename cwise_promote_storage_type<typename traits<Lhs>::StorageKind,
43 typename traits<Rhs>::StorageKind,
44 BinaryOp>::ret StorageKind;
45 typedef typename promote_index_type<typename traits<Lhs>::StorageIndex,
46 typename traits<Rhs>::StorageIndex>::type StorageIndex;
47 typedef typename Lhs::Nested LhsNested;
48 typedef typename Rhs::Nested RhsNested;
49 typedef typename remove_reference<LhsNested>::type _LhsNested;
50 typedef typename remove_reference<RhsNested>::type _RhsNested;
51 enum {
52 Flags = cwise_promote_storage_order<typename traits<Lhs>::StorageKind, typename traits<Rhs>::StorageKind, _LhsNested::Flags& RowMajorBit, _RhsNested::Flags& RowMajorBit>::value
53 };
54 };
55 } // end namespace internal
56
57 template<typename BinaryOp, typename Lhs, typename Rhs, typename StorageKind>
58 class CwiseHeteroBinaryOpImpl;
59
79 template<typename BinaryOp, typename LhsType, typename RhsType>
81 public CwiseHeteroBinaryOpImpl<
82 BinaryOp, LhsType, RhsType,
83 typename internal::cwise_promote_storage_type<typename internal::traits<LhsType>::StorageKind,
84 typename internal::traits<RhsType>::StorageKind,
85 BinaryOp>::ret>,
86 internal::no_assignment_operator
87 {
88 public:
89
90 typedef typename internal::remove_all<BinaryOp>::type Functor;
91 typedef typename internal::remove_all<LhsType>::type Lhs;
92 typedef typename internal::remove_all<RhsType>::type Rhs;
93
94 typedef typename CwiseHeteroBinaryOpImpl<
95 BinaryOp, LhsType, RhsType,
96 typename internal::cwise_promote_storage_type<typename internal::traits<LhsType>::StorageKind,
97 typename internal::traits<Rhs>::StorageKind,
98 BinaryOp>::ret>::Base Base;
99 EIGEN_GENERIC_PUBLIC_INTERFACE(CwiseHeteroBinaryOp)
100
101 typedef typename internal::ref_selector<LhsType>::type LhsNested;
102 typedef typename internal::ref_selector<RhsType>::type RhsNested;
103 typedef typename internal::remove_reference<LhsNested>::type _LhsNested;
104 typedef typename internal::remove_reference<RhsNested>::type _RhsNested;
105
106#if EIGEN_COMP_MSVC && EIGEN_HAS_CXX11
107 //Required for Visual Studio or the Copy constructor will probably not get inlined!
108 EIGEN_STRONG_INLINE
110#endif
111
112 EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE
113 CwiseHeteroBinaryOp(const Lhs& aLhs, const Rhs& aRhs, const BinaryOp& func = BinaryOp())
114 : m_lhs(aLhs), m_rhs(aRhs), m_functor(func)
115 {
116 // require the sizes to match
117 EIGEN_STATIC_ASSERT_SAME_MATRIX_SIZE(Lhs, Rhs)
118 eigen_assert(aLhs.rows() == aRhs.rows() && aLhs.cols() == aRhs.cols());
119 }
120
121 EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE constexpr
122 Index rows() const EIGEN_NOEXCEPT {
123 // return the fixed size type if available to enable compile time optimizations
124 return internal::traits<typename internal::remove_all<LhsNested>::type>::RowsAtCompileTime == Dynamic ? m_rhs.rows() : m_lhs.rows();
125 }
126 EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE constexpr
127 Index cols() const EIGEN_NOEXCEPT {
128 // return the fixed size type if available to enable compile time optimizations
129 return internal::traits<typename internal::remove_all<LhsNested>::type>::ColsAtCompileTime == Dynamic ? m_rhs.cols() : m_lhs.cols();
130 }
131
133 EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE
134 const _LhsNested& lhs() const { return m_lhs; }
136 EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE
137 const _RhsNested& rhs() const { return m_rhs; }
139 EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE
140 const BinaryOp& functor() const { return m_functor; }
141
142 protected:
143 LhsNested m_lhs;
144 RhsNested m_rhs;
145 const BinaryOp m_functor;
146 };
147
148 // Generic API dispatcher
149 template<typename BinaryOp, typename Lhs, typename Rhs, typename StorageKind>
150 class CwiseHeteroBinaryOpImpl
151 : public internal::generic_xpr_base<CwiseHeteroBinaryOp<BinaryOp, Lhs, Rhs> >::type
152 {
153 public:
154 typedef typename internal::generic_xpr_base<CwiseHeteroBinaryOp<BinaryOp, Lhs, Rhs> >::type Base;
155 };
156
157
158 namespace internal {
159 // -------------------- CwiseHeteroBinaryOp --------------------
160
161 // this is a binary expression
162 template<typename BinaryOp, typename Lhs, typename Rhs>
163 struct evaluator<CwiseHeteroBinaryOp<BinaryOp, Lhs, Rhs> >
164 : public binary_evaluator<CwiseHeteroBinaryOp<BinaryOp, Lhs, Rhs> >
165 {
166 typedef CwiseHeteroBinaryOp<BinaryOp, Lhs, Rhs> XprType;
167 typedef binary_evaluator<CwiseHeteroBinaryOp<BinaryOp, Lhs, Rhs> > Base;
168
169 EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE
170 explicit evaluator(const XprType& xpr) : Base(xpr) {}
171 };
172
173 template<typename BinaryOp, typename Lhs, typename Rhs>
174 struct binary_evaluator<CwiseHeteroBinaryOp<BinaryOp, Lhs, Rhs>, IndexBased, IndexBased>
175 : evaluator_base<CwiseHeteroBinaryOp<BinaryOp, Lhs, Rhs> >
176 {
177 typedef CwiseHeteroBinaryOp<BinaryOp, Lhs, Rhs> XprType;
178 using LhsScalar = typename Lhs::Scalar;
179 using RhsScalar = typename Rhs::Scalar;
180
181 enum {
182 CoeffReadCost = int(evaluator<Lhs>::CoeffReadCost) + int(evaluator<Rhs>::CoeffReadCost) + int(functor_traits<BinaryOp>::Cost),
183
184 LhsFlags = evaluator<Lhs>::Flags,
185 RhsFlags = evaluator<Rhs>::Flags,
186 SameType = is_same<typename Lhs::Scalar, typename Rhs::Scalar>::value,
187 StorageOrdersAgree = (int(LhsFlags) & RowMajorBit) == (int(RhsFlags) & RowMajorBit),
188 Flags0 = (int(LhsFlags) | int(RhsFlags)) & (
189 HereditaryBits
190 | (int(LhsFlags) & int(RhsFlags) &
191 ((StorageOrdersAgree ? LinearAccessBit : 0)
192 | (functor_traits<BinaryOp>::PacketAccess && StorageOrdersAgree ? PacketAccessBit : 0)
193 )
194 )
195 ),
196 Flags = (Flags0 & ~RowMajorBit) | (LhsFlags & RowMajorBit),
197 Alignment = EIGEN_PLAIN_ENUM_MIN(evaluator<Lhs>::Alignment, evaluator<Rhs>::Alignment)
198 };
199
200 EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE
201 explicit binary_evaluator(const XprType& xpr) : m_d(xpr)
202 {
203 EIGEN_INTERNAL_CHECK_COST_VALUE(functor_traits<BinaryOp>::Cost);
204 EIGEN_INTERNAL_CHECK_COST_VALUE(CoeffReadCost);
205 }
206
207 typedef typename XprType::CoeffReturnType CoeffReturnType;
208
209 EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE
210 CoeffReturnType coeff(Index row, Index col) const
211 {
212 return m_d.func()(m_d.lhsImpl.coeff(row, col), m_d.rhsImpl.coeff(row, col));
213 }
214
215 EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE
216 CoeffReturnType coeff(Index index) const
217 {
218 return m_d.func()(m_d.lhsImpl.coeff(index), m_d.rhsImpl.coeff(index));
219 }
220
221 template<int LoadMode, typename PacketType>
222 EIGEN_STRONG_INLINE
223 PacketType packet(Index row, Index col) const
224 {
225 using IPacketType = decltype(reinterpret_to_float(std::declval<PacketType>()));
226 using FPacketType = decltype(reinterpret_to_float(std::declval<PacketType>()));
227 using RhsPacket = typename std::conditional<std::is_same<RhsScalar, float>::value, FPacketType, IPacketType>::type;
228
229 return m_d.func().packetOp(m_d.lhsImpl.template packet<LoadMode, PacketType>(row, col),
230 m_d.rhsImpl.template packet<LoadMode, RhsPacket>(row, col));
231 }
232
233 template<int LoadMode, typename PacketType>
234 EIGEN_STRONG_INLINE
235 PacketType packet(Index index) const
236 {
237 using IPacketType = decltype(reinterpret_to_float(std::declval<PacketType>()));
238 using FPacketType = decltype(reinterpret_to_float(std::declval<PacketType>()));
239 using RhsPacket = typename std::conditional<std::is_same<RhsScalar, float>::value, FPacketType, IPacketType>::type;
240
241 return m_d.func().packetOp(m_d.lhsImpl.template packet<LoadMode, PacketType>(index),
242 m_d.rhsImpl.template packet<LoadMode, RhsPacket>(index));
243 }
244
245 protected:
246
247 // this helper permits to completely eliminate the functor if it is empty
248 struct Data
249 {
250 EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE
251 Data(const XprType& xpr) : op(xpr.functor()), lhsImpl(xpr.lhs()), rhsImpl(xpr.rhs()) {}
252 EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE
253 const BinaryOp& func() const { return op; }
254 BinaryOp op;
255 evaluator<Lhs> lhsImpl;
256 evaluator<Rhs> rhsImpl;
257 };
258
259 Data m_d;
260 };
261 }
262
263} // end namespace Eigen
264
265#endif // EIGEN_CWISE_HETERO_BINARY_OP_H
Generic expression where a coefficient-wise binary operator is applied to two expressions.
Definition: CwiseHeteroBinaryOp.h:87
EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE const BinaryOp & functor() const
Definition: CwiseHeteroBinaryOp.h:140
EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE const _RhsNested & rhs() const
Definition: CwiseHeteroBinaryOp.h:137
EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE const _LhsNested & lhs() const
Definition: CwiseHeteroBinaryOp.h:134