// // Copyright © 2017 Arm Ltd. All rights reserved. // SPDX-License-Identifier: MIT // #include "TensorUtils.hpp" #include #include #include #include namespace armnnUtils { armnn::TensorShape GetTensorShape(unsigned int numberOfBatches, unsigned int numberOfChannels, unsigned int height, unsigned int width, const armnn::DataLayout dataLayout) { switch (dataLayout) { case armnn::DataLayout::NCHW: return armnn::TensorShape({numberOfBatches, numberOfChannels, height, width}); case armnn::DataLayout::NHWC: return armnn::TensorShape({numberOfBatches, height, width, numberOfChannels}); default: throw armnn::InvalidArgumentException("Unknown data layout [" + std::to_string(static_cast(dataLayout)) + "]", CHECK_LOCATION()); } } armnn::TensorInfo GetTensorInfo(unsigned int numberOfBatches, unsigned int numberOfChannels, unsigned int height, unsigned int width, const armnn::DataLayout dataLayout, const armnn::DataType dataType) { switch (dataLayout) { case armnn::DataLayout::NCHW: return armnn::TensorInfo({numberOfBatches, numberOfChannels, height, width}, dataType); case armnn::DataLayout::NHWC: return armnn::TensorInfo({numberOfBatches, height, width, numberOfChannels}, dataType); default: throw armnn::InvalidArgumentException("Unknown data layout [" + std::to_string(static_cast(dataLayout)) + "]", CHECK_LOCATION()); } } std::pair FindMinMax(armnn::ITensorHandle* tensorHandle) { auto tensor_data = static_cast(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); } armnn::TensorShape ExpandDims(const armnn::TensorShape& tensorShape, int axis) { unsigned int outputDim = tensorShape.GetNumDimensions() + 1; if (axis < -boost::numeric_cast(outputDim) || axis > boost::numeric_cast(tensorShape.GetNumDimensions())) { throw armnn::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(outputDim) + axis; } std::vector outputShape; for (unsigned int i = 0; i < tensorShape.GetNumDimensions(); ++i) { outputShape.push_back(tensorShape[i]); } outputShape.insert(outputShape.begin() + axis, 1); return armnn::TensorShape(outputDim, outputShape.data()); } unsigned int GetNumElementsBetween(const armnn::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(inputDimension), "Required axis index greater than number of dimensions."); BOOST_ASSERT_MSG(axis >= -boost::numeric_cast(inputDimension), "Required axis index lower than negative of the number of dimensions"); unsigned int uAxis = axis < 0 ? inputDimension - boost::numeric_cast(abs(axis)) : boost::numeric_cast(axis); return uAxis; } }