10#ifndef EIGEN_CXX11_TENSOR_TENSOR_MORPHING_H
11#define EIGEN_CXX11_TENSOR_TENSOR_MORPHING_H
16template<
typename NewDimensions,
typename XprType>
17struct traits<TensorReshapingOp<NewDimensions, XprType> > :
public traits<XprType>
19 typedef typename XprType::Scalar Scalar;
20 typedef traits<XprType> XprTraits;
21 typedef typename XprTraits::StorageKind StorageKind;
22 typedef typename XprTraits::Index
Index;
23 typedef typename XprType::Nested Nested;
24 typedef typename remove_reference<Nested>::type _Nested;
25 static const int NumDimensions = array_size<NewDimensions>::value;
26 static const int Layout = XprTraits::Layout;
27 typedef typename XprTraits::PointerType PointerType;
30template<
typename NewDimensions,
typename XprType>
31struct eval<TensorReshapingOp<NewDimensions, XprType>, Eigen::Dense>
33 typedef const TensorReshapingOp<NewDimensions, XprType>EIGEN_DEVICE_REF type;
36template<
typename NewDimensions,
typename XprType>
37struct nested<TensorReshapingOp<NewDimensions, XprType>, 1, typename eval<TensorReshapingOp<NewDimensions, XprType> >::type>
39 typedef TensorReshapingOp<NewDimensions, XprType> type;
49template <
typename NewDimensions,
typename XprType>
50class TensorReshapingOp :
public TensorBase<TensorReshapingOp<NewDimensions, XprType>, WriteAccessors> {
53 typedef typename Eigen::internal::traits<TensorReshapingOp>::Scalar Scalar;
54 typedef typename internal::remove_const<typename XprType::CoeffReturnType>::type CoeffReturnType;
55 typedef typename Eigen::internal::nested<TensorReshapingOp>::type Nested;
56 typedef typename Eigen::internal::traits<TensorReshapingOp>::StorageKind StorageKind;
57 typedef typename Eigen::internal::traits<TensorReshapingOp>::Index Index;
59 EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE TensorReshapingOp(
const XprType& expr,
const NewDimensions& dims)
60 : m_xpr(expr), m_dims(dims) {}
63 const NewDimensions& dimensions()
const {
return m_dims; }
66 const typename internal::remove_all<typename XprType::Nested>::type&
67 expression()
const {
return m_xpr; }
69 EIGEN_TENSOR_INHERIT_ASSIGNMENT_OPERATORS(TensorReshapingOp)
72 typename XprType::Nested m_xpr;
73 const NewDimensions m_dims;
78template<
typename NewDimensions,
typename ArgType,
typename Device>
84 typedef typename XprType::Index
Index;
85 typedef typename XprType::Scalar
Scalar;
87 typedef typename PacketType<CoeffReturnType, Device>::type PacketReturnType;
88 typedef StorageMemory<CoeffReturnType, Device> Storage;
89 typedef typename Storage::Type EvaluatorPointerType;
90 typedef StorageMemory<typename internal::remove_const<CoeffReturnType>::type, Device> ConstCastStorage;
92 static const int NumOutputDims = internal::array_size<Dimensions>::value;
93 static const int NumInputDims = internal::array_size<typename TensorEvaluator<ArgType, Device>::Dimensions>::value;
104 static const ReshapingKind kind =
105#if defined(EIGEN_HAS_INDEX_LIST)
106 (NumOutputDims == 2 && internal::index_statically_eq<NewDimensions>(0, 1)) ? OneByN
107 : (NumOutputDims == 2 && internal::index_statically_eq<NewDimensions>(1, 1)) ? NByOne
115 IsAligned = TensorEvaluator<ArgType, Device>::IsAligned,
116 PacketAccess = TensorEvaluator<ArgType, Device>::PacketAccess,
120 BlockAccess = TensorEvaluator<ArgType, Device>::RawAccess &&
121 NumInputDims > 0 && NumOutputDims > 0,
122 PreferBlockAccess =
false,
123 Layout = TensorEvaluator<ArgType, Device>::Layout,
125 RawAccess = TensorEvaluator<ArgType, Device>::RawAccess
128 typedef typename internal::remove_const<Scalar>::type ScalarNoConst;
131 typedef internal::TensorBlockDescriptor<NumOutputDims, Index> TensorBlockDesc;
132 typedef internal::TensorBlockScratchAllocator<Device> TensorBlockScratch;
135 typename internal::TensorMaterializedBlock<ScalarNoConst, NumOutputDims,
140 EIGEN_STRONG_INLINE TensorEvaluator(
const XprType& op,
const Device& device)
141 : m_impl(op.expression(), device), m_dimensions(op.dimensions())
145 eigen_assert(internal::array_prod(m_impl.dimensions()) == internal::array_prod(op.dimensions()));
148 EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE
const Dimensions& dimensions()
const {
return m_dimensions; }
150#ifdef EIGEN_USE_THREADS
151 template <
typename EvalSubExprsCallback>
152 EIGEN_STRONG_INLINE
void evalSubExprsIfNeededAsync(
153 EvaluatorPointerType data, EvalSubExprsCallback done) {
154 m_impl.evalSubExprsIfNeededAsync(data, std::move(done));
158 EIGEN_STRONG_INLINE
bool evalSubExprsIfNeeded(EvaluatorPointerType data) {
159 return m_impl.evalSubExprsIfNeeded(data);
161 EIGEN_STRONG_INLINE
void cleanup() {
165 EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE CoeffReturnType coeff(Index index)
const
167 return m_impl.coeff(index);
170 template<
int LoadMode>
171 EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE PacketReturnType packet(Index index)
const
173 return m_impl.template packet<LoadMode>(index);
176 EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE TensorOpCost costPerCoeff(
bool vectorized)
const {
177 return m_impl.costPerCoeff(vectorized);
180 EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE
181 internal::TensorBlockResourceRequirements getResourceRequirements()
const {
182 return internal::TensorBlockResourceRequirements::any();
187 struct BlockIteratorState {
194 EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE TensorBlock
195 block(TensorBlockDesc& desc, TensorBlockScratch& scratch,
196 bool =
false)
const {
197 eigen_assert(m_impl.data() != NULL);
198 eigen_assert((kind == Runtime) ||
199 (kind == OneByN && desc.dimensions()[0] == 1) ||
200 (kind == NByOne && desc.dimensions()[1] == 1));
202 if (kind == OneByN || kind == NByOne) {
205 return TensorBlock(internal::TensorBlockKind::kView,
206 m_impl.data() + desc.offset(), desc.dimensions());
210 return TensorBlock::materialize(m_impl.data(), m_dimensions, desc,
215 EIGEN_DEVICE_FUNC
typename Storage::Type data()
const {
216 return constCast(m_impl.data());
219 EIGEN_DEVICE_FUNC
const TensorEvaluator<ArgType, Device>& impl()
const {
return m_impl; }
221 #ifdef EIGEN_USE_SYCL
223 EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE
void bind(cl::sycl::handler &cgh)
const {
228 TensorEvaluator<ArgType, Device> m_impl;
229 NewDimensions m_dimensions;
234template<
typename NewDimensions,
typename ArgType,
typename Device>
236 :
public TensorEvaluator<const TensorReshapingOp<NewDimensions, ArgType>, Device>
239 typedef TensorEvaluator<const TensorReshapingOp<NewDimensions, ArgType>, Device> Base;
240 typedef TensorReshapingOp<NewDimensions, ArgType> XprType;
241 typedef NewDimensions Dimensions;
244 IsAligned = TensorEvaluator<ArgType, Device>::IsAligned,
245 PacketAccess = TensorEvaluator<ArgType, Device>::PacketAccess,
246 BlockAccess = TensorEvaluator<ArgType, Device>::RawAccess,
247 PreferBlockAccess =
false,
248 Layout = TensorEvaluator<ArgType, Device>::Layout,
250 RawAccess = TensorEvaluator<ArgType, Device>::RawAccess
253 EIGEN_STRONG_INLINE TensorEvaluator(
const XprType& op,
const Device& device)
257 typedef typename XprType::Index Index;
258 typedef typename XprType::Scalar Scalar;
259 typedef typename XprType::CoeffReturnType CoeffReturnType;
260 typedef typename PacketType<CoeffReturnType, Device>::type PacketReturnType;
263 typedef internal::TensorBlockDescriptor<TensorEvaluator::NumOutputDims, Index>
267 EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE CoeffReturnType& coeffRef(Index index)
269 return this->m_impl.coeffRef(index);
272 template <
int StoreMode> EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE
273 void writePacket(Index index,
const PacketReturnType& x)
275 this->m_impl.template writePacket<StoreMode>(index, x);
278 template <
typename TensorBlock>
279 EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE
void writeBlock(
280 const TensorBlockDesc& desc,
const TensorBlock& block) {
281 assert(this->m_impl.data() != NULL);
283 typedef typename TensorBlock::XprType TensorBlockExpr;
284 typedef internal::TensorBlockAssignment<
285 Scalar, TensorEvaluator::NumOutputDims, TensorBlockExpr, Index>
288 TensorBlockAssign::Run(
289 TensorBlockAssign::target(desc.dimensions(),
290 internal::strides<Layout>(this->dimensions()),
291 this->m_impl.data(), desc.offset()),
305template<
typename StartIndices,
typename Sizes,
typename XprType>
306struct traits<TensorSlicingOp<StartIndices, Sizes, XprType> > :
public traits<XprType>
308 typedef typename XprType::Scalar Scalar;
309 typedef traits<XprType> XprTraits;
310 typedef typename XprTraits::StorageKind StorageKind;
311 typedef typename XprTraits::Index Index;
312 typedef typename XprType::Nested Nested;
313 typedef typename remove_reference<Nested>::type _Nested;
314 static const int NumDimensions = array_size<StartIndices>::value;
315 static const int Layout = XprTraits::Layout;
316 typedef typename XprTraits::PointerType PointerType;
319template<
typename StartIndices,
typename Sizes,
typename XprType>
320struct eval<TensorSlicingOp<StartIndices, Sizes, XprType>,
Eigen::Dense>
322 typedef const TensorSlicingOp<StartIndices, Sizes, XprType>EIGEN_DEVICE_REF type;
325template<
typename StartIndices,
typename Sizes,
typename XprType>
326struct nested<TensorSlicingOp<StartIndices, Sizes, XprType>, 1, typename eval<TensorSlicingOp<StartIndices, Sizes, XprType> >::type>
328 typedef TensorSlicingOp<StartIndices, Sizes, XprType> type;
335template<
typename StartIndices,
typename Sizes,
typename XprType>
336class TensorSlicingOp :
public TensorBase<TensorSlicingOp<StartIndices, Sizes, XprType> >
339 typedef TensorBase<TensorSlicingOp<StartIndices, Sizes, XprType> > Base;
340 typedef typename Eigen::internal::traits<TensorSlicingOp>::Scalar Scalar;
341 typedef typename XprType::CoeffReturnType CoeffReturnType;
342 typedef typename Eigen::internal::nested<TensorSlicingOp>::type Nested;
343 typedef typename Eigen::internal::traits<TensorSlicingOp>::StorageKind StorageKind;
344 typedef typename Eigen::internal::traits<TensorSlicingOp>::Index Index;
346 EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE TensorSlicingOp(
const XprType& expr,
const StartIndices& indices,
const Sizes& sizes)
347 : m_xpr(expr), m_indices(indices), m_sizes(sizes) {}
350 const StartIndices& startIndices()
const {
return m_indices; }
352 const Sizes& sizes()
const {
return m_sizes; }
355 const typename internal::remove_all<typename XprType::Nested>::type&
356 expression()
const {
return m_xpr; }
358 EIGEN_TENSOR_INHERIT_ASSIGNMENT_OPERATORS(TensorSlicingOp)
361 typename XprType::Nested m_xpr;
362 const StartIndices m_indices;
370template <
typename Index,
typename Device,
bool BlockAccess>
struct MemcpyTriggerForSlicing {
371 EIGEN_DEVICE_FUNC MemcpyTriggerForSlicing(
const Device& device) : threshold_(2 * device.numThreads()) { }
372 EIGEN_DEVICE_FUNC
bool operator ()(
Index total,
Index contiguous)
const {
373 const bool prefer_block_evaluation = BlockAccess && total > 32*1024;
374 return !prefer_block_evaluation && contiguous > threshold_;
384template <
typename Index,
bool BlockAccess>
struct MemcpyTriggerForSlicing<
Index, GpuDevice, BlockAccess> {
385 EIGEN_DEVICE_FUNC MemcpyTriggerForSlicing(
const GpuDevice&) { }
386 EIGEN_DEVICE_FUNC
bool operator ()(
Index,
Index contiguous)
const {
return contiguous > 4*1024*1024; }
393template <
typename Index,
bool BlockAccess>
struct MemcpyTriggerForSlicing<
Index, Eigen::SyclDevice, BlockAccess> {
394 EIGEN_DEVICE_FUNC MemcpyTriggerForSlicing(
const SyclDevice&) { }
395 EIGEN_DEVICE_FUNC
bool operator ()(
Index,
Index contiguous)
const {
return contiguous > 4*1024*1024; }
402template<
typename StartIndices,
typename Sizes,
typename ArgType,
typename Device>
403struct TensorEvaluator<const TensorSlicingOp<StartIndices, Sizes, ArgType>, Device>
405 typedef TensorSlicingOp<StartIndices, Sizes, ArgType> XprType;
406 static const int NumDims = internal::array_size<Sizes>::value;
408 typedef typename XprType::Index Index;
409 typedef typename XprType::Scalar Scalar;
410 typedef typename XprType::CoeffReturnType CoeffReturnType;
411 typedef typename PacketType<CoeffReturnType, Device>::type PacketReturnType;
412 typedef Sizes Dimensions;
413 typedef StorageMemory<CoeffReturnType, Device> Storage;
414 typedef StorageMemory<typename internal::remove_const<CoeffReturnType>::type, Device> ConstCastStorage;
415 typedef typename Storage::Type EvaluatorPointerType;
421 PacketAccess = TensorEvaluator<ArgType, Device>::PacketAccess,
422 BlockAccess = TensorEvaluator<ArgType, Device>::BlockAccess &&
424 !internal::is_same<typename internal::remove_const<Scalar>::type,
bool>::value,
425 PreferBlockAccess =
true,
426 Layout = TensorEvaluator<ArgType, Device>::Layout,
431 typedef typename internal::remove_const<Scalar>::type ScalarNoConst;
434 typedef internal::TensorBlockDescriptor<NumDims, Index> TensorBlockDesc;
435 typedef internal::TensorBlockScratchAllocator<Device> TensorBlockScratch;
438 typedef typename TensorEvaluator<const ArgType, Device>::TensorBlock
442 EIGEN_STRONG_INLINE TensorEvaluator(
const XprType& op,
const Device& device)
443 : m_impl(op.expression(), device), m_device(device), m_dimensions(op.sizes()), m_offsets(op.startIndices())
445 m_is_identity =
true;
446 for (
int i = 0; i < internal::array_size<Dimensions>::value; ++i) {
447 eigen_assert(m_impl.dimensions()[i] >=
448 op.sizes()[i] + op.startIndices()[i]);
449 if (m_impl.dimensions()[i] != op.sizes()[i] ||
450 op.startIndices()[i] != 0) {
451 m_is_identity =
false;
456 if (NumDims == 0)
return;
458 const typename TensorEvaluator<ArgType, Device>::Dimensions& input_dims = m_impl.dimensions();
459 const Sizes& output_dims = op.sizes();
460 if (
static_cast<int>(Layout) ==
static_cast<int>(
ColMajor)) {
461 m_inputStrides[0] = 1;
462 for (
int i = 1; i < NumDims; ++i) {
463 m_inputStrides[i] = m_inputStrides[i-1] * input_dims[i-1];
467 m_outputStrides[0] = 1;
468 for (
int i = 1; i < NumDims; ++i) {
469 m_outputStrides[i] = m_outputStrides[i-1] * output_dims[i-1];
470 m_fastOutputStrides[i] = internal::TensorIntDivisor<Index>(m_outputStrides[i] > 0 ? m_outputStrides[i] : 1);
473 m_inputStrides[NumDims-1] = 1;
474 for (
int i = NumDims - 2; i >= 0; --i) {
475 m_inputStrides[i] = m_inputStrides[i+1] * input_dims[i+1];
479 m_outputStrides[NumDims-1] = 1;
480 for (
int i = NumDims - 2; i >= 0; --i) {
481 m_outputStrides[i] = m_outputStrides[i+1] * output_dims[i+1];
482 m_fastOutputStrides[i] = internal::TensorIntDivisor<Index>(m_outputStrides[i] > 0 ? m_outputStrides[i] : 1);
487 EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE
const Dimensions& dimensions()
const {
return m_dimensions; }
489 EIGEN_STRONG_INLINE
bool evalSubExprsIfNeeded(EvaluatorPointerType data) {
490 m_impl.evalSubExprsIfNeeded(NULL);
491 if (!NumTraits<
typename internal::remove_const<Scalar>::type>::RequireInitialization
492 && data && m_impl.data()) {
493 Index contiguous_values = 1;
494 if (
static_cast<int>(Layout) ==
static_cast<int>(
ColMajor)) {
495 for (
int i = 0; i < NumDims; ++i) {
496 contiguous_values *= dimensions()[i];
497 if (dimensions()[i] != m_impl.dimensions()[i]) {
502 for (
int i = NumDims-1; i >= 0; --i) {
503 contiguous_values *= dimensions()[i];
504 if (dimensions()[i] != m_impl.dimensions()[i]) {
510 const internal::MemcpyTriggerForSlicing<Index, Device, BlockAccess> trigger(m_device);
511 if (trigger(internal::array_prod(dimensions()), contiguous_values)) {
512 EvaluatorPointerType src = (EvaluatorPointerType)m_impl.data();
513 for (Index i = 0; i < internal::array_prod(dimensions()); i += contiguous_values) {
514 Index offset = srcCoeff(i);
515 m_device.memcpy((
void*)(m_device.get(data + i)), m_device.get(src+offset), contiguous_values *
sizeof(Scalar));
523#ifdef EIGEN_USE_THREADS
524 template <
typename EvalSubExprsCallback>
525 EIGEN_STRONG_INLINE
void evalSubExprsIfNeededAsync(
526 EvaluatorPointerType , EvalSubExprsCallback done) {
527 m_impl.evalSubExprsIfNeededAsync(
nullptr, [done](
bool) { done(
true); });
531 EIGEN_STRONG_INLINE
void cleanup() {
535 EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE CoeffReturnType coeff(Index index)
const
538 return m_impl.coeff(index);
540 return m_impl.coeff(srcCoeff(index));
544 template<
int LoadMode>
545 EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE PacketReturnType packet(Index index)
const
547 const int packetSize = PacketType<CoeffReturnType, Device>::size;
548 EIGEN_STATIC_ASSERT((packetSize > 1), YOU_MADE_A_PROGRAMMING_MISTAKE)
549 eigen_assert(index+packetSize-1 < internal::array_prod(dimensions()));
552 return m_impl.template packet<LoadMode>(index);
555 Index inputIndices[] = {0, 0};
556 Index indices[] = {index, index + packetSize - 1};
557 if (
static_cast<int>(Layout) ==
static_cast<int>(
ColMajor)) {
559 for (
int i = NumDims - 1; i > 0; --i) {
560 const Index idx0 = indices[0] / m_fastOutputStrides[i];
561 const Index idx1 = indices[1] / m_fastOutputStrides[i];
562 inputIndices[0] += (idx0 + m_offsets[i]) * m_inputStrides[i];
563 inputIndices[1] += (idx1 + m_offsets[i]) * m_inputStrides[i];
564 indices[0] -= idx0 * m_outputStrides[i];
565 indices[1] -= idx1 * m_outputStrides[i];
567 inputIndices[0] += (indices[0] + m_offsets[0]);
568 inputIndices[1] += (indices[1] + m_offsets[0]);
571 for (
int i = 0; i < NumDims - 1; ++i) {
572 const Index idx0 = indices[0] / m_fastOutputStrides[i];
573 const Index idx1 = indices[1] / m_fastOutputStrides[i];
574 inputIndices[0] += (idx0 + m_offsets[i]) * m_inputStrides[i];
575 inputIndices[1] += (idx1 + m_offsets[i]) * m_inputStrides[i];
576 indices[0] -= idx0 * m_outputStrides[i];
577 indices[1] -= idx1 * m_outputStrides[i];
579 inputIndices[0] += (indices[0] + m_offsets[NumDims-1]);
580 inputIndices[1] += (indices[1] + m_offsets[NumDims-1]);
582 if (inputIndices[1] - inputIndices[0] == packetSize - 1) {
583 PacketReturnType rslt = m_impl.template packet<Unaligned>(inputIndices[0]);
587 EIGEN_ALIGN_MAX
typename internal::remove_const<CoeffReturnType>::type values[packetSize];
588 values[0] = m_impl.coeff(inputIndices[0]);
589 values[packetSize-1] = m_impl.coeff(inputIndices[1]);
591 for (
int i = 1; i < packetSize-1; ++i) {
592 values[i] = coeff(index+i);
594 PacketReturnType rslt = internal::pload<PacketReturnType>(values);
599 EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE TensorOpCost costPerCoeff(
bool vectorized)
const {
600 return m_impl.costPerCoeff(vectorized) + TensorOpCost(0, 0, m_is_identity ? 1 : NumDims);
603 EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE
604 internal::TensorBlockResourceRequirements getResourceRequirements()
const {
605 const size_t target_size = m_device.lastLevelCacheSize();
606 return internal::TensorBlockResourceRequirements::merge(
607 internal::TensorBlockResourceRequirements::skewed<Scalar>(target_size),
608 m_impl.getResourceRequirements());
611 EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE TensorBlock
612 block(TensorBlockDesc& desc, TensorBlockScratch& scratch,
613 bool =
false)
const {
614 TensorBlockDesc arg_desc = desc.WithOffset(srcCoeff(desc.offset()));
615 TensorBlock block = m_impl.block(arg_desc, scratch);
616 if (!arg_desc.HasDestinationBuffer()) desc.DropDestinationBuffer();
620 EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE
typename Storage::Type data()
const {
621 typename Storage::Type result = constCast(m_impl.data());
624 if (
static_cast<int>(Layout) ==
static_cast<int>(
ColMajor)) {
625 for (
int i = 0; i < NumDims; ++i) {
626 if (m_dimensions[i] != m_impl.dimensions()[i]) {
627 offset += m_offsets[i] * m_inputStrides[i];
628 for (
int j = i+1; j < NumDims; ++j) {
629 if (m_dimensions[j] > 1) {
632 offset += m_offsets[j] * m_inputStrides[j];
638 for (
int i = NumDims - 1; i >= 0; --i) {
639 if (m_dimensions[i] != m_impl.dimensions()[i]) {
640 offset += m_offsets[i] * m_inputStrides[i];
641 for (
int j = i-1; j >= 0; --j) {
642 if (m_dimensions[j] > 1) {
645 offset += m_offsets[j] * m_inputStrides[j];
651 return result + offset;
657 EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE
void bind(cl::sycl::handler &cgh)
const {
663 EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE Index srcCoeff(Index index)
const
665 Index inputIndex = 0;
666 if (
static_cast<int>(Layout) ==
static_cast<int>(
ColMajor)) {
668 for (
int i = NumDims - 1; i > 0; --i) {
669 const Index idx = index / m_fastOutputStrides[i];
670 inputIndex += (idx + m_offsets[i]) * m_inputStrides[i];
671 index -= idx * m_outputStrides[i];
673 inputIndex += (index + m_offsets[0]);
676 for (
int i = 0; i < NumDims - 1; ++i) {
677 const Index idx = index / m_fastOutputStrides[i];
678 inputIndex += (idx + m_offsets[i]) * m_inputStrides[i];
679 index -= idx * m_outputStrides[i];
681 inputIndex += (index + m_offsets[NumDims-1]);
686 array<Index, NumDims> m_outputStrides;
687 array<internal::TensorIntDivisor<Index>, NumDims> m_fastOutputStrides;
688 array<Index, NumDims> m_inputStrides;
689 TensorEvaluator<ArgType, Device> m_impl;
690 const Device EIGEN_DEVICE_REF m_device;
691 Dimensions m_dimensions;
693 const StartIndices m_offsets;
698template<
typename StartIndices,
typename Sizes,
typename ArgType,
typename Device>
699struct TensorEvaluator<TensorSlicingOp<StartIndices, Sizes, ArgType>, Device>
700 :
public TensorEvaluator<const TensorSlicingOp<StartIndices, Sizes, ArgType>, Device>
702 typedef TensorEvaluator<const TensorSlicingOp<StartIndices, Sizes, ArgType>, Device> Base;
703 typedef TensorSlicingOp<StartIndices, Sizes, ArgType> XprType;
704 static const int NumDims = internal::array_size<Sizes>::value;
706 typedef typename XprType::Index Index;
707 typedef typename XprType::Scalar Scalar;
708 typedef typename XprType::CoeffReturnType CoeffReturnType;
709 typedef typename PacketType<CoeffReturnType, Device>::type PacketReturnType;
710 typedef Sizes Dimensions;
714 PacketAccess = TensorEvaluator<ArgType, Device>::PacketAccess,
715 BlockAccess = TensorEvaluator<ArgType, Device>::BlockAccess,
716 PreferBlockAccess =
true,
717 Layout = TensorEvaluator<ArgType, Device>::Layout,
719 RawAccess = (NumDims == 1) & TensorEvaluator<ArgType, Device>::RawAccess
722 typedef typename internal::remove_const<Scalar>::type ScalarNoConst;
725 typedef internal::TensorBlockDescriptor<NumDims, Index> TensorBlockDesc;
726 typedef internal::TensorBlockScratchAllocator<Device> TensorBlockScratch;
729 EIGEN_STRONG_INLINE TensorEvaluator(
const XprType& op,
const Device& device)
733 EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE CoeffReturnType& coeffRef(Index index)
735 if (this->m_is_identity) {
736 return this->m_impl.coeffRef(index);
738 return this->m_impl.coeffRef(this->srcCoeff(index));
742 template <
int StoreMode> EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE
743 void writePacket(Index index,
const PacketReturnType& x)
745 if (this->m_is_identity) {
746 this->m_impl.template writePacket<StoreMode>(index, x);
750 const int packetSize = PacketType<CoeffReturnType, Device>::size;
751 Index inputIndices[] = {0, 0};
752 Index indices[] = {index, index + packetSize - 1};
753 if (
static_cast<int>(Layout) ==
static_cast<int>(
ColMajor)) {
755 for (
int i = NumDims - 1; i > 0; --i) {
756 const Index idx0 = indices[0] / this->m_fastOutputStrides[i];
757 const Index idx1 = indices[1] / this->m_fastOutputStrides[i];
758 inputIndices[0] += (idx0 + this->m_offsets[i]) * this->m_inputStrides[i];
759 inputIndices[1] += (idx1 + this->m_offsets[i]) * this->m_inputStrides[i];
760 indices[0] -= idx0 * this->m_outputStrides[i];
761 indices[1] -= idx1 * this->m_outputStrides[i];
763 inputIndices[0] += (indices[0] + this->m_offsets[0]);
764 inputIndices[1] += (indices[1] + this->m_offsets[0]);
767 for (
int i = 0; i < NumDims - 1; ++i) {
768 const Index idx0 = indices[0] / this->m_fastOutputStrides[i];
769 const Index idx1 = indices[1] / this->m_fastOutputStrides[i];
770 inputIndices[0] += (idx0 + this->m_offsets[i]) * this->m_inputStrides[i];
771 inputIndices[1] += (idx1 + this->m_offsets[i]) * this->m_inputStrides[i];
772 indices[0] -= idx0 * this->m_outputStrides[i];
773 indices[1] -= idx1 * this->m_outputStrides[i];
775 inputIndices[0] += (indices[0] + this->m_offsets[NumDims-1]);
776 inputIndices[1] += (indices[1] + this->m_offsets[NumDims-1]);
778 if (inputIndices[1] - inputIndices[0] == packetSize - 1) {
779 this->m_impl.template writePacket<StoreMode>(inputIndices[0], x);
782 EIGEN_ALIGN_MAX CoeffReturnType values[packetSize];
783 internal::pstore<CoeffReturnType, PacketReturnType>(values, x);
784 this->m_impl.coeffRef(inputIndices[0]) = values[0];
785 this->m_impl.coeffRef(inputIndices[1]) = values[packetSize-1];
787 for (
int i = 1; i < packetSize-1; ++i) {
788 this->coeffRef(index+i) = values[i];
793 template<
typename TensorBlock>
794 EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE
void writeBlock(
795 const TensorBlockDesc& desc,
const TensorBlock& block) {
796 TensorBlockDesc arg_desc = desc.WithOffset(this->srcCoeff(desc.offset()));
797 this->m_impl.writeBlock(arg_desc, block);
802template<
typename StartIndices,
typename StopIndices,
typename Str
ides,
typename XprType>
803struct traits<TensorStridingSlicingOp<StartIndices, StopIndices, Strides, XprType> > :
public traits<XprType>
805 typedef typename XprType::Scalar Scalar;
806 typedef traits<XprType> XprTraits;
807 typedef typename XprTraits::StorageKind StorageKind;
808 typedef typename XprTraits::Index
Index;
809 typedef typename XprType::Nested Nested;
810 typedef typename remove_reference<Nested>::type _Nested;
811 static const int NumDimensions = array_size<StartIndices>::value;
812 static const int Layout = XprTraits::Layout;
813 typedef typename XprTraits::PointerType PointerType;
816template<
typename StartIndices,
typename StopIndices,
typename Str
ides,
typename XprType>
817struct eval<TensorStridingSlicingOp<StartIndices, StopIndices, Strides, XprType>, Eigen::Dense>
819 typedef const TensorStridingSlicingOp<StartIndices, StopIndices, Strides, XprType>EIGEN_DEVICE_REF type;
822template<
typename StartIndices,
typename StopIndices,
typename Str
ides,
typename XprType>
823struct nested<TensorStridingSlicingOp<StartIndices, StopIndices, Strides, XprType>, 1, typename eval<TensorStridingSlicingOp<StartIndices, StopIndices, Strides, XprType> >::type>
825 typedef TensorStridingSlicingOp<StartIndices, StopIndices, Strides, XprType> type;
831template<
typename StartIndices,
typename StopIndices,
typename Str
ides,
typename XprType>
832class TensorStridingSlicingOp :
public TensorBase<TensorStridingSlicingOp<StartIndices, StopIndices, Strides, XprType> >
835 typedef TensorBase<TensorStridingSlicingOp<StartIndices, StopIndices, Strides, XprType> > Base;
836 typedef typename internal::traits<TensorStridingSlicingOp>::Scalar Scalar;
837 typedef typename XprType::CoeffReturnType CoeffReturnType;
838 typedef typename internal::nested<TensorStridingSlicingOp>::type Nested;
839 typedef typename internal::traits<TensorStridingSlicingOp>::StorageKind StorageKind;
840 typedef typename internal::traits<TensorStridingSlicingOp>::Index Index;
842 EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE TensorStridingSlicingOp(
843 const XprType& expr,
const StartIndices& startIndices,
844 const StopIndices& stopIndices,
const Strides& strides)
845 : m_xpr(expr), m_startIndices(startIndices), m_stopIndices(stopIndices),
846 m_strides(strides) {}
849 const StartIndices& startIndices()
const {
return m_startIndices; }
851 const StartIndices& stopIndices()
const {
return m_stopIndices; }
853 const StartIndices& strides()
const {
return m_strides; }
856 const typename internal::remove_all<typename XprType::Nested>::type&
857 expression()
const {
return m_xpr; }
859 EIGEN_TENSOR_INHERIT_ASSIGNMENT_OPERATORS(TensorStridingSlicingOp)
862 typename XprType::Nested m_xpr;
863 const StartIndices m_startIndices;
864 const StopIndices m_stopIndices;
865 const Strides m_strides;
869template<
typename StartIndices,
typename StopIndices,
typename Str
ides,
typename ArgType,
typename Device>
870struct TensorEvaluator<const TensorStridingSlicingOp<StartIndices, StopIndices, Strides, ArgType>, Device>
872 typedef TensorStridingSlicingOp<StartIndices, StopIndices, Strides, ArgType> XprType;
873 static const int NumDims = internal::array_size<Strides>::value;
874 typedef typename XprType::Index Index;
875 typedef typename XprType::Scalar Scalar;
876 typedef typename XprType::CoeffReturnType CoeffReturnType;
877 typedef typename PacketType<CoeffReturnType, Device>::type PacketReturnType;
878 typedef StorageMemory<CoeffReturnType, Device> Storage;
879 typedef typename Storage::Type EvaluatorPointerType;
880 typedef Strides Dimensions;
886 PacketAccess =
false,
888 PreferBlockAccess = TensorEvaluator<ArgType, Device>::PreferBlockAccess,
889 Layout = TensorEvaluator<ArgType, Device>::Layout,
894 typedef internal::TensorBlockNotImplemented TensorBlock;
897 EIGEN_STRONG_INLINE TensorEvaluator(
const XprType& op,
const Device& device)
898 : m_impl(op.expression(), device),
900 m_strides(op.strides())
903 DSizes<Index, NumDims> startIndicesClamped, stopIndicesClamped;
904 for (ptrdiff_t i = 0; i < internal::array_size<Dimensions>::value; ++i) {
905 eigen_assert(m_strides[i] != 0 &&
"0 stride is invalid");
906 if (m_strides[i] > 0) {
907 startIndicesClamped[i] =
908 clamp(op.startIndices()[i], 0, m_impl.dimensions()[i]);
909 stopIndicesClamped[i] =
910 clamp(op.stopIndices()[i], 0, m_impl.dimensions()[i]);
913 startIndicesClamped[i] =
914 clamp(op.startIndices()[i], -1, m_impl.dimensions()[i] - 1);
915 stopIndicesClamped[i] =
916 clamp(op.stopIndices()[i], -1, m_impl.dimensions()[i] - 1);
918 m_startIndices[i] = startIndicesClamped[i];
921 typedef typename TensorEvaluator<ArgType, Device>::Dimensions InputDimensions;
922 const InputDimensions& input_dims = m_impl.dimensions();
925 m_is_identity =
true;
926 for (
int i = 0; i < NumDims; i++) {
927 Index interval = stopIndicesClamped[i] - startIndicesClamped[i];
928 if (interval == 0 || ((interval < 0) != (m_strides[i] < 0))) {
932 (interval / m_strides[i]) + (interval % m_strides[i] != 0 ? 1 : 0);
933 eigen_assert(m_dimensions[i] >= 0);
935 if (m_strides[i] != 1 || interval != m_impl.dimensions()[i]) {
936 m_is_identity =
false;
940 Strides output_dims = m_dimensions;
942 if (
static_cast<int>(Layout) ==
static_cast<int>(
ColMajor)) {
943 m_inputStrides[0] = m_strides[0];
944 m_offsets[0] = startIndicesClamped[0];
945 Index previousDimProduct = 1;
946 for (
int i = 1; i < NumDims; ++i) {
947 previousDimProduct *= input_dims[i-1];
948 m_inputStrides[i] = previousDimProduct * m_strides[i];
949 m_offsets[i] = startIndicesClamped[i] * previousDimProduct;
953 m_outputStrides[0] = 1;
954 for (
int i = 1; i < NumDims; ++i) {
955 m_outputStrides[i] = m_outputStrides[i-1] * output_dims[i-1];
956 m_fastOutputStrides[i] = internal::TensorIntDivisor<Index>(m_outputStrides[i] > 0 ? m_outputStrides[i] : 1);
959 m_inputStrides[NumDims-1] = m_strides[NumDims-1];
960 m_offsets[NumDims-1] = startIndicesClamped[NumDims-1];
961 Index previousDimProduct = 1;
962 for (
int i = NumDims - 2; i >= 0; --i) {
963 previousDimProduct *= input_dims[i+1];
964 m_inputStrides[i] = previousDimProduct * m_strides[i];
965 m_offsets[i] = startIndicesClamped[i] * previousDimProduct;
968 m_outputStrides[NumDims-1] = 1;
969 for (
int i = NumDims - 2; i >= 0; --i) {
970 m_outputStrides[i] = m_outputStrides[i+1] * output_dims[i+1];
971 m_fastOutputStrides[i] = internal::TensorIntDivisor<Index>(m_outputStrides[i] > 0 ? m_outputStrides[i] : 1);
976 EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE
const Dimensions& dimensions()
const {
return m_dimensions; }
979 EIGEN_STRONG_INLINE
bool evalSubExprsIfNeeded(EvaluatorPointerType) {
980 m_impl.evalSubExprsIfNeeded(NULL);
984 EIGEN_STRONG_INLINE
void cleanup() {
988 EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE CoeffReturnType coeff(Index index)
const
991 return m_impl.coeff(index);
993 return m_impl.coeff(srcCoeff(index));
997 EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE TensorOpCost costPerCoeff(
bool vectorized)
const {
998 return m_impl.costPerCoeff(vectorized) + TensorOpCost(0, 0, m_is_identity ? 1 : NumDims);
1001 EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE
typename Storage::Type data()
const {
1004#ifdef EIGEN_USE_SYCL
1006 EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE
void bind(cl::sycl::handler &cgh)
const {
1011 EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE Index srcCoeff(Index index)
const
1013 Index inputIndex = 0;
1014 if (
static_cast<int>(Layout) ==
static_cast<int>(
ColMajor)) {
1016 for (
int i = NumDims - 1; i >= 0; --i) {
1017 const Index idx = index / m_fastOutputStrides[i];
1018 inputIndex += idx * m_inputStrides[i] + m_offsets[i];
1019 index -= idx * m_outputStrides[i];
1023 for (
int i = 0; i < NumDims; ++i) {
1024 const Index idx = index / m_fastOutputStrides[i];
1025 inputIndex += idx * m_inputStrides[i] + m_offsets[i];
1026 index -= idx * m_outputStrides[i];
1032 static EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE Index clamp(Index value, Index min, Index max) {
1033#ifndef SYCL_DEVICE_ONLY
1034 return numext::maxi(min, numext::mini(max,value));
1036 return cl::sycl::clamp(value, min, max);
1040 array<Index, NumDims> m_outputStrides;
1041 array<internal::TensorIntDivisor<Index>, NumDims> m_fastOutputStrides;
1042 array<Index, NumDims> m_inputStrides;
1044 TensorEvaluator<ArgType, Device> m_impl;
1045 const Device EIGEN_DEVICE_REF m_device;
1046 DSizes<Index, NumDims> m_startIndices;
1047 DSizes<Index, NumDims> m_dimensions;
1048 DSizes<Index, NumDims> m_offsets;
1049 const Strides m_strides;
1053template<
typename StartIndices,
typename StopIndices,
typename Str
ides,
typename ArgType,
typename Device>
1054struct TensorEvaluator<TensorStridingSlicingOp<StartIndices, StopIndices, Strides, ArgType>, Device>
1055 :
public TensorEvaluator<const TensorStridingSlicingOp<StartIndices, StopIndices, Strides, ArgType>, Device>
1057 typedef TensorEvaluator<const TensorStridingSlicingOp<StartIndices, StopIndices, Strides, ArgType>, Device> Base;
1058 typedef TensorStridingSlicingOp<StartIndices, StopIndices, Strides, ArgType> XprType;
1059 static const int NumDims = internal::array_size<Strides>::value;
1063 PacketAccess =
false,
1064 BlockAccess =
false,
1065 PreferBlockAccess = TensorEvaluator<ArgType, Device>::PreferBlockAccess,
1066 Layout = TensorEvaluator<ArgType, Device>::Layout,
1067 CoordAccess = TensorEvaluator<ArgType, Device>::CoordAccess,
1072 typedef internal::TensorBlockNotImplemented TensorBlock;
1075 EIGEN_STRONG_INLINE TensorEvaluator(
const XprType& op,
const Device& device)
1079 typedef typename XprType::Index Index;
1080 typedef typename XprType::Scalar Scalar;
1081 typedef typename XprType::CoeffReturnType CoeffReturnType;
1082 typedef typename PacketType<CoeffReturnType, Device>::type PacketReturnType;
1083 typedef Strides Dimensions;
1085 EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE CoeffReturnType& coeffRef(Index index)
1087 if (this->m_is_identity) {
1088 return this->m_impl.coeffRef(index);
1090 return this->m_impl.coeffRef(this->srcCoeff(index));
The tensor base class.
Definition TensorForwardDeclarations.h:56
Tensor reshaping class.
Definition TensorMorphing.h:50
Namespace containing all symbols from the Eigen library.
EIGEN_DEFAULT_DENSE_INDEX_TYPE Index
The tensor evaluator class.
Definition TensorEvaluator.h:27