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

#include "TensorUtils.hpp"

#include <backendsCommon/ITensorHandle.hpp>

#include <boost/assert.hpp>
#include <boost/format.hpp>
#include <boost/numeric/conversion/cast.hpp>

using namespace armnn;

namespace armnnUtils
{

TensorShape GetTensorShape(unsigned int numberOfBatches,
                                  unsigned int numberOfChannels,
                                  unsigned int height,
                                  unsigned int width,
                                  const DataLayout dataLayout)
{
    switch (dataLayout)
    {
        case DataLayout::NCHW:
            return TensorShape({numberOfBatches, numberOfChannels, height, width});
        case DataLayout::NHWC:
            return TensorShape({numberOfBatches, height, width, numberOfChannels});
        default:
            throw InvalidArgumentException("Unknown data layout ["
                                                  + std::to_string(static_cast<int>(dataLayout)) +
                                                  "]", CHECK_LOCATION());
    }
}

TensorInfo GetTensorInfo(unsigned int numberOfBatches,
                                unsigned int numberOfChannels,
                                unsigned int height,
                                unsigned int width,
                                const DataLayout dataLayout,
                                const DataType dataType)
{
    switch (dataLayout)
    {
        case DataLayout::NCHW:
            return TensorInfo({numberOfBatches, numberOfChannels, height, width}, dataType);
        case DataLayout::NHWC:
            return TensorInfo({numberOfBatches, height, width, numberOfChannels}, dataType);
        default:
            throw InvalidArgumentException("Unknown data layout ["
                                                  + std::to_string(static_cast<int>(dataLayout)) +
                                                  "]", CHECK_LOCATION());
    }
}

std::pair<float, float> FindMinMax(ITensorHandle* tensorHandle)
{
    auto tensor_data = static_cast<const float *>(tensorHandle->Map(true));
    auto tensor_size = tensorHandle->GetShape().GetNumElements();

    // Set min/max initially to first value in tensor
    float min = tensor_data[0];
    float max = tensor_data[0];

    // Loop over rest of tensor and update min/max if necessary
    for (unsigned int val = 1; val < tensor_size; val++)
    {
        if (tensor_data[val] < min)
        {
            min = tensor_data[val];
        }
        else if (tensor_data[val] > max)
        {
            max = tensor_data[val];
        }
    }

    tensorHandle->Unmap();

    return std::make_pair(min, max);
}

TensorShape ExpandDims(const TensorShape& tensorShape, int axis)
{
    unsigned int outputDim = tensorShape.GetNumDimensions() + 1;

    if (axis < -boost::numeric_cast<int>(outputDim) || axis > boost::numeric_cast<int>(tensorShape.GetNumDimensions()))
    {
        throw InvalidArgumentException(
            boost::str(boost::format("Invalid expansion axis %1% for %2%D input tensor. %3%") %
                       axis %
                       tensorShape.GetNumDimensions() %
                       CHECK_LOCATION().AsString()));
    }

    if (axis < 0)
    {
        axis = boost::numeric_cast<int>(outputDim) + axis;
    }

    std::vector<unsigned int> outputShape;
    for (unsigned int i = 0; i < tensorShape.GetNumDimensions(); ++i)
    {
        outputShape.push_back(tensorShape[i]);
    }
    outputShape.insert(outputShape.begin() + axis, 1);

    return TensorShape(outputDim, outputShape.data());
}

unsigned int GetNumElementsBetween(const TensorShape& shape,
                                   const unsigned int firstAxisInclusive,
                                   const unsigned int lastAxisExclusive)
{
    BOOST_ASSERT(0 <= firstAxisInclusive);
    BOOST_ASSERT(firstAxisInclusive <= lastAxisExclusive);
    BOOST_ASSERT(lastAxisExclusive <= shape.GetNumDimensions());
    unsigned int count = 1;
    for (unsigned int i = firstAxisInclusive; i < lastAxisExclusive; i++)
    {
        count *= shape[i];
    }
    return count;
}

unsigned int GetUnsignedAxis(const unsigned int inputDimension, const int axis)
{
    BOOST_ASSERT_MSG(axis < boost::numeric_cast<int>(inputDimension),
                     "Required axis index greater than number of dimensions.");
    BOOST_ASSERT_MSG(axis >= -boost::numeric_cast<int>(inputDimension),
                     "Required axis index lower than negative of the number of dimensions");

    unsigned int uAxis = axis < 0  ?
                         inputDimension - boost::numeric_cast<unsigned int>(abs(axis))
                         : boost::numeric_cast<unsigned int>(axis);
    return uAxis;
}

unsigned int GetNumElementsAfter(const armnn::TensorShape& shape, unsigned int axis)
{
    unsigned int numDim = shape.GetNumDimensions();
    BOOST_ASSERT(0 >= axis);
    BOOST_ASSERT(axis <= numDim - 1);
    unsigned int count = 1;
    for (unsigned int i = axis; i < numDim; i++)
    {
        count *= shape[i];
    }
    return count;
}

std::pair<unsigned int, std::vector<float>> GetPerAxisParams(const armnn::TensorInfo& info)
{
    const std::vector<float>& scales = info.GetQuantizationScales();
    armnn::Optional<unsigned int> quantizationDim = info.GetQuantizationDim();
    if (!info.HasPerAxisQuantization())
    {
        throw armnn::InvalidArgumentException(
            std::string("Per-axis quantization params not set for tensor of type ") +
            armnn::GetDataTypeName(info.GetDataType()), CHECK_LOCATION());
    }
    unsigned int axisFactor = GetNumElementsAfter(info.GetShape(), quantizationDim.value());

    return { axisFactor, scales };
}

} // namespace armnnUtils
