MCPcopy Create free account
hub / github.com/DeepRec-AI/DeepRec / StrideOrInflate

Function StrideOrInflate

tensorflow/core/kernels/einsum_op.cc:342–412  ·  view source on GitHub ↗

Source from the content-addressed store, hash-verified

340// the input (e.g. iii->i) or inflates it (e.g. i->iii), respectively.
341template <typename Device, typename T>
342Status StrideOrInflate(OpKernelContext* ctx, const Tensor& input,
343 const Labels& labels, const LabelCounts& label_counts,
344 const bool should_inflate, Tensor* output) {
345 // Return early if there are no repeated indices.
346 if (absl::c_all_of(label_counts, [](int c) { return c <= 1; })) {
347 return CopyFrom(input, input.shape(), output);
348 }
349 // We reshape so that each repeated label is compressed to one dimension.
350 // E.g. For iiij -> ij, The shape [3, 3, 3, 5] would be compressed to [27, 5].
351 // Striding appropriately (in this case with strides 14 (=1+3+9) and 1)
352 // recovers the generalized diagonal of shape [3, 5].
353 ShapeVec reshape;
354 ShapeVec strides;
355 // Strided and inflated shapes correspond to input and output shapes,
356 // respectively, should_inflate is true (vice-versa if should_inflate is
357 // false). E.g. they are [3, 5] and [3, 3, 3, 5] in the above example.
358 ShapeVec strided_shape;
359 ShapeVec inflated_shape;
360 for (int label : labels) {
361 const int count = label_counts[label];
362 const int current_axis =
363 should_inflate ? strided_shape.size() : inflated_shape.size();
364 const int64 dim = input.dim_size(current_axis);
365 strided_shape.push_back(dim);
366 inflated_shape.insert(inflated_shape.end(), count, dim);
367 const int64 reshape_dim = MathUtil::IPow(dim, count);
368 reshape.push_back(reshape_dim);
369 // While taking the d-diagonal in a rank k Tensor, we take d equally-spaced
370 // elements including the first and last element. Then,
371 // (k - 1) * stride = d^k - 1, or, stride = (d^k - 1)/(d - 1).
372 const int64 stride =
373 (dim > 1 && count > 1) ? (reshape_dim - 1) / (dim - 1) : 1;
374 strides.push_back(stride);
375 }
376
377 TensorShape output_shape =
378 TensorShape(should_inflate ? inflated_shape : strided_shape);
379 TF_RETURN_IF_ERROR(
380 ctx->allocate_temp(DataTypeToEnum<T>::value, output_shape, output));
381 const Device& device = ctx->eigen_device<Device>();
382 switch (reshape.size()) {
383#define NDIMS_CASE(N) \
384 case N: { \
385 if (should_inflate) { \
386 auto output_map = output->shaped<T, N>(reshape); \
387 auto input_map = input.shaped<T, N>(strided_shape); \
388 functor::InflateFunctor<Device, T, N>()( \
389 device, input_map, TensorShape(strides).AsEigenDSizes<N>(), \
390 output_map); \
391 } else { \
392 auto input_map = input.shaped<T, N>(reshape); \
393 auto output_map = output->shaped<T, N>(strided_shape); \
394 functor::StrideFunctor<Device, T, N>()( \
395 device, input_map, TensorShape(strides).AsEigenDSizes<N>(), \
396 output_map); \
397 } \
398 } break;
399 NDIMS_CASE(1);

Callers

nothing calls this directly

Calls 10

CopyFromFunction · 0.85
UnimplementedFunction · 0.85
TensorShapeClass · 0.50
shapeMethod · 0.45
sizeMethod · 0.45
dim_sizeMethod · 0.45
push_backMethod · 0.45
insertMethod · 0.45
endMethod · 0.45
allocate_tempMethod · 0.45

Tested by

no test coverage detected