<commit_before>//
// Copyright © 2022 Arm Ltd and Contributors. All rights reserved.
// SPDX-License-Identifier: MIT
//

#include "BatchMatMulImpl.hpp"

#include <armnn/backends/WorkloadData.hpp>
#include <armnn/Logging.hpp>

namespace armnn
{

void BatchMatMul::BatchMatMulImpl()
{
    inputXData = inputXDecoder.DecodeTensor(inputXInfo.GetShape());
    inputYData = inputYDecoder.DecodeTensor(inputYInfo.GetShape());
    // At this point, we don't touch the input decoders - just the resultant vectors

    // Pre-transpose and pre-adjoint if their vectors aren't empty
    // and also DataLayouts which may change with permutations/adjoints

    // Todo: Have you updated input validation and inferred output shapes to accommodate for these pre-permutes?

    auto idx = std::vector<unsigned int>(outputInfo.GetNumDimensions(), 0);
    RecurseBMM(idx, 0);
}

void BatchMatMul::RecurseBMM(std::vector<unsigned int>& curIdx, unsigned int curDim)
{
    // We're working off of the indexes of the output tensor (the max possible shape)

    if(!(curDim < outputInfo.GetNumDimensions()))
    {
        // We're at the leaf level of this call tree, so we operate here (each leaf is a data point)

        auto axesToMul = BatchMatMulDescriptor::GetAxesToMul(params,
                                                             inputXInfo.GetShape(),
                                                             inputYInfo.GetShape());
        AdjustAxesToMulForUnequalRanks(axesToMul);

        unsigned int inputXColDim = axesToMul.first.second;
        unsigned int inputYRowDim = axesToMul.second.first;

        unsigned int inputYRowSize = inputYInfo.GetShape()[inputYRowDim];

        float sum = 0.0f;

        // You could also use inputXColSize
        for (unsigned int inputYRowIdx = 0; inputYRowIdx < inputYRowSize; inputYRowIdx++) {
            auto xIdx = curIdx;
            xIdx[inputXColDim] = inputYRowIdx;

            auto yIdx = curIdx;
            yIdx[inputYRowDim] = inputYRowIdx;

            sum += (GetValueAt(DataSlot::InputX, xIdx)
                  * GetValueAt(DataSlot::InputY, yIdx));
        }

        SetValueAt(sum, DataSlot::Output, curIdx);

        return;
    }

    for (unsigned int i = 0; i < outputInfo.GetShape()[curDim]; i++)
    {
        curIdx[curDim] = i;
        RecurseBMM(curIdx, curDim+1);
    }
}

void BatchMatMul::AdjustAxesToMulForUnequalRanks(
    std::pair<std::pair<unsigned int, unsigned int>, std::pair<unsigned int, unsigned int>>& axesToMul)
{
    long rankDiff = static_cast<long>(inputXInfo.GetNumDimensions()) - inputYInfo.GetNumDimensions();
    if(rankDiff == 0)
    {
        return;
    }
    else if(rankDiff < 0)
    {
        // Y is the larger one
        axesToMul.first.first += static_cast<std::make_unsigned<unsigned int>::type>(std::abs(rankDiff));
        axesToMul.first.second += static_cast<std::make_unsigned<unsigned int>::type>(std::abs(rankDiff));
    }<commit_msg>IVGCVSW-7145: BatchMatMul Fix for Raspi Cross Compile Failing<commit_after>//
// Copyright © 2022 Arm Ltd and Contributors. All rights reserved.
// SPDX-License-Identifier: MIT
//

#include "BatchMatMulImpl.hpp"

#include <armnn/backends/WorkloadData.hpp>
#include <armnn/Logging.hpp>

namespace armnn
{

void BatchMatMul::BatchMatMulImpl()
{
    inputXData = inputXDecoder.DecodeTensor(inputXInfo.GetShape());
    inputYData = inputYDecoder.DecodeTensor(inputYInfo.GetShape());
    // At this point, we don't touch the input decoders - just the resultant vectors

    // Pre-transpose and pre-adjoint if their vectors aren't empty
    // and also DataLayouts which may change with permutations/adjoints

    // Todo: Have you updated input validation and inferred output shapes to accommodate for these pre-permutes?

    auto idx = std::vector<unsigned int>(outputInfo.GetNumDimensions(), 0);
    RecurseBMM(idx, 0);
}

void BatchMatMul::RecurseBMM(std::vector<unsigned int>& curIdx, unsigned int curDim)
{
    // We're working off of the indexes of the output tensor (the max possible shape)

    if(!(curDim < outputInfo.GetNumDimensions()))
    {
        // We're at the leaf level of this call tree, so we operate here (each leaf is a data point)

        auto axesToMul = BatchMatMulDescriptor::GetAxesToMul(params,
                                                             inputXInfo.GetShape(),
                                                             inputYInfo.GetShape());
        AdjustAxesToMulForUnequalRanks(axesToMul);

        unsigned int inputXColDim = axesToMul.first.second;
        unsigned int inputYRowDim = axesToMul.second.first;

        unsigned int inputYRowSize = inputYInfo.GetShape()[inputYRowDim];

        float sum = 0.0f;

        // You could also use inputXColSize
        for (unsigned int inputYRowIdx = 0; inputYRowIdx < inputYRowSize; inputYRowIdx++) {
            auto xIdx = curIdx;
            xIdx[inputXColDim] = inputYRowIdx;

            auto yIdx = curIdx;
            yIdx[inputYRowDim] = inputYRowIdx;

            sum += (GetValueAt(DataSlot::InputX, xIdx)
                  * GetValueAt(DataSlot::InputY, yIdx));
        }

        SetValueAt(sum, DataSlot::Output, curIdx);

        return;
    }

    for (unsigned int i = 0; i < outputInfo.GetShape()[curDim]; i++)
    {
        curIdx[curDim] = i;
        RecurseBMM(curIdx, curDim+1);
    }
}

void BatchMatMul::AdjustAxesToMulForUnequalRanks(
    std::pair<std::pair<unsigned int, unsigned int>, std::pair<unsigned int, unsigned int>>& axesToMul)
{
    int rankDiff = static_cast<int>(inputXInfo.GetNumDimensions()) -
                   static_cast<int>(inputYInfo.GetNumDimensions());
    if(rankDiff == 0)
    {
        return;
    }
    else if(rankDiff < 0)
    {
        // Y is the larger one
        axesToMul.first.first += static_cast<std::make_unsigned<unsigned int>::type>(std::abs(rankDiff));
        axesToMul.first.second += static_cast<std::make_unsigned<unsigned int>::type>(std::abs(rankDiff));
    }
{'fraction_non_alphanumeric': 0.10656422248204443, 'fraction_numerical': 0.005010856856522465, 'mean_word_length': 2.737827715355805, 'pattern_counts': {'":': 0, '<': 36, '<?xml version=': 0, '>': 28, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 8, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '6955623', 'n_tokens_mistral': 1894, 'n_tokens_neox': 1792, 'n_words': 441}