//
// Copyright © 2021 Arm Ltd and Contributors. All rights reserved.
// SPDX-License-Identifier: MIT
//

#include "Reduce.hpp"

#include <armnn/utility/NumericCast.hpp>

#include <backendsCommon/WorkloadData.hpp>

#include <cmath>
#include <cstddef>
#include <functional>
#include <limits>

namespace armnn
{

bool NextIndex(const unsigned int numDims, const armnn::TensorShape& dims, std::vector<unsigned int>& current)
{
    unsigned int carry = 1;

    for (unsigned int idx = numDims; idx-- > 0; )
    {
        unsigned int current_val = current[idx] + carry;
        if (dims[idx] == current_val)
        {
            current[idx] = 0;
        }
        else
        {
            current[idx] = current_val;
            carry = 0;
            break;
        }
    }
    return (carry == 0);
}

unsigned int ReducedOutputOffset(const unsigned int numDims,
                                 const armnn::TensorShape& dims,
                                 std::vector<unsigned int>& index,
                                 const unsigned int numAxis,
                                 const std::vector<unsigned int>& axis)
{
    unsigned int offset = 0;
    for (unsigned int idx = 0; idx < numDims; ++idx)
    {
        bool isAxis = false;
        if (!axis.empty())
        {
            for (unsigned int axisIdx = 0; axisIdx < numAxis; ++axisIdx)
            {
                if (idx == axis[axisIdx])
                {
                    isAxis = true;
                    break;
                }
            }
        }
        if (!isAxis)
        {
            offset = offset * dims[idx] + index[idx];
        }
    }
    return offset;
}


void Reduce(const TensorInfo& inputInfo,
            const TensorInfo& outputInfo,
            Decoder<float>& input,
            Encoder<float>& output,
            const std::vector<uint32_t> axis,
            const ReduceOperation reduceOperation)
{
    armnn::TensorShape inputDims = inputInfo.GetShape();
    unsigned int inputNumDims    = inputInfo.GetNumDimensions();
    unsigned int numOutputs      = outputInfo.GetNumElements();

    // Initialise temp output
    std::vector<float> tempOut(numOutputs);
    if (reduceOperation == ReduceOperation::Max || reduceOperation == ReduceOperation::Min)
    {
        for (unsigned int idx = 0; idx < numOutputs; ++idx)
        {
            input[idx];
            tempOut[idx] = input.Get();
        }
    }
    else
    {
        std::fill(tempOut.begin(), tempOut.end(), 0.0);
    }

    // Initialise temp index
    std::vector<unsigned int> tempIndex(inputNumDims, 0);

    std::vector<unsigned int> resolvedAxis = axis;
    if (resolvedAxis.empty())
    {
        for (unsigned int idx = 0; idx < inputNumDims; ++idx)
        {
            resolvedAxis.push_back(idx);
        }
    }
    auto numResolvedAxis = armnn::numeric_cast<unsigned int>(resolvedAxis.size());

    // Iterates through input_data and operates over the reduced axis
    for (bool hasNext = true; hasNext; hasNext = NextIndex(inputNumDims, inputDims, tempIndex))
    {
        unsigned int inputOffset = ReducedOutputOffset(inputNumDims, inputDims, tempIndex, 0, {});
        unsigned int outputOffset = ReducedOutputOffset(inputNumDims, inputDims, tempIndex,
                                                        numResolvedAxis, resolvedAxis);
        input[inputOffset];
        auto inputValue = input.Get();
        if (reduceOperation == ReduceOperation::Max)
        {
            if (inputValue > tempOut[outputOffset])
            {
                tempOut[outputOffset] = inputValue;
            }
        }
        else if (reduceOperation == ReduceOperation::Min)
        {
            if (inputValue < tempOut[outputOffset])
            {
                tempOut[outputOffset] = inputValue;
            }
        }
        else
        {
            tempOut[outputOffset] += inputValue;
        }
    }

    // Takes average by num of elements added to get MEAN
    size_t numElementsInAxis = 1;
    for (unsigned int idx = 0; idx < numResolvedAxis; ++idx)
    {
        unsigned int current = inputDims[resolvedAxis[idx]];
        ARMNN_ASSERT(armnn::numeric_cast<float>(current) <
                     (std::numeric_limits<float>::max() / armnn::numeric_cast<float>(numElementsInAxis)));
        numElementsInAxis *= current;
    }

    for (unsigned int idx = 0; idx < numOutputs; ++idx)
    {
        output[idx];
        if (reduceOperation == ReduceOperation::Mean)
        {
            if (numElementsInAxis > 0)
            {
                output.Set(tempOut[idx] / armnn::numeric_cast<float>(numElementsInAxis));
            }
        }
        else
        {
            output.Set(tempOut[idx]);
        }
    }
}

} //namespace armnn