11#ifndef EIGEN_TENSOR_TENSOR_EVALUATOR_H
12#define EIGEN_TENSOR_TENSOR_EVALUATOR_H
15#include "./InternalHeaderCheck.h"
26template <
typename Functor,
typename =
void>
27struct tensor_functor_is_repeatable : std::false_type {};
29template <
typename Functor>
30struct tensor_functor_is_repeatable<Functor, void_t<decltype(functor_traits<Functor>::IsRepeatable)>>
31 : bool_constant<functor_traits<Functor>::IsRepeatable> {};
46template <
typename Derived,
typename Device>
47struct TensorEvaluator {
48 typedef typename Derived::Index Index;
49 typedef typename Derived::Scalar Scalar;
50 typedef typename Derived::Scalar CoeffReturnType;
51 typedef typename PacketType<CoeffReturnType, Device>::type PacketReturnType;
52 typedef typename Derived::Dimensions Dimensions;
53 typedef Derived XprType;
54 static constexpr int PacketSize = PacketType<CoeffReturnType, Device>::size;
55 typedef typename internal::traits<Derived>::template MakePointer<Scalar>::Type TensorPointerType;
56 typedef StorageMemory<Scalar, Device> Storage;
57 typedef typename Storage::Type EvaluatorPointerType;
60 static constexpr int NumCoords =
61 internal::traits<Derived>::NumDimensions > 0 ? internal::traits<Derived>::NumDimensions : 0;
62 static constexpr int Layout = Derived::Layout;
65 IsAligned = Derived::IsAligned,
66 PacketAccess = (PacketType<CoeffReturnType, Device>::size > 1),
67 BlockAccess = internal::is_arithmetic<std::remove_const_t<Scalar>>::value,
68 PreferBlockAccess =
false,
69 CoordAccess = NumCoords > 0,
73 typedef std::remove_const_t<Scalar> ScalarNoConst;
76 typedef internal::TensorBlockDescriptor<NumCoords, Index> TensorBlockDesc;
77 typedef internal::TensorBlockScratchAllocator<Device> TensorBlockScratch;
79 typedef typename internal::TensorMaterializedBlock<ScalarNoConst, NumCoords, Layout, Index> TensorBlock;
82 EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE TensorEvaluator(
const Derived& m,
const Device& device)
83 : m_data(device.get(
const_cast<TensorPointerType
>(m.data()))), m_dims(m.dimensions()), m_device(device) {}
85 EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE
const Dimensions& dimensions()
const {
return m_dims; }
87 EIGEN_STRONG_INLINE
bool evalSubExprsIfNeeded(EvaluatorPointerType dest) {
88 EIGEN_IF_CONSTEXPR (!
NumTraits<std::remove_const_t<Scalar>>::RequireInitialization) {
90 m_device.memcpy((
void*)(m_device.get(dest)), m_device.get(m_data), m_dims.TotalSize() *
sizeof(Scalar));
97#ifdef EIGEN_USE_THREADS
98 template <
typename EvalSubExprsCallback>
99 EIGEN_STRONG_INLINE
void evalSubExprsIfNeededAsync(EvaluatorPointerType dest, EvalSubExprsCallback done) {
101 done(evalSubExprsIfNeeded(dest));
105 EIGEN_STRONG_INLINE
void cleanup() {}
107 EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE CoeffReturnType coeff(Index index)
const {
108 eigen_assert(m_data !=
nullptr);
109 return m_data[index];
112 EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE CoeffReturnType& coeffRef(Index index)
const {
113 eigen_assert(m_data !=
nullptr);
114 return m_data[index];
117 template <
int LoadMode>
118 EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE PacketReturnType packet(Index index)
const {
119 return internal::ploadt<PacketReturnType, LoadMode>(m_data + index);
127 template <
typename PacketReturnTypeT>
128 EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE
129 std::enable_if_t<internal::unpacket_traits<PacketReturnTypeT>::masked_load_available, PacketReturnTypeT>
130 partialPacket(Index index,
typename internal::unpacket_traits<PacketReturnTypeT>::mask_t umask)
const {
131 return internal::ploadu<PacketReturnTypeT>(m_data + index, umask);
134 template <
int StoreMode>
135 EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE
void writePacket(Index index,
const PacketReturnType& x)
const {
136 return internal::pstoret<Scalar, PacketReturnType, StoreMode>(m_data + index, x);
139 EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE CoeffReturnType coeff(
const array<DenseIndex, NumCoords>& coords)
const {
140 eigen_assert(m_data !=
nullptr);
141 EIGEN_IF_CONSTEXPR (
static_cast<int>(Layout) ==
static_cast<int>(
ColMajor)) {
142 return m_data[m_dims.IndexOfColMajor(coords)];
144 return m_data[m_dims.IndexOfRowMajor(coords)];
148 EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE CoeffReturnType& coeffRef(
const array<DenseIndex, NumCoords>& coords)
const {
149 eigen_assert(m_data !=
nullptr);
150 EIGEN_IF_CONSTEXPR (
static_cast<int>(Layout) ==
static_cast<int>(
ColMajor)) {
151 return m_data[m_dims.IndexOfColMajor(coords)];
153 return m_data[m_dims.IndexOfRowMajor(coords)];
157 EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE TensorOpCost costPerCoeff(
bool vectorized)
const {
158 return TensorOpCost(
sizeof(CoeffReturnType), 0, 0, vectorized, PacketType<CoeffReturnType, Device>::size);
161 EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE internal::TensorBlockResourceRequirements getResourceRequirements()
const {
162 return internal::TensorBlockResourceRequirements::any();
165 EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE TensorBlock block(TensorBlockDesc& desc, TensorBlockScratch& scratch,
166 bool =
false)
const {
167 eigen_assert(m_data !=
nullptr);
168 return TensorBlock::materialize(m_data, m_dims, desc, scratch);
171 template <
typename TensorBlock>
172 EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE
void writeBlock(
const TensorBlockDesc& desc,
const TensorBlock& block) {
173 eigen_assert(m_data !=
nullptr);
175 typedef typename TensorBlock::XprType TensorBlockExpr;
176 typedef internal::TensorBlockAssignment<Scalar, NumCoords, TensorBlockExpr, Index> TensorBlockAssign;
178 TensorBlockAssign::Run(
179 TensorBlockAssign::target(desc.dimensions(), internal::strides<Layout>(m_dims), m_data, desc.offset()),
183 EIGEN_DEVICE_FUNC EvaluatorPointerType data()
const {
return m_data; }
186 EvaluatorPointerType m_data;
188 const Device EIGEN_DEVICE_REF m_device;
193EIGEN_DEVICE_FUNC EIGEN_ALWAYS_INLINE T loadConstant(
const T* address) {
197#if defined(EIGEN_CUDA_ARCH)
199EIGEN_DEVICE_FUNC EIGEN_ALWAYS_INLINE
float loadConstant(
const float* address) {
200 return __ldg(address);
203EIGEN_DEVICE_FUNC EIGEN_ALWAYS_INLINE
double loadConstant(
const double* address) {
204 return __ldg(address);
207EIGEN_DEVICE_FUNC EIGEN_ALWAYS_INLINE Eigen::half loadConstant(
const Eigen::half* address) {
208 return Eigen::half(half_impl::raw_uint16_to_half(__ldg(&address->x)));
215template <
typename Derived,
typename Device>
217 typedef typename Derived::Index Index;
218 typedef typename Derived::Scalar Scalar;
219 typedef typename Derived::Scalar CoeffReturnType;
220 typedef typename PacketType<CoeffReturnType, Device>::type PacketReturnType;
221 typedef typename Derived::Dimensions Dimensions;
222 typedef const Derived XprType;
223 typedef typename internal::traits<Derived>::template MakePointer<const Scalar>::Type TensorPointerType;
224 typedef StorageMemory<const Scalar, Device> Storage;
225 typedef typename Storage::Type EvaluatorPointerType;
227 typedef std::remove_const_t<Scalar> ScalarNoConst;
230 static constexpr int NumCoords =
231 internal::traits<Derived>::NumDimensions > 0 ? internal::traits<Derived>::NumDimensions : 0;
232 static constexpr int PacketSize = PacketType<CoeffReturnType, Device>::size;
233 static constexpr int Layout = Derived::Layout;
236 IsAligned = Derived::IsAligned,
237 PacketAccess = (PacketType<CoeffReturnType, Device>::size > 1),
238 BlockAccess = internal::is_arithmetic<ScalarNoConst>::value,
239 PreferBlockAccess =
false,
240 CoordAccess = NumCoords > 0,
245 typedef internal::TensorBlockDescriptor<NumCoords, Index> TensorBlockDesc;
246 typedef internal::TensorBlockScratchAllocator<Device> TensorBlockScratch;
248 typedef typename internal::TensorMaterializedBlock<ScalarNoConst, NumCoords, Layout, Index> TensorBlock;
251 EIGEN_STRONG_INLINE EIGEN_DEVICE_FUNC TensorEvaluator(
const Derived& m,
const Device& device)
252 : m_data(device.get(m.data())), m_dims(m.dimensions()), m_device(device) {}
254 EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE
const Dimensions& dimensions()
const {
return m_dims; }
256 EIGEN_STRONG_INLINE
bool evalSubExprsIfNeeded(EvaluatorPointerType data) {
257 EIGEN_IF_CONSTEXPR (!NumTraits<std::remove_const_t<Scalar>>::RequireInitialization) {
259 m_device.memcpy((
void*)(m_device.get(data)), m_device.get(m_data), m_dims.TotalSize() *
sizeof(Scalar));
266#ifdef EIGEN_USE_THREADS
267 template <
typename EvalSubExprsCallback>
268 EIGEN_STRONG_INLINE
void evalSubExprsIfNeededAsync(EvaluatorPointerType dest, EvalSubExprsCallback done) {
270 done(evalSubExprsIfNeeded(dest));
274 EIGEN_STRONG_INLINE
void cleanup() {}
276 EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE CoeffReturnType coeff(Index index)
const {
277 eigen_assert(m_data !=
nullptr);
278 return internal::loadConstant(m_data + index);
281 template <
int LoadMode>
282 EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE PacketReturnType packet(Index index)
const {
283 return internal::ploadt_ro<PacketReturnType, LoadMode>(m_data + index);
291 template <
typename PacketReturnTypeT>
292 EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE
293 std::enable_if_t<internal::unpacket_traits<PacketReturnTypeT>::masked_load_available, PacketReturnTypeT>
294 partialPacket(Index index,
typename internal::unpacket_traits<PacketReturnTypeT>::mask_t umask)
const {
295 return internal::ploadu<PacketReturnTypeT>(m_data + index, umask);
298 EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE CoeffReturnType coeff(
const array<DenseIndex, NumCoords>& coords)
const {
299 eigen_assert(m_data !=
nullptr);
300 const Index index = (
static_cast<int>(Layout) ==
static_cast<int>(
ColMajor)) ? m_dims.IndexOfColMajor(coords)
301 : m_dims.IndexOfRowMajor(coords);
302 return internal::loadConstant(m_data + index);
305 EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE TensorOpCost costPerCoeff(
bool vectorized)
const {
306 return TensorOpCost(
sizeof(CoeffReturnType), 0, 0, vectorized, PacketType<CoeffReturnType, Device>::size);
309 EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE internal::TensorBlockResourceRequirements getResourceRequirements()
const {
310 return internal::TensorBlockResourceRequirements::any();
313 EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE TensorBlock block(TensorBlockDesc& desc, TensorBlockScratch& scratch,
314 bool =
false)
const {
315 eigen_assert(m_data !=
nullptr);
316 return TensorBlock::materialize(m_data, m_dims, desc, scratch);
319 EIGEN_DEVICE_FUNC EvaluatorPointerType data()
const {
return m_data; }
322 EvaluatorPointerType m_data;
324 const Device EIGEN_DEVICE_REF m_device;
329template <
typename NullaryOp,
typename ArgType,
typename Device>
331 typedef TensorCwiseNullaryOp<NullaryOp, ArgType> XprType;
333 EIGEN_DEVICE_FUNC TensorEvaluator(
const XprType& op,
const Device& device)
334 : m_functor(op.functor()), m_argImpl(op.nestedExpression(), device), m_wrapper() {}
336 typedef typename XprType::Index Index;
337 typedef typename XprType::Scalar Scalar;
338 typedef typename internal::traits<XprType>::Scalar CoeffReturnType;
339 typedef typename PacketType<CoeffReturnType, Device>::type PacketReturnType;
340 static constexpr int PacketSize = PacketType<CoeffReturnType, Device>::size;
341 typedef typename TensorEvaluator<ArgType, Device>::Dimensions Dimensions;
342 typedef StorageMemory<CoeffReturnType, Device> Storage;
343 typedef typename Storage::Type EvaluatorPointerType;
344 static constexpr int NumDims = internal::array_size<Dimensions>::value;
345 typedef std::remove_const_t<CoeffReturnType> ScalarNoConst;
352 static constexpr bool RepeatableFunctor = internal::tensor_functor_is_repeatable<NullaryOp>::value;
356 static constexpr bool IndexDependentFunctor =
357 internal::has_unary_operator<NullaryOp, Index>::value || internal::has_binary_operator<NullaryOp, Index>::value;
365 static constexpr bool IndexIndependentFunctor =
366 RepeatableFunctor && !IndexDependentFunctor && internal::has_nullary_operator<NullaryOp, Index>::value;
368 static constexpr int Layout = TensorEvaluator<ArgType, Device>::Layout;
371 PacketAccess = internal::functor_traits<NullaryOp>::PacketAccess
373 && (PacketType<CoeffReturnType, Device>::size > 1)
383 BlockAccess = NumDims > 0 && internal::is_arithmetic<ScalarNoConst>::value &&
384 (IndexIndependentFunctor || (IndexDependentFunctor && RepeatableFunctor)),
385 PreferBlockAccess =
false,
391 typedef internal::TensorBlockDescriptor<NumDims, Index> TensorBlockDesc;
392 typedef internal::TensorBlockScratchAllocator<Device> TensorBlockScratch;
398 class TensorNullaryBlock {
400 typedef TensorMap<const Tensor<ScalarNoConst, NumDims, Layout, Index>> ArgXprType;
401 typedef TensorCwiseNullaryOp<NullaryOp, const ArgXprType> XprType;
402 typedef typename internal::XprScalar<XprType>::type Scalar;
404 TensorNullaryBlock(
const NullaryOp& functor,
const DSizes<Index, NumDims>& dimensions)
405 : m_functor(functor), m_dimensions(dimensions) {}
407 constexpr internal::TensorBlockKind kind()
const {
return internal::TensorBlockKind::kExpr; }
408 XprType expr()
const {
409 return XprType(ArgXprType(
static_cast<const ScalarNoConst*
>(
nullptr), m_dimensions), m_functor);
411 const Scalar* data()
const {
return nullptr; }
416 DSizes<Index, NumDims> m_dimensions;
419 typedef internal::TensorMaterializedBlock<ScalarNoConst, NumDims, Layout, Index> MaterializedTensorBlock;
420 typedef std::conditional_t<IndexIndependentFunctor, TensorNullaryBlock, MaterializedTensorBlock> TensorBlock;
423 EIGEN_DEVICE_FUNC
const Dimensions& dimensions()
const {
return m_argImpl.dimensions(); }
425 EIGEN_STRONG_INLINE
bool evalSubExprsIfNeeded(EvaluatorPointerType) {
return true; }
427#ifdef EIGEN_USE_THREADS
428 template <
typename EvalSubExprsCallback>
429 EIGEN_STRONG_INLINE
void evalSubExprsIfNeededAsync(EvaluatorPointerType, EvalSubExprsCallback done) {
434 EIGEN_STRONG_INLINE
void cleanup() {}
436 EIGEN_DEVICE_FUNC CoeffReturnType coeff(Index index)
const {
return m_wrapper(m_functor, index); }
438 template <
int LoadMode>
439 EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE PacketReturnType packet(Index index)
const {
440 return m_wrapper.template packetOp<PacketReturnType, Index>(m_functor, index);
443 EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE TensorOpCost costPerCoeff(
bool vectorized)
const {
449 return TensorOpCost(0, 0, 0, vectorized, PacketType<CoeffReturnType, Device>::size);
452 EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE internal::TensorBlockResourceRequirements getResourceRequirements()
const {
453 return internal::TensorBlockResourceRequirements::any();
459 template <
typename Self,
bool Vectorizable>
460 struct NullaryBlockFill {
461 static EIGEN_STRONG_INLINE
void Run(
const Self& self, ScalarNoConst* buffer, Index tensor_index, Index count) {
462 for (Index i = 0; i < count; ++i) {
463 buffer[i] = self.m_wrapper(self.m_functor, tensor_index + i);
468 template <
typename Self>
469 struct NullaryBlockFill<Self, true> {
470 static EIGEN_STRONG_INLINE
void Run(
const Self& self, ScalarNoConst* buffer, Index tensor_index, Index count) {
472 for (; i + PacketSize <= count; i += PacketSize) {
473 internal::pstoreu(buffer + i,
474 self.m_wrapper.template packetOp<PacketReturnType, Index>(self.m_functor, tensor_index + i));
476 for (; i < count; ++i) {
477 buffer[i] = self.m_wrapper(self.m_functor, tensor_index + i);
482 template <
typename Self,
bool IndexIndependent>
483 struct NullaryBlockImpl {
486 static EIGEN_STRONG_INLINE TensorBlock Run(
const Self& self, TensorBlockDesc& desc, TensorBlockScratch&) {
487 return TensorBlock(self.m_functor, desc.dimensions());
491 template <
typename Self>
492 struct NullaryBlockImpl<Self, false> {
498 static TensorBlock Run(
const Self& self, TensorBlockDesc& desc, TensorBlockScratch& scratch) {
499 constexpr bool is_col_major =
static_cast<int>(Layout) ==
static_cast<int>(ColMajor);
500 typedef NullaryBlockFill<Self, bool(PacketAccess)> Fill;
502 if (desc.size() == 0) {
503 return TensorBlock(internal::TensorBlockKind::kView,
nullptr, desc.dimensions());
507 const Dimensions& dims = self.m_argImpl.dimensions();
508 array<Index, NumDims> tensor_strides;
509 EIGEN_IF_CONSTEXPR (is_col_major) {
510 tensor_strides[0] = 1;
511 for (
int i = 1; i < NumDims; ++i) tensor_strides[i] = tensor_strides[i - 1] * dims[i - 1];
513 tensor_strides[NumDims - 1] = 1;
514 for (
int i = NumDims - 2; i >= 0; --i) tensor_strides[i] = tensor_strides[i + 1] * dims[i + 1];
518 struct BlockIteratorState {
524 array<BlockIteratorState, NumDims> it;
525 for (
int i = 0; i < NumDims; ++i) {
526 const int dim = is_col_major ? i : NumDims - 1 - i;
527 const Index size = desc.dimension(dim);
528 const Index stride = tensor_strides[dim];
529 it[i] = {size, 0, stride, stride * (size - 1)};
531 eigen_assert(it[0].tensor_stride == 1);
533 const typename TensorBlock::Storage block_storage = TensorBlock::prepareStorage(desc, scratch);
534 ScalarNoConst* block_buffer = block_storage.data();
536 const Index inner_size = it[0].size;
537 Index tensor_index = desc.offset();
540 Fill::Run(self, block_buffer + offset, tensor_index, inner_size);
541 offset += inner_size;
545 for (; i < NumDims; ++i) {
546 if (++it[i].count < it[i].size) {
547 tensor_index += it[i].tensor_stride;
551 tensor_index -= it[i].tensor_span;
553 if (i == NumDims)
break;
556 return block_storage.AsTensorMaterializedBlock();
560 EIGEN_STRONG_INLINE TensorBlock block(TensorBlockDesc& desc, TensorBlockScratch& scratch,
561 bool =
false)
const {
562 typedef TensorEvaluator<const TensorCwiseNullaryOp<NullaryOp, ArgType>, Device> Self;
563 return NullaryBlockImpl<Self, IndexIndependentFunctor>::Run(*
this, desc, scratch);
566 EIGEN_DEVICE_FUNC EvaluatorPointerType data()
const {
return nullptr; }
569 const NullaryOp m_functor;
570 TensorEvaluator<ArgType, Device> m_argImpl;
571 const internal::nullary_wrapper<CoeffReturnType, NullaryOp> m_wrapper;
576template <
typename UnaryOp,
typename ArgType,
typename Device>
578 typedef TensorCwiseUnaryOp<UnaryOp, ArgType> XprType;
580 static constexpr int Layout = TensorEvaluator<ArgType, Device>::Layout;
582 IsAligned = TensorEvaluator<ArgType, Device>::IsAligned,
584 int(TensorEvaluator<ArgType, Device>::PacketAccess) & int(internal::functor_traits<UnaryOp>::PacketAccess),
585 BlockAccess = TensorEvaluator<ArgType, Device>::BlockAccess,
586 PreferBlockAccess = TensorEvaluator<ArgType, Device>::PreferBlockAccess,
591 EIGEN_DEVICE_FUNC TensorEvaluator(
const XprType& op,
const Device& device)
592 : m_device(device), m_functor(op.functor()), m_argImpl(op.nestedExpression(), device) {}
594 typedef typename XprType::Index Index;
595 typedef typename XprType::Scalar Scalar;
596 typedef std::remove_const_t<Scalar> ScalarNoConst;
597 typedef typename internal::traits<XprType>::Scalar CoeffReturnType;
598 typedef typename PacketType<CoeffReturnType, Device>::type PacketReturnType;
599 static constexpr int PacketSize = PacketType<CoeffReturnType, Device>::size;
600 typedef typename TensorEvaluator<ArgType, Device>::Dimensions Dimensions;
601 typedef StorageMemory<CoeffReturnType, Device> Storage;
602 typedef typename Storage::Type EvaluatorPointerType;
603 static constexpr int NumDims = internal::array_size<Dimensions>::value;
606 typedef internal::TensorBlockDescriptor<NumDims, Index> TensorBlockDesc;
607 typedef internal::TensorBlockScratchAllocator<Device> TensorBlockScratch;
609 typedef typename TensorEvaluator<const ArgType, Device>::TensorBlock ArgTensorBlock;
611 typedef internal::TensorCwiseUnaryBlock<UnaryOp, ArgTensorBlock> TensorBlock;
614 EIGEN_DEVICE_FUNC
const Dimensions& dimensions()
const {
return m_argImpl.dimensions(); }
616 EIGEN_STRONG_INLINE
bool evalSubExprsIfNeeded(EvaluatorPointerType) {
617 m_argImpl.evalSubExprsIfNeeded(
nullptr);
621#ifdef EIGEN_USE_THREADS
622 template <
typename EvalSubExprsCallback>
623 EIGEN_STRONG_INLINE
void evalSubExprsIfNeededAsync(EvaluatorPointerType, EvalSubExprsCallback done) {
624 m_argImpl.evalSubExprsIfNeededAsync(
nullptr, [done](
bool) { done(
true); });
628 EIGEN_STRONG_INLINE
void cleanup() { m_argImpl.cleanup(); }
630 EIGEN_DEVICE_FUNC CoeffReturnType coeff(Index index)
const {
return m_functor(m_argImpl.coeff(index)); }
632 template <
int LoadMode>
633 EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE PacketReturnType packet(Index index)
const {
634 return m_functor.packetOp(m_argImpl.template packet<LoadMode>(index));
637 EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE TensorOpCost costPerCoeff(
bool vectorized)
const {
638 const double functor_cost = internal::functor_traits<UnaryOp>::Cost;
639 return m_argImpl.costPerCoeff(vectorized) + TensorOpCost(0, 0, functor_cost, vectorized, PacketSize);
642 EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE internal::TensorBlockResourceRequirements getResourceRequirements()
const {
643 static constexpr double functor_cost = internal::functor_traits<UnaryOp>::Cost;
644 return m_argImpl.getResourceRequirements().addCostPerCoeff({0, 0, functor_cost / PacketSize});
647 EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE TensorBlock block(TensorBlockDesc& desc, TensorBlockScratch& scratch,
648 bool =
false)
const {
656 constexpr bool ScalarTypesMatch =
657 std::is_same<std::remove_const_t<Scalar>,
658 std::remove_const_t<typename TensorEvaluator<ArgType, Device>::Scalar>>::value;
659 EIGEN_IF_CONSTEXPR (!ScalarTypesMatch) {
660 desc.DropDestinationBuffer();
662 return TensorBlock(m_argImpl.block(desc, scratch), m_functor);
665 EIGEN_DEVICE_FUNC EvaluatorPointerType data()
const {
return nullptr; }
668 const Device EIGEN_DEVICE_REF m_device;
669 const UnaryOp m_functor;
670 TensorEvaluator<ArgType, Device> m_argImpl;
675template <
typename BinaryOp,
typename LeftArgType,
typename RightArgType,
typename Device>
677 typedef TensorCwiseBinaryOp<BinaryOp, LeftArgType, RightArgType> XprType;
679 static constexpr int Layout = TensorEvaluator<LeftArgType, Device>::Layout;
682 int(TensorEvaluator<LeftArgType, Device>::IsAligned) & int(TensorEvaluator<RightArgType, Device>::IsAligned),
683 PacketAccess = int(TensorEvaluator<LeftArgType, Device>::PacketAccess) &
684 int(TensorEvaluator<RightArgType, Device>::PacketAccess) &
685 int(internal::functor_traits<BinaryOp>::PacketAccess),
686 BlockAccess = int(TensorEvaluator<LeftArgType, Device>::BlockAccess) &
687 int(TensorEvaluator<RightArgType, Device>::BlockAccess),
688 PreferBlockAccess = int(TensorEvaluator<LeftArgType, Device>::PreferBlockAccess) |
689 int(TensorEvaluator<RightArgType, Device>::PreferBlockAccess),
694 EIGEN_DEVICE_FUNC TensorEvaluator(
const XprType& op,
const Device& device)
696 m_functor(op.functor()),
697 m_leftImpl(op.lhsExpression(), device),
698 m_rightImpl(op.rhsExpression(), device) {
699 EIGEN_STATIC_ASSERT((
static_cast<int>(TensorEvaluator<LeftArgType, Device>::Layout) ==
700 static_cast<int>(TensorEvaluator<RightArgType, Device>::Layout) ||
701 internal::traits<XprType>::NumDimensions <= 1),
702 YOU_MADE_A_PROGRAMMING_MISTAKE);
703 eigen_assert(dimensions_match(m_leftImpl.dimensions(), m_rightImpl.dimensions()));
706 typedef typename XprType::Index Index;
707 typedef typename XprType::Scalar Scalar;
708 typedef typename internal::traits<XprType>::Scalar CoeffReturnType;
709 typedef typename PacketType<CoeffReturnType, Device>::type PacketReturnType;
710 static constexpr int PacketSize = PacketType<CoeffReturnType, Device>::size;
711 typedef typename TensorEvaluator<LeftArgType, Device>::Dimensions Dimensions;
712 typedef StorageMemory<CoeffReturnType, Device> Storage;
713 typedef typename Storage::Type EvaluatorPointerType;
715 static constexpr int NumDims = internal::array_size<typename TensorEvaluator<LeftArgType, Device>::Dimensions>::value;
718 typedef internal::TensorBlockDescriptor<NumDims, Index> TensorBlockDesc;
719 typedef internal::TensorBlockScratchAllocator<Device> TensorBlockScratch;
721 typedef typename TensorEvaluator<const LeftArgType, Device>::TensorBlock LeftTensorBlock;
722 typedef typename TensorEvaluator<const RightArgType, Device>::TensorBlock RightTensorBlock;
724 typedef internal::TensorCwiseBinaryBlock<BinaryOp, LeftTensorBlock, RightTensorBlock> TensorBlock;
727 EIGEN_DEVICE_FUNC
const Dimensions& dimensions()
const {
729 return m_leftImpl.dimensions();
732 EIGEN_STRONG_INLINE
bool evalSubExprsIfNeeded(EvaluatorPointerType) {
733 m_leftImpl.evalSubExprsIfNeeded(
nullptr);
734 m_rightImpl.evalSubExprsIfNeeded(
nullptr);
738#ifdef EIGEN_USE_THREADS
739 template <
typename EvalSubExprsCallback>
740 EIGEN_STRONG_INLINE
void evalSubExprsIfNeededAsync(EvaluatorPointerType, EvalSubExprsCallback done) {
742 m_leftImpl.evalSubExprsIfNeededAsync(
743 nullptr, [
this, done](
bool) { m_rightImpl.evalSubExprsIfNeededAsync(
nullptr, [done](
bool) { done(
true); }); });
747 EIGEN_STRONG_INLINE
void cleanup() {
748 m_leftImpl.cleanup();
749 m_rightImpl.cleanup();
752 EIGEN_DEVICE_FUNC CoeffReturnType coeff(Index index)
const {
753 return m_functor(m_leftImpl.coeff(index), m_rightImpl.coeff(index));
755 template <
int LoadMode>
756 EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE PacketReturnType packet(Index index)
const {
757 return m_functor.packetOp(m_leftImpl.template packet<LoadMode>(index),
758 m_rightImpl.template packet<LoadMode>(index));
761 EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE TensorOpCost costPerCoeff(
bool vectorized)
const {
762 const double functor_cost = internal::functor_traits<BinaryOp>::Cost;
763 return m_leftImpl.costPerCoeff(vectorized) + m_rightImpl.costPerCoeff(vectorized) +
764 TensorOpCost(0, 0, functor_cost, vectorized, PacketSize);
767 EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE internal::TensorBlockResourceRequirements getResourceRequirements()
const {
768 static constexpr double functor_cost = internal::functor_traits<BinaryOp>::Cost;
769 return internal::TensorBlockResourceRequirements::merge(m_leftImpl.getResourceRequirements(),
770 m_rightImpl.getResourceRequirements())
771 .addCostPerCoeff({0, 0, functor_cost / PacketSize});
774 EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE TensorBlock block(TensorBlockDesc& desc, TensorBlockScratch& scratch,
775 bool =
false)
const {
776 desc.DropDestinationBuffer();
777 return TensorBlock(m_leftImpl.block(desc, scratch), m_rightImpl.block(desc, scratch), m_functor);
780 EIGEN_DEVICE_FUNC EvaluatorPointerType data()
const {
return nullptr; }
783 const Device EIGEN_DEVICE_REF m_device;
784 const BinaryOp m_functor;
785 TensorEvaluator<LeftArgType, Device> m_leftImpl;
786 TensorEvaluator<RightArgType, Device> m_rightImpl;
791template <
typename TernaryOp,
typename Arg1Type,
typename Arg2Type,
typename Arg3Type,
typename Device>
792struct TensorEvaluator<const TensorCwiseTernaryOp<TernaryOp, Arg1Type, Arg2Type, Arg3Type>, Device> {
793 typedef TensorCwiseTernaryOp<TernaryOp, Arg1Type, Arg2Type, Arg3Type> XprType;
795 static constexpr int Layout = TensorEvaluator<Arg1Type, Device>::Layout;
797 IsAligned = TensorEvaluator<Arg1Type, Device>::IsAligned && TensorEvaluator<Arg2Type, Device>::IsAligned &&
798 TensorEvaluator<Arg3Type, Device>::IsAligned,
799 PacketAccess = TensorEvaluator<Arg1Type, Device>::PacketAccess && TensorEvaluator<Arg2Type, Device>::PacketAccess &&
800 TensorEvaluator<Arg3Type, Device>::PacketAccess && internal::functor_traits<TernaryOp>::PacketAccess,
801 BlockAccess = TensorEvaluator<Arg1Type, Device>::BlockAccess && TensorEvaluator<Arg2Type, Device>::BlockAccess &&
802 TensorEvaluator<Arg3Type, Device>::BlockAccess,
803 PreferBlockAccess = TensorEvaluator<Arg1Type, Device>::PreferBlockAccess ||
804 TensorEvaluator<Arg2Type, Device>::PreferBlockAccess ||
805 TensorEvaluator<Arg3Type, Device>::PreferBlockAccess,
810 EIGEN_DEVICE_FUNC TensorEvaluator(
const XprType& op,
const Device& device)
811 : m_functor(op.functor()),
812 m_arg1Impl(op.arg1Expression(), device),
813 m_arg2Impl(op.arg2Expression(), device),
814 m_arg3Impl(op.arg3Expression(), device) {
815 EIGEN_STATIC_ASSERT((
static_cast<int>(TensorEvaluator<Arg1Type, Device>::Layout) ==
816 static_cast<int>(TensorEvaluator<Arg3Type, Device>::Layout) ||
817 internal::traits<XprType>::NumDimensions <= 1),
818 YOU_MADE_A_PROGRAMMING_MISTAKE);
820 EIGEN_STATIC_ASSERT((std::is_same<
typename internal::traits<Arg1Type>::StorageKind,
821 typename internal::traits<Arg2Type>::StorageKind>::value),
822 STORAGE_KIND_MUST_MATCH)
823 EIGEN_STATIC_ASSERT((std::is_same<
typename internal::traits<Arg1Type>::StorageKind,
824 typename internal::traits<Arg3Type>::StorageKind>::value),
825 STORAGE_KIND_MUST_MATCH)
827 (std::is_same<
typename internal::traits<Arg1Type>::Index,
typename internal::traits<Arg2Type>::Index>::value),
828 STORAGE_INDEX_MUST_MATCH)
830 (std::is_same<
typename internal::traits<Arg1Type>::Index,
typename internal::traits<Arg3Type>::Index>::value),
831 STORAGE_INDEX_MUST_MATCH)
833 eigen_assert(dimensions_match(m_arg1Impl.dimensions(), m_arg2Impl.dimensions()) &&
834 dimensions_match(m_arg1Impl.dimensions(), m_arg3Impl.dimensions()));
837 typedef typename XprType::Index Index;
838 typedef typename XprType::Scalar Scalar;
839 typedef typename internal::traits<XprType>::Scalar CoeffReturnType;
840 typedef typename PacketType<CoeffReturnType, Device>::type PacketReturnType;
841 static constexpr int PacketSize = PacketType<CoeffReturnType, Device>::size;
842 typedef typename TensorEvaluator<Arg1Type, Device>::Dimensions Dimensions;
843 typedef StorageMemory<CoeffReturnType, Device> Storage;
844 typedef typename Storage::Type EvaluatorPointerType;
845 static constexpr int NumDims = internal::array_size<Dimensions>::value;
848 typedef internal::TensorBlockDescriptor<NumDims, Index> TensorBlockDesc;
849 typedef internal::TensorBlockScratchAllocator<Device> TensorBlockScratch;
851 typedef typename TensorEvaluator<const Arg1Type, Device>::TensorBlock Arg1TensorBlock;
852 typedef typename TensorEvaluator<const Arg2Type, Device>::TensorBlock Arg2TensorBlock;
853 typedef typename TensorEvaluator<const Arg3Type, Device>::TensorBlock Arg3TensorBlock;
857 struct TensorCwiseTernaryOpBlockFactory {
860 template <
typename Arg1XprType,
typename Arg2XprType,
typename Arg3XprType>
862 typedef TensorCwiseTernaryOp<TernaryOp, const Arg1XprType, const Arg2XprType, const Arg3XprType> type;
865 template <
typename Arg1XprType,
typename Arg2XprType,
typename Arg3XprType>
866 typename XprType<Arg1XprType, Arg2XprType, Arg3XprType>::type expr(
const Arg1XprType& arg1,
const Arg2XprType& arg2,
867 const Arg3XprType& arg3)
const {
868 return typename XprType<Arg1XprType, Arg2XprType, Arg3XprType>::type(arg1, arg2, arg3, func);
872 typedef internal::TensorTernaryExprBlock<TensorCwiseTernaryOpBlockFactory, Arg1TensorBlock, Arg2TensorBlock,
877 EIGEN_DEVICE_FUNC
const Dimensions& dimensions()
const {
879 return m_arg1Impl.dimensions();
882 EIGEN_STRONG_INLINE
bool evalSubExprsIfNeeded(EvaluatorPointerType) {
883 m_arg1Impl.evalSubExprsIfNeeded(
nullptr);
884 m_arg2Impl.evalSubExprsIfNeeded(
nullptr);
885 m_arg3Impl.evalSubExprsIfNeeded(
nullptr);
888 EIGEN_STRONG_INLINE
void cleanup() {
889 m_arg1Impl.cleanup();
890 m_arg2Impl.cleanup();
891 m_arg3Impl.cleanup();
894 EIGEN_DEVICE_FUNC CoeffReturnType coeff(Index index)
const {
895 return m_functor(m_arg1Impl.coeff(index), m_arg2Impl.coeff(index), m_arg3Impl.coeff(index));
897 template <
int LoadMode>
898 EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE PacketReturnType packet(Index index)
const {
899 return m_functor.packetOp(m_arg1Impl.template packet<LoadMode>(index), m_arg2Impl.template packet<LoadMode>(index),
900 m_arg3Impl.template packet<LoadMode>(index));
903 EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE TensorOpCost costPerCoeff(
bool vectorized)
const {
904 const double functor_cost = internal::functor_traits<TernaryOp>::Cost;
905 return m_arg1Impl.costPerCoeff(vectorized) + m_arg2Impl.costPerCoeff(vectorized) +
906 m_arg3Impl.costPerCoeff(vectorized) + TensorOpCost(0, 0, functor_cost, vectorized, PacketSize);
909 EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE internal::TensorBlockResourceRequirements getResourceRequirements()
const {
910 static constexpr double functor_cost = internal::functor_traits<TernaryOp>::Cost;
911 return internal::TensorBlockResourceRequirements::merge(
912 m_arg1Impl.getResourceRequirements(),
913 internal::TensorBlockResourceRequirements::merge(m_arg2Impl.getResourceRequirements(),
914 m_arg3Impl.getResourceRequirements()))
915 .addCostPerCoeff({0, 0, functor_cost / PacketSize});
918 EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE TensorBlock block(TensorBlockDesc& desc, TensorBlockScratch& scratch,
919 bool =
false)
const {
922 desc.DropDestinationBuffer();
923 return TensorBlock(m_arg1Impl.block(desc, scratch), m_arg2Impl.block(desc, scratch),
924 m_arg3Impl.block(desc, scratch), TensorCwiseTernaryOpBlockFactory{m_functor});
927 EIGEN_DEVICE_FUNC EvaluatorPointerType data()
const {
return nullptr; }
930 const TernaryOp m_functor;
931 TensorEvaluator<Arg1Type, Device> m_arg1Impl;
932 TensorEvaluator<Arg2Type, Device> m_arg2Impl;
933 TensorEvaluator<Arg3Type, Device> m_arg3Impl;
938template <
typename IfArgType,
typename ThenArgType,
typename ElseArgType,
typename Device>
939struct TensorEvaluator<const TensorSelectOp<IfArgType, ThenArgType, ElseArgType>, Device> {
940 typedef TensorSelectOp<IfArgType, ThenArgType, ElseArgType> XprType;
941 typedef typename XprType::Scalar Scalar;
943 using TernarySelectOp = internal::scalar_boolean_select_op<typename internal::traits<ThenArgType>::Scalar,
944 typename internal::traits<ElseArgType>::Scalar,
945 typename internal::traits<IfArgType>::Scalar>;
946 static constexpr bool TernaryPacketAccess =
947 TensorEvaluator<ThenArgType, Device>::PacketAccess && TensorEvaluator<ElseArgType, Device>::PacketAccess &&
948 TensorEvaluator<IfArgType, Device>::PacketAccess && internal::functor_traits<TernarySelectOp>::PacketAccess;
950 static constexpr int Layout = TensorEvaluator<IfArgType, Device>::Layout;
952 IsAligned = TensorEvaluator<ThenArgType, Device>::IsAligned && TensorEvaluator<ElseArgType, Device>::IsAligned,
954 (TensorEvaluator<ThenArgType, Device>::PacketAccess && TensorEvaluator<ElseArgType, Device>::PacketAccess) ||
956 BlockAccess = TensorEvaluator<IfArgType, Device>::BlockAccess &&
957 TensorEvaluator<ThenArgType, Device>::BlockAccess &&
958 TensorEvaluator<ElseArgType, Device>::BlockAccess,
959 PreferBlockAccess = TensorEvaluator<IfArgType, Device>::PreferBlockAccess ||
960 TensorEvaluator<ThenArgType, Device>::PreferBlockAccess ||
961 TensorEvaluator<ElseArgType, Device>::PreferBlockAccess,
966 EIGEN_DEVICE_FUNC TensorEvaluator(
const XprType& op,
const Device& device)
967 : m_condImpl(op.ifExpression(), device),
968 m_thenImpl(op.thenExpression(), device),
969 m_elseImpl(op.elseExpression(), device) {
970 EIGEN_STATIC_ASSERT((
static_cast<int>(TensorEvaluator<IfArgType, Device>::Layout) ==
971 static_cast<int>(TensorEvaluator<ThenArgType, Device>::Layout)),
972 YOU_MADE_A_PROGRAMMING_MISTAKE);
973 EIGEN_STATIC_ASSERT((
static_cast<int>(TensorEvaluator<IfArgType, Device>::Layout) ==
974 static_cast<int>(TensorEvaluator<ElseArgType, Device>::Layout)),
975 YOU_MADE_A_PROGRAMMING_MISTAKE);
976 eigen_assert(dimensions_match(m_condImpl.dimensions(), m_thenImpl.dimensions()));
977 eigen_assert(dimensions_match(m_thenImpl.dimensions(), m_elseImpl.dimensions()));
980 typedef typename XprType::Index Index;
981 typedef typename internal::traits<XprType>::Scalar CoeffReturnType;
982 typedef typename PacketType<CoeffReturnType, Device>::type PacketReturnType;
983 static constexpr int PacketSize = PacketType<CoeffReturnType, Device>::size;
984 typedef typename TensorEvaluator<IfArgType, Device>::Dimensions Dimensions;
985 typedef StorageMemory<CoeffReturnType, Device> Storage;
986 typedef typename Storage::Type EvaluatorPointerType;
988 static constexpr int NumDims = internal::array_size<Dimensions>::value;
991 typedef internal::TensorBlockDescriptor<NumDims, Index> TensorBlockDesc;
992 typedef internal::TensorBlockScratchAllocator<Device> TensorBlockScratch;
994 typedef typename TensorEvaluator<const IfArgType, Device>::TensorBlock IfArgTensorBlock;
995 typedef typename TensorEvaluator<const ThenArgType, Device>::TensorBlock ThenArgTensorBlock;
996 typedef typename TensorEvaluator<const ElseArgType, Device>::TensorBlock ElseArgTensorBlock;
998 struct TensorSelectOpBlockFactory {
999 template <
typename IfArgXprType,
typename ThenArgXprType,
typename ElseArgXprType>
1001 typedef TensorSelectOp<const IfArgXprType, const ThenArgXprType, const ElseArgXprType> type;
1004 template <
typename IfArgXprType,
typename ThenArgXprType,
typename ElseArgXprType>
1005 typename XprType<IfArgXprType, ThenArgXprType, ElseArgXprType>::type expr(
const IfArgXprType& if_expr,
1006 const ThenArgXprType& then_expr,
1007 const ElseArgXprType& else_expr)
const {
1008 return typename XprType<IfArgXprType, ThenArgXprType, ElseArgXprType>::type(if_expr, then_expr, else_expr);
1012 typedef internal::TensorTernaryExprBlock<TensorSelectOpBlockFactory, IfArgTensorBlock, ThenArgTensorBlock,
1017 EIGEN_DEVICE_FUNC
const Dimensions& dimensions()
const {
1019 return m_condImpl.dimensions();
1022 EIGEN_STRONG_INLINE
bool evalSubExprsIfNeeded(EvaluatorPointerType) {
1023 m_condImpl.evalSubExprsIfNeeded(
nullptr);
1024 m_thenImpl.evalSubExprsIfNeeded(
nullptr);
1025 m_elseImpl.evalSubExprsIfNeeded(
nullptr);
1029#ifdef EIGEN_USE_THREADS
1030 template <
typename EvalSubExprsCallback>
1031 EIGEN_STRONG_INLINE
void evalSubExprsIfNeededAsync(EvaluatorPointerType, EvalSubExprsCallback done) {
1032 m_condImpl.evalSubExprsIfNeeded(
nullptr, [
this, done](
bool) {
1033 m_thenImpl.evalSubExprsIfNeeded(
1034 nullptr, [
this, done](
bool) { m_elseImpl.evalSubExprsIfNeeded(
nullptr, [done](
bool) { done(
true); }); });
1039 EIGEN_STRONG_INLINE
void cleanup() {
1040 m_condImpl.cleanup();
1041 m_thenImpl.cleanup();
1042 m_elseImpl.cleanup();
1045 EIGEN_DEVICE_FUNC CoeffReturnType coeff(Index index)
const {
1046 return m_condImpl.coeff(index) ? m_thenImpl.coeff(index) : m_elseImpl.coeff(index);
1049 template <
int LoadMode,
bool UseTernary = TernaryPacketAccess, std::enable_if_t<!UseTernary,
bool> = true>
1050 EIGEN_DEVICE_FUNC PacketReturnType packet(Index index)
const {
1051 EIGEN_ALIGN_TO_BOUNDARY(internal::unpacket_traits<PacketReturnType>::alignment)
1052 std::remove_const_t<Scalar> arr[PacketSize];
1054 for (Index i = 0; i < PacketSize; ++i) {
1055 arr[i] = m_condImpl.coeff(index + i) ? Scalar(-1) : Scalar(0);
1057 return TernarySelectOp().template packetOp<PacketReturnType>(m_thenImpl.template packet<LoadMode>(index),
1058 m_elseImpl.template packet<LoadMode>(index),
1059 internal::pload<PacketReturnType>(arr));
1062 template <
int LoadMode,
bool UseTernary = TernaryPacketAccess, std::enable_if_t<UseTernary,
bool> = true>
1063 EIGEN_DEVICE_FUNC PacketReturnType packet(Index index)
const {
1064 return TernarySelectOp().template packetOp<PacketReturnType>(m_thenImpl.template packet<LoadMode>(index),
1065 m_elseImpl.template packet<LoadMode>(index),
1066 m_condImpl.template packet<LoadMode>(index));
1069 EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE TensorOpCost costPerCoeff(
bool vectorized)
const {
1070 return m_condImpl.costPerCoeff(vectorized) +
1071 m_thenImpl.costPerCoeff(vectorized).cwiseMax(m_elseImpl.costPerCoeff(vectorized));
1074 EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE internal::TensorBlockResourceRequirements getResourceRequirements()
const {
1075 auto then_req = m_thenImpl.getResourceRequirements();
1076 auto else_req = m_elseImpl.getResourceRequirements();
1078 auto merged_req = internal::TensorBlockResourceRequirements::merge(then_req, else_req);
1079 merged_req.cost_per_coeff = then_req.cost_per_coeff.cwiseMax(else_req.cost_per_coeff);
1081 return internal::TensorBlockResourceRequirements::merge(m_condImpl.getResourceRequirements(), merged_req);
1084 EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE TensorBlock block(TensorBlockDesc& desc, TensorBlockScratch& scratch,
1085 bool =
false)
const {
1088 desc.DropDestinationBuffer();
1090 return TensorBlock(m_condImpl.block(desc, scratch), m_thenImpl.block(desc, scratch),
1091 m_elseImpl.block(desc, scratch), TensorSelectOpBlockFactory());
1094 EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE EvaluatorPointerType data()
const {
return nullptr; }
1096#ifdef EIGEN_USE_SYCL
1098 EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE
void bind(cl::sycl::handler& cgh)
const {
1099 m_condImpl.bind(cgh);
1100 m_thenImpl.bind(cgh);
1101 m_elseImpl.bind(cgh);
1105 TensorEvaluator<IfArgType, Device> m_condImpl;
1106 TensorEvaluator<ThenArgType, Device> m_thenImpl;
1107 TensorEvaluator<ElseArgType, Device> m_elseImpl;
1112#if defined(EIGEN_USE_SYCL) && defined(SYCL_COMPILER_IS_DPCPP)
1113template <
typename Derived,
typename Device>
1114struct cl::sycl::is_device_copyable<
1115 Eigen::TensorEvaluator<Derived, Device>,
1116 std::enable_if_t<!std::is_trivially_copyable<Eigen::TensorEvaluator<Derived, Device>>::value>> : std::true_type {};
Tensor binary expression.
Definition TensorExpr.h:153
Tensor nullary expression.
Definition TensorExpr.h:41
Tensor unary expression.
Definition TensorExpr.h:90
Namespace containing all symbols from the Eigen library.
The tensor evaluator class.
Definition TensorEvaluator.h:47