diff options
-rw-r--r-- | arm_compute/core/QuantizationInfo.h | 28 | ||||
-rw-r--r-- | src/core/cpu/kernels/add/neon/qasymm8.cpp | 2 | ||||
-rw-r--r-- | support/ToolchainSupport.h | 32 |
3 files changed, 56 insertions, 6 deletions
diff --git a/arm_compute/core/QuantizationInfo.h b/arm_compute/core/QuantizationInfo.h index af7b8c66d8..b331f7d923 100644 --- a/arm_compute/core/QuantizationInfo.h +++ b/arm_compute/core/QuantizationInfo.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2019-2020 Arm Limited. + * Copyright (c) 2019-2021 Arm Limited. * * SPDX-License-Identifier: MIT * @@ -24,9 +24,10 @@ #ifndef ARM_COMPUTE_QUANTIZATION_INFO_H #define ARM_COMPUTE_QUANTIZATION_INFO_H +#include "arm_compute/core/Error.h" #include "arm_compute/core/Rounding.h" +#include "support/ToolchainSupport.h" #include "utils/misc/Utility.h" -#include "arm_compute/core/Error.h" #include <cstddef> #include <type_traits> @@ -216,14 +217,33 @@ struct Qasymm8QuantizationHelper /** Quantize a value given a 8-bit asymmetric quantization scheme * + * @param[in] value Value to quantize + * @param[in] qinfo Quantization information to use for quantizing + * + * @return Quantized value + */ + static inline QUANTIZED_TYPE quantize(float value, const UniformQuantizationInfo &qinfo) + { + ARM_COMPUTE_ERROR_ON(qinfo.scale == 0); + const int quantized = support::cpp11::lround(value / qinfo.scale) + qinfo.offset; + return static_cast<QUANTIZED_TYPE>(arm_compute::utility::clamp<decltype(quantized), QUANTIZED_TYPE>(quantized)); + } + + /** Quantize a value given a 8-bit asymmetric quantization scheme using a specific rounding policy + * * @param[in] value Value to quantize * @param[in] qinfo Quantization information to use for quantizing - * @param[in] rounding_policy (Optional) Rounding policy to use. Default: nearest up + * @param[in] rounding_policy Rounding policy to use * * @return Quantized value */ - static inline QUANTIZED_TYPE quantize(float value, const UniformQuantizationInfo &qinfo, RoundingPolicy rounding_policy = RoundingPolicy::TO_NEAREST_UP) + static inline QUANTIZED_TYPE quantize(float value, const UniformQuantizationInfo &qinfo, RoundingPolicy rounding_policy) { + if(rounding_policy == RoundingPolicy::TO_NEAREST_UP) + { + return quantize(value, qinfo); + } + ARM_COMPUTE_ERROR_ON(qinfo.scale == 0); const int quantized = arm_compute::round(value / qinfo.scale, rounding_policy) + qinfo.offset; return static_cast<QUANTIZED_TYPE>(arm_compute::utility::clamp<decltype(quantized), QUANTIZED_TYPE>(quantized)); diff --git a/src/core/cpu/kernels/add/neon/qasymm8.cpp b/src/core/cpu/kernels/add/neon/qasymm8.cpp index cc97f0067c..e357a7ef7f 100644 --- a/src/core/cpu/kernels/add/neon/qasymm8.cpp +++ b/src/core/cpu/kernels/add/neon/qasymm8.cpp @@ -199,7 +199,7 @@ void add_qasymm8_neon(const ITensor *src0, const ITensor *src1, ITensor *dst, co { const float afs = static_cast<int32_t>((*(input1_ptr + x)) - iq1_info.offset) * iq1_info.scale; const float bfs = static_cast<int32_t>((*(input2_ptr + x)) - iq2_info.offset) * iq2_info.scale; - *(output_ptr + x) = quantize_qasymm8((afs + bfs), dst->info()->quantization_info()); + *(output_ptr + x) = quantize_qasymm8((afs + bfs), oq_info); } }, input1, input2, output); diff --git a/support/ToolchainSupport.h b/support/ToolchainSupport.h index e79084a629..d8c14411e8 100644 --- a/support/ToolchainSupport.h +++ b/support/ToolchainSupport.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017-2020 Arm Limited. + * Copyright (c) 2017-2021 Arm Limited. * * SPDX-License-Identifier: MIT * @@ -72,6 +72,21 @@ inline T round(T value) return ::round(value); } +/** Round floating-point value with half value rounding away from zero and cast to long + * + * @note This function implements the same behaviour as std::lround except that it doesn't + * support Integral type. The latter is not in the namespace std in some Android toolchains. + * + * @param[in] value floating-point value to be rounded. + * + * @return Floating-point value of rounded @p value casted to long + */ +template <typename T, typename = typename std::enable_if<std::is_floating_point<T>::value>::type> +inline long lround(T value) +{ + return ::lround(value); +} + /** Truncate floating-point value. * * @note This function implements the same behaviour as std::truncate except that it doesn't @@ -172,6 +187,21 @@ inline T round(T value) return (value < 0.f) ? static_cast<int>(value - 0.5f) : static_cast<int>(value + 0.5f); } +/** Round floating-point value with half value rounding away from zero and cast to long + * + * @note This function implements the same behaviour as std::lround except that it doesn't + * support Integral type. The latter is not in the namespace std in some Android toolchains. + * + * @param[in] value floating-point value to be rounded. + * + * @return Floating-point value of rounded @p value casted to long + */ +template <typename T, typename = typename std::enable_if<std::is_floating_point<T>::value>::type> +inline long lround(T value) +{ + return std::lround(value); +} + /** Truncate floating-point value. * * @note This function implements the same behaviour as std::truncate except that it doesn't |