11#ifndef EIGEN_CXX11_TENSOR_TENSOR_REVERSE_H
12#define EIGEN_CXX11_TENSOR_TENSOR_REVERSE_H
16template<
typename ReverseDimensions,
typename XprType>
17struct traits<TensorReverseOp<ReverseDimensions,
18 XprType> > :
public traits<XprType>
20 typedef typename XprType::Scalar Scalar;
21 typedef traits<XprType> XprTraits;
22 typedef typename XprTraits::StorageKind StorageKind;
23 typedef typename XprTraits::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 typedef typename XprTraits::PointerType PointerType;
31template<
typename ReverseDimensions,
typename XprType>
32struct eval<TensorReverseOp<ReverseDimensions, XprType>, Eigen::Dense>
34 typedef const TensorReverseOp<ReverseDimensions, XprType>& type;
37template<
typename ReverseDimensions,
typename XprType>
38struct nested<TensorReverseOp<ReverseDimensions, XprType>, 1,
39 typename eval<TensorReverseOp<ReverseDimensions, XprType> >::type>
41 typedef TensorReverseOp<ReverseDimensions, XprType> type;
52template <
typename ReverseDimensions,
typename XprType>
53class TensorReverseOp :
public TensorBase<TensorReverseOp<ReverseDimensions, XprType>, WriteAccessors> {
56 typedef typename Eigen::internal::traits<TensorReverseOp>::Scalar Scalar;
58 typedef typename XprType::CoeffReturnType CoeffReturnType;
59 typedef typename Eigen::internal::nested<TensorReverseOp>::type Nested;
60 typedef typename Eigen::internal::traits<TensorReverseOp>::StorageKind StorageKind;
61 typedef typename Eigen::internal::traits<TensorReverseOp>::Index Index;
63 EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE TensorReverseOp(
64 const XprType& expr,
const ReverseDimensions& reverse_dims)
65 : m_xpr(expr), m_reverse_dims(reverse_dims) { }
68 const ReverseDimensions& reverse()
const {
return m_reverse_dims; }
71 const typename internal::remove_all<typename XprType::Nested>::type&
72 expression()
const {
return m_xpr; }
74 EIGEN_TENSOR_INHERIT_ASSIGNMENT_OPERATORS(TensorReverseOp)
78 typename XprType::Nested m_xpr;
79 const ReverseDimensions m_reverse_dims;
83template<
typename ReverseDimensions,
typename ArgType,
typename Device>
87 typedef typename XprType::Index
Index;
88 static const int NumDims = internal::array_size<ReverseDimensions>::value;
90 typedef typename XprType::Scalar
Scalar;
92 typedef typename PacketType<CoeffReturnType, Device>::type PacketReturnType;
93 static const int PacketSize = PacketType<CoeffReturnType, Device>::size;
94 typedef StorageMemory<CoeffReturnType, Device> Storage;
95 typedef typename Storage::Type EvaluatorPointerType;
99 PacketAccess = TensorEvaluator<ArgType, Device>::PacketAccess,
100 BlockAccess = NumDims > 0,
101 PreferBlockAccess =
true,
102 Layout = TensorEvaluator<ArgType, Device>::Layout,
107 typedef internal::TensorIntDivisor<Index> IndexDivisor;
110 typedef internal::TensorBlockDescriptor<NumDims, Index> TensorBlockDesc;
111 typedef internal::TensorBlockScratchAllocator<Device> TensorBlockScratch;
113 typedef typename TensorEvaluator<const ArgType, Device>::TensorBlock
116 typedef typename internal::TensorMaterializedBlock<CoeffReturnType, NumDims,
121 EIGEN_STRONG_INLINE TensorEvaluator(
const XprType& op,
const Device& device)
122 : m_impl(op.expression(), device),
123 m_reverse(op.reverse()),
127 EIGEN_STATIC_ASSERT((NumDims > 0), YOU_MADE_A_PROGRAMMING_MISTAKE);
130 m_dimensions = m_impl.dimensions();
131 if (
static_cast<int>(Layout) ==
static_cast<int>(
ColMajor)) {
133 for (
int i = 1; i < NumDims; ++i) {
134 m_strides[i] = m_strides[i-1] * m_dimensions[i-1];
135 if (m_strides[i] > 0) m_fastStrides[i] = IndexDivisor(m_strides[i]);
138 m_strides[NumDims-1] = 1;
139 for (
int i = NumDims - 2; i >= 0; --i) {
140 m_strides[i] = m_strides[i+1] * m_dimensions[i+1];
141 if (m_strides[i] > 0) m_fastStrides[i] = IndexDivisor(m_strides[i]);
146 EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE
147 const Dimensions& dimensions()
const {
return m_dimensions; }
149 EIGEN_STRONG_INLINE
bool evalSubExprsIfNeeded(EvaluatorPointerType) {
150 m_impl.evalSubExprsIfNeeded(NULL);
154#ifdef EIGEN_USE_THREADS
155 template <
typename EvalSubExprsCallback>
156 EIGEN_STRONG_INLINE
void evalSubExprsIfNeededAsync(
157 EvaluatorPointerType, EvalSubExprsCallback done) {
158 m_impl.evalSubExprsIfNeededAsync(
nullptr, [done](
bool) { done(
true); });
162 EIGEN_STRONG_INLINE
void cleanup() {
166 EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE Index reverseIndex(
168 eigen_assert(index < dimensions().TotalSize());
169 Index inputIndex = 0;
170 if (
static_cast<int>(Layout) ==
static_cast<int>(
ColMajor)) {
172 for (
int i = NumDims - 1; i > 0; --i) {
173 Index idx = index / m_fastStrides[i];
174 index -= idx * m_strides[i];
176 idx = m_dimensions[i] - idx - 1;
178 inputIndex += idx * m_strides[i] ;
181 inputIndex += (m_dimensions[0] - index - 1);
187 for (
int i = 0; i < NumDims - 1; ++i) {
188 Index idx = index / m_fastStrides[i];
189 index -= idx * m_strides[i];
191 idx = m_dimensions[i] - idx - 1;
193 inputIndex += idx * m_strides[i] ;
195 if (m_reverse[NumDims-1]) {
196 inputIndex += (m_dimensions[NumDims-1] - index - 1);
204 EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE CoeffReturnType coeff(
206 return m_impl.coeff(reverseIndex(index));
209 template<
int LoadMode>
210 EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE
211 PacketReturnType packet(Index index)
const
213 EIGEN_STATIC_ASSERT((PacketSize > 1), YOU_MADE_A_PROGRAMMING_MISTAKE)
214 eigen_assert(index+PacketSize-1 < dimensions().TotalSize());
218 EIGEN_ALIGN_MAX
typename internal::remove_const<CoeffReturnType>::type
221 for (
int i = 0; i < PacketSize; ++i) {
222 values[i] = coeff(index+i);
224 PacketReturnType rslt = internal::pload<PacketReturnType>(values);
228 EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE
229 internal::TensorBlockResourceRequirements getResourceRequirements()
const {
230 const size_t target_size = m_device.lastLevelCacheSize();
233 return internal::TensorBlockResourceRequirements::skewed<Scalar>(
235 .addCostPerCoeff({0, 0, 24});
238 EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE TensorBlock
239 block(TensorBlockDesc& desc, TensorBlockScratch& scratch,
240 bool =
false)
const {
248 static const bool isColMajor =
249 static_cast<int>(Layout) ==
static_cast<int>(
ColMajor);
251 static const Index inner_dim_idx = isColMajor ? 0 : NumDims - 1;
252 const bool inner_dim_reversed = m_reverse[inner_dim_idx];
255 Index block_offset = 0;
258 Index input_offset = reverseIndex(desc.offset());
262 array<BlockIteratorState, NumDims> it;
263 for (
int i = 0; i < NumDims; ++i) {
264 const int dim = isColMajor ? i : NumDims - 1 - i;
265 it[i].size = desc.dimension(dim);
267 it[i].reverse = m_reverse[dim];
270 i == 0 ? 1 : (it[i - 1].size * it[i - 1].block_stride);
271 it[i].block_span = it[i].block_stride * (it[i].size - 1);
273 it[i].input_stride = m_strides[dim];
274 it[i].input_span = it[i].input_stride * (it[i].size - 1);
277 it[i].input_stride = -1 * it[i].input_stride;
278 it[i].input_span = -1 * it[i].input_span;
284 int effective_inner_dim = 0;
285 for (
int i = 1; i < NumDims; ++i) {
286 if (it[i].reverse != it[effective_inner_dim].reverse)
break;
287 if (it[i].block_stride != it[effective_inner_dim].size)
break;
288 if (it[i].block_stride != numext::abs(it[i].input_stride))
break;
290 it[i].size = it[effective_inner_dim].size * it[i].size;
292 it[i].block_stride = 1;
293 it[i].input_stride = (inner_dim_reversed ? -1 : 1);
295 it[i].block_span = it[i].block_stride * (it[i].size - 1);
296 it[i].input_span = it[i].input_stride * (it[i].size - 1);
298 effective_inner_dim = i;
301 eigen_assert(it[effective_inner_dim].block_stride == 1);
302 eigen_assert(it[effective_inner_dim].input_stride ==
303 (inner_dim_reversed ? -1 : 1));
305 const Index inner_dim_size = it[effective_inner_dim].size;
308 const typename TensorBlock::Storage block_storage =
309 TensorBlock::prepareStorage(desc, scratch);
310 CoeffReturnType* block_buffer = block_storage.data();
312 while (it[NumDims - 1].count < it[NumDims - 1].size) {
314 Index dst = block_offset;
315 Index src = input_offset;
319 if (inner_dim_reversed) {
320 for (Index i = 0; i < inner_dim_size; ++i) {
321 block_buffer[dst] = m_impl.coeff(src);
326 for (Index i = 0; i < inner_dim_size; ++i) {
327 block_buffer[dst] = m_impl.coeff(src);
334 if ((NumDims - effective_inner_dim) == 1)
break;
337 for (Index i = effective_inner_dim + 1; i < NumDims; ++i) {
338 if (++it[i].count < it[i].size) {
339 block_offset += it[i].block_stride;
340 input_offset += it[i].input_stride;
343 if (i != NumDims - 1) it[i].count = 0;
344 block_offset -= it[i].block_span;
345 input_offset -= it[i].input_span;
349 return block_storage.AsTensorMaterializedBlock();
352 EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE TensorOpCost costPerCoeff(
bool vectorized)
const {
353 double compute_cost = NumDims * (2 * TensorOpCost::AddCost<Index>() +
354 2 * TensorOpCost::MulCost<Index>() +
355 TensorOpCost::DivCost<Index>());
356 for (
int i = 0; i < NumDims; ++i) {
358 compute_cost += 2 * TensorOpCost::AddCost<Index>();
361 return m_impl.costPerCoeff(vectorized) +
362 TensorOpCost(0, 0, compute_cost,
false , PacketSize);
365 EIGEN_DEVICE_FUNC
typename Storage::Type data()
const {
return NULL; }
369 EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE
void bind(cl::sycl::handler &cgh)
const {
375 Dimensions m_dimensions;
376 array<Index, NumDims> m_strides;
377 array<IndexDivisor, NumDims> m_fastStrides;
378 TensorEvaluator<ArgType, Device> m_impl;
379 ReverseDimensions m_reverse;
380 const Device EIGEN_DEVICE_REF m_device;
383 struct BlockIteratorState {
405template <
typename ReverseDimensions,
typename ArgType,
typename Device>
407 :
public TensorEvaluator<const TensorReverseOp<ReverseDimensions, ArgType>,
409 typedef TensorEvaluator<const TensorReverseOp<ReverseDimensions, ArgType>,
411 typedef TensorReverseOp<ReverseDimensions, ArgType> XprType;
412 typedef typename XprType::Index Index;
413 static const int NumDims = internal::array_size<ReverseDimensions>::value;
414 typedef DSizes<Index, NumDims> Dimensions;
418 PacketAccess = TensorEvaluator<ArgType, Device>::PacketAccess,
420 PreferBlockAccess =
false,
421 Layout = TensorEvaluator<ArgType, Device>::Layout,
425 EIGEN_STRONG_INLINE TensorEvaluator(
const XprType& op,
const Device& device)
426 : Base(op, device) {}
428 typedef typename XprType::Scalar Scalar;
429 typedef typename XprType::CoeffReturnType CoeffReturnType;
430 typedef typename PacketType<CoeffReturnType, Device>::type PacketReturnType;
431 static const int PacketSize = PacketType<CoeffReturnType, Device>::size;
434 typedef internal::TensorBlockNotImplemented TensorBlock;
437 EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE
438 const Dimensions& dimensions()
const {
return this->m_dimensions; }
440 EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE Scalar& coeffRef(Index index) {
441 return this->m_impl.coeffRef(this->reverseIndex(index));
444 template <
int StoreMode> EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE
445 void writePacket(Index index,
const PacketReturnType& x) {
446 EIGEN_STATIC_ASSERT((PacketSize > 1), YOU_MADE_A_PROGRAMMING_MISTAKE)
447 eigen_assert(index+PacketSize-1 < dimensions().TotalSize());
450 EIGEN_ALIGN_MAX CoeffReturnType values[PacketSize];
451 internal::pstore<CoeffReturnType, PacketReturnType>(values, x);
453 for (
int i = 0; i < PacketSize; ++i) {
454 this->coeffRef(index+i) = values[i];
The tensor base class.
Definition TensorForwardDeclarations.h:56
Tensor reverse elements class.
Definition TensorReverse.h:53
Namespace containing all symbols from the Eigen library.
EIGEN_DEFAULT_DENSE_INDEX_TYPE Index
The tensor evaluator class.
Definition TensorEvaluator.h:27