CoreEvaluators.h 61 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688
  1. // This file is part of Eigen, a lightweight C++ template library
  2. // for linear algebra.
  3. //
  4. // Copyright (C) 2011 Benoit Jacob <jacob.benoit.1@gmail.com>
  5. // Copyright (C) 2011-2014 Gael Guennebaud <gael.guennebaud@inria.fr>
  6. // Copyright (C) 2011-2012 Jitse Niesen <jitse@maths.leeds.ac.uk>
  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. #ifndef EIGEN_COREEVALUATORS_H
  12. #define EIGEN_COREEVALUATORS_H
  13. namespace Eigen {
  14. namespace internal {
  15. // This class returns the evaluator kind from the expression storage kind.
  16. // Default assumes index based accessors
  17. template<typename StorageKind>
  18. struct storage_kind_to_evaluator_kind {
  19. typedef IndexBased Kind;
  20. };
  21. // This class returns the evaluator shape from the expression storage kind.
  22. // It can be Dense, Sparse, Triangular, Diagonal, SelfAdjoint, Band, etc.
  23. template<typename StorageKind> struct storage_kind_to_shape;
  24. template<> struct storage_kind_to_shape<Dense> { typedef DenseShape Shape; };
  25. template<> struct storage_kind_to_shape<SolverStorage> { typedef SolverShape Shape; };
  26. template<> struct storage_kind_to_shape<PermutationStorage> { typedef PermutationShape Shape; };
  27. template<> struct storage_kind_to_shape<TranspositionsStorage> { typedef TranspositionsShape Shape; };
  28. // Evaluators have to be specialized with respect to various criteria such as:
  29. // - storage/structure/shape
  30. // - scalar type
  31. // - etc.
  32. // Therefore, we need specialization of evaluator providing additional template arguments for each kind of evaluators.
  33. // We currently distinguish the following kind of evaluators:
  34. // - unary_evaluator for expressions taking only one arguments (CwiseUnaryOp, CwiseUnaryView, Transpose, MatrixWrapper, ArrayWrapper, Reverse, Replicate)
  35. // - binary_evaluator for expression taking two arguments (CwiseBinaryOp)
  36. // - ternary_evaluator for expression taking three arguments (CwiseTernaryOp)
  37. // - product_evaluator for linear algebra products (Product); special case of binary_evaluator because it requires additional tags for dispatching.
  38. // - mapbase_evaluator for Map, Block, Ref
  39. // - block_evaluator for Block (special dispatching to a mapbase_evaluator or unary_evaluator)
  40. template< typename T,
  41. typename Arg1Kind = typename evaluator_traits<typename T::Arg1>::Kind,
  42. typename Arg2Kind = typename evaluator_traits<typename T::Arg2>::Kind,
  43. typename Arg3Kind = typename evaluator_traits<typename T::Arg3>::Kind,
  44. typename Arg1Scalar = typename traits<typename T::Arg1>::Scalar,
  45. typename Arg2Scalar = typename traits<typename T::Arg2>::Scalar,
  46. typename Arg3Scalar = typename traits<typename T::Arg3>::Scalar> struct ternary_evaluator;
  47. template< typename T,
  48. typename LhsKind = typename evaluator_traits<typename T::Lhs>::Kind,
  49. typename RhsKind = typename evaluator_traits<typename T::Rhs>::Kind,
  50. typename LhsScalar = typename traits<typename T::Lhs>::Scalar,
  51. typename RhsScalar = typename traits<typename T::Rhs>::Scalar> struct binary_evaluator;
  52. template< typename T,
  53. typename Kind = typename evaluator_traits<typename T::NestedExpression>::Kind,
  54. typename Scalar = typename T::Scalar> struct unary_evaluator;
  55. // evaluator_traits<T> contains traits for evaluator<T>
  56. template<typename T>
  57. struct evaluator_traits_base
  58. {
  59. // by default, get evaluator kind and shape from storage
  60. typedef typename storage_kind_to_evaluator_kind<typename traits<T>::StorageKind>::Kind Kind;
  61. typedef typename storage_kind_to_shape<typename traits<T>::StorageKind>::Shape Shape;
  62. };
  63. // Default evaluator traits
  64. template<typename T>
  65. struct evaluator_traits : public evaluator_traits_base<T>
  66. {
  67. };
  68. template<typename T, typename Shape = typename evaluator_traits<T>::Shape >
  69. struct evaluator_assume_aliasing {
  70. static const bool value = false;
  71. };
  72. // By default, we assume a unary expression:
  73. template<typename T>
  74. struct evaluator : public unary_evaluator<T>
  75. {
  76. typedef unary_evaluator<T> Base;
  77. EIGEN_DEVICE_FUNC explicit evaluator(const T& xpr) : Base(xpr) {}
  78. };
  79. // TODO: Think about const-correctness
  80. template<typename T>
  81. struct evaluator<const T>
  82. : evaluator<T>
  83. {
  84. EIGEN_DEVICE_FUNC
  85. explicit evaluator(const T& xpr) : evaluator<T>(xpr) {}
  86. };
  87. // ---------- base class for all evaluators ----------
  88. template<typename ExpressionType>
  89. struct evaluator_base : public noncopyable
  90. {
  91. // TODO that's not very nice to have to propagate all these traits. They are currently only needed to handle outer,inner indices.
  92. typedef traits<ExpressionType> ExpressionTraits;
  93. enum {
  94. Alignment = 0
  95. };
  96. };
  97. // -------------------- Matrix and Array --------------------
  98. //
  99. // evaluator<PlainObjectBase> is a common base class for the
  100. // Matrix and Array evaluators.
  101. // Here we directly specialize evaluator. This is not really a unary expression, and it is, by definition, dense,
  102. // so no need for more sophisticated dispatching.
  103. template<typename Derived>
  104. struct evaluator<PlainObjectBase<Derived> >
  105. : evaluator_base<Derived>
  106. {
  107. typedef PlainObjectBase<Derived> PlainObjectType;
  108. typedef typename PlainObjectType::Scalar Scalar;
  109. typedef typename PlainObjectType::CoeffReturnType CoeffReturnType;
  110. enum {
  111. IsRowMajor = PlainObjectType::IsRowMajor,
  112. IsVectorAtCompileTime = PlainObjectType::IsVectorAtCompileTime,
  113. RowsAtCompileTime = PlainObjectType::RowsAtCompileTime,
  114. ColsAtCompileTime = PlainObjectType::ColsAtCompileTime,
  115. CoeffReadCost = NumTraits<Scalar>::ReadCost,
  116. Flags = traits<Derived>::EvaluatorFlags,
  117. Alignment = traits<Derived>::Alignment
  118. };
  119. EIGEN_DEVICE_FUNC evaluator()
  120. : m_data(0),
  121. m_outerStride(IsVectorAtCompileTime ? 0
  122. : int(IsRowMajor) ? ColsAtCompileTime
  123. : RowsAtCompileTime)
  124. {
  125. EIGEN_INTERNAL_CHECK_COST_VALUE(CoeffReadCost);
  126. }
  127. EIGEN_DEVICE_FUNC explicit evaluator(const PlainObjectType& m)
  128. : m_data(m.data()), m_outerStride(IsVectorAtCompileTime ? 0 : m.outerStride())
  129. {
  130. EIGEN_INTERNAL_CHECK_COST_VALUE(CoeffReadCost);
  131. }
  132. EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE
  133. CoeffReturnType coeff(Index row, Index col) const
  134. {
  135. if (IsRowMajor)
  136. return m_data[row * m_outerStride.value() + col];
  137. else
  138. return m_data[row + col * m_outerStride.value()];
  139. }
  140. EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE
  141. CoeffReturnType coeff(Index index) const
  142. {
  143. return m_data[index];
  144. }
  145. EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE
  146. Scalar& coeffRef(Index row, Index col)
  147. {
  148. if (IsRowMajor)
  149. return const_cast<Scalar*>(m_data)[row * m_outerStride.value() + col];
  150. else
  151. return const_cast<Scalar*>(m_data)[row + col * m_outerStride.value()];
  152. }
  153. EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE
  154. Scalar& coeffRef(Index index)
  155. {
  156. return const_cast<Scalar*>(m_data)[index];
  157. }
  158. template<int LoadMode, typename PacketType>
  159. EIGEN_STRONG_INLINE
  160. PacketType packet(Index row, Index col) const
  161. {
  162. if (IsRowMajor)
  163. return ploadt<PacketType, LoadMode>(m_data + row * m_outerStride.value() + col);
  164. else
  165. return ploadt<PacketType, LoadMode>(m_data + row + col * m_outerStride.value());
  166. }
  167. template<int LoadMode, typename PacketType>
  168. EIGEN_STRONG_INLINE
  169. PacketType packet(Index index) const
  170. {
  171. return ploadt<PacketType, LoadMode>(m_data + index);
  172. }
  173. template<int StoreMode,typename PacketType>
  174. EIGEN_STRONG_INLINE
  175. void writePacket(Index row, Index col, const PacketType& x)
  176. {
  177. if (IsRowMajor)
  178. return pstoret<Scalar, PacketType, StoreMode>
  179. (const_cast<Scalar*>(m_data) + row * m_outerStride.value() + col, x);
  180. else
  181. return pstoret<Scalar, PacketType, StoreMode>
  182. (const_cast<Scalar*>(m_data) + row + col * m_outerStride.value(), x);
  183. }
  184. template<int StoreMode, typename PacketType>
  185. EIGEN_STRONG_INLINE
  186. void writePacket(Index index, const PacketType& x)
  187. {
  188. return pstoret<Scalar, PacketType, StoreMode>(const_cast<Scalar*>(m_data) + index, x);
  189. }
  190. protected:
  191. const Scalar *m_data;
  192. // We do not need to know the outer stride for vectors
  193. variable_if_dynamic<Index, IsVectorAtCompileTime ? 0
  194. : int(IsRowMajor) ? ColsAtCompileTime
  195. : RowsAtCompileTime> m_outerStride;
  196. };
  197. template<typename Scalar, int Rows, int Cols, int Options, int MaxRows, int MaxCols>
  198. struct evaluator<Matrix<Scalar, Rows, Cols, Options, MaxRows, MaxCols> >
  199. : evaluator<PlainObjectBase<Matrix<Scalar, Rows, Cols, Options, MaxRows, MaxCols> > >
  200. {
  201. typedef Matrix<Scalar, Rows, Cols, Options, MaxRows, MaxCols> XprType;
  202. EIGEN_DEVICE_FUNC evaluator() {}
  203. EIGEN_DEVICE_FUNC explicit evaluator(const XprType& m)
  204. : evaluator<PlainObjectBase<XprType> >(m)
  205. { }
  206. };
  207. template<typename Scalar, int Rows, int Cols, int Options, int MaxRows, int MaxCols>
  208. struct evaluator<Array<Scalar, Rows, Cols, Options, MaxRows, MaxCols> >
  209. : evaluator<PlainObjectBase<Array<Scalar, Rows, Cols, Options, MaxRows, MaxCols> > >
  210. {
  211. typedef Array<Scalar, Rows, Cols, Options, MaxRows, MaxCols> XprType;
  212. EIGEN_DEVICE_FUNC evaluator() {}
  213. EIGEN_DEVICE_FUNC explicit evaluator(const XprType& m)
  214. : evaluator<PlainObjectBase<XprType> >(m)
  215. { }
  216. };
  217. // -------------------- Transpose --------------------
  218. template<typename ArgType>
  219. struct unary_evaluator<Transpose<ArgType>, IndexBased>
  220. : evaluator_base<Transpose<ArgType> >
  221. {
  222. typedef Transpose<ArgType> XprType;
  223. enum {
  224. CoeffReadCost = evaluator<ArgType>::CoeffReadCost,
  225. Flags = evaluator<ArgType>::Flags ^ RowMajorBit,
  226. Alignment = evaluator<ArgType>::Alignment
  227. };
  228. EIGEN_DEVICE_FUNC explicit unary_evaluator(const XprType& t) : m_argImpl(t.nestedExpression()) {}
  229. typedef typename XprType::Scalar Scalar;
  230. typedef typename XprType::CoeffReturnType CoeffReturnType;
  231. EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE
  232. CoeffReturnType coeff(Index row, Index col) const
  233. {
  234. return m_argImpl.coeff(col, row);
  235. }
  236. EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE
  237. CoeffReturnType coeff(Index index) const
  238. {
  239. return m_argImpl.coeff(index);
  240. }
  241. EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE
  242. Scalar& coeffRef(Index row, Index col)
  243. {
  244. return m_argImpl.coeffRef(col, row);
  245. }
  246. EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE
  247. typename XprType::Scalar& coeffRef(Index index)
  248. {
  249. return m_argImpl.coeffRef(index);
  250. }
  251. template<int LoadMode, typename PacketType>
  252. EIGEN_STRONG_INLINE
  253. PacketType packet(Index row, Index col) const
  254. {
  255. return m_argImpl.template packet<LoadMode,PacketType>(col, row);
  256. }
  257. template<int LoadMode, typename PacketType>
  258. EIGEN_STRONG_INLINE
  259. PacketType packet(Index index) const
  260. {
  261. return m_argImpl.template packet<LoadMode,PacketType>(index);
  262. }
  263. template<int StoreMode, typename PacketType>
  264. EIGEN_STRONG_INLINE
  265. void writePacket(Index row, Index col, const PacketType& x)
  266. {
  267. m_argImpl.template writePacket<StoreMode,PacketType>(col, row, x);
  268. }
  269. template<int StoreMode, typename PacketType>
  270. EIGEN_STRONG_INLINE
  271. void writePacket(Index index, const PacketType& x)
  272. {
  273. m_argImpl.template writePacket<StoreMode,PacketType>(index, x);
  274. }
  275. protected:
  276. evaluator<ArgType> m_argImpl;
  277. };
  278. // -------------------- CwiseNullaryOp --------------------
  279. // Like Matrix and Array, this is not really a unary expression, so we directly specialize evaluator.
  280. // Likewise, there is not need to more sophisticated dispatching here.
  281. template<typename Scalar,typename NullaryOp,
  282. bool has_nullary = has_nullary_operator<NullaryOp>::value,
  283. bool has_unary = has_unary_operator<NullaryOp>::value,
  284. bool has_binary = has_binary_operator<NullaryOp>::value>
  285. struct nullary_wrapper
  286. {
  287. template <typename IndexType>
  288. EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE Scalar operator()(const NullaryOp& op, IndexType i, IndexType j) const { return op(i,j); }
  289. template <typename IndexType>
  290. EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE Scalar operator()(const NullaryOp& op, IndexType i) const { return op(i); }
  291. template <typename T, typename IndexType> EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE T packetOp(const NullaryOp& op, IndexType i, IndexType j) const { return op.template packetOp<T>(i,j); }
  292. template <typename T, typename IndexType> EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE T packetOp(const NullaryOp& op, IndexType i) const { return op.template packetOp<T>(i); }
  293. };
  294. template<typename Scalar,typename NullaryOp>
  295. struct nullary_wrapper<Scalar,NullaryOp,true,false,false>
  296. {
  297. template <typename IndexType>
  298. EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE Scalar operator()(const NullaryOp& op, IndexType=0, IndexType=0) const { return op(); }
  299. template <typename T, typename IndexType> EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE T packetOp(const NullaryOp& op, IndexType=0, IndexType=0) const { return op.template packetOp<T>(); }
  300. };
  301. template<typename Scalar,typename NullaryOp>
  302. struct nullary_wrapper<Scalar,NullaryOp,false,false,true>
  303. {
  304. template <typename IndexType>
  305. EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE Scalar operator()(const NullaryOp& op, IndexType i, IndexType j=0) const { return op(i,j); }
  306. template <typename T, typename IndexType> EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE T packetOp(const NullaryOp& op, IndexType i, IndexType j=0) const { return op.template packetOp<T>(i,j); }
  307. };
  308. // We need the following specialization for vector-only functors assigned to a runtime vector,
  309. // for instance, using linspace and assigning a RowVectorXd to a MatrixXd or even a row of a MatrixXd.
  310. // In this case, i==0 and j is used for the actual iteration.
  311. template<typename Scalar,typename NullaryOp>
  312. struct nullary_wrapper<Scalar,NullaryOp,false,true,false>
  313. {
  314. template <typename IndexType>
  315. EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE Scalar operator()(const NullaryOp& op, IndexType i, IndexType j) const {
  316. eigen_assert(i==0 || j==0);
  317. return op(i+j);
  318. }
  319. template <typename T, typename IndexType> EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE T packetOp(const NullaryOp& op, IndexType i, IndexType j) const {
  320. eigen_assert(i==0 || j==0);
  321. return op.template packetOp<T>(i+j);
  322. }
  323. template <typename IndexType>
  324. EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE Scalar operator()(const NullaryOp& op, IndexType i) const { return op(i); }
  325. template <typename T, typename IndexType>
  326. EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE T packetOp(const NullaryOp& op, IndexType i) const { return op.template packetOp<T>(i); }
  327. };
  328. template<typename Scalar,typename NullaryOp>
  329. struct nullary_wrapper<Scalar,NullaryOp,false,false,false> {};
  330. #if 0 && EIGEN_COMP_MSVC>0
  331. // Disable this ugly workaround. This is now handled in traits<Ref>::match,
  332. // but this piece of code might still become handly if some other weird compilation
  333. // erros pop up again.
  334. // MSVC exhibits a weird compilation error when
  335. // compiling:
  336. // Eigen::MatrixXf A = MatrixXf::Random(3,3);
  337. // Ref<const MatrixXf> R = 2.f*A;
  338. // and that has_*ary_operator<scalar_constant_op<float>> have not been instantiated yet.
  339. // The "problem" is that evaluator<2.f*A> is instantiated by traits<Ref>::match<2.f*A>
  340. // and at that time has_*ary_operator<T> returns true regardless of T.
  341. // Then nullary_wrapper is badly instantiated as nullary_wrapper<.,.,true,true,true>.
  342. // The trick is thus to defer the proper instantiation of nullary_wrapper when coeff(),
  343. // and packet() are really instantiated as implemented below:
  344. // This is a simple wrapper around Index to enforce the re-instantiation of
  345. // has_*ary_operator when needed.
  346. template<typename T> struct nullary_wrapper_workaround_msvc {
  347. nullary_wrapper_workaround_msvc(const T&);
  348. operator T()const;
  349. };
  350. template<typename Scalar,typename NullaryOp>
  351. struct nullary_wrapper<Scalar,NullaryOp,true,true,true>
  352. {
  353. template <typename IndexType>
  354. EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE Scalar operator()(const NullaryOp& op, IndexType i, IndexType j) const {
  355. return nullary_wrapper<Scalar,NullaryOp,
  356. has_nullary_operator<NullaryOp,nullary_wrapper_workaround_msvc<IndexType> >::value,
  357. has_unary_operator<NullaryOp,nullary_wrapper_workaround_msvc<IndexType> >::value,
  358. has_binary_operator<NullaryOp,nullary_wrapper_workaround_msvc<IndexType> >::value>().operator()(op,i,j);
  359. }
  360. template <typename IndexType>
  361. EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE Scalar operator()(const NullaryOp& op, IndexType i) const {
  362. return nullary_wrapper<Scalar,NullaryOp,
  363. has_nullary_operator<NullaryOp,nullary_wrapper_workaround_msvc<IndexType> >::value,
  364. has_unary_operator<NullaryOp,nullary_wrapper_workaround_msvc<IndexType> >::value,
  365. has_binary_operator<NullaryOp,nullary_wrapper_workaround_msvc<IndexType> >::value>().operator()(op,i);
  366. }
  367. template <typename T, typename IndexType>
  368. EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE T packetOp(const NullaryOp& op, IndexType i, IndexType j) const {
  369. return nullary_wrapper<Scalar,NullaryOp,
  370. has_nullary_operator<NullaryOp,nullary_wrapper_workaround_msvc<IndexType> >::value,
  371. has_unary_operator<NullaryOp,nullary_wrapper_workaround_msvc<IndexType> >::value,
  372. has_binary_operator<NullaryOp,nullary_wrapper_workaround_msvc<IndexType> >::value>().template packetOp<T>(op,i,j);
  373. }
  374. template <typename T, typename IndexType>
  375. EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE T packetOp(const NullaryOp& op, IndexType i) const {
  376. return nullary_wrapper<Scalar,NullaryOp,
  377. has_nullary_operator<NullaryOp,nullary_wrapper_workaround_msvc<IndexType> >::value,
  378. has_unary_operator<NullaryOp,nullary_wrapper_workaround_msvc<IndexType> >::value,
  379. has_binary_operator<NullaryOp,nullary_wrapper_workaround_msvc<IndexType> >::value>().template packetOp<T>(op,i);
  380. }
  381. };
  382. #endif // MSVC workaround
  383. template<typename NullaryOp, typename PlainObjectType>
  384. struct evaluator<CwiseNullaryOp<NullaryOp,PlainObjectType> >
  385. : evaluator_base<CwiseNullaryOp<NullaryOp,PlainObjectType> >
  386. {
  387. typedef CwiseNullaryOp<NullaryOp,PlainObjectType> XprType;
  388. typedef typename internal::remove_all<PlainObjectType>::type PlainObjectTypeCleaned;
  389. enum {
  390. CoeffReadCost = internal::functor_traits<NullaryOp>::Cost,
  391. Flags = (evaluator<PlainObjectTypeCleaned>::Flags
  392. & ( HereditaryBits
  393. | (functor_has_linear_access<NullaryOp>::ret ? LinearAccessBit : 0)
  394. | (functor_traits<NullaryOp>::PacketAccess ? PacketAccessBit : 0)))
  395. | (functor_traits<NullaryOp>::IsRepeatable ? 0 : EvalBeforeNestingBit),
  396. Alignment = AlignedMax
  397. };
  398. EIGEN_DEVICE_FUNC explicit evaluator(const XprType& n)
  399. : m_functor(n.functor()), m_wrapper()
  400. {
  401. EIGEN_INTERNAL_CHECK_COST_VALUE(CoeffReadCost);
  402. }
  403. typedef typename XprType::CoeffReturnType CoeffReturnType;
  404. template <typename IndexType>
  405. EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE
  406. CoeffReturnType coeff(IndexType row, IndexType col) const
  407. {
  408. return m_wrapper(m_functor, row, col);
  409. }
  410. template <typename IndexType>
  411. EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE
  412. CoeffReturnType coeff(IndexType index) const
  413. {
  414. return m_wrapper(m_functor,index);
  415. }
  416. template<int LoadMode, typename PacketType, typename IndexType>
  417. EIGEN_STRONG_INLINE
  418. PacketType packet(IndexType row, IndexType col) const
  419. {
  420. return m_wrapper.template packetOp<PacketType>(m_functor, row, col);
  421. }
  422. template<int LoadMode, typename PacketType, typename IndexType>
  423. EIGEN_STRONG_INLINE
  424. PacketType packet(IndexType index) const
  425. {
  426. return m_wrapper.template packetOp<PacketType>(m_functor, index);
  427. }
  428. protected:
  429. const NullaryOp m_functor;
  430. const internal::nullary_wrapper<CoeffReturnType,NullaryOp> m_wrapper;
  431. };
  432. // -------------------- CwiseUnaryOp --------------------
  433. template<typename UnaryOp, typename ArgType>
  434. struct unary_evaluator<CwiseUnaryOp<UnaryOp, ArgType>, IndexBased >
  435. : evaluator_base<CwiseUnaryOp<UnaryOp, ArgType> >
  436. {
  437. typedef CwiseUnaryOp<UnaryOp, ArgType> XprType;
  438. enum {
  439. CoeffReadCost = evaluator<ArgType>::CoeffReadCost + functor_traits<UnaryOp>::Cost,
  440. Flags = evaluator<ArgType>::Flags
  441. & (HereditaryBits | LinearAccessBit | (functor_traits<UnaryOp>::PacketAccess ? PacketAccessBit : 0)),
  442. Alignment = evaluator<ArgType>::Alignment
  443. };
  444. EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE
  445. explicit unary_evaluator(const XprType& op)
  446. : m_functor(op.functor()),
  447. m_argImpl(op.nestedExpression())
  448. {
  449. EIGEN_INTERNAL_CHECK_COST_VALUE(functor_traits<UnaryOp>::Cost);
  450. EIGEN_INTERNAL_CHECK_COST_VALUE(CoeffReadCost);
  451. }
  452. typedef typename XprType::CoeffReturnType CoeffReturnType;
  453. EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE
  454. CoeffReturnType coeff(Index row, Index col) const
  455. {
  456. return m_functor(m_argImpl.coeff(row, col));
  457. }
  458. EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE
  459. CoeffReturnType coeff(Index index) const
  460. {
  461. return m_functor(m_argImpl.coeff(index));
  462. }
  463. template<int LoadMode, typename PacketType>
  464. EIGEN_STRONG_INLINE
  465. PacketType packet(Index row, Index col) const
  466. {
  467. return m_functor.packetOp(m_argImpl.template packet<LoadMode, PacketType>(row, col));
  468. }
  469. template<int LoadMode, typename PacketType>
  470. EIGEN_STRONG_INLINE
  471. PacketType packet(Index index) const
  472. {
  473. return m_functor.packetOp(m_argImpl.template packet<LoadMode, PacketType>(index));
  474. }
  475. protected:
  476. const UnaryOp m_functor;
  477. evaluator<ArgType> m_argImpl;
  478. };
  479. // -------------------- CwiseTernaryOp --------------------
  480. // this is a ternary expression
  481. template<typename TernaryOp, typename Arg1, typename Arg2, typename Arg3>
  482. struct evaluator<CwiseTernaryOp<TernaryOp, Arg1, Arg2, Arg3> >
  483. : public ternary_evaluator<CwiseTernaryOp<TernaryOp, Arg1, Arg2, Arg3> >
  484. {
  485. typedef CwiseTernaryOp<TernaryOp, Arg1, Arg2, Arg3> XprType;
  486. typedef ternary_evaluator<CwiseTernaryOp<TernaryOp, Arg1, Arg2, Arg3> > Base;
  487. EIGEN_DEVICE_FUNC explicit evaluator(const XprType& xpr) : Base(xpr) {}
  488. };
  489. template<typename TernaryOp, typename Arg1, typename Arg2, typename Arg3>
  490. struct ternary_evaluator<CwiseTernaryOp<TernaryOp, Arg1, Arg2, Arg3>, IndexBased, IndexBased>
  491. : evaluator_base<CwiseTernaryOp<TernaryOp, Arg1, Arg2, Arg3> >
  492. {
  493. typedef CwiseTernaryOp<TernaryOp, Arg1, Arg2, Arg3> XprType;
  494. enum {
  495. CoeffReadCost = evaluator<Arg1>::CoeffReadCost + evaluator<Arg2>::CoeffReadCost + evaluator<Arg3>::CoeffReadCost + functor_traits<TernaryOp>::Cost,
  496. Arg1Flags = evaluator<Arg1>::Flags,
  497. Arg2Flags = evaluator<Arg2>::Flags,
  498. Arg3Flags = evaluator<Arg3>::Flags,
  499. SameType = is_same<typename Arg1::Scalar,typename Arg2::Scalar>::value && is_same<typename Arg1::Scalar,typename Arg3::Scalar>::value,
  500. StorageOrdersAgree = (int(Arg1Flags)&RowMajorBit)==(int(Arg2Flags)&RowMajorBit) && (int(Arg1Flags)&RowMajorBit)==(int(Arg3Flags)&RowMajorBit),
  501. Flags0 = (int(Arg1Flags) | int(Arg2Flags) | int(Arg3Flags)) & (
  502. HereditaryBits
  503. | (int(Arg1Flags) & int(Arg2Flags) & int(Arg3Flags) &
  504. ( (StorageOrdersAgree ? LinearAccessBit : 0)
  505. | (functor_traits<TernaryOp>::PacketAccess && StorageOrdersAgree && SameType ? PacketAccessBit : 0)
  506. )
  507. )
  508. ),
  509. Flags = (Flags0 & ~RowMajorBit) | (Arg1Flags & RowMajorBit),
  510. Alignment = EIGEN_PLAIN_ENUM_MIN(
  511. EIGEN_PLAIN_ENUM_MIN(evaluator<Arg1>::Alignment, evaluator<Arg2>::Alignment),
  512. evaluator<Arg3>::Alignment)
  513. };
  514. EIGEN_DEVICE_FUNC explicit ternary_evaluator(const XprType& xpr)
  515. : m_functor(xpr.functor()),
  516. m_arg1Impl(xpr.arg1()),
  517. m_arg2Impl(xpr.arg2()),
  518. m_arg3Impl(xpr.arg3())
  519. {
  520. EIGEN_INTERNAL_CHECK_COST_VALUE(functor_traits<TernaryOp>::Cost);
  521. EIGEN_INTERNAL_CHECK_COST_VALUE(CoeffReadCost);
  522. }
  523. typedef typename XprType::CoeffReturnType CoeffReturnType;
  524. EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE
  525. CoeffReturnType coeff(Index row, Index col) const
  526. {
  527. return m_functor(m_arg1Impl.coeff(row, col), m_arg2Impl.coeff(row, col), m_arg3Impl.coeff(row, col));
  528. }
  529. EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE
  530. CoeffReturnType coeff(Index index) const
  531. {
  532. return m_functor(m_arg1Impl.coeff(index), m_arg2Impl.coeff(index), m_arg3Impl.coeff(index));
  533. }
  534. template<int LoadMode, typename PacketType>
  535. EIGEN_STRONG_INLINE
  536. PacketType packet(Index row, Index col) const
  537. {
  538. return m_functor.packetOp(m_arg1Impl.template packet<LoadMode,PacketType>(row, col),
  539. m_arg2Impl.template packet<LoadMode,PacketType>(row, col),
  540. m_arg3Impl.template packet<LoadMode,PacketType>(row, col));
  541. }
  542. template<int LoadMode, typename PacketType>
  543. EIGEN_STRONG_INLINE
  544. PacketType packet(Index index) const
  545. {
  546. return m_functor.packetOp(m_arg1Impl.template packet<LoadMode,PacketType>(index),
  547. m_arg2Impl.template packet<LoadMode,PacketType>(index),
  548. m_arg3Impl.template packet<LoadMode,PacketType>(index));
  549. }
  550. protected:
  551. const TernaryOp m_functor;
  552. evaluator<Arg1> m_arg1Impl;
  553. evaluator<Arg2> m_arg2Impl;
  554. evaluator<Arg3> m_arg3Impl;
  555. };
  556. // -------------------- CwiseBinaryOp --------------------
  557. // this is a binary expression
  558. template<typename BinaryOp, typename Lhs, typename Rhs>
  559. struct evaluator<CwiseBinaryOp<BinaryOp, Lhs, Rhs> >
  560. : public binary_evaluator<CwiseBinaryOp<BinaryOp, Lhs, Rhs> >
  561. {
  562. typedef CwiseBinaryOp<BinaryOp, Lhs, Rhs> XprType;
  563. typedef binary_evaluator<CwiseBinaryOp<BinaryOp, Lhs, Rhs> > Base;
  564. EIGEN_DEVICE_FUNC explicit evaluator(const XprType& xpr) : Base(xpr) {}
  565. };
  566. template<typename BinaryOp, typename Lhs, typename Rhs>
  567. struct binary_evaluator<CwiseBinaryOp<BinaryOp, Lhs, Rhs>, IndexBased, IndexBased>
  568. : evaluator_base<CwiseBinaryOp<BinaryOp, Lhs, Rhs> >
  569. {
  570. typedef CwiseBinaryOp<BinaryOp, Lhs, Rhs> XprType;
  571. enum {
  572. CoeffReadCost = evaluator<Lhs>::CoeffReadCost + evaluator<Rhs>::CoeffReadCost + functor_traits<BinaryOp>::Cost,
  573. LhsFlags = evaluator<Lhs>::Flags,
  574. RhsFlags = evaluator<Rhs>::Flags,
  575. SameType = is_same<typename Lhs::Scalar,typename Rhs::Scalar>::value,
  576. StorageOrdersAgree = (int(LhsFlags)&RowMajorBit)==(int(RhsFlags)&RowMajorBit),
  577. Flags0 = (int(LhsFlags) | int(RhsFlags)) & (
  578. HereditaryBits
  579. | (int(LhsFlags) & int(RhsFlags) &
  580. ( (StorageOrdersAgree ? LinearAccessBit : 0)
  581. | (functor_traits<BinaryOp>::PacketAccess && StorageOrdersAgree && SameType ? PacketAccessBit : 0)
  582. )
  583. )
  584. ),
  585. Flags = (Flags0 & ~RowMajorBit) | (LhsFlags & RowMajorBit),
  586. Alignment = EIGEN_PLAIN_ENUM_MIN(evaluator<Lhs>::Alignment,evaluator<Rhs>::Alignment)
  587. };
  588. EIGEN_DEVICE_FUNC explicit binary_evaluator(const XprType& xpr)
  589. : m_functor(xpr.functor()),
  590. m_lhsImpl(xpr.lhs()),
  591. m_rhsImpl(xpr.rhs())
  592. {
  593. EIGEN_INTERNAL_CHECK_COST_VALUE(functor_traits<BinaryOp>::Cost);
  594. EIGEN_INTERNAL_CHECK_COST_VALUE(CoeffReadCost);
  595. }
  596. typedef typename XprType::CoeffReturnType CoeffReturnType;
  597. EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE
  598. CoeffReturnType coeff(Index row, Index col) const
  599. {
  600. return m_functor(m_lhsImpl.coeff(row, col), m_rhsImpl.coeff(row, col));
  601. }
  602. EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE
  603. CoeffReturnType coeff(Index index) const
  604. {
  605. return m_functor(m_lhsImpl.coeff(index), m_rhsImpl.coeff(index));
  606. }
  607. template<int LoadMode, typename PacketType>
  608. EIGEN_STRONG_INLINE
  609. PacketType packet(Index row, Index col) const
  610. {
  611. return m_functor.packetOp(m_lhsImpl.template packet<LoadMode,PacketType>(row, col),
  612. m_rhsImpl.template packet<LoadMode,PacketType>(row, col));
  613. }
  614. template<int LoadMode, typename PacketType>
  615. EIGEN_STRONG_INLINE
  616. PacketType packet(Index index) const
  617. {
  618. return m_functor.packetOp(m_lhsImpl.template packet<LoadMode,PacketType>(index),
  619. m_rhsImpl.template packet<LoadMode,PacketType>(index));
  620. }
  621. protected:
  622. const BinaryOp m_functor;
  623. evaluator<Lhs> m_lhsImpl;
  624. evaluator<Rhs> m_rhsImpl;
  625. };
  626. // -------------------- CwiseUnaryView --------------------
  627. template<typename UnaryOp, typename ArgType>
  628. struct unary_evaluator<CwiseUnaryView<UnaryOp, ArgType>, IndexBased>
  629. : evaluator_base<CwiseUnaryView<UnaryOp, ArgType> >
  630. {
  631. typedef CwiseUnaryView<UnaryOp, ArgType> XprType;
  632. enum {
  633. CoeffReadCost = evaluator<ArgType>::CoeffReadCost + functor_traits<UnaryOp>::Cost,
  634. Flags = (evaluator<ArgType>::Flags & (HereditaryBits | LinearAccessBit | DirectAccessBit)),
  635. Alignment = 0 // FIXME it is not very clear why alignment is necessarily lost...
  636. };
  637. EIGEN_DEVICE_FUNC explicit unary_evaluator(const XprType& op)
  638. : m_unaryOp(op.functor()),
  639. m_argImpl(op.nestedExpression())
  640. {
  641. EIGEN_INTERNAL_CHECK_COST_VALUE(functor_traits<UnaryOp>::Cost);
  642. EIGEN_INTERNAL_CHECK_COST_VALUE(CoeffReadCost);
  643. }
  644. typedef typename XprType::Scalar Scalar;
  645. typedef typename XprType::CoeffReturnType CoeffReturnType;
  646. EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE
  647. CoeffReturnType coeff(Index row, Index col) const
  648. {
  649. return m_unaryOp(m_argImpl.coeff(row, col));
  650. }
  651. EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE
  652. CoeffReturnType coeff(Index index) const
  653. {
  654. return m_unaryOp(m_argImpl.coeff(index));
  655. }
  656. EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE
  657. Scalar& coeffRef(Index row, Index col)
  658. {
  659. return m_unaryOp(m_argImpl.coeffRef(row, col));
  660. }
  661. EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE
  662. Scalar& coeffRef(Index index)
  663. {
  664. return m_unaryOp(m_argImpl.coeffRef(index));
  665. }
  666. protected:
  667. const UnaryOp m_unaryOp;
  668. evaluator<ArgType> m_argImpl;
  669. };
  670. // -------------------- Map --------------------
  671. // FIXME perhaps the PlainObjectType could be provided by Derived::PlainObject ?
  672. // but that might complicate template specialization
  673. template<typename Derived, typename PlainObjectType>
  674. struct mapbase_evaluator;
  675. template<typename Derived, typename PlainObjectType>
  676. struct mapbase_evaluator : evaluator_base<Derived>
  677. {
  678. typedef Derived XprType;
  679. typedef typename XprType::PointerType PointerType;
  680. typedef typename XprType::Scalar Scalar;
  681. typedef typename XprType::CoeffReturnType CoeffReturnType;
  682. enum {
  683. IsRowMajor = XprType::RowsAtCompileTime,
  684. ColsAtCompileTime = XprType::ColsAtCompileTime,
  685. CoeffReadCost = NumTraits<Scalar>::ReadCost
  686. };
  687. EIGEN_DEVICE_FUNC explicit mapbase_evaluator(const XprType& map)
  688. : m_data(const_cast<PointerType>(map.data())),
  689. m_innerStride(map.innerStride()),
  690. m_outerStride(map.outerStride())
  691. {
  692. EIGEN_STATIC_ASSERT(EIGEN_IMPLIES(evaluator<Derived>::Flags&PacketAccessBit, internal::inner_stride_at_compile_time<Derived>::ret==1),
  693. PACKET_ACCESS_REQUIRES_TO_HAVE_INNER_STRIDE_FIXED_TO_1);
  694. EIGEN_INTERNAL_CHECK_COST_VALUE(CoeffReadCost);
  695. }
  696. EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE
  697. CoeffReturnType coeff(Index row, Index col) const
  698. {
  699. return m_data[col * colStride() + row * rowStride()];
  700. }
  701. EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE
  702. CoeffReturnType coeff(Index index) const
  703. {
  704. return m_data[index * m_innerStride.value()];
  705. }
  706. EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE
  707. Scalar& coeffRef(Index row, Index col)
  708. {
  709. return m_data[col * colStride() + row * rowStride()];
  710. }
  711. EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE
  712. Scalar& coeffRef(Index index)
  713. {
  714. return m_data[index * m_innerStride.value()];
  715. }
  716. template<int LoadMode, typename PacketType>
  717. EIGEN_STRONG_INLINE
  718. PacketType packet(Index row, Index col) const
  719. {
  720. PointerType ptr = m_data + row * rowStride() + col * colStride();
  721. return internal::ploadt<PacketType, LoadMode>(ptr);
  722. }
  723. template<int LoadMode, typename PacketType>
  724. EIGEN_STRONG_INLINE
  725. PacketType packet(Index index) const
  726. {
  727. return internal::ploadt<PacketType, LoadMode>(m_data + index * m_innerStride.value());
  728. }
  729. template<int StoreMode, typename PacketType>
  730. EIGEN_STRONG_INLINE
  731. void writePacket(Index row, Index col, const PacketType& x)
  732. {
  733. PointerType ptr = m_data + row * rowStride() + col * colStride();
  734. return internal::pstoret<Scalar, PacketType, StoreMode>(ptr, x);
  735. }
  736. template<int StoreMode, typename PacketType>
  737. EIGEN_STRONG_INLINE
  738. void writePacket(Index index, const PacketType& x)
  739. {
  740. internal::pstoret<Scalar, PacketType, StoreMode>(m_data + index * m_innerStride.value(), x);
  741. }
  742. protected:
  743. EIGEN_DEVICE_FUNC
  744. inline Index rowStride() const { return XprType::IsRowMajor ? m_outerStride.value() : m_innerStride.value(); }
  745. EIGEN_DEVICE_FUNC
  746. inline Index colStride() const { return XprType::IsRowMajor ? m_innerStride.value() : m_outerStride.value(); }
  747. PointerType m_data;
  748. const internal::variable_if_dynamic<Index, XprType::InnerStrideAtCompileTime> m_innerStride;
  749. const internal::variable_if_dynamic<Index, XprType::OuterStrideAtCompileTime> m_outerStride;
  750. };
  751. template<typename PlainObjectType, int MapOptions, typename StrideType>
  752. struct evaluator<Map<PlainObjectType, MapOptions, StrideType> >
  753. : public mapbase_evaluator<Map<PlainObjectType, MapOptions, StrideType>, PlainObjectType>
  754. {
  755. typedef Map<PlainObjectType, MapOptions, StrideType> XprType;
  756. typedef typename XprType::Scalar Scalar;
  757. // TODO: should check for smaller packet types once we can handle multi-sized packet types
  758. typedef typename packet_traits<Scalar>::type PacketScalar;
  759. enum {
  760. InnerStrideAtCompileTime = StrideType::InnerStrideAtCompileTime == 0
  761. ? int(PlainObjectType::InnerStrideAtCompileTime)
  762. : int(StrideType::InnerStrideAtCompileTime),
  763. OuterStrideAtCompileTime = StrideType::OuterStrideAtCompileTime == 0
  764. ? int(PlainObjectType::OuterStrideAtCompileTime)
  765. : int(StrideType::OuterStrideAtCompileTime),
  766. HasNoInnerStride = InnerStrideAtCompileTime == 1,
  767. HasNoOuterStride = StrideType::OuterStrideAtCompileTime == 0,
  768. HasNoStride = HasNoInnerStride && HasNoOuterStride,
  769. IsDynamicSize = PlainObjectType::SizeAtCompileTime==Dynamic,
  770. PacketAccessMask = bool(HasNoInnerStride) ? ~int(0) : ~int(PacketAccessBit),
  771. LinearAccessMask = bool(HasNoStride) || bool(PlainObjectType::IsVectorAtCompileTime) ? ~int(0) : ~int(LinearAccessBit),
  772. Flags = int( evaluator<PlainObjectType>::Flags) & (LinearAccessMask&PacketAccessMask),
  773. Alignment = int(MapOptions)&int(AlignedMask)
  774. };
  775. EIGEN_DEVICE_FUNC explicit evaluator(const XprType& map)
  776. : mapbase_evaluator<XprType, PlainObjectType>(map)
  777. { }
  778. };
  779. // -------------------- Ref --------------------
  780. template<typename PlainObjectType, int RefOptions, typename StrideType>
  781. struct evaluator<Ref<PlainObjectType, RefOptions, StrideType> >
  782. : public mapbase_evaluator<Ref<PlainObjectType, RefOptions, StrideType>, PlainObjectType>
  783. {
  784. typedef Ref<PlainObjectType, RefOptions, StrideType> XprType;
  785. enum {
  786. Flags = evaluator<Map<PlainObjectType, RefOptions, StrideType> >::Flags,
  787. Alignment = evaluator<Map<PlainObjectType, RefOptions, StrideType> >::Alignment
  788. };
  789. EIGEN_DEVICE_FUNC explicit evaluator(const XprType& ref)
  790. : mapbase_evaluator<XprType, PlainObjectType>(ref)
  791. { }
  792. };
  793. // -------------------- Block --------------------
  794. template<typename ArgType, int BlockRows, int BlockCols, bool InnerPanel,
  795. bool HasDirectAccess = internal::has_direct_access<ArgType>::ret> struct block_evaluator;
  796. template<typename ArgType, int BlockRows, int BlockCols, bool InnerPanel>
  797. struct evaluator<Block<ArgType, BlockRows, BlockCols, InnerPanel> >
  798. : block_evaluator<ArgType, BlockRows, BlockCols, InnerPanel>
  799. {
  800. typedef Block<ArgType, BlockRows, BlockCols, InnerPanel> XprType;
  801. typedef typename XprType::Scalar Scalar;
  802. // TODO: should check for smaller packet types once we can handle multi-sized packet types
  803. typedef typename packet_traits<Scalar>::type PacketScalar;
  804. enum {
  805. CoeffReadCost = evaluator<ArgType>::CoeffReadCost,
  806. RowsAtCompileTime = traits<XprType>::RowsAtCompileTime,
  807. ColsAtCompileTime = traits<XprType>::ColsAtCompileTime,
  808. MaxRowsAtCompileTime = traits<XprType>::MaxRowsAtCompileTime,
  809. MaxColsAtCompileTime = traits<XprType>::MaxColsAtCompileTime,
  810. ArgTypeIsRowMajor = (int(evaluator<ArgType>::Flags)&RowMajorBit) != 0,
  811. IsRowMajor = (MaxRowsAtCompileTime==1 && MaxColsAtCompileTime!=1) ? 1
  812. : (MaxColsAtCompileTime==1 && MaxRowsAtCompileTime!=1) ? 0
  813. : ArgTypeIsRowMajor,
  814. HasSameStorageOrderAsArgType = (IsRowMajor == ArgTypeIsRowMajor),
  815. InnerSize = IsRowMajor ? int(ColsAtCompileTime) : int(RowsAtCompileTime),
  816. InnerStrideAtCompileTime = HasSameStorageOrderAsArgType
  817. ? int(inner_stride_at_compile_time<ArgType>::ret)
  818. : int(outer_stride_at_compile_time<ArgType>::ret),
  819. OuterStrideAtCompileTime = HasSameStorageOrderAsArgType
  820. ? int(outer_stride_at_compile_time<ArgType>::ret)
  821. : int(inner_stride_at_compile_time<ArgType>::ret),
  822. MaskPacketAccessBit = (InnerStrideAtCompileTime == 1 || HasSameStorageOrderAsArgType) ? PacketAccessBit : 0,
  823. FlagsLinearAccessBit = (RowsAtCompileTime == 1 || ColsAtCompileTime == 1 || (InnerPanel && (evaluator<ArgType>::Flags&LinearAccessBit))) ? LinearAccessBit : 0,
  824. FlagsRowMajorBit = XprType::Flags&RowMajorBit,
  825. Flags0 = evaluator<ArgType>::Flags & ( (HereditaryBits & ~RowMajorBit) |
  826. DirectAccessBit |
  827. MaskPacketAccessBit),
  828. Flags = Flags0 | FlagsLinearAccessBit | FlagsRowMajorBit,
  829. PacketAlignment = unpacket_traits<PacketScalar>::alignment,
  830. Alignment0 = (InnerPanel && (OuterStrideAtCompileTime!=Dynamic)
  831. && (OuterStrideAtCompileTime!=0)
  832. && (((OuterStrideAtCompileTime * int(sizeof(Scalar))) % int(PacketAlignment)) == 0)) ? int(PacketAlignment) : 0,
  833. Alignment = EIGEN_PLAIN_ENUM_MIN(evaluator<ArgType>::Alignment, Alignment0)
  834. };
  835. typedef block_evaluator<ArgType, BlockRows, BlockCols, InnerPanel> block_evaluator_type;
  836. EIGEN_DEVICE_FUNC explicit evaluator(const XprType& block) : block_evaluator_type(block)
  837. {
  838. EIGEN_INTERNAL_CHECK_COST_VALUE(CoeffReadCost);
  839. }
  840. };
  841. // no direct-access => dispatch to a unary evaluator
  842. template<typename ArgType, int BlockRows, int BlockCols, bool InnerPanel>
  843. struct block_evaluator<ArgType, BlockRows, BlockCols, InnerPanel, /*HasDirectAccess*/ false>
  844. : unary_evaluator<Block<ArgType, BlockRows, BlockCols, InnerPanel> >
  845. {
  846. typedef Block<ArgType, BlockRows, BlockCols, InnerPanel> XprType;
  847. EIGEN_DEVICE_FUNC explicit block_evaluator(const XprType& block)
  848. : unary_evaluator<XprType>(block)
  849. {}
  850. };
  851. template<typename ArgType, int BlockRows, int BlockCols, bool InnerPanel>
  852. struct unary_evaluator<Block<ArgType, BlockRows, BlockCols, InnerPanel>, IndexBased>
  853. : evaluator_base<Block<ArgType, BlockRows, BlockCols, InnerPanel> >
  854. {
  855. typedef Block<ArgType, BlockRows, BlockCols, InnerPanel> XprType;
  856. EIGEN_DEVICE_FUNC explicit unary_evaluator(const XprType& block)
  857. : m_argImpl(block.nestedExpression()),
  858. m_startRow(block.startRow()),
  859. m_startCol(block.startCol()),
  860. m_linear_offset(InnerPanel?(XprType::IsRowMajor ? block.startRow()*block.cols() : block.startCol()*block.rows()):0)
  861. { }
  862. typedef typename XprType::Scalar Scalar;
  863. typedef typename XprType::CoeffReturnType CoeffReturnType;
  864. enum {
  865. RowsAtCompileTime = XprType::RowsAtCompileTime,
  866. ForwardLinearAccess = InnerPanel && bool(evaluator<ArgType>::Flags&LinearAccessBit)
  867. };
  868. EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE
  869. CoeffReturnType coeff(Index row, Index col) const
  870. {
  871. return m_argImpl.coeff(m_startRow.value() + row, m_startCol.value() + col);
  872. }
  873. EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE
  874. CoeffReturnType coeff(Index index) const
  875. {
  876. if (ForwardLinearAccess)
  877. return m_argImpl.coeff(m_linear_offset.value() + index);
  878. else
  879. return coeff(RowsAtCompileTime == 1 ? 0 : index, RowsAtCompileTime == 1 ? index : 0);
  880. }
  881. EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE
  882. Scalar& coeffRef(Index row, Index col)
  883. {
  884. return m_argImpl.coeffRef(m_startRow.value() + row, m_startCol.value() + col);
  885. }
  886. EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE
  887. Scalar& coeffRef(Index index)
  888. {
  889. if (ForwardLinearAccess)
  890. return m_argImpl.coeffRef(m_linear_offset.value() + index);
  891. else
  892. return coeffRef(RowsAtCompileTime == 1 ? 0 : index, RowsAtCompileTime == 1 ? index : 0);
  893. }
  894. template<int LoadMode, typename PacketType>
  895. EIGEN_STRONG_INLINE
  896. PacketType packet(Index row, Index col) const
  897. {
  898. return m_argImpl.template packet<LoadMode,PacketType>(m_startRow.value() + row, m_startCol.value() + col);
  899. }
  900. template<int LoadMode, typename PacketType>
  901. EIGEN_STRONG_INLINE
  902. PacketType packet(Index index) const
  903. {
  904. if (ForwardLinearAccess)
  905. return m_argImpl.template packet<LoadMode,PacketType>(m_linear_offset.value() + index);
  906. else
  907. return packet<LoadMode,PacketType>(RowsAtCompileTime == 1 ? 0 : index,
  908. RowsAtCompileTime == 1 ? index : 0);
  909. }
  910. template<int StoreMode, typename PacketType>
  911. EIGEN_STRONG_INLINE
  912. void writePacket(Index row, Index col, const PacketType& x)
  913. {
  914. return m_argImpl.template writePacket<StoreMode,PacketType>(m_startRow.value() + row, m_startCol.value() + col, x);
  915. }
  916. template<int StoreMode, typename PacketType>
  917. EIGEN_STRONG_INLINE
  918. void writePacket(Index index, const PacketType& x)
  919. {
  920. if (ForwardLinearAccess)
  921. return m_argImpl.template writePacket<StoreMode,PacketType>(m_linear_offset.value() + index, x);
  922. else
  923. return writePacket<StoreMode,PacketType>(RowsAtCompileTime == 1 ? 0 : index,
  924. RowsAtCompileTime == 1 ? index : 0,
  925. x);
  926. }
  927. protected:
  928. evaluator<ArgType> m_argImpl;
  929. const variable_if_dynamic<Index, (ArgType::RowsAtCompileTime == 1 && BlockRows==1) ? 0 : Dynamic> m_startRow;
  930. const variable_if_dynamic<Index, (ArgType::ColsAtCompileTime == 1 && BlockCols==1) ? 0 : Dynamic> m_startCol;
  931. const variable_if_dynamic<Index, InnerPanel ? Dynamic : 0> m_linear_offset;
  932. };
  933. // TODO: This evaluator does not actually use the child evaluator;
  934. // all action is via the data() as returned by the Block expression.
  935. template<typename ArgType, int BlockRows, int BlockCols, bool InnerPanel>
  936. struct block_evaluator<ArgType, BlockRows, BlockCols, InnerPanel, /* HasDirectAccess */ true>
  937. : mapbase_evaluator<Block<ArgType, BlockRows, BlockCols, InnerPanel>,
  938. typename Block<ArgType, BlockRows, BlockCols, InnerPanel>::PlainObject>
  939. {
  940. typedef Block<ArgType, BlockRows, BlockCols, InnerPanel> XprType;
  941. typedef typename XprType::Scalar Scalar;
  942. EIGEN_DEVICE_FUNC explicit block_evaluator(const XprType& block)
  943. : mapbase_evaluator<XprType, typename XprType::PlainObject>(block)
  944. {
  945. // TODO: for the 3.3 release, this should be turned to an internal assertion, but let's keep it as is for the beta lifetime
  946. eigen_assert(((internal::UIntPtr(block.data()) % EIGEN_PLAIN_ENUM_MAX(1,evaluator<XprType>::Alignment)) == 0) && "data is not aligned");
  947. }
  948. };
  949. // -------------------- Select --------------------
  950. // NOTE shall we introduce a ternary_evaluator?
  951. // TODO enable vectorization for Select
  952. template<typename ConditionMatrixType, typename ThenMatrixType, typename ElseMatrixType>
  953. struct evaluator<Select<ConditionMatrixType, ThenMatrixType, ElseMatrixType> >
  954. : evaluator_base<Select<ConditionMatrixType, ThenMatrixType, ElseMatrixType> >
  955. {
  956. typedef Select<ConditionMatrixType, ThenMatrixType, ElseMatrixType> XprType;
  957. enum {
  958. CoeffReadCost = evaluator<ConditionMatrixType>::CoeffReadCost
  959. + EIGEN_PLAIN_ENUM_MAX(evaluator<ThenMatrixType>::CoeffReadCost,
  960. evaluator<ElseMatrixType>::CoeffReadCost),
  961. Flags = (unsigned int)evaluator<ThenMatrixType>::Flags & evaluator<ElseMatrixType>::Flags & HereditaryBits,
  962. Alignment = EIGEN_PLAIN_ENUM_MIN(evaluator<ThenMatrixType>::Alignment, evaluator<ElseMatrixType>::Alignment)
  963. };
  964. EIGEN_DEVICE_FUNC explicit evaluator(const XprType& select)
  965. : m_conditionImpl(select.conditionMatrix()),
  966. m_thenImpl(select.thenMatrix()),
  967. m_elseImpl(select.elseMatrix())
  968. {
  969. EIGEN_INTERNAL_CHECK_COST_VALUE(CoeffReadCost);
  970. }
  971. typedef typename XprType::CoeffReturnType CoeffReturnType;
  972. EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE
  973. CoeffReturnType coeff(Index row, Index col) const
  974. {
  975. if (m_conditionImpl.coeff(row, col))
  976. return m_thenImpl.coeff(row, col);
  977. else
  978. return m_elseImpl.coeff(row, col);
  979. }
  980. EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE
  981. CoeffReturnType coeff(Index index) const
  982. {
  983. if (m_conditionImpl.coeff(index))
  984. return m_thenImpl.coeff(index);
  985. else
  986. return m_elseImpl.coeff(index);
  987. }
  988. protected:
  989. evaluator<ConditionMatrixType> m_conditionImpl;
  990. evaluator<ThenMatrixType> m_thenImpl;
  991. evaluator<ElseMatrixType> m_elseImpl;
  992. };
  993. // -------------------- Replicate --------------------
  994. template<typename ArgType, int RowFactor, int ColFactor>
  995. struct unary_evaluator<Replicate<ArgType, RowFactor, ColFactor> >
  996. : evaluator_base<Replicate<ArgType, RowFactor, ColFactor> >
  997. {
  998. typedef Replicate<ArgType, RowFactor, ColFactor> XprType;
  999. typedef typename XprType::CoeffReturnType CoeffReturnType;
  1000. enum {
  1001. Factor = (RowFactor==Dynamic || ColFactor==Dynamic) ? Dynamic : RowFactor*ColFactor
  1002. };
  1003. typedef typename internal::nested_eval<ArgType,Factor>::type ArgTypeNested;
  1004. typedef typename internal::remove_all<ArgTypeNested>::type ArgTypeNestedCleaned;
  1005. enum {
  1006. CoeffReadCost = evaluator<ArgTypeNestedCleaned>::CoeffReadCost,
  1007. LinearAccessMask = XprType::IsVectorAtCompileTime ? LinearAccessBit : 0,
  1008. Flags = (evaluator<ArgTypeNestedCleaned>::Flags & (HereditaryBits|LinearAccessMask) & ~RowMajorBit) | (traits<XprType>::Flags & RowMajorBit),
  1009. Alignment = evaluator<ArgTypeNestedCleaned>::Alignment
  1010. };
  1011. EIGEN_DEVICE_FUNC explicit unary_evaluator(const XprType& replicate)
  1012. : m_arg(replicate.nestedExpression()),
  1013. m_argImpl(m_arg),
  1014. m_rows(replicate.nestedExpression().rows()),
  1015. m_cols(replicate.nestedExpression().cols())
  1016. {}
  1017. EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE
  1018. CoeffReturnType coeff(Index row, Index col) const
  1019. {
  1020. // try to avoid using modulo; this is a pure optimization strategy
  1021. const Index actual_row = internal::traits<XprType>::RowsAtCompileTime==1 ? 0
  1022. : RowFactor==1 ? row
  1023. : row % m_rows.value();
  1024. const Index actual_col = internal::traits<XprType>::ColsAtCompileTime==1 ? 0
  1025. : ColFactor==1 ? col
  1026. : col % m_cols.value();
  1027. return m_argImpl.coeff(actual_row, actual_col);
  1028. }
  1029. EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE
  1030. CoeffReturnType coeff(Index index) const
  1031. {
  1032. // try to avoid using modulo; this is a pure optimization strategy
  1033. const Index actual_index = internal::traits<XprType>::RowsAtCompileTime==1
  1034. ? (ColFactor==1 ? index : index%m_cols.value())
  1035. : (RowFactor==1 ? index : index%m_rows.value());
  1036. return m_argImpl.coeff(actual_index);
  1037. }
  1038. template<int LoadMode, typename PacketType>
  1039. EIGEN_STRONG_INLINE
  1040. PacketType packet(Index row, Index col) const
  1041. {
  1042. const Index actual_row = internal::traits<XprType>::RowsAtCompileTime==1 ? 0
  1043. : RowFactor==1 ? row
  1044. : row % m_rows.value();
  1045. const Index actual_col = internal::traits<XprType>::ColsAtCompileTime==1 ? 0
  1046. : ColFactor==1 ? col
  1047. : col % m_cols.value();
  1048. return m_argImpl.template packet<LoadMode,PacketType>(actual_row, actual_col);
  1049. }
  1050. template<int LoadMode, typename PacketType>
  1051. EIGEN_STRONG_INLINE
  1052. PacketType packet(Index index) const
  1053. {
  1054. const Index actual_index = internal::traits<XprType>::RowsAtCompileTime==1
  1055. ? (ColFactor==1 ? index : index%m_cols.value())
  1056. : (RowFactor==1 ? index : index%m_rows.value());
  1057. return m_argImpl.template packet<LoadMode,PacketType>(actual_index);
  1058. }
  1059. protected:
  1060. const ArgTypeNested m_arg;
  1061. evaluator<ArgTypeNestedCleaned> m_argImpl;
  1062. const variable_if_dynamic<Index, ArgType::RowsAtCompileTime> m_rows;
  1063. const variable_if_dynamic<Index, ArgType::ColsAtCompileTime> m_cols;
  1064. };
  1065. // -------------------- PartialReduxExpr --------------------
  1066. template< typename ArgType, typename MemberOp, int Direction>
  1067. struct evaluator<PartialReduxExpr<ArgType, MemberOp, Direction> >
  1068. : evaluator_base<PartialReduxExpr<ArgType, MemberOp, Direction> >
  1069. {
  1070. typedef PartialReduxExpr<ArgType, MemberOp, Direction> XprType;
  1071. typedef typename internal::nested_eval<ArgType,1>::type ArgTypeNested;
  1072. typedef typename internal::remove_all<ArgTypeNested>::type ArgTypeNestedCleaned;
  1073. typedef typename ArgType::Scalar InputScalar;
  1074. typedef typename XprType::Scalar Scalar;
  1075. enum {
  1076. TraversalSize = Direction==int(Vertical) ? int(ArgType::RowsAtCompileTime) : int(ArgType::ColsAtCompileTime)
  1077. };
  1078. typedef typename MemberOp::template Cost<InputScalar,int(TraversalSize)> CostOpType;
  1079. enum {
  1080. CoeffReadCost = TraversalSize==Dynamic ? HugeCost
  1081. : TraversalSize * evaluator<ArgType>::CoeffReadCost + int(CostOpType::value),
  1082. Flags = (traits<XprType>::Flags&RowMajorBit) | (evaluator<ArgType>::Flags&(HereditaryBits&(~RowMajorBit))) | LinearAccessBit,
  1083. Alignment = 0 // FIXME this will need to be improved once PartialReduxExpr is vectorized
  1084. };
  1085. EIGEN_DEVICE_FUNC explicit evaluator(const XprType xpr)
  1086. : m_arg(xpr.nestedExpression()), m_functor(xpr.functor())
  1087. {
  1088. EIGEN_INTERNAL_CHECK_COST_VALUE(TraversalSize==Dynamic ? HugeCost : int(CostOpType::value));
  1089. EIGEN_INTERNAL_CHECK_COST_VALUE(CoeffReadCost);
  1090. }
  1091. typedef typename XprType::CoeffReturnType CoeffReturnType;
  1092. EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE
  1093. const Scalar coeff(Index i, Index j) const
  1094. {
  1095. if (Direction==Vertical)
  1096. return m_functor(m_arg.col(j));
  1097. else
  1098. return m_functor(m_arg.row(i));
  1099. }
  1100. EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE
  1101. const Scalar coeff(Index index) const
  1102. {
  1103. if (Direction==Vertical)
  1104. return m_functor(m_arg.col(index));
  1105. else
  1106. return m_functor(m_arg.row(index));
  1107. }
  1108. protected:
  1109. typename internal::add_const_on_value_type<ArgTypeNested>::type m_arg;
  1110. const MemberOp m_functor;
  1111. };
  1112. // -------------------- MatrixWrapper and ArrayWrapper --------------------
  1113. //
  1114. // evaluator_wrapper_base<T> is a common base class for the
  1115. // MatrixWrapper and ArrayWrapper evaluators.
  1116. template<typename XprType>
  1117. struct evaluator_wrapper_base
  1118. : evaluator_base<XprType>
  1119. {
  1120. typedef typename remove_all<typename XprType::NestedExpressionType>::type ArgType;
  1121. enum {
  1122. CoeffReadCost = evaluator<ArgType>::CoeffReadCost,
  1123. Flags = evaluator<ArgType>::Flags,
  1124. Alignment = evaluator<ArgType>::Alignment
  1125. };
  1126. EIGEN_DEVICE_FUNC explicit evaluator_wrapper_base(const ArgType& arg) : m_argImpl(arg) {}
  1127. typedef typename ArgType::Scalar Scalar;
  1128. typedef typename ArgType::CoeffReturnType CoeffReturnType;
  1129. EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE
  1130. CoeffReturnType coeff(Index row, Index col) const
  1131. {
  1132. return m_argImpl.coeff(row, col);
  1133. }
  1134. EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE
  1135. CoeffReturnType coeff(Index index) const
  1136. {
  1137. return m_argImpl.coeff(index);
  1138. }
  1139. EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE
  1140. Scalar& coeffRef(Index row, Index col)
  1141. {
  1142. return m_argImpl.coeffRef(row, col);
  1143. }
  1144. EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE
  1145. Scalar& coeffRef(Index index)
  1146. {
  1147. return m_argImpl.coeffRef(index);
  1148. }
  1149. template<int LoadMode, typename PacketType>
  1150. EIGEN_STRONG_INLINE
  1151. PacketType packet(Index row, Index col) const
  1152. {
  1153. return m_argImpl.template packet<LoadMode,PacketType>(row, col);
  1154. }
  1155. template<int LoadMode, typename PacketType>
  1156. EIGEN_STRONG_INLINE
  1157. PacketType packet(Index index) const
  1158. {
  1159. return m_argImpl.template packet<LoadMode,PacketType>(index);
  1160. }
  1161. template<int StoreMode, typename PacketType>
  1162. EIGEN_STRONG_INLINE
  1163. void writePacket(Index row, Index col, const PacketType& x)
  1164. {
  1165. m_argImpl.template writePacket<StoreMode>(row, col, x);
  1166. }
  1167. template<int StoreMode, typename PacketType>
  1168. EIGEN_STRONG_INLINE
  1169. void writePacket(Index index, const PacketType& x)
  1170. {
  1171. m_argImpl.template writePacket<StoreMode>(index, x);
  1172. }
  1173. protected:
  1174. evaluator<ArgType> m_argImpl;
  1175. };
  1176. template<typename TArgType>
  1177. struct unary_evaluator<MatrixWrapper<TArgType> >
  1178. : evaluator_wrapper_base<MatrixWrapper<TArgType> >
  1179. {
  1180. typedef MatrixWrapper<TArgType> XprType;
  1181. EIGEN_DEVICE_FUNC explicit unary_evaluator(const XprType& wrapper)
  1182. : evaluator_wrapper_base<MatrixWrapper<TArgType> >(wrapper.nestedExpression())
  1183. { }
  1184. };
  1185. template<typename TArgType>
  1186. struct unary_evaluator<ArrayWrapper<TArgType> >
  1187. : evaluator_wrapper_base<ArrayWrapper<TArgType> >
  1188. {
  1189. typedef ArrayWrapper<TArgType> XprType;
  1190. EIGEN_DEVICE_FUNC explicit unary_evaluator(const XprType& wrapper)
  1191. : evaluator_wrapper_base<ArrayWrapper<TArgType> >(wrapper.nestedExpression())
  1192. { }
  1193. };
  1194. // -------------------- Reverse --------------------
  1195. // defined in Reverse.h:
  1196. template<typename PacketType, bool ReversePacket> struct reverse_packet_cond;
  1197. template<typename ArgType, int Direction>
  1198. struct unary_evaluator<Reverse<ArgType, Direction> >
  1199. : evaluator_base<Reverse<ArgType, Direction> >
  1200. {
  1201. typedef Reverse<ArgType, Direction> XprType;
  1202. typedef typename XprType::Scalar Scalar;
  1203. typedef typename XprType::CoeffReturnType CoeffReturnType;
  1204. enum {
  1205. IsRowMajor = XprType::IsRowMajor,
  1206. IsColMajor = !IsRowMajor,
  1207. ReverseRow = (Direction == Vertical) || (Direction == BothDirections),
  1208. ReverseCol = (Direction == Horizontal) || (Direction == BothDirections),
  1209. ReversePacket = (Direction == BothDirections)
  1210. || ((Direction == Vertical) && IsColMajor)
  1211. || ((Direction == Horizontal) && IsRowMajor),
  1212. CoeffReadCost = evaluator<ArgType>::CoeffReadCost,
  1213. // let's enable LinearAccess only with vectorization because of the product overhead
  1214. // FIXME enable DirectAccess with negative strides?
  1215. Flags0 = evaluator<ArgType>::Flags,
  1216. LinearAccess = ( (Direction==BothDirections) && (int(Flags0)&PacketAccessBit) )
  1217. || ((ReverseRow && XprType::ColsAtCompileTime==1) || (ReverseCol && XprType::RowsAtCompileTime==1))
  1218. ? LinearAccessBit : 0,
  1219. Flags = int(Flags0) & (HereditaryBits | PacketAccessBit | LinearAccess),
  1220. Alignment = 0 // FIXME in some rare cases, Alignment could be preserved, like a Vector4f.
  1221. };
  1222. EIGEN_DEVICE_FUNC explicit unary_evaluator(const XprType& reverse)
  1223. : m_argImpl(reverse.nestedExpression()),
  1224. m_rows(ReverseRow ? reverse.nestedExpression().rows() : 1),
  1225. m_cols(ReverseCol ? reverse.nestedExpression().cols() : 1)
  1226. { }
  1227. EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE
  1228. CoeffReturnType coeff(Index row, Index col) const
  1229. {
  1230. return m_argImpl.coeff(ReverseRow ? m_rows.value() - row - 1 : row,
  1231. ReverseCol ? m_cols.value() - col - 1 : col);
  1232. }
  1233. EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE
  1234. CoeffReturnType coeff(Index index) const
  1235. {
  1236. return m_argImpl.coeff(m_rows.value() * m_cols.value() - index - 1);
  1237. }
  1238. EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE
  1239. Scalar& coeffRef(Index row, Index col)
  1240. {
  1241. return m_argImpl.coeffRef(ReverseRow ? m_rows.value() - row - 1 : row,
  1242. ReverseCol ? m_cols.value() - col - 1 : col);
  1243. }
  1244. EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE
  1245. Scalar& coeffRef(Index index)
  1246. {
  1247. return m_argImpl.coeffRef(m_rows.value() * m_cols.value() - index - 1);
  1248. }
  1249. template<int LoadMode, typename PacketType>
  1250. EIGEN_STRONG_INLINE
  1251. PacketType packet(Index row, Index col) const
  1252. {
  1253. enum {
  1254. PacketSize = unpacket_traits<PacketType>::size,
  1255. OffsetRow = ReverseRow && IsColMajor ? PacketSize : 1,
  1256. OffsetCol = ReverseCol && IsRowMajor ? PacketSize : 1
  1257. };
  1258. typedef internal::reverse_packet_cond<PacketType,ReversePacket> reverse_packet;
  1259. return reverse_packet::run(m_argImpl.template packet<LoadMode,PacketType>(
  1260. ReverseRow ? m_rows.value() - row - OffsetRow : row,
  1261. ReverseCol ? m_cols.value() - col - OffsetCol : col));
  1262. }
  1263. template<int LoadMode, typename PacketType>
  1264. EIGEN_STRONG_INLINE
  1265. PacketType packet(Index index) const
  1266. {
  1267. enum { PacketSize = unpacket_traits<PacketType>::size };
  1268. return preverse(m_argImpl.template packet<LoadMode,PacketType>(m_rows.value() * m_cols.value() - index - PacketSize));
  1269. }
  1270. template<int LoadMode, typename PacketType>
  1271. EIGEN_STRONG_INLINE
  1272. void writePacket(Index row, Index col, const PacketType& x)
  1273. {
  1274. // FIXME we could factorize some code with packet(i,j)
  1275. enum {
  1276. PacketSize = unpacket_traits<PacketType>::size,
  1277. OffsetRow = ReverseRow && IsColMajor ? PacketSize : 1,
  1278. OffsetCol = ReverseCol && IsRowMajor ? PacketSize : 1
  1279. };
  1280. typedef internal::reverse_packet_cond<PacketType,ReversePacket> reverse_packet;
  1281. m_argImpl.template writePacket<LoadMode>(
  1282. ReverseRow ? m_rows.value() - row - OffsetRow : row,
  1283. ReverseCol ? m_cols.value() - col - OffsetCol : col,
  1284. reverse_packet::run(x));
  1285. }
  1286. template<int LoadMode, typename PacketType>
  1287. EIGEN_STRONG_INLINE
  1288. void writePacket(Index index, const PacketType& x)
  1289. {
  1290. enum { PacketSize = unpacket_traits<PacketType>::size };
  1291. m_argImpl.template writePacket<LoadMode>
  1292. (m_rows.value() * m_cols.value() - index - PacketSize, preverse(x));
  1293. }
  1294. protected:
  1295. evaluator<ArgType> m_argImpl;
  1296. // If we do not reverse rows, then we do not need to know the number of rows; same for columns
  1297. // Nonetheless, in this case it is important to set to 1 such that the coeff(index) method works fine for vectors.
  1298. const variable_if_dynamic<Index, ReverseRow ? ArgType::RowsAtCompileTime : 1> m_rows;
  1299. const variable_if_dynamic<Index, ReverseCol ? ArgType::ColsAtCompileTime : 1> m_cols;
  1300. };
  1301. // -------------------- Diagonal --------------------
  1302. template<typename ArgType, int DiagIndex>
  1303. struct evaluator<Diagonal<ArgType, DiagIndex> >
  1304. : evaluator_base<Diagonal<ArgType, DiagIndex> >
  1305. {
  1306. typedef Diagonal<ArgType, DiagIndex> XprType;
  1307. enum {
  1308. CoeffReadCost = evaluator<ArgType>::CoeffReadCost,
  1309. Flags = (unsigned int)(evaluator<ArgType>::Flags & (HereditaryBits | DirectAccessBit) & ~RowMajorBit) | LinearAccessBit,
  1310. Alignment = 0
  1311. };
  1312. EIGEN_DEVICE_FUNC explicit evaluator(const XprType& diagonal)
  1313. : m_argImpl(diagonal.nestedExpression()),
  1314. m_index(diagonal.index())
  1315. { }
  1316. typedef typename XprType::Scalar Scalar;
  1317. typedef typename XprType::CoeffReturnType CoeffReturnType;
  1318. EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE
  1319. CoeffReturnType coeff(Index row, Index) const
  1320. {
  1321. return m_argImpl.coeff(row + rowOffset(), row + colOffset());
  1322. }
  1323. EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE
  1324. CoeffReturnType coeff(Index index) const
  1325. {
  1326. return m_argImpl.coeff(index + rowOffset(), index + colOffset());
  1327. }
  1328. EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE
  1329. Scalar& coeffRef(Index row, Index)
  1330. {
  1331. return m_argImpl.coeffRef(row + rowOffset(), row + colOffset());
  1332. }
  1333. EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE
  1334. Scalar& coeffRef(Index index)
  1335. {
  1336. return m_argImpl.coeffRef(index + rowOffset(), index + colOffset());
  1337. }
  1338. protected:
  1339. evaluator<ArgType> m_argImpl;
  1340. const internal::variable_if_dynamicindex<Index, XprType::DiagIndex> m_index;
  1341. private:
  1342. EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE Index rowOffset() const { return m_index.value() > 0 ? 0 : -m_index.value(); }
  1343. EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE Index colOffset() const { return m_index.value() > 0 ? m_index.value() : 0; }
  1344. };
  1345. //----------------------------------------------------------------------
  1346. // deprecated code
  1347. //----------------------------------------------------------------------
  1348. // -------------------- EvalToTemp --------------------
  1349. // expression class for evaluating nested expression to a temporary
  1350. template<typename ArgType> class EvalToTemp;
  1351. template<typename ArgType>
  1352. struct traits<EvalToTemp<ArgType> >
  1353. : public traits<ArgType>
  1354. { };
  1355. template<typename ArgType>
  1356. class EvalToTemp
  1357. : public dense_xpr_base<EvalToTemp<ArgType> >::type
  1358. {
  1359. public:
  1360. typedef typename dense_xpr_base<EvalToTemp>::type Base;
  1361. EIGEN_GENERIC_PUBLIC_INTERFACE(EvalToTemp)
  1362. explicit EvalToTemp(const ArgType& arg)
  1363. : m_arg(arg)
  1364. { }
  1365. const ArgType& arg() const
  1366. {
  1367. return m_arg;
  1368. }
  1369. Index rows() const
  1370. {
  1371. return m_arg.rows();
  1372. }
  1373. Index cols() const
  1374. {
  1375. return m_arg.cols();
  1376. }
  1377. private:
  1378. const ArgType& m_arg;
  1379. };
  1380. template<typename ArgType>
  1381. struct evaluator<EvalToTemp<ArgType> >
  1382. : public evaluator<typename ArgType::PlainObject>
  1383. {
  1384. typedef EvalToTemp<ArgType> XprType;
  1385. typedef typename ArgType::PlainObject PlainObject;
  1386. typedef evaluator<PlainObject> Base;
  1387. EIGEN_DEVICE_FUNC explicit evaluator(const XprType& xpr)
  1388. : m_result(xpr.arg())
  1389. {
  1390. ::new (static_cast<Base*>(this)) Base(m_result);
  1391. }
  1392. // This constructor is used when nesting an EvalTo evaluator in another evaluator
  1393. EIGEN_DEVICE_FUNC evaluator(const ArgType& arg)
  1394. : m_result(arg)
  1395. {
  1396. ::new (static_cast<Base*>(this)) Base(m_result);
  1397. }
  1398. protected:
  1399. PlainObject m_result;
  1400. };
  1401. } // namespace internal
  1402. } // end namespace Eigen
  1403. #endif // EIGEN_COREEVALUATORS_H