/*
 * Copyright (c) 2018 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 "ROIAlignLayer.h"

#include "arm_compute/core/Types.h"
#include "arm_compute/core/utils/misc/ShapeCalculator.h"
#include "tests/validation/Helpers.h"

#include <algorithm>

namespace arm_compute
{
namespace test
{
namespace validation
{
namespace reference
{
namespace
{
/** Average pooling over an aligned window */
template <typename T>
inline T roi_align_1x1(const T *input, TensorShape input_shape,
                       float region_start_x,
                       float bin_size_x,
                       int   grid_size_x,
                       float region_end_x,
                       float region_start_y,
                       float bin_size_y,
                       int   grid_size_y,
                       float region_end_y,
                       int   pz)
{
    if((region_end_x <= region_start_x) || (region_end_y <= region_start_y))
    {
        return T(0);
    }
    else
    {
        float avg = 0;
        // Iterate through the aligned pooling region
        for(int iy = 0; iy < grid_size_y; ++iy)
        {
            for(int ix = 0; ix < grid_size_x; ++ix)
            {
                // Align the window in the middle of every bin
                float y = region_start_y + (iy + 0.5) * bin_size_y / float(grid_size_y);
                float x = region_start_x + (ix + 0.5) * bin_size_x / float(grid_size_x);

                // Interpolation in the [0,0] [0,1] [1,0] [1,1] square
                const int y_low  = y;
                const int x_low  = x;
                const int y_high = y_low + 1;
                const int x_high = x_low + 1;

                const float ly = y - y_low;
                const float lx = x - x_low;
                const float hy = 1. - ly;
                const float hx = 1. - lx;

                const float w1 = hy * hx;
                const float w2 = hy * lx;
                const float w3 = ly * hx;
                const float w4 = ly * lx;

                const size_t idx1  = coord2index(input_shape, Coordinates(x_low, y_low, pz));
                T            data1 = input[idx1];

                const size_t idx2  = coord2index(input_shape, Coordinates(x_high, y_low, pz));
                T            data2 = input[idx2];

                const size_t idx3  = coord2index(input_shape, Coordinates(x_low, y_high, pz));
                T            data3 = input[idx3];

                const size_t idx4  = coord2index(input_shape, Coordinates(x_high, y_high, pz));
                T            data4 = input[idx4];

                avg += w1 * data1 + w2 * data2 + w3 * data3 + w4 * data4;
            }
        }

        avg /= grid_size_x * grid_size_y;

        return T(avg);
    }
}

/** Clamp the value between lower and upper */
template <typename T>
T clamp(T value, T lower, T upper)
{
    return std::max(lower, std::min(value, upper));
}
} // namespace
template <typename T>
SimpleTensor<T> roi_align_layer(const SimpleTensor<T> &src, const std::vector<ROI> &rois, const ROIPoolingLayerInfo &pool_info)
{
    const size_t num_rois      = rois.size();
    DataType     dst_data_type = src.data_type();

    TensorShape     input_shape = src.shape();
    TensorShape     output_shape(pool_info.pooled_width(), pool_info.pooled_height(), src.shape()[2], num_rois);
    SimpleTensor<T> dst(output_shape, dst_data_type);

    // Iterate over every pixel of the input image
    for(size_t px = 0; px < pool_info.pooled_width(); px++)
    {
        for(size_t py = 0; py < pool_info.pooled_height(); py++)
        {
            for(size_t pw = 0; pw < num_rois; pw++)
            {
                ROI       roi       = rois[pw];
                const int roi_batch = roi.batch_idx;

                const float roi_anchor_x = roi.rect.x * pool_info.spatial_scale();
                const float roi_anchor_y = roi.rect.y * pool_info.spatial_scale();
                const float roi_dims_x   = std::max(roi.rect.width * pool_info.spatial_scale(), 1.0f);
                const float roi_dims_y   = std::max(roi.rect.height * pool_info.spatial_scale(), 1.0f);
                ;

                float bin_size_x     = roi_dims_x / pool_info.pooled_width();
                float bin_size_y     = roi_dims_y / pool_info.pooled_height();
                float region_start_x = px * bin_size_x + roi_anchor_x;
                float region_start_y = py * bin_size_y + roi_anchor_y;
                float region_end_x   = (px + 1) * bin_size_x + roi_anchor_x;
                float region_end_y   = (py + 1) * bin_size_y + roi_anchor_y;

                region_start_x = clamp(region_start_x, 0.0f, float(input_shape[0]));
                region_start_y = clamp(region_start_y, 0.0f, float(input_shape[1]));
                region_end_x   = clamp(region_end_x, 0.0f, float(input_shape[0]));
                region_end_y   = clamp(region_end_y, 0.0f, float(input_shape[1]));

                const int roi_bin_grid_x = (pool_info.sampling_ratio() > 0) ? pool_info.sampling_ratio() : int(ceil(bin_size_x));
                const int roi_bin_grid_y = (pool_info.sampling_ratio() > 0) ? pool_info.sampling_ratio() : int(ceil(bin_size_y));

                // Move input and output pointer across the fourth dimension
                const size_t input_stride_w  = input_shape[0] * input_shape[1] * input_shape[2];
                const size_t output_stride_w = output_shape[0] * output_shape[1] * output_shape[2];
                const T     *input_ptr       = src.data() + roi_batch * input_stride_w;
                T           *output_ptr      = dst.data() + px + py * output_shape[0] + pw * output_stride_w;

                for(int pz = 0; pz < int(input_shape[2]); ++pz)
                {
                    // For every pixel pool over an aligned region
                    *(output_ptr + pz * output_shape[0] * output_shape[1]) = roi_align_1x1(input_ptr, input_shape,
                                                                                           region_start_x,
                                                                                           bin_size_x,
                                                                                           roi_bin_grid_x,
                                                                                           region_end_x,
                                                                                           region_start_y,
                                                                                           bin_size_y,
                                                                                           roi_bin_grid_y,
                                                                                           region_end_y, pz);
                }
            }
        }
    }
    return dst;
}
template SimpleTensor<float> roi_align_layer(const SimpleTensor<float> &src, const std::vector<ROI> &rois, const ROIPoolingLayerInfo &pool_info);
template SimpleTensor<half> roi_align_layer(const SimpleTensor<half> &src, const std::vector<ROI> &rois, const ROIPoolingLayerInfo &pool_info);
} // namespace reference
} // namespace validation
} // namespace test
} // namespace arm_compute
