1 // This file is part of Eigen, a lightweight C++ template library
2 // for linear algebra.
3 //
4 // Copyright (C) 2014 Benoit Steiner <benoit.steiner.goog@gmail.com>
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_CXX11_TENSOR_TENSOR_FORCED_EVAL_H
11 #define EIGEN_CXX11_TENSOR_TENSOR_FORCED_EVAL_H
12 
13 namespace Eigen {
14 
15 namespace internal {
16 template<typename XprType, template <class> class MakePointer_>
17 struct traits<TensorForcedEvalOp<XprType, MakePointer_> >
18 {
19   // Type promotion to handle the case where the types of the lhs and the rhs are different.
20   typedef typename XprType::Scalar Scalar;
21   typedef traits<XprType> XprTraits;
22   typedef typename traits<XprType>::StorageKind StorageKind;
23   typedef typename traits<XprType>::Index Index;
24   typedef typename XprType::Nested Nested;
25   typedef typename remove_reference<Nested>::type _Nested;
26   static const int NumDimensions = XprTraits::NumDimensions;
27   static const int Layout = XprTraits::Layout;
28 
29   enum {
30     Flags = 0
31   };
32   template <class T> struct MakePointer {
33     // Intermediate typedef to workaround MSVC issue.
34     typedef MakePointer_<T> MakePointerT;
35     typedef typename MakePointerT::Type Type;
36   };
37 };
38 
39 template<typename XprType, template <class> class MakePointer_>
40 struct eval<TensorForcedEvalOp<XprType, MakePointer_>, Eigen::Dense>
41 {
42   typedef const TensorForcedEvalOp<XprType, MakePointer_>& type;
43 };
44 
45 template<typename XprType, template <class> class MakePointer_>
46 struct nested<TensorForcedEvalOp<XprType, MakePointer_>, 1, typename eval<TensorForcedEvalOp<XprType, MakePointer_> >::type>
47 {
48   typedef TensorForcedEvalOp<XprType, MakePointer_> type;
49 };
50 
51 }  // end namespace internal
52 
53 
54 
55 // FIXME use proper doxygen documentation (e.g. \tparam MakePointer_)
56 
57 /** \class TensorForcedEvalOp
58   * \ingroup CXX11_Tensor_Module
59   *
60   * \brief Tensor reshaping class.
61   *
62   *
63   */
64 /// `template <class> class MakePointer_` is added to convert the host pointer to the device pointer.
65 /// It is added due to the fact that for our device compiler `T*` is not allowed.
66 /// If we wanted to use the same Evaluator functions we have to convert that type to our pointer `T`.
67 /// This is done through our `MakePointer_` class. By default the Type in the `MakePointer_<T>` is `T*` .
68 /// Therefore, by adding the default value, we managed to convert the type and it does not break any
69 /// existing code as its default value is `T*`.
70 template<typename XprType, template <class> class MakePointer_>
71 class TensorForcedEvalOp : public TensorBase<TensorForcedEvalOp<XprType, MakePointer_>, ReadOnlyAccessors>
72 {
73   public:
74   typedef typename Eigen::internal::traits<TensorForcedEvalOp>::Scalar Scalar;
75   typedef typename Eigen::NumTraits<Scalar>::Real RealScalar;
76   typedef typename internal::remove_const<typename XprType::CoeffReturnType>::type CoeffReturnType;
77   typedef typename Eigen::internal::nested<TensorForcedEvalOp>::type Nested;
78   typedef typename Eigen::internal::traits<TensorForcedEvalOp>::StorageKind StorageKind;
79   typedef typename Eigen::internal::traits<TensorForcedEvalOp>::Index Index;
80 
81   EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE TensorForcedEvalOp(const XprType& expr)
82       : m_xpr(expr) {}
83 
84     EIGEN_DEVICE_FUNC
85     const typename internal::remove_all<typename XprType::Nested>::type&
86     expression() const { return m_xpr; }
87 
88   protected:
89     typename XprType::Nested m_xpr;
90 };
91 
92 
93 template<typename ArgType, typename Device, template <class> class MakePointer_>
94 struct TensorEvaluator<const TensorForcedEvalOp<ArgType, MakePointer_>, Device>
95 {
96   typedef TensorForcedEvalOp<ArgType, MakePointer_> XprType;
97   typedef typename ArgType::Scalar Scalar;
98   typedef typename TensorEvaluator<ArgType, Device>::Dimensions Dimensions;
99   typedef typename XprType::Index Index;
100   typedef typename XprType::CoeffReturnType CoeffReturnType;
101   typedef typename PacketType<CoeffReturnType, Device>::type PacketReturnType;
102   static const int PacketSize = internal::unpacket_traits<PacketReturnType>::size;
103 
104   enum {
105     IsAligned = true,
106     PacketAccess = (PacketSize > 1),
107     Layout = TensorEvaluator<ArgType, Device>::Layout,
108     RawAccess = true
109   };
110 
111   EIGEN_DEVICE_FUNC TensorEvaluator(const XprType& op, const Device& device)
112 	/// op_ is used for sycl
113       : m_impl(op.expression(), device), m_op(op.expression()), m_device(device), m_buffer(NULL)
114   { }
115 
116   EIGEN_DEVICE_FUNC const Dimensions& dimensions() const { return m_impl.dimensions(); }
117 
118   EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE bool evalSubExprsIfNeeded(CoeffReturnType*) {
119     const Index numValues =  internal::array_prod(m_impl.dimensions());
120     m_buffer = (CoeffReturnType*)m_device.allocate(numValues * sizeof(CoeffReturnType));
121     // Should initialize the memory in case we're dealing with non POD types.
122     if (NumTraits<CoeffReturnType>::RequireInitialization) {
123       for (Index i = 0; i < numValues; ++i) {
124         new(m_buffer+i) CoeffReturnType();
125       }
126     }
127     typedef TensorEvalToOp< const typename internal::remove_const<ArgType>::type > EvalTo;
128     EvalTo evalToTmp(m_buffer, m_op);
129     const bool PacketAccess = internal::IsVectorizable<Device, const ArgType>::value;
130     internal::TensorExecutor<const EvalTo, typename internal::remove_const<Device>::type, PacketAccess>::run(evalToTmp, m_device);
131     return true;
132   }
133   EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE void cleanup() {
134     m_device.deallocate(m_buffer);
135     m_buffer = NULL;
136   }
137 
138   EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE CoeffReturnType coeff(Index index) const
139   {
140     return m_buffer[index];
141   }
142 
143   template<int LoadMode>
144   EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE PacketReturnType packet(Index index) const
145   {
146     return internal::ploadt<PacketReturnType, LoadMode>(m_buffer + index);
147   }
148 
149   EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE TensorOpCost costPerCoeff(bool vectorized) const {
150     return TensorOpCost(sizeof(CoeffReturnType), 0, 0, vectorized, PacketSize);
151   }
152 
153   EIGEN_DEVICE_FUNC typename MakePointer<Scalar>::Type data() const { return m_buffer; }
154 
155   /// required by sycl in order to extract the sycl accessor
156   const TensorEvaluator<ArgType, Device>& impl() { return m_impl; }
157   /// used by sycl in order to build the sycl buffer
158   const Device& device() const{return m_device;}
159  private:
160   TensorEvaluator<ArgType, Device> m_impl;
161   const ArgType m_op;
162   const Device& m_device;
163   typename MakePointer<CoeffReturnType>::Type m_buffer;
164 };
165 
166 
167 } // end namespace Eigen
168 
169 #endif // EIGEN_CXX11_TENSOR_TENSOR_FORCED_EVAL_H
170