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

#include "bit_ops.h"

namespace arm_compute
{
namespace helpers
{
namespace tensor_transform
{
int calculate_stride_on_index(int index, Coordinates strides)
{
    return index >= static_cast<int>(strides.num_dimensions()) ? 1 : strides[index];
}

int calculate_start_on_index(TensorShape input_shape, int index, Coordinates starts, Coordinates strides, int32_t begin_mask)
{
    // Early exit
    if(index >= static_cast<int>(starts.num_dimensions()))
    {
        return 0;
    }

    // Get stride
    const int stride = calculate_stride_on_index(index, strides);

    // Calculate start
    int start = starts[index];

    // Reset in case of begin mask present
    if(arm_compute::helpers::bit_ops::is_bit_set(begin_mask, index))
    {
        start = stride > 0 ? std::numeric_limits<int>::lowest() : std::numeric_limits<int>::max();
    }

    // Account negative start points
    const int dim_size = input_shape[index];
    if(start < 0)
    {
        start += dim_size;
    }

    // Final clamp
    start = utility::clamp(start, 0, dim_size - 1);

    return start;
}

int calculate_end_on_index(TensorShape input_shape, int index, int start_on_index,
                           Coordinates ends, Coordinates strides,
                           int32_t end_mask, int32_t shrink_axis_mask)
{
    // Early exit
    if(index >= static_cast<int>(ends.num_dimensions()))
    {
        return input_shape[index];
    }

    const int  stride      = calculate_stride_on_index(index, strides);
    const bool shrink_axis = arm_compute::helpers::bit_ops::is_bit_set(shrink_axis_mask, index);

    // Calculate start
    int stop = ends[index];

    // Shrink dimension
    if(shrink_axis)
    {
        if(start_on_index == std::numeric_limits<int>::max())
        {
            stop = start_on_index;
        }
        else
        {
            stop = start_on_index + 1;
        }
    }

    // Reset in case of begin mask present
    if(arm_compute::helpers::bit_ops::is_bit_set(end_mask, index) && !shrink_axis)
    {
        stop = (stride > 0) ? std::numeric_limits<int>::max() : std::numeric_limits<int>::lowest();
    }

    // Account negative end points
    const int dim_size = input_shape[index];
    if(stop < 0)
    {
        stop += dim_size;
    }

    // Final clamp
    stop = (stride > 0) ? utility::clamp(stop, 0, dim_size) : utility::clamp(stop, -1, dim_size - 1);

    return stop;
}

std::tuple<Coordinates, Coordinates, Coordinates> calculate_strided_slice_coords(TensorShape input_shape,
                                                                                 Coordinates starts, Coordinates ends, Coordinates strides,
                                                                                 int32_t begin_mask, int32_t end_mask, int32_t shrink_axis_mask)
{
    Coordinates starts_abs{};
    Coordinates ends_abs{};
    Coordinates final_strides{};

    for(unsigned int i = 0; i < input_shape.num_dimensions(); ++i)
    {
        const int start_i = calculate_start_on_index(input_shape, i, starts, strides, begin_mask);
        starts_abs.set(i, start_i);
        ends_abs.set(i, calculate_end_on_index(input_shape, i, start_i, ends, strides, end_mask, shrink_axis_mask));
        final_strides.set(i, calculate_stride_on_index(i, strides));
    }

    return std::make_tuple(starts_abs, ends_abs, final_strides);
}

TensorShape compute_strided_slice_output_shape(TensorShape input_shape, Coordinates starts, Coordinates ends, Coordinates strides,
                                               int32_t begin_mask, int32_t end_mask, int32_t shrink_axis_mask, bool return_unshrinked)
{
    unsigned int index = 0;

    TensorShape output_shape;
    for(unsigned int i = 0; i < input_shape.num_dimensions(); ++i)
    {
        const int stride = calculate_stride_on_index(index, strides);
        const int start  = calculate_start_on_index(input_shape, i, starts, strides, begin_mask);
        const int end    = calculate_end_on_index(input_shape, i, start, ends, strides, end_mask, shrink_axis_mask);
        const int range  = end - start;

        const bool is_shrink = arm_compute::helpers::bit_ops::is_bit_set(shrink_axis_mask, i);
        if(return_unshrinked || !is_shrink)
        {
            if((range == 0) ||               // Zero range
               (range < 0 && stride >= 0) || // Negative range with positive stride
               (range > 0 && stride <= 0))   // Positive range with negative stride
            {
                output_shape.set(index, 0);
                return output_shape;
            }
            else
            {
                int dim = range / stride + (range % stride != 0 ? 1 : 0);
                output_shape.set(index++, dim);
            }
        }
    }
    return output_shape;
}

int32_t construct_slice_end_mask(Coordinates ends)
{
    // Create end mask
    int32_t end_mask = 0;
    for(unsigned int i = 0; i < ends.num_dimensions(); ++i)
    {
        if(ends[i] < 0)
        {
            end_mask |= 1 << i;
        }
    }

    return end_mask;
}
} // namespace tensor_transform
} // namespace helpers
} // namespace arm_compute
