// // Copyright © 2017 Arm Ltd. All rights reserved. // SPDX-License-Identifier: MIT // #pragma once #include "ResolveType.hpp" #include "DataLayoutIndexed.hpp" #include "EndToEndTestImpl.hpp" #include "armnn/INetwork.hpp" #include "backendsCommon/test/CommonTestUtils.hpp" #include #include #include namespace { template> void PermuteDataToNCHW(const std::vector& backends, const armnn::DataLayout& dataLayout, TensorInfo& tensorInfo, std::vector& data) { const armnn::PermutationVector NHWCToNCHW = {0, 2, 3, 1}; tensorInfo = armnnUtils::Permuted(tensorInfo, NHWCToNCHW); std::vector tmp(data.size()); armnnUtils::Permute(tensorInfo.GetShape(), NHWCToNCHW, data.data(), tmp.data(), sizeof(T)); data = tmp; } template armnn::INetworkPtr CreateSpaceToDepthNetwork(const armnn::TensorShape& inputShape, const armnn::TensorShape& outputShape, const armnn::DataLayout dataLayout, unsigned int blockSize, const float qScale = 1.0f, const int32_t qOffset = 0) { using namespace armnn; // Builds up the structure of the network. INetworkPtr net(INetwork::Create()); TensorInfo inputTensorInfo(inputShape, DataType, qScale, qOffset); armnnUtils::DataLayoutIndexed dimensionIndices(dataLayout); if (inputShape[dimensionIndices.GetHeightIndex()] % blockSize!=0 || inputShape[dimensionIndices.GetWidthIndex()] % blockSize!=0) { throw InvalidArgumentException("Input shape must be divisible by block size in all spatial dimensions"); } SpaceToDepthDescriptor spaceToDepthDesc; spaceToDepthDesc.m_BlockSize = blockSize; spaceToDepthDesc.m_DataLayout = dataLayout; IConnectableLayer* SpaceToDepth = net->AddSpaceToDepthLayer(spaceToDepthDesc, "SpaceToDepth"); IConnectableLayer* input = net->AddInputLayer(0, "input"); Connect(input, SpaceToDepth, inputTensorInfo, 0, 0); TensorInfo outputTensorInfo(outputShape, DataType, qScale, qOffset); IConnectableLayer* output = net->AddOutputLayer(0, "output"); Connect(SpaceToDepth, output, outputTensorInfo, 0, 0); return net; } void SpaceToDepthEndToEnd(const std::vector& backends, const armnn::DataLayout& dataLayout, TensorInfo& inputTensorInfo, TensorInfo& outputTensorInfo, std::vector& inputData, std::vector& expectedOutputData, const unsigned int blockSize) { using namespace armnn; if (dataLayout == armnn::DataLayout::NCHW) { PermuteDataToNCHW(backends, dataLayout, inputTensorInfo, inputData); PermuteDataToNCHW(backends, dataLayout, outputTensorInfo, expectedOutputData); } // Builds up the structure of the network INetworkPtr net = CreateSpaceToDepthNetwork( inputTensorInfo.GetShape(), outputTensorInfo.GetShape(), dataLayout, blockSize); BOOST_TEST_CHECKPOINT("Create a network"); std::map> inputTensorData = { { 0, inputData } }; std::map> expectedOutputTensorData = { { 0, expectedOutputData } }; EndToEndLayerTestImpl( move(net), inputTensorData, expectedOutputTensorData, backends); } void SpaceToDepthNHWCEndToEndTest1(const std::vector& defaultBackends) { const unsigned int blockSize = 2; armnn::TensorShape inputShape{1, 2, 2, 1}; armnn::TensorInfo inputTensorInfo(inputShape, armnn::DataType::Float32); armnn::TensorShape outputShape{1, 1, 1, 4}; armnn::TensorInfo outputTensorInfo(outputShape, armnn::DataType::Float32); std::vector inputData = std::vector( { 1.0f, 2.0f, 3.0f, 4.0f }); std::vector expectedOutputData = std::vector( { 1.0f, 2.0f, 3.0f, 4.0f }); SpaceToDepthEndToEnd(defaultBackends, armnn::DataLayout::NHWC, inputTensorInfo, outputTensorInfo, inputData, expectedOutputData, blockSize); } void SpaceToDepthNCHWEndToEndTest1(const std::vector& defaultBackends) { const unsigned int blockSize = 2; armnn::TensorShape inputShape{1, 2, 2, 1}; armnn::TensorInfo inputTensorInfo(inputShape, armnn::DataType::Float32); armnn::TensorShape outputShape{1, 1, 1, 4}; armnn::TensorInfo outputTensorInfo(outputShape, armnn::DataType::Float32); std::vector inputData = std::vector( { 1.0f, 2.0f, 3.0f, 4.0f }); std::vector expectedOutputData = std::vector( { 1.0f, 2.0f, 3.0f, 4.0f }); SpaceToDepthEndToEnd(defaultBackends, armnn::DataLayout::NCHW, inputTensorInfo, outputTensorInfo, inputData, expectedOutputData, blockSize); } void SpaceToDepthNHWCEndToEndTest2(const std::vector& defaultBackends) { const unsigned int blockSize = 2; armnn::TensorShape inputShape{1, 2, 2, 2}; armnn::TensorShape outputShape{1, 1, 1, 8}; armnn::TensorInfo outputTensorInfo(outputShape, armnn::DataType::Float32); armnn::TensorInfo inputTensorInfo(inputShape, armnn::DataType::Float32); std::vector inputData = std::vector( { 1.4f, 2.3f, 3.2f, 4.1f, 5.4f, 6.3f, 7.2f, 8.1f }); std::vector expectedOutputData = std::vector( { 1.4f, 2.3f, 3.2f, 4.1f, 5.4f, 6.3f, 7.2f, 8.1f }); SpaceToDepthEndToEnd(defaultBackends, armnn::DataLayout::NHWC, inputTensorInfo, outputTensorInfo, inputData, expectedOutputData, blockSize); } void SpaceToDepthNCHWEndToEndTest2(const std::vector& defaultBackends) { const unsigned int blockSize = 2; armnn::TensorShape inputShape{1, 2, 2, 2}; armnn::TensorShape outputShape{1, 1, 1, 8}; armnn::TensorInfo inputTensorInfo(inputShape, armnn::DataType::Float32); armnn::TensorInfo outputTensorInfo(outputShape, armnn::DataType::Float32); std::vector inputData = std::vector( { 1.4f, 2.3f, 3.2f, 4.1f, 5.4f, 6.3f, 7.2f, 8.1f }); std::vector expectedOutputData = std::vector( { 1.4f, 2.3f, 3.2f, 4.1f, 5.4f, 6.3f, 7.2f, 8.1f }); SpaceToDepthEndToEnd(defaultBackends, armnn::DataLayout::NCHW, inputTensorInfo, outputTensorInfo, inputData, expectedOutputData, blockSize); } } // anonymous namespace