aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorFrancis Murtagh <francis.murtagh@arm.com>2019-02-22 16:35:13 +0000
committerFrancis Murtagh <francis.murtagh@arm.com>2019-02-25 09:46:01 +0000
commit0d0a78ebd60e058746ea161914b45709245d4e1b (patch)
tree0220a0e885a81dd33e3e770f9dc7c02091eb4159
parentd1ae3a632af09cd065d983a51c40916e2202121d (diff)
downloadarmnn-0d0a78ebd60e058746ea161914b45709245d4e1b.tar.gz
IVGCVSW-2721 Quantize and Dequantize aren't quite right
* Add check for infinity and negative infinity in quantize() * Add assert for NaN value in quantize and dequantize() * Add unit tests for infinity and negative infinity Change-Id: Ie60e1e15b289ccbf99df4a3281f067b82cc9f9bf Signed-off-by: Francis Murtagh <francis.murtagh@arm.com>
-rw-r--r--include/armnn/TypesUtils.hpp15
-rw-r--r--src/armnn/test/QuantizerTest.cpp29
2 files changed, 36 insertions, 8 deletions
diff --git a/include/armnn/TypesUtils.hpp b/include/armnn/TypesUtils.hpp
index c65eefc510..e7652649b0 100644
--- a/include/armnn/TypesUtils.hpp
+++ b/include/armnn/TypesUtils.hpp
@@ -189,18 +189,16 @@ inline std::ostream & operator<<(std::ostream & os, const armnn::TensorShape & s
template<typename QuantizedType>
inline QuantizedType Quantize(float value, float scale, int32_t offset)
{
- // TODO : check we act sensibly for Inf, NaN and -Inf
- // see IVGCVSW-1849
static_assert(IsQuantizedType<QuantizedType>(), "Not an integer type.");
constexpr QuantizedType max = std::numeric_limits<QuantizedType>::max();
constexpr QuantizedType min = std::numeric_limits<QuantizedType>::lowest();
BOOST_ASSERT(scale != 0.f);
- int quantized = boost::numeric_cast<int>(round(value / scale)) + offset;
- QuantizedType quantizedBits = quantized <= min
- ? min
- : quantized >= max
- ? max
- : static_cast<QuantizedType>(quantized);
+ BOOST_ASSERT(!std::isnan(value));
+
+ float clampedValue = std::min(std::max(static_cast<float>(round(value/scale) + offset), static_cast<float>(min)),
+ static_cast<float>(max));
+ auto quantizedBits = static_cast<QuantizedType>(clampedValue);
+
return quantizedBits;
}
@@ -215,6 +213,7 @@ inline float Dequantize(QuantizedType value, float scale, int32_t offset)
{
static_assert(IsQuantizedType<QuantizedType>(), "Not an integer type.");
BOOST_ASSERT(scale != 0.f);
+ BOOST_ASSERT(!std::isnan(value));
float dequantized = boost::numeric_cast<float>(value - offset) * scale;
return dequantized;
}
diff --git a/src/armnn/test/QuantizerTest.cpp b/src/armnn/test/QuantizerTest.cpp
index 548203a6a9..fcce208c59 100644
--- a/src/armnn/test/QuantizerTest.cpp
+++ b/src/armnn/test/QuantizerTest.cpp
@@ -14,6 +14,7 @@
#include "../NetworkQuantizerUtils.hpp"
#include "../OverrideInputRangeVisitor.hpp"
#include "../RangeTracker.hpp"
+#include "../backends/backendsCommon/test/QuantizeHelper.hpp"
#include <boost/test/unit_test.hpp>
@@ -1215,5 +1216,33 @@ BOOST_AUTO_TEST_CASE(QuantizeBatchToSpace)
VisitLayersTopologically(quantizedNetwork.get(), validator);
}
+std::vector<uint8_t> SetupQuantize(float value)
+{
+ armnn::TensorInfo inputInfo({ 1, 2, 2 }, armnn::DataType::Float32);
+ inputInfo.SetQuantizationScale(1.0f);
+ inputInfo.SetQuantizationOffset(1);
+ std::vector<float> input({
+ value, 0.0f,
+ 0.0f, 1.0f
+ });
+ const std::vector<float> &inputRef = input;
+
+ auto output = QuantizedVector<uint8_t>(inputInfo.GetQuantizationScale(),
+ inputInfo.GetQuantizationOffset(),
+ inputRef);
+
+ return output;
+}
+
+BOOST_AUTO_TEST_CASE(QuantizeInf)
+{
+ BOOST_CHECK_EQUAL(SetupQuantize(std::numeric_limits<float>::infinity())[0], 255);
+}
+
+BOOST_AUTO_TEST_CASE(QuantizeNegativeInf)
+{
+ BOOST_CHECK_EQUAL(SetupQuantize(-1 * std::numeric_limits<float>::infinity())[0], 0);
+}
+
BOOST_AUTO_TEST_SUITE_END()
} // namespace armnn