// // Copyright © 2024 Arm Ltd and Contributors. All rights reserved. // SPDX-License-Identifier: MIT // #pragma once #include #include #include #include using namespace armnn; namespace { template> INetworkPtr CreateScatterNdNetwork(const TensorInfo& shapeInfo, const TensorInfo& indicesInfo, const TensorInfo& updatesInfo, const TensorInfo& outputInfo, const std::vector& indicesData, const std::vector& updatesData, const ScatterNdDescriptor& descriptor) { INetworkPtr net(INetwork::Create()); IConnectableLayer* shapeLayer = net->AddInputLayer(0); IConnectableLayer* indicesLayer = net->AddConstantLayer(ConstTensor(indicesInfo, indicesData)); IConnectableLayer* updatesLayer = net->AddConstantLayer(ConstTensor(updatesInfo, updatesData)); IConnectableLayer* scatterNdLayer = net->AddScatterNdLayer(descriptor, "scatterNd"); IConnectableLayer* outputLayer = net->AddOutputLayer(0, "output"); Connect(shapeLayer, scatterNdLayer, shapeInfo, 0, 0); Connect(indicesLayer, scatterNdLayer, indicesInfo, 0, 1); Connect(updatesLayer, scatterNdLayer, updatesInfo, 0, 2); Connect(scatterNdLayer, outputLayer, outputInfo, 0, 0); return net; } template> void ScatterNd1DimUpdateWithInputEndToEnd(const std::vector& backends) { float_t qScale = 1.f; int32_t qOffset = 0; TensorInfo inputInfo({ 5 }, ArmnnType, qScale, qOffset, true); TensorInfo indicesInfo({ 3, 1 }, DataType::Signed32, 1.0f, 0, true); TensorInfo updatesInfo({ 3 }, ArmnnType, qScale, qOffset, true); TensorInfo outputInfo({ 5 }, ArmnnType, qScale, qOffset, false); std::vector inputData = armnnUtils::QuantizedVector({ 0, 0, 0, 0, 0 }, qScale, qOffset); std::vector indicesData{0, 1, 2}; std::vector updatesData = armnnUtils::QuantizedVector({ 1, 2, 3 }, qScale, qOffset); std::vector expectedOutput = armnnUtils::QuantizedVector({ 1, 2, 3, 0, 0 }, qScale, qOffset); armnn::ScatterNdDescriptor descriptor(armnn::ScatterNdFunction::Update, true); INetworkPtr net = CreateScatterNdNetwork(inputInfo, indicesInfo, updatesInfo, outputInfo, indicesData, updatesData, descriptor); CHECK(net); std::map> inputTensorData = {{ 0, inputData }}; std::map> expectedOutputData = {{ 0, expectedOutput }}; EndToEndLayerTestImpl(std::move(net), inputTensorData, expectedOutputData, backends); } template> void ScatterNd1DimUpdateNoInputEndToEnd(const std::vector& backends) { float_t qScale = 1.f; int32_t qOffset = 0; TensorInfo shapeInfo({ 1 }, DataType::Signed32, 1.0f, 0, true); TensorInfo indicesInfo({ 3, 1 }, DataType::Signed32, 1.0f, 0, true); TensorInfo updatesInfo({ 3 }, ArmnnType, qScale, qOffset, true); TensorInfo outputInfo({ 5 }, ArmnnType, qScale, qOffset, false); std::vector shapeData{ 5 }; std::vector indicesData{ 0, 1, 2 }; std::vector updatesData = armnnUtils::QuantizedVector({ 1, 2, 3 }, qScale, qOffset); std::vector expectedOutput = armnnUtils::QuantizedVector({ 1, 2, 3, 0, 0 }, qScale, qOffset); armnn::ScatterNdDescriptor descriptor(armnn::ScatterNdFunction::Update, false); INetworkPtr net = CreateScatterNdNetwork(shapeInfo, indicesInfo, updatesInfo, outputInfo, indicesData, updatesData, descriptor); CHECK(net); std::map> inputTensorData = {{ 0, shapeData }}; std::map> expectedOutputData = {{ 0, expectedOutput }}; EndToEndLayerTestImpl(std::move(net), inputTensorData, expectedOutputData, backends); } template> void ScatterNd2DimUpdateWithInputEndToEnd(const std::vector& backends) { float_t qScale = 1.f; int32_t qOffset = 0; TensorInfo inputInfo({ 3, 3 }, ArmnnType, qScale, qOffset, true); TensorInfo indicesInfo({ 3, 2 }, DataType::Signed32, 1.0f, 0, true); TensorInfo updatesInfo({ 3 }, ArmnnType, qScale, qOffset, true); TensorInfo outputInfo({ 3, 3 }, ArmnnType, qScale, qOffset, false); std::vector inputData = armnnUtils::QuantizedVector({ 1, 1, 1, 1, 1, 1, 1, 1, 1 }, qScale, qOffset); std::vector indicesData{0, 0, 1, 1, 2, 2}; std::vector updatesData = armnnUtils::QuantizedVector({ 1, 2, 3 }, qScale, qOffset); std::vector expectedOutput = armnnUtils::QuantizedVector({ 1, 1, 1, 1, 2, 1, 1, 1, 3 }, qScale, qOffset); armnn::ScatterNdDescriptor descriptor(armnn::ScatterNdFunction::Update, true); INetworkPtr net = CreateScatterNdNetwork(inputInfo, indicesInfo, updatesInfo, outputInfo, indicesData, updatesData, descriptor); CHECK(net); std::map> inputTensorData = {{ 0, inputData }}; std::map> expectedOutputData = {{ 0, expectedOutput }}; EndToEndLayerTestImpl(std::move(net), inputTensorData, expectedOutputData, backends); } template> void ScatterNd2DimUpdateNoInputEndToEnd(const std::vector& backends) { float_t qScale = 1.f; int32_t qOffset = 0; TensorInfo shapeInfo({ 2 }, DataType::Signed32, 1.0f, 0, true); TensorInfo indicesInfo({ 3, 2 }, DataType::Signed32, 1.0f, 0, true); TensorInfo updatesInfo({ 3 }, ArmnnType, qScale, qOffset, true); TensorInfo outputInfo({ 3, 3 }, ArmnnType, qScale, qOffset, false); std::vector shapeData{ 3, 3 }; std::vector indicesData{0, 0, 1, 1, 2, 2}; std::vector updatesData = armnnUtils::QuantizedVector({ 1, 2, 3 }, qScale, qOffset); std::vector expectedOutput = armnnUtils::QuantizedVector({ 1, 0, 0, 0, 2, 0, 0, 0, 3 }, qScale, qOffset); armnn::ScatterNdDescriptor descriptor(armnn::ScatterNdFunction::Update, false); INetworkPtr net = CreateScatterNdNetwork(shapeInfo, indicesInfo, updatesInfo, outputInfo, indicesData, updatesData, descriptor); CHECK(net); std::map> inputTensorData = {{ 0, shapeData }}; std::map> expectedOutputData = {{ 0, expectedOutput }}; EndToEndLayerTestImpl(std::move(net), inputTensorData, expectedOutputData, backends); } } // anonymous namespace