//
// Copyright © 2017 Arm Ltd. All rights reserved.
// SPDX-License-Identifier: MIT
//

#include "GatherTestImpl.hpp"

#include <ResolveType.hpp>


#include <backendsCommon/test/TensorCopyUtils.hpp>
#include <backendsCommon/test/WorkloadTestUtils.hpp>

#include <test/TensorHelpers.hpp>

namespace
{

template <armnn::DataType ArmnnType,
          typename T = armnn::ResolveType<ArmnnType>,
          size_t ParamsDim,
          size_t IndicesDim,
          size_t OutputDim>
LayerTestResult<T, OutputDim> GatherTestImpl(
    armnn::IWorkloadFactory& workloadFactory,
    const armnn::IBackendInternal::IMemoryManagerSharedPtr& memoryManager,
    const armnn::TensorInfo& paramsInfo,
    const armnn::TensorInfo& indicesInfo,
    const armnn::TensorInfo& outputInfo,
    const std::vector<T>& paramsData,
    const std::vector<int32_t>& indicesData,
    const std::vector<T>& outputData)
{
    boost::ignore_unused(memoryManager);
    auto params  = MakeTensor<T, ParamsDim>(paramsInfo, paramsData);
    auto indices = MakeTensor<int32_t, IndicesDim>(indicesInfo, indicesData);

    LayerTestResult<T, OutputDim> result(outputInfo);
    result.outputExpected = MakeTensor<T, OutputDim>(outputInfo, outputData);

    std::unique_ptr<armnn::ITensorHandle> paramsHandle = workloadFactory.CreateTensorHandle(paramsInfo);
    std::unique_ptr<armnn::ITensorHandle> indicesHandle = workloadFactory.CreateTensorHandle(indicesInfo);
    std::unique_ptr<armnn::ITensorHandle> outputHandle = workloadFactory.CreateTensorHandle(outputInfo);

    armnn::GatherQueueDescriptor data;
    armnn::WorkloadInfo info;
    AddInputToWorkload(data,  info, paramsInfo, paramsHandle.get());
    AddInputToWorkload(data, info, indicesInfo, indicesHandle.get());
    AddOutputToWorkload(data, info, outputInfo, outputHandle.get());

    std::unique_ptr<armnn::IWorkload> workload = workloadFactory.CreateGather(data, info);

    paramsHandle->Allocate();
    indicesHandle->Allocate();
    outputHandle->Allocate();

    CopyDataToITensorHandle(paramsHandle.get(), params.origin());
    CopyDataToITensorHandle(indicesHandle.get(), indices.origin());

    workload->Execute();

    CopyDataFromITensorHandle(result.output.origin(), outputHandle.get());

    return result;
}

template<armnn::DataType ArmnnType, typename T = armnn::ResolveType<ArmnnType>>
struct GatherTestHelper
{
    static LayerTestResult<T, 1> Gather1dParamsTestImpl(
        armnn::IWorkloadFactory& workloadFactory,
        const armnn::IBackendInternal::IMemoryManagerSharedPtr& memoryManager)
    {
        armnn::TensorInfo paramsInfo({ 8 }, ArmnnType);
        armnn::TensorInfo indicesInfo({ 4 }, armnn::DataType::Signed32);
        armnn::TensorInfo outputInfo({ 4 }, ArmnnType);

        if (armnn::IsQuantizedType<T>())
        {
            paramsInfo.SetQuantizationScale(1.0f);
            paramsInfo.SetQuantizationOffset(1);
            outputInfo.SetQuantizationScale(1.0f);
            outputInfo.SetQuantizationOffset(1);
        }
        const std::vector<T> params         = std::vector<T>({ 1, 2, 3, 4, 5, 6, 7, 8 });
        const std::vector<int32_t> indices  = std::vector<int32_t>({ 0, 2, 1, 5 });
        const std::vector<T> expectedOutput = std::vector<T>({ 1, 3, 2, 6 });

        return GatherTestImpl<ArmnnType, T, 1, 1, 1>(
            workloadFactory,
            memoryManager,
            paramsInfo,
            indicesInfo,
            outputInfo,
            params,
            indices,
            expectedOutput);
    }

