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_EVAL_TO_H
11#define EIGEN_CXX11_TENSOR_TENSOR_EVAL_TO_H
12
13namespace Eigen {
14
15/** \class TensorForcedEval
16  * \ingroup CXX11_Tensor_Module
17  *
18  * \brief Tensor reshaping class.
19  *
20  *
21  */
22namespace internal {
23template<typename XprType, template <class> class MakePointer_>
24struct traits<TensorEvalToOp<XprType, MakePointer_> >
25{
26  // Type promotion to handle the case where the types of the lhs and the rhs are different.
27  typedef typename XprType::Scalar Scalar;
28  typedef traits<XprType> XprTraits;
29  typedef typename XprTraits::StorageKind StorageKind;
30  typedef typename XprTraits::Index Index;
31  typedef typename XprType::Nested Nested;
32  typedef typename remove_reference<Nested>::type _Nested;
33  static const int NumDimensions = XprTraits::NumDimensions;
34  static const int Layout = XprTraits::Layout;
35
36  enum {
37    Flags = 0
38  };
39  template <class T>
40  struct MakePointer {
41    // Intermediate typedef to workaround MSVC issue.
42    typedef MakePointer_<T> MakePointerT;
43    typedef typename MakePointerT::Type Type;
44  };
45};
46
47template<typename XprType, template <class> class MakePointer_>
48struct eval<TensorEvalToOp<XprType, MakePointer_>, Eigen::Dense>
49{
50  typedef const TensorEvalToOp<XprType, MakePointer_>& type;
51};
52
53template<typename XprType, template <class> class MakePointer_>
54struct nested<TensorEvalToOp<XprType, MakePointer_>, 1, typename eval<TensorEvalToOp<XprType, MakePointer_> >::type>
55{
56  typedef TensorEvalToOp<XprType, MakePointer_> type;
57};
58
59}  // end namespace internal
60
61
62
63
64template<typename XprType, template <class> class MakePointer_>
65class TensorEvalToOp : public TensorBase<TensorEvalToOp<XprType, MakePointer_>, ReadOnlyAccessors>
66{
67  public:
68  typedef typename Eigen::internal::traits<TensorEvalToOp>::Scalar Scalar;
69  typedef typename Eigen::NumTraits<Scalar>::Real RealScalar;
70  typedef typename internal::remove_const<typename XprType::CoeffReturnType>::type CoeffReturnType;
71  typedef typename MakePointer_<CoeffReturnType>::Type PointerType;
72  typedef typename Eigen::internal::nested<TensorEvalToOp>::type Nested;
73  typedef typename Eigen::internal::traits<TensorEvalToOp>::StorageKind StorageKind;
74  typedef typename Eigen::internal::traits<TensorEvalToOp>::Index Index;
75
76  EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE TensorEvalToOp(PointerType buffer, const XprType& expr)
77      : m_xpr(expr), m_buffer(buffer) {}
78
79    EIGEN_DEVICE_FUNC
80    const typename internal::remove_all<typename XprType::Nested>::type&
81    expression() const { return m_xpr; }
82
83    EIGEN_DEVICE_FUNC PointerType buffer() const { return m_buffer; }
84
85  protected:
86    typename XprType::Nested m_xpr;
87    PointerType m_buffer;
88};
89
90
91
92template<typename ArgType, typename Device, template <class> class MakePointer_>
93struct TensorEvaluator<const TensorEvalToOp<ArgType, MakePointer_>, Device>
94{
95  typedef TensorEvalToOp<ArgType, MakePointer_> XprType;
96  typedef typename ArgType::Scalar Scalar;
97  typedef typename TensorEvaluator<ArgType, Device>::Dimensions Dimensions;
98  typedef typename XprType::Index Index;
99  typedef typename internal::remove_const<typename XprType::CoeffReturnType>::type CoeffReturnType;
100  typedef typename PacketType<CoeffReturnType, Device>::type PacketReturnType;
101  static const int PacketSize = internal::unpacket_traits<PacketReturnType>::size;
102
103  enum {
104    IsAligned = TensorEvaluator<ArgType, Device>::IsAligned,
105    PacketAccess = TensorEvaluator<ArgType, Device>::PacketAccess,
106    Layout = TensorEvaluator<ArgType, Device>::Layout,
107    CoordAccess = false,  // to be implemented
108    RawAccess = true
109  };
110
111  EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE TensorEvaluator(const XprType& op, const Device& device)
112      : m_impl(op.expression(), device), m_device(device),
113          m_buffer(op.buffer()), m_op(op), m_expression(op.expression())
114  { }
115
116  // Used for accessor extraction in SYCL Managed TensorMap:
117  EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE const XprType& op() const {
118    return m_op;
119  }
120
121  EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE ~TensorEvaluator() {
122  }
123
124  typedef typename internal::traits<const TensorEvalToOp<ArgType, MakePointer_> >::template MakePointer<CoeffReturnType>::Type DevicePointer;
125  EIGEN_DEVICE_FUNC const Dimensions& dimensions() const { return m_impl.dimensions(); }
126
127  EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE bool evalSubExprsIfNeeded(DevicePointer scalar) {
128    EIGEN_UNUSED_VARIABLE(scalar);
129    eigen_assert(scalar == NULL);
130    return m_impl.evalSubExprsIfNeeded(m_buffer);
131  }
132
133  EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE void evalScalar(Index i) {
134    m_buffer[i] = m_impl.coeff(i);
135  }
136  EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE void evalPacket(Index i) {
137    internal::pstoret<CoeffReturnType, PacketReturnType, Aligned>(m_buffer + i, m_impl.template packet<TensorEvaluator<ArgType, Device>::IsAligned ? Aligned : Unaligned>(i));
138  }
139
140  EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE void cleanup() {
141    m_impl.cleanup();
142  }
143
144  EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE CoeffReturnType coeff(Index index) const
145  {
146    return m_buffer[index];
147  }
148
149  template<int LoadMode>
150  EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE PacketReturnType packet(Index index) const
151  {
152    return internal::ploadt<PacketReturnType, LoadMode>(m_buffer + index);
153  }
154
155  EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE TensorOpCost costPerCoeff(bool vectorized) const {
156    // We assume that evalPacket or evalScalar is called to perform the
157    // assignment and account for the cost of the write here.
158    return m_impl.costPerCoeff(vectorized) +
159        TensorOpCost(0, sizeof(CoeffReturnType), 0, vectorized, PacketSize);
160  }
161
162  EIGEN_DEVICE_FUNC DevicePointer data() const { return m_buffer; }
163  ArgType expression() const { return m_expression; }
164
165  /// required by sycl in order to extract the accessor
166  const TensorEvaluator<ArgType, Device>& impl() const { return m_impl; }
167  /// added for sycl in order to construct the buffer from the sycl device
168  const Device& device() const{return m_device;}
169
170 private:
171  TensorEvaluator<ArgType, Device> m_impl;
172  const Device& m_device;
173  DevicePointer m_buffer;
174  const XprType& m_op;
175  const ArgType m_expression;
176};
177
178
179} // end namespace Eigen
180
181#endif // EIGEN_CXX11_TENSOR_TENSOR_EVAL_TO_H
182