// // Copyright © 2023 Arm Ltd and Contributors. All rights reserved. // SPDX-License-Identifier: MIT // #include "Tile.hpp" #include "Encoders.hpp" #include #include #include namespace armnn { // Converts a flatten index into a multi-dimensional coordinate. std::vector IndexToCoordinates(std::vector& shape, uint32_t index) { std::vector 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& 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& inputDecoder, Encoder& outputEncoder) { // Input and output will always have same rank uint32_t rank = inputInfo.GetNumDimensions(); TensorShape inputShape = inputInfo.GetShape(); std::vector 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 inputData = inputDecoder.DecodeTensor(inputInfo.GetShape()); std::vector outputData; auto outputNumElements = inputData.size() * static_cast(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 outputCoords = IndexToCoordinates(outputShape, outputIndex); // Converting output coordinates to input coordinates using modulus std::vector 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