/*
 * Copyright (c) 2017-2020 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 "arm_compute/core/NEON/kernels/NENormalizationLayerKernel.h"

#include "arm_compute/core/AccessWindowStatic.h"
#include "arm_compute/core/CPP/Validate.h"
#include "arm_compute/core/Error.h"
#include "arm_compute/core/Helpers.h"
#include "arm_compute/core/TensorInfo.h"
#include "arm_compute/core/Utils.h"
#include "arm_compute/core/Validate.h"
#include "arm_compute/core/Window.h"
#include "src/core/NEON/NEFixedPoint.h"
#include "src/core/NEON/NEMath.h"
#include "src/core/NEON/wrapper/wrapper.h"

namespace arm_compute
{
namespace
{
Status validate_arguments(const ITensorInfo *input, const ITensorInfo *input_squared, const ITensorInfo *output, const NormalizationLayerInfo &norm_info)
{
    ARM_COMPUTE_RETURN_ERROR_ON_NULLPTR(input, input_squared, output);
    ARM_COMPUTE_RETURN_ERROR_ON_CPU_F16_UNSUPPORTED(input);
    ARM_COMPUTE_RETURN_ERROR_ON_DATA_TYPE_CHANNEL_NOT_IN(input, 1, DataType::F16, DataType::F32);

    ARM_COMPUTE_RETURN_ERROR_ON_MISMATCHING_DATA_TYPES(input, input_squared);
    ARM_COMPUTE_RETURN_ERROR_ON_MISMATCHING_SHAPES(input, input_squared);
    ARM_COMPUTE_RETURN_ERROR_ON_MSG(!(norm_info.norm_size() % 2), "Normalization size should be odd");

    // Checks performed when output is configured
    if(output->total_size() != 0)
    {
        ARM_COMPUTE_RETURN_ERROR_ON_MISMATCHING_DATA_TYPES(input, output);
        ARM_COMPUTE_RETURN_ERROR_ON_MISMATCHING_SHAPES(input, output);
        ARM_COMPUTE_RETURN_ERROR_ON_MISMATCHING_DATA_LAYOUT(input, output);
    }

    return Status{};
}

} // namespace

NENormalizationLayerKernel::NENormalizationLayerKernel()
    : _func(nullptr), _input(nullptr), _input_squared(nullptr), _output(nullptr), _norm_info(NormType::IN_MAP_1D)
{
}

void NENormalizationLayerKernel::configure(const ITensor *input, const ITensor *input_squared, ITensor *output, NormalizationLayerInfo norm_info)
{
    ARM_COMPUTE_ERROR_ON_NULLPTR(input, input_squared, output);
    // Output tensor auto initialization if not yet initialized
    auto_init_if_empty(*output->info(), *input->info());

    // Perform validation step
    ARM_COMPUTE_ERROR_THROW_ON(validate_arguments(input->info(), input_squared->info(), output->info(), norm_info));

    const unsigned int norm_idx = get_normalization_dimension_index(input->info()->data_layout(), norm_info);

    _input         = input;
    _input_squared = input_squared;
    _output        = output;
    _norm_info     = norm_info;

    switch(_input->info()->data_type())
    {
        case DataType::F32:
        {
            switch(norm_idx)
            {
                case 0:
                {
                    if(norm_info.type() == NormType::IN_MAP_2D)
                    {
                        _func = &NENormalizationLayerKernel::normalize_float<float, 4, 0, true>;
                    }
                    else
                    {
                        _func = &NENormalizationLayerKernel::normalize_float<float, 4, 0, false>;
                    }
                    break;
                }
                case 1:
                    if(norm_info.type() == NormType::IN_MAP_2D)
                    {
                        _func = &NENormalizationLayerKernel::normalize_float<float, 4, 1, true>;
                    }
                    else
                    {
                        _func = &NENormalizationLayerKernel::normalize_float<float, 4, 1, false>;
                    }
                    break;
                case 2:
                    _func = &NENormalizationLayerKernel::normalize_float<float, 4, 2, false>;
                    break;
                default:
                    break;
            }
            break;
        }
#ifdef __ARM_FEATURE_FP16_VECTOR_ARITHMETIC
        case DataType::F16:
        {
            switch(norm_idx)
            {
                case 0:
                {
                    if(norm_info.type() == NormType::IN_MAP_2D)
                    {
                        _func = &NENormalizationLayerKernel::normalize_float<float16_t, 8, 0, true>;
                    }
                    else
                    {
                        _func = &NENormalizationLayerKernel::normalize_float<float16_t, 8, 0, false>;
                    }
                    break;
                }
                case 1:
                    if(norm_info.type() == NormType::IN_MAP_2D)
                    {
                        _func = &NENormalizationLayerKernel::normalize_float<float16_t, 8, 1, true>;
                    }
                    else
                    {
                        _func = &NENormalizationLayerKernel::normalize_float<float16_t, 8, 1, false>;
                    }
                    break;
                case 2:
                    _func = &NENormalizationLayerKernel::normalize_float<float16_t, 8, 2, false>;
                    break;
                default:
                    break;
            }
            break;
        }
#endif /* __ARM_FEATURE_FP16_VECTOR_ARITHMETIC */
        default:
            ARM_COMPUTE_ERROR("NOT SUPPORTED!");
    }

    // Configure kernel window
    Window      win = calculate_max_window(*input->info(), Steps());
    Coordinates coord;
    coord.set_num_dimensions(output->info()->num_dimensions());
    output->info()->set_valid_region(ValidRegion(coord, output->info()->tensor_shape()));
    INEKernel::configure(win);
}

