/*
 * Copyright (c) 2021-2022 Arm Limited.
 *
 * SPDX-License-Identifier: MIT
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to
 * deal in the Software without restriction, including without limitation the
 * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
 * sell copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in all
 * copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
 * SOFTWARE.
 */
#include "src/cpu/kernels/internal/CpuPool2dAssemblyWrapperKernel.h"

#include "arm_compute/core/Utils.h"
#include "arm_compute/core/utils/misc/ShapeCalculator.h"
#include "arm_compute/core/utils/quantization/AsymmHelpers.h"
#include "arm_compute/core/Validate.h"

#include "src/core/CPP/Validate.h"
#include "src/core/helpers/AutoConfiguration.h"
#include "src/core/helpers/WindowHelpers.h"
#include "src/core/NEON/INEKernel.h"

#include <arm_neon.h>

namespace arm_compute
{
namespace cpu
{
namespace kernels
{
using namespace arm_compute::misc::shape_calculator;

void CpuPool2dAssemblyWrapperKernel::configure(const ITensorInfo      *src,
                                               ITensorInfo            *dst,
                                               const PoolingLayerInfo &info,
                                               const CPUInfo          &cpu_info)
{
    ARM_COMPUTE_UNUSED(cpu_info);
    ARM_COMPUTE_ERROR_ON_NULLPTR(src, dst);

    // dst initialization if not yet initialized
    auto_init_if_empty(*dst, src->clone()->set_tensor_shape(compute_pool_shape(*src, info)));

#if defined(__aarch64__)
    const bool requantize = src->quantization_info() != dst->quantization_info();

    switch (src->data_type())
    {
        case DataType::QASYMM8:
            if (requantize)
            {
                create_arm_pooling_requant<uint8_t, uint8_t>(src, dst, info, cpu_info);
            }
            else
            {
                create_arm_pooling<uint8_t, uint8_t>(src, dst, info, cpu_info);
            }
            break;
        case DataType::QASYMM8_SIGNED:
            if (requantize)
            {
                create_arm_pooling_requant<int8_t, int8_t>(src, dst, info, cpu_info);
            }
            else
            {
                create_arm_pooling<int8_t, int8_t>(src, dst, info, cpu_info);
            }
            break;
#ifdef __ARM_FEATURE_FP16_VECTOR_ARITHMETIC
        case DataType::F16:
            create_arm_pooling<float16_t, float16_t>(src, dst, info, cpu_info);
            break;
#endif /* __ARM_FEATURE_FP16_VECTOR_ARITHMETIC */
        case DataType::F32:
            create_arm_pooling<float, float>(src, dst, info, cpu_info);
            break;
        default:
            break;
    }
#endif // defined(__aarch64__)

    Window win = calculate_max_window(*dst, Steps());
    INEKernel::configure(win);
}

Status
CpuPool2dAssemblyWrapperKernel::validate(const ITensorInfo *src, const ITensorInfo *dst, const PoolingLayerInfo &info)
{
    ARM_COMPUTE_RETURN_ERROR_ON_NULLPTR(src, dst);

#ifndef __aarch64__
    ARM_COMPUTE_RETURN_ERROR_MSG("32-bit is not supported by assembly kernels");
#endif /* __aarch64__ */
    ARM_COMPUTE_RETURN_ERROR_ON_CPU_F16_UNSUPPORTED(src);
    ARM_COMPUTE_RETURN_ERROR_ON_DATA_TYPE_CHANNEL_NOT_IN(src, 1, DataType::QASYMM8, DataType::QASYMM8_SIGNED,
                                                         DataType::F16, DataType::F32);
    ARM_COMPUTE_RETURN_ERROR_ON_MSG((src->data_layout() != DataLayout::NHWC) || (info.data_layout != DataLayout::NHWC),
                                    "Only NHWC is supported by assembly kernels");
    ARM_COMPUTE_RETURN_ERROR_ON_MSG((info.pool_type != PoolingType::AVG) && (info.pool_type != PoolingType::MAX),
                                    "Only AVG and MAX pooling are supported by assembly kernels");

    ARM_COMPUTE_RETURN_ERROR_ON_MSG(
        is_pool_region_entirely_outside_input(info),
        "Pooling region that is entirely outside input tensor is unsupported by assembly kernels");

    if (dst->total_size() > 0)
    {
        ARM_COMPUTE_RETURN_ERROR_ON_MISMATCHING_DATA_TYPES(src, dst);

        const auto src_qinfo = src->quantization_info().uniform();
        const auto dst_qinfo = dst->quantization_info().uniform();

        if (src_qinfo != dst_qinfo)
        {
            const float multiplier = src_qinfo.scale / dst_qinfo.scale;
            int32_t     dst_multiplier{};
            int32_t     dst_shift{};
            ARM_COMPUTE_RETURN_ERROR_ON(
                quantization::calculate_quantized_multiplier(multiplier, &dst_multiplier, &dst_shift));
        }
        else
        {
            if (src->data_type() == DataType::QASYMM8)
            {
                const bool has_padding = info.pad_stride_info.has_padding();
                ARM_COMPUTE_RETURN_ERROR_ON_MSG(
                    !info.exclude_padding && has_padding,
                    "Assembly kernels do not support padding for QASYMM8 with same src/dst quantization info");
            }
        }
    }
    else
    {
        if (src->data_type() == DataType::QASYMM8)
        {
            // If dst is not configured, the quantization info are the same
            const bool has_padding = info.pad_stride_info.has_padding();
            ARM_COMPUTE_RETURN_ERROR_ON_MSG(
                !info.exclude_padding && has_padding,
                "Assembly kernels do not support padding for QASYMM8 with same src/dst quantization info");
        }
    }
    return Status{};
}

void CpuPool2dAssemblyWrapperKernel::run_op(ITensorPack &tensors, const Window &window, const ThreadInfo &info)
{
    ARM_COMPUTE_ERROR_ON_NULLPTR(_kernel_asm.get());
    ARM_COMPUTE_ERROR_ON_UNCONFIGURED_KERNEL(this);
    ARM_COMPUTE_UNUSED(window);
    ARM_COMPUTE_UNUSED(info);

    ARM_COMPUTE_ERROR_ON(tensors.empty());

    const ITensor *src       = tensors.get_const_tensor(TensorType::ACL_SRC);
    ITensor       *dst       = tensors.get_tensor(TensorType::ACL_DST);
    ITensor       *workspace = tensors.get_tensor(TensorType::ACL_INT_0);

    const auto in_ptr  = src->buffer() + src->info()->offset_first_element_in_bytes();
    auto       out_ptr = dst->buffer() + dst->info()->offset_first_element_in_bytes();
    auto       working_space =
        (workspace == nullptr) ? nullptr : workspace->buffer() + workspace->info()->offset_first_element_in_bytes();

    const auto src_shape   = src->info()->tensor_shape();
    const auto dst_shape   = dst->info()->tensor_shape();
    const auto src_padding = src->info()->padding();
    const auto dst_padding = dst->info()->padding();

    const size_t ld_src_col   = src_shape[0] + src_padding.left + src_padding.right;
    const size_t ld_src_row   = ld_src_col * (src_shape[1] + src_padding.top + src_padding.bottom);
    const size_t ld_src_batch = ld_src_row * src_shape[2];
    const size_t ld_dst_col   = dst_shape[0] + dst_padding.left + dst_padding.right;
    const size_t ld_dst_row   = ld_dst_col * (dst_shape[1] + dst_padding.top + dst_padding.bottom);
    const size_t ld_dst_batch = ld_dst_row * dst_shape[2];

    _kernel_asm->execute(in_ptr, ld_src_col, ld_src_row, ld_src_batch, out_ptr, ld_dst_col, ld_dst_row, ld_dst_batch,
                         working_space, info.thread_id, info.num_threads);
}

size_t CpuPool2dAssemblyWrapperKernel::get_working_size(unsigned int num_threads) const
{
    return _kernel_asm->get_working_size(num_threads);
}

bool CpuPool2dAssemblyWrapperKernel::is_configured() const
{
    return _kernel_asm != nullptr;
}

template <typename Typesrc, typename Typedst>
void CpuPool2dAssemblyWrapperKernel::create_arm_pooling(const ITensorInfo      *src,
                                                        ITensorInfo            *dst,
                                                        const PoolingLayerInfo &info,
                                                        const CPUInfo          &cpu_info)
{
    const arm_conv::pooling::PoolingType pool_type = (info.pool_type == PoolingType::AVG)
                                                         ? arm_conv::pooling::PoolingType::AVERAGE
                                                         : arm_conv::pooling::PoolingType::MAX;

    arm_conv::pooling::PoolingWindow window{};
    window.cols = static_cast<unsigned int>(info.pool_size.x());
    window.rows = static_cast<unsigned int>(info.pool_size.y());

    arm_conv::pooling::PoolingStride stride{};
    std::tie(stride.cols, stride.rows) = info.pad_stride_info.stride();

    const arm_conv::pooling::PaddingValues padding{info.pad_stride_info.pad_left(), info.pad_stride_info.pad_top(),
                                                   info.pad_stride_info.pad_right(), info.pad_stride_info.pad_bottom()};

    constexpr unsigned int idx_width    = 1;
    constexpr unsigned int idx_height   = 2;
    constexpr unsigned int idx_channels = 0;
    constexpr unsigned int idx_batches  = 3;

    const unsigned int n_batches  = src->dimension(idx_batches);
    const unsigned int src_rows   = src->dimension(idx_height);
    const unsigned int src_cols   = src->dimension(idx_width);
    const unsigned int n_channels = src->dimension(idx_channels);
    const unsigned int dst_rows   = dst->dimension(idx_height);
    const unsigned int dst_cols   = dst->dimension(idx_width);

    arm_conv::pooling::PoolingArgs args(&cpu_info, pool_type, window, stride, info.exclude_padding, n_batches, src_rows,
                                        src_cols, n_channels, dst_rows, dst_cols, padding, nullptr);

    // Configure assembly pooling kernel
    auto pooling_kernel_asm = arm_conv::pooling::pooling<Typesrc, Typedst>(args);
    if (pooling_kernel_asm == nullptr)
    {
        // Configuration not supported: Leave function unconfigured:
        return;
    }

    _kernel_asm = std::move(pooling_kernel_asm);
}

template <typename Typesrc, typename Typedst>
void CpuPool2dAssemblyWrapperKernel::create_arm_pooling_requant(const ITensorInfo      *src,
                                                                ITensorInfo            *dst,
                                                                const PoolingLayerInfo &info,
                                                                const CPUInfo          &cpu_info)
{
    const arm_conv::pooling::PoolingType pool_type = (info.pool_type == PoolingType::AVG)
                                                         ? arm_conv::pooling::PoolingType::AVERAGE
                                                         : arm_conv::pooling::PoolingType::MAX;

    arm_conv::pooling::PoolingWindow window{};
    window.cols = static_cast<unsigned int>(info.pool_size.x());
    window.rows = static_cast<unsigned int>(info.pool_size.y());

    arm_conv::pooling::PoolingStride stride{};
    std::tie(stride.cols, stride.rows) = info.pad_stride_info.stride();

    const arm_conv::pooling::PaddingValues padding{info.pad_stride_info.pad_left(), info.pad_stride_info.pad_top(),
                                                   info.pad_stride_info.pad_right(), info.pad_stride_info.pad_bottom()};

    constexpr unsigned int idx_width    = 1;
    constexpr unsigned int idx_height   = 2;
    constexpr unsigned int idx_channels = 0;
    constexpr unsigned int idx_batches  = 3;

    const unsigned int n_batches  = src->dimension(idx_batches);
    const unsigned int src_rows   = src->dimension(idx_height);
    const unsigned int src_cols   = src->dimension(idx_width);
    const unsigned int n_channels = src->dimension(idx_channels);
    const unsigned int dst_rows   = dst->dimension(idx_height);
    const unsigned int dst_cols   = dst->dimension(idx_width);

    arm_conv::pooling::PoolingArgs args(&cpu_info, pool_type, window, stride, info.exclude_padding, n_batches, src_rows,
                                        src_cols, n_channels, dst_rows, dst_cols, padding, nullptr);

    const auto src_qinfo = src->quantization_info().uniform();
    const auto dst_qinfo = dst->quantization_info().uniform();

    const float multiplier = src_qinfo.scale / dst_qinfo.scale;
    int32_t     dst_multiplier{};
    int32_t     dst_shift{};
    quantization::calculate_quantized_multiplier(multiplier, &dst_multiplier, &dst_shift);

    const arm_conv::pooling::Requantize32 requant_args(src_qinfo.offset, dst_qinfo.offset,
                                                       dst_shift, // left shift
                                                       0,         // right shift
                                                       dst_multiplier);

    // Configure assembly pooling kernel with requantization
    auto pooling_kernel_asm =
        arm_conv::pooling::pooling<Typesrc, Typedst, arm_conv::pooling::Requantize32>(args, requant_args);
    if (pooling_kernel_asm == nullptr)
    {
        // Configuration not supported: Leave function unconfigured:
        return;
    }

    _kernel_asm = std::move(pooling_kernel_asm);
}

size_t CpuPool2dAssemblyWrapperKernel::get_mws(const CPUInfo &platform, size_t thread_count) const
{
    ARM_COMPUTE_UNUSED(thread_count);
    ARM_COMPUTE_UNUSED(platform);

    return ICPPKernel::default_mws;
}
} // namespace kernels
} // namespace cpu
} // namespace arm_compute
