diff options
Diffstat (limited to 'src/backends/reference/workloads/Tile.cpp')
-rw-r--r-- | src/backends/reference/workloads/Tile.cpp | 102 |
1 files changed, 102 insertions, 0 deletions
diff --git a/src/backends/reference/workloads/Tile.cpp b/src/backends/reference/workloads/Tile.cpp new file mode 100644 index 0000000000..148c51de2e --- /dev/null +++ b/src/backends/reference/workloads/Tile.cpp @@ -0,0 +1,102 @@ +// +// Copyright © 2023 Arm Ltd and Contributors. All rights reserved. +// SPDX-License-Identifier: MIT +// + +#include "Tile.hpp" +#include "Encoders.hpp" +#include <numeric> +#include <armnn/backends/WorkloadData.hpp> +#include <armnn/Logging.hpp> + +namespace armnn +{ + +// Converts a flatten index into a multi-dimensional coordinate. +std::vector<uint32_t> IndexToCoordinates(std::vector<uint32_t>& shape, uint32_t index) +{ + std::vector<uint32_t> coordinates; + // Iterating through dimensions starting from the last dimension to the first + for (std::size_t i = shape.size() - 1; i < shape.size(); --i) + { + // Coordinate is found by getting the index and modulus it by the current dimension size + // shape of dimension = dimension size + coordinates.insert(coordinates.begin(), index % shape[i]); + // Pass the index to next iteration making index = index / size of the current dimension + index = index/shape[i]; + } + return coordinates; +} + +// Convert a multidimensional coordinate to a flattened index. +uint32_t CoordinatesToIndex(TensorShape& shape, std::vector<uint32_t>& coordinates) +{ + uint32_t index = 0; + uint32_t base = 1; + uint32_t rank = shape.GetNumDimensions(); + for (uint32_t i = rank; i > 0; --i) + { + index = index + coordinates[i - 1] * base; + base = base * shape[i - 1]; + } + return index; +} + +void Tile(const TileDescriptor& params, + const TensorInfo& inputInfo, + Decoder<float>& inputDecoder, + Encoder<float>& outputEncoder) +{ + // Input and output will always have same rank + uint32_t rank = inputInfo.GetNumDimensions(); + + TensorShape inputShape = inputInfo.GetShape(); + + std::vector<uint32_t> outputShape(rank); + for (uint32_t i = 0; i < rank; ++i) + { + outputShape[i] = inputShape[i] * params.m_Multiples[i]; + } + + // If all values of multiples are 1, then return the input + if ( std::adjacent_find( params.m_Multiples.begin(), params.m_Multiples.end(), + std::not_equal_to<>() ) == params.m_Multiples.end() && params.m_Multiples[0] == 1) + { + for (uint32_t idx = 0; idx < inputInfo.GetNumElements(); ++idx) + { + float inputValue = inputDecoder.Get(); + ++inputDecoder; + outputEncoder.Set(inputValue); + ++outputEncoder; + } + return; + } + + std::vector<float> inputData = inputDecoder.DecodeTensor(inputInfo.GetShape()); + std::vector<float> outputData; + auto outputNumElements = inputData.size() * static_cast<uint32_t>(std::accumulate(begin(params.m_Multiples), + end(params.m_Multiples), + 1, + std::multiplies<>())); + outputData.reserve(outputNumElements); + + for (uint32_t outputIndex = 0; outputIndex < outputNumElements; ++outputIndex) + { + std::vector<uint32_t> outputCoords = IndexToCoordinates(outputShape, outputIndex); + + // Converting output coordinates to input coordinates using modulus + std::vector<uint32_t> inputCoordinates; + inputCoordinates.reserve(rank); + for (uint32_t i = 0; i < rank; ++i) + { + inputCoordinates.push_back(outputCoords[i] % inputShape[i]); + } + + uint32_t inputIndex = CoordinatesToIndex(inputShape, inputCoordinates); + + outputEncoder[outputIndex]; + outputEncoder.Set(inputData[inputIndex]); + } +} + +} // namespace armnn
\ No newline at end of file |