aboutsummaryrefslogtreecommitdiff
path: root/arm_compute/core/Utils.h
diff options
context:
space:
mode:
Diffstat (limited to 'arm_compute/core/Utils.h')
-rw-r--r--arm_compute/core/Utils.h1239
1 files changed, 116 insertions, 1123 deletions
diff --git a/arm_compute/core/Utils.h b/arm_compute/core/Utils.h
index eff6157b1f..a2146522f7 100644
--- a/arm_compute/core/Utils.h
+++ b/arm_compute/core/Utils.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2016-2020 ARM Limited.
+ * Copyright (c) 2016-2023 Arm Limited.
*
* SPDX-License-Identifier: MIT
*
@@ -26,63 +26,29 @@
#include "arm_compute/core/Error.h"
#include "arm_compute/core/PixelValue.h"
-#include "arm_compute/core/Rounding.h"
#include "arm_compute/core/Types.h"
-#include "arm_compute/core/Version.h"
-#include <algorithm>
-#include <cstdint>
-#include <cstdlib>
-#include <iomanip>
+#include <cmath>
#include <numeric>
#include <sstream>
#include <string>
#include <type_traits>
+#include <unordered_map>
#include <utility>
-#include <vector>
-namespace arm_compute
-{
-/** Calculate the rounded up quotient of val / m.
- *
- * @param[in] val Value to divide and round up.
- * @param[in] m Value to divide by.
- *
- * @return the result.
- */
-template <typename S, typename T>
-constexpr auto DIV_CEIL(S val, T m) -> decltype((val + m - 1) / m)
-{
- return (val + m - 1) / m;
-}
-
-/** Computes the smallest number larger or equal to value that is a multiple of divisor.
- *
- * @param[in] value Lower bound value
- * @param[in] divisor Value to compute multiple of.
- *
- * @return the result.
- */
-template <typename S, typename T>
-inline auto ceil_to_multiple(S value, T divisor) -> decltype(((value + divisor - 1) / divisor) * divisor)
-{
- ARM_COMPUTE_ERROR_ON(value < 0 || divisor <= 0);
- return DIV_CEIL(value, divisor) * divisor;
-}
+/* Convenience / backwards compatibility includes */
+#include "arm_compute/core/utils/ActivationFunctionUtils.h"
+#include "arm_compute/core/utils/DataLayoutUtils.h"
+#include "arm_compute/core/utils/DataTypeUtils.h"
+#include "arm_compute/core/utils/FormatUtils.h"
+#include "arm_compute/core/utils/InterpolationPolicyUtils.h"
+#include "arm_compute/core/utils/StringUtils.h"
-/** Computes the largest number smaller or equal to value that is a multiple of divisor.
- *
- * @param[in] value Upper bound value
- * @param[in] divisor Value to compute multiple of.
- *
- * @return the result.
- */
-template <typename S, typename T>
-inline auto floor_to_multiple(S value, T divisor) -> decltype((value / divisor) * divisor)
+namespace arm_compute
{
- ARM_COMPUTE_ERROR_ON(value < 0 || divisor <= 0);
- return (value / divisor) * divisor;
-}
+class ITensor;
+class ITensorInfo;
+class ActivationLayerInfo;
/** Load an entire file in memory
*
@@ -93,814 +59,6 @@ inline auto floor_to_multiple(S value, T divisor) -> decltype((value / divisor)
*/
std::string read_file(const std::string &filename, bool binary);
-/** The size in bytes of the data type
- *
- * @param[in] data_type Input data type
- *
- * @return The size in bytes of the data type
- */
-inline size_t data_size_from_type(DataType data_type)
-{
- switch(data_type)
- {
- case DataType::U8:
- case DataType::S8:
- case DataType::QSYMM8:
- case DataType::QASYMM8:
- case DataType::QASYMM8_SIGNED:
- case DataType::QSYMM8_PER_CHANNEL:
- return 1;
- case DataType::U16:
- case DataType::S16:
- case DataType::QSYMM16:
- case DataType::QASYMM16:
- case DataType::BFLOAT16:
- case DataType::F16:
- return 2;
- case DataType::F32:
- case DataType::U32:
- case DataType::S32:
- return 4;
- case DataType::F64:
- case DataType::U64:
- case DataType::S64:
- return 8;
- case DataType::SIZET:
- return sizeof(size_t);
- default:
- ARM_COMPUTE_ERROR("Invalid data type");
- return 0;
- }
-}
-
-/** The size in bytes of the pixel format
- *
- * @param[in] format Input format
- *
- * @return The size in bytes of the pixel format
- */
-inline size_t pixel_size_from_format(Format format)
-{
- switch(format)
- {
- case Format::U8:
- return 1;
- case Format::U16:
- case Format::S16:
- case Format::BFLOAT16:
- case Format::F16:
- case Format::UV88:
- case Format::YUYV422:
- case Format::UYVY422:
- return 2;
- case Format::RGB888:
- return 3;
- case Format::RGBA8888:
- return 4;
- case Format::U32:
- case Format::S32:
- case Format::F32:
- return 4;
- //Doesn't make sense for planar formats:
- case Format::NV12:
- case Format::NV21:
- case Format::IYUV:
- case Format::YUV444:
- default:
- ARM_COMPUTE_ERROR("Undefined pixel size for given format");
- return 0;
- }
-}
-
-/** The size in bytes of the data type
- *
- * @param[in] dt Input data type
- *
- * @return The size in bytes of the data type
- */
-inline size_t element_size_from_data_type(DataType dt)
-{
- switch(dt)
- {
- case DataType::S8:
- case DataType::U8:
- case DataType::QSYMM8:
- case DataType::QASYMM8:
- case DataType::QASYMM8_SIGNED:
- case DataType::QSYMM8_PER_CHANNEL:
- return 1;
- case DataType::U16:
- case DataType::S16:
- case DataType::QSYMM16:
- case DataType::QASYMM16:
- case DataType::BFLOAT16:
- case DataType::F16:
- return 2;
- case DataType::U32:
- case DataType::S32:
- case DataType::F32:
- return 4;
- default:
- ARM_COMPUTE_ERROR("Undefined element size for given data type");
- return 0;
- }
-}
-
-/** Return the data type used by a given single-planar pixel format
- *
- * @param[in] format Input format
- *
- * @return The size in bytes of the pixel format
- */
-inline DataType data_type_from_format(Format format)
-{
- switch(format)
- {
- case Format::U8:
- case Format::UV88:
- case Format::RGB888:
- case Format::RGBA8888:
- case Format::YUYV422:
- case Format::UYVY422:
- return DataType::U8;
- case Format::U16:
- return DataType::U16;
- case Format::S16:
- return DataType::S16;
- case Format::U32:
- return DataType::U32;
- case Format::S32:
- return DataType::S32;
- case Format::BFLOAT16:
- return DataType::BFLOAT16;
- case Format::F16:
- return DataType::F16;
- case Format::F32:
- return DataType::F32;
- //Doesn't make sense for planar formats:
- case Format::NV12:
- case Format::NV21:
- case Format::IYUV:
- case Format::YUV444:
- default:
- ARM_COMPUTE_ERROR("Not supported data_type for given format");
- return DataType::UNKNOWN;
- }
-}
-
-/** Return the plane index of a given channel given an input format.
- *
- * @param[in] format Input format
- * @param[in] channel Input channel
- *
- * @return The plane index of the specific channel of the specific format
- */
-inline int plane_idx_from_channel(Format format, Channel channel)
-{
- switch(format)
- {
- // Single planar formats have a single plane
- case Format::U8:
- case Format::U16:
- case Format::S16:
- case Format::U32:
- case Format::S32:
- case Format::BFLOAT16:
- case Format::F16:
- case Format::F32:
- case Format::UV88:
- case Format::RGB888:
- case Format::RGBA8888:
- case Format::YUYV422:
- case Format::UYVY422:
- return 0;
- // Multi planar formats
- case Format::NV12:
- case Format::NV21:
- {
- // Channel U and V share the same plane of format UV88
- switch(channel)
- {
- case Channel::Y:
- return 0;
- case Channel::U:
- case Channel::V:
- return 1;
- default:
- ARM_COMPUTE_ERROR("Not supported channel");
- return 0;
- }
- }
- case Format::IYUV:
- case Format::YUV444:
- {
- switch(channel)
- {
- case Channel::Y:
- return 0;
- case Channel::U:
- return 1;
- case Channel::V:
- return 2;
- default:
- ARM_COMPUTE_ERROR("Not supported channel");
- return 0;
- }
- }
- default:
- ARM_COMPUTE_ERROR("Not supported format");
- return 0;
- }
-}
-
-/** Return the channel index of a given channel given an input format.
- *
- * @param[in] format Input format
- * @param[in] channel Input channel
- *
- * @return The channel index of the specific channel of the specific format
- */
-inline int channel_idx_from_format(Format format, Channel channel)
-{
- switch(format)
- {
- case Format::RGB888:
- {
- switch(channel)
- {
- case Channel::R:
- return 0;
- case Channel::G:
- return 1;
- case Channel::B:
- return 2;
- default:
- ARM_COMPUTE_ERROR("Not supported channel");
- return 0;
- }
- }
- case Format::RGBA8888:
- {
- switch(channel)
- {
- case Channel::R:
- return 0;
- case Channel::G:
- return 1;
- case Channel::B:
- return 2;
- case Channel::A:
- return 3;
- default:
- ARM_COMPUTE_ERROR("Not supported channel");
- return 0;
- }
- }
- case Format::YUYV422:
- {
- switch(channel)
- {
- case Channel::Y:
- return 0;
- case Channel::U:
- return 1;
- case Channel::V:
- return 3;
- default:
- ARM_COMPUTE_ERROR("Not supported channel");
- return 0;
- }
- }
- case Format::UYVY422:
- {
- switch(channel)
- {
- case Channel::Y:
- return 1;
- case Channel::U:
- return 0;
- case Channel::V:
- return 2;
- default:
- ARM_COMPUTE_ERROR("Not supported channel");
- return 0;
- }
- }
- case Format::NV12:
- {
- switch(channel)
- {
- case Channel::Y:
- return 0;
- case Channel::U:
- return 0;
- case Channel::V:
- return 1;
- default:
- ARM_COMPUTE_ERROR("Not supported channel");
- return 0;
- }
- }
- case Format::NV21:
- {
- switch(channel)
- {
- case Channel::Y:
- return 0;
- case Channel::U:
- return 1;
- case Channel::V:
- return 0;
- default:
- ARM_COMPUTE_ERROR("Not supported channel");
- return 0;
- }
- }
- case Format::YUV444:
- case Format::IYUV:
- {
- switch(channel)
- {
- case Channel::Y:
- return 0;
- case Channel::U:
- return 0;
- case Channel::V:
- return 0;
- default:
- ARM_COMPUTE_ERROR("Not supported channel");
- return 0;
- }
- }
- default:
- ARM_COMPUTE_ERROR("Not supported format");
- return 0;
- }
-}
-
-/** Return the number of planes for a given format
- *
- * @param[in] format Input format
- *
- * @return The number of planes for a given image format.
- */
-inline size_t num_planes_from_format(Format format)
-{
- switch(format)
- {
- case Format::U8:
- case Format::S16:
- case Format::U16:
- case Format::S32:
- case Format::U32:
- case Format::BFLOAT16:
- case Format::F16:
- case Format::F32:
- case Format::RGB888:
- case Format::RGBA8888:
- case Format::YUYV422:
- case Format::UYVY422:
- return 1;
- case Format::NV12:
- case Format::NV21:
- return 2;
- case Format::IYUV:
- case Format::YUV444:
- return 3;
- default:
- ARM_COMPUTE_ERROR("Not supported format");
- return 0;
- }
-}
-
-/** Return the number of channels for a given single-planar pixel format
- *
- * @param[in] format Input format
- *
- * @return The number of channels for a given image format.
- */
-inline size_t num_channels_from_format(Format format)
-{
- switch(format)
- {
- case Format::U8:
- case Format::U16:
- case Format::S16:
- case Format::U32:
- case Format::S32:
- case Format::BFLOAT16:
- case Format::F16:
- case Format::F32:
- return 1;
- // Because the U and V channels are subsampled
- // these formats appear like having only 2 channels:
- case Format::YUYV422:
- case Format::UYVY422:
- return 2;
- case Format::UV88:
- return 2;
- case Format::RGB888:
- return 3;
- case Format::RGBA8888:
- return 4;
- //Doesn't make sense for planar formats:
- case Format::NV12:
- case Format::NV21:
- case Format::IYUV:
- case Format::YUV444:
- default:
- return 0;
- }
-}
-
-/** Return the promoted data type of a given data type.
- *
- * @note If promoted data type is not supported an error will be thrown
- *
- * @param[in] dt Data type to get the promoted type of.
- *
- * @return Promoted data type
- */
-inline DataType get_promoted_data_type(DataType dt)
-{
- switch(dt)
- {
- case DataType::U8:
- return DataType::U16;
- case DataType::S8:
- return DataType::S16;
- case DataType::U16:
- return DataType::U32;
- case DataType::S16:
- return DataType::S32;
- case DataType::QSYMM8:
- case DataType::QASYMM8:
- case DataType::QASYMM8_SIGNED:
- case DataType::QSYMM8_PER_CHANNEL:
- case DataType::QSYMM16:
- case DataType::QASYMM16:
- case DataType::BFLOAT16:
- case DataType::F16:
- case DataType::U32:
- case DataType::S32:
- case DataType::F32:
- ARM_COMPUTE_ERROR("Unsupported data type promotions!");
- default:
- ARM_COMPUTE_ERROR("Undefined data type!");
- }
- return DataType::UNKNOWN;
-}
-
-/** Compute the mininum and maximum values a data type can take
- *
- * @param[in] dt Data type to get the min/max bounds of
- *
- * @return A tuple (min,max) with the minimum and maximum values respectively wrapped in PixelValue.
- */
-inline std::tuple<PixelValue, PixelValue> get_min_max(DataType dt)
-{
- PixelValue min{};
- PixelValue max{};
- switch(dt)
- {
- case DataType::U8:
- case DataType::QASYMM8:
- {
- min = PixelValue(static_cast<int32_t>(std::numeric_limits<uint8_t>::lowest()));
- max = PixelValue(static_cast<int32_t>(std::numeric_limits<uint8_t>::max()));
- break;
- }
- case DataType::S8:
- case DataType::QSYMM8:
- case DataType::QASYMM8_SIGNED:
- case DataType::QSYMM8_PER_CHANNEL:
- {
- min = PixelValue(static_cast<int32_t>(std::numeric_limits<int8_t>::lowest()));
- max = PixelValue(static_cast<int32_t>(std::numeric_limits<int8_t>::max()));
- break;
- }
- case DataType::U16:
- case DataType::QASYMM16:
- {
- min = PixelValue(static_cast<int32_t>(std::numeric_limits<uint16_t>::lowest()));
- max = PixelValue(static_cast<int32_t>(std::numeric_limits<uint16_t>::max()));
- break;
- }
- case DataType::S16:
- case DataType::QSYMM16:
- {
- min = PixelValue(static_cast<int32_t>(std::numeric_limits<int16_t>::lowest()));
- max = PixelValue(static_cast<int32_t>(std::numeric_limits<int16_t>::max()));
- break;
- }
- case DataType::U32:
- {
- min = PixelValue(std::numeric_limits<uint32_t>::lowest());
- max = PixelValue(std::numeric_limits<uint32_t>::max());
- break;
- }
- case DataType::S32:
- {
- min = PixelValue(std::numeric_limits<int32_t>::lowest());
- max = PixelValue(std::numeric_limits<int32_t>::max());
- break;
- }
- case DataType::BFLOAT16:
- {
- min = PixelValue(bfloat16::lowest());
- max = PixelValue(bfloat16::max());
- break;
- }
- case DataType::F16:
- {
- min = PixelValue(std::numeric_limits<half>::lowest());
- max = PixelValue(std::numeric_limits<half>::max());
- break;
- }
- case DataType::F32:
- {
- min = PixelValue(std::numeric_limits<float>::lowest());
- max = PixelValue(std::numeric_limits<float>::max());
- break;
- }
- default:
- ARM_COMPUTE_ERROR("Undefined data type!");
- }
- return std::make_tuple(min, max);
-}
-
-/** Return true if the given format has horizontal subsampling.
- *
- * @param[in] format Format to determine subsampling.
- *
- * @return True if the format can be subsampled horizontaly.
- */
-inline bool has_format_horizontal_subsampling(Format format)
-{
- return (format == Format::YUYV422 || format == Format::UYVY422 || format == Format::NV12 || format == Format::NV21 || format == Format::IYUV || format == Format::UV88) ? true : false;
-}
-
-/** Return true if the given format has vertical subsampling.
- *
- * @param[in] format Format to determine subsampling.
- *
- * @return True if the format can be subsampled verticaly.
- */
-inline bool has_format_vertical_subsampling(Format format)
-{
- return (format == Format::NV12 || format == Format::NV21 || format == Format::IYUV || format == Format::UV88) ? true : false;
-}
-
-/** Separate a 2D convolution into two 1D convolutions
- *
- * @param[in] conv 2D convolution
- * @param[out] conv_col 1D vertical convolution
- * @param[out] conv_row 1D horizontal convolution
- * @param[in] size Size of the 2D convolution
- *
- * @return true if the separation was successful
- */
-inline bool separate_matrix(const int16_t *conv, int16_t *conv_col, int16_t *conv_row, uint8_t size)
-{
- int32_t min_col = -1;
- int16_t min_col_val = -1;
-
- for(int32_t i = 0; i < size; ++i)
- {
- if(conv[i] != 0 && (min_col < 0 || abs(min_col_val) > abs(conv[i])))
- {
- min_col = i;
- min_col_val = conv[i];
- }
- }
-
- if(min_col < 0)
- {
- return false;
- }
-
- for(uint32_t j = 0; j < size; ++j)
- {
- conv_col[j] = conv[min_col + j * size];
- }
-
- for(uint32_t i = 0; i < size; i++)
- {
- if(static_cast<int>(i) == min_col)
- {
- conv_row[i] = 1;
- }
- else
- {
- int16_t coeff = conv[i] / conv[min_col];
-
- for(uint32_t j = 1; j < size; ++j)
- {
- if(conv[i + j * size] != (conv_col[j] * coeff))
- {
- return false;
- }
- }
-
- conv_row[i] = coeff;
- }
- }
-
- return true;
-}
-
-/** Calculate the scale of the given square matrix
- *
- * The scale is the absolute value of the sum of all the coefficients in the matrix.
- *
- * @note If the coefficients add up to 0 then the scale is set to 1.
- *
- * @param[in] matrix Matrix coefficients
- * @param[in] matrix_size Number of elements per side of the square matrix. (Number of coefficients = matrix_size * matrix_size).
- *
- * @return The absolute value of the sum of the coefficients if they don't add up to 0, otherwise 1.
- */
-inline uint32_t calculate_matrix_scale(const int16_t *matrix, unsigned int matrix_size)
-{
- const size_t size = matrix_size * matrix_size;
-
- return std::max(1, std::abs(std::accumulate(matrix, matrix + size, 0)));
-}
-
-/** Adjust tensor shape size if width or height are odd for a given multi-planar format. No modification is done for other formats.
- *
- * @note Adding here a few links discussing the issue of odd size and sharing the same solution:
- * <a href="https://android.googlesource.com/platform/frameworks/base/+/refs/heads/master/graphics/java/android/graphics/YuvImage.java">Android Source</a>
- * <a href="https://groups.google.com/a/webmproject.org/forum/#!topic/webm-discuss/LaCKpqiDTXM">WebM</a>
- * <a href="https://bugs.chromium.org/p/libyuv/issues/detail?id=198&amp;can=1&amp;q=odd%20width">libYUV</a>
- * <a href="https://sourceforge.net/p/raw-yuvplayer/bugs/1/">YUVPlayer</a> *
- *
- * @param[in, out] shape Tensor shape of 2D size
- * @param[in] format Format of the tensor
- *
- * @return The adjusted tensor shape.
- */
-inline TensorShape adjust_odd_shape(const TensorShape &shape, Format format)
-{
- TensorShape output{ shape };
-
- // Force width to be even for formats which require subsampling of the U and V channels
- if(has_format_horizontal_subsampling(format))
- {
- output.set(0, output.x() & ~1U);
- }
-
- // Force height to be even for formats which require subsampling of the U and V channels
- if(has_format_vertical_subsampling(format))
- {
- output.set(1, output.y() & ~1U);
- }
-
- return output;
-}
-
-/** Calculate subsampled shape for a given format and channel
- *
- * @param[in] shape Shape of the tensor to calculate the extracted channel.
- * @param[in] format Format of the tensor.
- * @param[in] channel Channel to create tensor shape to be extracted.
- *
- * @return The subsampled tensor shape.
- */
-inline TensorShape calculate_subsampled_shape(const TensorShape &shape, Format format, Channel channel = Channel::UNKNOWN)
-{
- TensorShape output{ shape };
-
- // Subsample shape only for U or V channel
- if(Channel::U == channel || Channel::V == channel || Channel::UNKNOWN == channel)
- {
- // Subsample width for the tensor shape when channel is U or V
- if(has_format_horizontal_subsampling(format))
- {
- output.set(0, output.x() / 2U);
- }
-
- // Subsample height for the tensor shape when channel is U or V
- if(has_format_vertical_subsampling(format))
- {
- output.set(1, output.y() / 2U);
- }
- }
-
- return output;
-}
-
-/** Calculate accurary required by the horizontal and vertical convolution computations
- *
- * @param[in] conv_col Pointer to the vertical vector of the separated convolution filter
- * @param[in] conv_row Pointer to the horizontal vector of the convolution filter
- * @param[in] size Number of elements per vector of the separated matrix
- *
- * @return The return type is a pair. The first element of the pair is the biggest data type needed for the first stage. The second
- * element of the pair is the biggest data type needed for the second stage.
- */
-inline std::pair<DataType, DataType> data_type_for_convolution(const int16_t *conv_col, const int16_t *conv_row, size_t size)
-{
- DataType first_stage = DataType::UNKNOWN;
- DataType second_stage = DataType::UNKNOWN;
-
- auto gez = [](const int16_t &v)
- {
- return v >= 0;
- };
-
- auto accu_neg = [](const int &first, const int &second)
- {
- return first + (second < 0 ? second : 0);
- };
-
- auto accu_pos = [](const int &first, const int &second)
- {
- return first + (second > 0 ? second : 0);
- };
-
- const bool only_positive_coefficients = std::all_of(conv_row, conv_row + size, gez) && std::all_of(conv_col, conv_col + size, gez);
-
- if(only_positive_coefficients)
- {
- const int max_row_value = std::accumulate(conv_row, conv_row + size, 0) * UINT8_MAX;
- const int max_value = std::accumulate(conv_col, conv_col + size, 0) * max_row_value;
-
- first_stage = (max_row_value <= UINT16_MAX) ? DataType::U16 : DataType::S32;
-
- second_stage = (max_value <= UINT16_MAX) ? DataType::U16 : DataType::S32;
- }
- else
- {
- const int min_row_value = std::accumulate(conv_row, conv_row + size, 0, accu_neg) * UINT8_MAX;
- const int max_row_value = std::accumulate(conv_row, conv_row + size, 0, accu_pos) * UINT8_MAX;
- const int neg_coeffs_sum = std::accumulate(conv_col, conv_col + size, 0, accu_neg);
- const int pos_coeffs_sum = std::accumulate(conv_col, conv_col + size, 0, accu_pos);
- const int min_value = neg_coeffs_sum * max_row_value + pos_coeffs_sum * min_row_value;
- const int max_value = neg_coeffs_sum * min_row_value + pos_coeffs_sum * max_row_value;
-
- first_stage = ((INT16_MIN <= min_row_value) && (max_row_value <= INT16_MAX)) ? DataType::S16 : DataType::S32;
-
- second_stage = ((INT16_MIN <= min_value) && (max_value <= INT16_MAX)) ? DataType::S16 : DataType::S32;
- }
-
- return std::make_pair(first_stage, second_stage);
-}
-
-/** Calculate the accuracy required by the squared convolution calculation.
- *
- *
- * @param[in] conv Pointer to the squared convolution matrix
- * @param[in] size The total size of the convolution matrix
- *
- * @return The return is the biggest data type needed to do the convolution
- */
-inline DataType data_type_for_convolution_matrix(const int16_t *conv, size_t size)
-{
- auto gez = [](const int16_t v)
- {
- return v >= 0;
- };
-
- const bool only_positive_coefficients = std::all_of(conv, conv + size, gez);
-
- if(only_positive_coefficients)
- {
- const int max_conv_value = std::accumulate(conv, conv + size, 0) * UINT8_MAX;
- if(max_conv_value <= UINT16_MAX)
- {
- return DataType::U16;
- }
- else
- {
- return DataType::S32;
- }
- }
- else
- {
- const int min_value = std::accumulate(conv, conv + size, 0, [](int a, int b)
- {
- return b < 0 ? a + b : a;
- })
- * UINT8_MAX;
-
- const int max_value = std::accumulate(conv, conv + size, 0, [](int a, int b)
- {
- return b > 0 ? a + b : a;
- })
- * UINT8_MAX;
-
- if((INT16_MIN <= min_value) && (INT16_MAX >= max_value))
- {
- return DataType::S16;
- }
- else
- {
- return DataType::S32;
- }
- }
-}
-
/** Permutes the given dimensions according the permutation vector
*
* @param[in,out] dimensions Dimensions to be permuted.
@@ -911,7 +69,7 @@ template <typename T>
inline void permute_strides(Dimensions<T> &dimensions, const PermutationVector &perm)
{
const auto old_dim = utility::make_array<Dimensions<T>::num_max_dimensions>(dimensions.begin(), dimensions.end());
- for(unsigned int i = 0; i < perm.num_dimensions(); ++i)
+ for (unsigned int i = 0; i < perm.num_dimensions(); ++i)
{
T dimension_val = old_dim[i];
dimensions.set(perm[i], dimension_val);
@@ -929,7 +87,11 @@ inline void permute_strides(Dimensions<T> &dimensions, const PermutationVector &
*
* @return PadStrideInfo for SAME padding
*/
-PadStrideInfo calculate_same_pad(TensorShape input_shape, TensorShape weights_shape, PadStrideInfo conv_info, DataLayout data_layout = DataLayout::NCHW, const Size2D &dilation = Size2D(1u, 1u),
+PadStrideInfo calculate_same_pad(TensorShape input_shape,
+ TensorShape weights_shape,
+ PadStrideInfo conv_info,
+ DataLayout data_layout = DataLayout::NCHW,
+ const Size2D &dilation = Size2D(1u, 1u),
const DimensionRoundingType &rounding_type = DimensionRoundingType::FLOOR);
/** Returns expected width and height of the deconvolution's output tensor.
@@ -942,8 +104,10 @@ PadStrideInfo calculate_same_pad(TensorShape input_shape, TensorShape weights_sh
*
* @return A pair with the new width in the first position and the new height in the second.
*/
-std::pair<unsigned int, unsigned int> deconvolution_output_dimensions(unsigned int in_width, unsigned int in_height,
- unsigned int kernel_width, unsigned int kernel_height,
+std::pair<unsigned int, unsigned int> deconvolution_output_dimensions(unsigned int in_width,
+ unsigned int in_height,
+ unsigned int kernel_width,
+ unsigned int kernel_height,
const PadStrideInfo &pad_stride_info);
/** Returns expected width and height of output scaled tensor depending on dimensions rounding mode.
@@ -957,11 +121,47 @@ std::pair<unsigned int, unsigned int> deconvolution_output_dimensions(unsigned i
*
* @return A pair with the new width in the first position and the new height in the second.
*/
-std::pair<unsigned int, unsigned int> scaled_dimensions(int width, int height,
- int kernel_width, int kernel_height,
+std::pair<unsigned int, unsigned int> scaled_dimensions(int width,
+ int height,
+ int kernel_width,
+ int kernel_height,
const PadStrideInfo &pad_stride_info,
const Size2D &dilation = Size2D(1U, 1U));
+/** Returns calculated width and height of output scaled tensor depending on dimensions rounding mode.
+ *
+ * @param[in] width Width of input tensor (Number of columns)
+ * @param[in] height Height of input tensor (Number of rows)
+ * @param[in] kernel_width Kernel width.
+ * @param[in] kernel_height Kernel height.
+ * @param[in] pad_stride_info Pad and stride information.
+ *
+ * @return A pair with the new width in the first position and the new height in the second, returned values can be < 1
+ */
+std::pair<int, int> scaled_dimensions_signed(
+ int width, int height, int kernel_width, int kernel_height, const PadStrideInfo &pad_stride_info);
+
+/** Returns calculated width, height and depth of output scaled tensor depending on dimensions rounding mode.
+ *
+ * @param[in] width Width of input tensor
+ * @param[in] height Height of input tensor
+ * @param[in] depth Depth of input tensor
+ * @param[in] kernel_width Kernel width.
+ * @param[in] kernel_height Kernel height.
+ * @param[in] kernel_depth Kernel depth.
+ * @param[in] pool3d_info Pad and stride and round information for 3d pooling
+ *
+ * @return A tuple with the new width in the first position, the new height in the second, and the new depth in the third.
+ * Returned values can be < 1
+ */
+std::tuple<int, int, int> scaled_3d_dimensions_signed(int width,
+ int height,
+ int depth,
+ int kernel_width,
+ int kernel_height,
+ int kernel_depth,
+ const Pooling3dLayerInfo &pool3d_info);
+
/** Check if the given reduction operation should be handled in a serial way.
*
* @param[in] op Reduction operation to perform
@@ -981,16 +181,6 @@ bool needs_serialized_reduction(ReductionOperation op, DataType dt, unsigned int
*/
QuantizationInfo get_softmax_output_quantization_info(DataType input_type, bool is_log);
-/** Returns resize ratio between input and output with consideration of aligned corners
- *
- * @param[in] input_size The input size
- * @param[in] output_size the output size
- * @param[in] align_corners True to align corners of input and output. Defaults to false.
- *
- * @return The ratio between input and output (i.e., the input size divided by the output size)
- */
-float calculate_resize_ratio(size_t input_size, size_t output_size, bool align_corners = false);
-
/** Returns a pair of minimum and maximum values for a quantized activation
*
* @param[in] act_info The information for activation
@@ -999,15 +189,9 @@ float calculate_resize_ratio(size_t input_size, size_t output_size, bool align_c
*
* @return The pair with minimum and maximum values
*/
-std::pair<int32_t, int32_t> get_quantized_activation_min_max(ActivationLayerInfo act_info, DataType data_type, UniformQuantizationInfo oq_info);
-
-/** Convert a tensor format into a string.
- *
- * @param[in] format @ref Format to be translated to string.
- *
- * @return The string describing the format.
- */
-const std::string &string_from_format(Format format);
+std::pair<int32_t, int32_t> get_quantized_activation_min_max(const ActivationLayerInfo &act_info,
+ DataType data_type,
+ UniformQuantizationInfo oq_info);
/** Convert a channel identity into a string.
*
@@ -1016,48 +200,7 @@ const std::string &string_from_format(Format format);
* @return The string describing the channel.
*/
const std::string &string_from_channel(Channel channel);
-/** Convert a data layout identity into a string.
- *
- * @param[in] dl @ref DataLayout to be translated to string.
- *
- * @return The string describing the data layout.
- */
-const std::string &string_from_data_layout(DataLayout dl);
-/** Convert a data type identity into a string.
- *
- * @param[in] dt @ref DataType to be translated to string.
- *
- * @return The string describing the data type.
- */
-const std::string &string_from_data_type(DataType dt);
-/** Convert a matrix pattern into a string.
- *
- * @param[in] pattern @ref MatrixPattern to be translated to string.
- *
- * @return The string describing the matrix pattern.
- */
-const std::string &string_from_matrix_pattern(MatrixPattern pattern);
-/** Translates a given activation function to a string.
- *
- * @param[in] act @ref ActivationLayerInfo::ActivationFunction to be translated to string.
- *
- * @return The string describing the activation function.
- */
-const std::string &string_from_activation_func(ActivationLayerInfo::ActivationFunction act);
-/** Translates a given non linear function to a string.
- *
- * @param[in] function @ref NonLinearFilterFunction to be translated to string.
- *
- * @return The string describing the non linear function.
- */
-const std::string &string_from_non_linear_filter_function(NonLinearFilterFunction function);
-/** Translates a given interpolation policy to a string.
- *
- * @param[in] policy @ref InterpolationPolicy to be translated to string.
- *
- * @return The string describing the interpolation policy.
- */
-const std::string &string_from_interpolation_policy(InterpolationPolicy policy);
+
/** Translates a given border mode policy to a string.
*
* @param[in] border_mode @ref BorderMode to be translated to string.
@@ -1079,162 +222,67 @@ const std::string &string_from_norm_type(NormType type);
* @return The string describing the pooling type.
*/
const std::string &string_from_pooling_type(PoolingType type);
-/** Translates a given GEMMLowp output stage to a string.
- *
- * @param[in] output_stage @ref GEMMLowpOutputStageInfo to be translated to string.
- *
- * @return The string describing the GEMMLowp output stage
- */
-const std::string &string_from_gemmlowp_output_stage(GEMMLowpOutputStageType output_stage);
-/** Convert a PixelValue to a string, represented through the specific data type
- *
- * @param[in] value The PixelValue to convert
- * @param[in] data_type The type to be used to convert the @p value
+/** Check if the pool region is entirely outside the input tensor
*
- * @return String representation of the PixelValue through the given data type.
- */
-std::string string_from_pixel_value(const PixelValue &value, const DataType data_type);
-/** Lower a given string.
+ * @param[in] info @ref PoolingLayerInfo to be checked.
*
- * @param[in] val Given string to lower.
- *
- * @return The lowered string
+ * @return True if the pool region is entirely outside the input tensor, False otherwise.
*/
-std::string lower_string(const std::string &val);
-
-/** Check if a given data type is of floating point type
+bool is_pool_region_entirely_outside_input(const PoolingLayerInfo &info);
+/** Check if the 3d pool region is entirely outside the input tensor
*
- * @param[in] dt Input data type.
+ * @param[in] info @ref Pooling3dLayerInfo to be checked.
*
- * @return True if data type is of floating point type, else false.
+ * @return True if the pool region is entirely outside the input tensor, False otherwise.
*/
-inline bool is_data_type_float(DataType dt)
-{
- switch(dt)
- {
- case DataType::F16:
- case DataType::F32:
- return true;
- default:
- return false;
- }
-}
-
-/** Check if a given data type is of quantized type
- *
- * @note Quantized is considered a super-set of fixed-point and asymmetric data types.
+bool is_pool_3d_region_entirely_outside_input(const Pooling3dLayerInfo &info);
+/** Check if the 3D padding is symmetric i.e. padding in each opposite sides are euqal (left=right, top=bottom and front=back)
*
- * @param[in] dt Input data type.
+ * @param[in] info @ref Padding3D input 3D padding object to check if it is symmetric
*
- * @return True if data type is of quantized type, else false.
+ * @return True if padding is symmetric
*/
-inline bool is_data_type_quantized(DataType dt)
+inline bool is_symmetric(const Padding3D &info)
{
- switch(dt)
- {
- case DataType::QSYMM8:
- case DataType::QASYMM8:
- case DataType::QASYMM8_SIGNED:
- case DataType::QSYMM8_PER_CHANNEL:
- case DataType::QSYMM16:
- case DataType::QASYMM16:
- return true;
- default:
- return false;
- }
+ return ((info.left == info.right) && (info.top == info.bottom) && (info.front == info.back));
}
-
-/** Check if a given data type is of asymmetric quantized type
+/** Translates a given GEMMLowp output stage to a string.
*
- * @param[in] dt Input data type.
+ * @param[in] output_stage @ref GEMMLowpOutputStageInfo to be translated to string.
*
- * @return True if data type is of asymmetric quantized type, else false.
+ * @return The string describing the GEMMLowp output stage
*/
-inline bool is_data_type_quantized_asymmetric(DataType dt)
-{
- switch(dt)
- {
- case DataType::QASYMM8:
- case DataType::QASYMM8_SIGNED:
- case DataType::QASYMM16:
- return true;
- default:
- return false;
- }
-}
-
-/** Check if a given data type is of asymmetric quantized signed type
+const std::string &string_from_gemmlowp_output_stage(GEMMLowpOutputStageType output_stage);
+/** Convert a PixelValue to a string, represented through the specific data type
*
- * @param[in] dt Input data type.
+ * @param[in] value The PixelValue to convert
+ * @param[in] data_type The type to be used to convert the @p value
*
- * @return True if data type is of asymmetric quantized signed type, else false.
+ * @return String representation of the PixelValue through the given data type.
*/
-inline bool is_data_type_quantized_asymmetric_signed(DataType dt)
-{
- switch(dt)
- {
- case DataType::QASYMM8_SIGNED:
- return true;
- default:
- return false;
- }
-}
+std::string string_from_pixel_value(const PixelValue &value, const DataType data_type);
-/** Check if a given data type is of symmetric quantized type
+/** Stores padding information before configuring a kernel
*
- * @param[in] dt Input data type.
+ * @param[in] infos list of tensor infos to store the padding info for
*
- * @return True if data type is of symmetric quantized type, else false.
+ * @return An unordered map where each tensor info pointer is paired with its original padding info
*/
-inline bool is_data_type_quantized_symmetric(DataType dt)
-{
- switch(dt)
- {
- case DataType::QSYMM8:
- case DataType::QSYMM8_PER_CHANNEL:
- case DataType::QSYMM16:
- return true;
- default:
- return false;
- }
-}
-
-/** Check if a given data type is of per channel type
+std::unordered_map<const ITensorInfo *, PaddingSize> get_padding_info(std::initializer_list<const ITensorInfo *> infos);
+/** Stores padding information before configuring a kernel
*
- * @param[in] dt Input data type.
+ * @param[in] tensors list of tensors to store the padding info for
*
- * @return True if data type is of per channel type, else false.
+ * @return An unordered map where each tensor info pointer is paired with its original padding info
*/
-inline bool is_data_type_quantized_per_channel(DataType dt)
-{
- switch(dt)
- {
- case DataType::QSYMM8_PER_CHANNEL:
- return true;
- default:
- return false;
- }
-}
-
-/** Create a string with the float in full precision.
+std::unordered_map<const ITensorInfo *, PaddingSize> get_padding_info(std::initializer_list<const ITensor *> tensors);
+/** Check if the previously stored padding info has changed after configuring a kernel
*
- * @param val Floating point value
+ * @param[in] padding_map an unordered map where each tensor info pointer is paired with its original padding info
*
- * @return String with the floating point value.
+ * @return true if any of the tensor infos has changed its paddings
*/
-inline std::string float_to_string_with_full_precision(float val)
-{
- std::stringstream ss;
- ss.precision(std::numeric_limits<float>::max_digits10);
- ss << val;
-
- if(val != static_cast<int>(val))
- {
- ss << "f";
- }
-
- return ss.str();
-}
+bool has_padding_changed(const std::unordered_map<const ITensorInfo *, PaddingSize> &padding_map);
/** Returns the number of elements required to go from start to end with the wanted step
*
@@ -1250,67 +298,6 @@ inline size_t num_of_elements_in_range(const float start, const float end, const
return size_t(std::ceil((end - start) / step));
}
-/** Returns true if the value can be represented by the given data type
- *
- * @param[in] val value to be checked
- * @param[in] dt data type that is checked
- * @param[in] qinfo (Optional) quantization info if the data type is QASYMM8
- *
- * @return true if the data type can hold the value.
- */
-template <typename T>
-bool check_value_range(T val, DataType dt, QuantizationInfo qinfo = QuantizationInfo())
-{
- switch(dt)
- {
- case DataType::U8:
- {
- const auto val_u8 = static_cast<uint8_t>(val);
- return ((val_u8 == val) && val_u8 >= std::numeric_limits<uint8_t>::lowest() && val_u8 <= std::numeric_limits<uint8_t>::max());
- }
- case DataType::QASYMM8:
- {
- double min = static_cast<double>(dequantize_qasymm8(0, qinfo));
- double max = static_cast<double>(dequantize_qasymm8(std::numeric_limits<uint8_t>::max(), qinfo));
- return ((double)val >= min && (double)val <= max);
- }
- case DataType::S8:
- {
- const auto val_s8 = static_cast<int8_t>(val);
- return ((val_s8 == val) && val_s8 >= std::numeric_limits<int8_t>::lowest() && val_s8 <= std::numeric_limits<int8_t>::max());
- }
- case DataType::U16:
- {
- const auto val_u16 = static_cast<uint16_t>(val);
- return ((val_u16 == val) && val_u16 >= std::numeric_limits<uint16_t>::lowest() && val_u16 <= std::numeric_limits<uint16_t>::max());
- }
- case DataType::S16:
- {
- const auto val_s16 = static_cast<int16_t>(val);
- return ((val_s16 == val) && val_s16 >= std::numeric_limits<int16_t>::lowest() && val_s16 <= std::numeric_limits<int16_t>::max());
- }
- case DataType::U32:
- {
- const auto val_u32 = static_cast<uint32_t>(val);
- return ((val_u32 == val) && val_u32 >= std::numeric_limits<uint32_t>::lowest() && val_u32 <= std::numeric_limits<uint32_t>::max());
- }
- case DataType::S32:
- {
- const auto val_s32 = static_cast<int32_t>(val);
- return ((val_s32 == val) && val_s32 >= std::numeric_limits<int32_t>::lowest() && val_s32 <= std::numeric_limits<int32_t>::max());
- }
- case DataType::BFLOAT16:
- return (val >= bfloat16::lowest() && val <= bfloat16::max());
- case DataType::F16:
- return (val >= std::numeric_limits<half>::lowest() && val <= std::numeric_limits<half>::max());
- case DataType::F32:
- return (val >= std::numeric_limits<float>::lowest() && val <= std::numeric_limits<float>::max());
- default:
- ARM_COMPUTE_ERROR("Data type not supported");
- return false;
- }
-}
-
#ifdef ARM_COMPUTE_ASSERTS_ENABLED
/** Print consecutive elements to an output stream.
*
@@ -1321,26 +308,27 @@ bool check_value_range(T val, DataType dt, QuantizationInfo qinfo = Quantization
* @param[in] element_delim (Optional) Delimeter among the consecutive elements. Defaults to space delimeter
*/
template <typename T>
-void print_consecutive_elements_impl(std::ostream &s, const T *ptr, unsigned int n, int stream_width = 0, const std::string &element_delim = " ")
+void print_consecutive_elements_impl(
+ std::ostream &s, const T *ptr, unsigned int n, int stream_width = 0, const std::string &element_delim = " ")
{
using print_type = typename std::conditional<std::is_floating_point<T>::value, T, int>::type;
std::ios stream_status(nullptr);
stream_status.copyfmt(s);
- for(unsigned int i = 0; i < n; ++i)
+ for (unsigned int i = 0; i < n; ++i)
{
// Set stream width as it is not a "sticky" stream manipulator
- if(stream_width != 0)
+ if (stream_width != 0)
{
s.width(stream_width);
}
- if(std::is_same<typename std::decay<T>::type, half>::value)
+ if (std::is_same<typename std::decay<T>::type, half>::value)
{
// We use T instead of print_type here is because the std::is_floating_point<half> returns false and then the print_type becomes int.
s << std::right << static_cast<T>(ptr[i]) << element_delim;
}
- else if(std::is_same<typename std::decay<T>::type, bfloat16>::value)
+ else if (std::is_same<typename std::decay<T>::type, bfloat16>::value)
{
// We use T instead of print_type here is because the std::is_floating_point<bfloat16> returns false and then the print_type becomes int.
s << std::right << float(ptr[i]) << element_delim;
@@ -1369,17 +357,17 @@ int max_consecutive_elements_display_width_impl(std::ostream &s, const T *ptr, u
using print_type = typename std::conditional<std::is_floating_point<T>::value, T, int>::type;
int max_width = -1;
- for(unsigned int i = 0; i < n; ++i)
+ for (unsigned int i = 0; i < n; ++i)
{
std::stringstream ss;
ss.copyfmt(s);
- if(std::is_same<typename std::decay<T>::type, half>::value)
+ if (std::is_same<typename std::decay<T>::type, half>::value)
{
// We use T instead of print_type here is because the std::is_floating_point<half> returns false and then the print_type becomes int.
ss << static_cast<T>(ptr[i]);
}
- else if(std::is_same<typename std::decay<T>::type, bfloat16>::value)
+ else if (std::is_same<typename std::decay<T>::type, bfloat16>::value)
{
// We use T instead of print_type here is because the std::is_floating_point<bfloat> returns false and then the print_type becomes int.
ss << float(ptr[i]);
@@ -1403,7 +391,12 @@ int max_consecutive_elements_display_width_impl(std::ostream &s, const T *ptr, u
* @param[in] stream_width (Optional) Width of the stream. If set to 0 the element's width is used. Defaults to 0.
* @param[in] element_delim (Optional) Delimeter among the consecutive elements. Defaults to space delimeter
*/
-void print_consecutive_elements(std::ostream &s, DataType dt, const uint8_t *ptr, unsigned int n, int stream_width, const std::string &element_delim = " ");
+void print_consecutive_elements(std::ostream &s,
+ DataType dt,
+ const uint8_t *ptr,
+ unsigned int n,
+ int stream_width,
+ const std::string &element_delim = " ");
/** Identify the maximum width of n consecutive elements.
*
@@ -1416,5 +409,5 @@ void print_consecutive_elements(std::ostream &s, DataType dt, const uint8_t *ptr
*/
int max_consecutive_elements_display_width(std::ostream &s, DataType dt, const uint8_t *ptr, unsigned int n);
#endif /* ARM_COMPUTE_ASSERTS_ENABLED */
-}
+} // namespace arm_compute
#endif /*ARM_COMPUTE_UTILS_H */