    static LayerTestResult<T, 2> GatherMultiDimParamsTestImpl(
        armnn::IWorkloadFactory& workloadFactory,
        const armnn::IBackendInternal::IMemoryManagerSharedPtr& memoryManager)
    {
        armnn::TensorInfo paramsInfo({ 5, 2 }, ArmnnType);
        armnn::TensorInfo indicesInfo({ 3 }, armnn::DataType::Signed32);
        armnn::TensorInfo outputInfo({ 3, 2 }, ArmnnType);

        if (armnn::IsQuantizedType<T>())
        {
            paramsInfo.SetQuantizationScale(1.0f);
            paramsInfo.SetQuantizationOffset(1);
            outputInfo.SetQuantizationScale(1.0f);
            outputInfo.SetQuantizationOffset(1);
        }

        const std::vector<T> params         = std::vector<T>({ 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 });
        const std::vector<int32_t> indices  = std::vector<int32_t>({ 1, 3, 4 });
        const std::vector<T> expectedOutput = std::vector<T>({ 3, 4, 7, 8, 9, 10 });

        return GatherTestImpl<ArmnnType, T, 2, 1, 2>(
            workloadFactory,
            memoryManager,
            paramsInfo,
            indicesInfo,
            outputInfo,
            params,
            indices,
            expectedOutput);
    }

    static LayerTestResult<T, 4> GatherMultiDimParamsMultiDimIndicesTestImpl(
        armnn::IWorkloadFactory& workloadFactory,
        const armnn::IBackendInternal::IMemoryManagerSharedPtr& memoryManager)
    {
        armnn::TensorInfo paramsInfo({ 3, 2, 3}, ArmnnType);
        armnn::TensorInfo indicesInfo({ 2, 3 }, armnn::DataType::Signed32);
        armnn::TensorInfo outputInfo({ 2, 3, 2, 3 }, ArmnnType);

        if (armnn::IsQuantizedType<T>())
        {
            paramsInfo.SetQuantizationScale(1.0f);
            paramsInfo.SetQuantizationOffset(1);
            outputInfo.SetQuantizationScale(1.0f);
            outputInfo.SetQuantizationOffset(1);
        }

        const std::vector<T> params =
        {
            1,  2,  3,
            4,  5,  6,

            7,  8,  9,
            10, 11, 12,

            13, 14, 15,
            16, 17, 18
        };

        const std::vector<int32_t> indices = { 1, 2, 1, 2, 1, 0 };

        const std::vector<T> expectedOutput =
        {
            7,  8,  9,
            10, 11, 12,
            13, 14, 15,
            16, 17, 18,
            7,  8,  9,
            10, 11, 12,

            13, 14, 15,
            16, 17, 18,
            7,  8,  9,
            10, 11, 12,
            1,  2,  3,
            4,  5,  6
        };

        return GatherTestImpl<ArmnnType, T, 3, 2, 4>(
            workloadFactory,
            memoryManager,
            paramsInfo,
            indicesInfo,
            outputInfo,
            params,
            indices,
            expectedOutput);
    }
};

template<typename T>
struct GatherTestHelper<armnn::DataType::Float16, T>
{
    static LayerTestResult<T, 1> Gather1dParamsTestImpl(
        armnn::IWorkloadFactory& workloadFactory,
        const armnn::IBackendInternal::IMemoryManagerSharedPtr& memoryManager)
    {
        using namespace half_float::literal;

        armnn::TensorInfo paramsInfo({ 8 }, armnn::DataType::Float16);
        armnn::TensorInfo indicesInfo({ 4 }, armnn::DataType::Signed32);
        armnn::TensorInfo outputInfo({ 4 }, armnn::DataType::Float16);

        const std::vector<T> params = std::vector<T>({ 1._h, 2._h, 3._h, 4._h, 5._h, 6._h, 7._h, 8._h });
        const std::vector<int32_t> indices  = std::vector<int32_t>({ 0, 2, 1, 5 });
        const std::vector<T> expectedOutput = std::vector<T>({ 1._h, 3._h, 2._h, 6._h });

        return GatherTestImpl<armnn::DataType::Float16, T, 1, 1, 1>(
            workloadFactory,
            memoryManager,
            paramsInfo,
            indicesInfo,
            outputInfo,
            params,
            indices,
            expectedOutput);
    }

