1 | // This file is part of Eigen, a lightweight C++ template library |
2 | // for linear algebra. |
3 | // |
4 | // Copyright (C) 2014 Benoit Steiner <[email protected]> |
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_MAP_H |
11 | #define EIGEN_CXX11_TENSOR_TENSOR_MAP_H |
12 | |
13 | #include "./InternalHeaderCheck.h" |
14 | |
15 | namespace Eigen { |
16 | |
17 | // FIXME use proper doxygen documentation (e.g. \tparam MakePointer_) |
18 | |
19 | /** \class TensorMap |
20 | * \ingroup CXX11_Tensor_Module |
21 | * |
22 | * \brief A tensor expression mapping an existing array of data. |
23 | * |
24 | */ |
25 | /// `template <class> class MakePointer_` is added to convert the host pointer to the device pointer. |
26 | /// It is added due to the fact that for our device compiler `T*` is not allowed. |
27 | /// If we wanted to use the same Evaluator functions we have to convert that type to our pointer `T`. |
28 | /// This is done through our `MakePointer_` class. By default the Type in the `MakePointer_<T>` is `T*` . |
29 | /// Therefore, by adding the default value, we managed to convert the type and it does not break any |
30 | /// existing code as its default value is `T*`. |
31 | template<typename PlainObjectType, int Options_, template <class> class MakePointer_> class TensorMap : public TensorBase<TensorMap<PlainObjectType, Options_, MakePointer_> > |
32 | { |
33 | public: |
34 | typedef TensorMap<PlainObjectType, Options_, MakePointer_> Self; |
35 | typedef TensorBase<TensorMap<PlainObjectType, Options_, MakePointer_> > Base; |
36 | #ifdef EIGEN_USE_SYCL |
37 | typedef std::remove_reference_t<typename Eigen::internal::nested<Self>::type> Nested; |
38 | #else |
39 | typedef typename Eigen::internal::nested<Self>::type Nested; |
40 | #endif |
41 | typedef typename internal::traits<PlainObjectType>::StorageKind StorageKind; |
42 | typedef typename internal::traits<PlainObjectType>::Index Index; |
43 | typedef typename internal::traits<PlainObjectType>::Scalar Scalar; |
44 | typedef typename NumTraits<Scalar>::Real RealScalar; |
45 | typedef typename PlainObjectType::Base::CoeffReturnType CoeffReturnType; |
46 | |
47 | typedef typename MakePointer_<Scalar>::Type PointerType; |
48 | typedef typename MakePointer_<Scalar>::ConstType PointerConstType; |
49 | |
50 | // WARN: PointerType still can be a pointer to const (const Scalar*), for |
51 | // example in TensorMap<Tensor<const Scalar, ...>> expression. This type of |
52 | // expression should be illegal, but adding this restriction is not possible |
53 | // in practice (see https://bitbucket.org/eigen/eigen/pull-requests/488). |
54 | typedef std::conditional_t< |
55 | bool(internal::is_lvalue<PlainObjectType>::value), |
56 | PointerType, // use simple pointer in lvalue expressions |
57 | PointerConstType // use const pointer in rvalue expressions |
58 | > StoragePointerType; |
59 | |
60 | // If TensorMap was constructed over rvalue expression (e.g. const Tensor), |
61 | // we should return a reference to const from operator() (and others), even |
62 | // if TensorMap itself is not const. |
63 | typedef std::conditional_t< |
64 | bool(internal::is_lvalue<PlainObjectType>::value), |
65 | Scalar&, |
66 | const Scalar& |
67 | > StorageRefType; |
68 | |
69 | static constexpr int Options = Options_; |
70 | |
71 | static constexpr Index NumIndices = PlainObjectType::NumIndices; |
72 | typedef typename PlainObjectType::Dimensions Dimensions; |
73 | |
74 | static constexpr int Layout = PlainObjectType::Layout; |
75 | enum { |
76 | IsAligned = ((int(Options_)&Aligned)==Aligned), |
77 | CoordAccess = true, |
78 | RawAccess = true |
79 | }; |
80 | |
81 | EIGEN_DEVICE_FUNC |
82 | EIGEN_STRONG_INLINE TensorMap(StoragePointerType dataPtr) : m_data(dataPtr), m_dimensions() { |
83 | // The number of dimensions used to construct a tensor must be equal to the rank of the tensor. |
84 | EIGEN_STATIC_ASSERT((0 == NumIndices || NumIndices == Dynamic), YOU_MADE_A_PROGRAMMING_MISTAKE) |
85 | } |
86 | |
87 | template<typename... IndexTypes> EIGEN_DEVICE_FUNC |
88 | EIGEN_STRONG_INLINE TensorMap(StoragePointerType dataPtr, Index firstDimension, IndexTypes... otherDimensions) : m_data(dataPtr), m_dimensions(firstDimension, otherDimensions...) { |
89 | // The number of dimensions used to construct a tensor must be equal to the rank of the tensor. |
90 | EIGEN_STATIC_ASSERT((sizeof...(otherDimensions) + 1 == NumIndices || NumIndices == Dynamic), YOU_MADE_A_PROGRAMMING_MISTAKE) |
91 | } |
92 | |
93 | EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE TensorMap(StoragePointerType dataPtr, const array<Index, NumIndices>& dimensions) |
94 | : m_data(dataPtr), m_dimensions(dimensions) |
95 | { } |
96 | |
97 | template <typename Dimensions> |
98 | EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE TensorMap(StoragePointerType dataPtr, const Dimensions& dimensions) |
99 | : m_data(dataPtr), m_dimensions(dimensions) |
100 | { } |
101 | |
102 | EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE TensorMap(PlainObjectType& tensor) |
103 | : m_data(tensor.data()), m_dimensions(tensor.dimensions()) |
104 | { } |
105 | |
106 | EIGEN_DEVICE_FUNC |
107 | EIGEN_STRONG_INLINE Index rank() const { return m_dimensions.rank(); } |
108 | EIGEN_DEVICE_FUNC |
109 | EIGEN_STRONG_INLINE Index dimension(Index n) const { return m_dimensions[n]; } |
110 | EIGEN_DEVICE_FUNC |
111 | EIGEN_STRONG_INLINE const Dimensions& dimensions() const { return m_dimensions; } |
112 | EIGEN_DEVICE_FUNC |
113 | EIGEN_STRONG_INLINE Index size() const { return m_dimensions.TotalSize(); } |
114 | EIGEN_DEVICE_FUNC |
115 | EIGEN_STRONG_INLINE StoragePointerType data() { return m_data; } |
116 | EIGEN_DEVICE_FUNC |
117 | EIGEN_STRONG_INLINE StoragePointerType data() const { return m_data; } |
118 | |
119 | EIGEN_DEVICE_FUNC |
120 | EIGEN_STRONG_INLINE StorageRefType operator()(const array<Index, NumIndices>& indices) const |
121 | { |
122 | // eigen_assert(checkIndexRange(indices)); |
123 | if (PlainObjectType::Options&RowMajor) { |
124 | const Index index = m_dimensions.IndexOfRowMajor(indices); |
125 | return m_data[index]; |
126 | } else { |
127 | const Index index = m_dimensions.IndexOfColMajor(indices); |
128 | return m_data[index]; |
129 | } |
130 | } |
131 | |
132 | EIGEN_DEVICE_FUNC |
133 | EIGEN_STRONG_INLINE StorageRefType operator()() const |
134 | { |
135 | EIGEN_STATIC_ASSERT(NumIndices == 0, YOU_MADE_A_PROGRAMMING_MISTAKE) |
136 | return m_data[0]; |
137 | } |
138 | |
139 | EIGEN_DEVICE_FUNC |
140 | EIGEN_STRONG_INLINE StorageRefType operator()(Index index) const |
141 | { |
142 | eigen_internal_assert(index >= 0 && index < size()); |
143 | return m_data[index]; |
144 | } |
145 | |
146 | template<typename... IndexTypes> EIGEN_DEVICE_FUNC |
147 | EIGEN_STRONG_INLINE StorageRefType operator()(Index firstIndex, Index secondIndex, IndexTypes... otherIndices) const |
148 | { |
149 | EIGEN_STATIC_ASSERT(sizeof...(otherIndices) + 2 == NumIndices, YOU_MADE_A_PROGRAMMING_MISTAKE) |
150 | eigen_assert(internal::all((Eigen::NumTraits<Index>::highest() >= otherIndices)...)); |
151 | if (PlainObjectType::Options&RowMajor) { |
152 | const Index index = m_dimensions.IndexOfRowMajor(array<Index, NumIndices>{{firstIndex, secondIndex, otherIndices...}}); |
153 | return m_data[index]; |
154 | } else { |
155 | const Index index = m_dimensions.IndexOfColMajor(array<Index, NumIndices>{{firstIndex, secondIndex, otherIndices...}}); |
156 | return m_data[index]; |
157 | } |
158 | } |
159 | |
160 | EIGEN_DEVICE_FUNC |
161 | EIGEN_STRONG_INLINE StorageRefType operator()(const array<Index, NumIndices>& indices) |
162 | { |
163 | // eigen_assert(checkIndexRange(indices)); |
164 | if (PlainObjectType::Options&RowMajor) { |
165 | const Index index = m_dimensions.IndexOfRowMajor(indices); |
166 | return m_data[index]; |
167 | } else { |
168 | const Index index = m_dimensions.IndexOfColMajor(indices); |
169 | return m_data[index]; |
170 | } |
171 | } |
172 | |
173 | EIGEN_DEVICE_FUNC |
174 | EIGEN_STRONG_INLINE StorageRefType operator()() |
175 | { |
176 | EIGEN_STATIC_ASSERT(NumIndices == 0, YOU_MADE_A_PROGRAMMING_MISTAKE) |
177 | return m_data[0]; |
178 | } |
179 | |
180 | EIGEN_DEVICE_FUNC |
181 | EIGEN_STRONG_INLINE StorageRefType operator()(Index index) |
182 | { |
183 | eigen_internal_assert(index >= 0 && index < size()); |
184 | return m_data[index]; |
185 | } |
186 | |
187 | template<typename... IndexTypes> EIGEN_DEVICE_FUNC |
188 | EIGEN_STRONG_INLINE StorageRefType operator()(Index firstIndex, Index secondIndex, IndexTypes... otherIndices) |
189 | { |
190 | static_assert(sizeof...(otherIndices) + 2 == NumIndices || NumIndices == Dynamic, "Number of indices used to access a tensor coefficient must be equal to the rank of the tensor." ); |
191 | eigen_assert(internal::all((Eigen::NumTraits<Index>::highest() >= otherIndices)...)); |
192 | const std::size_t NumDims = sizeof...(otherIndices) + 2; |
193 | if (PlainObjectType::Options&RowMajor) { |
194 | const Index index = m_dimensions.IndexOfRowMajor(array<Index, NumDims>{{firstIndex, secondIndex, otherIndices...}}); |
195 | return m_data[index]; |
196 | } else { |
197 | const Index index = m_dimensions.IndexOfColMajor(array<Index, NumDims>{{firstIndex, secondIndex, otherIndices...}}); |
198 | return m_data[index]; |
199 | } |
200 | } |
201 | |
202 | EIGEN_TENSOR_INHERIT_ASSIGNMENT_OPERATORS(TensorMap) |
203 | |
204 | private: |
205 | StoragePointerType m_data; |
206 | Dimensions m_dimensions; |
207 | }; |
208 | |
209 | } // end namespace Eigen |
210 | |
211 | #endif // EIGEN_CXX11_TENSOR_TENSOR_MAP_H |
212 | |