template <typename T, unsigned int S, unsigned int dim, bool do_2D_norm>
void NENormalizationLayerKernel::normalize_float(const Window &window)
{
    /** NEON vector tag type. */
    using ExactTagType = typename wrapper::traits::neon_vector<T, S>::tag_type;

    Window win(window);
    win.set(Window::DimX, Window::Dimension(0, 1, 1));

    const auto window_start_x = static_cast<int>(window.x().start());
    const auto window_end_x   = static_cast<int>(window.x().end());
    const int  window_step_x  = S;

    Iterator input(_input, win);
    Iterator input_squared(_input_squared, win);
    Iterator output(_output, win);

    const int dim_y                      = _input->info()->data_layout() == DataLayout::NCHW ? 1 : 2;
    const int radius                     = _norm_info.norm_size() / 2;
    const int input_squared_stride_x     = _input_squared->info()->strides_in_bytes()[0];
    const int input_squared_stride_slice = _input_squared->info()->strides_in_bytes()[dim];
    const int input_squared_stride_row   = _input_squared->info()->strides_in_bytes()[dim_y];

    const int max_right  = _input->info()->dimension(dim) - 1;
    const int max_bottom = _input->info()->dimension(dim_y) - 1;

    const auto coeff_vec = wrapper::vdup_n(static_cast<T>(_norm_info.scale_coeff()), ExactTagType{});
    const auto beta_vec  = wrapper::vdup_n(static_cast<T>(_norm_info.beta()), ExactTagType{});
    const auto kappa_vec = wrapper::vdup_n(static_cast<T>(_norm_info.kappa()), ExactTagType{});

    auto sequential_normalization = [&](const int x, const Coordinates & id, const int current_row, const int first_row, const int last_row, const T * input_ptr, const uint8_t *input_squared_start_ptr,
                                        T * output_ptr)
    {
        const int current_slice = dim == 0 ? x : id[dim];
        const int first_slice   = std::max(current_slice - radius, 0);
        const int last_slice    = std::min(current_slice + radius, max_right);

        const uint8_t *const input_squared_x_ptr = input_squared_start_ptr + x * input_squared_stride_x;
        // Accumulate 2D In-Map values
        auto accu = static_cast<T>(0.f);
        for(int j = first_row; j <= last_row; ++j)
        {
            // Compute row displacement
            const uint8_t *const input_squared_ptr = input_squared_x_ptr + (j - current_row) * input_squared_stride_row;
            for(int i = first_slice; i <= last_slice; ++i)
            {
                accu += *reinterpret_cast<const T *>(input_squared_ptr + (i - current_slice) * input_squared_stride_slice);
            }
        }

        // Normalize
        const auto normalized       = std::pow(accu * static_cast<T>(_norm_info.scale_coeff()) + static_cast<T>(_norm_info.kappa()), _norm_info.beta());
        const auto normalized_pixel = (*(input_ptr + x)) / normalized;
        *(output_ptr + x)           = normalized_pixel;
    };

    execute_window_loop(win, [&](const Coordinates & id)
    {
        const auto input_ptr  = reinterpret_cast<const T *>(input.ptr());
        auto       output_ptr = reinterpret_cast<T *>(output.ptr());

        // Get range to normalize
        const int current_row = do_2D_norm ? id[dim_y] : 0;
        const int first_row   = do_2D_norm ? std::max(current_row - radius, 0) : 0;
        const int last_row    = do_2D_norm ? std::min(current_row + radius, max_bottom) : 0;

        int x = window_start_x;
        // Compute serially starting elements for the case x dimension is width
        for(; x < radius && x < window_end_x && dim == 0; ++x)
        {
            sequential_normalization(x, id, current_row, first_row, last_row, input_ptr, input_squared.ptr(), output_ptr);
        }

        // Compute vectorized
        for(; x <= window_end_x - window_step_x - radius; x += window_step_x)
        {
            const int current_slice = dim == 0 ? x : id[dim];
            const int first_slice   = std::max(current_slice - radius, 0);
            const int last_slice    = std::min(current_slice + radius, max_right);

            const uint8_t *const input_squared_x_ptr = input_squared.ptr() + x * input_squared_stride_x;
            // Accumulate 2D In-Map values
            auto accu = wrapper::vdup_n(static_cast<T>(0.f), ExactTagType{});
            for(int j = first_row; j <= last_row; ++j)
            {
                // Compute row displacement
                const uint8_t *const input_squared_ptr = input_squared_x_ptr + (j - current_row) * input_squared_stride_row;
                for(int i = first_slice; i <= last_slice; ++i)
                {
                    accu = wrapper::vadd(accu, wrapper::vloadq(reinterpret_cast<const T *>(input_squared_ptr + (i - current_slice) * input_squared_stride_slice)));
                }
            }

            // Normalize
            const auto normalized       = wrapper::vpow(wrapper::vmla(kappa_vec, coeff_vec, accu), beta_vec);
            const auto normalized_pixel = wrapper::vmul(wrapper::vloadq(input_ptr + x), wrapper::vinv(normalized));
            wrapper::vstore(reinterpret_cast<T *>(output_ptr + x), normalized_pixel);
        }

        // Compute left-over elements
        for(; x < window_end_x; ++x)
        {
            sequential_normalization(x, id, current_row, first_row, last_row, input_ptr, input_squared.ptr(), output_ptr);
        }
    },
    input, input_squared, output);
}

Status NENormalizationLayerKernel::validate(const ITensorInfo *input, const ITensorInfo *input_squared, const ITensorInfo *output, const NormalizationLayerInfo norm_info)
{
    ARM_COMPUTE_RETURN_ON_ERROR(validate_arguments(input, input_squared, output, norm_info));

    return Status{};
}

void NENormalizationLayerKernel::run(const Window &window, const ThreadInfo &info)
{
    ARM_COMPUTE_UNUSED(info);
    ARM_COMPUTE_ERROR_ON_UNCONFIGURED_KERNEL(this);
    ARM_COMPUTE_ERROR_ON_INVALID_SUBWINDOW(INEKernel::window(), window);
    ARM_COMPUTE_ERROR_ON(_func == nullptr);

    // Run function
    (this->*_func)(window);
}
} // namespace arm_compute