blob: db02a84a4561cb4433cfc021db45b905bf50f42b [file] [log] [blame]
//
// Copyright © 2017 Arm Ltd. All rights reserved.
// SPDX-License-Identifier: MIT
//
#pragma once
#include "BaseIterator.hpp"
#include <backendsCommon/CpuTensorHandle.hpp>
namespace
{
// Helper functions ported from the Android code base
// Refer to: android/external/tensorflow/tensorflow/contrib/lite/kernels/internal/reference/portable_tensor_utils.cc
void MatrixBatchVectorMultiplyAccumulate(armnn::Decoder<float>& matrix,
uint32_t mRows,
uint32_t mCols,
armnn::Decoder<float>& vector,
uint32_t nBatch,
armnn::Encoder<float>& outResult)
{
for (uint32_t b = 0; b < nBatch; b++)
{
for (uint32_t r = 0; r < mRows; r++)
{
vector += b * mCols;
for (uint32_t c = 0; c < mCols; c++)
{
outResult.Set(outResult.Get() + matrix.Get() * vector.Get());
++matrix;
++vector;
}
outResult += 1;
vector -= (b+1) * mCols;
}
matrix -= (mRows * mCols);
}
outResult -= (mRows * nBatch);
}
void VectorBatchVectorAssign(armnn::Decoder<float>& vector,
uint32_t vSize,
uint32_t nBatch,
armnn::Encoder<float>& outBatchVector)
{
for (uint32_t b = 0; b < nBatch; b++)
{
for (uint32_t v = 0; v < vSize; v++)
{
outBatchVector.Set(vector.Get());
++outBatchVector;
++vector;
}
vector -= vSize;
}
outBatchVector -= (nBatch * vSize);
}
void VectorBatchVectorCwiseProductAccumulate(armnn::Decoder<float>& vector,
uint32_t vSize,
armnn::Decoder<float>& batchVector,
uint32_t nBatch,
armnn::Encoder<float>& outResult)
{
for (uint32_t b = 0; b < nBatch; b++)
{
for (uint32_t v = 0; v < vSize; v++)
{
outResult.Set(outResult.Get() + vector.Get() * batchVector.Get());
++outResult;
++vector;
++batchVector;
}
vector -= vSize;
}
batchVector -= vSize * nBatch;
outResult -= vSize * nBatch;
}
void Sub1Vector(armnn::Decoder<float>& vector,
uint32_t vSize,
armnn::Encoder<float>& result)
{
for (uint32_t v = 0; v < vSize; v++)
{
result.Set(1.0f - vector.Get());
++vector;
++result;
}
vector -= vSize;
result -= vSize;
}
void VectorVectorCwiseProduct(armnn::Decoder<float>& vector1,
armnn::Decoder<float>& vector2,
uint32_t vSize,
armnn::Encoder<float>& outResult)
{
for (uint32_t v = 0; v < vSize; v++)
{
outResult.Set(vector1.Get() * vector2.Get());
++outResult;
++vector1;
++vector2;
}
outResult -= vSize;
vector1 -= vSize;
vector2 -= vSize;
}
void VectorVectorCwiseProductAccumulate(armnn::Decoder<float>& vector1,
armnn::Decoder<float>& vector2,
uint32_t vSize,
armnn::Encoder<float>& outResult)
{
for (uint32_t v = 0; v < vSize; v++)
{
outResult.Set(outResult.Get() + vector1.Get() * vector2.Get());
++outResult;
++vector1;
++vector2;
}
outResult -= vSize;
vector1 -= vSize;
vector2 -= vSize;
}
float Clip(float f,
float absLimit)
{
float result = (absLimit < f) ? absLimit : f;
result = (-absLimit > result) ? -absLimit : result;
return result;
}
void ClipVector(armnn::Decoder<float>& vector,
uint32_t vSize,
float absLimit,
armnn::Encoder<float>& outResult)
{
for (uint32_t v = 0; v < vSize; v++)
{
outResult.Set(Clip(vector.Get(), absLimit));
++vector;
++outResult;
}
vector -= vSize;
outResult -= vSize;
}
void CopyVector(armnn::Decoder<float>& vector,
uint32_t vSize,
armnn::Encoder<float>& outResult)
{
for (uint32_t v = 0; v < vSize; v++)
{
outResult.Set(vector.Get());
++outResult;
++vector;
}
outResult -= vSize;
vector -= vSize;
}
void SetActivationParameters(uint32_t activation,
armnn::ActivationFunction& outArmnnActivation,
float& outA,
float& outB)
{
switch (activation)
{
case 0: // None
outA = 0;
outB = 0;
return;
case 1: // Relu
outArmnnActivation = armnn::ActivationFunction::ReLu;
outA = 0;
outB = 0;
return;
case 3: // Relu6
outArmnnActivation = armnn::ActivationFunction::BoundedReLu;
outA = 6;
outB = 0;
return;
case 4: // Tanh
outArmnnActivation = armnn::ActivationFunction::TanH;
outA = 1;
outB = 1;
return;
case 6: // Sigmoid
outArmnnActivation = armnn::ActivationFunction::Sigmoid;
outA = 0;
outB = 0;
return;
default:
throw armnn::Exception("Unsupported activation function: " + std::to_string(activation));
}
}
std::unique_ptr<armnn::ScopedCpuTensorHandle> AssignScopedCpuTensorHandle(const armnn::ConstCpuTensorHandle* ptr)
{
if (!ptr)
{
return nullptr;
}
return std::make_unique<armnn::ScopedCpuTensorHandle>(*ptr);
}
} // anonymous namespace