    static LayerTestResult<T, 2> GatherMultiDimParamsTestImpl(
        armnn::IWorkloadFactory& workloadFactory,
        const armnn::IBackendInternal::IMemoryManagerSharedPtr& memoryManager)
    {
        using namespace half_float::literal;

        armnn::TensorInfo paramsInfo({ 5, 2 }, armnn::DataType::Float16);
        armnn::TensorInfo indicesInfo({ 3 }, armnn::DataType::Signed32);
        armnn::TensorInfo outputInfo({ 3, 2 }, armnn::DataType::Float16);

        const std::vector<T> params = std::vector<T>({ 1._h, 2._h, 3._h, 4._h, 5._h, 6._h, 7._h, 8._h, 9._h, 10._h });

        const std::vector<int32_t> indices  = std::vector<int32_t>({ 1, 3, 4 });
        const std::vector<T> expectedOutput = std::vector<T>({ 3._h, 4._h, 7._h, 8._h, 9._h, 10._h });

        return GatherTestImpl<armnn::DataType::Float16, T, 2, 1, 2>(
            workloadFactory,
            memoryManager,
            paramsInfo,
            indicesInfo,
            outputInfo,
            params,
            indices,
            expectedOutput);
    }

    static LayerTestResult<T, 4> GatherMultiDimParamsMultiDimIndicesTestImpl(
        armnn::IWorkloadFactory& workloadFactory,
        const armnn::IBackendInternal::IMemoryManagerSharedPtr& memoryManager)
    {
        using namespace half_float::literal;

        armnn::TensorInfo paramsInfo({ 3, 2, 3 }, armnn::DataType::Float16);
        armnn::TensorInfo indicesInfo({ 2, 3 }, armnn::DataType::Signed32);
        armnn::TensorInfo outputInfo({ 2, 3, 2, 3 }, armnn::DataType::Float16);

        const std::vector<T> params =
        {
            1._h,  2._h,  3._h,
            4._h,  5._h,  6._h,

            7._h,  8._h,  9._h,
            10._h, 11._h, 12._h,

            13._h, 14._h, 15._h,
            16._h, 17._h, 18._h
        };

        const std::vector<int32_t> indices = { 1, 2, 1, 2, 1, 0 };

        const std::vector<T> expectedOutput =
        {
            7._h,  8._h,  9._h,
            10._h, 11._h, 12._h,
            13._h, 14._h, 15._h,
            16._h, 17._h, 18._h,
            7._h,  8._h,  9._h,
            10._h, 11._h, 12._h,

            13._h, 14._h, 15._h,
            16._h, 17._h, 18._h,
            7._h,  8._h,  9._h,
            10._h, 11._h, 12._h,
            1._h,  2._h,  3._h,
            4._h,  5._h,  6._h
        };

        return GatherTestImpl<armnn::DataType::Float16, T, 3, 2, 4>(
            workloadFactory,
            memoryManager,
            paramsInfo,
            indicesInfo,
            outputInfo,
            params,
            indices,
            expectedOutput);
    }
};

} // anonymous namespace

LayerTestResult<float, 1> Gather1dParamsFloat32Test(
    armnn::IWorkloadFactory& workloadFactory,
    const armnn::IBackendInternal::IMemoryManagerSharedPtr& memoryManager)
{
    return GatherTestHelper<armnn::DataType::Float32>::Gather1dParamsTestImpl(workloadFactory, memoryManager);
}

LayerTestResult<armnn::Half, 1> Gather1dParamsFloat16Test(
    armnn::IWorkloadFactory& workloadFactory,
    const armnn::IBackendInternal::IMemoryManagerSharedPtr& memoryManager)
{
    return GatherTestHelper<armnn::DataType::Float16>::Gather1dParamsTestImpl(workloadFactory, memoryManager);
}

