blob: 148c51de2e7bb76721b94dc1014402147de90909 [file] [log] [blame]
Teresa Charlin79a06a52023-07-13 17:16:45 +01001//
2// Copyright © 2023 Arm Ltd and Contributors. All rights reserved.
3// SPDX-License-Identifier: MIT
4//
5
6#include "Tile.hpp"
7#include "Encoders.hpp"
8#include <numeric>
9#include <armnn/backends/WorkloadData.hpp>
10#include <armnn/Logging.hpp>
11
12namespace armnn
13{
14
15// Converts a flatten index into a multi-dimensional coordinate.
16std::vector<uint32_t> IndexToCoordinates(std::vector<uint32_t>& shape, uint32_t index)
17{
18 std::vector<uint32_t> coordinates;
19 // Iterating through dimensions starting from the last dimension to the first
20 for (std::size_t i = shape.size() - 1; i < shape.size(); --i)
21 {
22 // Coordinate is found by getting the index and modulus it by the current dimension size
23 // shape of dimension = dimension size
24 coordinates.insert(coordinates.begin(), index % shape[i]);
25 // Pass the index to next iteration making index = index / size of the current dimension
26 index = index/shape[i];
27 }
28 return coordinates;
29}
30
31// Convert a multidimensional coordinate to a flattened index.
32uint32_t CoordinatesToIndex(TensorShape& shape, std::vector<uint32_t>& coordinates)
33{
34 uint32_t index = 0;
35 uint32_t base = 1;
36 uint32_t rank = shape.GetNumDimensions();
37 for (uint32_t i = rank; i > 0; --i)
38 {
39 index = index + coordinates[i - 1] * base;
40 base = base * shape[i - 1];
41 }
42 return index;
43}
44
45void Tile(const TileDescriptor& params,
46 const TensorInfo& inputInfo,
47 Decoder<float>& inputDecoder,
48 Encoder<float>& outputEncoder)
49{
50 // Input and output will always have same rank
51 uint32_t rank = inputInfo.GetNumDimensions();
52
53 TensorShape inputShape = inputInfo.GetShape();
54
55 std::vector<uint32_t> outputShape(rank);
56 for (uint32_t i = 0; i < rank; ++i)
57 {
58 outputShape[i] = inputShape[i] * params.m_Multiples[i];
59 }
60
61 // If all values of multiples are 1, then return the input
62 if ( std::adjacent_find( params.m_Multiples.begin(), params.m_Multiples.end(),
63 std::not_equal_to<>() ) == params.m_Multiples.end() && params.m_Multiples[0] == 1)
64 {
65 for (uint32_t idx = 0; idx < inputInfo.GetNumElements(); ++idx)
66 {
67 float inputValue = inputDecoder.Get();
68 ++inputDecoder;
69 outputEncoder.Set(inputValue);
70 ++outputEncoder;
71 }
72 return;
73 }
74
75 std::vector<float> inputData = inputDecoder.DecodeTensor(inputInfo.GetShape());
76 std::vector<float> outputData;
77 auto outputNumElements = inputData.size() * static_cast<uint32_t>(std::accumulate(begin(params.m_Multiples),
78 end(params.m_Multiples),
79 1,
80 std::multiplies<>()));
81 outputData.reserve(outputNumElements);
82
83 for (uint32_t outputIndex = 0; outputIndex < outputNumElements; ++outputIndex)
84 {
85 std::vector<uint32_t> outputCoords = IndexToCoordinates(outputShape, outputIndex);
86
87 // Converting output coordinates to input coordinates using modulus
88 std::vector<uint32_t> inputCoordinates;
89 inputCoordinates.reserve(rank);
90 for (uint32_t i = 0; i < rank; ++i)
91 {
92 inputCoordinates.push_back(outputCoords[i] % inputShape[i]);
93 }
94
95 uint32_t inputIndex = CoordinatesToIndex(inputShape, inputCoordinates);
96
97 outputEncoder[outputIndex];
98 outputEncoder.Set(inputData[inputIndex]);
99 }
100}
101
102} // namespace armnn