11#ifndef EIGEN_TENSOR_TENSOR_INFLATION_H
12#define EIGEN_TENSOR_TENSOR_INFLATION_H
15#include "./InternalHeaderCheck.h"
20template <
typename Str
ides,
typename XprType>
21struct traits<TensorInflationOp<Strides, XprType>> :
public traits<XprType> {
22 typedef typename XprType::Scalar Scalar;
23 typedef traits<XprType> XprTraits;
24 typedef typename XprTraits::StorageKind StorageKind;
25 typedef typename XprTraits::Index Index;
26 static constexpr int NumDimensions = XprTraits::NumDimensions;
27 static constexpr int Layout = XprTraits::Layout;
28 typedef typename XprTraits::PointerType PointerType;
31template <
typename Str
ides,
typename XprType>
32struct eval<TensorInflationOp<Strides, XprType>, Eigen::Dense> {
33 typedef const TensorInflationOp<Strides, XprType>& type;
43template <
typename Str
ides,
typename XprType>
44class TensorInflationOp :
public TensorBase<TensorInflationOp<Strides, XprType>, ReadOnlyAccessors> {
46 typedef typename Eigen::internal::traits<TensorInflationOp>::Scalar Scalar;
48 typedef typename XprType::CoeffReturnType CoeffReturnType;
49 typedef typename Eigen::internal::ref_selector<TensorInflationOp>::type Nested;
50 typedef typename Eigen::internal::traits<TensorInflationOp>::StorageKind StorageKind;
51 typedef typename Eigen::internal::traits<TensorInflationOp>::Index Index;
53 EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE TensorInflationOp(
const XprType& expr,
const Strides& strides)
54 : m_xpr(expr), m_strides(strides) {}
56 EIGEN_DEVICE_FUNC
const Strides& strides()
const {
return m_strides; }
58 EIGEN_DEVICE_FUNC
const internal::remove_all_t<typename XprType::Nested>& expression()
const {
return m_xpr; }
61 typename XprType::Nested m_xpr;
62 const Strides m_strides;
66template <
typename Str
ides,
typename ArgType,
typename Device>
69 typedef typename XprType::Index Index;
70 static constexpr int NumDims = internal::array_size<typename TensorEvaluator<ArgType, Device>::Dimensions>::value;
72 typedef typename XprType::Scalar Scalar;
74 typedef typename PacketType<CoeffReturnType, Device>::type PacketReturnType;
75 static constexpr int PacketSize = PacketType<CoeffReturnType, Device>::size;
76 typedef StorageMemory<CoeffReturnType, Device> Storage;
77 typedef typename Storage::Type EvaluatorPointerType;
79 static constexpr int Layout = TensorEvaluator<ArgType, Device>::Layout;
82 PacketAccess = TensorEvaluator<ArgType, Device>::PacketAccess,
96 PreferBlockAccess =
true,
102 typedef internal::TensorBlockDescriptor<NumDims, Index> TensorBlockDesc;
103 typedef internal::TensorBlockScratchAllocator<Device> TensorBlockScratch;
104 typedef internal::TensorMaterializedBlock<CoeffReturnType, NumDims, Layout, Index> TensorBlock;
107 EIGEN_STRONG_INLINE TensorEvaluator(
const XprType& op,
const Device& device)
108 : m_impl(op.expression(), device), m_strides(op.strides()), m_device(device) {
109 m_dimensions = m_impl.dimensions();
111 for (
int i = 0; i < NumDims; ++i) {
112 m_dimensions[i] = (m_dimensions[i] - 1) * op.strides()[i] + 1;
116 for (
int i = 0; i < NumDims; ++i) {
117 m_fastStrides[i] = internal::TensorIntDivisor<Index>(m_strides[i]);
120 const typename TensorEvaluator<ArgType, Device>::Dimensions& input_dims = m_impl.dimensions();
121 EIGEN_IF_CONSTEXPR (
static_cast<int>(Layout) ==
static_cast<int>(
ColMajor)) {
122 m_outputStrides[0] = 1;
123 m_inputStrides[0] = 1;
124 for (
int i = 1; i < NumDims; ++i) {
125 m_outputStrides[i] = m_outputStrides[i - 1] * m_dimensions[i - 1];
126 m_inputStrides[i] = m_inputStrides[i - 1] * input_dims[i - 1];
129 m_outputStrides[NumDims - 1] = 1;
130 m_inputStrides[NumDims - 1] = 1;
131 for (
int i = NumDims - 2; i >= 0; --i) {
132 m_outputStrides[i] = m_outputStrides[i + 1] * m_dimensions[i + 1];
133 m_inputStrides[i] = m_inputStrides[i + 1] * input_dims[i + 1];
138 EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE
const Dimensions& dimensions()
const {
return m_dimensions; }
140 EIGEN_STRONG_INLINE
bool evalSubExprsIfNeeded(EvaluatorPointerType ) {
141 m_impl.evalSubExprsIfNeeded(
nullptr);
144 EIGEN_STRONG_INLINE
void cleanup() { m_impl.cleanup(); }
148 EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE
bool getInputIndex(Index index, Index* inputIndex)
const {
149 eigen_assert(index < dimensions().TotalSize());
151 EIGEN_IF_CONSTEXPR (
static_cast<int>(Layout) ==
static_cast<int>(
ColMajor)) {
153 for (
int i = NumDims - 1; i > 0; --i) {
154 const Index idx = index / m_outputStrides[i];
155 if (idx != idx / m_fastStrides[i] * m_strides[i]) {
158 *inputIndex += idx / m_strides[i] * m_inputStrides[i];
159 index -= idx * m_outputStrides[i];
161 if (index != index / m_fastStrides[0] * m_strides[0]) {
164 *inputIndex += index / m_strides[0];
168 for (
int i = 0; i < NumDims - 1; ++i) {
169 const Index idx = index / m_outputStrides[i];
170 if (idx != idx / m_fastStrides[i] * m_strides[i]) {
173 *inputIndex += idx / m_strides[i] * m_inputStrides[i];
174 index -= idx * m_outputStrides[i];
176 if (index != index / m_fastStrides[NumDims - 1] * m_strides[NumDims - 1]) {
179 *inputIndex += index / m_strides[NumDims - 1];
184 EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE CoeffReturnType coeff(Index index)
const {
185 Index inputIndex = 0;
186 if (getInputIndex(index, &inputIndex)) {
187 return m_impl.coeff(inputIndex);
195 template <
int LoadMode>
196 EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE PacketReturnType packet(Index index)
const {
197 EIGEN_STATIC_ASSERT((PacketSize > 1), YOU_MADE_A_PROGRAMMING_MISTAKE)
198 eigen_assert(index + PacketSize - 1 < dimensions().TotalSize());
200 EIGEN_ALIGN_TO_BOUNDARY(internal::unpacket_traits<PacketReturnType>::alignment)
201 std::remove_const_t<CoeffReturnType> values[PacketSize];
203 for (
int i = 0; i < PacketSize; ++i) {
204 values[i] = coeff(index + i);
206 PacketReturnType rslt = internal::pload<PacketReturnType>(values);
210 EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE internal::TensorBlockResourceRequirements getResourceRequirements()
const {
211 const size_t target_size = m_device.lastLevelCacheSize();
215 const double density = latticeDensity();
216 const TensorOpCost cost_per_coeff =
217 density * m_impl.costPerCoeff(
false) +
218 TensorOpCost(0, (1.0 + density) *
sizeof(CoeffReturnType),
222 return internal::TensorBlockResourceRequirements::withShapeAndSize<Scalar>(
223 internal::TensorBlockShapeType::kSkewedInnerDims, target_size, cost_per_coeff);
226 EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE TensorBlock block(TensorBlockDesc& desc, TensorBlockScratch& scratch,
227 bool =
false)
const {
228 constexpr bool is_col_major =
static_cast<int>(Layout) ==
static_cast<int>(
ColMajor);
231 if (desc.size() == 0) {
232 return TensorBlock(internal::TensorBlockKind::kView,
nullptr, desc.dimensions());
237 typename TensorBlock::Storage block_storage = TensorBlock::prepareStorage(desc, scratch);
238 CoeffReturnType* block_buffer = block_storage.data();
241 array<Index, NumDims> coords;
242 extract_coordinates(desc.offset(), coords);
245 const DSizes<Index, NumDims>& block_strides = block_storage.strides();
246 array<Index, NumDims> lattice_count;
247 Index dst_offset = 0;
248 Index src_offset = 0;
249 for (
int i = 0; i < NumDims; ++i) {
250 const Index stride = m_strides[i];
251 const Index first_input = numext::div_ceil(coords[i], stride);
252 const Index first = first_input * stride;
253 const Index end = coords[i] + desc.dimension(i);
256 Map<ArrayX<CoeffReturnType>>(block_buffer, desc.size()).setZero();
257 return block_storage.AsTensorMaterializedBlock();
259 lattice_count[i] = numext::div_ceil(end - first, stride);
260 dst_offset += (first - coords[i]) * block_strides[i];
261 src_offset += first_input * m_inputStrides[i];
267 for (
int i = 0; i < NumDims; ++i) dense = dense && (lattice_count[i] == desc.dimension(i));
268 if (!dense) Map<ArrayX<CoeffReturnType>>(block_buffer, desc.size()).setZero();
271 array<BlockIteratorState, NumDims> it;
272 for (
int i = 0; i < NumDims; ++i) {
273 const int dim = is_col_major ? i : NumDims - 1 - i;
274 const Index size = lattice_count[dim];
275 const Index dst_stride = block_strides[dim] * m_strides[dim];
276 const Index src_stride = m_inputStrides[dim];
280 dst_stride * (size - 1),
282 src_stride * (size - 1)};
285 const Index inner_size = it[0].size;
286 const Index inner_dst_stride = it[0].dst_stride;
289 eigen_assert(it[0].src_stride == 1);
290 Index dst = dst_offset;
291 Index src = src_offset;
292 while (it[NumDims - 1].count < it[NumDims - 1].size) {
293 for (Index j = 0; j < inner_size; ++j) {
294 block_buffer[dst + j * inner_dst_stride] = m_impl.coeff(src + j);
297 EIGEN_IF_CONSTEXPR (NumDims == 1) break;
299 for (
int i = 1; i < NumDims; ++i) {
300 if (++it[i].count < it[i].size) {
301 dst += it[i].dst_stride;
302 src += it[i].src_stride;
305 if (i != NumDims - 1) it[i].count = 0;
306 dst -= it[i].dst_span;
307 src -= it[i].src_span;
311 return block_storage.AsTensorMaterializedBlock();
314 EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE TensorOpCost costPerCoeff(
bool vectorized)
const {
315 const double compute_cost = NumDims * (3 * TensorOpCost::DivCost<Index>() + 3 * TensorOpCost::MulCost<Index>() +
316 2 * TensorOpCost::AddCost<Index>());
317 if (m_dimensions.TotalSize() == 0)
return TensorOpCost();
318 return m_impl.costPerCoeff(vectorized) +
319 TensorOpCost(
sizeof(CoeffReturnType) * latticeDensity(), 0, compute_cost, vectorized, PacketSize);
322 EIGEN_DEVICE_FUNC EvaluatorPointerType data()
const {
return nullptr; }
326 EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE
double latticeDensity()
const {
327 const double output_size =
static_cast<double>(m_dimensions.TotalSize());
328 if (output_size == 0)
return 0.0;
329 return static_cast<double>(m_impl.dimensions().TotalSize()) / output_size;
332 EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE
void extract_coordinates(Index index, array<Index, NumDims>& coords)
const {
333 EIGEN_IF_CONSTEXPR (
static_cast<int>(Layout) ==
static_cast<int>(
ColMajor)) {
334 for (
int i = NumDims - 1; i > 0; --i) {
335 const Index idx = index / m_outputStrides[i];
336 index -= idx * m_outputStrides[i];
341 for (
int i = 0; i < NumDims - 1; ++i) {
342 const Index idx = index / m_outputStrides[i];
343 index -= idx * m_outputStrides[i];
346 coords[NumDims - 1] = index;
350 Dimensions m_dimensions;
351 array<Index, NumDims> m_outputStrides;
352 array<Index, NumDims> m_inputStrides;
353 TensorEvaluator<ArgType, Device> m_impl;
354 const Strides m_strides;
355 array<internal::TensorIntDivisor<Index>, NumDims> m_fastStrides;
356 const Device EIGEN_DEVICE_REF m_device;
359 struct BlockIteratorState {
The tensor base class.
Definition TensorForwardDeclarations.h:69
Tensor inflation class.
Definition TensorInflation.h:44
Namespace containing all symbols from the Eigen library.
The tensor evaluator class.
Definition TensorEvaluator.h:47