LayerTestResult<uint8_t, 1> Gather1dParamsUint8Test(
    armnn::IWorkloadFactory& workloadFactory,
    const armnn::IBackendInternal::IMemoryManagerSharedPtr& memoryManager)
{
    return GatherTestHelper<armnn::DataType::QAsymmU8>::Gather1dParamsTestImpl(workloadFactory, memoryManager);
}

LayerTestResult<int16_t, 1> Gather1dParamsInt16Test(
        armnn::IWorkloadFactory& workloadFactory,
        const armnn::IBackendInternal::IMemoryManagerSharedPtr& memoryManager)
{
    return GatherTestHelper<armnn::DataType::QSymmS16>::Gather1dParamsTestImpl(workloadFactory, memoryManager);
}

LayerTestResult<float, 2> GatherMultiDimParamsFloat32Test(
    armnn::IWorkloadFactory& workloadFactory,
    const armnn::IBackendInternal::IMemoryManagerSharedPtr& memoryManager)
{
    return GatherTestHelper<armnn::DataType::Float32>::GatherMultiDimParamsTestImpl(workloadFactory, memoryManager);
}

LayerTestResult<armnn::Half, 2> GatherMultiDimParamsFloat16Test(
    armnn::IWorkloadFactory& workloadFactory,
    const armnn::IBackendInternal::IMemoryManagerSharedPtr& memoryManager)
{
    return GatherTestHelper<armnn::DataType::Float16>::GatherMultiDimParamsTestImpl(workloadFactory, memoryManager);
}

LayerTestResult<uint8_t, 2> GatherMultiDimParamsUint8Test(
    armnn::IWorkloadFactory& workloadFactory,
    const armnn::IBackendInternal::IMemoryManagerSharedPtr& memoryManager)
{
    return GatherTestHelper<armnn::DataType::QAsymmU8>::GatherMultiDimParamsTestImpl(
        workloadFactory, memoryManager);
}

LayerTestResult<int16_t, 2> GatherMultiDimParamsInt16Test(
        armnn::IWorkloadFactory& workloadFactory,
        const armnn::IBackendInternal::IMemoryManagerSharedPtr& memoryManager)
{
    return GatherTestHelper<armnn::DataType::QSymmS16>::GatherMultiDimParamsTestImpl(
        workloadFactory, memoryManager);
}

LayerTestResult<float, 4> GatherMultiDimParamsMultiDimIndicesFloat32Test(
    armnn::IWorkloadFactory& workloadFactory,
    const armnn::IBackendInternal::IMemoryManagerSharedPtr& memoryManager)
{
    return GatherTestHelper<armnn::DataType::Float32>::GatherMultiDimParamsMultiDimIndicesTestImpl(
        workloadFactory, memoryManager);
}

LayerTestResult<armnn::Half, 4> GatherMultiDimParamsMultiDimIndicesFloat16Test(
    armnn::IWorkloadFactory& workloadFactory,
    const armnn::IBackendInternal::IMemoryManagerSharedPtr& memoryManager)
{
    return GatherTestHelper<armnn::DataType::Float16>::GatherMultiDimParamsMultiDimIndicesTestImpl(
        workloadFactory, memoryManager);
}

LayerTestResult<uint8_t, 4> GatherMultiDimParamsMultiDimIndicesUint8Test(
    armnn::IWorkloadFactory& workloadFactory,
    const armnn::IBackendInternal::IMemoryManagerSharedPtr& memoryManager)
{
    return GatherTestHelper<armnn::DataType::QAsymmU8>::GatherMultiDimParamsMultiDimIndicesTestImpl(
        workloadFactory, memoryManager);
}

LayerTestResult<int16_t, 4> GatherMultiDimParamsMultiDimIndicesInt16Test(
        armnn::IWorkloadFactory& workloadFactory,
        const armnn::IBackendInternal::IMemoryManagerSharedPtr& memoryManager)
{
    return GatherTestHelper<armnn::DataType::QSymmS16>::GatherMultiDimParamsMultiDimIndicesTestImpl(
        workloadFactory, memoryManager);
}
