From fbba364350fcea447aaa6d108787820dea3fe23a Mon Sep 17 00:00:00 2001 From: Matthew Sloyan Date: Thu, 15 Oct 2020 13:53:27 +0100 Subject: IVGCVSW-5435 Add FloatingPointComparison to remove boost::math::fpc uses * Added FloatingPointComparison.hpp and FloatingPointComparisonTest.cpp, which compares two floats and returns true if the values are within a specified or default tolerance of each other. * Also removed boost::math::fpc from test/TensorHelpers.hpp to validate. Signed-off-by: Matthew Sloyan Change-Id: I164c32eccd213c53bb1bc4f9cd4ee4838f1781c9 --- CMakeLists.txt | 6 +- include/armnnUtils/FloatingPointComparison.hpp | 27 ++++ src/armnn/test/TensorHelpers.hpp | 5 +- .../test/FloatingPointComparisonTest.cpp | 137 +++++++++++++++++++++ 4 files changed, 170 insertions(+), 5 deletions(-) create mode 100644 include/armnnUtils/FloatingPointComparison.hpp create mode 100644 src/armnnUtils/test/FloatingPointComparisonTest.cpp diff --git a/CMakeLists.txt b/CMakeLists.txt index b7c8cb52fe..cf12a57b16 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -39,6 +39,7 @@ set(armnnUtils_sources) list(APPEND armnnUtils_sources include/armnnUtils/DataLayoutIndexed.hpp include/armnnUtils/Permute.hpp + include/armnnUtils/FloatingPointComparison.hpp include/armnnUtils/FloatingPointConverter.hpp include/armnnUtils/TensorUtils.hpp include/armnnUtils/Transpose.hpp @@ -690,9 +691,10 @@ if(BUILD_UNIT_TESTS) src/armnn/test/UnitTests.cpp src/armnn/test/UnitTests.hpp src/armnn/test/UtilsTests.cpp - src/armnnUtils/test/QuantizeHelperTest.cpp - src/armnnUtils/test/PrototxtConversionsTest.cpp + src/armnnUtils/test/FloatingPointComparisonTest.cpp src/armnnUtils/test/ParserHelperTest.cpp + src/armnnUtils/test/PrototxtConversionsTest.cpp + src/armnnUtils/test/QuantizeHelperTest.cpp src/armnnUtils/test/TensorUtilsTest.cpp src/profiling/test/BufferTests.cpp src/profiling/test/FileOnlyProfilingDecoratorTests.cpp diff --git a/include/armnnUtils/FloatingPointComparison.hpp b/include/armnnUtils/FloatingPointComparison.hpp new file mode 100644 index 0000000000..1e7b15a982 --- /dev/null +++ b/include/armnnUtils/FloatingPointComparison.hpp @@ -0,0 +1,27 @@ +// +// Copyright © 2020 Arm Ltd. All rights reserved. +// SPDX-License-Identifier: MIT +// + +#pragma once + +#include + +namespace armnnUtils +{ + +/** + * Compare two floats and return true if their values are within a specified tolerance of each other. + * @param a + * @param b + * @param tolerancePercentage If not supplied default will be 1% tolerance (1.0f) + * @return true if the value of float b is within tolerancePercentage of the value for float a. + */ +inline bool within_percentage_tolerance(float a, float b, float tolerancePercent = 1.0f) +{ + float toleranceValue = std::fabs(a * (tolerancePercent / 100)); + return std::fabs(a - b) <= toleranceValue; +} + +} //namespace armnn + diff --git a/src/armnn/test/TensorHelpers.hpp b/src/armnn/test/TensorHelpers.hpp index d67cd5b979..fd9dd83770 100644 --- a/src/armnn/test/TensorHelpers.hpp +++ b/src/armnn/test/TensorHelpers.hpp @@ -6,13 +6,13 @@ #include #include +#include #include #include #include #include -#include #include #include @@ -53,8 +53,7 @@ struct SelectiveComparer } // For unquantized floats we use a tolerance of 1%. - boost::math::fpc::close_at_tolerance comparer(boost::math::fpc::percent_tolerance(1.0f)); - return comparer(a, b); + return armnnUtils::within_percentage_tolerance(a, b); } }; diff --git a/src/armnnUtils/test/FloatingPointComparisonTest.cpp b/src/armnnUtils/test/FloatingPointComparisonTest.cpp new file mode 100644 index 0000000000..dab0deb5e6 --- /dev/null +++ b/src/armnnUtils/test/FloatingPointComparisonTest.cpp @@ -0,0 +1,137 @@ +// +// Copyright © 2020 Arm Ltd. All rights reserved. +// SPDX-License-Identifier: MIT +// + +#include + +#include + +using namespace armnnUtils; + +BOOST_AUTO_TEST_SUITE(FloatingPointComparisonSuite) + +BOOST_AUTO_TEST_CASE(FloatingPointComparisonDefaultTolerance) +{ + // 1% range of 1.2 is 1.188 -> 1.212 + // Just below tolerance. + BOOST_TEST(!within_percentage_tolerance(1.2f, 1.17f)); + // Just above tolerance. + BOOST_TEST(!within_percentage_tolerance(1.2f, 1.213f)); + // Just inside the lower range. + BOOST_TEST(within_percentage_tolerance(1.2f, 1.189f)); + // Just inside the upper range. + BOOST_TEST(within_percentage_tolerance(1.2f, 1.210f)); + // Exact match + BOOST_TEST(within_percentage_tolerance(1.2f, 1.2f)); + + // Negative value tests. + BOOST_TEST(!within_percentage_tolerance(-1.2f, -1.17f)); + BOOST_TEST(!within_percentage_tolerance(-1.2f, -1.213f)); + BOOST_TEST(within_percentage_tolerance(-1.2f, -1.189f)); + BOOST_TEST(within_percentage_tolerance(-1.2f, -1.210f)); + BOOST_TEST(within_percentage_tolerance(-1.2f, -1.2f)); + + // Negative & positive tests + BOOST_TEST(!within_percentage_tolerance(1.2f, -1.2f)); + BOOST_TEST(!within_percentage_tolerance(-1.2f, 1.2f)); + + // Negative and positive test with large float values. + BOOST_TEST(!within_percentage_tolerance(3.3E+38f, -1.17549435e38f)); + BOOST_TEST(!within_percentage_tolerance(-1.17549435e38f, 3.3E+38f)); + + // 1% range of 0.04 is 0.0396 -> 0.0404 + // Just below tolerance. + BOOST_TEST(!within_percentage_tolerance(0.04f, 0.039f)); + // Just above tolerance. + BOOST_TEST(!within_percentage_tolerance(0.04f, 0.04041f)); + // Just inside the lower range. + BOOST_TEST(within_percentage_tolerance(0.04f, 0.0397f)); + // Just inside the upper range. + BOOST_TEST(within_percentage_tolerance(0.04f, 0.04039f)); + // Exact match + BOOST_TEST(within_percentage_tolerance(0.04f, 0.04f)); +} + +BOOST_AUTO_TEST_CASE(FloatingPointComparisonLargePositiveNumbersDefaultTolerance) +{ + // Just below tolerance. + BOOST_TEST(!within_percentage_tolerance(3.3E+38f, (3.3E+38f * 0.989f))); + // Just above tolerance. + BOOST_TEST(!within_percentage_tolerance(3.3E+38f, (3.3E+38f * 1.011f))); + // Just inside the lower range. + BOOST_TEST(within_percentage_tolerance(3.3E+38f, (3.3E+38f * 0.992f))); + // Just inside the upper range. + BOOST_TEST(within_percentage_tolerance(3.3E+38f, (3.3E+38f * 1.009f))); + // Exact match + BOOST_TEST(within_percentage_tolerance(3.3E+38f, 3.3E+38f)); +} + +BOOST_AUTO_TEST_CASE(FloatingPointComparisonLargeNegativeNumbersDefaultTolerance) +{ + // Just below tolerance. + BOOST_TEST(!within_percentage_tolerance(-1.17549435e38f, (-1.17549435e38f * -1.009f))); + // Just above tolerance. + BOOST_TEST(!within_percentage_tolerance(-1.17549435e38f, (-1.17549435e38f * 1.011f))); + // Just inside the lower range. + BOOST_TEST(within_percentage_tolerance(-1.17549435e38f, -1.17549435e38f - (-1.17549435e38f * 0.0099f))); + // Just inside the upper range. + BOOST_TEST(within_percentage_tolerance(-1.17549435e38f, -1.17549435e38f + (-1.17549435e38f * 0.0099f))); + // Exact match + BOOST_TEST(within_percentage_tolerance(-1.17549435e38f, -1.17549435e38f)); +} + +BOOST_AUTO_TEST_CASE(FloatingPointComparisonSpecifiedTolerance) +{ + // 2% range of 1.2 is 1.176 -> 1.224 + // Just below tolerance. + BOOST_TEST(!within_percentage_tolerance(1.2f, 1.175f, 2.0f)); + // Just above tolerance. + BOOST_TEST(!within_percentage_tolerance(1.2f, 1.226f, 2.0f)); + // Just inside the lower range. + BOOST_TEST(within_percentage_tolerance(1.2f, 1.18f, 2.0f)); + // Just inside the upper range. + BOOST_TEST(within_percentage_tolerance(1.2f, 1.22f, 2.0f)); + // Exact match. + BOOST_TEST(within_percentage_tolerance(1.2f, 1.2f, 2.0f)); + + // 5% range of 6.2 is 5.89 -> 6.51 + // Just below tolerance. + BOOST_TEST(!within_percentage_tolerance(6.2f, 5.88f, 5.0f)); + // Just above tolerance. + BOOST_TEST(!within_percentage_tolerance(6.2f, 6.52f, 5.0f)); + // Just inside the lower range. + BOOST_TEST(within_percentage_tolerance(6.2f, 5.9f, 5.0f)); + // Just inside the upper range. + BOOST_TEST(within_percentage_tolerance(6.2f, 6.5f, 5.0f)); + + // Larger tolerance (unlikely to be used). + BOOST_TEST(within_percentage_tolerance(10.0f, 9.01f, 10.0f)); + BOOST_TEST(!within_percentage_tolerance(10.0f, 8.99f, 10.0f)); +} + +BOOST_AUTO_TEST_CASE(FloatingPointComparisonLargePositiveNumbersSpecifiedTolerance) +{ + // Just below tolerance. + BOOST_TEST(!within_percentage_tolerance(3.3E+38f, (3.3E+38f * 0.979f), 2.0f)); + // Just above tolerance. + BOOST_TEST(!within_percentage_tolerance(3.3E+38f, (3.3E+38f * 1.021f), 2.0f)); + // Just inside the lower range. + BOOST_TEST(within_percentage_tolerance(3.3E+38f, (3.3E+38f * 0.982f), 2.0f)); + // Just inside the upper range. + BOOST_TEST(within_percentage_tolerance(3.3E+38f, (3.3E+38f * 1.019f), 2.0f)); +} + +BOOST_AUTO_TEST_CASE(FloatingPointComparisonLargeNegativeNumbersSpecifiedTolerance) +{ + // Just below tolerance. + BOOST_TEST(!within_percentage_tolerance(-1.17549435e38f, (-1.17549435e38f * -1.019f), 2.0f)); + // Just above tolerance. + BOOST_TEST(!within_percentage_tolerance(-1.17549435e38f, (-1.17549435e38f * 1.021f), 2.0f)); + // Just inside the lower range. + BOOST_TEST(within_percentage_tolerance(-1.17549435e38f, -1.17549435e38f - (-1.17549435e38f * 0.0089f), 2.0f)); + // Just inside the upper range. + BOOST_TEST(within_percentage_tolerance(-1.17549435e38f, -1.17549435e38f + (-1.17549435e38f * 0.0089f), 2.0f)); +} + +BOOST_AUTO_TEST_SUITE_END() -- cgit v1.2.1